Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/emotion/benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
"react-dom": "^19.3.0"
},
"devDependencies": {
"@babel/core": "^7.29.7",
"@babel/core": "^8.0.5",
"@emotion/babel-plugin": "^11.13.5",
"@oxc-node/cli": "catalog:",
"@rolldown/benchmark-utils": "workspace:*",
"@rolldown/plugin-babel": "file:../../babel",
"@rolldown/plugin-babel": "workspace:*",
"@rolldown/plugin-emotion": "workspace:*",
"@rollup/plugin-swc": "catalog:",
"@swc/core": "catalog:",
Expand Down
2 changes: 1 addition & 1 deletion packages/jsx-remove-attributes/benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@babel/core": "^8.0.5",
"@oxc-node/cli": "catalog:",
"@rolldown/benchmark-utils": "workspace:*",
"@rolldown/plugin-babel": "file:../../babel",
"@rolldown/plugin-babel": "workspace:*",
"@rolldown/plugin-jsx-remove-attributes": "workspace:*",
"@rollup/plugin-swc": "catalog:",
"@swc/core": "catalog:",
Expand Down
4 changes: 2 additions & 2 deletions packages/styled-jsx/benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
"styled-jsx": "^5.1.7"
},
"devDependencies": {
"@babel/core": "^7.29.7",
"@babel/core": "^8.0.5",
"@oxc-node/cli": "catalog:",
"@rolldown/benchmark-utils": "workspace:*",
"@rolldown/plugin-babel": "file:../../babel",
"@rolldown/plugin-babel": "workspace:*",
"@rolldown/plugin-styled-jsx": "workspace:*",
"@rollup/plugin-swc": "catalog:",
"@swc/core": "catalog:",
Expand Down
2 changes: 1 addition & 1 deletion packages/transform-imports/benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"devDependencies": {
"@oxc-node/cli": "catalog:",
"@rolldown/benchmark-utils": "workspace:*",
"@rolldown/plugin-babel": "file:../../babel",
"@rolldown/plugin-babel": "workspace:*",
"@rolldown/plugin-transform-imports": "workspace:*",
"@rollup/plugin-swc": "catalog:",
"@swc/core": "catalog:",
Expand Down
132 changes: 132 additions & 0 deletions patches/@emotion__babel-plugin@11.13.5.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
diff --git a/dist/emotion-babel-plugin.cjs.js b/dist/emotion-babel-plugin.cjs.js
index c97c6b411c19b21314ee80042df8c6afbce46653..502d95a9c3f52195a1edd5a45753580d77c2cd73 100644
--- a/dist/emotion-babel-plugin.cjs.js
+++ b/dist/emotion-babel-plugin.cjs.js
@@ -1058,6 +1058,50 @@ isWeb: boolean
});
};

