mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-06 17:34:25 +00:00
fix(react_compiler): codegen destructuring reassignment targets (#24131)
## Root cause
The reactive-function backend (`codegen_reactive_function.rs`) only knew
how to turn a plain `BindingIdentifier` lvalue into an
`AssignmentTarget`. Any **destructuring reassignment** to an existing
binding — `[x] = arr`, `({a} = obj)`, `({a} = {a:{}}), ([x] = [[]])` —
hit an unported `invariant_err("Destructuring reassignment targets are
not yet ported to oxc")`.
`codegen_function` deliberately swallows any emission error and falls
back to an **empty body** (a shim from the de-Babel batches). So every
function containing such an assignment silently compiled to `function
f() {}` — params and body both dropped — with **no diagnostic**. This is
a hard miscompile, not a whitespace diff.
## Fix
Port `ox_binding_pattern_to_assignment_target` to recursively reshape
`BindingPattern` → `AssignmentTarget`, since oxc (unlike Babel) models
declaration patterns and assignment targets as distinct node families.
Adds handling for:
- array patterns → `ArrayAssignmentTarget` (elements + holes + rest)
- object patterns → `ObjectAssignmentTarget`, distinguishing shorthand
(`{a}` / `{a = 1}` → `AssignmentTargetPropertyIdentifier`) from keyed
(`{a: b}` → `AssignmentTargetPropertyProperty`)
- rest elements (`...x`)
- nested patterns and defaults (`AssignmentTargetWithDefault`)
Mirrors Babel, which reuses the same pattern nodes as the assignment
LHS.
## Impact
23 corpus snapshots changed — **all move toward the fork golden, none
regress**; 14 now match the fork exactly. Verified old-vs-new token
distance to each fork golden.
Within this batch (`reduce-reactive-deps` /
`propagate-scope-deps-hir-fork`):
- `ssa-renaming-via-destructuring-with-mutation` — was empty function,
now matches the fork exactly.
- `ssa-renaming-ternary-destruction` /
`ssa-renaming-ternary-destruction-with-mutation` — were empty functions,
now compile with **matching dependency sets, cache keys, scope
boundaries, and dead-code elimination**; the only residual is
codegen-only (sequence-expression parenthesisation `([x]=[[]], …)` vs
`(([x]=[[]]), …)` and object-literal whitespace).
Other improved fixtures across the corpus (also previously
empty-bodied): `destructuring`, `destructuring-assignment`,
`destructuring-assignment-array-default`,
`destructure-direct-reassignment`, `destructure-in-branch-ssa`,
`destructuring-object-pattern-within-rest`,
`escape-analysis-destructured-rest-element`,
`call-args-destructuring-assignment`,
`array-pattern-spread-creates-array`, the `nonmutated-spread-*` set,
`repro-reassign-props`, `switch-with-only-default`,
`new-mutability__ssa-renaming-ternary-destruction`.
## Remaining work (out of scope here)
The rest of the batch's diffs are pure codegen and live in
`oxc_codegen`, not the dependency passes:
- sequence-expression parenthesisation of assignment operands (`(a=[],
b)` vs `((a=[]), b)`)
- JSX multi-line wrapping, TS type printing, object/array-literal
whitespace
The two `try-catch-*` fixtures (stray `;`) belong to a sibling
`fix/rc-try-catch` branch and are left untouched.
This commit is contained in:
1 parent
b82c394e2f
commit
cb2a5051af
24 files changed
+740
-28
No files matched your search
+113
-5
@@ -2566,6 +2566,12 @@ fn ox_codegen_dependency<'a>(
|
||||
|
||||
/// Convert a `BindingPattern` (from `ox_codegen_lvalue`) into an `AssignmentTarget`
|
||||
/// for reassignment / `StoreLocal` emission.
|
||||
///
|
||||
/// oxc models declaration binding patterns (`BindingPattern`) and assignment targets
|
||||
/// (`AssignmentTarget`) as distinct node families, so a destructuring reassignment
|
||||
/// like `[x] = arr` or `({a} = obj)` must be re-shaped from the pattern produced by
|
||||
/// `ox_codegen_lvalue` into the corresponding assignment-target tree. Mirrors Babel,
|
||||
/// which reuses the same `ArrayPattern`/`ObjectPattern` nodes as assignment LHS.
|
||||
fn ox_binding_pattern_to_assignment_target<'a>(
|
||||
cx: &OxcContext<'a, '_, '_>,
|
||||
pattern: oxc::BindingPattern<'a>,
|
||||
@@ -2573,17 +2579,119 @@ fn ox_binding_pattern_to_assignment_target<'a>(
|
||||
match pattern {
|
||||
oxc::BindingPattern::BindingIdentifier(id) => {
|
||||
let id = id.unbox();
|
||||
Ok(oxc::AssignmentTarget::AssignmentTargetIdentifier(
|
||||
oxc_ast::ast::IdentifierReference::boxed(SPAN, id.name, &cx.ast),
|
||||
Ok(oxc::AssignmentTarget::new_assignment_target_identifier(SPAN, id.name, &cx.ast))
|
||||
}
|
||||
oxc::BindingPattern::ArrayPattern(arr) => {
|
||||
let arr = arr.unbox();
|
||||
let mut elements: oxc_allocator::Vec<
|
||||
'a,
|
||||
Option<oxc::AssignmentTargetMaybeDefault<'a>>,
|
||||
> = oxc_allocator::ArenaVec::new_in(&cx.ast);
|
||||
for element in arr.elements {
|
||||
match element {
|
||||
Some(bp) => elements.push(Some(ox_binding_pattern_to_maybe_default(cx, bp)?)),
|
||||
None => elements.push(None),
|
||||
}
|
||||
}
|
||||
let rest = ox_binding_rest_to_assignment_rest(cx, arr.rest)?;
|
||||
Ok(oxc::AssignmentTarget::new_array_assignment_target(SPAN, elements, rest, &cx.ast))
|
||||
}
|
||||
oxc::BindingPattern::ObjectPattern(obj) => {
|
||||
let obj = obj.unbox();
|
||||
let mut properties: oxc_allocator::Vec<'a, oxc::AssignmentTargetProperty<'a>> =
|
||||
oxc_allocator::ArenaVec::new_in(&cx.ast);
|
||||
for prop in obj.properties {
|
||||
properties.push(ox_binding_property_to_assignment_property(cx, prop)?);
|
||||
}
|
||||
let rest = ox_binding_rest_to_assignment_rest(cx, obj.rest)?;
|
||||
Ok(oxc::AssignmentTarget::new_object_assignment_target(SPAN, properties, rest, &cx.ast))
|
||||
}
|
||||
// A top-level default (`x = 1`) is not a valid assignment target on its own;
|
||||
// defaults only appear nested and are handled by `ox_binding_pattern_to_maybe_default`.
|
||||
oxc::BindingPattern::AssignmentPattern(_) => {
|
||||
Err(invariant_err("Unexpected default in destructuring assignment target", None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `BindingPattern` element into an `AssignmentTargetMaybeDefault`, turning a
|
||||
/// nested default (`[x = 1] = arr`) into an `AssignmentTargetWithDefault`.
|
||||
fn ox_binding_pattern_to_maybe_default<'a>(
|
||||
cx: &OxcContext<'a, '_, '_>,
|
||||
pattern: oxc::BindingPattern<'a>,
|
||||
) -> Result<oxc::AssignmentTargetMaybeDefault<'a>, CompilerError> {
|
||||
match pattern {
|
||||
oxc::BindingPattern::AssignmentPattern(assign) => {
|
||||
let assign = assign.unbox();
|
||||
let binding = ox_binding_pattern_to_assignment_target(cx, assign.left)?;
|
||||
Ok(oxc::AssignmentTargetMaybeDefault::new_assignment_target_with_default(
|
||||
SPAN,
|
||||
binding,
|
||||
assign.right,
|
||||
&cx.ast,
|
||||
))
|
||||
}
|
||||
_ => Err(unimplemented_err(
|
||||
"Destructuring reassignment targets are not yet ported to oxc",
|
||||
None,
|
||||
other => Ok(oxc::AssignmentTargetMaybeDefault::from(
|
||||
ox_binding_pattern_to_assignment_target(cx, other)?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an object `BindingProperty` into an `AssignmentTargetProperty`, preserving the
|
||||
/// shorthand form (`{a}` / `{a = 1}`) vs the keyed form (`{a: b}` / `{a: b = 1}`).
|
||||
fn ox_binding_property_to_assignment_property<'a>(
|
||||
cx: &OxcContext<'a, '_, '_>,
|
||||
prop: oxc::BindingProperty<'a>,
|
||||
) -> Result<oxc::AssignmentTargetProperty<'a>, CompilerError> {
|
||||
if prop.shorthand {
|
||||
let (binding, init) = match prop.value {
|
||||
oxc::BindingPattern::BindingIdentifier(id) => (id.unbox(), None),
|
||||
oxc::BindingPattern::AssignmentPattern(assign) => {
|
||||
let assign = assign.unbox();
|
||||
let oxc::BindingPattern::BindingIdentifier(id) = assign.left else {
|
||||
return Err(invariant_err(
|
||||
"Expected an identifier in shorthand destructuring property",
|
||||
None,
|
||||
));
|
||||
};
|
||||
(id.unbox(), Some(assign.right))
|
||||
}
|
||||
_ => {
|
||||
return Err(invariant_err(
|
||||
"Expected an identifier in shorthand destructuring property",
|
||||
None,
|
||||
));
|
||||
}
|
||||
};
|
||||
let reference = oxc_ast::ast::IdentifierReference::new(SPAN, binding.name, &cx.ast);
|
||||
return Ok(oxc::AssignmentTargetProperty::new_assignment_target_property_identifier(
|
||||
SPAN, reference, init, &cx.ast,
|
||||
));
|
||||
}
|
||||
let binding = ox_binding_pattern_to_maybe_default(cx, prop.value)?;
|
||||
Ok(oxc::AssignmentTargetProperty::new_assignment_target_property_property(
|
||||
SPAN,
|
||||
prop.key,
|
||||
binding,
|
||||
prop.computed,
|
||||
&cx.ast,
|
||||
))
|
||||
}
|
||||
|
||||
/// Convert a binding rest element (`...x`) into an assignment-target rest.
|
||||
fn ox_binding_rest_to_assignment_rest<'a>(
|
||||
cx: &OxcContext<'a, '_, '_>,
|
||||
rest: Option<oxc_allocator::Box<'a, oxc::BindingRestElement<'a>>>,
|
||||
) -> Result<Option<oxc::AssignmentTargetRest<'a>>, CompilerError> {
|
||||
match rest {
|
||||
Some(rest) => {
|
||||
let target = ox_binding_pattern_to_assignment_target(cx, rest.unbox().argument)?;
|
||||
Ok(Some(oxc_ast::ast::AssignmentTargetRest::new(SPAN, target, &cx.ast)))
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an expression to a `SimpleAssignmentTarget` for update expressions.
|
||||
fn ox_expression_to_simple_assignment_target<'a>(
|
||||
cx: &OxcContext<'a, '_, '_>,
|
||||
|
||||
@@ -2,10 +2,56 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/array-pattern-spread-creates-array.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
// @validatePreserveExistingMemoizationGuarantees @validateExhaustiveMemoizationDependencies:false
|
||||
import { useMemo } from "react";
|
||||
import { makeObject_Primitives, ValidateMemoization } from "shared-runtime";
|
||||
function Component() {}
|
||||
function Component(props) {
|
||||
const $ = _c(9);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = makeObject_Primitives();
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const x = t0;
|
||||
let rest;
|
||||
if ($[1] !== props.array) {
|
||||
[, ...rest] = props.array;
|
||||
rest.push(x);
|
||||
$[1] = props.array;
|
||||
$[2] = rest;
|
||||
} else {
|
||||
rest = $[2];
|
||||
}
|
||||
const rest_0 = rest;
|
||||
let t1;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = <ValidateMemoization inputs={[]} output={x} />;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
let t2;
|
||||
if ($[4] !== props.array) {
|
||||
t2 = [props.array];
|
||||
$[4] = props.array;
|
||||
$[5] = t2;
|
||||
} else {
|
||||
t2 = $[5];
|
||||
}
|
||||
let t3;
|
||||
if ($[6] !== rest_0 || $[7] !== t2) {
|
||||
t3 = <>{t1}<ValidateMemoization inputs={t2} output={rest_0} /></>;
|
||||
$[6] = rest_0;
|
||||
$[7] = t2;
|
||||
$[8] = t3;
|
||||
} else {
|
||||
t3 = $[8];
|
||||
}
|
||||
return t3;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ array: [
|
||||
|
||||
@@ -2,4 +2,16 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/call-args-destructuring-assignment.js
|
||||
---
|
||||
function Component() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function Component(props) {
|
||||
const $ = _c(1);
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = makeObject();
|
||||
x.foo([x] = makeObject());
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@@ -3,7 +3,17 @@ source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/destructure-direct-reassignment.js
|
||||
---
|
||||
// @enablePreserveExistingMemoizationGuarantees:false
|
||||
function foo() {}
|
||||
function foo(props) {
|
||||
let x;
|
||||
let y;
|
||||
({x, y} = {
|
||||
x: props.a,
|
||||
y: props.b
|
||||
});
|
||||
console.log(x);
|
||||
x = props.c;
|
||||
return x + y;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: foo,
|
||||
params: ["TodoAdd"],
|
||||
|
||||
@@ -2,7 +2,46 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/destructure-in-branch-ssa.ts
|
||||
---
|
||||
function useFoo() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function useFoo(props) {
|
||||
const $ = _c(9);
|
||||
let x = null;
|
||||
let y = null;
|
||||
let z;
|
||||
let myList;
|
||||
if ($[0] !== props) {
|
||||
myList = [];
|
||||
if (props.doDestructure) {
|
||||
({x, y, z} = props);
|
||||
myList.push(z);
|
||||
}
|
||||
$[0] = props;
|
||||
$[1] = myList;
|
||||
$[2] = x;
|
||||
$[3] = y;
|
||||
$[4] = z;
|
||||
} else {
|
||||
myList = $[1];
|
||||
x = $[2];
|
||||
y = $[3];
|
||||
z = $[4];
|
||||
}
|
||||
let t0;
|
||||
if ($[5] !== myList || $[6] !== x || $[7] !== y) {
|
||||
t0 = {
|
||||
x,
|
||||
y,
|
||||
myList
|
||||
};
|
||||
$[5] = myList;
|
||||
$[6] = x;
|
||||
$[7] = y;
|
||||
$[8] = t0;
|
||||
} else {
|
||||
t0 = $[8];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
+20
-1
@@ -2,7 +2,26 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/destructuring-assignment-array-default.js
|
||||
---
|
||||
function Component() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function Component(props) {
|
||||
const $ = _c(2);
|
||||
let x;
|
||||
if (props.cond) {
|
||||
const [t0] = props.y;
|
||||
let t1;
|
||||
if ($[0] !== t0) {
|
||||
t1 = t0 === undefined ? ["default"] : t0;
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
[x] = t1;
|
||||
} else {
|
||||
x = props.fallback;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: ["TodoAdd"],
|
||||
|
||||
@@ -2,7 +2,41 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/destructuring-assignment.js
|
||||
---
|
||||
function foo() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function foo(a, b, c) {
|
||||
const $ = _c(5);
|
||||
let d;
|
||||
let g;
|
||||
let n;
|
||||
let o;
|
||||
const [t0, t1] = a;
|
||||
d = t0;
|
||||
const [t2] = t1;
|
||||
const { e: t3 } = t2;
|
||||
({f: g} = t3);
|
||||
const { l: t4, o: t5 } = b;
|
||||
const { m: t6 } = t4;
|
||||
const [t7] = t6;
|
||||
[n] = t7;
|
||||
o = t5;
|
||||
let t8;
|
||||
if ($[0] !== d || $[1] !== g || $[2] !== n || $[3] !== o) {
|
||||
t8 = {
|
||||
d,
|
||||
g,
|
||||
n,
|
||||
o
|
||||
};
|
||||
$[0] = d;
|
||||
$[1] = g;
|
||||
$[2] = n;
|
||||
$[3] = o;
|
||||
$[4] = t8;
|
||||
} else {
|
||||
t8 = $[4];
|
||||
}
|
||||
return t8;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: foo,
|
||||
params: ["TodoAdd"],
|
||||
|
||||
+26
-1
@@ -2,7 +2,32 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/destructuring-object-pattern-within-rest.js
|
||||
---
|
||||
function Component() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function Component(props) {
|
||||
const $ = _c(6);
|
||||
let t0;
|
||||
let y;
|
||||
if ($[0] !== props.value) {
|
||||
[y, ...t0] = props.value;
|
||||
$[0] = props.value;
|
||||
$[1] = t0;
|
||||
$[2] = y;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
y = $[2];
|
||||
}
|
||||
const { z } = t0;
|
||||
let t1;
|
||||
if ($[3] !== y || $[4] !== z) {
|
||||
t1 = [y, z];
|
||||
$[3] = y;
|
||||
$[4] = z;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ value: ["y", { z: "z!" }] }]
|
||||
|
||||
@@ -2,7 +2,74 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/destructuring.js
|
||||
---
|
||||
function foo() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function foo(a, b, c) {
|
||||
const $ = _c(18);
|
||||
let d;
|
||||
let h;
|
||||
let t0;
|
||||
if ($[0] !== a) {
|
||||
[d, t0, ...h] = a;
|
||||
$[0] = a;
|
||||
$[1] = d;
|
||||
$[2] = h;
|
||||
$[3] = t0;
|
||||
} else {
|
||||
d = $[1];
|
||||
h = $[2];
|
||||
t0 = $[3];
|
||||
}
|
||||
const [t1] = t0;
|
||||
let g;
|
||||
let t2;
|
||||
if ($[4] !== t1) {
|
||||
({e: t2, ...g} = t1);
|
||||
$[4] = t1;
|
||||
$[5] = g;
|
||||
$[6] = t2;
|
||||
} else {
|
||||
g = $[5];
|
||||
t2 = $[6];
|
||||
}
|
||||
const { f } = t2;
|
||||
const { l: t3, p } = b;
|
||||
const { m: t4 } = t3;
|
||||
let o;
|
||||
let t5;
|
||||
if ($[7] !== t4) {
|
||||
[t5, ...o] = t4;
|
||||
$[7] = t4;
|
||||
$[8] = o;
|
||||
$[9] = t5;
|
||||
} else {
|
||||
o = $[8];
|
||||
t5 = $[9];
|
||||
}
|
||||
const [n] = t5;
|
||||
let t6;
|
||||
if ($[10] !== d || $[11] !== f || $[12] !== g || $[13] !== h || $[14] !== n || $[15] !== o || $[16] !== p) {
|
||||
t6 = [
|
||||
d,
|
||||
f,
|
||||
g,
|
||||
h,
|
||||
n,
|
||||
o,
|
||||
p
|
||||
];
|
||||
$[10] = d;
|
||||
$[11] = f;
|
||||
$[12] = g;
|
||||
$[13] = h;
|
||||
$[14] = n;
|
||||
$[15] = o;
|
||||
$[16] = p;
|
||||
$[17] = t6;
|
||||
} else {
|
||||
t6 = $[17];
|
||||
}
|
||||
return t6;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: foo,
|
||||
params: ["TodoAdd"],
|
||||
|
||||
+31
-1
@@ -2,7 +2,37 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/escape-analysis-destructured-rest-element.js
|
||||
---
|
||||
function Component() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function Component(props) {
|
||||
const $ = _c(7);
|
||||
let b;
|
||||
if ($[0] !== props.a) {
|
||||
const { a, ...t0 } = props.a;
|
||||
b = t0;
|
||||
$[0] = props.a;
|
||||
$[1] = b;
|
||||
} else {
|
||||
b = $[1];
|
||||
}
|
||||
let d;
|
||||
if ($[2] !== props.c) {
|
||||
[, ...d] = props.c;
|
||||
$[2] = props.c;
|
||||
$[3] = d;
|
||||
} else {
|
||||
d = $[3];
|
||||
}
|
||||
let t0;
|
||||
if ($[4] !== b || $[5] !== d) {
|
||||
t0 = <div b={b} d={d} />;
|
||||
$[4] = b;
|
||||
$[5] = d;
|
||||
$[6] = t0;
|
||||
} else {
|
||||
t0 = $[6];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: ["TodoAdd"],
|
||||
|
||||
+22
-1
@@ -2,8 +2,29 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/new-mutability/ssa-renaming-ternary-destruction.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
// @enablePropagateDepsInHIR @enableNewMutationAliasingModel
|
||||
function useFoo() {}
|
||||
function useFoo(props) {
|
||||
const $ = _c(5);
|
||||
let x;
|
||||
if ($[0] !== props.bar) {
|
||||
x = [];
|
||||
x.push(props.bar);
|
||||
$[0] = props.bar;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
if ($[2] !== props.cond || $[3] !== props.foo) {
|
||||
props.cond ? ([x] = [[]], x.push(props.foo)) : null;
|
||||
$[2] = props.cond;
|
||||
$[3] = props.foo;
|
||||
$[4] = x;
|
||||
} else {
|
||||
x = $[4];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
@@ -2,8 +2,35 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/nonmutated-spread-hook-return.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { identity, Stringify, useIdentity } from "shared-runtime";
|
||||
function Component() {}
|
||||
function Component(props) {
|
||||
const $ = _c(6);
|
||||
const t0 = useIdentity(props);
|
||||
let rest;
|
||||
let x;
|
||||
if ($[0] !== t0) {
|
||||
({x, ...rest} = t0);
|
||||
$[0] = t0;
|
||||
$[1] = rest;
|
||||
$[2] = x;
|
||||
} else {
|
||||
rest = $[1];
|
||||
x = $[2];
|
||||
}
|
||||
const z = rest.z;
|
||||
identity(z);
|
||||
let t1;
|
||||
if ($[3] !== x || $[4] !== z) {
|
||||
t1 = <Stringify x={x} z={z} />;
|
||||
$[3] = x;
|
||||
$[4] = z;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{
|
||||
|
||||
@@ -2,8 +2,32 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/nonmutated-spread-props-jsx.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { identity, Stringify } from "shared-runtime";
|
||||
function Component() {}
|
||||
function Component(t0) {
|
||||
const $ = _c(6);
|
||||
let rest;
|
||||
let x;
|
||||
if ($[0] !== t0) {
|
||||
({x, ...rest} = t0);
|
||||
$[0] = t0;
|
||||
$[1] = rest;
|
||||
$[2] = x;
|
||||
} else {
|
||||
rest = $[1];
|
||||
x = $[2];
|
||||
}
|
||||
let t1;
|
||||
if ($[3] !== rest || $[4] !== x) {
|
||||
t1 = <Stringify {...rest} x={x} />;
|
||||
$[3] = rest;
|
||||
$[4] = x;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{
|
||||
|
||||
+28
-1
@@ -2,8 +2,35 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/nonmutated-spread-props-local-indirection.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { identity, Stringify } from "shared-runtime";
|
||||
function Component() {}
|
||||
function Component(t0) {
|
||||
const $ = _c(6);
|
||||
let rest;
|
||||
let x;
|
||||
if ($[0] !== t0) {
|
||||
({x, ...rest} = t0);
|
||||
$[0] = t0;
|
||||
$[1] = rest;
|
||||
$[2] = x;
|
||||
} else {
|
||||
rest = $[1];
|
||||
x = $[2];
|
||||
}
|
||||
const restAlias = rest;
|
||||
const z = restAlias.z;
|
||||
identity(z);
|
||||
let t1;
|
||||
if ($[3] !== x || $[4] !== z) {
|
||||
t1 = <Stringify x={x} z={z} />;
|
||||
$[3] = x;
|
||||
$[4] = z;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{
|
||||
|
||||
@@ -2,8 +2,34 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/nonmutated-spread-props.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { identity, Stringify } from "shared-runtime";
|
||||
function Component() {}
|
||||
function Component(t0) {
|
||||
const $ = _c(6);
|
||||
let rest;
|
||||
let x;
|
||||
if ($[0] !== t0) {
|
||||
({x, ...rest} = t0);
|
||||
$[0] = t0;
|
||||
$[1] = rest;
|
||||
$[2] = x;
|
||||
} else {
|
||||
rest = $[1];
|
||||
x = $[2];
|
||||
}
|
||||
const z = rest.z;
|
||||
identity(z);
|
||||
let t1;
|
||||
if ($[3] !== x || $[4] !== z) {
|
||||
t1 = <Stringify x={x} z={z} />;
|
||||
$[3] = x;
|
||||
$[4] = z;
|
||||
$[5] = t1;
|
||||
} else {
|
||||
t1 = $[5];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{
|
||||
|
||||
+18
-1
@@ -2,9 +2,26 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/propagate-scope-deps-hir-fork/ssa-renaming-ternary-destruction-with-mutation.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
// @enablePropagateDepsInHIR
|
||||
import { mutate } from "shared-runtime";
|
||||
function useFoo() {}
|
||||
function useFoo(props) {
|
||||
const $ = _c(4);
|
||||
let x;
|
||||
if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {
|
||||
x = [];
|
||||
x.push(props.bar);
|
||||
props.cond ? ([x] = [[]], x.push(props.foo)) : null;
|
||||
mutate(x);
|
||||
$[0] = props.bar;
|
||||
$[1] = props.cond;
|
||||
$[2] = props.foo;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x = $[3];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
+22
-1
@@ -2,8 +2,29 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/propagate-scope-deps-hir-fork/ssa-renaming-ternary-destruction.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
// @enablePropagateDepsInHIR
|
||||
function useFoo() {}
|
||||
function useFoo(props) {
|
||||
const $ = _c(5);
|
||||
let x;
|
||||
if ($[0] !== props.bar) {
|
||||
x = [];
|
||||
x.push(props.bar);
|
||||
$[0] = props.bar;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
if ($[2] !== props.cond || $[3] !== props.foo) {
|
||||
props.cond ? ([x] = [[]], x.push(props.foo)) : null;
|
||||
$[2] = props.cond;
|
||||
$[3] = props.foo;
|
||||
$[4] = x;
|
||||
} else {
|
||||
x = $[4];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
+21
-1
@@ -2,9 +2,29 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/propagate-scope-deps-hir-fork/ssa-renaming-via-destructuring-with-mutation.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
// @enablePropagateDepsInHIR
|
||||
import { mutate } from "shared-runtime";
|
||||
function useFoo() {}
|
||||
function useFoo(props) {
|
||||
const $ = _c(4);
|
||||
let x;
|
||||
if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {
|
||||
({x} = { x: [] });
|
||||
x.push(props.bar);
|
||||
if (props.cond) {
|
||||
({x} = { x: [] });
|
||||
x.push(props.foo);
|
||||
}
|
||||
mutate(x);
|
||||
$[0] = props.bar;
|
||||
$[1] = props.cond;
|
||||
$[2] = props.foo;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x = $[3];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
@@ -2,8 +2,39 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/repro-reassign-props.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { Stringify, useIdentity } from "shared-runtime";
|
||||
function Component() {}
|
||||
function Component(t0, ref) {
|
||||
const $ = _c(7);
|
||||
let props;
|
||||
if ($[0] !== t0) {
|
||||
let { other, ...t1 } = t0;
|
||||
props = t1;
|
||||
$[0] = t0;
|
||||
$[1] = props;
|
||||
} else {
|
||||
props = $[1];
|
||||
}
|
||||
let t1;
|
||||
if ($[2] !== props || $[3] !== ref) {
|
||||
t1 = [props, ref];
|
||||
$[2] = props;
|
||||
$[3] = ref;
|
||||
$[4] = t1;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
}
|
||||
[props, ref] = useIdentity(t1);
|
||||
let t2;
|
||||
if ($[5] !== props) {
|
||||
t2 = <Stringify props={props} />;
|
||||
$[5] = props;
|
||||
$[6] = t2;
|
||||
} else {
|
||||
t2 = $[6];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{
|
||||
|
||||
+18
-1
@@ -2,8 +2,25 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/ssa-renaming-ternary-destruction-with-mutation.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { mutate } from "shared-runtime";
|
||||
function useFoo() {}
|
||||
function useFoo(props) {
|
||||
const $ = _c(4);
|
||||
let x;
|
||||
if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {
|
||||
x = [];
|
||||
x.push(props.bar);
|
||||
props.cond ? ([x] = [[]], x.push(props.foo)) : null;
|
||||
mutate(x);
|
||||
$[0] = props.bar;
|
||||
$[1] = props.cond;
|
||||
$[2] = props.foo;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x = $[3];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
@@ -2,7 +2,28 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/ssa-renaming-ternary-destruction.js
|
||||
---
|
||||
function useFoo() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function useFoo(props) {
|
||||
const $ = _c(5);
|
||||
let x;
|
||||
if ($[0] !== props.bar) {
|
||||
x = [];
|
||||
x.push(props.bar);
|
||||
$[0] = props.bar;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
if ($[2] !== props.cond || $[3] !== props.foo) {
|
||||
props.cond ? ([x] = [[]], x.push(props.foo)) : null;
|
||||
$[2] = props.cond;
|
||||
$[3] = props.foo;
|
||||
$[4] = x;
|
||||
} else {
|
||||
x = $[4];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
+21
-1
@@ -2,8 +2,28 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/ssa-renaming-via-destructuring-with-mutation.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { mutate } from "shared-runtime";
|
||||
function useFoo() {}
|
||||
function useFoo(props) {
|
||||
const $ = _c(4);
|
||||
let x;
|
||||
if ($[0] !== props.bar || $[1] !== props.cond || $[2] !== props.foo) {
|
||||
({x} = { x: [] });
|
||||
x.push(props.bar);
|
||||
if (props.cond) {
|
||||
({x} = { x: [] });
|
||||
x.push(props.foo);
|
||||
}
|
||||
mutate(x);
|
||||
$[0] = props.bar;
|
||||
$[1] = props.cond;
|
||||
$[2] = props.foo;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x = $[3];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{
|
||||
|
||||
@@ -2,7 +2,30 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/ssa-renaming-via-destructuring.js
|
||||
---
|
||||
function foo() {}
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function foo(props) {
|
||||
const $ = _c(4);
|
||||
let x;
|
||||
if ($[0] !== props.bar) {
|
||||
({x} = { x: [] });
|
||||
x.push(props.bar);
|
||||
$[0] = props.bar;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
if (props.cond) {
|
||||
if ($[2] !== props.foo) {
|
||||
({x} = { x: [] });
|
||||
x.push(props.foo);
|
||||
$[2] = props.foo;
|
||||
$[3] = x;
|
||||
} else {
|
||||
x = $[3];
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: foo,
|
||||
params: ["TodoAdd"],
|
||||
|
||||
@@ -2,8 +2,35 @@
|
||||
source: crates/oxc_react_compiler/tests/snapshot.rs
|
||||
input_file: crates/oxc_react_compiler/fixtures/switch-with-only-default.js
|
||||
---
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { Stringify } from "shared-runtime";
|
||||
function Component() {}
|
||||
function Component(t0) {
|
||||
const $ = _c(5);
|
||||
let kind;
|
||||
let props;
|
||||
if ($[0] !== t0) {
|
||||
({kind, ...props} = t0);
|
||||
$[0] = t0;
|
||||
$[1] = kind;
|
||||
$[2] = props;
|
||||
} else {
|
||||
kind = $[1];
|
||||
props = $[2];
|
||||
}
|
||||
switch (kind) {
|
||||
default: {
|
||||
let t1;
|
||||
if ($[3] !== props) {
|
||||
t1 = <Stringify {...props} />;
|
||||
$[3] = props;
|
||||
$[4] = t1;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{
|
||||
|
||||
Reference in new issue
Block a user