mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[valueblocks] Disallow AssignmentExpression in value blocks (temporarily)
There's a bug with assignment expression in normal value blocks due to LeaveSSA. Until that's resolved i'm temporarily distinguishing "loop" blocks and "value" blocks, and disallowing assignment expressions in value blocks specifically.
This commit is contained in:
@@ -247,11 +247,11 @@ function lowerStatement(
|
||||
case "ForStatement": {
|
||||
const stmt = stmtPath as NodePath<t.ForStatement>;
|
||||
|
||||
const testBlock = builder.reserve("value");
|
||||
const testBlock = builder.reserve("loop");
|
||||
// Block for code following the loop
|
||||
const continuationBlock = builder.reserve("block");
|
||||
|
||||
const initBlock = builder.enter("value", (blockId) => {
|
||||
const initBlock = builder.enter("loop", (blockId) => {
|
||||
const init = stmt.get("init");
|
||||
if (!init.isVariableDeclaration()) {
|
||||
builder.errors.push({
|
||||
@@ -271,7 +271,7 @@ function lowerStatement(
|
||||
};
|
||||
});
|
||||
|
||||
const updateBlock = builder.enter("value", (blockId) => {
|
||||
const updateBlock = builder.enter("loop", (blockId) => {
|
||||
const update = stmt.get("update");
|
||||
if (update.node == null) {
|
||||
builder.errors.push({
|
||||
@@ -342,7 +342,7 @@ function lowerStatement(
|
||||
case "WhileStatement": {
|
||||
const stmt = stmtPath as NodePath<t.WhileStatement>;
|
||||
// Block used to evaluate whether to (re)enter or exit the loop
|
||||
const conditionalBlock = builder.reserve("value");
|
||||
const conditionalBlock = builder.reserve("loop");
|
||||
// Block for code following the loop
|
||||
const continuationBlock = builder.reserve("block");
|
||||
// Loop body
|
||||
@@ -899,7 +899,7 @@ function lowerExpression(
|
||||
const place = buildTemporaryPlace(builder, exprLoc);
|
||||
|
||||
// Block for the consequent (if the test is truthy)
|
||||
const consequentBlock = builder.enter("block", (blockId) => {
|
||||
const consequentBlock = builder.enter("value", (blockId) => {
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
|
||||
@@ -914,7 +914,7 @@ function lowerExpression(
|
||||
};
|
||||
});
|
||||
// Block for the alternate (if the test is not truthy)
|
||||
const alternateBlock = builder.enter("block", (blockId) => {
|
||||
const alternateBlock = builder.enter("value", (blockId) => {
|
||||
builder.push({
|
||||
id: makeInstructionId(0),
|
||||
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
|
||||
@@ -1023,6 +1023,15 @@ function lowerExpression(
|
||||
const expr = exprPath as NodePath<t.AssignmentExpression>;
|
||||
const operator = expr.node.operator;
|
||||
|
||||
if (builder.currentBlockKind() === "value") {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerExpression) Handle AssignmentExpression within a LogicalExpression or ConditionalExpression`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
nodePath: expr,
|
||||
});
|
||||
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
|
||||
}
|
||||
|
||||
if (operator === "=") {
|
||||
const left = expr.get("left");
|
||||
return lowerAssignment(
|
||||
|
||||
@@ -223,7 +223,7 @@ export type HIR = {
|
||||
* an exception occurs, therefore the block model only represents explicit throw
|
||||
* statements and not implicit exceptions which may occur.
|
||||
*/
|
||||
export type BlockKind = "block" | "value";
|
||||
export type BlockKind = "block" | "value" | "loop";
|
||||
export type BasicBlock = {
|
||||
kind: BlockKind;
|
||||
id: BlockId;
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
* (ie ends in a goto) and where the predecessor is the only predecessor
|
||||
* for that successor (ie, there is no other way to reach the successor).
|
||||
*
|
||||
* Note that this pass leaves "value" blocks alone because they cannot
|
||||
* Note that this pass leaves value/loop blocks alone because they cannot
|
||||
* be merged without breaking the structure of the high-level terminals
|
||||
* that reference them.
|
||||
*
|
||||
@@ -32,7 +32,7 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
|
||||
for (const [, block] of fn.body.blocks) {
|
||||
// Can only merge blocks with a single predecessor, can't merge
|
||||
// value blocks
|
||||
if (block.kind === "value" || block.preds.size !== 1) {
|
||||
if (block.kind !== "block" || block.preds.size !== 1) {
|
||||
continue;
|
||||
}
|
||||
const originalPredecessorId = Array.from(block.preds)[0]!;
|
||||
|
||||
@@ -104,7 +104,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
if (block.kind === "value") {
|
||||
if (block.kind !== "block") {
|
||||
// can't rewrite terminals in value blocks yet
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @only
|
||||
// @skip
|
||||
function ternary(props) {
|
||||
let x = 0;
|
||||
const y = props.a ? (x = 1) : (x = 2);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// @skip
|
||||
function foo(props) {
|
||||
let x = 0;
|
||||
while (x > props.min && x < props.max) {
|
||||
x *= 2;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user