From 9697e15bd556dc50e5a6b355765de0bcb270fb3a Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Fri, 20 Jan 2023 11:47:09 -0500 Subject: [PATCH] Collect bailouts in BuildHIR::lowerMemberExpression --- compiler/forget/src/HIR/BuildHIR.ts | 36 ++- .../hir/error.todo-kitchensink.expect.md | 207 +++++++++--------- .../fixtures/hir/error.todo-kitchensink.js | 7 +- 3 files changed, 142 insertions(+), 108 deletions(-) diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 7f8b1b83c4..7059c26495 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -1388,11 +1388,23 @@ function lowerMemberExpression( builder: HIRBuilder, expr: NodePath ): { object: Place; property: Place | string; value: InstructionValue } { - const exprLoc = expr.node.loc ?? GeneratedSource; + const exprNode = expr.node; + const exprLoc = exprNode.loc ?? GeneratedSource; const object = lowerExpressionToPlace(builder, expr.get("object")); const property = expr.get("property"); if (!expr.node.computed) { - todoInvariant(property.isIdentifier(), "Support private names"); + if (!property.isIdentifier()) { + builder.pushError({ + reason: "Support private names", + severity: ErrorSeverity.Todo, + nodePath: property, + }); + return { + object, + property: property.toString(), + value: { kind: "UnsupportedNode", node: exprNode, loc: exprLoc }, + }; + } const value: InstructionValue = { kind: "PropertyLoad", object: { ...object }, @@ -1401,10 +1413,22 @@ function lowerMemberExpression( }; return { object, property: property.node.name, value }; } else { - invariant( - property.isExpression(), - "Expected private names to be non-computed" - ); + if (!property.isExpression()) { + builder.pushError({ + reason: "Expected private names to be non-computed", + severity: ErrorSeverity.InvalidInput, + nodePath: property, + }); + return { + object, + property: property.toString(), + value: { + kind: "UnsupportedNode", + node: exprNode, + loc: exprLoc, + }, + }; + } const propertyPlace = lowerExpressionToPlace(builder, property); const value: InstructionValue = { kind: "ComputedLoad", diff --git a/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.expect.md b/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.expect.md index 0ececd041f..948e5eeff6 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.expect.md @@ -6,7 +6,12 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) { let i = 0; var x = []; - class Bar {} + class Bar { + #secretSauce = 42; + constructor() { + console.log(this.#secretSauce); + } + } with (true) { } @@ -70,158 +75,158 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) { > 3 | var x = []; | ^^^^^^^^^^^ 4 | - 5 | class Bar {} - 6 | + 5 | class Bar { + 6 | #secretSauce = 42; [ReactForget] TodoError: Unhandled statement type: ClassDeclaration 3 | var x = []; 4 | -> 5 | class Bar {} - | ^^^^^^^^^^^^ - 6 | - 7 | with (true) { - 8 | } +> 5 | class Bar { + | ^ + 6 | #secretSauce = 42; + 7 | constructor() { + 8 | console.log(this.#secretSauce); [ReactForget] TodoError: Unhandled statement type: WithStatement - 5 | class Bar {} - 6 | -> 7 | with (true) { + 10 | } + 11 | +> 12 | with (true) { | ^ - 8 | } - 9 | - 10 | const g = { ...a }; + 13 | } + 14 | + 15 | const g = { ...a }; [ReactForget] TodoError: Handle object property spread - 8 | } - 9 | -> 10 | const g = { ...a }; + 13 | } + 14 | +> 15 | const g = { ...a }; | ^^^^ - 11 | const h = [...b]; - 12 | new c(...args); - 13 | c(...args); + 16 | const h = [...b]; + 17 | new c(...args); + 18 | c(...args); [ReactForget] TodoError: Handle non-expression array elements - 9 | - 10 | const g = { ...a }; -> 11 | const h = [...b]; + 14 | + 15 | const g = { ...a }; +> 16 | const h = [...b]; | ^^^^ - 12 | new c(...args); - 13 | c(...args); - 14 | g["e"] += 1; + 17 | new c(...args); + 18 | c(...args); + 19 | g["e"] += 1; [ReactForget] TodoError: Support non-expression arguments to NewExpression - 10 | const g = { ...a }; - 11 | const h = [...b]; -> 12 | new c(...args); + 15 | const g = { ...a }; + 16 | const h = [...b]; +> 17 | new c(...args); | ^^^^^^^ - 13 | c(...args); - 14 | g["e"] += 1; - 15 | + 18 | c(...args); + 19 | g["e"] += 1; + 20 | [ReactForget] TodoError: Support non-expression arguments to CallExpression - 11 | const h = [...b]; - 12 | new c(...args); -> 13 | c(...args); + 16 | const h = [...b]; + 17 | new c(...args); +> 18 | c(...args); | ^^^^^^^ - 14 | g["e"] += 1; - 15 | - 16 | ; + 19 | g["e"] += 1; + 20 | + 21 | ; [ReactForget] TodoError: Assignment expression to dynamic properties is not yet supported - 12 | new c(...args); - 13 | c(...args); -> 14 | g["e"] += 1; + 17 | new c(...args); + 18 | c(...args); +> 19 | g["e"] += 1; | ^^^ - 15 | - 16 | ; - 17 | ; + 20 | + 21 | ; + 22 | ; [ReactForget] TodoError: Handle spread attributes - 14 | g["e"] += 1; - 15 | -> 16 | ; + 19 | g["e"] += 1; + 20 | +> 21 | ; | ^^^^^^^^^ - 17 | ; - 18 | ; - 19 | + 22 | ; + 23 | ; + 24 | [ReactForget] TodoError: Handle non-identifier jsx attribute names - 15 | - 16 | ; -> 17 | ; + 20 | + 21 | ; +> 22 | ; | ^^^^^^^^^^ - 18 | ; - 19 | - 20 | const j = function bar([quz, qux], ...args) {}; + 23 | ; + 24 | + 25 | const j = function bar([quz, qux], ...args) {}; [ReactForget] TodoError: Handle non identifier params - 18 | ; - 19 | -> 20 | const j = function bar([quz, qux], ...args) {}; + 23 | ; + 24 | +> 25 | const j = function bar([quz, qux], ...args) {}; | ^^^^^^^^^^ - 21 | - 22 | for (; i < 3; i += 1) { - 23 | x.push(i); + 26 | + 27 | for (; i < 3; i += 1) { + 28 | x.push(i); [ReactForget] TodoError: Handle non identifier params - 18 | ; - 19 | -> 20 | const j = function bar([quz, qux], ...args) {}; + 23 | ; + 24 | +> 25 | const j = function bar([quz, qux], ...args) {}; | ^^^^^^^ - 21 | - 22 | for (; i < 3; i += 1) { - 23 | x.push(i); + 26 | + 27 | for (; i < 3; i += 1) { + 28 | x.push(i); [ReactForget] TodoError: Support non-variable initialization in for - 20 | const j = function bar([quz, qux], ...args) {}; - 21 | -> 22 | for (; i < 3; i += 1) { + 25 | const j = function bar([quz, qux], ...args) {}; + 26 | +> 27 | for (; i < 3; i += 1) { | ^ - 23 | x.push(i); - 24 | } - 25 | for (; i < 3; ) {} + 28 | x.push(i); + 29 | } + 30 | for (; i < 3; ) {} [ReactForget] TodoError: Support non-variable initialization in for - 23 | x.push(i); - 24 | } -> 25 | for (; i < 3; ) {} + 28 | x.push(i); + 29 | } +> 30 | for (; i < 3; ) {} | ^^^^^^^^^^^^^^^^^^ - 26 | for (;;) {} - 27 | } - 28 | + 31 | for (;;) {} + 32 | } + 33 | [ReactForget] TodoError: Handle empty for updater - 23 | x.push(i); - 24 | } -> 25 | for (; i < 3; ) {} + 28 | x.push(i); + 29 | } +> 30 | for (; i < 3; ) {} | ^^^^^^^^^^^^^^^^^^ - 26 | for (;;) {} - 27 | } - 28 | + 31 | for (;;) {} + 32 | } + 33 | [ReactForget] TodoError: Support non-variable initialization in for - 24 | } - 25 | for (; i < 3; ) {} -> 26 | for (;;) {} + 29 | } + 30 | for (; i < 3; ) {} +> 31 | for (;;) {} | ^^^^^^^^^^^ - 27 | } - 28 | + 32 | } + 33 | [ReactForget] TodoError: Handle empty for updater - 24 | } - 25 | for (; i < 3; ) {} -> 26 | for (;;) {} + 29 | } + 30 | for (; i < 3; ) {} +> 31 | for (;;) {} | ^^^^^^^^^^^ - 27 | } - 28 | + 32 | } + 33 | [ReactForget] TodoError: ForStatement without test - 24 | } - 25 | for (; i < 3; ) {} -> 26 | for (;;) {} + 29 | } + 30 | for (; i < 3; ) {} +> 31 | for (;;) {} | ^^^^^^^^^^^ - 27 | } - 28 | + 32 | } + 33 | ``` \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.js b/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.js index 8a2b88e4c7..26e8fc5c25 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.js +++ b/compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.js @@ -2,7 +2,12 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) { let i = 0; var x = []; - class Bar {} + class Bar { + #secretSauce = 42; + constructor() { + console.log(this.#secretSauce); + } + } with (true) { }