// Chrome 153 vs 154: paste into the DevTools console on any https:// page and press Enter.
// Each line prints "<change> <check> = <value>". Expected values: clearcotelabs.com/chrome-releases/154
(async () => {
const checks = [
["grease-brand", () => navigator.userAgentData.brands.map((b) => `${b.brand};v=${b.version}`).join(', ')],
["v8-property-order", () => Object.getOwnPropertyNames(window)[Object.getOwnPropertyNames(window).indexOf('Float64Array') + 1]],
["v8-property-order", () => Object.getOwnPropertyNames(window)[Object.getOwnPropertyNames(window).indexOf('URIError') + 1]],
["v8-property-order", () => Object.getOwnPropertyNames(Math).slice(-2).join(',')],
["v8-property-order", () => Object.getOwnPropertyNames(DataView.prototype).indexOf('getFloat16') < Object.getOwnPropertyNames(DataView.prototype).indexOf('getFloat32')],
["v8-property-order", () => Object.getOwnPropertyNames(Intl.Locale.prototype).indexOf('variants') < Object.getOwnPropertyNames(Intl.Locale.prototype).indexOf('baseName')],
["promise-try-identity", () => ((p) => Promise.try(() => p) === p)(Promise.resolve(1))],
["iterator-includes", () => typeof Iterator.prototype.includes],
["request-resize", () => typeof window.requestResize],
["fontface-width", () => 'width' in FontFace.prototype],
["typed-om-workers", () => new Promise((r) => { const w = new Worker(URL.createObjectURL(new Blob(['postMessage(typeof CSSStyleValue)']))); w.onmessage = (e) => r(e.data); })],
["svg-textpath-sidetype", () => 'TEXTPATH_SIDETYPE_LEFT' in SVGTextPathElement],
["active-view-transition-order", () => Object.getOwnPropertyNames(Document.prototype).indexOf('activeViewTransition') < Object.getOwnPropertyNames(Document.prototype).indexOf('fonts')],
["storage-access-for-removed", () => 'requestStorageAccessFor' in document],
["storage-access-for-removed", () => 'setSharedStorageContext' in FencedFrameConfig.prototype],
["xml-parser-libxml2", () => new DOMParser().parseFromString('<a><b></a>', 'application/xml').querySelector('parsererror div').textContent.trim()],
["xslt-banner", () => /This site uses XSLT/.test(new XMLSerializer().serializeToString(((p) => (p.importStylesheet(new DOMParser().parseFromString('<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/"><html><body><p><xsl:value-of select="r/v"/></p></body></html></xsl:template></xsl:stylesheet>', 'application/xml')), p.transformToDocument(new DOMParser().parseFromString('<r><v>1</v></r>', 'application/xml'))))(new XSLTProcessor())))],
["frame-sizing", () => CSS.supports('frame-sizing', 'content-height')],
["scroll-marker-group-modes-on", () => CSS.supports('scroll-marker-group', 'after tabs')],
["wgsl-swizzle-assignment", () => navigator.gpu.wgslLanguageFeatures.has('swizzle_assignment')],
["tzdata-2026c", () => new Intl.DateTimeFormat('en-US', { timeZone: 'Africa/Casablanca', timeZoneName: 'longOffset' }).formatToParts(Date.UTC(2026, 9, 1)).find((p) => p.type === 'timeZoneName').value],
["tzdata-2026c", () => new Intl.DateTimeFormat('en-US', { timeZone: 'America/Vancouver', timeZoneName: 'longOffset' }).formatToParts(Date.UTC(2026, 10, 15)).find((p) => p.type === 'timeZoneName').value],
["tzdata-2026c", () => new Intl.DateTimeFormat('en-US', { timeZone: 'America/Edmonton', timeZoneName: 'longOffset' }).formatToParts(Date.UTC(2026, 10, 15)).find((p) => p.type === 'timeZoneName').value],
];
const out = [];
for (const [id, f] of checks) {
let v;
try { v = await f(); } catch (e) { v = "throws " + e.name; }
const expr = f.toString().replace(/^\(\)\s*=>\s*/, "");
out.push(id.padEnd(28) + expr + " = " + (typeof v === "string" ? JSON.stringify(v) : String(v)));
}
console.log(out.join("\n"));
})();