diff --git a/crates/oxc_transformer/src/jsx/jsx_impl.rs b/crates/oxc_transformer/src/jsx/jsx_impl.rs index 0f93ba652e2db..96493727c5dbc 100644 --- a/crates/oxc_transformer/src/jsx/jsx_impl.rs +++ b/crates/oxc_transformer/src/jsx/jsx_impl.rs @@ -624,7 +624,12 @@ impl<'a> JsxImpl<'a, '_> { // optimize `{...prop}` to `prop` in static mode JSXAttributeItem::SpreadAttribute(spread) => { let JSXSpreadAttribute { argument, span } = spread.unbox(); - if is_classic && attributes_len == 1 { + if is_classic + && attributes_len == 1 + // Don't optimize when dev plugins are enabled - spread must be preserved + // to merge with injected `__self` and `__source` props + && !(self.options.jsx_self_plugin || self.options.jsx_source_plugin) + { // deopt if spreading an object with `__proto__` key if !matches!(&argument, Expression::ObjectExpression(o) if has_proto(o)) { diff --git a/tasks/coverage/snapshots/semantic_typescript.snap b/tasks/coverage/snapshots/semantic_typescript.snap index f46456867f39d..5e006eb8fc451 100644 --- a/tasks/coverage/snapshots/semantic_typescript.snap +++ b/tasks/coverage/snapshots/semantic_typescript.snap @@ -16082,8 +16082,8 @@ rebuilt : ["Function", "Number", "dec"] semantic Error: tasks/coverage/typescript/tests/cases/compiler/importHelpersInTsx.tsx Bindings mismatch: -after transform: ScopeId(0): ["React", "_jsxFileName", "o", "x"] -rebuilt : ScopeId(0): ["_jsxFileName", "x"] +after transform: ScopeId(0): ["React", "_jsxFileName", "_objectSpread", "o", "x"] +rebuilt : ScopeId(0): ["_jsxFileName", "_objectSpread", "x"] Reference symbol mismatch for "React": after transform: SymbolId(0) "React" rebuilt : @@ -19219,8 +19219,8 @@ rebuilt : ScopeId(0): [] semantic Error: tasks/coverage/typescript/tests/cases/compiler/jsxSpreadFirstUnionNoErrors.tsx Bindings mismatch: -after transform: ScopeId(0): ["Info", "React", "_jsxFileName", "a", "b", "c", "infoProps"] -rebuilt : ScopeId(0): ["Info", "React", "_jsxFileName", "a", "b", "c"] +after transform: ScopeId(0): ["Info", "React", "_jsxFileName", "_objectSpread", "a", "b", "c", "infoProps"] +rebuilt : ScopeId(0): ["Info", "React", "_jsxFileName", "_objectSpread", "a", "b", "c"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2)] rebuilt : ScopeId(0): [ScopeId(1)] @@ -25874,8 +25874,8 @@ rebuilt : ["print"] semantic Error: tasks/coverage/typescript/tests/cases/compiler/reactHOCSpreadprops.tsx Symbol reference IDs mismatch for "React": -after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(4), ReferenceId(9)] -rebuilt : SymbolId(1): [ReferenceId(1), ReferenceId(2)] +after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(4), ReferenceId(11)] +rebuilt : SymbolId(2): [ReferenceId(1), ReferenceId(2)] semantic Error: tasks/coverage/typescript/tests/cases/compiler/reactNamespaceImportPresevation.tsx Bindings mismatch: @@ -28859,10 +28859,10 @@ rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)] semantic Error: tasks/coverage/typescript/tests/cases/compiler/spreadIntersectionJsx.tsx Symbol reference IDs mismatch for "A": after transform: SymbolId(1): [ReferenceId(0)] -rebuilt : SymbolId(3): [] +rebuilt : SymbolId(4): [] Symbol reference IDs mismatch for "C": after transform: SymbolId(2): [ReferenceId(1)] -rebuilt : SymbolId(4): [] +rebuilt : SymbolId(5): [] semantic Error: tasks/coverage/typescript/tests/cases/compiler/spreadObjectNoCircular1.ts Bindings mismatch: @@ -30329,13 +30329,13 @@ rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), Sc semantic Error: tasks/coverage/typescript/tests/cases/compiler/tsxReactPropsInferenceSucceedsOnIntersections.tsx Bindings mismatch: -after transform: ScopeId(0): ["Button", "CustomButton", "React", "_jsxFileName"] -rebuilt : ScopeId(0): ["CustomButton", "React", "_jsxFileName"] +after transform: ScopeId(0): ["Button", "CustomButton", "React", "_jsxFileName", "_objectSpread"] +rebuilt : ScopeId(0): ["CustomButton", "React", "_jsxFileName", "_objectSpread"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4)] rebuilt : ScopeId(0): [ScopeId(1)] Symbol reference IDs mismatch for "React": -after transform: SymbolId(0): [ReferenceId(0), ReferenceId(3), ReferenceId(7), ReferenceId(12)] +after transform: SymbolId(0): [ReferenceId(0), ReferenceId(3), ReferenceId(7), ReferenceId(14)] rebuilt : SymbolId(0): [ReferenceId(0)] Reference symbol mismatch for "Button": after transform: SymbolId(3) "Button" @@ -46555,8 +46555,8 @@ rebuilt : ["React", "__proto__"] semantic Error: tasks/coverage/typescript/tests/cases/conformance/jsx/tsxExternalModuleEmit2.tsx Bindings mismatch: -after transform: ScopeId(0): ["Foo", "Main", "React", "_jsxFileName"] -rebuilt : ScopeId(0): ["Main", "_jsxFileName"] +after transform: ScopeId(0): ["Foo", "Main", "React", "_jsxFileName", "_objectSpread"] +rebuilt : ScopeId(0): ["Main", "_jsxFileName", "_objectSpread"] Reference symbol mismatch for "React": after transform: SymbolId(2) "React" rebuilt : diff --git a/tasks/transform_conformance/snapshots/oxc.snap.md b/tasks/transform_conformance/snapshots/oxc.snap.md index 32f85ccb5e911..23a3067146738 100644 --- a/tasks/transform_conformance/snapshots/oxc.snap.md +++ b/tasks/transform_conformance/snapshots/oxc.snap.md @@ -1,6 +1,6 @@ commit: 98d18aa4 -Passed: 182/302 +Passed: 183/303 # All Passed: * babel-plugin-transform-class-static-block @@ -521,7 +521,7 @@ after transform: [ReferenceId(0), ReferenceId(1), ReferenceId(4), ReferenceId(9) rebuilt : [ReferenceId(5)] -# babel-plugin-transform-react-jsx (44/47) +# babel-plugin-transform-react-jsx (45/48) * refresh/import-after-component/input.js Missing ScopeId Missing ReferenceId: "useFoo" diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/input.jsx b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/input.jsx new file mode 100644 index 0000000000000..f925428a5cd45 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/input.jsx @@ -0,0 +1,7 @@ +export function Foo(props) { + return ( +
+

a

+
+ ); +} \ No newline at end of file diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/options.json b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/options.json new file mode 100644 index 0000000000000..a255067d949e9 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + [ + "transform-react-jsx-development", + { + "runtime": "classic" + } + ] + ] +} diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/output.js new file mode 100644 index 0000000000000..42654e6e05646 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/output.js @@ -0,0 +1,19 @@ +var _jsxFileName = "/tests/babel-plugin-transform-react-jsx/test/fixtures/spread-props-classic/input.jsx"; +export function Foo(props) { + return /* @__PURE__ */ React.createElement("div", { + ...props, + __self: this, + __source: { + fileName: _jsxFileName, + lineNumber: 3, + columnNumber: 5 + } + }, /* @__PURE__ */ React.createElement("p", { + __self: this, + __source: { + fileName: _jsxFileName, + lineNumber: 4, + columnNumber: 7 + } + }, "a")); +}