mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Add support for DoWhile statements
Adds support for DoWhileStatements. It's pretty similar to how we handle While, except in the case where a test block is unreachable (for example, an early unconditional `break` within the loop body). In this scenario we eliminate the terminal altogether and replace it with a goto to the loop block.
This commit is contained in:
@@ -644,9 +644,61 @@ function lowerStatement(
|
||||
});
|
||||
return;
|
||||
}
|
||||
case "DoWhileStatement": {
|
||||
const stmt = stmtPath as NodePath<t.DoWhileStatement>;
|
||||
// Block used to evaluate whether to (re)enter or exit the loop
|
||||
const conditionalBlock = builder.reserve("loop");
|
||||
// Block for code following the loop
|
||||
const continuationBlock = builder.reserve("block");
|
||||
// Loop body, executed at least once uncondtionally prior to exit
|
||||
const loopBlock = builder.enter("block", (_loopBlockId) => {
|
||||
return builder.loop(
|
||||
label,
|
||||
conditionalBlock.id,
|
||||
continuationBlock.id,
|
||||
() => {
|
||||
lowerStatement(builder, stmt.get("body"));
|
||||
return {
|
||||
kind: "goto",
|
||||
block: conditionalBlock.id,
|
||||
variant: GotoVariant.Continue,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
// Jump to the conditional block to evaluate whether to (re)enter the loop or exit to the
|
||||
// continuation block.
|
||||
const loc = stmt.node.loc ?? GeneratedSource;
|
||||
builder.terminateWithContinuation(
|
||||
{
|
||||
kind: "do-while",
|
||||
loc,
|
||||
test: conditionalBlock.id,
|
||||
loop: loopBlock,
|
||||
fallthrough: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
},
|
||||
conditionalBlock
|
||||
);
|
||||
/**
|
||||
* The conditional block is empty and exists solely as conditional for
|
||||
* (re)entering or exiting the loop
|
||||
*/
|
||||
const test = lowerExpressionToTemporary(builder, stmt.get("test"));
|
||||
const terminal: BranchTerminal = {
|
||||
kind: "branch",
|
||||
test,
|
||||
consequent: loopBlock,
|
||||
alternate: continuationBlock.id,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
// Complete the conditional and continue with code after the loop
|
||||
builder.terminateWithContinuation(terminal, continuationBlock);
|
||||
return;
|
||||
}
|
||||
case "ForOfStatement":
|
||||
case "ForInStatement":
|
||||
case "DoWhileStatement":
|
||||
case "ClassDeclaration":
|
||||
case "DebuggerStatement":
|
||||
case "DeclareClass":
|
||||
|
||||
@@ -122,6 +122,7 @@ export type ReactiveTerminal =
|
||||
| ReactiveReturnTerminal
|
||||
| ReactiveThrowTerminal
|
||||
| ReactiveSwitchTerminal
|
||||
| ReactiveDoWhileTerminal
|
||||
| ReactiveWhileTerminal
|
||||
| ReactiveForTerminal
|
||||
| ReactiveIfTerminal;
|
||||
@@ -157,6 +158,12 @@ export type ReactiveSwitchTerminal = {
|
||||
}>;
|
||||
id: InstructionId;
|
||||
};
|
||||
export type ReactiveDoWhileTerminal = {
|
||||
kind: "do-while";
|
||||
loop: ReactiveBlock;
|
||||
test: ReactiveValue;
|
||||
id: InstructionId;
|
||||
};
|
||||
export type ReactiveWhileTerminal = {
|
||||
kind: "while";
|
||||
test: ReactiveValue;
|
||||
@@ -241,6 +248,7 @@ export type Terminal =
|
||||
| BranchTerminal
|
||||
| SwitchTerminal
|
||||
| ForTerminal
|
||||
| DoWhileTerminal
|
||||
| WhileTerminal
|
||||
| LogicalTerminal
|
||||
| TernaryTerminal;
|
||||
@@ -298,6 +306,15 @@ export type SwitchTerminal = {
|
||||
id: InstructionId;
|
||||
};
|
||||
|
||||
export type DoWhileTerminal = {
|
||||
kind: "do-while";
|
||||
loop: BlockId;
|
||||
test: BlockId;
|
||||
fallthrough: BlockId;
|
||||
id: InstructionId;
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
export type WhileTerminal = {
|
||||
kind: "while";
|
||||
loc: SourceLocation;
|
||||
|
||||
@@ -264,6 +264,7 @@ export default class HIRBuilder {
|
||||
// then convert to reverse postorder
|
||||
reversePostorderBlocks(ir);
|
||||
removeUnreachableFallthroughs(ir);
|
||||
removeDeadDoWhileStatements(ir);
|
||||
markInstructionIds(ir);
|
||||
markPredecessors(ir);
|
||||
|
||||
@@ -530,6 +531,30 @@ export function removeUnreachableFallthroughs(func: HIR): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function removeDeadDoWhileStatements(func: HIR): void {
|
||||
const visited: Set<BlockId> = new Set();
|
||||
for (const [_, block] of func.blocks) {
|
||||
visited.add(block.id);
|
||||
}
|
||||
|
||||
// If the test condition of a DoWhile is unreachable, the terminal is effectively deadcode and we
|
||||
// can just inline the loop body. We replace the terminal with a goto to the loop block and
|
||||
// MergeConsecutiveBlocks figures out how to merge as appropriate.
|
||||
for (const [_, block] of func.blocks) {
|
||||
if (block.terminal.kind === "do-while") {
|
||||
if (!visited.has(block.terminal.test)) {
|
||||
block.terminal = {
|
||||
kind: "goto",
|
||||
block: block.terminal.loop,
|
||||
variant: GotoVariant.Break,
|
||||
id: block.terminal.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the graph to reverse-postorder, with predecessor blocks appearing
|
||||
* before successors except in the case of back links (ie loops).
|
||||
@@ -604,6 +629,10 @@ export function reversePostorderBlocks(func: HIR): void {
|
||||
visit(terminal.test);
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
visit(terminal.loop);
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
visit(terminal.test);
|
||||
break;
|
||||
|
||||
@@ -87,7 +87,8 @@ export function printMixedHIR(
|
||||
case "while":
|
||||
case "for":
|
||||
case "unsupported":
|
||||
case "goto": {
|
||||
case "goto":
|
||||
case "do-while": {
|
||||
const terminal = printTerminal(value);
|
||||
if (Array.isArray(terminal)) {
|
||||
return terminal.join("; ");
|
||||
@@ -184,6 +185,12 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
|
||||
value = output;
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
value = `[${terminal.id}] DoWhile loop=${`bb${terminal.loop}`} test=bb${
|
||||
terminal.test
|
||||
} fallthrough=${`bb${terminal.fallthrough}`}`;
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
value = `[${terminal.id}] While test=bb${terminal.test} loop=${
|
||||
terminal.loop !== null ? `bb${terminal.loop}` : ""
|
||||
|
||||
@@ -366,6 +366,19 @@ export function mapTerminalSuccessors(
|
||||
case "throw": {
|
||||
return terminal;
|
||||
}
|
||||
case "do-while": {
|
||||
const loop = fn(terminal.loop);
|
||||
const test = fn(terminal.test);
|
||||
const fallthrough = fn(terminal.fallthrough);
|
||||
return {
|
||||
kind: "do-while",
|
||||
loc: terminal.loc,
|
||||
test,
|
||||
loop,
|
||||
fallthrough,
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
}
|
||||
case "while": {
|
||||
const test = fn(terminal.test);
|
||||
const loop = fn(terminal.loop);
|
||||
@@ -446,6 +459,10 @@ export function* eachTerminalSuccessor(terminal: Terminal): Iterable<BlockId> {
|
||||
case "throw": {
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
yield terminal.loop;
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
yield terminal.test;
|
||||
break;
|
||||
@@ -497,6 +514,7 @@ export function mapTerminalOperands(
|
||||
}
|
||||
case "ternary":
|
||||
case "logical":
|
||||
case "do-while":
|
||||
case "while":
|
||||
case "for":
|
||||
case "goto":
|
||||
@@ -542,6 +560,7 @@ export function* eachTerminalOperand(terminal: Terminal): Iterable<Place> {
|
||||
}
|
||||
case "ternary":
|
||||
case "logical":
|
||||
case "do-while":
|
||||
case "while":
|
||||
case "for":
|
||||
case "goto":
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
reversePostorderBlocks,
|
||||
shrink,
|
||||
} from "../HIR";
|
||||
import { removeDeadDoWhileStatements } from "../HIR/HIRBuilder";
|
||||
import { eliminateRedundantPhi } from "../SSA";
|
||||
|
||||
/**
|
||||
@@ -49,6 +50,7 @@ export function constantPropagation(fn: HIRFunction): void {
|
||||
shrink(fn.body);
|
||||
reversePostorderBlocks(fn.body);
|
||||
removeUnreachableFallthroughs(fn.body);
|
||||
removeDeadDoWhileStatements(fn.body);
|
||||
markInstructionIds(fn.body);
|
||||
markPredecessors(fn.body);
|
||||
|
||||
|
||||
@@ -231,6 +231,55 @@ class Driver {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
const fallthroughId = !this.cx.isScheduled(terminal.fallthrough)
|
||||
? terminal.fallthrough
|
||||
: null;
|
||||
const loopId =
|
||||
!this.cx.isScheduled(terminal.loop) &&
|
||||
terminal.loop !== terminal.fallthrough
|
||||
? terminal.loop
|
||||
: null;
|
||||
const scheduleId = this.cx.scheduleLoop(
|
||||
terminal.fallthrough,
|
||||
terminal.test,
|
||||
terminal.loop
|
||||
);
|
||||
scheduleIds.push(scheduleId);
|
||||
|
||||
let loopBody: ReactiveBlock;
|
||||
if (loopId) {
|
||||
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
|
||||
} else {
|
||||
const break_ = this.visitBreak(terminal.loop, null);
|
||||
invariant(
|
||||
break_ !== null,
|
||||
"If loop body is already scheduled it must be a break"
|
||||
);
|
||||
loopBody = [break_];
|
||||
}
|
||||
|
||||
const testValue = this.visitValueBlock(
|
||||
terminal.test,
|
||||
terminal.loc
|
||||
).value;
|
||||
|
||||
this.cx.unscheduleAll(scheduleIds);
|
||||
blockValue.push({
|
||||
kind: "terminal",
|
||||
terminal: {
|
||||
kind: "do-while",
|
||||
test: testValue,
|
||||
loop: loopBody,
|
||||
id: terminal.id,
|
||||
},
|
||||
label: fallthroughId,
|
||||
});
|
||||
if (fallthroughId !== null) {
|
||||
this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
const fallthroughId =
|
||||
terminal.fallthrough !== null &&
|
||||
|
||||
@@ -340,6 +340,10 @@ function codegenTerminal(
|
||||
case "throw": {
|
||||
return t.throwStatement(codegenPlace(cx, terminal.value));
|
||||
}
|
||||
case "do-while": {
|
||||
const test = codegenInstructionValue(cx, terminal.test);
|
||||
return t.doWhileStatement(test, codegenBlock(cx, terminal.loop));
|
||||
}
|
||||
case "while": {
|
||||
const test = codegenInstructionValue(cx, terminal.test);
|
||||
return t.whileStatement(test, codegenBlock(cx, terminal.loop));
|
||||
|
||||
@@ -46,6 +46,7 @@ class Transform extends ReactiveFunctionTransform<boolean> {
|
||||
): void {
|
||||
switch (stmt.terminal.kind) {
|
||||
// Loop terminals flatten nested scopes
|
||||
case "do-while":
|
||||
case "while":
|
||||
case "for": {
|
||||
this.traverseTerminal(stmt, true);
|
||||
|
||||
@@ -578,6 +578,11 @@ function visit(context: Context, block: ReactiveBlock): void {
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
visit(context, terminal.loop);
|
||||
visitReactiveValue(context, terminal.test);
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
visitReactiveValue(context, terminal.test);
|
||||
context.enterConditional(() => {
|
||||
|
||||
@@ -106,6 +106,11 @@ export class ReactiveFunctionVisitor<TState = void> {
|
||||
this.visitBlock(terminal.loop, state);
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
this.visitBlock(terminal.loop, state);
|
||||
this.visitValue(terminal.id, terminal.test, state);
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
this.visitValue(terminal.id, terminal.test, state);
|
||||
this.visitBlock(terminal.loop, state);
|
||||
@@ -309,6 +314,7 @@ export function mapTerminalBlocks(
|
||||
terminal.loop = fn(terminal.loop);
|
||||
break;
|
||||
}
|
||||
case "do-while":
|
||||
case "while": {
|
||||
terminal.loop = fn(terminal.loop);
|
||||
break;
|
||||
|
||||
@@ -107,6 +107,10 @@ function printTerminalLabel(terminal: Terminal): string {
|
||||
buffer.push("Ternary");
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
buffer.push("DoWhile");
|
||||
break;
|
||||
}
|
||||
case "while":
|
||||
buffer.push("While");
|
||||
break;
|
||||
@@ -174,6 +178,12 @@ function printTerminalArrows(blockId: BlockId, terminal: Terminal): string {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "do-while": {
|
||||
buffer.push(printJumpArrow(blockId, terminal.loop, "loop"));
|
||||
buffer.push(printJumpArrow(blockId, terminal.test, "test"));
|
||||
buffer.push(printJumpArrow(blockId, terminal.fallthrough, "fallthrough"));
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
buffer.push(printJumpArrow(blockId, terminal.test, "test"));
|
||||
buffer.push(printJumpArrow(blockId, terminal.loop, "loop"));
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
do {
|
||||
break;
|
||||
} while (props.cond);
|
||||
return props;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
return props;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
function Component(props) {
|
||||
do {
|
||||
break;
|
||||
} while (props.cond);
|
||||
return props;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
let x = [1, 2, 3];
|
||||
let ret = [];
|
||||
do {
|
||||
let item = x.pop();
|
||||
ret.push(item * 2);
|
||||
} while (x.length && props.cond);
|
||||
return ret;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props;
|
||||
let ret;
|
||||
if (c_0) {
|
||||
const x = [1, 2, 3];
|
||||
ret = [];
|
||||
do {
|
||||
const item = x.pop();
|
||||
ret.push(item * 2);
|
||||
} while (x.length && props.cond);
|
||||
$[0] = props;
|
||||
$[1] = ret;
|
||||
} else {
|
||||
ret = $[1];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
function Component(props) {
|
||||
let x = [1, 2, 3];
|
||||
let ret = [];
|
||||
do {
|
||||
let item = x.pop();
|
||||
ret.push(item * 2);
|
||||
} while (x.length && props.cond);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
let x = [0, 1, 2, 3];
|
||||
do {
|
||||
if (x === 0) {
|
||||
break;
|
||||
}
|
||||
mutate(x);
|
||||
} while (props.cond);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(2);
|
||||
const c_0 = $[0] !== props.cond;
|
||||
let x;
|
||||
if (c_0) {
|
||||
x = [0, 1, 2, 3];
|
||||
do {
|
||||
if (x === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
mutate(x);
|
||||
} while (props.cond);
|
||||
$[0] = props.cond;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function Component(props) {
|
||||
let x = [0, 1, 2, 3];
|
||||
do {
|
||||
if (x === 0) {
|
||||
break;
|
||||
}
|
||||
mutate(x);
|
||||
} while (props.cond);
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
const x = [0, 1, 2, 3];
|
||||
const ret = [];
|
||||
do {
|
||||
const item = x.pop();
|
||||
if (item === 0) {
|
||||
continue;
|
||||
}
|
||||
ret.push(item / 2);
|
||||
} while (x.length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let ret;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
const x = [0, 1, 2, 3];
|
||||
ret = [];
|
||||
do {
|
||||
const item = x.pop();
|
||||
if (item === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.push(item / 2);
|
||||
} while (x.length);
|
||||
$[0] = ret;
|
||||
} else {
|
||||
ret = $[0];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
function Component() {
|
||||
const x = [0, 1, 2, 3];
|
||||
const ret = [];
|
||||
do {
|
||||
const item = x.pop();
|
||||
if (item === 0) {
|
||||
continue;
|
||||
}
|
||||
ret.push(item / 2);
|
||||
} while (x.length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
let x = [1, 2, 3];
|
||||
do {
|
||||
mutate(x);
|
||||
break;
|
||||
} while (props.cond);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = [1, 2, 3];
|
||||
|
||||
mutate(x);
|
||||
$[0] = x;
|
||||
} else {
|
||||
x = $[0];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
function Component(props) {
|
||||
let x = [1, 2, 3];
|
||||
do {
|
||||
mutate(x);
|
||||
break;
|
||||
} while (props.cond);
|
||||
return x;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
let x = [1, 2, 3];
|
||||
let ret = [];
|
||||
do {
|
||||
let item = x.pop();
|
||||
ret.push(item * 2);
|
||||
} while (x.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
let ret;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
const x = [1, 2, 3];
|
||||
ret = [];
|
||||
do {
|
||||
const item = x.pop();
|
||||
ret.push(item * 2);
|
||||
} while (x.length);
|
||||
$[0] = ret;
|
||||
} else {
|
||||
ret = $[0];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
function Component() {
|
||||
let x = [1, 2, 3];
|
||||
let ret = [];
|
||||
do {
|
||||
let item = x.pop();
|
||||
ret.push(item * 2);
|
||||
} while (x.length);
|
||||
return ret;
|
||||
}
|
||||
@@ -50,8 +50,6 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
|
||||
for (let x in { a: 1 }) {
|
||||
}
|
||||
|
||||
do {} while (i < 3);
|
||||
|
||||
let updateIdentifier = 0;
|
||||
--updateIdentifier;
|
||||
++updateIdentifier;
|
||||
@@ -333,97 +331,88 @@ let moduleLocal = false;
|
||||
| ^
|
||||
47 | }
|
||||
48 |
|
||||
49 | do {} while (i < 3);
|
||||
49 | let updateIdentifier = 0;
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle DoWhileStatement statements
|
||||
47 | }
|
||||
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle prefix UpdateExpression
|
||||
48 |
|
||||
> 49 | do {} while (i < 3);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
50 |
|
||||
51 | let updateIdentifier = 0;
|
||||
52 | --updateIdentifier;
|
||||
49 | let updateIdentifier = 0;
|
||||
> 50 | --updateIdentifier;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
51 | ++updateIdentifier;
|
||||
52 | updateIdentifier.y++;
|
||||
53 | updateIdentifier.y--;
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle prefix UpdateExpression
|
||||
50 |
|
||||
51 | let updateIdentifier = 0;
|
||||
> 52 | --updateIdentifier;
|
||||
49 | let updateIdentifier = 0;
|
||||
50 | --updateIdentifier;
|
||||
> 51 | ++updateIdentifier;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
53 | ++updateIdentifier;
|
||||
54 | updateIdentifier.y++;
|
||||
55 | updateIdentifier.y--;
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle prefix UpdateExpression
|
||||
51 | let updateIdentifier = 0;
|
||||
52 | --updateIdentifier;
|
||||
> 53 | ++updateIdentifier;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
54 | updateIdentifier.y++;
|
||||
55 | updateIdentifier.y--;
|
||||
56 |
|
||||
52 | updateIdentifier.y++;
|
||||
53 | updateIdentifier.y--;
|
||||
54 |
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument
|
||||
52 | --updateIdentifier;
|
||||
53 | ++updateIdentifier;
|
||||
> 54 | updateIdentifier.y++;
|
||||
50 | --updateIdentifier;
|
||||
51 | ++updateIdentifier;
|
||||
> 52 | updateIdentifier.y++;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
55 | updateIdentifier.y--;
|
||||
56 |
|
||||
57 | switch (i) {
|
||||
53 | updateIdentifier.y--;
|
||||
54 |
|
||||
55 | switch (i) {
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument
|
||||
53 | ++updateIdentifier;
|
||||
54 | updateIdentifier.y++;
|
||||
> 55 | updateIdentifier.y--;
|
||||
51 | ++updateIdentifier;
|
||||
52 | updateIdentifier.y++;
|
||||
> 53 | updateIdentifier.y--;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
56 |
|
||||
57 | switch (i) {
|
||||
58 | case 1 + 1: {
|
||||
54 |
|
||||
55 | switch (i) {
|
||||
56 | case 1 + 1: {
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported
|
||||
60 | case foo(): {
|
||||
61 | }
|
||||
> 62 | case x.y: {
|
||||
58 | case foo(): {
|
||||
59 | }
|
||||
> 60 | case x.y: {
|
||||
| ^^^
|
||||
63 | }
|
||||
64 | default: {
|
||||
65 | }
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported
|
||||
58 | case 1 + 1: {
|
||||
59 | }
|
||||
> 60 | case foo(): {
|
||||
| ^^^^^
|
||||
61 | }
|
||||
62 | case x.y: {
|
||||
62 | default: {
|
||||
63 | }
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported
|
||||
56 |
|
||||
57 | switch (i) {
|
||||
> 58 | case 1 + 1: {
|
||||
56 | case 1 + 1: {
|
||||
57 | }
|
||||
> 58 | case foo(): {
|
||||
| ^^^^^
|
||||
59 | }
|
||||
60 | case foo(): {
|
||||
60 | case x.y: {
|
||||
61 | }
|
||||
|
||||
[ReactForget] TodoError: (BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported
|
||||
54 |
|
||||
55 | switch (i) {
|
||||
> 56 | case 1 + 1: {
|
||||
| ^^^^^
|
||||
57 | }
|
||||
58 | case foo(): {
|
||||
59 | }
|
||||
|
||||
[ReactForget] InvalidInputError: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported.
|
||||
67 |
|
||||
68 | // Cannot assign to globals
|
||||
> 69 | someUnknownGlobal = true;
|
||||
65 |
|
||||
66 | // Cannot assign to globals
|
||||
> 67 | someUnknownGlobal = true;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
70 | moduleLocal = true;
|
||||
71 | }
|
||||
72 |
|
||||
68 | moduleLocal = true;
|
||||
69 | }
|
||||
70 |
|
||||
|
||||
[ReactForget] InvalidInputError: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported.
|
||||
68 | // Cannot assign to globals
|
||||
69 | someUnknownGlobal = true;
|
||||
> 70 | moduleLocal = true;
|
||||
66 | // Cannot assign to globals
|
||||
67 | someUnknownGlobal = true;
|
||||
> 68 | moduleLocal = true;
|
||||
| ^^^^^^^^^^^
|
||||
71 | }
|
||||
72 |
|
||||
73 | let moduleLocal = false;
|
||||
69 | }
|
||||
70 |
|
||||
71 | let moduleLocal = false;
|
||||
```
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
|
||||
for (let x in { a: 1 }) {
|
||||
}
|
||||
|
||||
do {} while (i < 3);
|
||||
|
||||
let updateIdentifier = 0;
|
||||
--updateIdentifier;
|
||||
++updateIdentifier;
|
||||
|
||||
Reference in New Issue
Block a user