Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] main from facebook:main #26

Merged
merged 3 commits into from
Dec 10, 2024
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
58 changes: 35 additions & 23 deletions compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,12 @@ function lowerStatement(
const left = stmt.get('left');
const leftLoc = left.node.loc ?? GeneratedSource;
let test: Place;
const advanceIterator = lowerValueToTemporary(builder, {
kind: 'IteratorNext',
loc: leftLoc,
iterator: {...iterator},
collection: {...value},
});
if (left.isVariableDeclaration()) {
const declarations = left.get('declarations');
CompilerError.invariant(declarations.length === 1, {
Expand All @@ -1087,12 +1093,6 @@ function lowerStatement(
suggestions: null,
});
const id = declarations[0].get('id');
const advanceIterator = lowerValueToTemporary(builder, {
kind: 'IteratorNext',
loc: leftLoc,
iterator: {...iterator},
collection: {...value},
});
const assign = lowerAssignment(
builder,
leftLoc,
Expand All @@ -1103,13 +1103,19 @@ function lowerStatement(
);
test = lowerValueToTemporary(builder, assign);
} else {
builder.errors.push({
reason: `(BuildHIR::lowerStatement) Handle ${left.type} inits in ForOfStatement`,
severity: ErrorSeverity.Todo,
loc: left.node.loc ?? null,
suggestions: null,
CompilerError.invariant(left.isLVal(), {
loc: leftLoc,
reason: 'Expected ForOf init to be a variable declaration or lval',
});
return;
const assign = lowerAssignment(
builder,
leftLoc,
InstructionKind.Reassign,
left,
advanceIterator,
'Assignment',
);
test = lowerValueToTemporary(builder, assign);
}
builder.terminateWithContinuation(
{
Expand Down Expand Up @@ -1166,6 +1172,11 @@ function lowerStatement(
const left = stmt.get('left');
const leftLoc = left.node.loc ?? GeneratedSource;
let test: Place;
const nextPropertyTemp = lowerValueToTemporary(builder, {
kind: 'NextPropertyOf',
loc: leftLoc,
value,
});
if (left.isVariableDeclaration()) {
const declarations = left.get('declarations');
CompilerError.invariant(declarations.length === 1, {
Expand All @@ -1175,11 +1186,6 @@ function lowerStatement(
suggestions: null,
});
const id = declarations[0].get('id');
const nextPropertyTemp = lowerValueToTemporary(builder, {
kind: 'NextPropertyOf',
loc: leftLoc,
value,
});
const assign = lowerAssignment(
builder,
leftLoc,
Expand All @@ -1190,13 +1196,19 @@ function lowerStatement(
);
test = lowerValueToTemporary(builder, assign);
} else {
builder.errors.push({
reason: `(BuildHIR::lowerStatement) Handle ${left.type} inits in ForInStatement`,
severity: ErrorSeverity.Todo,
loc: left.node.loc ?? null,
suggestions: null,
CompilerError.invariant(left.isLVal(), {
loc: leftLoc,
reason: 'Expected ForIn init to be a variable declaration or lval',
});
return;
const assign = lowerAssignment(
builder,
leftLoc,
InstructionKind.Reassign,
left,
nextPropertyTemp,
'Assignment',
);
test = lowerValueToTemporary(builder, assign);
}
builder.terminateWithContinuation(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1354,20 +1354,6 @@ function codegenForInit(
init: ReactiveValue,
): t.Expression | t.VariableDeclaration | null {
if (init.kind === 'SequenceExpression') {
for (const instr of init.instructions) {
if (instr.value.kind === 'DeclareContext') {
CompilerError.throwTodo({
reason: `Support for loops where the index variable is a context variable`,
loc: instr.loc,
description:
instr.value.lvalue.place.identifier.name != null
? `\`${instr.value.lvalue.place.identifier.name.value}\` is a context variable`
: null,
suggestions: null,
});
}
}

const body = codegenBlock(
cx,
init.instructions.map(instruction => ({
Expand All @@ -1378,20 +1364,33 @@ function codegenForInit(
const declarators: Array<t.VariableDeclarator> = [];
let kind: 'let' | 'const' = 'const';
body.forEach(instr => {
CompilerError.invariant(
instr.type === 'VariableDeclaration' &&
(instr.kind === 'let' || instr.kind === 'const'),
{
reason: 'Expected a variable declaration',
loc: init.loc,
description: `Got ${instr.type}`,
suggestions: null,
},
);
if (instr.kind === 'let') {
kind = 'let';
let top: undefined | t.VariableDeclarator = undefined;
if (
instr.type === 'ExpressionStatement' &&
instr.expression.type === 'AssignmentExpression' &&
instr.expression.operator === '=' &&
instr.expression.left.type === 'Identifier' &&
(top = declarators.at(-1))?.id.type === 'Identifier' &&
top?.id.name === instr.expression.left.name &&
top?.init == null
) {
top.init = instr.expression.right;
} else {
CompilerError.invariant(
instr.type === 'VariableDeclaration' &&
(instr.kind === 'let' || instr.kind === 'const'),
{
reason: 'Expected a variable declaration',
loc: init.loc,
description: `Got ${instr.type}`,
suggestions: null,
},
);
if (instr.kind === 'let') {
kind = 'let';
}
declarators.push(...instr.declarations);
}
declarators.push(...instr.declarations);
});
CompilerError.invariant(declarators.length > 0, {
reason: 'Expected a variable declaration',
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ Todo: (BuildHIR::lowerExpression) Handle tagged template with interpolations (30

Todo: (BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value (34:34)

Todo: (BuildHIR::lowerStatement) Handle Identifier inits in ForOfStatement (36:36)

Todo: (BuildHIR::lowerStatement) Handle ArrayPattern inits in ForOfStatement (38:38)

Todo: (BuildHIR::lowerStatement) Handle ObjectPattern inits in ForOfStatement (40:40)

Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `MemberExpression` cannot be safely reordered (57:57)

Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `BinaryExpression` cannot be safely reordered (53:53)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

## Input

```javascript
function Component() {
const data = useData();
const items = [];
// NOTE: `i` is a context variable because it's reassigned and also referenced
// within a closure, the `onClick` handler of each item
for (let i = MIN; i <= MAX; i += INCREMENT) {
items.push(<div key={i} onClick={() => data.set(i)} />);
}
return <>{items}</>;
}

const MIN = 0;
const MAX = 3;
const INCREMENT = 1;

function useData() {
return new Map();
}

export const FIXTURE_ENTRYPOINT = {
params: [],
fn: Component,
};

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime";
function Component() {
const $ = _c(2);
const data = useData();
let t0;
if ($[0] !== data) {
const items = [];
for (let i = MIN; i <= MAX; i = i + INCREMENT, i) {
items.push(<div key={i} onClick={() => data.set(i)} />);
}

t0 = <>{items}</>;
$[0] = data;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}

const MIN = 0;
const MAX = 3;
const INCREMENT = 1;

function useData() {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = new Map();
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}

export const FIXTURE_ENTRYPOINT = {
params: [],
fn: Component,
};

```

### Eval output
(kind: ok) <div></div><div></div><div></div><div></div>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,20 @@ function Component() {
// NOTE: `i` is a context variable because it's reassigned and also referenced
// within a closure, the `onClick` handler of each item
for (let i = MIN; i <= MAX; i += INCREMENT) {
items.push(<Stringify key={i} onClick={() => data.set(i)} />);
items.push(<div key={i} onClick={() => data.set(i)} />);
}
return items;
return <>{items}</>;
}

const MIN = 0;
const MAX = 3;
const INCREMENT = 1;

function useData() {
return new Map();
}

export const FIXTURE_ENTRYPOINT = {
params: [],
fn: Component,
};
Loading
Loading