The library for web and native user interfaces.
Use CompilerError.invariant consistently
This PR updates all current usages of invariant to CompilerError.invariant along with any available locs
Lauren Tan committed
Jun 22, 2023 at 10:18 UTC
e7e67f335adea5a24ff59a467b22b92702350a5e
25 files changed
+313
-202
compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+27
-18
@@ -8,7 +8,6 @@
8
import { NodePath, Scope } from "@babel/traverse";
9
import * as t from "@babel/types";
10
import { Expression } from "@babel/types";
11
-import invariant from "invariant";
11
import { CompilerError, ErrorSeverity } from "../CompilerError";
12
import { Err, Ok, Result } from "../Utils/Result";
13
import { assertExhaustive } from "../Utils/utils";
@@ -769,9 +768,10 @@ function lowerStatement(
768
case "FunctionDeclaration": {
769
const stmt = stmtPath as NodePath<t.FunctionDeclaration>;
770
stmt.skip();
772
- invariant(
771
+ CompilerError.invariant(
772
stmt.get("id").type === "Identifier",
774
- "function declarations must have a name"
773
+ "function declarations must have a name",
774
+ stmt.node.loc ?? null
775
);
776
const id = stmt.get("id") as NodePath<t.Identifier>;
777
@@ -795,9 +795,10 @@ function lowerStatement(
795
),
796
])
797
);
798
- invariant(
798
+ CompilerError.invariant(
799
desugared.length === 1,
800
- "only one declaration is created from desugaring function declaration"
800
+ "only one declaration is created from desugaring function declaration",
801
+ stmt.node.loc ?? null
802
);
803
lowerStatement(builder, desugared.at(0)!);
804
return;
@@ -843,9 +844,10 @@ function lowerStatement(
844
let test: Place;
845
if (left.isVariableDeclaration()) {
846
const declarations = left.get("declarations");
846
- invariant(
847
+ CompilerError.invariant(
848
declarations.length === 1,
848
- `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`
849
+ `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`,
850
+ left.node.loc ?? null
851
);
852
const id = declarations[0].get("id");
853
const nextIterableOf = lowerValueToTemporary(builder, {
@@ -1517,7 +1519,11 @@ function lowerExpression(
1519
});
1520
}
1521
} else {
1520
- invariant(namePath.isJSXNamespacedName(), "Refinement");
1522
+ CompilerError.invariant(
1523
+ namePath.isJSXNamespacedName(),
1524
+ "Refinement",
1525
+ namePath.node.loc ?? null
1526
+ );
1527
const namespace = namePath.node.namespace.name;
1528
const name = namePath.node.name.name;
1529
propName = `${namespace}:${name}`;
@@ -1586,9 +1592,10 @@ function lowerExpression(
1592
});
1593
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
1594
}
1589
- invariant(
1595
+ CompilerError.invariant(
1596
expr.get("quasi").get("quasis").length == 1,
1591
- "there should be only one quasi as we don't support interpolations yet"
1597
+ "there should be only one quasi as we don't support interpolations yet",
1598
+ expr.node.loc ?? null
1599
);
1600
const value = expr.get("quasi").get("quasis").at(0)!.node.value;
1601
if (value.raw !== value.cooked) {
@@ -1836,7 +1843,7 @@ function lowerOptionalMemberExpression(
1843
loc,
1844
};
1845
});
1839
- invariant(object !== null, "Satisfy type checker");
1846
+ CompilerError.invariant(object !== null, "Satisfy type checker", null);
1847
1848
// block to evaluate if the callee is non-null/undefined. arguments are lowered in this block to preserve
1849
// the semantic of conditional evaluation depending on the callee
@@ -2268,10 +2275,10 @@ function lowerJsxMemberExpression(
2275
if (object.isJSXMemberExpression()) {
2276
objectPlace = lowerJsxMemberExpression(builder, object);
2277
} else {
2271
- invariant(
2278
+ CompilerError.invariant(
2279
object.isJSXIdentifier(),
2273
- "TypeScript refinement fail: expected 'JsxIdentifier', got '%s'",
2274
- object.node.type
2280
+ `TypeScript refinement fail: expected 'JsxIdentifier', got '${object.node.type}'`,
2281
+ object.node.loc ?? null
2282
);
2283
objectPlace = lowerIdentifier(builder, object);
2284
}
@@ -2303,9 +2310,10 @@ function lowerJsxElement(
2310
if (expression.isJSXEmptyExpression()) {
2311
return null;
2312
} else {
2306
- invariant(
2313
+ CompilerError.invariant(
2314
expression.isExpression(),
2308
- `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`
2315
+ `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`,
2316
+ expression.node.loc ?? null
2317
);
2318
return lowerExpressionToTemporary(builder, expression);
2319
}
@@ -2554,9 +2562,10 @@ function lowerAssignment(
2562
}
2563
case "MemberExpression": {
2564
// This can only occur because of a coding error, parsers enforce this condition
2557
- invariant(
2565
+ CompilerError.invariant(
2566
kind === InstructionKind.Reassign,
2559
- "MemberExpression may only appear in an assignment expression"
2567
+ "MemberExpression may only appear in an assignment expression",
2568
+ lvaluePath.node.loc ?? null
2569
);
2570
const lvalue = lvaluePath as NodePath<t.MemberExpression>;
2571
const property = lvalue.get("property");
compiler/forget/packages/babel-plugin-react-forget/src/HIR/Dominator.ts
+6
-5
@@ -5,8 +5,8 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
import prettyFormat from "pretty-format";
9
+import { CompilerError } from "../CompilerError";
10
import { BlockId, HIRFunction } from "./HIR";
11
import { eachTerminalSuccessor } from "./visitors";
12
@@ -88,7 +88,7 @@ export class Dominator<T> {
88
*/
89
get(id: T): T | null {
90
const dominator = this.#nodes.get(id);
91
- invariant(dominator !== undefined, "Unknown node");
91
+ CompilerError.invariant(dominator !== undefined, "Unknown node", null);
92
return dominator === id ? null : dominator;
93
}
94
@@ -119,7 +119,7 @@ export class PostDominator<T> {
119
*/
120
get(id: T): T | null {
121
const dominator = this.#nodes.get(id);
122
- invariant(dominator !== undefined, "Unknown node");
122
+ CompilerError.invariant(dominator !== undefined, "Unknown node", null);
123
return dominator === id ? null : dominator;
124
}
125
@@ -159,9 +159,10 @@ function computeImmediateDominators<T>(graph: Graph<T>): Map<T, T> {
159
break;
160
}
161
}
162
- invariant(
162
+ CompilerError.invariant(
163
newIdom !== null,
164
- `At least one predecessor must have been visited for block ${id}`
164
+ `At least one predecessor must have been visited for block ${id}`,
165
+ null
166
);
167
168
for (const pred of node.preds) {
compiler/forget/packages/babel-plugin-react-forget/src/HIR/Environment.ts
+10
-7
@@ -6,7 +6,7 @@
6
*/
7
8
import * as t from "@babel/types";
9
-import invariant from "invariant";
9
+import { CompilerError } from "../CompilerError";
10
import { ExternalFunction } from "../Entrypoint/Options";
11
import { log } from "../Utils/logger";
12
import {
@@ -195,9 +195,10 @@ export class Environment {
195
if (config?.customHooks) {
196
this.#globals = new Map(DEFAULT_GLOBALS);
197
for (const [hookName, hook] of config.customHooks) {
198
- invariant(
198
+ CompilerError.invariant(
199
!this.#globals.has(hookName),
200
- `[Globals] Found existing definition in global registry for custom hook ${hookName}`
200
+ `[Globals] Found existing definition in global registry for custom hook ${hookName}`,
201
+ null
202
);
203
this.#globals.set(
204
hookName,
@@ -270,9 +271,10 @@ export class Environment {
271
// If an object or function has a shapeId, it must have been assigned
272
// by Forget (and be present in a builtin or user-defined registry)
273
const shape = this.#shapes.get(shapeId);
273
- invariant(
274
+ CompilerError.invariant(
275
shape !== undefined,
275
- `[HIR] Forget internal error: cannot resolve shape ${shapeId}`
276
+ `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,
277
+ null
278
);
279
return shape.properties.get(property) ?? null;
280
} else {
@@ -284,9 +286,10 @@ export class Environment {
286
const { shapeId } = type;
287
if (shapeId !== null) {
288
const shape = this.#shapes.get(shapeId);
287
- invariant(
289
+ CompilerError.invariant(
290
shape !== undefined,
289
- `[HIR] Forget internal error: cannot resolve shape ${shapeId}`
291
+ `[HIR] Forget internal error: cannot resolve shape ${shapeId}`,
292
+ null
293
);
294
return shape.functionType;
295
}
compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIR.ts
+12
-9
@@ -6,7 +6,6 @@
6
*/
7
8
import * as t from "@babel/types";
9
-import invariant from "invariant";
9
import { CompilerError } from "../CompilerError";
10
import { assertExhaustive } from "../Utils/utils";
11
import { Environment } from "./Environment";
@@ -922,9 +921,10 @@ const opaqueBlockId = Symbol();
921
export type BlockId = number & { [opaqueBlockId]: "BlockId" };
922
923
export function makeBlockId(id: number): BlockId {
925
- invariant(
924
+ CompilerError.invariant(
925
id >= 0 && Number.isInteger(id),
927
- "Expected block id to be a non-negative integer"
926
+ "Expected block id to be a non-negative integer",
927
+ null
928
);
929
return id as BlockId;
930
}
@@ -937,9 +937,10 @@ const opaqueScopeId = Symbol();
937
export type ScopeId = number & { [opaqueScopeId]: "ScopeId" };
938
939
export function makeScopeId(id: number): ScopeId {
940
- invariant(
940
+ CompilerError.invariant(
941
id >= 0 && Number.isInteger(id),
942
- "Expected block id to be a non-negative integer"
942
+ "Expected block id to be a non-negative integer",
943
+ null
944
);
945
return id as ScopeId;
946
}
@@ -952,9 +953,10 @@ const opaqueIdentifierId = Symbol();
953
export type IdentifierId = number & { [opaqueIdentifierId]: "IdentifierId" };
954
955
export function makeIdentifierId(id: number): IdentifierId {
955
- invariant(
956
+ CompilerError.invariant(
957
id >= 0 && Number.isInteger(id),
957
- "Expected identifier id to be a non-negative integer"
958
+ "Expected identifier id to be a non-negative integer",
959
+ null
960
);
961
return id as IdentifierId;
962
}
@@ -967,9 +969,10 @@ const opaqueInstructionId = Symbol();
969
export type InstructionId = number & { [opaqueInstructionId]: "IdentifierId" };
970
971
export function makeInstructionId(id: number): InstructionId {
970
- invariant(
972
+ CompilerError.invariant(
973
id >= 0 && Number.isInteger(id),
972
- "Expected instruction id to be a non-negative integer"
974
+ "Expected instruction id to be a non-negative integer",
975
+ null
976
);
977
return id as InstructionId;
978
}
compiler/forget/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts
+28
-13
@@ -7,7 +7,6 @@
7
8
import { Binding, NodePath } from "@babel/traverse";
9
import * as t from "@babel/types";
10
-import invariant from "invariant";
10
import { CompilerError } from "../CompilerError";
11
import { assertExhaustive } from "../Utils/utils";
12
import { Environment } from "./Environment";
@@ -388,12 +387,13 @@ export default class HIRBuilder {
387
});
388
const value = fn();
389
const last = this.#scopes.pop();
391
- invariant(
390
+ CompilerError.invariant(
391
last != null &&
392
last.kind === "label" &&
393
last.label === label &&
394
last.breakBlock === breakBlock,
396
- "Mismatched label"
395
+ "Mismatched label",
396
+ null
397
);
398
return value;
399
}
@@ -406,12 +406,13 @@ export default class HIRBuilder {
406
});
407
const value = fn();
408
const last = this.#scopes.pop();
409
- invariant(
409
+ CompilerError.invariant(
410
last != null &&
411
last.kind === "switch" &&
412
last.label === label &&
413
last.breakBlock === breakBlock,
414
- "Mismatched label"
414
+ "Mismatched label",
415
+ null
416
);
417
return value;
418
}
@@ -440,13 +441,14 @@ export default class HIRBuilder {
441
});
442
const value = fn();
443
const last = this.#scopes.pop();
443
- invariant(
444
+ CompilerError.invariant(
445
last != null &&
446
last.kind === "loop" &&
447
last.label === label &&
448
last.continueBlock === continueBlock &&
449
last.breakBlock === breakBlock,
449
- "Mismatched loops"
450
+ "Mismatched loops",
451
+ null
452
);
453
return value;
454
}
@@ -462,7 +464,11 @@ export default class HIRBuilder {
464
return scope.breakBlock;
465
}
466
}
465
- invariant(false, "Expected a loop or switch to be in scope");
467
+ CompilerError.invariant(
468
+ false,
469
+ "Expected a loop or switch to be in scope",
470
+ null
471
+ );
472
}
473
474
/**
@@ -478,10 +484,14 @@ export default class HIRBuilder {
484
return scope.continueBlock;
485
}
486
} else if (label !== null && scope.label === label) {
481
- invariant(false, "Continue may only refer to a labeled loop");
487
+ CompilerError.invariant(
488
+ false,
489
+ "Continue may only refer to a labeled loop",
490
+ null
491
+ );
492
}
493
}
484
- invariant(false, "Expected a loop to be in scope");
494
+ CompilerError.invariant(false, "Expected a loop to be in scope", null);
495
}
496
}
497
@@ -501,7 +511,11 @@ function _shrink(func: HIR): void {
511
return target;
512
}
513
const block = func.blocks.get(blockId);
504
- invariant(block != null, "expected block %s to exist", blockId);
514
+ CompilerError.invariant(
515
+ block != null,
516
+ `expected block ${blockId} to exist`,
517
+ null
518
+ );
519
target = getTargetIfIndirection(block);
520
if (target !== null) {
521
// the target might also be a simple goto, recurse
@@ -717,9 +731,10 @@ export function markInstructionIds(func: HIR): void {
731
const visited = new Set<Instruction>();
732
for (const [_, block] of func.blocks) {
733
for (const instr of block.instructions) {
720
- invariant(
734
+ CompilerError.invariant(
735
!visited.has(instr),
722
- `${printInstruction(instr)} already visited!`
736
+ `${printInstruction(instr)} already visited!`,
737
+ instr.loc
738
);
739
visited.add(instr);
740
instr.id = makeInstructionId(++id);
compiler/forget/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts
+7
-7
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import {
10
BlockId,
11
Effect,
@@ -47,10 +47,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
47
const originalPredecessorId = Array.from(block.preds)[0]!;
48
const predecessorId = merged.get(originalPredecessorId);
49
const predecessor = fn.body.blocks.get(predecessorId);
50
- invariant(
50
+ CompilerError.invariant(
51
predecessor !== undefined,
52
- "Expected predecessor %s to exist",
53
- predecessorId
52
+ `Expected predecessor ${predecessorId} to exist`,
53
+ null
54
);
55
if (predecessor.terminal.kind !== "goto" || predecessor.kind !== "block") {
56
// The predecessor is not guaranteed to transfer control to this block,
@@ -60,10 +60,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
60
61
// Replace phis in the merged block with canonical assignments to the single operand value
62
for (const phi of block.phis) {
63
- invariant(
63
+ CompilerError.invariant(
64
phi.operands.size === 1,
65
- "Found a block with a single predecessor but where a phi has multiple (%s) operands",
66
- phi.operands.size
65
+ `Found a block with a single predecessor but where a phi has multiple (${phi.operands.size}) operands`,
66
+ null
67
);
68
const operand = Array.from(phi.operands.values())[0]!;
69
const instr: Instruction = {
compiler/forget/packages/babel-plugin-react-forget/src/HIR/ObjectShape.ts
+4
-3
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import { Effect, ValueKind } from "./HIR";
10
import {
11
BuiltInType,
@@ -103,9 +103,10 @@ function addShape(
103
functionType,
104
};
105
106
- invariant(
106
+ CompilerError.invariant(
107
!registry.has(id),
108
- `[ObjectShape] Could not add shape to registry: name ${id} already exists.`
108
+ `[ObjectShape] Could not add shape to registry: name ${id} already exists.`,
109
+ null
110
);
111
registry.set(id, shape);
112
return shape;
compiler/forget/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts
+4
-3
@@ -6,7 +6,7 @@
6
*/
7
8
import generate from "@babel/generator";
9
-import invariant from "invariant";
9
+import { CompilerError } from "../CompilerError";
10
import DisjointSet from "../Utils/DisjointSet";
11
import { assertExhaustive } from "../Utils/utils";
12
import {
@@ -467,9 +467,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
467
}
468
case "TemplateLiteral": {
469
value = "`";
470
- invariant(
470
+ CompilerError.invariant(
471
instrValue.subexprs.length === instrValue.quasis.length - 1,
472
- "Bad assumption about quasi length."
472
+ "Bad assumption about quasi length.",
473
+ instrValue.loc
474
);
475
for (let i = 0; i < instrValue.subexprs.length; i++) {
476
value += instrValue.quasis[i].raw;
compiler/forget/packages/babel-plugin-react-forget/src/HIR/Types.ts
+4
-3
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
10
export type BuiltInType = PrimitiveType | FunctionType | ObjectType;
11
@@ -62,9 +62,10 @@ const opaqueTypeId = Symbol();
62
export type TypeId = number & { [opaqueTypeId]: "IdentifierId" };
63
64
export function makeTypeId(id: number): TypeId {
65
- invariant(
65
+ CompilerError.invariant(
66
id >= 0 && Number.isInteger(id),
67
- "Expected instruction id to be a non-negative integer"
67
+ "Expected instruction id to be a non-negative integer",
68
+ null
69
);
70
return id as TypeId;
71
}
compiler/forget/packages/babel-plugin-react-forget/src/Inference/AnalyseFunctions.ts
+4
-3
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import {
10
Effect,
11
FunctionExpression,
@@ -169,9 +169,10 @@ function infer(
169
// In practice this never really matters because the Component function has no
170
// context refs, so it will never have duplicate deps.
171
for (const place of context) {
172
- invariant(
172
+ CompilerError.invariant(
173
place.identifier.name !== null,
174
- "context refs should always have a name"
174
+ "context refs should always have a name",
175
+ place.loc
176
);
177
178
const effect = mutations.get(place.identifier.name);
compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferMutableLifetimes.ts
+4
-3
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import {
10
Effect,
11
HIRFunction,
@@ -108,9 +108,10 @@ export function inferMutableLifetimes(
108
start = Math.min(start, operand.mutableRange.start);
109
end = Math.max(end, operand.mutableRange.end);
110
}
111
- invariant(
111
+ CompilerError.invariant(
112
start !== Number.MAX_SAFE_INTEGER,
113
- "Expected phi to have a start range value"
113
+ "Expected phi to have a start range value",
114
+ null
115
);
116
phi.id.mutableRange = {
117
start: makeInstructionId(start),
compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts
+29
-20
@@ -5,7 +5,6 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
import { CompilerError } from "../CompilerError";
9
import { Environment } from "../HIR";
10
import {
@@ -192,9 +191,10 @@ class InferenceState {
191
* (Re)initializes a @param value with its default @param kind.
192
*/
193
initialize(value: InstructionValue, kind: ValueKind): void {
195
- invariant(
194
+ CompilerError.invariant(
195
value.kind !== "LoadLocal",
197
- "Expected all top-level identifiers to be defined as variables, not values"
196
+ "Expected all top-level identifiers to be defined as variables, not values",
197
+ value.loc
198
);
199
this.#values.set(value, kind);
200
}
@@ -204,11 +204,12 @@ class InferenceState {
204
*/
205
kind(place: Place): ValueKind {
206
const values = this.#variables.get(place.identifier.id);
207
- invariant(
207
+ CompilerError.invariant(
208
values != null,
209
`Expected value kind to be initialized at '${printSourceLocation(
210
place.loc
211
- )}'`
211
+ )}'`,
212
+ place.loc
213
);
214
let mergedKind: ValueKind | null = null;
215
for (const value of values) {
@@ -229,10 +230,10 @@ class InferenceState {
230
*/
231
alias(place: Place, value: Place): void {
232
const values = this.#variables.get(value.identifier.id);
232
- invariant(
233
+ CompilerError.invariant(
234
values != null,
234
- "Expected value for identifier `%s` to be initialized.",
235
- value.identifier.id
235
+ `Expected value for identifier \`${value.identifier.id}\` to be initialized.`,
236
+ value.loc
237
);
238
this.#variables.set(place.identifier.id, new Set(values));
239
}
@@ -241,9 +242,10 @@ class InferenceState {
242
* Defines (initializing or updating) a variable with a specific kind of value.
243
*/
244
define(place: Place, value: InstructionValue): void {
244
- invariant(
245
+ CompilerError.invariant(
246
this.#values.has(value),
246
- `Expected value to be initialized at '${printSourceLocation(value.loc)}'`
247
+ `Expected value to be initialized at '${printSourceLocation(value.loc)}'`,
248
+ value.loc
249
);
250
this.#variables.set(place.identifier.id, new Set([value]));
251
}
@@ -363,9 +365,10 @@ class InferenceState {
365
break;
366
}
367
case Effect.Unknown: {
366
- invariant(
368
+ CompilerError.invariant(
369
false,
368
- "Unexpected unknown effect, expected to infer a precise effect kind"
370
+ "Unexpected unknown effect, expected to infer a precise effect kind",
371
+ place.loc
372
);
373
}
374
default: {
@@ -375,7 +378,11 @@ class InferenceState {
378
);
379
}
380
}
378
- invariant(effect !== null, "Expected effect to be set");
381
+ CompilerError.invariant(
382
+ effect !== null,
383
+ "Expected effect to be set",
384
+ place.loc
385
+ );
386
place.effect = effect;
387
}
388
@@ -746,9 +753,10 @@ function inferBlock(
753
continue;
754
}
755
case "MethodCall": {
749
- invariant(
756
+ CompilerError.invariant(
757
state.isDefined(instrValue.receiver),
751
- "[InferReferenceEffects] Internal error: receiver of PropertyCall should have been defined by corresponding PropertyLoad"
758
+ "[InferReferenceEffects] Internal error: receiver of PropertyCall should have been defined by corresponding PropertyLoad",
759
+ instrValue.loc
760
);
761
state.reference(instrValue.property, Effect.Read);
762
@@ -882,9 +890,10 @@ function inferBlock(
890
const lvalue = instr.lvalue;
891
lvalue.effect = Effect.ConditionallyMutate;
892
const valueKind = state.kind(instrValue.place);
885
- invariant(
893
+ CompilerError.invariant(
894
valueKind === ValueKind.Mutable || valueKind === ValueKind.Context,
887
- "[InferReferenceEffects] Context variables are always mutable."
895
+ "[InferReferenceEffects] Context variables are always mutable.",
896
+ instrValue.loc
897
);
898
state.initialize(instrValue, valueKind);
899
state.define(lvalue, instrValue);
@@ -971,10 +980,10 @@ function inferBlock(
980
}
981
982
for (const operand of eachInstructionOperand(instr)) {
974
- invariant(
983
+ CompilerError.invariant(
984
effectKind != null,
976
- "effectKind must be set for instruction value `%s`",
977
- instrValue.kind
985
+ `effectKind must be set for instruction value \`${instrValue.kind}\``,
986
+ instrValue.loc
987
);
988
state.reference(operand, effectKind);
989
}
compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveBlocks.ts
+20
-9
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import {
10
BlockId,
11
InstructionId,
@@ -70,7 +70,11 @@ class Context {
70
this.#builders.push(builder);
71
fn();
72
const popped = this.#builders.pop();
73
- invariant(popped === builder, "Expected push/pop to be called 1:1");
73
+ CompilerError.invariant(
74
+ popped === builder,
75
+ "Expected push/pop to be called 1:1",
76
+ null
77
+ );
78
return builder.complete();
79
}
80
}
@@ -90,7 +94,11 @@ class Builder {
94
95
append(item: ReactiveStatement, label: BlockId | null): void {
96
if (label !== null) {
93
- invariant(item.kind === "terminal", "Only terminals may have a label");
97
+ CompilerError.invariant(
98
+ item.kind === "terminal",
99
+ "Only terminals may have a label",
100
+ null
101
+ );
102
item.label = label;
103
}
104
this.#instructions.push(item);
@@ -130,9 +138,10 @@ class Builder {
138
// "Expected all scopes to be closed when exiting a block"
139
// );
140
const first = this.#stack[0]!;
133
- invariant(
141
+ CompilerError.invariant(
142
first.kind === "block",
135
- "Expected first stack item to be a basic block"
143
+ "Expected first stack item to be a basic block",
144
+ null
145
);
146
return first.block;
147
}
@@ -164,9 +173,10 @@ function visitBlock(context: Context, block: ReactiveBlock): void {
173
break;
174
}
175
case "scope": {
167
- invariant(
176
+ CompilerError.invariant(
177
false,
169
- "Expected the function to not have scopes already assigned"
178
+ "Expected the function to not have scopes already assigned",
179
+ null
180
);
181
}
182
default: {
@@ -182,10 +192,11 @@ function visitBlock(context: Context, block: ReactiveBlock): void {
192
export function getInstructionScope(
193
instr: ReactiveInstruction
194
): ReactiveScope | null {
185
- invariant(
195
+ CompilerError.invariant(
196
instr.lvalue !== null,
197
"Expected lvalues to not be null when assigning scopes. " +
188
- "Pruning lvalues too early can result in missing scope information."
198
+ "Pruning lvalues too early can result in missing scope information.",
199
+ instr.loc
200
);
201
for (const operand of eachInstructionLValue(instr)) {
202
const operandScope = getPlaceScope(instr.id, operand);
compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/BuildReactiveFunction.ts
+51
-37
@@ -5,7 +5,6 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
import { CompilerError } from "../CompilerError";
9
import {
10
BasicBlock,
@@ -66,9 +65,10 @@ class Driver {
65
}
66
67
visitBlock(block: BasicBlock, blockValue: ReactiveBlock): void {
69
- invariant(
68
+ CompilerError.invariant(
69
!this.cx.emitted.has(block.id),
71
- `Cannot emit the same block twice: bb${block.id}`
70
+ `Cannot emit the same block twice: bb${block.id}`,
71
+ null
72
);
73
this.cx.emitted.add(block.id);
74
for (const instruction of block.instructions) {
@@ -252,9 +252,10 @@ class Driver {
252
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
253
} else {
254
const break_ = this.visitBreak(terminal.loop, null);
255
- invariant(
255
+ CompilerError.invariant(
256
break_ !== null,
257
- "If loop body is already scheduled it must be a break"
257
+ "If loop body is already scheduled it must be a break",
258
+ null
259
);
260
loopBody = [break_];
261
}
@@ -308,9 +309,10 @@ class Driver {
309
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
310
} else {
311
const break_ = this.visitBreak(terminal.loop, null);
311
- invariant(
312
+ CompilerError.invariant(
313
break_ !== null,
313
- "If loop body is already scheduled it must be a break"
314
+ "If loop body is already scheduled it must be a break",
315
+ null
316
);
317
loopBody = [break_];
318
}
@@ -392,9 +394,10 @@ class Driver {
394
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
395
} else {
396
const break_ = this.visitBreak(terminal.loop, null);
395
- invariant(
397
+ CompilerError.invariant(
398
break_ !== null,
397
- "If loop body is already scheduled it must be a break"
399
+ "If loop body is already scheduled it must be a break",
400
+ null
401
);
402
loopBody = [break_];
403
}
@@ -467,9 +470,10 @@ class Driver {
470
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
471
} else {
472
const break_ = this.visitBreak(terminal.loop, null);
470
- invariant(
473
+ CompilerError.invariant(
474
break_ !== null,
472
- "If loop body is already scheduled it must be a break"
475
+ "If loop body is already scheduled it must be a break",
476
+ null
477
);
478
loopBody = [break_];
479
}
@@ -626,7 +630,11 @@ class Driver {
630
break;
631
}
632
case "unsupported": {
629
- invariant(false, "Unexpected unsupported terminal");
633
+ CompilerError.invariant(
634
+ false,
635
+ "Unexpected unsupported terminal",
636
+ terminal.loc
637
+ );
638
}
639
default: {
640
assertExhaustive(terminal, "Unexpected terminal");
@@ -654,10 +662,11 @@ class Driver {
662
};
663
} else if (defaultBlock.instructions.length === 1) {
664
const instr = defaultBlock.instructions[0]!;
657
- invariant(
665
+ CompilerError.invariant(
666
instr.lvalue.identifier.id ===
667
defaultBlock.terminal.test.identifier.id,
660
- "Expected branch block to end in an instruction that sets the test value"
668
+ "Expected branch block to end in an instruction that sets the test value",
669
+ instr.lvalue.loc
670
);
671
return {
672
block: defaultBlock.id,
@@ -684,9 +693,10 @@ class Driver {
693
} else if (defaultBlock.terminal.kind === "goto") {
694
const instructions = defaultBlock.instructions;
695
if (instructions.length === 0) {
687
- invariant(
696
+ CompilerError.invariant(
697
false,
689
- "Expected goto value block to have at least one instruction"
698
+ "Expected goto value block to have at least one instruction",
699
+ null
700
);
701
} else if (defaultBlock.instructions.length === 1) {
702
const instr = defaultBlock.instructions[0]!;
@@ -782,10 +792,10 @@ class Driver {
792
case "optional": {
793
const test = this.visitValueBlock(terminal.test, terminal.loc);
794
const testBlock = this.cx.ir.blocks.get(test.block)!;
785
- invariant(
795
+ CompilerError.invariant(
796
testBlock.terminal.kind === "branch",
787
- "Unexpected terminal kind '%s' for optional call test block",
788
- testBlock.terminal.kind
797
+ `Unexpected terminal kind '${testBlock.terminal.kind}' for optional call test block`,
798
+ testBlock.terminal.loc
799
);
800
const consequent = this.visitValueBlock(
801
testBlock.terminal.consequent,
@@ -821,10 +831,10 @@ class Driver {
831
case "logical": {
832
const test = this.visitValueBlock(terminal.test, terminal.loc);
833
const testBlock = this.cx.ir.blocks.get(test.block)!;
824
- invariant(
834
+ CompilerError.invariant(
835
testBlock.terminal.kind === "branch",
826
- "Unexpected terminal kind '%s' for logical test block",
827
- testBlock.terminal.kind
836
+ `Unexpected terminal kind '${testBlock.terminal.kind}' for logical test block`,
837
+ testBlock.terminal.loc
838
);
839
840
const leftFinal = this.visitValueBlock(
@@ -866,10 +876,10 @@ class Driver {
876
case "ternary": {
877
const test = this.visitValueBlock(terminal.test, terminal.loc);
878
const testBlock = this.cx.ir.blocks.get(test.block)!;
869
- invariant(
879
+ CompilerError.invariant(
880
testBlock.terminal.kind === "branch",
871
- "Unexpected terminal kind '%s' for ternary test block",
872
- testBlock.terminal.kind
881
+ `Unexpected terminal kind '${testBlock.terminal.kind}' for ternary test block`,
882
+ testBlock.terminal.loc
883
);
884
const consequent = this.visitValueBlock(
885
testBlock.terminal.consequent,
@@ -895,10 +905,10 @@ class Driver {
905
};
906
}
907
default: {
898
- invariant(
908
+ CompilerError.invariant(
909
false,
900
- "Unexpected value block terminal kind '%s'",
901
- terminal.kind
910
+ `Unexpected value block terminal kind '${terminal.kind}'`,
911
+ terminal.loc
912
);
913
}
914
}
@@ -914,7 +924,7 @@ class Driver {
924
): ReactiveTerminalStatement<ReactiveBreakTerminal> {
925
const target = this.cx.getBreakTarget(block);
926
if (target === null) {
917
- invariant(false, "Expected a break target");
927
+ CompilerError.invariant(false, "Expected a break target", null);
928
}
929
switch (target.type) {
930
case "implicit": {
@@ -952,9 +962,10 @@ class Driver {
962
id: InstructionId
963
): ReactiveTerminalStatement<ReactiveContinueTerminal> {
964
const target = this.cx.getContinueTarget(block);
955
- invariant(
965
+ CompilerError.invariant(
966
target !== null,
957
- `Expected continue target to be scheduled for bb${block}`
967
+ `Expected continue target to be scheduled for bb${block}`,
968
+ null
969
);
970
switch (target.type) {
971
case "implicit": {
@@ -1035,9 +1046,10 @@ class Context {
1046
*/
1047
schedule(block: BlockId, type: "if" | "switch" | "case"): number {
1048
const id = this.#nextScheduleId++;
1038
- invariant(
1049
+ CompilerError.invariant(
1050
!this.#scheduled.has(block),
1040
- `Break block is already scheduled: bb${block}`
1051
+ `Break block is already scheduled: bb${block}`,
1052
+ null
1053
);
1054
this.#scheduled.add(block);
1055
this.#controlFlowStack.push({ block, id, type });
@@ -1052,9 +1064,10 @@ class Context {
1064
const id = this.#nextScheduleId++;
1065
const ownsBlock = !this.#scheduled.has(fallthroughBlock);
1066
this.#scheduled.add(fallthroughBlock);
1055
- invariant(
1067
+ CompilerError.invariant(
1068
!this.#scheduled.has(continueBlock),
1057
- `Continue block is already scheduled: bb${continueBlock}`
1069
+ `Continue block is already scheduled: bb${continueBlock}`,
1070
+ null
1071
);
1072
this.#scheduled.add(continueBlock);
1073
let ownsLoop = false;
@@ -1080,9 +1093,10 @@ class Context {
1093
*/
1094
unschedule(scheduleId: number): void {
1095
const last = this.#controlFlowStack.pop();
1083
- invariant(
1096
+ CompilerError.invariant(
1097
last !== undefined && last.id === scheduleId,
1085
- "Can only unschedule the last target"
1098
+ "Can only unschedule the last target",
1099
+ null
1100
);
1101
if (last.type !== "loop" || last.ownsBlock !== null) {
1102
this.#scheduled.delete(last.block);
compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+35
-25
@@ -6,7 +6,6 @@
6
*/
7
8
import * as t from "@babel/types";
9
-import invariant from "invariant";
9
import { pruneUnusedLValues, pruneUnusedLabels, renameVariables } from ".";
10
import { CompilerError, ErrorSeverity } from "../CompilerError";
11
import { Environment } from "../HIR";
@@ -216,10 +215,10 @@ function codegenReactiveScope(
215
firstOutputIndex = index;
216
}
217
219
- invariant(
218
+ CompilerError.invariant(
219
identifier.name != null,
221
- "Expected identifier '@%s' to be named",
222
- identifier.id
220
+ `Expected identifier '@${identifier.id}' to be named`,
221
+ null
222
);
223
224
const name = convertIdentifier(identifier);
@@ -284,10 +283,10 @@ function codegenReactiveScope(
283
null as t.Expression | null
284
);
285
if (testCondition === null) {
287
- invariant(
286
+ CompilerError.invariant(
287
firstOutputIndex !== null,
289
- "Expected scope '@%s' to have at least one declaration",
290
- scope.id
288
+ `Expected scope '@${scope.id}' to have at least one declaration`,
289
+ null
290
);
291
testCondition = t.binaryExpression(
292
"===",
@@ -542,7 +541,11 @@ function codegenInstructionNullable(
541
]);
542
}
543
case InstructionKind.Reassign: {
545
- invariant(value !== null, "Expected a value for reassignment");
544
+ CompilerError.invariant(
545
+ value !== null,
546
+ "Expected a value for reassignment",
547
+ instr.value.loc
548
+ );
549
const expr = t.assignmentExpression("=", codegenLValue(lvalue), value);
550
if (instr.lvalue !== null) {
551
if (instr.value.kind !== "StoreContext") {
@@ -589,9 +592,10 @@ function codegenForInit(
592
}))
593
).body;
594
const declaration = body[0]!;
592
- invariant(
595
+ CompilerError.invariant(
596
declaration.type === "VariableDeclaration",
594
- "Expected a variable declaration"
597
+ "Expected a variable declaration",
598
+ declaration.loc ?? null
599
);
600
return declaration;
601
} else {
@@ -740,9 +744,10 @@ function codegenInstructionValue(
744
switch (optionalValue.type) {
745
case "OptionalCallExpression":
746
case "CallExpression": {
743
- invariant(
747
+ CompilerError.invariant(
748
t.isExpression(optionalValue.callee),
745
- "v8 intrinsics are validated during lowering"
749
+ "v8 intrinsics are validated during lowering",
750
+ optionalValue.callee.loc ?? null
751
);
752
value = t.optionalCallExpression(
753
optionalValue.callee,
@@ -754,9 +759,10 @@ function codegenInstructionValue(
759
case "OptionalMemberExpression":
760
case "MemberExpression": {
761
const property = optionalValue.property;
757
- invariant(
762
+ CompilerError.invariant(
763
t.isExpression(property),
759
- "Private names are validated during lowering"
764
+ "Private names are validated during lowering",
765
+ property.loc ?? null
766
);
767
value = t.optionalMemberExpression(
768
optionalValue.object,
@@ -779,19 +785,21 @@ function codegenInstructionValue(
785
}
786
case "MethodCall": {
787
const memberExpr = codegenPlace(cx, instrValue.property);
782
- invariant(
788
+ CompilerError.invariant(
789
t.isMemberExpression(memberExpr) ||
790
t.isOptionalMemberExpression(memberExpr),
791
"[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. " +
786
- `Got a '${memberExpr.type}'`
792
+ `Got a '${memberExpr.type}'`,
793
+ memberExpr.loc ?? null
794
);
788
- invariant(
795
+ CompilerError.invariant(
796
t.isNodesEquivalent(
797
memberExpr.object,
798
codegenPlace(cx, instrValue.receiver)
799
),
800
"[Codegen] Internal error: Forget should always generate MethodCall::property " +
794
- "as a MemberExpression of MethodCall::receiver"
801
+ "as a MemberExpression of MethodCall::receiver",
802
+ memberExpr.loc ?? null
803
);
804
const args = instrValue.args.map((arg) => codegenArgument(cx, arg));
805
value = createCallExpression(instrValue.loc, memberExpr, args);
@@ -843,10 +851,10 @@ function codegenInstructionValue(
851
} else if (tagValue.type === "MemberExpression") {
852
tag = convertMemberExpressionToJsx(tagValue);
853
} else {
846
- invariant(
854
+ CompilerError.invariant(
855
tagValue.type === "StringLiteral",
848
- "Expected JSX tag to be an identifier or string, got '%s'",
849
- tagValue.type
856
+ `Expected JSX tag to be an identifier or string, got '${tagValue.type}'`,
857
+ tagValue.loc ?? null
858
);
859
if (tagValue.value.indexOf(":") >= 0) {
860
const [namespace, name] = tagValue.value.split(":", 2);
@@ -1185,17 +1193,19 @@ function codegenJsxElement(
1193
function convertMemberExpressionToJsx(
1194
expr: t.MemberExpression
1195
): t.JSXMemberExpression {
1188
- invariant(
1196
+ CompilerError.invariant(
1197
expr.property.type === "Identifier",
1190
- "Expected JSX member expression property to be a string"
1198
+ "Expected JSX member expression property to be a string",
1199
+ expr.loc ?? null
1200
);
1201
const property = t.jsxIdentifier(expr.property.name);
1202
if (expr.object.type === "Identifier") {
1203
return t.jsxMemberExpression(t.jsxIdentifier(expr.object.name), property);
1204
} else {
1196
- invariant(
1205
+ CompilerError.invariant(
1206
expr.object.type === "MemberExpression",
1198
- "Expected JSX member expression to be an identifier or nested member expression"
1207
+ "Expected JSX member expression to be an identifier or nested member expression",
1208
+ expr.object.loc ?? null
1209
);
1210
const object = convertMemberExpressionToJsx(expr.object);
1211
return t.jsxMemberExpression(object, property);
compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/DeriveMinimalDependencies.ts
+13
-9
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import { Identifier, ReactiveScopeDependency } from "../HIR";
10
import { printIdentifier } from "../HIR/PrintHIR";
11
import { assertExhaustive } from "../Utils/utils";
@@ -122,11 +122,12 @@ export class ReactiveScopeDependencyTree {
122
const results = new Set<ReactiveScopeDependency>();
123
for (const [rootId, rootNode] of this.#roots.entries()) {
124
const deps = deriveMinimalDependenciesInSubtree(rootNode);
125
- invariant(
125
+ CompilerError.invariant(
126
deps.every(
127
(dep) => dep.accessType === PropertyAccessType.UnconditionalDependency
128
),
129
- "[PropagateScopeDependencies] All dependencies must be reduced to unconditional dependencies."
129
+ "[PropagateScopeDependencies] All dependencies must be reduced to unconditional dependencies.",
130
+ null
131
);
132
133
for (const dep of deps) {
@@ -162,9 +163,10 @@ export class ReactiveScopeDependencyTree {
163
promoteDepsFromExhaustiveConditionals(
164
trees: Array<ReactiveScopeDependencyTree>
165
): void {
165
- invariant(
166
+ CompilerError.invariant(
167
trees.length > 1,
167
- "Expected trees to be at least 2 elements long."
168
+ "Expected trees to be at least 2 elements long.",
169
+ null
170
);
171
172
for (const [id, root] of this.#roots) {
@@ -456,16 +458,18 @@ function addSubtreeIntersection(
458
otherProperties: Array<Map<string, DependencyNode>>,
459
currProperties: Map<string, DependencyNode>
460
): void {
459
- invariant(
461
+ CompilerError.invariant(
462
otherProperties.length > 1,
461
- "[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long."
463
+ "[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long.",
464
+ null
465
);
466
467
otherProperties.forEach((properties) =>
468
properties.forEach((node, _) =>
466
- invariant(
469
+ CompilerError.invariant(
470
!isUnconditional(node.accessType),
468
- "[DeriveMinimalDependencies] Expected otherProperties to only contain unconditional nodes!"
471
+ "[DeriveMinimalDependencies] Expected otherProperties to only contain unconditional nodes!",
472
+ null
473
)
474
)
475
);
compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts
+6
-2
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import {
10
ReactiveFunction,
11
ReactiveScopeBlock,
@@ -226,7 +226,11 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
226
writer.writeLine(`${prefix}: {`);
227
writer.indented(() => {
228
const block = case_.block;
229
- invariant(block != null, "Expected case to have a block");
229
+ CompilerError.invariant(
230
+ block != null,
231
+ "Expected case to have a block",
232
+ case_.test?.loc ?? null
233
+ );
234
printReactiveInstructions(writer, block);
235
});
236
writer.writeLine("}");
compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts
+11
-6
@@ -5,7 +5,6 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
import prettyFormat from "pretty-format";
9
import { CompilerError } from "../CompilerError";
10
import {
@@ -244,9 +243,10 @@ class State {
243
this.scopes.set(scope.id, node);
244
}
245
const identifierNode = this.identifiers.get(identifier);
247
- invariant(
246
+ CompilerError.invariant(
247
identifierNode !== undefined,
249
- "Expected identifier to be initialized"
248
+ "Expected identifier to be initialized",
249
+ place.loc
250
);
251
identifierNode.scopes.add(scope.id);
252
}
@@ -264,9 +264,10 @@ function computeMemoizedIdentifiers(state: State): Set<IdentifierId> {
264
// Visit an identifier, optionally forcing it to be memoized
265
function visit(id: IdentifierId, forceMemoize: boolean = false): boolean {
266
const node = state.identifiers.get(id);
267
- invariant(
267
+ CompilerError.invariant(
268
node !== undefined,
269
- `Expected a node for all identifiers, none found for '${id}'`
269
+ `Expected a node for all identifiers, none found for '${id}'`,
270
+ null
271
);
272
if (node.seen) {
273
return node.memoized;
@@ -302,7 +303,11 @@ function computeMemoizedIdentifiers(state: State): Set<IdentifierId> {
303
// Force all the scope's optionally-memoizeable dependencies (not "Never") to be memoized
304
function forceMemoizeScopeDependencies(id: ScopeId): void {
305
const node = state.scopes.get(id);
305
- invariant(node !== undefined, "Expected a node for all scopes");
306
+ CompilerError.invariant(
307
+ node !== undefined,
308
+ "Expected a node for all scopes",
309
+ null
310
+ );
311
if (node.seen) {
312
return;
313
}
compiler/forget/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts
+2
-2
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import {
10
Identifier,
11
IdentifierId,
@@ -103,6 +103,6 @@ class Scopes {
103
this.#stack.push(next);
104
fn();
105
const last = this.#stack.pop();
106
- invariant(last === next, "Mismatch push/pop calls");
106
+ CompilerError.invariant(last === next, "Mismatch push/pop calls", null);
107
}
108
}
compiler/forget/packages/babel-plugin-react-forget/src/SSA/EliminateRedundantPhi.ts
+6
-2
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
import { BlockId, HIRFunction, Identifier, Place } from "../HIR/HIR";
10
import {
11
eachInstructionLValue,
@@ -83,7 +83,11 @@ export function eliminateRedundantPhi(fn: HIRFunction): void {
83
same = operand;
84
}
85
}
86
- invariant(same !== null, "Expected phis to be non-empty");
86
+ CompilerError.invariant(
87
+ same !== null,
88
+ "Expected phis to be non-empty",
89
+ null
90
+ );
91
rewrites.set(phi.id, same);
92
block.phis.delete(phi);
93
}
compiler/forget/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts
+9
-7
@@ -5,7 +5,6 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
import { CompilerError } from "../CompilerError";
9
import { Environment } from "../HIR/Environment";
10
import {
@@ -68,9 +67,10 @@ class SSABuilder {
67
}
68
69
state(): State {
71
- invariant(
70
+ CompilerError.invariant(
71
this.#current !== null,
73
- "we need to be in a block to access state!"
72
+ "we need to be in a block to access state!",
73
+ null
74
);
75
return this.#states.get(this.#current)!;
76
}
@@ -237,9 +237,10 @@ function enterSSAImpl(
237
): void {
238
const visitedBlocks: Set<BasicBlock> = new Set();
239
for (const [blockId, block] of func.body.blocks) {
240
- invariant(
240
+ CompilerError.invariant(
241
!visitedBlocks.has(block),
242
- `found a cycle! visiting bb${block.id} again`
242
+ `found a cycle! visiting bb${block.id} again`,
243
+ null
244
);
245
visitedBlocks.add(block);
246
@@ -269,9 +270,10 @@ function enterSSAImpl(
270
) {
271
const loweredFunc = instr.value.loweredFunc;
272
const entry = loweredFunc.body.blocks.get(loweredFunc.body.entry)!;
272
- invariant(
273
+ CompilerError.invariant(
274
entry.preds.size === 0,
274
- "Expected function expression entry block to have zero predecessors"
275
+ "Expected function expression entry block to have zero predecessors",
276
+ null
277
);
278
entry.preds.add(blockId);
279
builder.defineFunction(loweredFunc);
compiler/forget/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts
+8
-4
@@ -5,7 +5,6 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
import { CompilerError } from "../CompilerError";
9
import {
10
BasicBlock,
@@ -220,7 +219,11 @@ export function leaveSSA(fn: HIRFunction): void {
219
}
220
}
221
}
223
- invariant(kind !== null, "Expected at least one operand");
222
+ CompilerError.invariant(
223
+ kind !== null,
224
+ "Expected at least one operand",
225
+ null
226
+ );
227
value.lvalue.kind = kind;
228
}
229
rewritePlace(lvalue, rewrites, declarations);
@@ -353,9 +356,10 @@ export function leaveSSA(fn: HIRFunction): void {
356
357
// If we never saw a declaration for this phi, it may have been pruned by DCE, so synthesize
358
// a new Let binding
356
- invariant(
359
+ CompilerError.invariant(
360
phi.id.name != null,
358
- "Expected reassignment phis to have a name"
361
+ "Expected reassignment phis to have a name",
362
+ null
363
);
364
const declaration = declarations.get(phi.id.name);
365
if (declaration === undefined) {
compiler/forget/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts
+6
-2
@@ -6,7 +6,7 @@
6
*/
7
8
import * as t from "@babel/types";
9
-import invariant from "invariant";
9
+import { CompilerError } from "../CompilerError";
10
import { Environment } from "../HIR";
11
import {
12
HIRFunction,
@@ -342,7 +342,11 @@ class Unifier {
342
if (type.kind === "Phi") {
343
const operands = new Set(type.operands.map((i) => this.get(i).kind));
344
345
- invariant(operands.size > 0, "there should be at least one operand");
345
+ CompilerError.invariant(
346
+ operands.size > 0,
347
+ "there should be at least one operand",
348
+ null
349
+ );
350
const kind = operands.values().next().value;
351
352
// there's only one unique type and it's not a type var
compiler/forget/packages/babel-plugin-react-forget/src/Utils/DisjointSet.ts
+6
-2
@@ -5,7 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
-import invariant from "invariant";
8
+import { CompilerError } from "../CompilerError";
9
10
/**
11
* Represents items which form disjoint sets.
@@ -20,7 +20,11 @@ export default class DisjointSet<T> {
20
*/
21
union(items: Array<T>): void {
22
const first = items.shift();
23
- invariant(first != null, "Expected set to be non-empty");
23
+ CompilerError.invariant(
24
+ first != null,
25
+ "Expected set to be non-empty",
26
+ null
27
+ );
28
// determine an arbitrary "root" for this set: if the first
29
// item already has a root then use that, otherwise the first item
30
// will be the new root.
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo.destructure-assignment-to-context-var.expect.md
+1
-1
@@ -18,7 +18,7 @@ function useFoo(props) {
18
## Error
19
20
```
21
-[InferReferenceEffects] Context variables are always mutable.
21
+[ReactForget] Invariant: [InferReferenceEffects] Context variables are always mutable. (5:5)
22
```
23
24
\ No newline at end of file