Skip to content

Commit 830585c

Browse files
Dunqingtaearls
authored andcommitted
fix(transformer/react): spread props optimization breaks __self and __source injection (oxc-project#13009) (oxc-project#13020)
* Fixes oxc-project#13009 The optimization that converts `{...props}` to `props` when it's the only attribute was incorrectly applied even when `jsx_self` or `jsx_source` plugins are enabled. This caused `__self` and `__source` props to not be merged properly, resulting in incorrect transformation output in development mode. This fix disables the optimization when these dev plugins are active, ensuring spread props are preserved for proper merging.
1 parent 31da59c commit 830585c

File tree

6 files changed

+57
-16
lines changed

6 files changed

+57
-16
lines changed

crates/oxc_transformer/src/jsx/jsx_impl.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,12 @@ impl<'a> JsxImpl<'a, '_> {
624624
// optimize `{...prop}` to `prop` in static mode
625625
JSXAttributeItem::SpreadAttribute(spread) => {
626626
let JSXSpreadAttribute { argument, span } = spread.unbox();
627-
if is_classic && attributes_len == 1 {
627+
if is_classic
628+
&& attributes_len == 1
629+
// Don't optimize when dev plugins are enabled - spread must be preserved
630+
// to merge with injected `__self` and `__source` props
631+
&& !(self.options.jsx_self_plugin || self.options.jsx_source_plugin)
632+
{
628633
// deopt if spreading an object with `__proto__` key
629634
if !matches!(&argument, Expression::ObjectExpression(o) if has_proto(o))
630635
{

tasks/coverage/snapshots/semantic_typescript.snap

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16082,8 +16082,8 @@ rebuilt : ["Function", "Number", "dec"]
1608216082

1608316083
semantic Error: tasks/coverage/typescript/tests/cases/compiler/importHelpersInTsx.tsx
1608416084
Bindings mismatch:
16085-
after transform: ScopeId(0): ["React", "_jsxFileName", "o", "x"]
16086-
rebuilt : ScopeId(0): ["_jsxFileName", "x"]
16085+
after transform: ScopeId(0): ["React", "_jsxFileName", "_objectSpread", "o", "x"]
16086+
rebuilt : ScopeId(0): ["_jsxFileName", "_objectSpread", "x"]
1608716087
Reference symbol mismatch for "React":
1608816088
after transform: SymbolId(0) "React"
1608916089
rebuilt : <None>
@@ -19219,8 +19219,8 @@ rebuilt : ScopeId(0): []
1921919219

1922019220
semantic Error: tasks/coverage/typescript/tests/cases/compiler/jsxSpreadFirstUnionNoErrors.tsx
1922119221
Bindings mismatch:
19222-
after transform: ScopeId(0): ["Info", "React", "_jsxFileName", "a", "b", "c", "infoProps"]
19223-
rebuilt : ScopeId(0): ["Info", "React", "_jsxFileName", "a", "b", "c"]
19222+
after transform: ScopeId(0): ["Info", "React", "_jsxFileName", "_objectSpread", "a", "b", "c", "infoProps"]
19223+
rebuilt : ScopeId(0): ["Info", "React", "_jsxFileName", "_objectSpread", "a", "b", "c"]
1922419224
Scope children mismatch:
1922519225
after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
1922619226
rebuilt : ScopeId(0): [ScopeId(1)]
@@ -25874,8 +25874,8 @@ rebuilt : ["print"]
2587425874

2587525875
semantic Error: tasks/coverage/typescript/tests/cases/compiler/reactHOCSpreadprops.tsx
2587625876
Symbol reference IDs mismatch for "React":
25877-
after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(4), ReferenceId(9)]
25878-
rebuilt : SymbolId(1): [ReferenceId(1), ReferenceId(2)]
25877+
after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(4), ReferenceId(11)]
25878+
rebuilt : SymbolId(2): [ReferenceId(1), ReferenceId(2)]
2587925879

2588025880
semantic Error: tasks/coverage/typescript/tests/cases/compiler/reactNamespaceImportPresevation.tsx
2588125881
Bindings mismatch:
@@ -28859,10 +28859,10 @@ rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
2885928859
semantic Error: tasks/coverage/typescript/tests/cases/compiler/spreadIntersectionJsx.tsx
2886028860
Symbol reference IDs mismatch for "A":
2886128861
after transform: SymbolId(1): [ReferenceId(0)]
28862-
rebuilt : SymbolId(3): []
28862+
rebuilt : SymbolId(4): []
2886328863
Symbol reference IDs mismatch for "C":
2886428864
after transform: SymbolId(2): [ReferenceId(1)]
28865-
rebuilt : SymbolId(4): []
28865+
rebuilt : SymbolId(5): []
2886628866

2886728867
semantic Error: tasks/coverage/typescript/tests/cases/compiler/spreadObjectNoCircular1.ts
2886828868
Bindings mismatch:
@@ -30329,13 +30329,13 @@ rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), Sc
3032930329

3033030330
semantic Error: tasks/coverage/typescript/tests/cases/compiler/tsxReactPropsInferenceSucceedsOnIntersections.tsx
3033130331
Bindings mismatch:
30332-
after transform: ScopeId(0): ["Button", "CustomButton", "React", "_jsxFileName"]
30333-
rebuilt : ScopeId(0): ["CustomButton", "React", "_jsxFileName"]
30332+
after transform: ScopeId(0): ["Button", "CustomButton", "React", "_jsxFileName", "_objectSpread"]
30333+
rebuilt : ScopeId(0): ["CustomButton", "React", "_jsxFileName", "_objectSpread"]
3033430334
Scope children mismatch:
3033530335
after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4)]
3033630336
rebuilt : ScopeId(0): [ScopeId(1)]
3033730337
Symbol reference IDs mismatch for "React":
30338-
after transform: SymbolId(0): [ReferenceId(0), ReferenceId(3), ReferenceId(7), ReferenceId(12)]
30338+
after transform: SymbolId(0): [ReferenceId(0), ReferenceId(3), ReferenceId(7), ReferenceId(14)]
3033930339
rebuilt : SymbolId(0): [ReferenceId(0)]
3034030340
Reference symbol mismatch for "Button":
3034130341
after transform: SymbolId(3) "Button"
@@ -46555,8 +46555,8 @@ rebuilt : ["React", "__proto__"]
4655546555

