// Chrome 152 vs 153: paste into the DevTools console on any https:// page and press Enter.
// Each line prints "<change> <check> = <value>". Expected values: clearcotelabs.com/chrome-releases/153
(async () => {
const checks = [
["grease-brand", () => navigator.userAgentData.brands.map((b) => `${b.brand};v=${b.version}`).join(', ')],
["iterator-helpers", () => typeof Iterator.zip],
["iterator-helpers", () => typeof Iterator.zipKeyed],
["iterator-helpers", () => typeof Iterator.prototype.join],
["camera-microphone-elements", () => typeof HTMLCameraElement],
["camera-microphone-elements", () => typeof HTMLMicrophoneElement],
["shared-storage-removed", () => 'sharedStorage' in window],
["shared-storage-removed", () => typeof SharedStorageWorklet],
["shared-storage-removed", () => 'sharedStorageWritable' in HTMLIFrameElement.prototype],
["shared-storage-removed", () => 'canLoadOpaqueURL' in HTMLFencedFrameElement],
["shared-storage-removed", () => document.featurePolicy.features().includes('run-ad-auction')],
["xml-parser-rust", () => new DOMParser().parseFromString('<a><b></a>', 'application/xml').querySelector('parsererror div').textContent.trim()],
["devtools-proxy-getters", () => (() => { let hit = false; const e = new Error('x'); Object.defineProperty(e, 'stack', { configurable: true, get: new Proxy(function () {}, { apply() { hit = true; return ''; } }) }); console.log(e); return hit; })()],
["html-autocorrect", () => 'autocorrect' in HTMLElement.prototype],
["render-quantum-size", () => 'renderQuantumSize' in BaseAudioContext.prototype],
["property-order", () => Object.getOwnPropertyNames(Element.prototype).indexOf('customElementRegistry') < Object.getOwnPropertyNames(Element.prototype).indexOf('onfullscreenchange')],
["property-order", () => Object.getOwnPropertyNames(Document.prototype).indexOf('customElementRegistry') < Object.getOwnPropertyNames(Document.prototype).indexOf('fonts')],
["property-order", () => Object.getOwnPropertyNames(CustomElementRegistry.prototype).indexOf('initialize') < Object.getOwnPropertyNames(CustomElementRegistry.prototype).indexOf('upgrade')],
["datachannel-enforce-range", () => (() => { const pc = new RTCPeerConnection(); try { pc.createDataChannel('x', { maxRetransmits: -1 }); return 'no throw'; } catch (e) { return e.name; } finally { pc.close(); } })()],
["canvas-zero-length-stroke", () => (() => { const c = document.createElement('canvas'); c.width = c.height = 20; const x = c.getContext('2d'); x.lineWidth = 10; x.lineCap = 'round'; x.beginPath(); x.moveTo(10, 10); x.lineTo(10, 10); x.stroke(); return x.getImageData(10, 10, 1, 1).data[3]; })()],
["scroll-axis-lock", () => CSS.supports('scroll-axis-lock', 'auto')],
["scroll-marker-group-modes", () => CSS.supports('scroll-marker-group', 'after tabs')],
["area-display-none", () => (() => { const a = document.body.appendChild(document.createElement('area')); const d = getComputedStyle(a).display; a.remove(); return d; })()],
["color-mix-serialization", () => ((s) => { s.color = 'color-mix(in oklab, red 30%, blue)'; return s.color; })(document.createElement('i').style)],
["iamf-audio", () => document.createElement('video').canPlayType('audio/mp4; codecs="iamf"')],
["iamf-audio", () => MediaSource.isTypeSupported('audio/mp4; codecs="iamf"')],
["wgsl-language-features", () => navigator.gpu.wgslLanguageFeatures.has('buffer_view')],
["wgsl-language-features", () => navigator.gpu.wgslLanguageFeatures.has('texture_formats_tier1')],
["webgl-shader-log-nul", () => (() => { const gl = document.createElement('canvas').getContext('webgl'); const s = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(s, 'void main(){ undeclared_x; }'); gl.compileShader(s); const l = gl.getShaderInfoLog(s); return l.charCodeAt(l.length - 1) === 0; })()],
];
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"));
})();