Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create bugfix plugin for classes in computed keys in Firefox (#16390)
- Loading branch information
1 parent
680d769
commit 48a3e19
Showing
66 changed files
with
583 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/.npmignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
src | ||
test | ||
*.log |
19 changes: 19 additions & 0 deletions
19
packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# @babel/plugin-bugfix-firefox-class-in-computed-class-key | ||
|
||
> Wraps classes defined in computed keys of other classes affected by https://bugzilla.mozilla.org/show_bug.cgi?id=1887677 | ||
See our website [@babel/plugin-bugfix-firefox-class-in-computed-class-key](https://babeljs.io/docs/babel-plugin-bugfix-firefox-class-in-computed-class-key) for more information. | ||
|
||
## Install | ||
|
||
Using npm: | ||
|
||
```sh | ||
npm install --save-dev @babel/plugin-bugfix-firefox-class-in-computed-class-key | ||
``` | ||
|
||
or using yarn: | ||
|
||
```sh | ||
yarn add @babel/plugin-bugfix-firefox-class-in-computed-class-key --dev | ||
``` |
57 changes: 57 additions & 0 deletions
57
packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{ | ||
"name": "@babel/plugin-bugfix-firefox-class-in-computed-class-key", | ||
"version": "7.24.1", | ||
"description": "Wraps classes defined in computed keys of other classes affected by https://bugzilla.mozilla.org/show_bug.cgi?id=1887677", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/babel/babel.git", | ||
"directory": "packages/babel-plugin-bugfix-firefox-class-in-computed-class-key" | ||
}, | ||
"homepage": "https://babel.dev/docs/en/next/babel-plugin-bugfix-firefox-class-in-computed-class-key", | ||
"license": "MIT", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"main": "./lib/index.js", | ||
"exports": { | ||
".": "./lib/index.js", | ||
"./package.json": "./package.json" | ||
}, | ||
"keywords": [ | ||
"babel-plugin", | ||
"bugfix" | ||
], | ||
"dependencies": { | ||
"@babel/helper-environment-visitor": "workspace:^", | ||
"@babel/helper-plugin-utils": "workspace:^" | ||
}, | ||
"peerDependencies": { | ||
"@babel/core": "^7.0.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "workspace:^", | ||
"@babel/helper-plugin-test-runner": "workspace:^", | ||
"@babel/traverse": "workspace:^" | ||
}, | ||
"engines": { | ||
"node": ">=6.9.0" | ||
}, | ||
"author": "The Babel Team (https://babel.dev/team)", | ||
"conditions": { | ||
"USE_ESM": [ | ||
{ | ||
"type": "module" | ||
}, | ||
null | ||
], | ||
"BABEL_8_BREAKING": [ | ||
{ | ||
"engines": { | ||
"node": "^16.20.0 || ^18.16.0 || >=20.0.0" | ||
} | ||
}, | ||
{} | ||
] | ||
}, | ||
"type": "commonjs" | ||
} |
113 changes: 113 additions & 0 deletions
113
packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/src/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import type { NodePath, Visitor } from "@babel/traverse"; | ||
import type { types as t } from "@babel/core"; | ||
import { declare } from "@babel/helper-plugin-utils"; | ||
import environmentVisitor from "@babel/helper-environment-visitor"; | ||
|
||
export default declare(({ types: t, traverse, assertVersion }) => { | ||
assertVersion(REQUIRED_VERSION(7)); | ||
|
||
const containsClassExpressionVisitor: Visitor<{ found: boolean }> = { | ||
ClassExpression(path, state) { | ||
state.found = true; | ||
path.stop(); | ||
}, | ||
Function(path) { | ||
path.skip(); | ||
}, | ||
}; | ||
|
||
const containsYieldOrAwaitVisitor = traverse.visitors.merge([ | ||
{ | ||
YieldExpression(path, state) { | ||
state.yield = true; | ||
if (state.await) path.stop(); | ||
}, | ||
AwaitExpression(path, state) { | ||
state.await = true; | ||
if (state.yield) path.stop(); | ||
}, | ||
} satisfies Visitor<{ yield: boolean; await: boolean }>, | ||
environmentVisitor, | ||
]); | ||
|
||
function containsClassExpression(path: NodePath<t.Node>) { | ||
if (t.isClassExpression(path.node)) return true; | ||
if (t.isFunction(path.node)) return false; | ||
const state = { found: false }; | ||
path.traverse(containsClassExpressionVisitor, state); | ||
return state.found; | ||
} | ||
|
||
function wrap(path: NodePath<t.Expression>) { | ||
const context = { | ||
yield: t.isYieldExpression(path.node), | ||
await: t.isAwaitExpression(path.node), | ||
}; | ||
path.traverse(containsYieldOrAwaitVisitor, context); | ||
|
||
let replacement; | ||
|
||
if (context.yield) { | ||
const fn = t.functionExpression( | ||
null, | ||
[], | ||
t.blockStatement([t.returnStatement(path.node)]), | ||
/* generator */ true, | ||
/* async */ context.await, | ||
); | ||
|
||
replacement = t.yieldExpression( | ||
t.callExpression(t.memberExpression(fn, t.identifier("call")), [ | ||
t.thisExpression(), | ||
// NOTE: In some context arguments is invalid (it might not be defined | ||
// in the top-level scope, or it's a syntax error in static class blocks). | ||
// However, `yield` is also invalid in those contexts, so we can safely | ||
// inject a reference to arguments. | ||
t.identifier("arguments"), | ||
]), | ||
true, | ||
); | ||
} else { | ||
const fn = t.arrowFunctionExpression([], path.node, context.await); | ||
|
||
if (context.await) { | ||
replacement = t.awaitExpression(t.callExpression(fn, [])); | ||
} else { | ||
replacement = t.callExpression( | ||
// We need to use fn.call() instead of just fn() because | ||
// terser transforms (() => class {})() to class {}, effectively | ||
// undoing the wrapping introduced by this plugin. | ||
// https://github.com/terser/terser/issues/1514 | ||
// TODO(Babel 8): Remove .call if Terser stops inlining this case. | ||
t.memberExpression(fn, t.identifier("call")), | ||
[], | ||
); | ||
} | ||
} | ||
|
||
path.replaceWith(replacement); | ||
} | ||
|
||
return { | ||
name: "bugfix-firefox-class-in-computed-class-key", | ||
|
||
visitor: { | ||
Class(path) { | ||
const hasPrivateElement = path.node.body.body.some(node => | ||
t.isPrivate(node), | ||
); | ||
if (!hasPrivateElement) return; | ||
|
||
for (const elem of path.get("body.body")) { | ||
if ( | ||
"computed" in elem.node && | ||
elem.node.computed && | ||
containsClassExpression(elem.get("key")) | ||
) { | ||
wrap(elem.get("key")); | ||
} | ||
} | ||
}, | ||
}, | ||
}; | ||
}); |
4 changes: 4 additions & 0 deletions
4
...fix-firefox-class-in-computed-class-key/test/fixtures/basic/nested-in-expression/input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class A { | ||
#x = 1; | ||
[useIt([1 + class {}])]; | ||
} |
4 changes: 4 additions & 0 deletions
4
...ix-firefox-class-in-computed-class-key/test/fixtures/basic/nested-in-expression/output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class A { | ||
#x = 1; | ||
[(() => useIt([1 + class {}])).call()]; | ||
} |
3 changes: 3 additions & 0 deletions
3
.../babel-plugin-bugfix-firefox-class-in-computed-class-key/test/fixtures/basic/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"plugins": ["bugfix-firefox-class-in-computed-class-key"] | ||
} |
4 changes: 4 additions & 0 deletions
4
...fox-class-in-computed-class-key/test/fixtures/basic/simple-class-in-computed-key/input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class A { | ||
#x = 1; | ||
[class {}]; | ||
} |
4 changes: 4 additions & 0 deletions
4
...ox-class-in-computed-class-key/test/fixtures/basic/simple-class-in-computed-key/output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class A { | ||
#x = 1; | ||
[(() => class {}).call()]; | ||
} |
16 changes: 16 additions & 0 deletions
16
...ugin-bugfix-firefox-class-in-computed-class-key/test/fixtures/basic/yield-await/input.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
class A { | ||
#x; | ||
[class {}] | ||
[await class {}] | ||
} | ||
|
||
async function* f() { | ||
class A { | ||
#x; | ||
[class {}] | ||
[await class {}] | ||
[yield class {}] | ||
[yield* class {}] | ||
[await (yield class {})] | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
...gin-bugfix-firefox-class-in-computed-class-key/test/fixtures/basic/yield-await/output.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class A { | ||
#x; | ||
[(() => class {}).call()]; | ||
[await (async () => await class {})()]; | ||
} | ||
async function* f() { | ||
class A { | ||
#x; | ||
[(() => class {}).call()]; | ||
[await (async () => await class {})()]; | ||
[yield* function* () { | ||
return yield class {}; | ||
}.call(this, arguments)]; | ||
[yield* function* () { | ||
return yield* class {}; | ||
}.call(this, arguments)]; | ||
[yield* async function* () { | ||
return await (yield class {}); | ||
}.call(this, arguments)]; | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
...in-computed-class-key/test/fixtures/decorators-transform/decorators-plugin-after/input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
@deco | ||
class A { | ||
#x = 1; | ||
static #y = 2; | ||
} |
6 changes: 6 additions & 0 deletions
6
...omputed-class-key/test/fixtures/decorators-transform/decorators-plugin-after/options.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"plugins": [ | ||
"bugfix-firefox-class-in-computed-class-key", | ||
["proposal-decorators", { "version": "2023-11" }] | ||
] | ||
} |
Oops, something went wrong.