mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Use CompilerError.invariant consistently
This PR updates all current usages of invariant to CompilerError.invariant along with any available locs
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
import { NodePath, Scope } from "@babel/traverse";
|
||||
import * as t from "@babel/types";
|
||||
import { Expression } from "@babel/types";
|
||||
import invariant from "invariant";
|
||||
import { CompilerError, ErrorSeverity } from "../CompilerError";
|
||||
import { Err, Ok, Result } from "../Utils/Result";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
@@ -769,9 +768,10 @@ function lowerStatement(
|
||||
case "FunctionDeclaration": {
|
||||
const stmt = stmtPath as NodePath<t.FunctionDeclaration>;
|
||||
stmt.skip();
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
stmt.get("id").type === "Identifier",
|
||||
"function declarations must have a name"
|
||||
"function declarations must have a name",
|
||||
stmt.node.loc ?? null
|
||||
);
|
||||
const id = stmt.get("id") as NodePath<t.Identifier>;
|
||||
|
||||
@@ -795,9 +795,10 @@ function lowerStatement(
|
||||
),
|
||||
])
|
||||
);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
desugared.length === 1,
|
||||
"only one declaration is created from desugaring function declaration"
|
||||
"only one declaration is created from desugaring function declaration",
|
||||
stmt.node.loc ?? null
|
||||
);
|
||||
lowerStatement(builder, desugared.at(0)!);
|
||||
return;
|
||||
@@ -843,9 +844,10 @@ function lowerStatement(
|
||||
let test: Place;
|
||||
if (left.isVariableDeclaration()) {
|
||||
const declarations = left.get("declarations");
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
declarations.length === 1,
|
||||
`Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`
|
||||
`Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`,
|
||||
left.node.loc ?? null
|
||||
);
|
||||
const id = declarations[0].get("id");
|
||||
const nextIterableOf = lowerValueToTemporary(builder, {
|
||||
@@ -1517,7 +1519,11 @@ function lowerExpression(
|
||||
});
|
||||
}
|
||||
} else {
|
||||
invariant(namePath.isJSXNamespacedName(), "Refinement");
|
||||
CompilerError.invariant(
|
||||
namePath.isJSXNamespacedName(),
|
||||
"Refinement",
|
||||
namePath.node.loc ?? null
|
||||
);
|
||||
const namespace = namePath.node.namespace.name;
|
||||
const name = namePath.node.name.name;
|
||||
propName = `${namespace}:${name}`;
|
||||
@@ -1586,9 +1592,10 @@ function lowerExpression(
|
||||
});
|
||||
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
|
||||
}
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
expr.get("quasi").get("quasis").length == 1,
|
||||
"there should be only one quasi as we don't support interpolations yet"
|
||||
"there should be only one quasi as we don't support interpolations yet",
|
||||
expr.node.loc ?? null
|
||||
);
|
||||
const value = expr.get("quasi").get("quasis").at(0)!.node.value;
|
||||
if (value.raw !== value.cooked) {
|
||||
@@ -1836,7 +1843,7 @@ function lowerOptionalMemberExpression(
|
||||
loc,
|
||||
};
|
||||
});
|
||||
invariant(object !== null, "Satisfy type checker");
|
||||
CompilerError.invariant(object !== null, "Satisfy type checker", null);
|
||||
|
||||
// block to evaluate if the callee is non-null/undefined. arguments are lowered in this block to preserve
|
||||
// the semantic of conditional evaluation depending on the callee
|
||||
@@ -2268,10 +2275,10 @@ function lowerJsxMemberExpression(
|
||||
if (object.isJSXMemberExpression()) {
|
||||
objectPlace = lowerJsxMemberExpression(builder, object);
|
||||
} else {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
object.isJSXIdentifier(),
|
||||
"TypeScript refinement fail: expected 'JsxIdentifier', got '%s'",
|
||||
object.node.type
|
||||
`TypeScript refinement fail: expected 'JsxIdentifier', got '${object.node.type}'`,
|
||||
object.node.loc ?? null
|
||||
);
|
||||
objectPlace = lowerIdentifier(builder, object);
|
||||
}
|
||||
@@ -2303,9 +2310,10 @@ function lowerJsxElement(
|
||||
if (expression.isJSXEmptyExpression()) {
|
||||
return null;
|
||||
} else {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
expression.isExpression(),
|
||||
`(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`
|
||||
`(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`,
|
||||
expression.node.loc ?? null
|
||||
);
|
||||
return lowerExpressionToTemporary(builder, expression);
|
||||
}
|
||||
@@ -2554,9 +2562,10 @@ function lowerAssignment(
|
||||
}
|
||||
case "MemberExpression": {
|
||||
// This can only occur because of a coding error, parsers enforce this condition
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
kind === InstructionKind.Reassign,
|
||||
"MemberExpression may only appear in an assignment expression"
|
||||
"MemberExpression may only appear in an assignment expression",
|
||||
lvaluePath.node.loc ?? null
|
||||
);
|
||||
const lvalue = lvaluePath as NodePath<t.MemberExpression>;
|
||||
const property = lvalue.get("property");
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import prettyFormat from "pretty-format";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { BlockId, HIRFunction } from "./HIR";
|
||||
import { eachTerminalSuccessor } from "./visitors";
|
||||
|
||||
@@ -88,7 +88,7 @@ export class Dominator<T> {
|
||||
*/
|
||||
get(id: T): T | null {
|
||||
const dominator = this.#nodes.get(id);
|
||||
invariant(dominator !== undefined, "Unknown node");
|
||||
CompilerError.invariant(dominator !== undefined, "Unknown node", null);
|
||||
return dominator === id ? null : dominator;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ export class PostDominator<T> {
|
||||
*/
|
||||
get(id: T): T | null {
|
||||
const dominator = this.#nodes.get(id);
|
||||
invariant(dominator !== undefined, "Unknown node");
|
||||
CompilerError.invariant(dominator !== undefined, "Unknown node", null);
|
||||
return dominator === id ? null : dominator;
|
||||
}
|
||||
|
||||
@@ -159,9 +159,10 @@ function computeImmediateDominators<T>(graph: Graph<T>): Map<T, T> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
newIdom !== null,
|
||||
`At least one predecessor must have been visited for block ${id}`
|
||||
`At least one predecessor must have been visited for block ${id}`,
|
||||
null
|
||||
);
|
||||
|
||||
for (const pred of node.preds) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import * as t from "@babel/types";
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { ExternalFunction } from "../Entrypoint/Options";
|
||||
import { log } from "../Utils/logger";
|
||||
import {
|
||||
@@ -195,9 +195,10 @@ export class Environment {
|
||||
if (config?.customHooks) {
|
||||
this.#globals = new Map(DEFAULT_GLOBALS);
|
||||
for (const [hookName, hook] of config.customHooks) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!this.#globals.has(hookName),
|
||||
`[Globals] Found existing definition in global registry for custom hook ${hookName}`
|
||||
`[Globals] Found existing definition in global registry for custom hook ${hookName}`,
|
||||
null
|
||||
);
|
||||
this.#globals.set(
|
||||
hookName,
|
||||
@@ -270,9 +271,10 @@ export class Environment {
|
||||
// If an object or function has a shapeId, it must have been assigned
|
||||
// by Forget (and be present in a builtin or user-defined registry)
|
||||
const shape = this.#shapes.get(shapeId);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
shape !== undefined,
|
||||
`[HIR] Forget internal error: cannot resolve shape ${shapeId}`
|
||||
`[HIR] Forget internal error: cannot resolve shape ${shapeId}`,
|
||||
null
|
||||
);
|
||||
return shape.properties.get(property) ?? null;
|
||||
} else {
|
||||
@@ -284,9 +286,10 @@ export class Environment {
|
||||
const { shapeId } = type;
|
||||
if (shapeId !== null) {
|
||||
const shape = this.#shapes.get(shapeId);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
shape !== undefined,
|
||||
`[HIR] Forget internal error: cannot resolve shape ${shapeId}`
|
||||
`[HIR] Forget internal error: cannot resolve shape ${shapeId}`,
|
||||
null
|
||||
);
|
||||
return shape.functionType;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import * as t from "@babel/types";
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import { Environment } from "./Environment";
|
||||
@@ -922,9 +921,10 @@ const opaqueBlockId = Symbol();
|
||||
export type BlockId = number & { [opaqueBlockId]: "BlockId" };
|
||||
|
||||
export function makeBlockId(id: number): BlockId {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
id >= 0 && Number.isInteger(id),
|
||||
"Expected block id to be a non-negative integer"
|
||||
"Expected block id to be a non-negative integer",
|
||||
null
|
||||
);
|
||||
return id as BlockId;
|
||||
}
|
||||
@@ -937,9 +937,10 @@ const opaqueScopeId = Symbol();
|
||||
export type ScopeId = number & { [opaqueScopeId]: "ScopeId" };
|
||||
|
||||
export function makeScopeId(id: number): ScopeId {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
id >= 0 && Number.isInteger(id),
|
||||
"Expected block id to be a non-negative integer"
|
||||
"Expected block id to be a non-negative integer",
|
||||
null
|
||||
);
|
||||
return id as ScopeId;
|
||||
}
|
||||
@@ -952,9 +953,10 @@ const opaqueIdentifierId = Symbol();
|
||||
export type IdentifierId = number & { [opaqueIdentifierId]: "IdentifierId" };
|
||||
|
||||
export function makeIdentifierId(id: number): IdentifierId {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
id >= 0 && Number.isInteger(id),
|
||||
"Expected identifier id to be a non-negative integer"
|
||||
"Expected identifier id to be a non-negative integer",
|
||||
null
|
||||
);
|
||||
return id as IdentifierId;
|
||||
}
|
||||
@@ -967,9 +969,10 @@ const opaqueInstructionId = Symbol();
|
||||
export type InstructionId = number & { [opaqueInstructionId]: "IdentifierId" };
|
||||
|
||||
export function makeInstructionId(id: number): InstructionId {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
id >= 0 && Number.isInteger(id),
|
||||
"Expected instruction id to be a non-negative integer"
|
||||
"Expected instruction id to be a non-negative integer",
|
||||
null
|
||||
);
|
||||
return id as InstructionId;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
import { Binding, NodePath } from "@babel/traverse";
|
||||
import * as t from "@babel/types";
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import { Environment } from "./Environment";
|
||||
@@ -388,12 +387,13 @@ export default class HIRBuilder {
|
||||
});
|
||||
const value = fn();
|
||||
const last = this.#scopes.pop();
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
last != null &&
|
||||
last.kind === "label" &&
|
||||
last.label === label &&
|
||||
last.breakBlock === breakBlock,
|
||||
"Mismatched label"
|
||||
"Mismatched label",
|
||||
null
|
||||
);
|
||||
return value;
|
||||
}
|
||||
@@ -406,12 +406,13 @@ export default class HIRBuilder {
|
||||
});
|
||||
const value = fn();
|
||||
const last = this.#scopes.pop();
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
last != null &&
|
||||
last.kind === "switch" &&
|
||||
last.label === label &&
|
||||
last.breakBlock === breakBlock,
|
||||
"Mismatched label"
|
||||
"Mismatched label",
|
||||
null
|
||||
);
|
||||
return value;
|
||||
}
|
||||
@@ -440,13 +441,14 @@ export default class HIRBuilder {
|
||||
});
|
||||
const value = fn();
|
||||
const last = this.#scopes.pop();
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
last != null &&
|
||||
last.kind === "loop" &&
|
||||
last.label === label &&
|
||||
last.continueBlock === continueBlock &&
|
||||
last.breakBlock === breakBlock,
|
||||
"Mismatched loops"
|
||||
"Mismatched loops",
|
||||
null
|
||||
);
|
||||
return value;
|
||||
}
|
||||
@@ -462,7 +464,11 @@ export default class HIRBuilder {
|
||||
return scope.breakBlock;
|
||||
}
|
||||
}
|
||||
invariant(false, "Expected a loop or switch to be in scope");
|
||||
CompilerError.invariant(
|
||||
false,
|
||||
"Expected a loop or switch to be in scope",
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,10 +484,14 @@ export default class HIRBuilder {
|
||||
return scope.continueBlock;
|
||||
}
|
||||
} else if (label !== null && scope.label === label) {
|
||||
invariant(false, "Continue may only refer to a labeled loop");
|
||||
CompilerError.invariant(
|
||||
false,
|
||||
"Continue may only refer to a labeled loop",
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
invariant(false, "Expected a loop to be in scope");
|
||||
CompilerError.invariant(false, "Expected a loop to be in scope", null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +511,11 @@ function _shrink(func: HIR): void {
|
||||
return target;
|
||||
}
|
||||
const block = func.blocks.get(blockId);
|
||||
invariant(block != null, "expected block %s to exist", blockId);
|
||||
CompilerError.invariant(
|
||||
block != null,
|
||||
`expected block ${blockId} to exist`,
|
||||
null
|
||||
);
|
||||
target = getTargetIfIndirection(block);
|
||||
if (target !== null) {
|
||||
// the target might also be a simple goto, recurse
|
||||
@@ -717,9 +731,10 @@ export function markInstructionIds(func: HIR): void {
|
||||
const visited = new Set<Instruction>();
|
||||
for (const [_, block] of func.blocks) {
|
||||
for (const instr of block.instructions) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!visited.has(instr),
|
||||
`${printInstruction(instr)} already visited!`
|
||||
`${printInstruction(instr)} already visited!`,
|
||||
instr.loc
|
||||
);
|
||||
visited.add(instr);
|
||||
instr.id = makeInstructionId(++id);
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
BlockId,
|
||||
Effect,
|
||||
@@ -47,10 +47,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
|
||||
const originalPredecessorId = Array.from(block.preds)[0]!;
|
||||
const predecessorId = merged.get(originalPredecessorId);
|
||||
const predecessor = fn.body.blocks.get(predecessorId);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
predecessor !== undefined,
|
||||
"Expected predecessor %s to exist",
|
||||
predecessorId
|
||||
`Expected predecessor ${predecessorId} to exist`,
|
||||
null
|
||||
);
|
||||
if (predecessor.terminal.kind !== "goto" || predecessor.kind !== "block") {
|
||||
// The predecessor is not guaranteed to transfer control to this block,
|
||||
@@ -60,10 +60,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
|
||||
|
||||
// Replace phis in the merged block with canonical assignments to the single operand value
|
||||
for (const phi of block.phis) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
phi.operands.size === 1,
|
||||
"Found a block with a single predecessor but where a phi has multiple (%s) operands",
|
||||
phi.operands.size
|
||||
`Found a block with a single predecessor but where a phi has multiple (${phi.operands.size}) operands`,
|
||||
null
|
||||
);
|
||||
const operand = Array.from(phi.operands.values())[0]!;
|
||||
const instr: Instruction = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { Effect, ValueKind } from "./HIR";
|
||||
import {
|
||||
BuiltInType,
|
||||
@@ -103,9 +103,10 @@ function addShape(
|
||||
functionType,
|
||||
};
|
||||
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!registry.has(id),
|
||||
`[ObjectShape] Could not add shape to registry: name ${id} already exists.`
|
||||
`[ObjectShape] Could not add shape to registry: name ${id} already exists.`,
|
||||
null
|
||||
);
|
||||
registry.set(id, shape);
|
||||
return shape;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import generate from "@babel/generator";
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import DisjointSet from "../Utils/DisjointSet";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import {
|
||||
@@ -467,9 +467,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
}
|
||||
case "TemplateLiteral": {
|
||||
value = "`";
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
instrValue.subexprs.length === instrValue.quasis.length - 1,
|
||||
"Bad assumption about quasi length."
|
||||
"Bad assumption about quasi length.",
|
||||
instrValue.loc
|
||||
);
|
||||
for (let i = 0; i < instrValue.subexprs.length; i++) {
|
||||
value += instrValue.quasis[i].raw;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
|
||||
export type BuiltInType = PrimitiveType | FunctionType | ObjectType;
|
||||
|
||||
@@ -62,9 +62,10 @@ const opaqueTypeId = Symbol();
|
||||
export type TypeId = number & { [opaqueTypeId]: "IdentifierId" };
|
||||
|
||||
export function makeTypeId(id: number): TypeId {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
id >= 0 && Number.isInteger(id),
|
||||
"Expected instruction id to be a non-negative integer"
|
||||
"Expected instruction id to be a non-negative integer",
|
||||
null
|
||||
);
|
||||
return id as TypeId;
|
||||
}
|
||||
|
||||
+4
-3
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
Effect,
|
||||
FunctionExpression,
|
||||
@@ -169,9 +169,10 @@ function infer(
|
||||
// In practice this never really matters because the Component function has no
|
||||
// context refs, so it will never have duplicate deps.
|
||||
for (const place of context) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
place.identifier.name !== null,
|
||||
"context refs should always have a name"
|
||||
"context refs should always have a name",
|
||||
place.loc
|
||||
);
|
||||
|
||||
const effect = mutations.get(place.identifier.name);
|
||||
|
||||
+4
-3
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
Effect,
|
||||
HIRFunction,
|
||||
@@ -108,9 +108,10 @@ export function inferMutableLifetimes(
|
||||
start = Math.min(start, operand.mutableRange.start);
|
||||
end = Math.max(end, operand.mutableRange.end);
|
||||
}
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
start !== Number.MAX_SAFE_INTEGER,
|
||||
"Expected phi to have a start range value"
|
||||
"Expected phi to have a start range value",
|
||||
null
|
||||
);
|
||||
phi.id.mutableRange = {
|
||||
start: makeInstructionId(start),
|
||||
|
||||
+29
-20
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { Environment } from "../HIR";
|
||||
import {
|
||||
@@ -192,9 +191,10 @@ class InferenceState {
|
||||
* (Re)initializes a @param value with its default @param kind.
|
||||
*/
|
||||
initialize(value: InstructionValue, kind: ValueKind): void {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
value.kind !== "LoadLocal",
|
||||
"Expected all top-level identifiers to be defined as variables, not values"
|
||||
"Expected all top-level identifiers to be defined as variables, not values",
|
||||
value.loc
|
||||
);
|
||||
this.#values.set(value, kind);
|
||||
}
|
||||
@@ -204,11 +204,12 @@ class InferenceState {
|
||||
*/
|
||||
kind(place: Place): ValueKind {
|
||||
const values = this.#variables.get(place.identifier.id);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
values != null,
|
||||
`Expected value kind to be initialized at '${printSourceLocation(
|
||||
place.loc
|
||||
)}'`
|
||||
)}'`,
|
||||
place.loc
|
||||
);
|
||||
let mergedKind: ValueKind | null = null;
|
||||
for (const value of values) {
|
||||
@@ -229,10 +230,10 @@ class InferenceState {
|
||||
*/
|
||||
alias(place: Place, value: Place): void {
|
||||
const values = this.#variables.get(value.identifier.id);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
values != null,
|
||||
"Expected value for identifier `%s` to be initialized.",
|
||||
value.identifier.id
|
||||
`Expected value for identifier \`${value.identifier.id}\` to be initialized.`,
|
||||
value.loc
|
||||
);
|
||||
this.#variables.set(place.identifier.id, new Set(values));
|
||||
}
|
||||
@@ -241,9 +242,10 @@ class InferenceState {
|
||||
* Defines (initializing or updating) a variable with a specific kind of value.
|
||||
*/
|
||||
define(place: Place, value: InstructionValue): void {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
this.#values.has(value),
|
||||
`Expected value to be initialized at '${printSourceLocation(value.loc)}'`
|
||||
`Expected value to be initialized at '${printSourceLocation(value.loc)}'`,
|
||||
value.loc
|
||||
);
|
||||
this.#variables.set(place.identifier.id, new Set([value]));
|
||||
}
|
||||
@@ -363,9 +365,10 @@ class InferenceState {
|
||||
break;
|
||||
}
|
||||
case Effect.Unknown: {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
false,
|
||||
"Unexpected unknown effect, expected to infer a precise effect kind"
|
||||
"Unexpected unknown effect, expected to infer a precise effect kind",
|
||||
place.loc
|
||||
);
|
||||
}
|
||||
default: {
|
||||
@@ -375,7 +378,11 @@ class InferenceState {
|
||||
);
|
||||
}
|
||||
}
|
||||
invariant(effect !== null, "Expected effect to be set");
|
||||
CompilerError.invariant(
|
||||
effect !== null,
|
||||
"Expected effect to be set",
|
||||
place.loc
|
||||
);
|
||||
place.effect = effect;
|
||||
}
|
||||
|
||||
@@ -746,9 +753,10 @@ function inferBlock(
|
||||
continue;
|
||||
}
|
||||
case "MethodCall": {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
state.isDefined(instrValue.receiver),
|
||||
"[InferReferenceEffects] Internal error: receiver of PropertyCall should have been defined by corresponding PropertyLoad"
|
||||
"[InferReferenceEffects] Internal error: receiver of PropertyCall should have been defined by corresponding PropertyLoad",
|
||||
instrValue.loc
|
||||
);
|
||||
state.reference(instrValue.property, Effect.Read);
|
||||
|
||||
@@ -882,9 +890,10 @@ function inferBlock(
|
||||
const lvalue = instr.lvalue;
|
||||
lvalue.effect = Effect.ConditionallyMutate;
|
||||
const valueKind = state.kind(instrValue.place);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
valueKind === ValueKind.Mutable || valueKind === ValueKind.Context,
|
||||
"[InferReferenceEffects] Context variables are always mutable."
|
||||
"[InferReferenceEffects] Context variables are always mutable.",
|
||||
instrValue.loc
|
||||
);
|
||||
state.initialize(instrValue, valueKind);
|
||||
state.define(lvalue, instrValue);
|
||||
@@ -971,10 +980,10 @@ function inferBlock(
|
||||
}
|
||||
|
||||
for (const operand of eachInstructionOperand(instr)) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
effectKind != null,
|
||||
"effectKind must be set for instruction value `%s`",
|
||||
instrValue.kind
|
||||
`effectKind must be set for instruction value \`${instrValue.kind}\``,
|
||||
instrValue.loc
|
||||
);
|
||||
state.reference(operand, effectKind);
|
||||
}
|
||||
|
||||
+20
-9
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
BlockId,
|
||||
InstructionId,
|
||||
@@ -70,7 +70,11 @@ class Context {
|
||||
this.#builders.push(builder);
|
||||
fn();
|
||||
const popped = this.#builders.pop();
|
||||
invariant(popped === builder, "Expected push/pop to be called 1:1");
|
||||
CompilerError.invariant(
|
||||
popped === builder,
|
||||
"Expected push/pop to be called 1:1",
|
||||
null
|
||||
);
|
||||
return builder.complete();
|
||||
}
|
||||
}
|
||||
@@ -90,7 +94,11 @@ class Builder {
|
||||
|
||||
append(item: ReactiveStatement, label: BlockId | null): void {
|
||||
if (label !== null) {
|
||||
invariant(item.kind === "terminal", "Only terminals may have a label");
|
||||
CompilerError.invariant(
|
||||
item.kind === "terminal",
|
||||
"Only terminals may have a label",
|
||||
null
|
||||
);
|
||||
item.label = label;
|
||||
}
|
||||
this.#instructions.push(item);
|
||||
@@ -130,9 +138,10 @@ class Builder {
|
||||
// "Expected all scopes to be closed when exiting a block"
|
||||
// );
|
||||
const first = this.#stack[0]!;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
first.kind === "block",
|
||||
"Expected first stack item to be a basic block"
|
||||
"Expected first stack item to be a basic block",
|
||||
null
|
||||
);
|
||||
return first.block;
|
||||
}
|
||||
@@ -164,9 +173,10 @@ function visitBlock(context: Context, block: ReactiveBlock): void {
|
||||
break;
|
||||
}
|
||||
case "scope": {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
false,
|
||||
"Expected the function to not have scopes already assigned"
|
||||
"Expected the function to not have scopes already assigned",
|
||||
null
|
||||
);
|
||||
}
|
||||
default: {
|
||||
@@ -182,10 +192,11 @@ function visitBlock(context: Context, block: ReactiveBlock): void {
|
||||
export function getInstructionScope(
|
||||
instr: ReactiveInstruction
|
||||
): ReactiveScope | null {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
instr.lvalue !== null,
|
||||
"Expected lvalues to not be null when assigning scopes. " +
|
||||
"Pruning lvalues too early can result in missing scope information."
|
||||
"Pruning lvalues too early can result in missing scope information.",
|
||||
instr.loc
|
||||
);
|
||||
for (const operand of eachInstructionLValue(instr)) {
|
||||
const operandScope = getPlaceScope(instr.id, operand);
|
||||
|
||||
+51
-37
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
BasicBlock,
|
||||
@@ -66,9 +65,10 @@ class Driver {
|
||||
}
|
||||
|
||||
visitBlock(block: BasicBlock, blockValue: ReactiveBlock): void {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!this.cx.emitted.has(block.id),
|
||||
`Cannot emit the same block twice: bb${block.id}`
|
||||
`Cannot emit the same block twice: bb${block.id}`,
|
||||
null
|
||||
);
|
||||
this.cx.emitted.add(block.id);
|
||||
for (const instruction of block.instructions) {
|
||||
@@ -252,9 +252,10 @@ class Driver {
|
||||
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
|
||||
} else {
|
||||
const break_ = this.visitBreak(terminal.loop, null);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
break_ !== null,
|
||||
"If loop body is already scheduled it must be a break"
|
||||
"If loop body is already scheduled it must be a break",
|
||||
null
|
||||
);
|
||||
loopBody = [break_];
|
||||
}
|
||||
@@ -308,9 +309,10 @@ class Driver {
|
||||
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
|
||||
} else {
|
||||
const break_ = this.visitBreak(terminal.loop, null);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
break_ !== null,
|
||||
"If loop body is already scheduled it must be a break"
|
||||
"If loop body is already scheduled it must be a break",
|
||||
null
|
||||
);
|
||||
loopBody = [break_];
|
||||
}
|
||||
@@ -392,9 +394,10 @@ class Driver {
|
||||
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
|
||||
} else {
|
||||
const break_ = this.visitBreak(terminal.loop, null);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
break_ !== null,
|
||||
"If loop body is already scheduled it must be a break"
|
||||
"If loop body is already scheduled it must be a break",
|
||||
null
|
||||
);
|
||||
loopBody = [break_];
|
||||
}
|
||||
@@ -467,9 +470,10 @@ class Driver {
|
||||
loopBody = this.traverseBlock(this.cx.ir.blocks.get(loopId)!);
|
||||
} else {
|
||||
const break_ = this.visitBreak(terminal.loop, null);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
break_ !== null,
|
||||
"If loop body is already scheduled it must be a break"
|
||||
"If loop body is already scheduled it must be a break",
|
||||
null
|
||||
);
|
||||
loopBody = [break_];
|
||||
}
|
||||
@@ -626,7 +630,11 @@ class Driver {
|
||||
break;
|
||||
}
|
||||
case "unsupported": {
|
||||
invariant(false, "Unexpected unsupported terminal");
|
||||
CompilerError.invariant(
|
||||
false,
|
||||
"Unexpected unsupported terminal",
|
||||
terminal.loc
|
||||
);
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(terminal, "Unexpected terminal");
|
||||
@@ -654,10 +662,11 @@ class Driver {
|
||||
};
|
||||
} else if (defaultBlock.instructions.length === 1) {
|
||||
const instr = defaultBlock.instructions[0]!;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
instr.lvalue.identifier.id ===
|
||||
defaultBlock.terminal.test.identifier.id,
|
||||
"Expected branch block to end in an instruction that sets the test value"
|
||||
"Expected branch block to end in an instruction that sets the test value",
|
||||
instr.lvalue.loc
|
||||
);
|
||||
return {
|
||||
block: defaultBlock.id,
|
||||
@@ -684,9 +693,10 @@ class Driver {
|
||||
} else if (defaultBlock.terminal.kind === "goto") {
|
||||
const instructions = defaultBlock.instructions;
|
||||
if (instructions.length === 0) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
false,
|
||||
"Expected goto value block to have at least one instruction"
|
||||
"Expected goto value block to have at least one instruction",
|
||||
null
|
||||
);
|
||||
} else if (defaultBlock.instructions.length === 1) {
|
||||
const instr = defaultBlock.instructions[0]!;
|
||||
@@ -782,10 +792,10 @@ class Driver {
|
||||
case "optional": {
|
||||
const test = this.visitValueBlock(terminal.test, terminal.loc);
|
||||
const testBlock = this.cx.ir.blocks.get(test.block)!;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
testBlock.terminal.kind === "branch",
|
||||
"Unexpected terminal kind '%s' for optional call test block",
|
||||
testBlock.terminal.kind
|
||||
`Unexpected terminal kind '${testBlock.terminal.kind}' for optional call test block`,
|
||||
testBlock.terminal.loc
|
||||
);
|
||||
const consequent = this.visitValueBlock(
|
||||
testBlock.terminal.consequent,
|
||||
@@ -821,10 +831,10 @@ class Driver {
|
||||
case "logical": {
|
||||
const test = this.visitValueBlock(terminal.test, terminal.loc);
|
||||
const testBlock = this.cx.ir.blocks.get(test.block)!;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
testBlock.terminal.kind === "branch",
|
||||
"Unexpected terminal kind '%s' for logical test block",
|
||||
testBlock.terminal.kind
|
||||
`Unexpected terminal kind '${testBlock.terminal.kind}' for logical test block`,
|
||||
testBlock.terminal.loc
|
||||
);
|
||||
|
||||
const leftFinal = this.visitValueBlock(
|
||||
@@ -866,10 +876,10 @@ class Driver {
|
||||
case "ternary": {
|
||||
const test = this.visitValueBlock(terminal.test, terminal.loc);
|
||||
const testBlock = this.cx.ir.blocks.get(test.block)!;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
testBlock.terminal.kind === "branch",
|
||||
"Unexpected terminal kind '%s' for ternary test block",
|
||||
testBlock.terminal.kind
|
||||
`Unexpected terminal kind '${testBlock.terminal.kind}' for ternary test block`,
|
||||
testBlock.terminal.loc
|
||||
);
|
||||
const consequent = this.visitValueBlock(
|
||||
testBlock.terminal.consequent,
|
||||
@@ -895,10 +905,10 @@ class Driver {
|
||||
};
|
||||
}
|
||||
default: {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
false,
|
||||
"Unexpected value block terminal kind '%s'",
|
||||
terminal.kind
|
||||
`Unexpected value block terminal kind '${terminal.kind}'`,
|
||||
terminal.loc
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -914,7 +924,7 @@ class Driver {
|
||||
): ReactiveTerminalStatement<ReactiveBreakTerminal> {
|
||||
const target = this.cx.getBreakTarget(block);
|
||||
if (target === null) {
|
||||
invariant(false, "Expected a break target");
|
||||
CompilerError.invariant(false, "Expected a break target", null);
|
||||
}
|
||||
switch (target.type) {
|
||||
case "implicit": {
|
||||
@@ -952,9 +962,10 @@ class Driver {
|
||||
id: InstructionId
|
||||
): ReactiveTerminalStatement<ReactiveContinueTerminal> {
|
||||
const target = this.cx.getContinueTarget(block);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
target !== null,
|
||||
`Expected continue target to be scheduled for bb${block}`
|
||||
`Expected continue target to be scheduled for bb${block}`,
|
||||
null
|
||||
);
|
||||
switch (target.type) {
|
||||
case "implicit": {
|
||||
@@ -1035,9 +1046,10 @@ class Context {
|
||||
*/
|
||||
schedule(block: BlockId, type: "if" | "switch" | "case"): number {
|
||||
const id = this.#nextScheduleId++;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!this.#scheduled.has(block),
|
||||
`Break block is already scheduled: bb${block}`
|
||||
`Break block is already scheduled: bb${block}`,
|
||||
null
|
||||
);
|
||||
this.#scheduled.add(block);
|
||||
this.#controlFlowStack.push({ block, id, type });
|
||||
@@ -1052,9 +1064,10 @@ class Context {
|
||||
const id = this.#nextScheduleId++;
|
||||
const ownsBlock = !this.#scheduled.has(fallthroughBlock);
|
||||
this.#scheduled.add(fallthroughBlock);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!this.#scheduled.has(continueBlock),
|
||||
`Continue block is already scheduled: bb${continueBlock}`
|
||||
`Continue block is already scheduled: bb${continueBlock}`,
|
||||
null
|
||||
);
|
||||
this.#scheduled.add(continueBlock);
|
||||
let ownsLoop = false;
|
||||
@@ -1080,9 +1093,10 @@ class Context {
|
||||
*/
|
||||
unschedule(scheduleId: number): void {
|
||||
const last = this.#controlFlowStack.pop();
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
last !== undefined && last.id === scheduleId,
|
||||
"Can only unschedule the last target"
|
||||
"Can only unschedule the last target",
|
||||
null
|
||||
);
|
||||
if (last.type !== "loop" || last.ownsBlock !== null) {
|
||||
this.#scheduled.delete(last.block);
|
||||
|
||||
+35
-25
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import * as t from "@babel/types";
|
||||
import invariant from "invariant";
|
||||
import { pruneUnusedLValues, pruneUnusedLabels, renameVariables } from ".";
|
||||
import { CompilerError, ErrorSeverity } from "../CompilerError";
|
||||
import { Environment } from "../HIR";
|
||||
@@ -216,10 +215,10 @@ function codegenReactiveScope(
|
||||
firstOutputIndex = index;
|
||||
}
|
||||
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
identifier.name != null,
|
||||
"Expected identifier '@%s' to be named",
|
||||
identifier.id
|
||||
`Expected identifier '@${identifier.id}' to be named`,
|
||||
null
|
||||
);
|
||||
|
||||
const name = convertIdentifier(identifier);
|
||||
@@ -284,10 +283,10 @@ function codegenReactiveScope(
|
||||
null as t.Expression | null
|
||||
);
|
||||
if (testCondition === null) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
firstOutputIndex !== null,
|
||||
"Expected scope '@%s' to have at least one declaration",
|
||||
scope.id
|
||||
`Expected scope '@${scope.id}' to have at least one declaration`,
|
||||
null
|
||||
);
|
||||
testCondition = t.binaryExpression(
|
||||
"===",
|
||||
@@ -542,7 +541,11 @@ function codegenInstructionNullable(
|
||||
]);
|
||||
}
|
||||
case InstructionKind.Reassign: {
|
||||
invariant(value !== null, "Expected a value for reassignment");
|
||||
CompilerError.invariant(
|
||||
value !== null,
|
||||
"Expected a value for reassignment",
|
||||
instr.value.loc
|
||||
);
|
||||
const expr = t.assignmentExpression("=", codegenLValue(lvalue), value);
|
||||
if (instr.lvalue !== null) {
|
||||
if (instr.value.kind !== "StoreContext") {
|
||||
@@ -589,9 +592,10 @@ function codegenForInit(
|
||||
}))
|
||||
).body;
|
||||
const declaration = body[0]!;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
declaration.type === "VariableDeclaration",
|
||||
"Expected a variable declaration"
|
||||
"Expected a variable declaration",
|
||||
declaration.loc ?? null
|
||||
);
|
||||
return declaration;
|
||||
} else {
|
||||
@@ -740,9 +744,10 @@ function codegenInstructionValue(
|
||||
switch (optionalValue.type) {
|
||||
case "OptionalCallExpression":
|
||||
case "CallExpression": {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
t.isExpression(optionalValue.callee),
|
||||
"v8 intrinsics are validated during lowering"
|
||||
"v8 intrinsics are validated during lowering",
|
||||
optionalValue.callee.loc ?? null
|
||||
);
|
||||
value = t.optionalCallExpression(
|
||||
optionalValue.callee,
|
||||
@@ -754,9 +759,10 @@ function codegenInstructionValue(
|
||||
case "OptionalMemberExpression":
|
||||
case "MemberExpression": {
|
||||
const property = optionalValue.property;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
t.isExpression(property),
|
||||
"Private names are validated during lowering"
|
||||
"Private names are validated during lowering",
|
||||
property.loc ?? null
|
||||
);
|
||||
value = t.optionalMemberExpression(
|
||||
optionalValue.object,
|
||||
@@ -779,19 +785,21 @@ function codegenInstructionValue(
|
||||
}
|
||||
case "MethodCall": {
|
||||
const memberExpr = codegenPlace(cx, instrValue.property);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
t.isMemberExpression(memberExpr) ||
|
||||
t.isOptionalMemberExpression(memberExpr),
|
||||
"[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. " +
|
||||
`Got a '${memberExpr.type}'`
|
||||
`Got a '${memberExpr.type}'`,
|
||||
memberExpr.loc ?? null
|
||||
);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
t.isNodesEquivalent(
|
||||
memberExpr.object,
|
||||
codegenPlace(cx, instrValue.receiver)
|
||||
),
|
||||
"[Codegen] Internal error: Forget should always generate MethodCall::property " +
|
||||
"as a MemberExpression of MethodCall::receiver"
|
||||
"as a MemberExpression of MethodCall::receiver",
|
||||
memberExpr.loc ?? null
|
||||
);
|
||||
const args = instrValue.args.map((arg) => codegenArgument(cx, arg));
|
||||
value = createCallExpression(instrValue.loc, memberExpr, args);
|
||||
@@ -843,10 +851,10 @@ function codegenInstructionValue(
|
||||
} else if (tagValue.type === "MemberExpression") {
|
||||
tag = convertMemberExpressionToJsx(tagValue);
|
||||
} else {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
tagValue.type === "StringLiteral",
|
||||
"Expected JSX tag to be an identifier or string, got '%s'",
|
||||
tagValue.type
|
||||
`Expected JSX tag to be an identifier or string, got '${tagValue.type}'`,
|
||||
tagValue.loc ?? null
|
||||
);
|
||||
if (tagValue.value.indexOf(":") >= 0) {
|
||||
const [namespace, name] = tagValue.value.split(":", 2);
|
||||
@@ -1185,17 +1193,19 @@ function codegenJsxElement(
|
||||
function convertMemberExpressionToJsx(
|
||||
expr: t.MemberExpression
|
||||
): t.JSXMemberExpression {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
expr.property.type === "Identifier",
|
||||
"Expected JSX member expression property to be a string"
|
||||
"Expected JSX member expression property to be a string",
|
||||
expr.loc ?? null
|
||||
);
|
||||
const property = t.jsxIdentifier(expr.property.name);
|
||||
if (expr.object.type === "Identifier") {
|
||||
return t.jsxMemberExpression(t.jsxIdentifier(expr.object.name), property);
|
||||
} else {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
expr.object.type === "MemberExpression",
|
||||
"Expected JSX member expression to be an identifier or nested member expression"
|
||||
"Expected JSX member expression to be an identifier or nested member expression",
|
||||
expr.object.loc ?? null
|
||||
);
|
||||
const object = convertMemberExpressionToJsx(expr.object);
|
||||
return t.jsxMemberExpression(object, property);
|
||||
|
||||
+13
-9
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { Identifier, ReactiveScopeDependency } from "../HIR";
|
||||
import { printIdentifier } from "../HIR/PrintHIR";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
@@ -122,11 +122,12 @@ export class ReactiveScopeDependencyTree {
|
||||
const results = new Set<ReactiveScopeDependency>();
|
||||
for (const [rootId, rootNode] of this.#roots.entries()) {
|
||||
const deps = deriveMinimalDependenciesInSubtree(rootNode);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
deps.every(
|
||||
(dep) => dep.accessType === PropertyAccessType.UnconditionalDependency
|
||||
),
|
||||
"[PropagateScopeDependencies] All dependencies must be reduced to unconditional dependencies."
|
||||
"[PropagateScopeDependencies] All dependencies must be reduced to unconditional dependencies.",
|
||||
null
|
||||
);
|
||||
|
||||
for (const dep of deps) {
|
||||
@@ -162,9 +163,10 @@ export class ReactiveScopeDependencyTree {
|
||||
promoteDepsFromExhaustiveConditionals(
|
||||
trees: Array<ReactiveScopeDependencyTree>
|
||||
): void {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
trees.length > 1,
|
||||
"Expected trees to be at least 2 elements long."
|
||||
"Expected trees to be at least 2 elements long.",
|
||||
null
|
||||
);
|
||||
|
||||
for (const [id, root] of this.#roots) {
|
||||
@@ -456,16 +458,18 @@ function addSubtreeIntersection(
|
||||
otherProperties: Array<Map<string, DependencyNode>>,
|
||||
currProperties: Map<string, DependencyNode>
|
||||
): void {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
otherProperties.length > 1,
|
||||
"[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long."
|
||||
"[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long.",
|
||||
null
|
||||
);
|
||||
|
||||
otherProperties.forEach((properties) =>
|
||||
properties.forEach((node, _) =>
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!isUnconditional(node.accessType),
|
||||
"[DeriveMinimalDependencies] Expected otherProperties to only contain unconditional nodes!"
|
||||
"[DeriveMinimalDependencies] Expected otherProperties to only contain unconditional nodes!",
|
||||
null
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
+6
-2
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
ReactiveFunction,
|
||||
ReactiveScopeBlock,
|
||||
@@ -226,7 +226,11 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
|
||||
writer.writeLine(`${prefix}: {`);
|
||||
writer.indented(() => {
|
||||
const block = case_.block;
|
||||
invariant(block != null, "Expected case to have a block");
|
||||
CompilerError.invariant(
|
||||
block != null,
|
||||
"Expected case to have a block",
|
||||
case_.test?.loc ?? null
|
||||
);
|
||||
printReactiveInstructions(writer, block);
|
||||
});
|
||||
writer.writeLine("}");
|
||||
|
||||
+11
-6
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import prettyFormat from "pretty-format";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
@@ -244,9 +243,10 @@ class State {
|
||||
this.scopes.set(scope.id, node);
|
||||
}
|
||||
const identifierNode = this.identifiers.get(identifier);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
identifierNode !== undefined,
|
||||
"Expected identifier to be initialized"
|
||||
"Expected identifier to be initialized",
|
||||
place.loc
|
||||
);
|
||||
identifierNode.scopes.add(scope.id);
|
||||
}
|
||||
@@ -264,9 +264,10 @@ function computeMemoizedIdentifiers(state: State): Set<IdentifierId> {
|
||||
// Visit an identifier, optionally forcing it to be memoized
|
||||
function visit(id: IdentifierId, forceMemoize: boolean = false): boolean {
|
||||
const node = state.identifiers.get(id);
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
node !== undefined,
|
||||
`Expected a node for all identifiers, none found for '${id}'`
|
||||
`Expected a node for all identifiers, none found for '${id}'`,
|
||||
null
|
||||
);
|
||||
if (node.seen) {
|
||||
return node.memoized;
|
||||
@@ -302,7 +303,11 @@ function computeMemoizedIdentifiers(state: State): Set<IdentifierId> {
|
||||
// Force all the scope's optionally-memoizeable dependencies (not "Never") to be memoized
|
||||
function forceMemoizeScopeDependencies(id: ScopeId): void {
|
||||
const node = state.scopes.get(id);
|
||||
invariant(node !== undefined, "Expected a node for all scopes");
|
||||
CompilerError.invariant(
|
||||
node !== undefined,
|
||||
"Expected a node for all scopes",
|
||||
null
|
||||
);
|
||||
if (node.seen) {
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
Identifier,
|
||||
IdentifierId,
|
||||
@@ -103,6 +103,6 @@ class Scopes {
|
||||
this.#stack.push(next);
|
||||
fn();
|
||||
const last = this.#stack.pop();
|
||||
invariant(last === next, "Mismatch push/pop calls");
|
||||
CompilerError.invariant(last === next, "Mismatch push/pop calls", null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { BlockId, HIRFunction, Identifier, Place } from "../HIR/HIR";
|
||||
import {
|
||||
eachInstructionLValue,
|
||||
@@ -83,7 +83,11 @@ export function eliminateRedundantPhi(fn: HIRFunction): void {
|
||||
same = operand;
|
||||
}
|
||||
}
|
||||
invariant(same !== null, "Expected phis to be non-empty");
|
||||
CompilerError.invariant(
|
||||
same !== null,
|
||||
"Expected phis to be non-empty",
|
||||
null
|
||||
);
|
||||
rewrites.set(phi.id, same);
|
||||
block.phis.delete(phi);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { Environment } from "../HIR/Environment";
|
||||
import {
|
||||
@@ -68,9 +67,10 @@ class SSABuilder {
|
||||
}
|
||||
|
||||
state(): State {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
this.#current !== null,
|
||||
"we need to be in a block to access state!"
|
||||
"we need to be in a block to access state!",
|
||||
null
|
||||
);
|
||||
return this.#states.get(this.#current)!;
|
||||
}
|
||||
@@ -237,9 +237,10 @@ function enterSSAImpl(
|
||||
): void {
|
||||
const visitedBlocks: Set<BasicBlock> = new Set();
|
||||
for (const [blockId, block] of func.body.blocks) {
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
!visitedBlocks.has(block),
|
||||
`found a cycle! visiting bb${block.id} again`
|
||||
`found a cycle! visiting bb${block.id} again`,
|
||||
null
|
||||
);
|
||||
visitedBlocks.add(block);
|
||||
|
||||
@@ -269,9 +270,10 @@ function enterSSAImpl(
|
||||
) {
|
||||
const loweredFunc = instr.value.loweredFunc;
|
||||
const entry = loweredFunc.body.blocks.get(loweredFunc.body.entry)!;
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
entry.preds.size === 0,
|
||||
"Expected function expression entry block to have zero predecessors"
|
||||
"Expected function expression entry block to have zero predecessors",
|
||||
null
|
||||
);
|
||||
entry.preds.add(blockId);
|
||||
builder.defineFunction(loweredFunc);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
BasicBlock,
|
||||
@@ -220,7 +219,11 @@ export function leaveSSA(fn: HIRFunction): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
invariant(kind !== null, "Expected at least one operand");
|
||||
CompilerError.invariant(
|
||||
kind !== null,
|
||||
"Expected at least one operand",
|
||||
null
|
||||
);
|
||||
value.lvalue.kind = kind;
|
||||
}
|
||||
rewritePlace(lvalue, rewrites, declarations);
|
||||
@@ -353,9 +356,10 @@ export function leaveSSA(fn: HIRFunction): void {
|
||||
|
||||
// If we never saw a declaration for this phi, it may have been pruned by DCE, so synthesize
|
||||
// a new Let binding
|
||||
invariant(
|
||||
CompilerError.invariant(
|
||||
phi.id.name != null,
|
||||
"Expected reassignment phis to have a name"
|
||||
"Expected reassignment phis to have a name",
|
||||
null
|
||||
);
|
||||
const declaration = declarations.get(phi.id.name);
|
||||
if (declaration === undefined) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import * as t from "@babel/types";
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import { Environment } from "../HIR";
|
||||
import {
|
||||
HIRFunction,
|
||||
@@ -342,7 +342,11 @@ class Unifier {
|
||||
if (type.kind === "Phi") {
|
||||
const operands = new Set(type.operands.map((i) => this.get(i).kind));
|
||||
|
||||
invariant(operands.size > 0, "there should be at least one operand");
|
||||
CompilerError.invariant(
|
||||
operands.size > 0,
|
||||
"there should be at least one operand",
|
||||
null
|
||||
);
|
||||
const kind = operands.values().next().value;
|
||||
|
||||
// there's only one unique type and it's not a type var
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { CompilerError } from "../CompilerError";
|
||||
|
||||
/**
|
||||
* Represents items which form disjoint sets.
|
||||
@@ -20,7 +20,11 @@ export default class DisjointSet<T> {
|
||||
*/
|
||||
union(items: Array<T>): void {
|
||||
const first = items.shift();
|
||||
invariant(first != null, "Expected set to be non-empty");
|
||||
CompilerError.invariant(
|
||||
first != null,
|
||||
"Expected set to be non-empty",
|
||||
null
|
||||
);
|
||||
// determine an arbitrary "root" for this set: if the first
|
||||
// item already has a root then use that, otherwise the first item
|
||||
// will be the new root.
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ function useFoo(props) {
|
||||
## Error
|
||||
|
||||
```
|
||||
[InferReferenceEffects] Context variables are always mutable.
|
||||
[ReactForget] Invariant: [InferReferenceEffects] Context variables are always mutable. (5:5)
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user