From 145b9d9882e0307a379315219cafef4b0f65cfc1 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 27 May 2025 11:38:55 +1000 Subject: [PATCH 01/32] feat: Style Macro DevTool # Conflicts: # yarn.lock --- package.json | 1 + .../@react-spectrum/s2/style/style-macro.ts | 71 +++++++++++++++---- .../dev/style-macro-chrome-plugin/.parcelrc | 9 +++ .../style-macro-chrome-plugin/package.json | 14 ++++ .../src/content-script.js | 17 +++++ .../style-macro-chrome-plugin/src/devtool.js | 70 ++++++++++++++++++ .../src/devtools.html | 7 ++ .../src/manifest.json | 10 +++ yarn.lock | 67 +++++++++++++++++ 9 files changed, 254 insertions(+), 12 deletions(-) create mode 100644 packages/dev/style-macro-chrome-plugin/.parcelrc create mode 100644 packages/dev/style-macro-chrome-plugin/package.json create mode 100644 packages/dev/style-macro-chrome-plugin/src/content-script.js create mode 100644 packages/dev/style-macro-chrome-plugin/src/devtool.js create mode 100644 packages/dev/style-macro-chrome-plugin/src/devtools.html create mode 100644 packages/dev/style-macro-chrome-plugin/src/manifest.json diff --git a/package.json b/package.json index 2ca9dad9daf..ece844c7a4f 100644 --- a/package.json +++ b/package.json @@ -221,6 +221,7 @@ "@babel/preset-env": "7.24.4", "@babel/traverse": "7.24.1", "@babel/types": "7.24.0", + "@parcel/config-webextension": "2.14.0", "postcss": "8.4.24", "postcss-custom-properties": "13.2.0", "postcss-import": "15.1.0", diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index d41d6aaeee6..1bfcc3124e7 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -176,7 +176,7 @@ export function parseArbitraryValue(value: Value): string | undefined { return value.slice(1, -1); } else if ( typeof value === 'string' && ( - /^(var|calc|min|max|clamp|round|mod|rem|sin|cos|tan|asin|acos|atan|atan2|pow|sqrt|hypot|log|exp|abs|sign)\(.+\)$/.test(value) || + /^(var|calc|min|max|clamp|round|mod|rem|sin|cos|tan|asin|acos|atan|atan2|pow|sqrt|hypot|log|exp|abs|sign)\(.+\)$/.test(value) || /^(inherit|initial|unset)$/.test(value) ) ) { @@ -205,6 +205,8 @@ interface MacroContext { addAsset(asset: {type: string, content: string}): void } +let isCompilingDependencies: boolean | null | string = false; + export function createTheme(theme: T): StyleFunction, 'default' | Extract> { let properties = new Map>(Object.entries(theme.properties).map(([k, v]) => { if (!Array.isArray(v) && v.cssProperties) { @@ -280,8 +282,11 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction(); - let js = 'let rules = " ";\n'; + let js = 'let rules = " ", currentRules = {};\n'; if (allowedOverrides?.length) { for (let property of allowedOverrides) { let shorthand = theme.shorthands[property]; @@ -315,7 +320,7 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction classNamePrefix(p, p)).join('|')})[^\\s]+/g`; + let regex = `/(?:^|\\s)(${[...allowedOverridesSet].map(p => classNamePrefix(p, p)).join('|')}|-macro\\$)[^\\s]+/g`; if (loop) { - js += `let matches = (overrides || '').matchAll(${regex});\n`; + js += `let matches = String(overrides || '').matchAll(${regex});\n`; js += 'for (let p of matches) {\n'; js += loop; js += ' rules += p[0];\n'; js += '}\n'; } else { - js += `rules += ((overrides || '').match(${regex}) || []).join('')\n`; + js += `rules += (String(overrides || '').match(${regex}) || []).join('')\n`; } } @@ -383,11 +388,19 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction(theme: T): StyleFunction(theme: T): StyleFunction, indent?: string): string } +let conditionStack = []; + /** A CSS style rule. */ class StyleRule implements Rule { className: string; @@ -642,11 +658,15 @@ class StyleRule implements Rule { property: string; value: string; - constructor(className: string, property: string, value: string) { + constructor(className: string, property: string, value: string, themeProperty, themeValue) { this.className = className; this.pseudos = ''; this.property = property; this.value = value; + if (isCompilingDependencies !== null) { + this.themeProperty = themeProperty; + this.themeValue = themeValue; + } } addPseudo(prelude: string) { @@ -687,6 +707,21 @@ class StyleRule implements Rule { res += `${indent}if (!${this.property.replace('--', '__')}) `; } res += `${indent}rules += ' ${this.className}';`; + if (this.themeProperty) { + let name = this.themeProperty; + if (this.pseudos) { + conditionStack.push(this.pseudos); + } + if (conditionStack.length) { + // name += ` (${conditionStack.join(', ')})`; + res += ` currentRules[${JSON.stringify(name)}] = typeof currentRules[${JSON.stringify(name)}] === 'object' ? currentRules[${JSON.stringify(name)}] : {"default": currentRules[${JSON.stringify(name)}]}; currentRules[${JSON.stringify(name)}][${JSON.stringify(conditionStack.join(' && '))}] = ${JSON.stringify(this.themeValue)};`; + } else { + res += ` currentRules[${JSON.stringify(name)}] = ${JSON.stringify(this.themeValue)};`; + } + if (this.pseudos) { + conditionStack.pop(); + } + } return res; } } @@ -739,10 +774,12 @@ class GroupRule implements Rule { /** A rule that applies conditionally in CSS (e.g. @media). */ class AtRule extends GroupRule { prelude: string; + themeCondition: string | null; - constructor(rules: Rule[], prelude: string, layer: string) { + constructor(rules: Rule[], prelude: string, layer: string, themeCondition: string | null) { super(rules, layer); this.prelude = prelude; + this.themeCondition = themeCondition; } toCSS(rulesByLayer: Map, preludes: string[] = [], layer?: string): void { @@ -750,6 +787,13 @@ class AtRule extends GroupRule { super.toCSS(rulesByLayer, preludes, layer); preludes?.pop(); } + + toJS(allowedOverridesSet: Set, indent?: string): string { + conditionStack.push(this.themeCondition || this.prelude); + let res = super.toJS(allowedOverridesSet, indent); + conditionStack.pop(); + return res; + } } /** A rule that applies conditionally at runtime. */ @@ -766,7 +810,10 @@ class ConditionalRule extends GroupRule { } toJS(allowedOverridesSet: Set, indent = ''): string { - return `${indent}if (props.${this.condition}) {\n${super.toJS(allowedOverridesSet, indent + ' ')}\n${indent}}`; + conditionStack.push(this.condition); + let res = `${indent}if (props.${this.condition}) {\n${super.toJS(allowedOverridesSet, indent + ' ')}\n${indent}}`; + conditionStack.pop(); + return res; } } diff --git a/packages/dev/style-macro-chrome-plugin/.parcelrc b/packages/dev/style-macro-chrome-plugin/.parcelrc new file mode 100644 index 00000000000..f497a196e5f --- /dev/null +++ b/packages/dev/style-macro-chrome-plugin/.parcelrc @@ -0,0 +1,9 @@ +{ + "extends": "@parcel/config-webextension", + "transformers": { + "*.{js,mjs,jsx,cjs,ts,tsx}": [ + "@parcel/transformer-js", + "@parcel/transformer-react-refresh-wrap" + ] + } +} diff --git a/packages/dev/style-macro-chrome-plugin/package.json b/packages/dev/style-macro-chrome-plugin/package.json new file mode 100644 index 00000000000..2e0ecb56b2f --- /dev/null +++ b/packages/dev/style-macro-chrome-plugin/package.json @@ -0,0 +1,14 @@ +{ + "name": "style-macro-chrome-plugin", + "version": "0.0.1", + "private": true, + "scripts": { + "start": "parcel watch src/manifest.json --host localhost --config .parcelrc", + "build": "parcel build src/manifest.json --config .parcelrc" + }, + "devDependencies": { + "@parcel/config-default": "^2.14.0", + "@parcel/config-webextension": "^2.14.0", + "parcel": "^2.14.0" + } +} diff --git a/packages/dev/style-macro-chrome-plugin/src/content-script.js b/packages/dev/style-macro-chrome-plugin/src/content-script.js new file mode 100644 index 00000000000..fd78eb00e33 --- /dev/null +++ b/packages/dev/style-macro-chrome-plugin/src/content-script.js @@ -0,0 +1,17 @@ +window.addEventListener('message', function(event) { + // Only accept messages from the same frame + if (event.source !== window) { + return; + } + + console.log(event) + var message = event.data; + + // Only accept messages that we know are ours. Note that this is not foolproof + // and the page can easily spoof messages if it wants to. + if (message !== 'update-macros') { + return; + } + + chrome.runtime.sendMessage(message); +}); diff --git a/packages/dev/style-macro-chrome-plugin/src/devtool.js b/packages/dev/style-macro-chrome-plugin/src/devtool.js new file mode 100644 index 00000000000..77365e42986 --- /dev/null +++ b/packages/dev/style-macro-chrome-plugin/src/devtool.js @@ -0,0 +1,70 @@ +let injectScript = () => { + chrome.scripting.executeScript({ + target: { + tabId: chrome.devtools.inspectedWindow.tabId, + allFrames: true + }, + files: chrome.runtime.getManifest().content_scripts[0].js + }); +}; + +injectScript(); +chrome.tabs.onUpdated.addListener((tabId) => { + if (tabId === chrome.devtools.inspectedWindow.tabId) { + injectScript(); + } +}) + +chrome.devtools.panels.elements.createSidebarPane("Style Macros", (sidebar) => { + sidebar.setObject({}); + let update = () => { + chrome.devtools.inspectedWindow.eval('$0.getAttribute("class")', async (className) => { + if (typeof className !== 'string') { + sidebar.setObject({}); + return; + } + + let macros = className.matchAll(/-macro\$([^\s]+)/g); + let matches = []; + for (let macro of macros) { + await new Promise(resolve => { + chrome.devtools.inspectedWindow.eval(`$0.ownerDocument.defaultView.__macros?.[${JSON.stringify(macro[1])}]`, (result, x) => { + if (result) { + matches.push(result); + } + resolve(); + }); + }); + } + + if (matches.length === 0) { + sidebar.setObject({}); + } else if (matches.length === 1) { + sidebar.setObject(matches[0].style ?? {}, matches[0].loc); + } else { + let seenProperties = new Set(); + for (let i = matches.length - 1; i >= 0; i--) { + for (let key in matches[i].style) { + if (seenProperties.has(key)) { + delete matches[i].style[key]; + } else { + seenProperties.add(key); + } + } + } + + let res = {}; + for (let match of matches) { + res[match.loc] = match.style; + } + sidebar.setObject(res); + } + }); + }; + + chrome.devtools.panels.elements.onSelectionChanged.addListener(() => { + update(); + }); + + chrome.runtime.onMessage.addListener(() => update()); +}); diff --git a/packages/dev/style-macro-chrome-plugin/src/devtools.html b/packages/dev/style-macro-chrome-plugin/src/devtools.html new file mode 100644 index 00000000000..6f5f400e09b --- /dev/null +++ b/packages/dev/style-macro-chrome-plugin/src/devtools.html @@ -0,0 +1,7 @@ + + + + Devtools! + + + diff --git a/packages/dev/style-macro-chrome-plugin/src/manifest.json b/packages/dev/style-macro-chrome-plugin/src/manifest.json new file mode 100644 index 00000000000..52294672ff1 --- /dev/null +++ b/packages/dev/style-macro-chrome-plugin/src/manifest.json @@ -0,0 +1,10 @@ +{ + "manifest_version": 3, + "name": "Style Macro DevTools", + "version": "0.0.1", + "devtools_page": "devtools.html", + "content_scripts": [{ + "matches": ["*://*/*"], + "js": ["content-script.js"] + }] +} diff --git a/yarn.lock b/yarn.lock index 56957f5e18d..a833a0a3fcf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4429,6 +4429,21 @@ __metadata: languageName: node linkType: hard +"@parcel/config-webextension@npm:2.14.0": + version: 2.14.0 + resolution: "@parcel/config-webextension@npm:2.14.0" + dependencies: + "@parcel/config-default": "npm:2.14.0" + "@parcel/packager-webextension": "npm:2.14.0" + "@parcel/runtime-webextension": "npm:2.14.0" + "@parcel/transformer-raw": "npm:2.14.0" + "@parcel/transformer-webextension": "npm:2.14.0" + peerDependencies: + "@parcel/core": ^2.14.0 + checksum: 10c0/3348bcfb3143aba2bd684b4a39c3eccfbeaacb154f332a58c0f3f3e9a737433110724ca703f3d7b183480e2b0f4a072857f6df602a17beb9a390ab1459cf6290 + languageName: node + linkType: hard + "@parcel/core@npm:2.14.0, @parcel/core@npm:^2.13.1, @parcel/core@npm:^2.14.0": version: 2.14.0 resolution: "@parcel/core@npm:2.14.0" @@ -4767,6 +4782,17 @@ __metadata: languageName: node linkType: hard +"@parcel/packager-webextension@npm:2.14.0": + version: 2.14.0 + resolution: "@parcel/packager-webextension@npm:2.14.0" + dependencies: + "@parcel/plugin": "npm:2.14.0" + "@parcel/utils": "npm:2.14.0" + nullthrows: "npm:^1.1.1" + checksum: 10c0/85b893868b7bfa9db350112de2e5736dcdb303cb07bd4269ce7c75d5f38b83e999f38fb518e7871dd691c696011463fc67a90ab05b561f2636c6510d93c9cf96 + languageName: node + linkType: hard + "@parcel/plugin@npm:2.14.0, @parcel/plugin@npm:^2.0.0, @parcel/plugin@npm:^2.10.2, @parcel/plugin@npm:^2.14.0": version: 2.14.0 resolution: "@parcel/plugin@npm:2.14.0" @@ -4903,6 +4929,17 @@ __metadata: languageName: node linkType: hard +"@parcel/runtime-webextension@npm:2.14.0": + version: 2.14.0 + resolution: "@parcel/runtime-webextension@npm:2.14.0" + dependencies: + "@parcel/plugin": "npm:2.14.0" + "@parcel/utils": "npm:2.14.0" + nullthrows: "npm:^1.1.1" + checksum: 10c0/19a26d2054b6d8acf0ef5a7e793bc9a1231370607cf691bacc54ede5859fe2a25e61915d175718eb8b0ce279d496ab8cde94a1e8e798ee2a199f06a23b1f653e + languageName: node + linkType: hard + "@parcel/rust@npm:2.14.0": version: 2.14.0 resolution: "@parcel/rust@npm:2.14.0" @@ -5156,6 +5193,19 @@ __metadata: languageName: node linkType: hard +"@parcel/transformer-webextension@npm:2.14.0": + version: 2.14.0 + resolution: "@parcel/transformer-webextension@npm:2.14.0" + dependencies: + "@mischnic/json-sourcemap": "npm:^0.1.0" + "@parcel/diagnostic": "npm:2.14.0" + "@parcel/plugin": "npm:2.14.0" + "@parcel/utils": "npm:2.14.0" + content-security-policy-parser: "npm:^0.6.0" + checksum: 10c0/b83c02346da27b0a4b5ec22a9d304724c41fe576f3c6b9ebe43e7c0d40ddf6dc80dbb9ca6086d97f4301181eb516e6bbfb98b166195325b8a223e83637769f41 + languageName: node + linkType: hard + "@parcel/ts-utils@npm:2.14.0": version: 2.14.0 resolution: "@parcel/ts-utils@npm:2.14.0" @@ -14859,6 +14909,13 @@ __metadata: languageName: node linkType: hard +"content-security-policy-parser@npm:^0.6.0": + version: 0.6.0 + resolution: "content-security-policy-parser@npm:0.6.0" + checksum: 10c0/f494e69020e2320179eab47ad2cdafb09752ed63ca4fb5445071381e392d19edd110c0c3ec43f135d27c34b49dbab851b7fcf188dd2ba30cacd6e1107b15b674 + languageName: node + linkType: hard + "content-type@npm:~1.0.4, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" @@ -30386,6 +30443,16 @@ __metadata: languageName: node linkType: hard +"style-macro-chrome-plugin@workspace:packages/dev/style-macro-chrome-plugin": + version: 0.0.0-use.local + resolution: "style-macro-chrome-plugin@workspace:packages/dev/style-macro-chrome-plugin" + dependencies: + "@parcel/config-default": "npm:^2.14.0" + "@parcel/config-webextension": "npm:^2.14.0" + parcel: "npm:^2.14.0" + languageName: unknown + linkType: soft + "style-to-object@npm:^0.3.0": version: 0.3.0 resolution: "style-to-object@npm:0.3.0" From 7d8b45369bc01e1988c1aac58df8be7274344ebc Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 27 May 2025 12:02:29 +1000 Subject: [PATCH 02/32] add parcel patch --- ...el-transformer-js-npm-2.14.0-9521af387e.patch | 16 ++++++++++++++++ package.json | 5 ++++- .../dev/style-macro-chrome-plugin/package.json | 1 + yarn.lock | 3 ++- 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 .yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch diff --git a/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch b/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch new file mode 100644 index 00000000000..2be536cf585 --- /dev/null +++ b/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch @@ -0,0 +1,16 @@ +diff --git a/lib/JSTransformer.js b/lib/JSTransformer.js +index 1e0991fc8f9c231b70eefd7e177119a06162eeca..e5be5a0901ebc97cbbbb7bc0c774787de36fa2b5 100644 +--- a/lib/JSTransformer.js ++++ b/lib/JSTransformer.js +@@ -446,6 +446,11 @@ var _default = exports.default = new (_plugin().Transformer)({ + specifierType: 'esm' + }); + }, ++ loc: { ++ filePath: asset.filePath, ++ line: loc.line, ++ col: loc.col ++ }, + invalidateOnFileChange(filePath) { + asset.invalidateOnFileChange(filePath); + }, diff --git a/package.json b/package.json index ece844c7a4f..a66478f7398 100644 --- a/package.json +++ b/package.json @@ -222,6 +222,7 @@ "@babel/traverse": "7.24.1", "@babel/types": "7.24.0", "@parcel/config-webextension": "2.14.0", + "@parcel/transformer-js": "2.14.0", "postcss": "8.4.24", "postcss-custom-properties": "13.2.0", "postcss-import": "15.1.0", @@ -239,7 +240,9 @@ "@types/node@npm:>= 8": "^22", "micromark-extension-mdxjs": "patch:micromark-extension-mdxjs@npm%3A1.0.0#~/.yarn/patches/micromark-extension-mdxjs-npm-1.0.0-d2b6b69e4a.patch", "remark-mdx": "patch:remark-mdx@npm%3A2.0.0-rc.2#~/.yarn/patches/remark-mdx-npm-2.0.0-rc.2-7a71234e1f.patch", - "remark-parse": "patch:remark-parse@npm%3A10.0.1#~/.yarn/patches/remark-parse-npm-10.0.1-e654d7df78.patch" + "remark-parse": "patch:remark-parse@npm%3A10.0.1#~/.yarn/patches/remark-parse-npm-10.0.1-e654d7df78.patch", + "@parcel/transformer-js@npm:2.14.0": "patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch", + "@parcel/transformer-js@npm:^2.13.1": "patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch" }, "@parcel/transformer-css": { "cssModules": { diff --git a/packages/dev/style-macro-chrome-plugin/package.json b/packages/dev/style-macro-chrome-plugin/package.json index 2e0ecb56b2f..cffb9921032 100644 --- a/packages/dev/style-macro-chrome-plugin/package.json +++ b/packages/dev/style-macro-chrome-plugin/package.json @@ -9,6 +9,7 @@ "devDependencies": { "@parcel/config-default": "^2.14.0", "@parcel/config-webextension": "^2.14.0", + "@parcel/core": "^2.14.0", "parcel": "^2.14.0" } } diff --git a/yarn.lock b/yarn.lock index a833a0a3fcf..7ddce244347 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5041,7 +5041,7 @@ __metadata: languageName: node linkType: hard -"@parcel/transformer-js@npm:2.14.0, @parcel/transformer-js@npm:^2.13.1": +"@parcel/transformer-js@npm:2.14.0": version: 2.14.0 resolution: "@parcel/transformer-js@npm:2.14.0" dependencies: @@ -30449,6 +30449,7 @@ __metadata: dependencies: "@parcel/config-default": "npm:^2.14.0" "@parcel/config-webextension": "npm:^2.14.0" + "@parcel/core": "npm:^2.14.0" parcel: "npm:^2.14.0" languageName: unknown linkType: soft From 3266c18cd722b03f1e8d8a8e0b2f61e457ff4313 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 27 May 2025 14:12:11 +1000 Subject: [PATCH 03/32] small fixes --- eslint.config.mjs | 5 +++++ packages/@react-spectrum/s2/chromatic/CardView.stories.tsx | 2 +- packages/@react-spectrum/s2/stories/CardView.stories.tsx | 6 +++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 7a94bf740f3..11a0df3af63 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -497,4 +497,9 @@ export default [{ rules: { "react/react-in-jsx-scope": OFF, }, +}, { + files: ["packages/dev/style-macro-chrome-plugin/**"], + env: { + webextensions: true + } }]; \ No newline at end of file diff --git a/packages/@react-spectrum/s2/chromatic/CardView.stories.tsx b/packages/@react-spectrum/s2/chromatic/CardView.stories.tsx index c8e89b63397..218d90a5f8b 100644 --- a/packages/@react-spectrum/s2/chromatic/CardView.stories.tsx +++ b/packages/@react-spectrum/s2/chromatic/CardView.stories.tsx @@ -41,7 +41,7 @@ const cardViewStyles = style({ } }); -export const Empty = (args: CardViewProps, {viewMode}) => { +export const Empty = (args: CardViewProps, {viewMode} = {viewMode: ''}) => { return ( , {viewMode}) => { +export const Example = (args: CardViewProps, {viewMode} = {viewMode: ''}) => { let list = useAsyncList({ async load({signal, cursor, items}) { let page = cursor || 1; @@ -157,7 +157,7 @@ Example.args = { selectionMode: 'multiple' }; -export const Empty = (args: CardViewProps, {viewMode}) => { +export const Empty = (args: CardViewProps, {viewMode} = {viewMode: ''}) => { return ( , {viewMode}) => { +export const CollectionCards = (args: CardViewProps, {viewMode} = {viewMode: ''}) => { let list = useAsyncList({ async load({signal, cursor}) { let page = cursor || 1; From 8e4f8eef963d052d402af17c9193bf1032e5964a Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 27 May 2025 15:48:06 +1000 Subject: [PATCH 04/32] fix mergeStyles --- eslint.config.mjs | 7 +++++-- packages/@react-spectrum/s2/style/runtime.ts | 15 +++++++++++---- .../@react-spectrum/s2/style/style-macro.ts | 17 +++++++++++++---- .../dev/style-macro-chrome-plugin/package.json | 13 +++++++++++-- .../src/content-script.js | 13 +++++++++++-- .../style-macro-chrome-plugin/src/devtool.js | 8 ++++---- 6 files changed, 55 insertions(+), 18 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 11a0df3af63..d43d06d328d 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -499,7 +499,10 @@ export default [{ }, }, { files: ["packages/dev/style-macro-chrome-plugin/**"], - env: { - webextensions: true + languageOptions: { + globals: { + ...globals.webextensions, + ...globals.browser + } } }]; \ No newline at end of file diff --git a/packages/@react-spectrum/s2/style/runtime.ts b/packages/@react-spectrum/s2/style/runtime.ts index 5b567e2ab56..9bbbfc982ff 100644 --- a/packages/@react-spectrum/s2/style/runtime.ts +++ b/packages/@react-spectrum/s2/style/runtime.ts @@ -39,16 +39,23 @@ import {StyleString} from './types'; export function mergeStyles(...styles: (StyleString | null | undefined)[]): StyleString { let definedStyles = styles.filter(Boolean) as StyleString[]; if (definedStyles.length === 1) { - return definedStyles[0]; + let first = definedStyles[0]; + if (typeof first !== 'string') { + // static macro has a toString method so that we generate the style macro map for the entry + // it's automatically called in other places, but for our merging, we have to call it ourselves + return (first as StyleString).toString() as StyleString; + } + return first; } - let map = new Map(); + let map = new Map(); for (let style of definedStyles) { - for (let [k, v] of parse(style)) { + // must call toString here for the static macro + for (let [k, v] of parse(style.toString())) { map.set(k, v); } } - + let res = ''; for (let value of map.values()) { res += value; diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 1bfcc3124e7..2dbd23e1322 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -388,19 +388,26 @@ export function createTheme(theme: T): StyleFunction, indent?: string): string } -let conditionStack = []; +let conditionStack: string[] = []; /** A CSS style rule. */ class StyleRule implements Rule { @@ -657,8 +664,10 @@ class StyleRule implements Rule { pseudos: string; property: string; value: string; + themeProperty: string | undefined; + themeValue: Value | undefined; - constructor(className: string, property: string, value: string, themeProperty, themeValue) { + constructor(className: string, property: string, value: string, themeProperty: string, themeValue) { this.className = className; this.pseudos = ''; this.property = property; diff --git a/packages/dev/style-macro-chrome-plugin/package.json b/packages/dev/style-macro-chrome-plugin/package.json index cffb9921032..d12a1966d24 100644 --- a/packages/dev/style-macro-chrome-plugin/package.json +++ b/packages/dev/style-macro-chrome-plugin/package.json @@ -1,7 +1,6 @@ { "name": "style-macro-chrome-plugin", - "version": "0.0.1", - "private": true, + "version": "0.1.0", "scripts": { "start": "parcel watch src/manifest.json --host localhost --config .parcelrc", "build": "parcel build src/manifest.json --config .parcelrc" @@ -11,5 +10,15 @@ "@parcel/config-webextension": "^2.14.0", "@parcel/core": "^2.14.0", "parcel": "^2.14.0" + }, + "rsp": { + "type": "cli" + }, + "repository": { + "type": "git", + "url": "https://github.com/adobe/react-spectrum" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/dev/style-macro-chrome-plugin/src/content-script.js b/packages/dev/style-macro-chrome-plugin/src/content-script.js index fd78eb00e33..c32edfbe61f 100644 --- a/packages/dev/style-macro-chrome-plugin/src/content-script.js +++ b/packages/dev/style-macro-chrome-plugin/src/content-script.js @@ -1,10 +1,16 @@ -window.addEventListener('message', function(event) { + +if (window.__macrosLoaded) { + return; +} +window.__macrosLoaded = true; + +window.addEventListener('message', function (event) { // Only accept messages from the same frame if (event.source !== window) { return; } - console.log(event) + // console.log(event) var message = event.data; // Only accept messages that we know are ours. Note that this is not foolproof @@ -12,6 +18,9 @@ window.addEventListener('message', function(event) { if (message !== 'update-macros') { return; } + // if this script is run multiple times on the page, then only handle it once + event.stopImmediatePropagation(); + event.stopPropagation(); chrome.runtime.sendMessage(message); }); diff --git a/packages/dev/style-macro-chrome-plugin/src/devtool.js b/packages/dev/style-macro-chrome-plugin/src/devtool.js index 77365e42986..e8816567a7f 100644 --- a/packages/dev/style-macro-chrome-plugin/src/devtool.js +++ b/packages/dev/style-macro-chrome-plugin/src/devtool.js @@ -9,13 +9,13 @@ let injectScript = () => { }; injectScript(); -chrome.tabs.onUpdated.addListener((tabId) => { - if (tabId === chrome.devtools.inspectedWindow.tabId) { +chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { + if (tabId === chrome.devtools.inspectedWindow.tabId && changeInfo.status === 'complete' && tab.active) { injectScript(); } -}) +}); -chrome.devtools.panels.elements.createSidebarPane("Style Macros", (sidebar) => { +chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { sidebar.setObject({}); let update = () => { chrome.devtools.inspectedWindow.eval('$0.getAttribute("class")', async (className) => { From af59e2ec1daece111bb51eecaceb064dab9cbef3 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 3 Jun 2025 13:42:28 +1000 Subject: [PATCH 05/32] Add README so people know how to develop this extension --- .../dev/style-macro-chrome-plugin/README.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 packages/dev/style-macro-chrome-plugin/README.md diff --git a/packages/dev/style-macro-chrome-plugin/README.md b/packages/dev/style-macro-chrome-plugin/README.md new file mode 100644 index 00000000000..5e363b5cc1c --- /dev/null +++ b/packages/dev/style-macro-chrome-plugin/README.md @@ -0,0 +1,28 @@ +# style-macro-chrome-plugin + +This is a chrome plugin to assist in debugging the styles applied by our Style Macro. + +## Local development + +From the root of our monopackage, run + +``` +yarn +yarn workspace style-macro-chrome-plugin start +``` + +This will create a dist directory in the directory `packages/dev/style-macro-chrome-plugin` which will update anytime the code changes and results in a rebuild. + +Next, open Chrome and go to [chrome://extensions/](chrome://extensions/). + +Load an unpacked extension, it's a button in the top left, and navigate to the dist directory. + +The extension is now registered in Chrome and you can go to storybook or docs, wherever you are working. + +Inspect an element on the page to open dev tools and go to the Style Macro panel. + +## Troubleshooting + +If the panel isn't updating with styles, try closing the dev tools and reopening it. + +If the extension doesn't appear to have the latest code, try closing the dev tools and reopening it. From 85e70d2b6b94a4aa91c3063d81195587cd166895 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 3 Jun 2025 16:03:32 +1000 Subject: [PATCH 06/32] add todos, fix tests, fix lint --- packages/@react-spectrum/s2/src/Button.tsx | 2 +- .../s2/style/__tests__/mergeStyles.test.js | 8 +- .../s2/style/__tests__/style-macro.test.js | 85 +++++++++++++------ .../@react-spectrum/s2/style/style-macro.ts | 11 ++- .../dev/style-macro-chrome-plugin/README.md | 12 +++ 5 files changed, 83 insertions(+), 35 deletions(-) diff --git a/packages/@react-spectrum/s2/src/Button.tsx b/packages/@react-spectrum/s2/src/Button.tsx index 0e25f55adc0..58289d79588 100644 --- a/packages/@react-spectrum/s2/src/Button.tsx +++ b/packages/@react-spectrum/s2/src/Button.tsx @@ -347,7 +347,7 @@ export const Button = forwardRef(function Button(props: ButtonProps, ref: Focusa isStaticColor: !!staticColor }, props.styles)}> {(renderProps) => (<> - {variant === 'genai' || variant === 'premium' + {variant === 'genai' || variant === 'premium' ? ( { it('should merge styles', () => { let a = style({backgroundColor: 'red-1000', color: 'pink-100'}); let b = style({fontSize: 'body-xs', backgroundColor: 'gray-50'}); let expected = style({backgroundColor: 'gray-50', color: 'pink-100', fontSize: 'body-xs'}); let merged = mergeStyles(a, b); - expect(merged).toBe(expected); + expect(stripMacro(merged)).toBe(stripMacro(expected.toString())); }); it('should merge with arbitrary values', () => { @@ -27,6 +31,6 @@ describe('mergeStyles', () => { let b = style({fontSize: '[15px]', backgroundColor: 'gray-50'}); let expected = style({backgroundColor: 'gray-50', color: '[hotpink]', fontSize: '[15px]'}); let merged = mergeStyles(a, b); - expect(merged).toBe(expected); + expect(stripMacro(merged)).toBe(stripMacro(expected.toString())); }); }); diff --git a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js index 1fa22b97fdf..9332e16d65a 100644 --- a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js +++ b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js @@ -22,7 +22,8 @@ function testStyle(...args) { }, args ); - return {css, js}; + + return {css, js: typeof js === 'function' ? js : js.toString()}; } describe('style-macro', () => { @@ -55,7 +56,7 @@ describe('style-macro', () => { " `); - expect(js).toMatchInlineSnapshot('" Jbs9 Jbpv9"'); + expect(js).toMatchInlineSnapshot('" Jbs9 Jbpv9 -macro$M74Bxe"'); }); it('should support self references', () => { @@ -118,7 +119,7 @@ describe('style-macro', () => { `); expect(js).toMatchInlineSnapshot( - '" _kc9 hc9 mCPFGYc9 lc9 SMBFGYc9 Rv9 ZjUQgKd9 -m_-mc9 -S_-Sv9"' + '" _kc9 hc9 mCPFGYc9 lc9 SMBFGYc9 Rv9 ZjUQgKd9 -m_-mc9 -S_-Sv9 -macro$wNXlmc"' ); }); @@ -136,9 +137,13 @@ describe('style-macro', () => { color: 'green-400' }); - expect(js()).toMatchInlineSnapshot('" gw9 pg9"'); - expect(overrides).toMatchInlineSnapshot('" g8tmWqb9 pHJ3AUd9"'); - expect(js({}, overrides)).toMatchInlineSnapshot('" g8tmWqb9 pg9"'); + expect(js()).toMatchInlineSnapshot('" gw9 pg9 -macro$7ucvu4"'); + expect(overrides).toMatchInlineSnapshot( + '" g8tmWqb9 pHJ3AUd9 -macro$sFRgme"' + ); + expect(js({}, overrides)).toMatchInlineSnapshot( + '" g8tmWqb9 -macro$sFRgme pg9 -macro$nt261r"' + ); }); it('should support allowed overrides for properties that expand into multiple', () => { @@ -153,9 +158,13 @@ describe('style-macro', () => { translateX: 40 }); - expect(js()).toMatchInlineSnapshot('" -_7PloMd-B9 __Ya9"'); - expect(overrides).toMatchInlineSnapshot('" -_7PloMd-D9 __Ya9"'); - expect(js({}, overrides)).toMatchInlineSnapshot('" -_7PloMd-D9 __Ya9"'); + expect(js()).toMatchInlineSnapshot('" -_7PloMd-B9 __Ya9 -macro$hzmozh"'); + expect(overrides).toMatchInlineSnapshot( + '" -_7PloMd-D9 __Ya9 -macro$f5PRU"' + ); + expect(js({}, overrides)).toMatchInlineSnapshot( + '" -_7PloMd-D9 __Ya9 -macro$f5PRU -macro$1vw5vro"' + ); }); it('should support allowed overrides for shorthands', () => { @@ -170,9 +179,11 @@ describe('style-macro', () => { padding: 40 }); - expect(js()).toMatchInlineSnapshot('" Tk9 Qk9 Sk9 Rk9"'); - expect(overrides).toMatchInlineSnapshot('" Tm9 Qm9 Sm9 Rm9"'); - expect(js({}, overrides)).toMatchInlineSnapshot('" Tm9 Qm9 Sm9 Rm9"'); + expect(js()).toMatchInlineSnapshot('" Tk9 Qk9 Sk9 Rk9 -macro$1jmmjz3"'); + expect(overrides).toMatchInlineSnapshot('" Tm9 Qm9 Sm9 Rm9 -macro$hWyGab"'); + expect(js({}, overrides)).toMatchInlineSnapshot( + '" Tm9 Qm9 Sm9 Rm9 -macro$hWyGab -macro$vku4y4"' + ); }); it("should support allowed overrides for values that aren't defined", () => { @@ -187,9 +198,11 @@ describe('style-macro', () => { minWidth: 32 }); - expect(js()).toMatchInlineSnapshot('" gE9"'); - expect(overrides).toMatchInlineSnapshot('" Nk9"'); - expect(js({}, overrides)).toMatchInlineSnapshot('" Nk9 gE9"'); + expect(js()).toMatchInlineSnapshot('" gE9 -macro$2v7u7e"'); + expect(overrides).toMatchInlineSnapshot('" Nk9 -macro$hsZrrc"'); + expect(js({}, overrides)).toMatchInlineSnapshot( + '" Nk9 -macro$hsZrrc gE9 -macro$emy58b"' + ); }); it('should support runtime conditions', () => { @@ -243,9 +256,13 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot('" gH9 pt9"'); - expect(js({isHovered: true})).toMatchInlineSnapshot('" gF9 po9"'); - expect(js({isPressed: true})).toMatchInlineSnapshot('" gE9 pm9"'); + expect(js({})).toMatchInlineSnapshot('" gH9 pt9 -macro$1cgd07e"'); + expect(js({isHovered: true})).toMatchInlineSnapshot( + '" gF9 po9 -macro$1b5rdyb"' + ); + expect(js({isPressed: true})).toMatchInlineSnapshot( + '" gE9 pm9 -macro$1aigku8"' + ); }); it('should support nested runtime conditions', () => { @@ -286,11 +303,15 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot('" gH9"'); - expect(js({isHovered: true})).toMatchInlineSnapshot('" gF9"'); - expect(js({isSelected: true})).toMatchInlineSnapshot('" g_h9"'); + expect(js({})).toMatchInlineSnapshot('" gH9 -macro$2v7ua5"'); + expect(js({isHovered: true})).toMatchInlineSnapshot( + '" gF9 -macro$2v7u8b"' + ); + expect(js({isSelected: true})).toMatchInlineSnapshot( + '" g_h9 -macro$nl39vw"' + ); expect(js({isSelected: true, isHovered: true})).toMatchInlineSnapshot( - '" g39"' + '" g39 -macro$2v7tqw"' ); }); @@ -305,9 +326,15 @@ describe('style-macro', () => { } }); - expect(js({variant: 'accent'})).toMatchInlineSnapshot('" gY9"'); - expect(js({variant: 'primary'})).toMatchInlineSnapshot('" gjQquMe9"'); - expect(js({variant: 'secondary'})).toMatchInlineSnapshot('" gw9"'); + expect(js({variant: 'accent'})).toMatchInlineSnapshot( + '" gY9 -macro$2v7upq"' + ); + expect(js({variant: 'primary'})).toMatchInlineSnapshot( + '" gjQquMe9 -macro$1xbmgag"' + ); + expect(js({variant: 'secondary'})).toMatchInlineSnapshot( + '" gw9 -macro$2v7vh8"' + ); }); it('supports runtime conditions nested inside css conditions', () => { @@ -341,8 +368,10 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot('" plb9"'); - expect(js({isSelected: true})).toMatchInlineSnapshot('" ple9"'); + expect(js({})).toMatchInlineSnapshot('" plb9 -macro$nlai7w"'); + expect(js({isSelected: true})).toMatchInlineSnapshot( + '" ple9 -macro$nlaian"' + ); }); it('should expand shorthand properties to longhands', () => { @@ -350,7 +379,7 @@ describe('style-macro', () => { padding: 24 }); - expect(js).toMatchInlineSnapshot('" Th9 Qh9 Sh9 Rh9"'); + expect(js).toMatchInlineSnapshot('" Th9 Qh9 Sh9 Rh9 -macro$tgBsxe"'); expect(css).toMatchInlineSnapshot(` "@layer _.a; diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 2dbd23e1322..73636d89141 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -389,9 +389,9 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction Date: Tue, 3 Jun 2025 16:04:59 +1000 Subject: [PATCH 07/32] fix dev logic --- packages/@react-spectrum/s2/style/style-macro.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 73636d89141..1c302f88f03 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -401,14 +401,14 @@ export function createTheme(theme: T): StyleFunction Date: Tue, 3 Jun 2025 16:28:20 +1000 Subject: [PATCH 08/32] add todo --- packages/dev/style-macro-chrome-plugin/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/dev/style-macro-chrome-plugin/README.md b/packages/dev/style-macro-chrome-plugin/README.md index 2e554386453..9e4a943249a 100644 --- a/packages/dev/style-macro-chrome-plugin/README.md +++ b/packages/dev/style-macro-chrome-plugin/README.md @@ -38,3 +38,4 @@ If the extension doesn't appear to have the latest code, try closing the dev too - [ ] Link to file on the side instead of grouping by filename? - [ ] Add classname that is applying style? - [ ] Work in MFE's +- [ ] Don't memory leak the global object From 5a89555790afbcf2b44f228d7168d2d41151e7a0 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Wed, 4 Jun 2025 13:54:50 +1000 Subject: [PATCH 09/32] use static method to inject script --- packages/dev/style-macro-chrome-plugin/README.md | 2 ++ .../dev/style-macro-chrome-plugin/src/devtool.js | 15 --------------- .../style-macro-chrome-plugin/src/manifest.json | 4 +++- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/packages/dev/style-macro-chrome-plugin/README.md b/packages/dev/style-macro-chrome-plugin/README.md index 9e4a943249a..b58aa54e91f 100644 --- a/packages/dev/style-macro-chrome-plugin/README.md +++ b/packages/dev/style-macro-chrome-plugin/README.md @@ -27,6 +27,8 @@ If the panel isn't updating with styles, try closing the dev tools and reopening If the extension doesn't appear to have the latest code, try closing the dev tools and reopening it. +If every tab you have open (or many of them) reload when you make local changes to the extension, then go into the extension settings and limit it to `localhost` or something appropriate. + ## ToDos - [ ] Work with RSC diff --git a/packages/dev/style-macro-chrome-plugin/src/devtool.js b/packages/dev/style-macro-chrome-plugin/src/devtool.js index e8816567a7f..eeff5601b62 100644 --- a/packages/dev/style-macro-chrome-plugin/src/devtool.js +++ b/packages/dev/style-macro-chrome-plugin/src/devtool.js @@ -1,19 +1,4 @@ -let injectScript = () => { - chrome.scripting.executeScript({ - target: { - tabId: chrome.devtools.inspectedWindow.tabId, - allFrames: true - }, - files: chrome.runtime.getManifest().content_scripts[0].js - }); -}; -injectScript(); -chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { - if (tabId === chrome.devtools.inspectedWindow.tabId && changeInfo.status === 'complete' && tab.active) { - injectScript(); - } -}); chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { sidebar.setObject({}); diff --git a/packages/dev/style-macro-chrome-plugin/src/manifest.json b/packages/dev/style-macro-chrome-plugin/src/manifest.json index 52294672ff1..770326cd24b 100644 --- a/packages/dev/style-macro-chrome-plugin/src/manifest.json +++ b/packages/dev/style-macro-chrome-plugin/src/manifest.json @@ -5,6 +5,8 @@ "devtools_page": "devtools.html", "content_scripts": [{ "matches": ["*://*/*"], - "js": ["content-script.js"] + "js": ["content-script.js"], + "all_frames": true, + "run_at": "document_start" }] } From a68dbfd8e61fded6dded1b3cb4f7c6c2111b2942 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Thu, 5 Jun 2025 13:01:54 +1000 Subject: [PATCH 10/32] fix the patch --- package.json | 4 +--- .../style-macro-chrome-plugin/package.json | 1 + yarn.lock | 22 +++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a66478f7398..5560b459421 100644 --- a/package.json +++ b/package.json @@ -222,7 +222,6 @@ "@babel/traverse": "7.24.1", "@babel/types": "7.24.0", "@parcel/config-webextension": "2.14.0", - "@parcel/transformer-js": "2.14.0", "postcss": "8.4.24", "postcss-custom-properties": "13.2.0", "postcss-import": "15.1.0", @@ -241,8 +240,7 @@ "micromark-extension-mdxjs": "patch:micromark-extension-mdxjs@npm%3A1.0.0#~/.yarn/patches/micromark-extension-mdxjs-npm-1.0.0-d2b6b69e4a.patch", "remark-mdx": "patch:remark-mdx@npm%3A2.0.0-rc.2#~/.yarn/patches/remark-mdx-npm-2.0.0-rc.2-7a71234e1f.patch", "remark-parse": "patch:remark-parse@npm%3A10.0.1#~/.yarn/patches/remark-parse-npm-10.0.1-e654d7df78.patch", - "@parcel/transformer-js@npm:2.14.0": "patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch", - "@parcel/transformer-js@npm:^2.13.1": "patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch" + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch" }, "@parcel/transformer-css": { "cssModules": { diff --git a/packages/dev/style-macro-chrome-plugin/package.json b/packages/dev/style-macro-chrome-plugin/package.json index d12a1966d24..11098f97b87 100644 --- a/packages/dev/style-macro-chrome-plugin/package.json +++ b/packages/dev/style-macro-chrome-plugin/package.json @@ -9,6 +9,7 @@ "@parcel/config-default": "^2.14.0", "@parcel/config-webextension": "^2.14.0", "@parcel/core": "^2.14.0", + "@parcel/transformer-js": "^2.14.0", "parcel": "^2.14.0" }, "rsp": { diff --git a/yarn.lock b/yarn.lock index 7ddce244347..a604d8bc635 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5062,6 +5062,27 @@ __metadata: languageName: node linkType: hard +"@parcel/transformer-js@patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch": + version: 2.14.0 + resolution: "@parcel/transformer-js@patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch::version=2.14.0&hash=773e96" + dependencies: + "@parcel/diagnostic": "npm:2.14.0" + "@parcel/plugin": "npm:2.14.0" + "@parcel/rust": "npm:2.14.0" + "@parcel/source-map": "npm:^2.1.1" + "@parcel/utils": "npm:2.14.0" + "@parcel/workers": "npm:2.14.0" + "@swc/helpers": "npm:^0.5.0" + browserslist: "npm:^4.6.6" + nullthrows: "npm:^1.1.1" + regenerator-runtime: "npm:^0.14.1" + semver: "npm:^7.5.2" + peerDependencies: + "@parcel/core": ^2.14.0 + checksum: 10c0/ac714d500c6ceb36290d6605a4de9724bcfc51965f7e496eb279943e73a7d0df5109bdb1dacec03966e5482b64c283e0583066f0272b8a4c860bd76923c55cf1 + languageName: node + linkType: hard + "@parcel/transformer-json@npm:2.14.0": version: 2.14.0 resolution: "@parcel/transformer-json@npm:2.14.0" @@ -30450,6 +30471,7 @@ __metadata: "@parcel/config-default": "npm:^2.14.0" "@parcel/config-webextension": "npm:^2.14.0" "@parcel/core": "npm:^2.14.0" + "@parcel/transformer-js": "npm:^2.14.0" parcel: "npm:^2.14.0" languageName: unknown linkType: soft From 2bf9d6a7d0d4d9d10f1027f45f68ddd4dde1d65b Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Thu, 5 Jun 2025 13:15:11 +1000 Subject: [PATCH 11/32] I don't think there is a bug here, different states get different macro hashes --- packages/@react-spectrum/s2/style/style-macro.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 1c302f88f03..b9a2eb7a216 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -388,7 +388,6 @@ export function createTheme(theme: T): StyleFunction Date: Thu, 5 Jun 2025 13:16:33 +1000 Subject: [PATCH 12/32] remove console logs --- packages/@react-spectrum/s2/style/style-macro.ts | 3 --- packages/dev/style-macro-chrome-plugin/src/content-script.js | 1 - 2 files changed, 4 deletions(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index b9a2eb7a216..db060370eea 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -395,7 +395,6 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction Date: Thu, 5 Jun 2025 17:32:05 +1000 Subject: [PATCH 13/32] add extension icon --- .../style-macro-chrome-plugin/src/icons/128.png | Bin 0 -> 10103 bytes .../style-macro-chrome-plugin/src/icons/16.png | Bin 0 -> 877 bytes .../style-macro-chrome-plugin/src/icons/32.png | Bin 0 -> 1987 bytes .../style-macro-chrome-plugin/src/icons/48.png | Bin 0 -> 3413 bytes .../style-macro-chrome-plugin/src/icons/96.png | Bin 0 -> 7532 bytes .../style-macro-chrome-plugin/src/manifest.json | 9 ++++++++- 6 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 packages/dev/style-macro-chrome-plugin/src/icons/128.png create mode 100644 packages/dev/style-macro-chrome-plugin/src/icons/16.png create mode 100644 packages/dev/style-macro-chrome-plugin/src/icons/32.png create mode 100644 packages/dev/style-macro-chrome-plugin/src/icons/48.png create mode 100644 packages/dev/style-macro-chrome-plugin/src/icons/96.png diff --git a/packages/dev/style-macro-chrome-plugin/src/icons/128.png b/packages/dev/style-macro-chrome-plugin/src/icons/128.png new file mode 100644 index 0000000000000000000000000000000000000000..a0a1377e1a933483bdcef461f0c3813bad037c80 GIT binary patch literal 10103 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 R5a3QaKtV=Tx>C{%@;{S}i6;O6 literal 0 HcmV?d00001 diff --git a/packages/dev/style-macro-chrome-plugin/src/icons/16.png b/packages/dev/style-macro-chrome-plugin/src/icons/16.png new file mode 100644 index 0000000000000000000000000000000000000000..41a22d0a311ca53a261ed94b5efab5669b7661bf GIT binary patch literal 877 zcmV-z1CsoSP)vUY3L+}6s7O_Vl*+BBleRJB0ig+FJGL|S z%$)3dy1_W62SUcOP`-(0>LUYTET?ZyuF zs(*TQ^IpJSdddKRCsuC>0FcOWOMK_tnK}T}^|S&2KaD;jZXP-;sw6`E^P;2NTy1KS zpdQNKuhXGH5F=wMX2TfvxkHQBuXQt4E4ws475+De%}B)UP=-4)>S!WOiy~_!7y|$# zj!g{!z+_{GQTToY05@|-jQ%iHk7Mr3i?QSS*1&y(1HC_;ct`<&1IuOpzZO)FW6a#f zKUCsUPS49&868co<3tB&GuZBSiVVvf)JG zze`_utVr4sy7aRhD;tPXqL9{7eiUJ)+4jp#tFDNm*AsUHp~Wc4G|bxmYB!Q;4FG78 z33z2>kOF{6Db{VzTeF<(o*(SD5{n4}0PUugb#0DM-u~EfcANhg3<$K7AVlqnJt8;& zfH2g4?eIMSNO4bJyR+5sY?q%ub+%okF>Q<=0WXzglF#IxeLAhqPp9M>09&UY`9M4&-B%PO#on00000NkvXXu0mjf D0OFE2 literal 0 HcmV?d00001 diff --git a/packages/dev/style-macro-chrome-plugin/src/icons/32.png b/packages/dev/style-macro-chrome-plugin/src/icons/32.png new file mode 100644 index 0000000000000000000000000000000000000000..493110735d24a98300418e84e5e0b40093a7e0b5 GIT binary patch literal 1987 zcmV;!2R!(RP)G3{hXJ>XE{eivAuGhqs+VgAfne#s1J@;P9Fbn`dOI7nz01g8P;r~m00FDhN zhmHdPWf%rps+x}zo`2G_^UG=ep{+V`Iz0=u#>o=uqZ3#&*e?)ORX9bq^sQXuAE<9c z&So!>)pI!^-+x_6zW8!b7sb~GlS5BY&Az6?gy#<}`NQvIieYREb-ZHq7WVw@RCGx^ z5}Z$_*I<%8OB&e=yT8es`D#2qHM#FOpDv2upqhP6BZ24kv)qRD^BOW!eQW~XKK=GR z9cMKi2L@v*fRs*A8r|B;PCvWfWtPcZ?2X2sKN=wbLiV+vb5%Aqm&%=A$>ecxC?0)t zG9^T0wJ7JJE!nGCxynH(2v_>7-#Yn6!EA?Jy~+xpjQ{{e)1}Rthqm^$sfIzas*X*=H@sW=dZbxh!f{>zpqhP6 zMyT^opXr>8N5KF3mAtO$EM3TDj%=uLvXK}jYpb#JyE{QFbix^^^P6>)q2b7heMf5C zj3u|(%W(kk?9&I3aC-p&;U~TdvXIOH;Bh07Oy#GM%m~pzA!hac@H_DR@<(#0r9mO# zc#QJ|{pC8=rUv(pTDLUo900!b;olQx8G4}sG_GsSANkoHjEzUA_WRdRPA3llHt+5y zpl3ynFxELbQ)3f3`hhlDJ@;|3#ciM7(9ALwD^MSs!1_1bGxQt@$FoE8ilGqEb2;meR?vB4s31$wQ?S#>8x~URy(gOv`crrDI46KD zeLd2l6TguRLO3)3g(Oq;#;K1o&5JzrYcF=iUVrC|Rm`M(1O1;Er(f?9Wib_0a_Nwg zONXRX!hYfWM_C&U7sc8@KhUO_ZLJ;|x(mi~=N;Xhb^y54yt*W?m`3p4!@Hc`b!+t} z_wKBIc+-9S?@xT7ur|iGb=$_`pixyV_m}P-k*CyRsmrUdZs=MO2Sp5+o%c61Cjiuy zR|f!oBGvjsL;+m2z^+y97v6nO7B5}4t!k>3moD~CJM1)BS?3M-Yy3rr6l()%38nRc zVf#!4ih!j7V9S*Ya>x5!MWCE*Yp>`W07Qe}y2jpRZ2yW)K7SGWA6#Jr5Ci~kWCs94DN#@i2#?jcv-25ey$(4( z79qN(SNtz38u}ZWi^&lHcqc9{I+xR>HowQxz}bpdaz)n>mE^nGiTP}}VC3pqW^pCs ziGmhg9P~I0!(gMgClZxp&J-MiYPpLM0sxb$0oH1@Zx1+1%5EhDA4H~eqgg4Z=sKq4 zg5N)E9kxs**tf;4Q=(*NhTGiFqZO zQS~`GD|D^4|N3Z2@5PMh*tho>yw`5%o9cpcrtZ$9&-Y(f0E7vEWADZ@?t)=RhN=p8cIxF{yiKi4CeY&Ik!@@e0l-jINqF^m5WwNt z$LWpn=f!_s zwgqX5q literal 0 HcmV?d00001 diff --git a/packages/dev/style-macro-chrome-plugin/src/icons/48.png b/packages/dev/style-macro-chrome-plugin/src/icons/48.png new file mode 100644 index 0000000000000000000000000000000000000000..6794ef2da835ad9fba232dee798d4443914188a6 GIT binary patch literal 3413 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 literal 0 HcmV?d00001 diff --git a/packages/dev/style-macro-chrome-plugin/src/icons/96.png b/packages/dev/style-macro-chrome-plugin/src/icons/96.png new file mode 100644 index 0000000000000000000000000000000000000000..b12d2c4a2f0104c313d0d3186e8e90d552154d85 GIT binary patch literal 7532 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 Date: Mon, 16 Jun 2025 12:59:15 +1000 Subject: [PATCH 14/32] use document idle instead of start to help with tab reload --- packages/dev/style-macro-chrome-plugin/src/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/style-macro-chrome-plugin/src/manifest.json b/packages/dev/style-macro-chrome-plugin/src/manifest.json index c2cab5a5a2c..9fce69eb06a 100644 --- a/packages/dev/style-macro-chrome-plugin/src/manifest.json +++ b/packages/dev/style-macro-chrome-plugin/src/manifest.json @@ -7,7 +7,7 @@ "matches": ["*://*/*"], "js": ["content-script.js"], "all_frames": true, - "run_at": "document_start" + "run_at": "document_idle" }], "icons": { "16": "icons/16.png", From 6fe2d0bfd2e6667e4297cced4d4a4cec55b53c6a Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Mon, 16 Jun 2025 13:32:06 +1000 Subject: [PATCH 15/32] fix package.json --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b4d19fa79f7..ea5c5239e2d 100644 --- a/package.json +++ b/package.json @@ -224,7 +224,7 @@ "@babel/types": "7.24.0", "@parcel/config-webextension": "2.14.0", "@parcel/transformer-react-refresh-wrap": "2.14.0", - "@parcel/transformer-js": "2.14.0", + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch", "@parcel/codeframe": "2.14.0", "postcss": "8.4.24", "postcss-custom-properties": "13.2.0", @@ -243,8 +243,7 @@ "@types/node@npm:>= 8": "^22", "micromark-extension-mdxjs": "patch:micromark-extension-mdxjs@npm%3A1.0.0#~/.yarn/patches/micromark-extension-mdxjs-npm-1.0.0-d2b6b69e4a.patch", "remark-mdx": "patch:remark-mdx@npm%3A2.0.0-rc.2#~/.yarn/patches/remark-mdx-npm-2.0.0-rc.2-7a71234e1f.patch", - "remark-parse": "patch:remark-parse@npm%3A10.0.1#~/.yarn/patches/remark-parse-npm-10.0.1-e654d7df78.patch", - "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.14.0#~/.yarn/patches/@parcel-transformer-js-npm-2.14.0-9521af387e.patch" + "remark-parse": "patch:remark-parse@npm%3A10.0.1#~/.yarn/patches/remark-parse-npm-10.0.1-e654d7df78.patch" }, "@parcel/transformer-css": { "cssModules": { From cafae4e661caa5535704fb764906e9a3406cc67e Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Thu, 23 Oct 2025 15:04:33 +1100 Subject: [PATCH 16/32] have dev tool handle all book keeping and poll to avoid memory leak --- .../@react-spectrum/s2/style/style-macro.ts | 7 +- .../dev/style-macro-chrome-plugin/README.md | 3 +- .../src/background.js | 60 +++++++ .../src/content-script.js | 92 ++++++++++- .../style-macro-chrome-plugin/src/devtool.js | 152 +++++++++++++----- .../src/manifest.json | 4 + 6 files changed, 270 insertions(+), 48 deletions(-) create mode 100644 packages/dev/style-macro-chrome-plugin/src/background.js diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index db060370eea..d325d6495de 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -388,13 +388,13 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction { + if (port.name === 'devtools-page') { + let tabId; + + // Listen for messages from DevTools + const messageListener = (message) => { + if (message.type === 'init') { + tabId = message.tabId; + devtoolsConnections.set(tabId, port); + console.log(`[Background] DevTools connected for tab ${tabId}`); + } else if (message.type === 'query-macros') { + console.log(`[Background] Forwarding query-macros to content script, hash: ${message.hash}, tabId: ${tabId}`); + // Forward query to content script + chrome.tabs.sendMessage(tabId, { + action: 'get-macro', + hash: message.hash + }).catch(err => { + console.error('[Background] Error sending message to content script:', err); + }); + } + }; + + port.onMessage.addListener(messageListener); + + // Clean up when DevTools disconnects + port.onDisconnect.addListener(() => { + if (tabId) { + devtoolsConnections.delete(tabId); + console.log(`DevTools disconnected for tab ${tabId}`); + } + }); + } +}); + +// Listen for messages from content scripts +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + const tabId = sender.tab?.id; + + if (!tabId) { + return; + } + + // Forward messages from content script to DevTools + if (message.action === 'update-macros' || message.action === 'macro-response') { + console.log(`[Background] Forwarding ${message.action} from content script to DevTools, tabId: ${tabId}`); + const devtoolsPort = devtoolsConnections.get(tabId); + if (devtoolsPort) { + devtoolsPort.postMessage(message); + } else { + console.warn(`[Background] No DevTools connection found for tab ${tabId}`); + } + } + + return false; // Don't keep channel open +}); + diff --git a/packages/dev/style-macro-chrome-plugin/src/content-script.js b/packages/dev/style-macro-chrome-plugin/src/content-script.js index 7111571a444..669f0af2438 100644 --- a/packages/dev/style-macro-chrome-plugin/src/content-script.js +++ b/packages/dev/style-macro-chrome-plugin/src/content-script.js @@ -4,6 +4,10 @@ if (window.__macrosLoaded) { } window.__macrosLoaded = true; +let debugLog = (...args) => { + // console.log('[Content Script]', ...args); +}; + window.addEventListener('message', function (event) { // Only accept messages from the same frame if (event.source !== window) { @@ -14,12 +18,88 @@ window.addEventListener('message', function (event) { // Only accept messages that we know are ours. Note that this is not foolproof // and the page can easily spoof messages if it wants to. - if (message !== 'update-macros') { - return; + if (message && typeof message === 'object' && message.action === 'update-macros') { + let {hash, loc, style} = message; + if (!window.__macros) { + window.__macros = {}; + } + + // Update the specific macro without overwriting others + window.__macros[hash] = { + loc, + style + }; + + debugLog('Updated macro:', hash, 'Total macros:', Object.keys(window.__macros).length); + + // if this script is run multiple times on the page, then only handle it once + event.stopImmediatePropagation(); + event.stopPropagation(); + + // Send message to background script (which forwards to DevTools) + try { + chrome.runtime.sendMessage({ + action: 'update-macros', + ...message + }); + } catch (err) { + debugLog('Failed to send update-macros message:', err); + } } - // if this script is run multiple times on the page, then only handle it once - event.stopImmediatePropagation(); - event.stopPropagation(); +}); + +// Listen for requests from DevTools (via background script) +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + debugLog('Received message:', message); + + if (message.action === 'get-macro') { + const macroData = window.__macros?.[message.hash]; + debugLog('get-macro request for hash:', message.hash, 'Found:', !!macroData); + debugLog('Available macros:', window.__macros ? Object.keys(window.__macros) : 'none'); - chrome.runtime.sendMessage(message); + // Send response back through background script + try { + chrome.runtime.sendMessage({ + action: 'macro-response', + hash: message.hash, + data: macroData || null + }); + } catch (err) { + debugLog('Failed to send macro-response message:', err); + } + } }); + +// Polling service to clean up stale macros +// Runs every 5 minutes to check if macro class names still exist on the page +const CLEANUP_INTERVAL = 1000 * 60 * 5; // 5 minutes + +setInterval(() => { + if (!window.__macros) { + return; + } + + const macroHashes = Object.keys(window.__macros); + if (macroHashes.length === 0) { + return; + } + + let removedCount = 0; + + for (const hash of macroHashes) { + // Check if any element with this macro class exists in the DOM + const selector = `.-macro\\$${CSS.escape(hash)}`; + const elementExists = document.querySelector(selector); + + if (!elementExists) { + debugLog('Cleaning up stale macro:', hash, window.__macros[hash].style); + delete window.__macros[hash]; + removedCount++; + } + } + + if (removedCount > 0) { + debugLog(`Cleaned up ${removedCount} stale macro(s). Remaining: ${Object.keys(window.__macros).length}`); + } +}, CLEANUP_INTERVAL); + diff --git a/packages/dev/style-macro-chrome-plugin/src/devtool.js b/packages/dev/style-macro-chrome-plugin/src/devtool.js index eeff5601b62..faa3ac0e3b5 100644 --- a/packages/dev/style-macro-chrome-plugin/src/devtool.js +++ b/packages/dev/style-macro-chrome-plugin/src/devtool.js @@ -1,55 +1,135 @@ - chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { sidebar.setObject({}); - let update = () => { - chrome.devtools.inspectedWindow.eval('$0.getAttribute("class")', async (className) => { - if (typeof className !== 'string') { - sidebar.setObject({}); - return; + + // Helper function to log to both DevTools-for-DevTools console and inspected page console + const debugLog = (...args) => { + // console.log(...args); // Logs to DevTools-for-DevTools console + // const message = args.map(arg => + // typeof arg === 'object' ? JSON.stringify(arg) : String(arg) + // ).join(' '); + // chrome.devtools.inspectedWindow.eval(`console.log('[DevTools]', ${JSON.stringify(message)})`); + }; + + const backgroundPageConnection = chrome.runtime.connect({name: 'devtools-page'}); + + // Monitor connection status + backgroundPageConnection.onDisconnect.addListener(() => { + debugLog('ERROR: Background connection disconnected!', chrome.runtime.lastError); + }); + + // Initialize connection with the background script + debugLog('Initializing connection with tabId:', chrome.devtools.inspectedWindow.tabId); + backgroundPageConnection.postMessage({ + type: 'init', + tabId: chrome.devtools.inspectedWindow.tabId + }); + debugLog('Init message sent to background'); + + // Track pending queries for macro data + const pendingQueries = new Map(); + + // Listen for responses from content script (via background script) + backgroundPageConnection.onMessage.addListener((message) => { + debugLog('Message from background:', message); + + if (message.action === 'macro-response') { + debugLog('Received macro-response for hash:', message.hash); + const resolve = pendingQueries.get(message.hash); + if (resolve) { + resolve(message.data); + pendingQueries.delete(message.hash); } + } else if (message.action === 'update-macros') { + debugLog('Received update-macros, refreshing...'); + update(); + } + }); - let macros = className.matchAll(/-macro\$([^\s]+)/g); - let matches = []; - for (let macro of macros) { - await new Promise(resolve => { - chrome.devtools.inspectedWindow.eval(`$0.ownerDocument.defaultView.__macros?.[${JSON.stringify(macro[1])}]`, (result, x) => { - if (result) { - matches.push(result); - } - resolve(); - }); + // Query macro data from content script via background script + const queryMacro = (hash) => { + debugLog('Querying macro with hash:', hash); + return new Promise((resolve) => { + pendingQueries.set(hash, resolve); + + try { + backgroundPageConnection.postMessage({ + type: 'query-macros', + hash: hash }); + debugLog('Query message sent to background for hash:', hash); + } catch (err) { + debugLog('ERROR sending message:', err); + pendingQueries.delete(hash); + resolve(null); + return; } - if (matches.length === 0) { - sidebar.setObject({}); - } else if (matches.length === 1) { - sidebar.setObject(matches[0].style ?? {}, matches[0].loc); - } else { - let seenProperties = new Set(); - for (let i = matches.length - 1; i >= 0; i--) { - for (let key in matches[i].style) { - if (seenProperties.has(key)) { - delete matches[i].style[key]; - } else { - seenProperties.add(key); - } + // Timeout after 1 second + setTimeout(() => { + if (pendingQueries.has(hash)) { + debugLog('Query timeout for hash:', hash); + pendingQueries.delete(hash); + resolve(null); + } + }, 1000); + }); + }; + + let update = () => { + debugLog('Starting update...'); + chrome.devtools.inspectedWindow.eval('$0.getAttribute("class")', (className) => { + debugLog('Got className:', className); + + // Handle the async operations outside the eval callback + (async () => { + if (typeof className !== 'string') { + sidebar.setObject({}); + return; + } + + let macros = className.matchAll(/-macro\$([^\s]+)/g); + let matches = []; + + for (let macro of macros) { + debugLog('Processing macro:', macro[1]); + const result = await queryMacro(macro[1]); + debugLog('Got result for macro:', macro[1], result ? 'found' : 'not found'); + if (result) { + matches.push(result); } } - let res = {}; - for (let match of matches) { - res[match.loc] = match.style; + debugLog('Total matches:', matches.length); + + if (matches.length === 0) { + sidebar.setObject({}); + } else if (matches.length === 1) { + sidebar.setObject(matches[0].style ?? {}, matches[0].loc); + } else { + let seenProperties = new Set(); + for (let i = matches.length - 1; i >= 0; i--) { + for (let key in matches[i].style) { + if (seenProperties.has(key)) { + delete matches[i].style[key]; + } else { + seenProperties.add(key); + } + } + } + + let res = {}; + for (let match of matches) { + res[match.loc] = match.style; + } + sidebar.setObject(res); } - sidebar.setObject(res); - } + })(); }); }; chrome.devtools.panels.elements.onSelectionChanged.addListener(() => { + debugLog('Element selection changed'); update(); }); - - chrome.runtime.onMessage.addListener(() => update()); }); diff --git a/packages/dev/style-macro-chrome-plugin/src/manifest.json b/packages/dev/style-macro-chrome-plugin/src/manifest.json index 9fce69eb06a..6d3bfaf858a 100644 --- a/packages/dev/style-macro-chrome-plugin/src/manifest.json +++ b/packages/dev/style-macro-chrome-plugin/src/manifest.json @@ -3,12 +3,16 @@ "name": "Style Macro DevTools", "version": "0.0.1", "devtools_page": "devtools.html", + "background": { + "service_worker": "background.js" + }, "content_scripts": [{ "matches": ["*://*/*"], "js": ["content-script.js"], "all_frames": true, "run_at": "document_idle" }], + "permissions": ["tabs"], "icons": { "16": "icons/16.png", "32": "icons/32.png", From 05bc7cf9df78d15fcf165ac93c6049abc619903a Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 24 Oct 2025 10:47:51 +1100 Subject: [PATCH 17/32] Add architecture diagrams and explanations --- .../dev/style-macro-chrome-plugin/README.md | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/packages/dev/style-macro-chrome-plugin/README.md b/packages/dev/style-macro-chrome-plugin/README.md index 0a43bf43aad..84d9f769ee8 100644 --- a/packages/dev/style-macro-chrome-plugin/README.md +++ b/packages/dev/style-macro-chrome-plugin/README.md @@ -40,3 +40,180 @@ If every tab you have open (or many of them) reload when you make local changes - [ ] Link to file on the side instead of grouping by filename? - [ ] Add classname that is applying style? - [ ] Work in MFE's + +## Extension Architecture + +This extension uses Chrome's standard extension architecture with three main components that communicate via message passing. + +### Components + +#### 1. **Page Context** (style-macro runtime) +- **Location**: Runs in the actual page's JavaScript context +- **Responsibility**: Generates macro metadata (hash, location, styles) when style macro is evaluated +- **Storage**: None - only sends messages +- **Communication**: + - Sends: `window.postMessage({ action: 'update-macros', hash, loc, style })` to content script + +#### 2. **Content Script** (`content-script.js`) +- **Location**: Isolated sandboxed environment injected into the page +- **Responsibility**: + - Listens for `window.postMessage({ action: 'update-macros' })` from the page and stores macro data in its own `window.__macros` + - Responds to queries from DevTools (via background script) + - Cleans up stale macros every 5 minutes +- **Storage**: `window.__macros[hash] = { loc: string, style: object }` (in content script context, not page context) +- **Communication**: + - Receives: + - `window.postMessage({ action: 'update-macros' })` from page + - `chrome.runtime.onMessage({ action: 'get-macro' })` from background + - Sends: + - `chrome.runtime.sendMessage({ action: 'update-macros' })` to background + - `chrome.runtime.sendMessage({ action: 'macro-response' })` to background + +#### 3. **Background Script** (`background.js`) +- **Location**: Service worker (isolated context) +- **Responsibility**: Acts as a message broker between DevTools and content scripts +- **State**: Maintains a map of DevTools connections per tab +- **Communication**: + - Receives: + - `chrome.runtime.onConnect({ name: 'devtools-page' })` from DevTools + - `port.onMessage({ type: 'init' })` from DevTools + - `port.onMessage({ type: 'query-macros' })` from DevTools + - `chrome.runtime.onMessage({ action: 'update-macros' })` from content script + - `chrome.runtime.onMessage({ action: 'macro-response' })` from content script + - Sends: + - `chrome.tabs.sendMessage({ action: 'get-macro' })` to content script + - `port.postMessage({ action: 'update-macros' })` to DevTools + - `port.postMessage({ action: 'macro-response' })` to DevTools + +#### 4. **DevTools Panel** (`devtool.js`) +- **Location**: DevTools sidebar panel context +- **Responsibility**: + - Extracts macro class names from selected element (`-macro$hash`) + - Queries for macro data from content script + - Displays style information in sidebar +- **Communication**: + - Receives: + - `port.onMessage({ action: 'macro-response' })` from background + - `port.onMessage({ action: 'update-macros' })` from background + - Sends: + - `chrome.runtime.connect({ name: 'devtools-page' })` to establish connection + - `port.postMessage({ type: 'init' })` to background + - `port.postMessage({ type: 'query-macros' })` to background + +### Message Flow Diagrams + +#### Flow 1: Style Macro Updates (Page → DevTools) + +``` +┌─────────────────┐ +│ Page Context │ +│ (style-macro) │ +└────────┬────────┘ + │ window.postMessage({ action: 'update-macros', hash, loc, style }) + ↓ +┌─────────────────┐ +│ Content Script │ Stores in window.__macros[hash] +└────────┬────────┘ + │ chrome.runtime.sendMessage({ action: 'update-macros', ... }) + ↓ +┌─────────────────┐ +│ Background │ Looks up DevTools connection for tabId +└────────┬────────┘ + │ port.postMessage({ action: 'update-macros', ... }) + ↓ +┌─────────────────┐ +│ DevTools Panel │ Triggers sidebar refresh +└─────────────────┘ +``` + +#### Flow 2: Query Macro Data (DevTools → Content Script → DevTools) + +``` +┌─────────────────┐ +│ DevTools Panel │ User selects element with -macro$hash class +└────────┬────────┘ + │ port.postMessage({ type: 'query-macros', hash }) + ↓ +┌─────────────────┐ +│ Background │ Forwards to content script in specified tab +└────────┬────────┘ + │ chrome.tabs.sendMessage(tabId, { action: 'get-macro', hash }) + ↓ +┌─────────────────┐ +│ Content Script │ Reads from window.__macros[hash] +└────────┬────────┘ + │ chrome.runtime.sendMessage({ action: 'macro-response', hash, data }) + ↓ +┌─────────────────┐ +│ Background │ Looks up DevTools connection +└────────┬────────┘ + │ port.postMessage({ action: 'macro-response', hash, data }) + ↓ +┌─────────────────┐ +│ DevTools Panel │ Resolves Promise, updates sidebar +└─────────────────┘ +``` + +#### Flow 3: Macro Cleanup (Automated) + +``` +┌─────────────────┐ +│ Content Script │ Every 5 minutes +└────────┬────────┘ + │ For each hash in window.__macros: + │ Check if document.querySelector(`.-macro\$${hash}`) exists + │ If not found, delete window.__macros[hash] + ↓ +┌─────────────────┐ +│ Garbage │ Stale macros removed from memory +│ Collection │ +└─────────────────┘ +``` + +### Key Technical Details + +#### Why Background Script is Needed +Chrome extensions prevent direct communication between DevTools and content scripts for security reasons. The background script acts as a trusted intermediary. + +#### Connection Management +- **DevTools → Background**: Uses persistent `chrome.runtime.connect()` with port-based messaging +- **Content Script → Background**: Uses one-time `chrome.runtime.sendMessage()` calls +- **Background tracks**: Map of `tabId → DevTools port` for routing messages + +#### Data Structure +```javascript +// In window.__macros (content script context only) +{ + "zsZ9Dc": { + loc: "packages/@react-spectrum/s2/src/Button.tsx:67", + style: { + "paddingX": "4", + // ... more CSS properties + } + } +} +``` + +Note: The page context does NOT have access to `window.__macros`. This is stored only in the content script's sandboxed environment for security. + +#### Message Types + +| Message Type | Direction | Purpose | +|-------------|-----------|---------| +| `update-macros` | Page → Content → Background → DevTools | Notify that a macro was added/updated | +| `query-macros` | DevTools → Background → Content | Request macro data by hash | +| `macro-response` | Content → Background → DevTools | Return requested macro data | +| `get-macro` | Background → Content | Internal forwarding of query-macros | +| `init` | DevTools → Background | Establish connection with tabId | + +### Debugging + +Enable debug logs by uncommenting the `console.log()` lines in each component: +- **DevTools Panel**: `devtool.js` → `debugLog()` function +- **Content Script**: `content-script.js` → `debugLog()` function +- **Background Script**: Already logging to service worker console + +View logs in: +- **Page Console**: Content Script and DevTools Panel logs (with `[Content Script]` and `[DevTools]` prefixes) +- **Service Worker Console**: Background Script logs (go to `chrome://extensions` → click "service worker") + From 22c9464ae3a2ddec9488104bd1cce34a426d7e0c Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 24 Oct 2025 11:17:07 +1100 Subject: [PATCH 18/32] Add patch back in --- ...transformer-js-npm-2.16.0-ae71b060cb.patch | 21 +++++++++++++++++++ package.json | 3 ++- .../dev/parcel-config-storybook/package.json | 2 +- packages/dev/s2-icon-builder/package.json | 2 +- .../style-macro-chrome-plugin/package.json | 2 +- 5 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 .yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch diff --git a/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch b/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch new file mode 100644 index 00000000000..b20edf91283 --- /dev/null +++ b/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch @@ -0,0 +1,21 @@ +diff --git a/lib/JSTransformer.js b/lib/JSTransformer.js +index c2a45a9665b4b88836d720669b997872082bb143..f46b0edf814e398ed2a2584efeb040c4b77d58db 100644 +--- a/lib/JSTransformer.js ++++ b/lib/JSTransformer.js +@@ -447,14 +447,8 @@ var _default = exports.default = new (_plugin().Transformer)({ + }, + loc: { + filePath: asset.filePath, +- start: { +- line: loc.start_line + Number(asset.meta.startLine ?? 1) - 1, +- column: loc.start_col +- }, +- end: { +- line: loc.end_line + Number(asset.meta.startLine ?? 1) - 1, +- column: loc.end_col +- } ++ line: loc.line, ++ column: loc.col + }, + invalidateOnFileChange(filePath) { + asset.invalidateOnFileChange(filePath); diff --git a/package.json b/package.json index 6fde5bad643..231617563a8 100644 --- a/package.json +++ b/package.json @@ -229,7 +229,8 @@ "remark-parse": "patch:remark-parse@npm%3A10.0.1#~/.yarn/patches/remark-parse-npm-10.0.1-e654d7df78.patch", "lightningcss": "1.30.1", "react-server-dom-parcel": "canary", - "react-test-renderer": "19.1.0" + "react-test-renderer": "19.1.0", + "@parcel/transformer-js@npm:2.16.0": "patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch" }, "@parcel/transformer-css": { "cssModules": { diff --git a/packages/dev/parcel-config-storybook/package.json b/packages/dev/parcel-config-storybook/package.json index f4e45a43096..598cb5abdb6 100644 --- a/packages/dev/parcel-config-storybook/package.json +++ b/packages/dev/parcel-config-storybook/package.json @@ -13,7 +13,7 @@ "@parcel/config-default": "^2.16.0", "@parcel/core": "^2.16.0", "@parcel/resolver-storybook": ">=0.0.0", - "@parcel/transformer-js": "^2.16.0", + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch", "@parcel/transformer-react-refresh-wrap": "^2.16.0", "@parcel/transformer-storybook": ">=0.0.2" }, diff --git a/packages/dev/s2-icon-builder/package.json b/packages/dev/s2-icon-builder/package.json index 83e4792c50e..a6abec4dba9 100644 --- a/packages/dev/s2-icon-builder/package.json +++ b/packages/dev/s2-icon-builder/package.json @@ -19,7 +19,7 @@ "@parcel/plugin": "^2.16.0", "@parcel/reporter-cli": "^2.16.0", "@parcel/resolver-default": "^2.16.0", - "@parcel/transformer-js": "^2.16.0", + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch", "@parcel/transformer-raw": "^2.16.0", "@parcel/transformer-react-refresh-wrap": "^2.16.0", "@react-spectrum/parcel-namer-s2": "^0.3.2", diff --git a/packages/dev/style-macro-chrome-plugin/package.json b/packages/dev/style-macro-chrome-plugin/package.json index df5cf73d3e3..36f4ad189ea 100644 --- a/packages/dev/style-macro-chrome-plugin/package.json +++ b/packages/dev/style-macro-chrome-plugin/package.json @@ -9,7 +9,7 @@ "@parcel/config-default": "^2.15.4", "@parcel/config-webextension": "^2.15.4", "@parcel/core": "^2.15.4", - "@parcel/transformer-js": "^2.15.4", + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch", "parcel": "^2.15.4" }, "rsp": { From 3cbc47f34a100f4a49d10896e3eda48611ecfc9e Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 24 Oct 2025 11:19:10 +1100 Subject: [PATCH 19/32] fix install --- yarn.lock | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 29f00cf1d0f..f7889daf81c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4374,7 +4374,7 @@ __metadata: "@parcel/config-default": "npm:^2.16.0" "@parcel/core": "npm:^2.16.0" "@parcel/resolver-storybook": "npm:>=0.0.0" - "@parcel/transformer-js": "npm:^2.16.0" + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch" "@parcel/transformer-react-refresh-wrap": "npm:^2.16.0" "@parcel/transformer-storybook": "npm:>=0.0.2" languageName: unknown @@ -5104,7 +5104,7 @@ __metadata: languageName: node linkType: hard -"@parcel/transformer-js@npm:2.16.0, @parcel/transformer-js@npm:^2.15.4, @parcel/transformer-js@npm:^2.16.0": +"@parcel/transformer-js@npm:2.16.0": version: 2.16.0 resolution: "@parcel/transformer-js@npm:2.16.0" dependencies: @@ -5125,6 +5125,27 @@ __metadata: languageName: node linkType: hard +"@parcel/transformer-js@patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch": + version: 2.16.0 + resolution: "@parcel/transformer-js@patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch::version=2.16.0&hash=648105" + dependencies: + "@parcel/diagnostic": "npm:2.16.0" + "@parcel/plugin": "npm:2.16.0" + "@parcel/rust": "npm:2.16.0" + "@parcel/source-map": "npm:^2.1.1" + "@parcel/utils": "npm:2.16.0" + "@parcel/workers": "npm:2.16.0" + "@swc/helpers": "npm:^0.5.0" + browserslist: "npm:^4.24.5" + nullthrows: "npm:^1.1.1" + regenerator-runtime: "npm:^0.14.1" + semver: "npm:^7.7.1" + peerDependencies: + "@parcel/core": ^2.16.0 + checksum: 10c0/372a80ba0d3b2ceb38c805e1eaac5dc6198de865c7adb37c58f30d8aa9dcfc95370f605c4a362f4687f337da62b7b269bfebe6d52226fc8dfb1c3337d0e9d60b + languageName: node + linkType: hard + "@parcel/transformer-json@npm:2.16.0": version: 2.16.0 resolution: "@parcel/transformer-json@npm:2.16.0" @@ -7552,7 +7573,7 @@ __metadata: "@parcel/plugin": "npm:^2.16.0" "@parcel/reporter-cli": "npm:^2.16.0" "@parcel/resolver-default": "npm:^2.16.0" - "@parcel/transformer-js": "npm:^2.16.0" + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch" "@parcel/transformer-raw": "npm:^2.16.0" "@parcel/transformer-react-refresh-wrap": "npm:^2.16.0" "@react-spectrum/parcel-namer-s2": "npm:^0.3.2" @@ -27103,7 +27124,7 @@ __metadata: "@parcel/config-default": "npm:^2.15.4" "@parcel/config-webextension": "npm:^2.15.4" "@parcel/core": "npm:^2.15.4" - "@parcel/transformer-js": "npm:^2.15.4" + "@parcel/transformer-js": "patch:@parcel/transformer-js@npm%3A2.16.0#~/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch" parcel: "npm:^2.15.4" languageName: unknown linkType: soft From ef751dac0fd62dbd64dfe43c11fbd1730d0f3e83 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 24 Oct 2025 11:19:47 +1100 Subject: [PATCH 20/32] remove console.log --- packages/@react-spectrum/s2/style/style-macro.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index d325d6495de..4aa45134f04 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -388,7 +388,6 @@ export function createTheme(theme: T): StyleFunction Date: Fri, 24 Oct 2025 11:41:18 +1100 Subject: [PATCH 21/32] fix patch and ts error --- .../@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch | 2 +- packages/@react-spectrum/s2/style/style-macro.ts | 1 + yarn.lock | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch b/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch index b20edf91283..972ba99e930 100644 --- a/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch +++ b/.yarn/patches/@parcel-transformer-js-npm-2.16.0-ae71b060cb.patch @@ -15,7 +15,7 @@ index c2a45a9665b4b88836d720669b997872082bb143..f46b0edf814e398ed2a2584efeb040c4 - column: loc.end_col - } + line: loc.line, -+ column: loc.col ++ col: loc.col }, invalidateOnFileChange(filePath) { asset.invalidateOnFileChange(filePath); diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 4aa45134f04..ac5d9c4c1e3 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -388,6 +388,7 @@ export function createTheme(theme: T): StyleFunction Date: Fri, 24 Oct 2025 11:50:16 +1100 Subject: [PATCH 22/32] fix lint --- .../s2/style/__tests__/style-macro.test.js | 40 +++++++++---------- .../dev/style-macro-chrome-plugin/README.md | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js index c7d9cd23107..d072c979e04 100644 --- a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js +++ b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js @@ -142,13 +142,13 @@ describe('style-macro', () => { color: 'green-400' }); - expect(js()).toMatchInlineSnapshot(`" gw12 pg12 -macro$1xxglvk"`); + expect(js()).toMatchInlineSnapshot('" gw12 pg12 -macro$1xxglvk"'); expect(overrides).toMatchInlineSnapshot(` { "toString": [Function], } `); - expect(js({}, overrides)).toMatchInlineSnapshot(`" g8tmWqb12 -macro$Su6dhb pg12 -macro$15fuj6j"`); + expect(js({}, overrides)).toMatchInlineSnapshot('" g8tmWqb12 -macro$Su6dhb pg12 -macro$15fuj6j"'); }); it('should support allowed overrides for properties that expand into multiple', () => { @@ -163,13 +163,13 @@ describe('style-macro', () => { translateX: 40 }); - expect(js()).toMatchInlineSnapshot(`" -_7PloMd-B12 __Ya12 -macro$1nf427l"`); + expect(js()).toMatchInlineSnapshot('" -_7PloMd-B12 __Ya12 -macro$1nf427l"'); expect(overrides).toMatchInlineSnapshot(` { "toString": [Function], } `); - expect(js({}, overrides)).toMatchInlineSnapshot(`" -_7PloMd-D12 __Ya12 -macro$ZCkud -macro$1q3as53"`); + expect(js({}, overrides)).toMatchInlineSnapshot('" -_7PloMd-D12 __Ya12 -macro$ZCkud -macro$1q3as53"'); }); it('should support allowed overrides for shorthands', () => { @@ -184,13 +184,13 @@ describe('style-macro', () => { padding: 40 }); - expect(js()).toMatchInlineSnapshot(`" Tk12 Qk12 Sk12 Rk12 -macro$1w5dwn"`); + expect(js()).toMatchInlineSnapshot('" Tk12 Qk12 Sk12 Rk12 -macro$1w5dwn"'); expect(overrides).toMatchInlineSnapshot(` { "toString": [Function], } `); - expect(js({}, overrides)).toMatchInlineSnapshot(`" Tm12 Qm12 Sm12 Rm12 -macro$FQziuc -macro$1nq030k"`); + expect(js({}, overrides)).toMatchInlineSnapshot('" Tm12 Qm12 Sm12 Rm12 -macro$FQziuc -macro$1nq030k"'); }); it("should support allowed overrides for values that aren't defined", () => { @@ -205,13 +205,13 @@ describe('style-macro', () => { minWidth: 32 }); - expect(js()).toMatchInlineSnapshot(`" gE12 -macro$nl2mms"`); + expect(js()).toMatchInlineSnapshot('" gE12 -macro$nl2mms"'); expect(overrides).toMatchInlineSnapshot(` { "toString": [Function], } `); - expect(js({}, overrides)).toMatchInlineSnapshot(`" Nk12 -macro$pDx0l gE12 -macro$v8n95n"`); + expect(js({}, overrides)).toMatchInlineSnapshot('" Nk12 -macro$pDx0l gE12 -macro$v8n95n"'); }); it('should support runtime conditions', () => { @@ -265,9 +265,9 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot(`" gH12 pt12 -macro$179ovcu"`); - expect(js({ isHovered: true })).toMatchInlineSnapshot(`" gF12 po12 -macro$1i83kjb"`); - expect(js({ isPressed: true })).toMatchInlineSnapshot(`" gE12 pm12 -macro$1npaxjo"`); + expect(js({})).toMatchInlineSnapshot('" gH12 pt12 -macro$179ovcu"'); + expect(js({isHovered: true})).toMatchInlineSnapshot('" gF12 po12 -macro$1i83kjb"'); + expect(js({isPressed: true})).toMatchInlineSnapshot('" gE12 pm12 -macro$1npaxjo"'); }); it('should support nested runtime conditions', () => { @@ -308,10 +308,10 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot(`" gH12 -macro$nl2p5j"`); - expect(js({ isHovered: true })).toMatchInlineSnapshot(`" gF12 -macro$nl2nh1"`); - expect(js({ isSelected: true })).toMatchInlineSnapshot(`" g_h12 -macro$1w0viba"`); - expect(js({ isSelected: true, isHovered: true })).toMatchInlineSnapshot(`" g312 -macro$nl27ia"`); + expect(js({})).toMatchInlineSnapshot('" gH12 -macro$nl2p5j"'); + expect(js({isHovered: true})).toMatchInlineSnapshot('" gF12 -macro$nl2nh1"'); + expect(js({isSelected: true})).toMatchInlineSnapshot('" g_h12 -macro$1w0viba"'); + expect(js({isSelected: true, isHovered: true})).toMatchInlineSnapshot('" g312 -macro$nl27ia"'); }); it('should support variant runtime conditions', () => { @@ -325,9 +325,9 @@ describe('style-macro', () => { } }); - expect(js({ variant: 'accent' })).toMatchInlineSnapshot(`" gY12 -macro$nl33fs"`); - expect(js({ variant: 'primary' })).toMatchInlineSnapshot(`" gjQquMe12 -macro$enz676"`); - expect(js({ variant: 'secondary' })).toMatchInlineSnapshot(`" gw12 -macro$nl3sna"`); + expect(js({variant: 'accent'})).toMatchInlineSnapshot('" gY12 -macro$nl33fs"'); + expect(js({variant: 'primary'})).toMatchInlineSnapshot('" gjQquMe12 -macro$enz676"'); + expect(js({variant: 'secondary'})).toMatchInlineSnapshot('" gw12 -macro$nl3sna"'); }); it('supports runtime conditions nested inside css conditions', () => { @@ -361,8 +361,8 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot(`" plb12 -macro$1w7i5ba"`); - expect(js({ isSelected: true })).toMatchInlineSnapshot(`" ple12 -macro$1w7i7u1"`); + expect(js({})).toMatchInlineSnapshot('" plb12 -macro$1w7i5ba"'); + expect(js({isSelected: true})).toMatchInlineSnapshot('" ple12 -macro$1w7i7u1"'); }); it('should expand shorthand properties to longhands', () => { diff --git a/packages/dev/style-macro-chrome-plugin/README.md b/packages/dev/style-macro-chrome-plugin/README.md index 84d9f769ee8..7ab470dcfed 100644 --- a/packages/dev/style-macro-chrome-plugin/README.md +++ b/packages/dev/style-macro-chrome-plugin/README.md @@ -25,7 +25,7 @@ Inspect an element on the page to open dev tools and go to the Style Macro panel If the panel isn't updating with styles, try closing the dev tools and reopening it. -If the extension doesn't appear to have the latest code, try closing the dev tools and reopening it. +If the extension doesn't appear to have the latest code, try closing the dev tools and reopening it. You may also want to go to the extensions page and either "refresh" or remove and re-add the extension. If every tab you have open (or many of them) reload when you make local changes to the extension, then go into the extension settings and limit it to `localhost` or something appropriate. From 3c1ce45a3921a942f399b3f7b014a9247a2e8b40 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 24 Oct 2025 11:56:02 +1100 Subject: [PATCH 23/32] fix RSC --- packages/@react-spectrum/s2/style/style-macro.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index ac5d9c4c1e3..21f8c589954 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -394,7 +394,7 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction Date: Fri, 24 Oct 2025 12:06:04 +1100 Subject: [PATCH 24/32] fix rsc more --- packages/@react-spectrum/s2/style/style-macro.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 21f8c589954..7f27d372f90 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -394,16 +394,15 @@ export function createTheme(theme: T): StyleFunction Date: Wed, 29 Oct 2025 14:19:12 +1100 Subject: [PATCH 25/32] Update static macros to store their data directly in a css class --- .../@react-spectrum/s2/style/style-macro.ts | 22 +++--- .../dev/style-macro-chrome-plugin/README.md | 79 ++++++++++++++++--- .../src/content-script.js | 55 ++++++++++--- .../style-macro-chrome-plugin/src/devtool.js | 58 +++++++++----- 4 files changed, 159 insertions(+), 55 deletions(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 7f27d372f90..3c23da41f5e 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -380,6 +380,14 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction { +chrome.runtime.onMessage.addListener((message, _sender, _sendResponse) => { debugLog('Received message:', message); if (message.action === 'get-macro') { - const macroData = window.__macros?.[message.hash]; - debugLog('get-macro request for hash:', message.hash, 'Found:', !!macroData); - debugLog('Available macros:', window.__macros ? Object.keys(window.__macros) : 'none'); + const sendMacroResponse = (data, attempt = 1) => { + debugLog(`Sending macro-response for hash: ${message.hash}, attempt: ${attempt}, has data: ${!!data}`); + try { + chrome.runtime.sendMessage({ + action: 'macro-response', + hash: message.hash, + data: data || null + }); + } catch (err) { + debugLog('Failed to send macro-response message:', err); + } + }; - // Send response back through background script - try { - chrome.runtime.sendMessage({ - action: 'macro-response', - hash: message.hash, - data: macroData || null - }); - } catch (err) { - debugLog('Failed to send macro-response message:', err); + // Check if data is immediately available + let macroData = window.__macros?.[message.hash]; + + if (macroData) { + debugLog('get-macro request for hash:', message.hash, 'Found immediately'); + sendMacroResponse(macroData, 1); + } else { + // Data not available yet, wait a bit for it to arrive via window.postMessage + debugLog('get-macro request for hash:', message.hash, 'Not found, waiting...'); + debugLog('Available macros:', window.__macros ? Object.keys(window.__macros) : 'none'); + + let attempts = 0; + const maxAttempts = 10; + const checkInterval = 50; // Check every 50ms + + const intervalId = setInterval(() => { + attempts++; + macroData = window.__macros?.[message.hash]; + + if (macroData) { + clearInterval(intervalId); + debugLog(`get-macro hash: ${message.hash} found after ${attempts} attempts (${attempts * checkInterval}ms)`); + sendMacroResponse(macroData, attempts + 1); + } else if (attempts >= maxAttempts) { + clearInterval(intervalId); + debugLog(`get-macro hash: ${message.hash} not found after ${maxAttempts} attempts, giving up`); + sendMacroResponse(null, attempts + 1); + } + }, checkInterval); } } }); diff --git a/packages/dev/style-macro-chrome-plugin/src/devtool.js b/packages/dev/style-macro-chrome-plugin/src/devtool.js index faa3ac0e3b5..d715b89a5be 100644 --- a/packages/dev/style-macro-chrome-plugin/src/devtool.js +++ b/packages/dev/style-macro-chrome-plugin/src/devtool.js @@ -34,11 +34,15 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { debugLog('Message from background:', message); if (message.action === 'macro-response') { - debugLog('Received macro-response for hash:', message.hash); + debugLog('Received macro-response for hash:', message.hash, 'Has data:', !!message.data); + debugLog('Pending queries has hash:', pendingQueries.has(message.hash), 'Total pending:', pendingQueries.size); const resolve = pendingQueries.get(message.hash); if (resolve) { + debugLog('Resolving promise for hash:', message.hash, 'with data:', message.data); resolve(message.data); pendingQueries.delete(message.hash); + } else { + debugLog('WARNING: No pending query found for hash:', message.hash); } } else if (message.action === 'update-macros') { debugLog('Received update-macros, refreshing...'); @@ -51,6 +55,7 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { debugLog('Querying macro with hash:', hash); return new Promise((resolve) => { pendingQueries.set(hash, resolve); + debugLog('Added to pendingQueries, total pending:', pendingQueries.size); try { backgroundPageConnection.postMessage({ @@ -68,14 +73,27 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { // Timeout after 1 second setTimeout(() => { if (pendingQueries.has(hash)) { - debugLog('Query timeout for hash:', hash); + debugLog('TIMEOUT: Query timeout for hash:', hash, 'Resolving to null'); pendingQueries.delete(hash); resolve(null); + } else { + debugLog('Timeout fired for hash:', hash, 'but query already resolved'); } }, 1000); }); }; + function getMacroData(className) { + let promise = new Promise((resolve) => { + debugLog('Getting macro data for:', className); + chrome.devtools.inspectedWindow.eval('window.getComputedStyle($0).getPropertyValue("--macro-data")', (style) => { + debugLog('Got style:', style); + resolve(style ? JSON.parse(style) : null); + }); + }); + return promise; + } + let update = () => { debugLog('Starting update...'); chrome.devtools.inspectedWindow.eval('$0.getAttribute("class")', (className) => { @@ -88,30 +106,28 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { return; } - let macros = className.matchAll(/-macro\$([^\s]+)/g); - let matches = []; + let staticMacroHashes = [...className.matchAll(/-macro-static-([^\s]+)/g)].map(m => m[1]); + let dynamicMacroHashes = [...className.matchAll(/-macro-dynamic-([^\s]+)/g)].map(m => m[1]); + debugLog('Static macro hashes:', staticMacroHashes); + debugLog('Dynamic macro hashes:', dynamicMacroHashes); - for (let macro of macros) { - debugLog('Processing macro:', macro[1]); - const result = await queryMacro(macro[1]); - debugLog('Got result for macro:', macro[1], result ? 'found' : 'not found'); - if (result) { - matches.push(result); - } - } + let staticMacros = staticMacroHashes.map(macro => getMacroData(macro)); + let dynamicMacros = dynamicMacroHashes.map(macro => queryMacro(macro)); - debugLog('Total matches:', matches.length); + debugLog('Waiting for', staticMacros.length, 'static and', dynamicMacros.length, 'dynamic macros...'); + let results = await Promise.all([...staticMacros, ...dynamicMacros]); + debugLog('Results:', results); - if (matches.length === 0) { + if (results.length === 0) { sidebar.setObject({}); - } else if (matches.length === 1) { - sidebar.setObject(matches[0].style ?? {}, matches[0].loc); + } else if (results.length === 1) { + sidebar.setObject(results[0].style ?? {}, results[0].loc); } else { let seenProperties = new Set(); - for (let i = matches.length - 1; i >= 0; i--) { - for (let key in matches[i].style) { + for (let i = results.length - 1; i >= 0; i--) { + for (let key in results[i].style) { if (seenProperties.has(key)) { - delete matches[i].style[key]; + delete results[i].style[key]; } else { seenProperties.add(key); } @@ -119,8 +135,8 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { } let res = {}; - for (let match of matches) { - res[match.loc] = match.style; + for (let result of results) { + res[result.loc] = result.style; } sidebar.setObject(res); } From 3ec550d657f3852df6c0f7437c52242b0173a946 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Wed, 29 Oct 2025 14:40:22 +1100 Subject: [PATCH 26/32] fix tests --- .../s2/style/__tests__/mergeStyles.test.js | 2 +- .../s2/style/__tests__/style-macro.test.js | 102 ++++++++---------- .../@react-spectrum/s2/style/style-macro.ts | 6 +- 3 files changed, 51 insertions(+), 59 deletions(-) diff --git a/packages/@react-spectrum/s2/style/__tests__/mergeStyles.test.js b/packages/@react-spectrum/s2/style/__tests__/mergeStyles.test.js index 3f2da3a4b99..ae8349a616f 100644 --- a/packages/@react-spectrum/s2/style/__tests__/mergeStyles.test.js +++ b/packages/@react-spectrum/s2/style/__tests__/mergeStyles.test.js @@ -14,7 +14,7 @@ import {mergeStyles} from '../runtime'; import {style} from '../spectrum-theme'; function stripMacro(css) { - return css.replaceAll(/-macro\$[0-9a-zA-Z]{6}[ ]?/gi, ''); + return css.replaceAll(/ -macro-static-[0-9a-zA-Z]+/gi, '').replaceAll(/ -macro-dynamic-[0-9a-zA-Z]+/gi, ''); } describe('mergeStyles', () => { diff --git a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js index d072c979e04..cf60f1bad7f 100644 --- a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js +++ b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js @@ -53,13 +53,13 @@ describe('style-macro', () => { } } +.-macro-static-EVNQL { + --macro-data: {"style":{"marginTop":{":first-child":{"default":4,"lg":8}}},"loc":"undefined:undefined:undefined"}; + } + " `); - expect(js).toMatchInlineSnapshot(` -{ - "toString": [Function], -} -`); + expect(js).toMatchInlineSnapshot(`" Jbs12 Jbpv12 -macro-static-EVNQL"`); }); it('should support self references', () => { @@ -118,14 +118,14 @@ describe('style-macro', () => { } } +.-macro-static-qHi23 { + --macro-data: {"style":{"borderWidth":2,"paddingX":"edge-to-text","width":"calc(200px - self(borderStartWidth) - self(paddingStart))"},"loc":"undefined:undefined:undefined"}; + } + " `); - expect(js).toMatchInlineSnapshot(` -{ - "toString": [Function], -} -`); + expect(js).toMatchInlineSnapshot(`" _kc12 hc12 mCPFGYc12 lc12 SMBFGYc12 Rv12 ZjUQgKd12 -m_-mc12 -S_-Sv12 -macro-static-qHi23"`); }); it('should support allowed overrides', () => { @@ -142,13 +142,9 @@ describe('style-macro', () => { color: 'green-400' }); - expect(js()).toMatchInlineSnapshot('" gw12 pg12 -macro$1xxglvk"'); - expect(overrides).toMatchInlineSnapshot(` -{ - "toString": [Function], -} -`); - expect(js({}, overrides)).toMatchInlineSnapshot('" g8tmWqb12 -macro$Su6dhb pg12 -macro$15fuj6j"'); + expect(js()).toMatchInlineSnapshot(`" gw12 pg12 -macro-dynamic-1xxglvk"`); + expect(overrides).toMatchInlineSnapshot(`" g8tmWqb12 pHJ3AUd12 -macro-static-Su6dhb"`); + expect(js({}, overrides)).toMatchInlineSnapshot(`" g8tmWqb12 pg12 -macro-dynamic-jk90zw"`); }); it('should support allowed overrides for properties that expand into multiple', () => { @@ -163,13 +159,9 @@ describe('style-macro', () => { translateX: 40 }); - expect(js()).toMatchInlineSnapshot('" -_7PloMd-B12 __Ya12 -macro$1nf427l"'); - expect(overrides).toMatchInlineSnapshot(` -{ - "toString": [Function], -} -`); - expect(js({}, overrides)).toMatchInlineSnapshot('" -_7PloMd-D12 __Ya12 -macro$ZCkud -macro$1q3as53"'); + expect(js()).toMatchInlineSnapshot(`" -_7PloMd-B12 __Ya12 -macro-dynamic-1nf427l"`); + expect(overrides).toMatchInlineSnapshot(`" -_7PloMd-D12 __Ya12 -macro-static-ZCkud"`); + expect(js({}, overrides)).toMatchInlineSnapshot(`" -_7PloMd-D12 __Ya12 -macro-dynamic-1pnuhyr"`); }); it('should support allowed overrides for shorthands', () => { @@ -184,13 +176,9 @@ describe('style-macro', () => { padding: 40 }); - expect(js()).toMatchInlineSnapshot('" Tk12 Qk12 Sk12 Rk12 -macro$1w5dwn"'); - expect(overrides).toMatchInlineSnapshot(` -{ - "toString": [Function], -} -`); - expect(js({}, overrides)).toMatchInlineSnapshot('" Tm12 Qm12 Sm12 Rm12 -macro$FQziuc -macro$1nq030k"'); + expect(js()).toMatchInlineSnapshot(`" Tk12 Qk12 Sk12 Rk12 -macro-dynamic-1w5dwn"`); + expect(overrides).toMatchInlineSnapshot(`" Tm12 Qm12 Sm12 Rm12 -macro-static-FQziuc"`); + expect(js({}, overrides)).toMatchInlineSnapshot(`" Tm12 Qm12 Sm12 Rm12 -macro-dynamic-p1i90v"`); }); it("should support allowed overrides for values that aren't defined", () => { @@ -205,13 +193,9 @@ describe('style-macro', () => { minWidth: 32 }); - expect(js()).toMatchInlineSnapshot('" gE12 -macro$nl2mms"'); - expect(overrides).toMatchInlineSnapshot(` -{ - "toString": [Function], -} -`); - expect(js({}, overrides)).toMatchInlineSnapshot('" Nk12 -macro$pDx0l gE12 -macro$v8n95n"'); + expect(js()).toMatchInlineSnapshot(`" gE12 -macro-dynamic-nl2mms"`); + expect(overrides).toMatchInlineSnapshot(`" Nk12 -macro-static-pDx0l"`); + expect(js({}, overrides)).toMatchInlineSnapshot(`" Nk12 gE12 -macro-dynamic-11y5vdc"`); }); it('should support runtime conditions', () => { @@ -265,9 +249,9 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot('" gH12 pt12 -macro$179ovcu"'); - expect(js({isHovered: true})).toMatchInlineSnapshot('" gF12 po12 -macro$1i83kjb"'); - expect(js({isPressed: true})).toMatchInlineSnapshot('" gE12 pm12 -macro$1npaxjo"'); + expect(js({})).toMatchInlineSnapshot(`" gH12 pt12 -macro-dynamic-179ovcu"`); + expect(js({ isHovered: true })).toMatchInlineSnapshot(`" gF12 po12 -macro-dynamic-1i83kjb"`); + expect(js({ isPressed: true })).toMatchInlineSnapshot(`" gE12 pm12 -macro-dynamic-1npaxjo"`); }); it('should support nested runtime conditions', () => { @@ -308,10 +292,10 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot('" gH12 -macro$nl2p5j"'); - expect(js({isHovered: true})).toMatchInlineSnapshot('" gF12 -macro$nl2nh1"'); - expect(js({isSelected: true})).toMatchInlineSnapshot('" g_h12 -macro$1w0viba"'); - expect(js({isSelected: true, isHovered: true})).toMatchInlineSnapshot('" g312 -macro$nl27ia"'); + expect(js({})).toMatchInlineSnapshot(`" gH12 -macro-dynamic-nl2p5j"`); + expect(js({ isHovered: true })).toMatchInlineSnapshot(`" gF12 -macro-dynamic-nl2nh1"`); + expect(js({ isSelected: true })).toMatchInlineSnapshot(`" g_h12 -macro-dynamic-1w0viba"`); + expect(js({ isSelected: true, isHovered: true })).toMatchInlineSnapshot(`" g312 -macro-dynamic-nl27ia"`); }); it('should support variant runtime conditions', () => { @@ -325,9 +309,9 @@ describe('style-macro', () => { } }); - expect(js({variant: 'accent'})).toMatchInlineSnapshot('" gY12 -macro$nl33fs"'); - expect(js({variant: 'primary'})).toMatchInlineSnapshot('" gjQquMe12 -macro$enz676"'); - expect(js({variant: 'secondary'})).toMatchInlineSnapshot('" gw12 -macro$nl3sna"'); + expect(js({ variant: 'accent' })).toMatchInlineSnapshot(`" gY12 -macro-dynamic-nl33fs"`); + expect(js({ variant: 'primary' })).toMatchInlineSnapshot(`" gjQquMe12 -macro-dynamic-enz676"`); + expect(js({ variant: 'secondary' })).toMatchInlineSnapshot(`" gw12 -macro-dynamic-nl3sna"`); }); it('supports runtime conditions nested inside css conditions', () => { @@ -361,8 +345,8 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot('" plb12 -macro$1w7i5ba"'); - expect(js({isSelected: true})).toMatchInlineSnapshot('" ple12 -macro$1w7i7u1"'); + expect(js({})).toMatchInlineSnapshot(`" plb12 -macro-dynamic-1w7i5ba"`); + expect(js({ isSelected: true })).toMatchInlineSnapshot(`" ple12 -macro-dynamic-1w7i7u1"`); }); it('should expand shorthand properties to longhands', () => { @@ -370,11 +354,7 @@ describe('style-macro', () => { padding: 24 }); - expect(js).toMatchInlineSnapshot(` -{ - "toString": [Function], -} -`); + expect(js).toMatchInlineSnapshot(`" Th12 Qh12 Sh12 Rh12 -macro-static-V268ld"`); expect(css).toMatchInlineSnapshot(` "@layer _.a; @@ -399,6 +379,10 @@ describe('style-macro', () => { } } +.-macro-static-V268ld { + --macro-data: {"style":{"padding":24},"loc":"undefined:undefined:undefined"}; + } + " `); }); @@ -417,6 +401,10 @@ describe('style-macro', () => { } } +.-macro-static-MvZuec { + --macro-data: {"style":{"backgroundColor":"blue-1000/50"},"loc":"undefined:undefined:undefined"}; + } + " `); }); @@ -438,6 +426,10 @@ describe('style-macro', () => { } } +.-macro-static-2pvxid { + --macro-data: {"style":{"--foo":{"type":"backgroundColor","value":"gray-300"}},"loc":"undefined:undefined:undefined"}; + } + " `); }); diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index 3c23da41f5e..fad7ebc95f9 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -382,11 +382,12 @@ export function createTheme(theme: T): StyleFunction(theme: T): StyleFunction Date: Wed, 29 Oct 2025 14:48:50 +1100 Subject: [PATCH 27/32] fix lint --- .../s2/style/__tests__/style-macro.test.js | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js index cf60f1bad7f..64c118617ae 100644 --- a/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js +++ b/packages/@react-spectrum/s2/style/__tests__/style-macro.test.js @@ -59,7 +59,7 @@ describe('style-macro', () => { " `); - expect(js).toMatchInlineSnapshot(`" Jbs12 Jbpv12 -macro-static-EVNQL"`); + expect(js).toMatchInlineSnapshot('" Jbs12 Jbpv12 -macro-static-EVNQL"'); }); it('should support self references', () => { @@ -125,7 +125,7 @@ describe('style-macro', () => { " `); - expect(js).toMatchInlineSnapshot(`" _kc12 hc12 mCPFGYc12 lc12 SMBFGYc12 Rv12 ZjUQgKd12 -m_-mc12 -S_-Sv12 -macro-static-qHi23"`); + expect(js).toMatchInlineSnapshot('" _kc12 hc12 mCPFGYc12 lc12 SMBFGYc12 Rv12 ZjUQgKd12 -m_-mc12 -S_-Sv12 -macro-static-qHi23"'); }); it('should support allowed overrides', () => { @@ -142,9 +142,9 @@ describe('style-macro', () => { color: 'green-400' }); - expect(js()).toMatchInlineSnapshot(`" gw12 pg12 -macro-dynamic-1xxglvk"`); - expect(overrides).toMatchInlineSnapshot(`" g8tmWqb12 pHJ3AUd12 -macro-static-Su6dhb"`); - expect(js({}, overrides)).toMatchInlineSnapshot(`" g8tmWqb12 pg12 -macro-dynamic-jk90zw"`); + expect(js()).toMatchInlineSnapshot('" gw12 pg12 -macro-dynamic-1xxglvk"'); + expect(overrides).toMatchInlineSnapshot('" g8tmWqb12 pHJ3AUd12 -macro-static-Su6dhb"'); + expect(js({}, overrides)).toMatchInlineSnapshot('" g8tmWqb12 pg12 -macro-dynamic-jk90zw"'); }); it('should support allowed overrides for properties that expand into multiple', () => { @@ -159,9 +159,9 @@ describe('style-macro', () => { translateX: 40 }); - expect(js()).toMatchInlineSnapshot(`" -_7PloMd-B12 __Ya12 -macro-dynamic-1nf427l"`); - expect(overrides).toMatchInlineSnapshot(`" -_7PloMd-D12 __Ya12 -macro-static-ZCkud"`); - expect(js({}, overrides)).toMatchInlineSnapshot(`" -_7PloMd-D12 __Ya12 -macro-dynamic-1pnuhyr"`); + expect(js()).toMatchInlineSnapshot('" -_7PloMd-B12 __Ya12 -macro-dynamic-1nf427l"'); + expect(overrides).toMatchInlineSnapshot('" -_7PloMd-D12 __Ya12 -macro-static-ZCkud"'); + expect(js({}, overrides)).toMatchInlineSnapshot('" -_7PloMd-D12 __Ya12 -macro-dynamic-1pnuhyr"'); }); it('should support allowed overrides for shorthands', () => { @@ -176,9 +176,9 @@ describe('style-macro', () => { padding: 40 }); - expect(js()).toMatchInlineSnapshot(`" Tk12 Qk12 Sk12 Rk12 -macro-dynamic-1w5dwn"`); - expect(overrides).toMatchInlineSnapshot(`" Tm12 Qm12 Sm12 Rm12 -macro-static-FQziuc"`); - expect(js({}, overrides)).toMatchInlineSnapshot(`" Tm12 Qm12 Sm12 Rm12 -macro-dynamic-p1i90v"`); + expect(js()).toMatchInlineSnapshot('" Tk12 Qk12 Sk12 Rk12 -macro-dynamic-1w5dwn"'); + expect(overrides).toMatchInlineSnapshot('" Tm12 Qm12 Sm12 Rm12 -macro-static-FQziuc"'); + expect(js({}, overrides)).toMatchInlineSnapshot('" Tm12 Qm12 Sm12 Rm12 -macro-dynamic-p1i90v"'); }); it("should support allowed overrides for values that aren't defined", () => { @@ -193,9 +193,9 @@ describe('style-macro', () => { minWidth: 32 }); - expect(js()).toMatchInlineSnapshot(`" gE12 -macro-dynamic-nl2mms"`); - expect(overrides).toMatchInlineSnapshot(`" Nk12 -macro-static-pDx0l"`); - expect(js({}, overrides)).toMatchInlineSnapshot(`" Nk12 gE12 -macro-dynamic-11y5vdc"`); + expect(js()).toMatchInlineSnapshot('" gE12 -macro-dynamic-nl2mms"'); + expect(overrides).toMatchInlineSnapshot('" Nk12 -macro-static-pDx0l"'); + expect(js({}, overrides)).toMatchInlineSnapshot('" Nk12 gE12 -macro-dynamic-11y5vdc"'); }); it('should support runtime conditions', () => { @@ -249,9 +249,9 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot(`" gH12 pt12 -macro-dynamic-179ovcu"`); - expect(js({ isHovered: true })).toMatchInlineSnapshot(`" gF12 po12 -macro-dynamic-1i83kjb"`); - expect(js({ isPressed: true })).toMatchInlineSnapshot(`" gE12 pm12 -macro-dynamic-1npaxjo"`); + expect(js({})).toMatchInlineSnapshot('" gH12 pt12 -macro-dynamic-179ovcu"'); + expect(js({isHovered: true})).toMatchInlineSnapshot('" gF12 po12 -macro-dynamic-1i83kjb"'); + expect(js({isPressed: true})).toMatchInlineSnapshot('" gE12 pm12 -macro-dynamic-1npaxjo"'); }); it('should support nested runtime conditions', () => { @@ -292,10 +292,10 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot(`" gH12 -macro-dynamic-nl2p5j"`); - expect(js({ isHovered: true })).toMatchInlineSnapshot(`" gF12 -macro-dynamic-nl2nh1"`); - expect(js({ isSelected: true })).toMatchInlineSnapshot(`" g_h12 -macro-dynamic-1w0viba"`); - expect(js({ isSelected: true, isHovered: true })).toMatchInlineSnapshot(`" g312 -macro-dynamic-nl27ia"`); + expect(js({})).toMatchInlineSnapshot('" gH12 -macro-dynamic-nl2p5j"'); + expect(js({isHovered: true})).toMatchInlineSnapshot('" gF12 -macro-dynamic-nl2nh1"'); + expect(js({isSelected: true})).toMatchInlineSnapshot('" g_h12 -macro-dynamic-1w0viba"'); + expect(js({isSelected: true, isHovered: true})).toMatchInlineSnapshot('" g312 -macro-dynamic-nl27ia"'); }); it('should support variant runtime conditions', () => { @@ -309,9 +309,9 @@ describe('style-macro', () => { } }); - expect(js({ variant: 'accent' })).toMatchInlineSnapshot(`" gY12 -macro-dynamic-nl33fs"`); - expect(js({ variant: 'primary' })).toMatchInlineSnapshot(`" gjQquMe12 -macro-dynamic-enz676"`); - expect(js({ variant: 'secondary' })).toMatchInlineSnapshot(`" gw12 -macro-dynamic-nl3sna"`); + expect(js({variant: 'accent'})).toMatchInlineSnapshot('" gY12 -macro-dynamic-nl33fs"'); + expect(js({variant: 'primary'})).toMatchInlineSnapshot('" gjQquMe12 -macro-dynamic-enz676"'); + expect(js({variant: 'secondary'})).toMatchInlineSnapshot('" gw12 -macro-dynamic-nl3sna"'); }); it('supports runtime conditions nested inside css conditions', () => { @@ -345,8 +345,8 @@ describe('style-macro', () => { " `); - expect(js({})).toMatchInlineSnapshot(`" plb12 -macro-dynamic-1w7i5ba"`); - expect(js({ isSelected: true })).toMatchInlineSnapshot(`" ple12 -macro-dynamic-1w7i7u1"`); + expect(js({})).toMatchInlineSnapshot('" plb12 -macro-dynamic-1w7i5ba"'); + expect(js({isSelected: true})).toMatchInlineSnapshot('" ple12 -macro-dynamic-1w7i7u1"'); }); it('should expand shorthand properties to longhands', () => { @@ -354,7 +354,7 @@ describe('style-macro', () => { padding: 24 }); - expect(js).toMatchInlineSnapshot(`" Th12 Qh12 Sh12 Rh12 -macro-static-V268ld"`); + expect(js).toMatchInlineSnapshot('" Th12 Qh12 Sh12 Rh12 -macro-static-V268ld"'); expect(css).toMatchInlineSnapshot(` "@layer _.a; From 0efc6b778e3f008852b9caa95230579c647a4139 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Wed, 29 Oct 2025 15:11:59 +1100 Subject: [PATCH 28/32] fix handling between multiple tabs --- packages/@react-spectrum/s2/src/Button.tsx | 8 ++ .../dev/style-macro-chrome-plugin/README.md | 107 ++++++++++++++++-- .../src/background.js | 2 +- .../src/content-script.js | 62 ++++++---- .../style-macro-chrome-plugin/src/devtool.js | 91 +++++++++++++++ 5 files changed, 240 insertions(+), 30 deletions(-) diff --git a/packages/@react-spectrum/s2/src/Button.tsx b/packages/@react-spectrum/s2/src/Button.tsx index acd77cb9721..ac175d07522 100644 --- a/packages/@react-spectrum/s2/src/Button.tsx +++ b/packages/@react-spectrum/s2/src/Button.tsx @@ -292,6 +292,13 @@ const gradient = style({ } }); +const buttonStyle1 = style({ + backgroundColor: 'red' +}); +const buttonStyle2 = style({ + backgroundColor: 'green' +}); + export function usePendingState(isPending: boolean) { let [isProgressVisible, setIsProgressVisible] = useState(false); useEffect(() => { @@ -348,6 +355,7 @@ export const Button = forwardRef(function Button(props: ButtonProps, ref: Focusa isStaticColor: !!staticColor }, props.styles)}> {(renderProps) => (<> + {variant === 'genai' || variant === 'premium' ? ( { + │ window.postMessage({ + │ action: 'class-changed', + │ elementId: $0.getAttribute('data-devtools-id') + │ }, '*'); + │ }); + │ + │ window.__styleMacroObserver.observe($0, { + │ attributes: true, + │ attributeFilter: ['class'] + │ }); + │ `) + ↓ +┌─────────────────┐ +│ Page DOM │ MutationObserver active on selected element +└────────┬────────┘ + │ + │ ... User interacts with page, element's className changes ... + │ + │ MutationObserver detects class attribute change + │ window.postMessage({ action: 'class-changed', elementId }, '*') + ↓ +┌─────────────────┐ +│ Content Script │ Receives window message, forwards to extension +└────────┬────────┘ + │ chrome.runtime.sendMessage({ action: 'class-changed', elementId }) + ↓ +┌─────────────────┐ +│ Background │ Looks up DevTools connection for tabId +└────────┬────────┘ + │ port.postMessage({ action: 'class-changed', elementId }) + ↓ +┌─────────────────┐ +│ DevTools Panel │ Verifies elementId matches currently selected element +│ │ Triggers full panel refresh (re-reads classes, re-queries macros) +└─────────────────┘ + +When selection changes or panel closes: + ↓ +┌─────────────────┐ +│ DevTools Panel │ Calls disconnectObserver() +└────────┬────────┘ + │ chrome.devtools.inspectedWindow.eval(` + │ if (window.__styleMacroObserver) { + │ window.__styleMacroObserver.disconnect(); + │ window.__styleMacroObserver = null; + │ } + │ `) + ↓ +┌─────────────────┐ +│ Page DOM │ Old observer disconnected, new observer created for new selection +└─────────────────┘ +``` + +**Key Benefits:** +- Panel automatically refreshes when element classes change (e.g., hover states, conditional styles) +- No manual refresh needed +- Observer is cleaned up properly to prevent memory leaks +- Each element has its own unique tracking ID to prevent cross-contamination + ### Key Technical Details #### Why Background Script is Needed @@ -262,6 +354,7 @@ Note: The page context does NOT have access to `window.__macros`. This is stored | `macro-response` | Content → Background → DevTools | Return requested macro data | | `get-macro` | Background → Content | Internal forwarding of query-macros | | `init` | DevTools → Background | Establish connection with tabId | +| `class-changed` | Page → Content → Background → DevTools | Notify that selected element's className changed | ### Debugging diff --git a/packages/dev/style-macro-chrome-plugin/src/background.js b/packages/dev/style-macro-chrome-plugin/src/background.js index f2c46403704..f91056033b0 100644 --- a/packages/dev/style-macro-chrome-plugin/src/background.js +++ b/packages/dev/style-macro-chrome-plugin/src/background.js @@ -45,7 +45,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { } // Forward messages from content script to DevTools - if (message.action === 'update-macros' || message.action === 'macro-response') { + if (message.action === 'update-macros' || message.action === 'macro-response' || message.action === 'class-changed') { console.log(`[Background] Forwarding ${message.action} from content script to DevTools, tabId: ${tabId}`); const devtoolsPort = devtoolsConnections.get(tabId); if (devtoolsPort) { diff --git a/packages/dev/style-macro-chrome-plugin/src/content-script.js b/packages/dev/style-macro-chrome-plugin/src/content-script.js index b8ac7a2036a..988ea05c9bc 100644 --- a/packages/dev/style-macro-chrome-plugin/src/content-script.js +++ b/packages/dev/style-macro-chrome-plugin/src/content-script.js @@ -18,32 +18,50 @@ window.addEventListener('message', function (event) { // Only accept messages that we know are ours. Note that this is not foolproof // and the page can easily spoof messages if it wants to. - if (message && typeof message === 'object' && message.action === 'update-macros') { - let {hash, loc, style} = message; - if (!window.__macros) { - window.__macros = {}; - } + if (message && typeof message === 'object') { + if (message.action === 'update-macros') { + let {hash, loc, style} = message; + if (!window.__macros) { + window.__macros = {}; + } - // Update the specific macro without overwriting others - window.__macros[hash] = { - loc, - style - }; + // Update the specific macro without overwriting others + window.__macros[hash] = { + loc, + style + }; - debugLog('Updated macro:', hash, 'Total macros:', Object.keys(window.__macros).length); + debugLog('Updated macro:', hash, 'Total macros:', Object.keys(window.__macros).length); - // if this script is run multiple times on the page, then only handle it once - event.stopImmediatePropagation(); - event.stopPropagation(); + // if this script is run multiple times on the page, then only handle it once + event.stopImmediatePropagation(); + event.stopPropagation(); - // Send message to background script (which forwards to DevTools) - try { - chrome.runtime.sendMessage({ - action: 'update-macros', - ...message - }); - } catch (err) { - debugLog('Failed to send update-macros message:', err); + // Send message to background script (which forwards to DevTools) + try { + chrome.runtime.sendMessage({ + action: 'update-macros', + ...message + }); + } catch (err) { + debugLog('Failed to send update-macros message:', err); + } + } else if (message.action === 'class-changed') { + // Forward class-changed messages from page context to background script + debugLog('Class changed for element:', message.elementId); + + // if this script is run multiple times on the page, then only handle it once + event.stopImmediatePropagation(); + event.stopPropagation(); + + try { + chrome.runtime.sendMessage({ + action: 'class-changed', + elementId: message.elementId + }); + } catch (err) { + debugLog('Failed to send class-changed message:', err); + } } } }); diff --git a/packages/dev/style-macro-chrome-plugin/src/devtool.js b/packages/dev/style-macro-chrome-plugin/src/devtool.js index d715b89a5be..4d1e8f7f5ac 100644 --- a/packages/dev/style-macro-chrome-plugin/src/devtool.js +++ b/packages/dev/style-macro-chrome-plugin/src/devtool.js @@ -16,6 +16,8 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { // Monitor connection status backgroundPageConnection.onDisconnect.addListener(() => { debugLog('ERROR: Background connection disconnected!', chrome.runtime.lastError); + // Clean up observer when connection is lost + disconnectObserver(); }); // Initialize connection with the background script @@ -29,6 +31,10 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { // Track pending queries for macro data const pendingQueries = new Map(); + // Track mutation observer for selected element + let currentObserver = null; + let currentElementId = null; + // Listen for responses from content script (via background script) backgroundPageConnection.onMessage.addListener((message) => { debugLog('Message from background:', message); @@ -47,6 +53,13 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { } else if (message.action === 'update-macros') { debugLog('Received update-macros, refreshing...'); update(); + } else if (message.action === 'class-changed') { + debugLog('Received class-changed notification for element:', message.elementId); + // Only update if the changed element is the one we're currently watching + if (message.elementId === currentElementId) { + debugLog('Class changed on watched element, updating panel...'); + update(); + } } }); @@ -94,6 +107,78 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { return promise; } + // Function to disconnect the current observer + const disconnectObserver = () => { + if (currentObserver) { + chrome.devtools.inspectedWindow.eval(` + if (window.__styleMacroObserver) { + window.__styleMacroObserver.disconnect(); + window.__styleMacroObserver = null; + } + `); + debugLog('Disconnected mutation observer for element:', currentElementId); + currentObserver = null; + currentElementId = null; + } + }; + + // Function to start observing the currently selected element + const startObserving = () => { + // First disconnect any existing observer + disconnectObserver(); + + // Generate a unique ID for the current element + chrome.devtools.inspectedWindow.eval(` + (function() { + const element = $0; + if (!element || !element.classList) { + return null; + } + + // Generate a unique ID if element doesn't have one + if (!element.hasAttribute('data-devtools-id')) { + element.setAttribute('data-devtools-id', 'dt-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9)); + } + + const elementId = element.getAttribute('data-devtools-id'); + + // Create mutation observer + if (window.__styleMacroObserver) { + window.__styleMacroObserver.disconnect(); + } + + window.__styleMacroObserver = new MutationObserver((mutations) => { + for (const mutation of mutations) { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + // Notify DevTools that the class has changed via window.postMessage + // (chrome.runtime is not available in page context) + window.postMessage({ + action: 'class-changed', + elementId: elementId + }, '*'); + break; + } + } + }); + + window.__styleMacroObserver.observe(element, { + attributes: true, + attributeFilter: ['class'] + }); + + return elementId; + })(); + `, (result, isException) => { + if (isException) { + debugLog('Error setting up mutation observer:', result); + } else if (result) { + currentElementId = result; + currentObserver = true; // Just track that we have an observer + debugLog('Started observing element:', currentElementId); + } + }); + }; + let update = () => { debugLog('Starting update...'); chrome.devtools.inspectedWindow.eval('$0.getAttribute("class")', (className) => { @@ -146,6 +231,12 @@ chrome.devtools.panels.elements.createSidebarPane('Style Macros', (sidebar) => { chrome.devtools.panels.elements.onSelectionChanged.addListener(() => { debugLog('Element selection changed'); + // Start observing the newly selected element + startObserving(); + // Update the panel with the new element's macros update(); }); + + // Initial observation when the panel is first opened + startObserving(); }); From e5ab27bd6ddfb5d51216f218c38e916e10ca454f Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Wed, 29 Oct 2025 15:15:44 +1100 Subject: [PATCH 29/32] fix polling cleanup to work with new classnames --- packages/dev/style-macro-chrome-plugin/src/content-script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/style-macro-chrome-plugin/src/content-script.js b/packages/dev/style-macro-chrome-plugin/src/content-script.js index 988ea05c9bc..e3b4626e2e6 100644 --- a/packages/dev/style-macro-chrome-plugin/src/content-script.js +++ b/packages/dev/style-macro-chrome-plugin/src/content-script.js @@ -119,7 +119,7 @@ chrome.runtime.onMessage.addListener((message, _sender, _sendResponse) => { // Polling service to clean up stale macros // Runs every 5 minutes to check if macro class names still exist on the page -const CLEANUP_INTERVAL = 1000 * 60 * 5; // 5 minutes +const CLEANUP_INTERVAL = 1000 * 60 * 5; setInterval(() => { if (!window.__macros) { @@ -135,7 +135,7 @@ setInterval(() => { for (const hash of macroHashes) { // Check if any element with this macro class exists in the DOM - const selector = `.-macro\\$${CSS.escape(hash)}`; + const selector = `.-macro-dynamic-${CSS.escape(hash)}`; const elementExists = document.querySelector(selector); if (!elementExists) { From ab75a0e6163e51f581b0b5bbed3f2d56f7b56706 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Wed, 29 Oct 2025 15:26:28 +1100 Subject: [PATCH 30/32] revert button change --- packages/@react-spectrum/s2/src/Button.tsx | 8 -------- packages/dev/style-macro-chrome-plugin/README.md | 2 ++ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/@react-spectrum/s2/src/Button.tsx b/packages/@react-spectrum/s2/src/Button.tsx index ac175d07522..acd77cb9721 100644 --- a/packages/@react-spectrum/s2/src/Button.tsx +++ b/packages/@react-spectrum/s2/src/Button.tsx @@ -292,13 +292,6 @@ const gradient = style({ } }); -const buttonStyle1 = style({ - backgroundColor: 'red' -}); -const buttonStyle2 = style({ - backgroundColor: 'green' -}); - export function usePendingState(isPending: boolean) { let [isProgressVisible, setIsProgressVisible] = useState(false); useEffect(() => { @@ -355,7 +348,6 @@ export const Button = forwardRef(function Button(props: ButtonProps, ref: Focusa isStaticColor: !!staticColor }, props.styles)}> {(renderProps) => (<> - {variant === 'genai' || variant === 'premium' ? ( Date: Wed, 29 Oct 2025 15:30:25 +1100 Subject: [PATCH 31/32] remove static macros extension information in production --- packages/@react-spectrum/s2/style/style-macro.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-spectrum/s2/style/style-macro.ts b/packages/@react-spectrum/s2/style/style-macro.ts index fad7ebc95f9..2e495a68468 100644 --- a/packages/@react-spectrum/s2/style/style-macro.ts +++ b/packages/@react-spectrum/s2/style/style-macro.ts @@ -382,7 +382,7 @@ export function createTheme(theme: T): StyleFunction Date: Wed, 29 Oct 2025 15:40:10 +1100 Subject: [PATCH 32/32] add info to the architecture --- packages/dev/style-macro-chrome-plugin/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/dev/style-macro-chrome-plugin/README.md b/packages/dev/style-macro-chrome-plugin/README.md index 8521d156794..5add7ba038c 100644 --- a/packages/dev/style-macro-chrome-plugin/README.md +++ b/packages/dev/style-macro-chrome-plugin/README.md @@ -149,6 +149,8 @@ Static macros are generated when style macro conditions don't change at runtime. #### Flow 1b: Dynamic Macro Updates (Page → DevTools) Dynamic macros are generated when style macro conditions can change at runtime. Updates are sent via message passing. +This could be simplified and we could rely on the MutationObserver to trigger the refresh, but this way ensures +that the storage is update before we try to access the data. ``` ┌─────────────────┐