4655646556
semantic Error: tasks/coverage/typescript/tests/cases/conformance/jsx/tsxExternalModuleEmit2.tsx
4655746557
Bindings mismatch:
46558-
after transform: ScopeId(0): ["Foo", "Main", "React", "_jsxFileName"]
46559-
rebuilt : ScopeId(0): ["Main", "_jsxFileName"]
46558+
after transform: ScopeId(0): ["Foo", "Main", "React", "_jsxFileName", "_objectSpread"]
46559+
rebuilt : ScopeId(0): ["Main", "_jsxFileName", "_objectSpread"]
4656046560
Reference symbol mismatch for "React":
4656146561
after transform: SymbolId(2) "React"
4656246562
rebuilt : <None>

tasks/transform_conformance/snapshots/oxc.snap.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
commit: 98d18aa4
22

3-
Passed: 182/302
3+
Passed: 183/303
44

55
# All Passed:
66
* babel-plugin-transform-class-static-block
@@ -521,7 +521,7 @@ after transform: [ReferenceId(0), ReferenceId(1), ReferenceId(4), ReferenceId(9)
521521
rebuilt : [ReferenceId(5)]
522522

523523

524-
# babel-plugin-transform-react-jsx (44/47)
524+
# babel-plugin-transform-react-jsx (45/48)
525525
* refresh/import-after-component/input.js
526526
Missing ScopeId
527527
Missing ReferenceId: "useFoo"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function Foo(props) {
2+
return (
3+
<div {...props}>
4+
<p>a</p>
5+
</div>
6+
);
7+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"plugins": [
3+
[
4+
"transform-react-jsx-development",
5+
{
6+
"runtime": "classic"
7+
}
8+
]
9+
]
10+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
var _jsxFileName = "<CWD>/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/input.jsx";
2+
export function Foo(props) {
3+
return /* @__PURE__ */ React.createElement("div", {
4+
...props,
5+
__self: this,
6+
__source: {
7+
fileName: _jsxFileName,
8+
lineNumber: 3,
9+
columnNumber: 5
10+
}
11+
}, /* @__PURE__ */ React.createElement("p", {
12+
__self: this,
13+
__source: {
14+
fileName: _jsxFileName,
15+
lineNumber: 4,
16+
columnNumber: 7
17+
}
18+
}, "a"));
19+
}

0 commit comments

Comments
 (0)