+// Babel 8 removed `NodePath#hoist` (emotion-js/emotion#3386). The general
+// hoister lifted an expression to the highest scope where its bindings stayed
+// valid; for serialized styles the only case that ever arises is "fully static,
+// so it can go to module scope". This reimplements just that case.
+const referencesOnlyProgramScopeBindings = path => {
+ let safe = true
+ const check = idPath => {
+ if (!idPath.isReferencedIdentifier()) return
+ const binding = idPath.scope.getBinding(idPath.node.name)
+ if (!binding) return
+ if (!binding.scope.path.isProgram()) safe = false
+ }
+ if (path.isIdentifier()) check(path)
+ if (path.isThisExpression()) safe = false
+ path.traverse({
+ Identifier: check,
+ JSXIdentifier: check,
+ ThisExpression() {
+ safe = false
+ }
+ })
+ return safe
+}
+
+const hoistToProgramScope = (path, t) => {
+ // Already at module scope — there is nowhere higher to lift it to, and
+ // `NodePath#hoist` was a no-op in that case.
+ if (!path.scope.getFunctionParent()) return
+ const programScope = path.scope.getProgramParent()
+ const id = programScope.generateUidIdentifier('ref')
+ const init = path.node
+ path.replaceWith(t.cloneNode(id))
+ // Insert immediately before the top-level statement that references it, which
+ // is what `NodePath#hoist` did — putting it at the very top of Program would
+ // land it above the imports.
+ const topLevelStatement = path.findParent(
+ parent => parent.parentPath && parent.parentPath.isProgram()
+ )
+ const [declaration] = topLevelStatement.insertBefore(
+ t.variableDeclaration('var', [t.variableDeclarator(t.cloneNode(id), init)])
+ )
+ programScope.registerDeclaration(declaration)
+}
+
var transformCssCallExpression = function transformCssCallExpression(_ref
/*: {
state: *,
@@ -1083,7 +1127,9 @@ annotateAsPure?: boolean

if (node) {
path.replaceWith(node);
- path.hoist();
+ if (referencesOnlyProgramScopeBindings(path)) {
+ hoistToProgramScope(path, babel.types)
+ }
} else if (annotateAsPure && path.isCallExpression()) {
path.addComment('leading', '#__PURE__');
}
diff --git a/dist/emotion-babel-plugin.esm.js b/dist/emotion-babel-plugin.esm.js
index fbe8ce1b2fc4ade3b8cddbc778694db4e7923a8c..0511eca0e39224aac9d271a767cc85a17d46508b 100644
--- a/dist/emotion-babel-plugin.esm.js
+++ b/dist/emotion-babel-plugin.esm.js
@@ -1045,6 +1045,50 @@ isWeb: boolean
});
};

+// Babel 8 removed `NodePath#hoist` (emotion-js/emotion#3386). The general
+// hoister lifted an expression to the highest scope where its bindings stayed
+// valid; for serialized styles the only case that ever arises is "fully static,
+// so it can go to module scope". This reimplements just that case.
+const referencesOnlyProgramScopeBindings = path => {
+ let safe = true
+ const check = idPath => {
+ if (!idPath.isReferencedIdentifier()) return
+ const binding = idPath.scope.getBinding(idPath.node.name)
+ if (!binding) return
+ if (!binding.scope.path.isProgram()) safe = false
+ }
+ if (path.isIdentifier()) check(path)
+ if (path.isThisExpression()) safe = false
+ path.traverse({
+ Identifier: check,
+ JSXIdentifier: check,
+ ThisExpression() {
+ safe = false
+ }
+ })
+ return safe
+}
+
+const hoistToProgramScope = (path, t) => {
+ // Already at module scope — there is nowhere higher to lift it to, and
+ // `NodePath#hoist` was a no-op in that case.
+ if (!path.scope.getFunctionParent()) return
+ const programScope = path.scope.getProgramParent()
+ const id = programScope.generateUidIdentifier('ref')
+ const init = path.node
+ path.replaceWith(t.cloneNode(id))
+ // Insert immediately before the top-level statement that references it, which
+ // is what `NodePath#hoist` did — putting it at the very top of Program would
+ // land it above the imports.
+ const topLevelStatement = path.findParent(
+ parent => parent.parentPath && parent.parentPath.isProgram()
+ )
+ const [declaration] = topLevelStatement.insertBefore(
+ t.variableDeclaration('var', [t.variableDeclarator(t.cloneNode(id), init)])
+ )
+ programScope.registerDeclaration(declaration)
+}
+
var transformCssCallExpression = function transformCssCallExpression(_ref
/*: {
state: *,
@@ -1070,7 +1114,9 @@ annotateAsPure?: boolean

if (node) {
path.replaceWith(node);
- path.hoist();
+ if (referencesOnlyProgramScopeBindings(path)) {
+ hoistToProgramScope(path, babel.types)
+ }
} else if (annotateAsPure && path.isCallExpression()) {
path.addComment('leading', '#__PURE__');
}
13 changes: 13 additions & 0 deletions patches/styled-jsx@5.1.7.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/dist/babel/index.js b/dist/babel/index.js
index ece0fd62fa168f667d1498c8a54fdfed6d2ac093..d71f530021ae596357125b18aab057ab45f3409f 100644
--- a/dist/babel/index.js
+++ b/dist/babel/index.js
@@ -117,7 +117,7 @@ Object.defineProperty(lib$3, "__esModule", {
var default_1 = lib$3.default = void 0;
var _helperPluginUtils = lib$2;
var _default$5 = (0, _helperPluginUtils.declare)(function(api) {
- api.assertVersion(7);
+ api.assertVersion("^7.0.0-0 || ^8.0.0-0");
return {
name: "syntax-jsx",
manipulateOptions: function manipulateOptions(opts, parserOpts) {
Loading
Loading