Combine dependency collection and propagation, more precise collection

I realized that properly propagating scope dependencies requires reusing the 
same logic as dependency collection itself: a dependency of an inner scope 
should only be propagated upward if the dependency was declared before the outer 
scope, for example. So this PR reimplements dependency collection in the 
propagation pass. 

At the same time I made a few other improvements: 

* Don't report dependencies that are "constant". This is a bit simplistic for 
now, we can use a more advanced analysis later. 

* Try to avoid creating duplicate dependencies. 

This addresses the todo from the previous PR (flattening scopes in loops) since 
now we don't need to compute deps until after that runs. As a follow-up i'll 
remove the existing dependency collection.
This commit is contained in:
Joe Savona
2022-12-14 08:42:39 -08:00
parent d909ae0434
commit dd1ff4dc30
47 changed files with 392 additions and 120 deletions
@@ -37,6 +37,7 @@ export function instructionInScope(
class ScopeDependenciesVisitor
implements Visitor<void, void, void, void, InstructionValue, void, void>
{
#kinds: Map<Identifier, DeclKind> = new Map();
#identifiers: Map<Identifier, InstructionId> = new Map();
// Scopes that are currently active at this point in the traversal
#activeScopes: Set<ReactiveScope> = new Set();
@@ -49,9 +50,11 @@ class ScopeDependenciesVisitor
constructor(fn: HIRFunction) {
if (fn.id !== null) {
this.#identifiers.set(fn.id, makeInstructionId(0));
this.#kinds.set(fn.id, DeclKind.Const);
}
for (const param of fn.params) {
this.#identifiers.set(param.identifier, makeInstructionId(0));
this.#kinds.set(param.identifier, DeclKind.Dynamic);
}
}
@@ -190,3 +193,56 @@ class ScopeDependenciesVisitor
}
leaveInitBlock(block: void): void {}
}
enum DeclKind {
Const = "Const",
Dynamic = "Dynamic",
}
function visitOperand(
operand: Place,
dependencies: Set<Place>,
declarations: Map<Identifier, DeclKind>
): void {
const kind = declarations.get(operand.identifier);
if (kind === undefined) {
// TODO: global, ignore
return;
} else if (kind === DeclKind.Const) {
// constant, dont need to add a dep
return;
} else {
for (const dep of dependencies) {
// not the same identifier
if (dep.identifier !== operand.identifier) {
continue;
}
const depPath = dep.memberPath;
// existing dep covers all paths
if (depPath === null) {
return;
}
const operandPath = operand.memberPath;
// existing dep is for a path, this operand covers all paths so swap them
if (operandPath === null) {
dependencies.delete(dep);
dependencies.add(operand);
return;
}
// both the operand and dep have paths, determine if the existing path
// is a subset of the new path
let commonPathIndex = 0;
while (
commonPathIndex < operandPath.length &&
commonPathIndex < depPath.length &&
operandPath[commonPathIndex] === depPath[commonPathIndex]
) {
commonPathIndex++;
}
if (commonPathIndex === depPath.length) {
return;
}
}
dependencies.add(operand);
}
}
@@ -6,57 +6,160 @@
*/
import { assertExhaustive } from "../Common/utils";
import { Place, ReactiveBasicBlock, ReactiveFunction } from "./HIR";
import {
Identifier,
Instruction,
InstructionId,
InstructionKind,
InstructionValue,
makeInstructionId,
Place,
ReactiveBasicBlock,
ReactiveFunction,
ReactiveValueBlock,
} from "./HIR";
import { eachInstructionValueOperand } from "./visitors";
/**
* Propagates the dependencies of each scope to its parent scope(s).
* Infers the dependencies of each scope to include variables whose values
* are non-stable and created prior to the start of the scope. Also propagates
* dependencies upwards, so that parent scope dependencies are the union of
* their direct dependencies and those of their child scopes.
*/
export function propagateScopeDependencies(fn: ReactiveFunction): void {
const dependencies: Set<Place> = new Set();
visit(fn.body, dependencies);
const declarations: DeclMap = new Map();
if (fn.id !== null) {
declarations.set(fn.id, { kind: DeclKind.Const, id: makeInstructionId(0) });
}
for (const param of fn.params) {
declarations.set(param.identifier, {
kind: DeclKind.Dynamic,
id: makeInstructionId(0),
});
}
visit(fn.body, dependencies, declarations, null);
}
function visit(block: ReactiveBasicBlock, dependencies: Set<Place>): void {
enum DeclKind {
Const = "Const",
Dynamic = "Dynamic",
}
type DeclMap = Map<Identifier, { kind: DeclKind; id: InstructionId }>;
function visit(
block: ReactiveBasicBlock,
dependencies: Set<Place>,
declarations: DeclMap,
scopeStart: InstructionId | null
): void {
for (const item of block) {
switch (item.kind) {
case "block": {
visit(item.instructions, item.dependencies);
for (const dep of item.dependencies) {
dependencies.add(dep);
const scopeDependencies: Set<Place> = new Set();
// TODO: it would be sufficient to use a single mapping of declarations
const scopeDeclarations: DeclMap = new Map(declarations);
visit(
item.instructions,
scopeDependencies,
scopeDeclarations,
item.range.start
);
item.dependencies = scopeDependencies;
for (const dep of scopeDependencies) {
// propagate dependencies upward using the same rules as
// normal dependency collection. child scopes may have dependencies
// on values created within the outer scope, which necessarily cannot
// be dependencies of the outer scope
visitOperand(dep, dependencies, declarations, scopeStart);
}
for (const [ident, kind] of scopeDeclarations) {
declarations.set(ident, kind);
}
break;
}
case "instruction": {
visitInstruction(
item.instruction,
dependencies,
declarations,
scopeStart
);
break;
}
case "terminal": {
const terminal = item.terminal;
switch (terminal.kind) {
case "break":
case "continue":
case "return":
case "continue": {
break;
}
case "return": {
if (terminal.value !== null) {
visitOperand(
terminal.value,
dependencies,
declarations,
scopeStart
);
}
break;
}
case "throw": {
visitOperand(
terminal.value,
dependencies,
declarations,
scopeStart
);
break;
}
case "for": {
visit(terminal.loop, dependencies);
visitValueBlock(
terminal.init,
dependencies,
declarations,
scopeStart
);
visitValueBlock(
terminal.test,
dependencies,
declarations,
scopeStart
);
visitValueBlock(
terminal.update,
dependencies,
declarations,
scopeStart
);
visit(terminal.loop, dependencies, declarations, scopeStart);
break;
}
case "while": {
visit(terminal.loop, dependencies);
visitValueBlock(
terminal.test,
dependencies,
declarations,
scopeStart
);
visit(terminal.loop, dependencies, declarations, scopeStart);
break;
}
case "if": {
visit(terminal.consequent, dependencies);
visitOperand(terminal.test, dependencies, declarations, scopeStart);
visit(terminal.consequent, dependencies, declarations, scopeStart);
if (terminal.alternate !== null) {
visit(terminal.alternate, dependencies);
visit(terminal.alternate, dependencies, declarations, scopeStart);
}
break;
}
case "switch": {
visitOperand(terminal.test, dependencies, declarations, scopeStart);
for (const case_ of terminal.cases) {
if (case_.block !== undefined) {
visit(case_.block, dependencies);
visit(case_.block, dependencies, declarations, scopeStart);
}
}
break;
@@ -76,3 +179,141 @@ function visit(block: ReactiveBasicBlock, dependencies: Set<Place>): void {
}
}
}
function visitValueBlock(
block: ReactiveValueBlock,
dependencies: Set<Place>,
declarations: DeclMap,
scopeStart: InstructionId | null
): void {
for (const initItem of block.instructions) {
if (initItem.kind === "instruction") {
visitInstruction(
initItem.instruction,
dependencies,
declarations,
scopeStart
);
}
}
if (block.value !== null) {
visitInstructionValue(block.value, dependencies, declarations, scopeStart);
}
}
function visitOperand(
operand: Place,
dependencies: Set<Place>,
declarations: DeclMap,
scopeStart: InstructionId | null
): void {
const decl = declarations.get(operand.identifier);
if (decl === undefined) {
// Probably a global, ignore for now
// TODO @josephsavona: improve handling of globals
return;
} else if (decl.kind === DeclKind.Const) {
// constant, dont need to add a dep
return;
} else if (scopeStart !== null && decl.id < scopeStart) {
// Check if there is an existing dependency that describes this operand
for (const dep of dependencies) {
// not the same identifier
if (dep.identifier !== operand.identifier) {
continue;
}
const depPath = dep.memberPath;
// existing dep covers all paths
if (depPath === null) {
return;
}
const operandPath = operand.memberPath;
// existing dep is for a path, this operand covers all paths so swap them
if (operandPath === null) {
dependencies.delete(dep);
dependencies.add(operand);
return;
}
// both the operand and dep have paths, determine if the existing path
// is a subset of the new path
let commonPathIndex = 0;
while (
commonPathIndex < operandPath.length &&
commonPathIndex < depPath.length &&
operandPath[commonPathIndex] === depPath[commonPathIndex]
) {
commonPathIndex++;
}
if (commonPathIndex === depPath.length) {
return;
}
}
dependencies.add(operand);
}
}
function visitInstructionValue(
value: InstructionValue,
dependencies: Set<Place>,
declarations: DeclMap,
scopeStart: InstructionId | null
): void {
for (const operand of eachInstructionValueOperand(value)) {
// check for method invocation, we want to depend on the callee, not the method
if (
value.kind === "CallExpression" &&
operand === value.callee &&
operand.memberPath !== null
) {
const callee = {
...operand,
memberPath: operand.memberPath.slice(0, -1),
};
visitOperand(callee, dependencies, declarations, scopeStart);
} else {
visitOperand(operand, dependencies, declarations, scopeStart);
}
}
}
function visitInstruction(
instr: Instruction,
dependencies: Set<Place>,
declarations: DeclMap,
scopeStart: InstructionId | null
): void {
visitInstructionValue(instr.value, dependencies, declarations, scopeStart);
const { lvalue } = instr;
if (
lvalue !== null &&
lvalue.kind !== InstructionKind.Reassign &&
lvalue.place.memberPath === null
) {
const kind = valueKind(instr.value);
declarations.set(lvalue.place.identifier, { kind, id: instr.id });
}
}
function valueKind(value: InstructionValue): DeclKind {
switch (value.kind) {
case "BinaryExpression":
case "JSXText":
case "Primitive": {
return DeclKind.Const;
}
case "Identifier":
case "ArrayExpression":
case "CallExpression":
case "JsxExpression":
case "JsxFragment":
case "NewExpression":
case "ObjectExpression":
case "OtherStatement":
case "UnaryExpression": {
return DeclKind.Dynamic;
}
default: {
assertExhaustive(value, `Unexpected value kind '${(value as any).kind}'`);
}
}
}
@@ -47,7 +47,7 @@ scope0 [1:7]:
function Component(
props,
) {
scope @0 [1:7] deps=[read props$3.a, read props$3.d, read props$3.c] {
scope @0 [1:7] deps=[read props$3.a, read props$3.b, read props$3.d, read props$3.c] {
[1] Const mutate a$4_@0:TFunction[1:7] = Array []
[2] Call mutate a$4_@0.push(read props$3.a)
if (read props$3.b) {
@@ -52,8 +52,6 @@ bb0:
[7] Const mutate $14:TPrimitive = "div"
[8] Const mutate $15_@2 = JSX <read $14:TPrimitive a={read a$10_@0:TObject} b={freeze b$11_@0:TObject} ></read $14:TPrimitive>
[9] Return read $15_@2
scope0 [1:7]:
- dependency: read $12:TPrimitive
scope1 [5:6]:
- dependency: read $12:TPrimitive
scope2 [8:9]:
@@ -68,18 +66,18 @@ scope2 [8:9]:
function Component(
props,
) {
scope @0 [1:7] deps=[read $12:TPrimitive] {
scope @0 [1:7] deps=[] {
[1] Const mutate a$10_@0:TObject[1:7] = Array []
[2] Const mutate b$11_@0:TObject[1:7] = Object { }
[3] Call mutate foo$4:TFunction(mutate a$10_@0:TObject, mutate b$11_@0:TObject)
[4] Const mutate $12:TPrimitive = "div"
scope @1 [5:6] deps=[read $12:TPrimitive] {
scope @1 [5:6] deps=[freeze a$10_@0:TObject] {
[5] Const mutate _$13_@1 = JSX <read $12:TPrimitive a={freeze a$10_@0:TObject} ></read $12:TPrimitive>
}
[6] Call mutate foo$4:TFunction(mutate b$11_@0:TObject)
}
[7] Const mutate $14:TPrimitive = "div"
scope @2 [8:9] deps=[read $14:TPrimitive, read a$10_@0:TObject, freeze b$11_@0:TObject] {
scope @2 [8:9] deps=[read a$10_@0:TObject, freeze b$11_@0:TObject] {
[8] Const mutate $15_@2 = JSX <read $14:TPrimitive a={read a$10_@0:TObject} b={freeze b$11_@0:TObject} ></read $14:TPrimitive>
}
return read $15_@2
@@ -100,9 +100,6 @@ bb2:
[40] Const mutate $73 = "\n "
[41] Const mutate $74_@5 = JSX <read $67:TPrimitive>{read $68}{read $71_@4}{read $72}{freeze renderedItems$32_@0:TFunction}{read $73}</read $67:TPrimitive>
[42] Return read $74_@5
scope0 [3:33]:
- dependency: read $34:TPrimitive
- dependency: read maxItems$31:TProp
scope2 [6:7]:
- dependency: read $34:TPrimitive
- dependency: read maxItems$31:TProp
@@ -129,11 +126,11 @@ function Component(
) {
[1] Const mutate items$30:TProp = read props$29.items
[2] Const mutate maxItems$31:TProp = read props$29.maxItems
scope @0 [3:33] deps=[read $34:TPrimitive, read maxItems$31:TProp] {
scope @0 [3:33] deps=[read maxItems$31:TProp, read items$30.length, read items$30] {
[3] Const mutate renderedItems$32_@0:TFunction[3:33] = Array []
[4] Const mutate seen$33_@0:TFunction[3:33] = New mutate Set$6()
[5] Const mutate $34:TPrimitive = 0
scope @2 [6:7] deps=[read $34:TPrimitive, read maxItems$31:TProp] {
scope @2 [6:7] deps=[read maxItems$31:TProp] {
[6] Const mutate max$35_@2:TPrimitive = Call mutate Math$8.max(read $34:TPrimitive, read maxItems$31:TProp)
}
for (
@@ -173,12 +170,12 @@ function Component(
[35] Const mutate $68 = "\n "
[36] Const mutate $69:TPrimitive = "h1"
[37] Const mutate $70 = " Items"
scope @4 [38:39] deps=[read $69:TPrimitive, freeze count$66:TProp, read $70] {
scope @4 [38:39] deps=[freeze count$66:TProp] {
[38] Const mutate $71_@4 = JSX <read $69:TPrimitive>{freeze count$66:TProp}{read $70}</read $69:TPrimitive>
}
[39] Const mutate $72 = "\n "
[40] Const mutate $73 = "\n "
scope @5 [41:42] deps=[read $67:TPrimitive, read $68, read $71_@4, read $72, freeze renderedItems$32_@0:TFunction, read $73] {
scope @5 [41:42] deps=[read $71_@4, freeze renderedItems$32_@0:TFunction] {
[41] Const mutate $74_@5 = JSX <read $67:TPrimitive>{read $68}{read $71_@4}{read $72}{freeze renderedItems$32_@0:TFunction}{read $73}</read $67:TPrimitive>
}
return read $74_@5
@@ -158,7 +158,7 @@ scope0 [1:7]:
function Component(
props,
) {
scope @0 [1:7] deps=[read props$3.a, read props$3.c, read props$3.b, read props$3.d] {
scope @0 [1:7] deps=[read props$3.a, read props$3.b, read props$3.c, read props$3.d] {
[1] Const mutate a$4_@0:TFunction[1:7] = Array []
[2] Call mutate a$4_@0.push(read props$3.a)
if (read props$3.b) {
@@ -215,7 +215,7 @@ scope0 [1:8]:
function Component(
props,
) {
scope @0 [1:8] deps=[read props$4.a, read props$4.c, read props$4.b, read props$4.d] {
scope @0 [1:8] deps=[read props$4.a, read props$4.b, read props$4.c, read props$4.d] {
[1] Const mutate a$5_@0:TFunction[1:8] = Array []
[2] Call mutate a$5_@0.push(read props$4.a)
if (read props$4.b) {
@@ -274,7 +274,7 @@ scope0 [1:7]:
function Component(
props,
) {
scope @0 [1:7] deps=[read props$3.a, read props$3.c, read props$3.b, read props$3.d] {
scope @0 [1:7] deps=[read props$3.a, read props$3.b, read props$3.c, read props$3.d] {
[1] Const mutate a$4_@0:TFunction[1:7] = Array []
[2] Call mutate a$4_@0.push(read props$3.a)
if (read props$3.b) {
@@ -331,7 +331,7 @@ scope0 [1:7]:
function Component(
props,
) {
scope @0 [1:7] deps=[read props$3.a, read props$3.d, read props$3.c] {
scope @0 [1:7] deps=[read props$3.a, read props$3.b, read props$3.d, read props$3.c] {
[1] Const mutate a$4_@0:TFunction[1:7] = Array []
[2] Call mutate a$4_@0.push(read props$3.a)
if (read props$3.b) {
@@ -64,7 +64,7 @@ scope2 [9:10]:
function Component(
props,
) {
scope @0 [1:9] deps=[] {
scope @0 [1:9] deps=[read props$6.p0, read props$6.p1, read props$6.p2] {
[1] Const mutate a$7_@0:TFunction[1:9] = Array []
[2] Const mutate b$8_@0:TFunction[1:9] = Array []
if (read b$8_@0:TFunction) {
@@ -134,7 +134,7 @@ scope2 [10:11]:
function Component(
props,
) {
scope @0 [1:10] deps=[] {
scope @0 [1:10] deps=[read props$8.p0, read props$8.p1, read props$8.p2] {
[1] Const mutate a$9_@0:TFunction[1:10] = Array []
[2] Const mutate b$10_@0:TFunction[1:10] = Array []
[3] Const mutate $11_@0[1:10] = Call mutate mayMutate$4:TFunction(mutate b$10_@0:TFunction)
@@ -52,8 +52,6 @@ bb0:
[7] Const mutate $14:TPrimitive = "div"
[8] Const mutate $15_@2 = JSX <read $14:TPrimitive a={read a$10_@0} b={freeze b$11_@0:TObject} ></read $14:TPrimitive>
[9] Return read $15_@2
scope0 [1:7]:
- dependency: read $12:TPrimitive
scope1 [5:6]:
- dependency: read $12:TPrimitive
scope2 [8:9]:
@@ -68,18 +66,18 @@ scope2 [8:9]:
function Component(
props,
) {
scope @0 [1:7] deps=[read $12:TPrimitive] {
scope @0 [1:7] deps=[] {
[1] Const mutate a$10_@0[1:7] = Array []
[2] Const mutate b$11_@0:TObject[1:7] = Object { }
[3] New mutate Foo$4(mutate a$10_@0, mutate b$11_@0:TObject)
[4] Const mutate $12:TPrimitive = "div"
scope @1 [5:6] deps=[read $12:TPrimitive] {
scope @1 [5:6] deps=[freeze a$10_@0] {
[5] Const mutate _$13_@1 = JSX <read $12:TPrimitive a={freeze a$10_@0} ></read $12:TPrimitive>
}
[6] New mutate Foo$4(mutate b$11_@0:TObject)
}
[7] Const mutate $14:TPrimitive = "div"
scope @2 [8:9] deps=[read $14:TPrimitive, read a$10_@0, freeze b$11_@0:TObject] {
scope @2 [8:9] deps=[read a$10_@0, freeze b$11_@0:TObject] {
[8] Const mutate $15_@2 = JSX <read $14:TPrimitive a={read a$10_@0} b={freeze b$11_@0:TObject} ></read $14:TPrimitive>
}
return read $15_@2
@@ -64,7 +64,7 @@ function foo(
}
[3] Const mutate $9:TPrimitive = "div"
[4] JSX <read $9:TPrimitive>{freeze x$8_@0:TFunction}</read $9:TPrimitive>
scope @1 [5:12] deps=[read x$8_@0:TFunction, read x$8_@0.length, read b$7:TFunction, read b$7:TFunction] {
scope @1 [5:12] deps=[read x$8_@0:TFunction, read b$7:TFunction] {
[5] Const mutate y$10_@1:TFunction[5:12] = Array []
if (read x$8_@0.length) {
[7] Call mutate y$10_@1.push(read x$8_@0:TFunction)
@@ -47,8 +47,6 @@ scope0 [1:10]:
- dependency: read x$6
- dependency: read x$6
- dependency: read y$7
- dependency: read y$7
- dependency: read x$6
scope1 [3:7]:
- dependency: read y$7
- dependency: read x$6
@@ -62,10 +60,10 @@ function foo(
y,
z,
) {
scope @0 [1:10] deps=[read z$8, read x$6, read x$6, read y$7, read y$7, read x$6] {
scope @0 [1:10] deps=[read z$8, read x$6, read y$7] {
[1] Const mutate items$9_@0:TFunction[1:10] = Array [read z$8]
[2] Call mutate items$9_@0.push(read x$6)
scope @1 [3:7] deps=[read y$7, read x$6] {
scope @1 [3:7] deps=[read x$6, read y$7] {
[3] Const mutate items2$10_@1:TFunction[3:7] = Array []
if (read x$6) {
[5] Call mutate items2$10_@1.push(read y$7)
@@ -60,7 +60,7 @@ function foo(
b,
c,
) {
scope @0 [1:8] deps=[read c$9, read b$8, read a$7] {
scope @0 [1:8] deps=[read a$7, read b$8, read c$9] {
[1] Const mutate x$10_@0:TFunction[1:8] = Array []
if (read a$7) {
if (read b$8) {
@@ -106,7 +106,7 @@ function Component(
[4] Const mutate $13 = "\n "
[5] Const mutate $14 = "\n "
[6] Const mutate $15 = "\n "
scope @2 [7:8] deps=[read Component$0, read $13, read x$11_@0, read $14, read y$12_@1, read $15] {
scope @2 [7:8] deps=[read x$11_@0, read y$12_@1] {
[7] Const mutate $16_@2 = JSX <read Component$0>{read $13}{read x$11_@0}{read $14}{read y$12_@1}{read $15}</read Component$0>
}
return read $16_@2
@@ -59,7 +59,7 @@ function Component(
[1] Const mutate cond$8:TProp = read props$7.cond
[2] Const mutate x$9:TProp = read props$7.x
[3] Const mutate a$10:TPrimitive = undefined
scope @0 [4:9] deps=[read x$9:TProp, read cond$8:TProp] {
scope @0 [4:9] deps=[read cond$8:TProp, read x$9:TProp] {
[4] Let mutate a$11_@0:TProp[4:9] = undefined
if (read cond$8:TProp) {
[5] Reassign mutate a$11_@0:TProp[4:9] = read x$9:TProp
@@ -158,7 +158,7 @@ scope2 [7:8]:
function Component(
props,
) {
scope @1 [1:7] deps=[read props$8.a] {
scope @1 [1:7] deps=[read props$8.a, read props$8.b, read props$8.c] {
[1] Const mutate a$9_@1[1:7] = Call mutate compute$3:TFunction(read props$8.a)
[2] Const mutate b$10_@1[1:7] = Call mutate compute$3:TFunction(read props$8.b)
if (read props$8.c) {
@@ -44,7 +44,7 @@ function foo(
b,
c,
) {
scope @0 [1:6] deps=[read c$7, read b$6, read a$5] {
scope @0 [1:6] deps=[read a$5, read b$6, read c$7] {
[1] Const mutate y$8_@0:TFunction[1:6] = Array []
if (read a$5) {
if (read b$6) {
@@ -59,15 +59,15 @@ function Foo(
[4] Const mutate $17:TPrimitive = "div"
[5] Const mutate $18 = "\n "
[6] Const mutate $19 = "Text"
scope @0 [7:8] deps=[read $19] {
scope @0 [7:8] deps=[] {
[7] Const mutate $20_@0 = JsxFragment [read $19]
}
[8] Const mutate $21 = "\n "
scope @1 [9:10] deps=[read $17:TPrimitive, read $18, read $20_@0, read $21] {
scope @1 [9:10] deps=[read $20_@0] {
[9] Const mutate $22_@1 = JSX <read $17:TPrimitive>{read $18}{read $20_@0}{read $21}</read $17:TPrimitive>
}
[10] Const mutate $23 = "\n "
scope @2 [11:12] deps=[read $14, read props$13.greeting, read $15:TPrimitive, read $16, read $22_@1, read $23] {
scope @2 [11:12] deps=[read props$13.greeting, read $22_@1] {
[11] Const mutate $24_@2 = JsxFragment [read $14, read props$13.greeting, read $15:TPrimitive, read $16, read $22_@1, read $23]
}
return read $24_@2
@@ -50,7 +50,7 @@ function And(
scope @0 [1:2] deps=[] {
[1] Const mutate $5_@0 = Call mutate f$1:TFunction()
}
scope @1 [2:7] deps=[read $5_@0, read $5_@0] {
scope @1 [2:7] deps=[read $5_@0] {
[2] Let mutate $6_@1[2:7] = undefined
if (read $5_@0) {
[3] Const mutate $6_@1[2:7] = Call mutate g$4:TFunction()
@@ -105,7 +105,7 @@ function Or(
scope @0 [1:2] deps=[] {
[1] Const mutate $5_@0 = Call mutate f$1:TFunction()
}
scope @1 [2:7] deps=[read $5_@0, read $5_@0] {
scope @1 [2:7] deps=[read $5_@0] {
[2] Let mutate $6_@1[2:7] = undefined
if (read $5_@0) {
[3] Const mutate $6_@1[2:7] = read $5_@0
@@ -165,7 +165,7 @@ function QuestionQuestion(
}
[2] Const mutate $10:TPrimitive = null
[3] Const mutate $11:TPrimitive = Binary read $9_@0:TPrimitive != read $10:TPrimitive
scope @1 [4:9] deps=[read $9_@0:TPrimitive, read $11:TPrimitive] {
scope @1 [4:9] deps=[read $9_@0:TPrimitive] {
[4] Let mutate $12_@1:TPrimitive[4:9] = undefined
if (read $11:TPrimitive) {
[5] Const mutate $12_@1:TPrimitive[4:9] = read $9_@0:TPrimitive
@@ -104,7 +104,7 @@ function Component(
scope @0 [1:2] deps=[] {
[1] Const mutate a$11_@0:TObject = Object { }
}
scope @1 [2:15] deps=[read a$11_@0:TObject, read a$11_@0:TObject] {
scope @1 [2:15] deps=[read a$11_@0:TObject] {
[2] Const mutate b$12_@1[2:15] = Array [read a$11_@0:TObject]
scope @2 [3:4] deps=[] {
[3] Const mutate c$13_@2:TObject = Object { }
@@ -38,7 +38,7 @@ function foo(
b,
c,
) {
scope @0 [1:6] deps=[] {
scope @0 [1:6] deps=[read a$6, read b$7] {
[1] Const mutate x$9_@0:TFunction[1:6] = Array []
[2] Const mutate y$10_@0:TFunction[1:6] = Array []
if (read x$9_@0:TFunction) {
@@ -30,7 +30,7 @@ function foo(
a,
b,
) {
scope @0 [1:5] deps=[] {
scope @0 [1:5] deps=[read a$5, read b$6] {
[1] Const mutate x$7_@0:TFunction[1:5] = Array []
[2] Const mutate y$8_@0:TFunction[1:5] = Array []
[3] Call mutate x$7_@0.push(read a$5)
@@ -22,7 +22,6 @@ bb0:
[5] Return
scope0 [1:5]:
- dependency: read a$5
- dependency: read b$6
scope1 [2:4]:
- dependency: read b$6
```
@@ -34,7 +33,7 @@ function foo(
a,
b,
) {
scope @0 [1:5] deps=[read a$5, read b$6] {
scope @0 [1:5] deps=[read b$6, read a$5] {
[1] Const mutate x$7_@0:TFunction[1:5] = Array []
scope @1 [2:4] deps=[read b$6] {
[2] Const mutate y$8_@1:TFunction[2:4] = Array []
@@ -42,10 +42,6 @@ bb1:
[11] Return freeze x$11_@0:TFunction
scope0 [1:11]:
- dependency: read a$8
- dependency: read c$10
- dependency: read b$9
- dependency: read $13:TPrimitive
- dependency: freeze y$12_@1:TFunction
scope1 [3:7]:
- dependency: read c$10
- dependency: read b$9
@@ -62,17 +58,17 @@ function foo(
b,
c,
) {
scope @0 [1:11] deps=[read a$8, read c$10, read b$9, read $13:TPrimitive, freeze y$12_@1:TFunction] {
scope @0 [1:11] deps=[read a$8, read b$9, read c$10] {
[1] Const mutate x$11_@0:TFunction[1:11] = Array []
if (read a$8) {
scope @1 [3:7] deps=[read c$10, read b$9] {
scope @1 [3:7] deps=[read b$9, read c$10] {
[3] Const mutate y$12_@1:TFunction[3:7] = Array []
if (read b$9) {
[5] Call mutate y$12_@1.push(read c$10)
}
}
[7] Const mutate $13:TPrimitive = "div"
scope @2 [8:9] deps=[read $13:TPrimitive, freeze y$12_@1:TFunction] {
scope @2 [8:9] deps=[freeze y$12_@1:TFunction] {
[8] Const mutate $15_@2 = JSX <read $13:TPrimitive>{freeze y$12_@1:TFunction}</read $13:TPrimitive>
}
[9] Call mutate x$11_@0.push(read $15_@2)
@@ -42,7 +42,7 @@ function foo(
b,
c,
) {
scope @0 [1:8] deps=[] {
scope @0 [1:8] deps=[read c$8, read b$7, read a$6] {
[1] Const mutate x$9_@0:TFunction[1:8] = Array []
[2] Const mutate y$10_@0:TFunction[1:8] = Array []
while (
@@ -52,7 +52,7 @@ function foo(
b,
c,
) {
scope @0 [1:9] deps=[read c$8, read b$7, read a$6] {
scope @0 [1:9] deps=[read a$6, read b$7, read c$8] {
[1] Const mutate x$9_@0:TFunction[1:9] = Array []
if (read a$6) {
[3] Const mutate y$10_@0:TFunction[1:9] = Array []
@@ -39,14 +39,14 @@ scope1 [6:7]:
function Component(
props,
) {
scope @0 [1:6] deps=[read Component$0, read props$6.p0] {
scope @0 [1:6] deps=[read props$6.p0] {
[1] Const mutate x$7_@0:TObject[1:6] = Object { }
[2] Const mutate y$8_@0[1:6] = Array []
[3] Reassign mutate x$7_@0.y[1:6] = read y$8_@0
[4] Const mutate child$9_@0[1:6] = JSX <read Component$0 data={freeze y$8_@0} ></read Component$0>
[5] Call mutate x$7_@0.y.push(read props$6.p0)
}
scope @1 [6:7] deps=[read Component$0, freeze x$7_@0:TObject, read child$9_@0] {
scope @1 [6:7] deps=[freeze x$7_@0:TObject, read child$9_@0] {
[6] Const mutate $10_@1 = JSX <read Component$0 data={freeze x$7_@0:TObject} >{read child$9_@0}</read Component$0>
}
return read $10_@1
@@ -40,9 +40,6 @@ bb1:
scope0 [1:11]:
- dependency: read c$10
- dependency: read a$8
- dependency: read b$9
- dependency: read $13:TPrimitive
- dependency: freeze y$12_@1:TFunction
scope1 [3:5]:
- dependency: read b$9
scope2 [6:7]:
@@ -58,7 +55,7 @@ function foo(
b,
c,
) {
scope @0 [1:11] deps=[read c$10, read a$8, read b$9, read $13:TPrimitive, freeze y$12_@1:TFunction] {
scope @0 [1:11] deps=[read a$8, read b$9, read c$10] {
[1] Const mutate x$11_@0:TFunction[1:11] = Array []
if (read a$8) {
scope @1 [3:5] deps=[read b$9] {
@@ -66,7 +63,7 @@ function foo(
[4] Call mutate y$12_@1.push(read b$9)
}
[5] Const mutate $13:TPrimitive = "div"
scope @2 [6:7] deps=[read $13:TPrimitive, freeze y$12_@1:TFunction] {
scope @2 [6:7] deps=[freeze y$12_@1:TFunction] {
[6] Const mutate $14_@2 = JSX <read $13:TPrimitive>{freeze y$12_@1:TFunction}</read $13:TPrimitive>
}
[7] Call mutate x$11_@0.push(read $14_@2)
@@ -51,7 +51,7 @@ function f(
a,
b,
) {
scope @0 [1:8] deps=[read a$8.length, read b$9, read b$9] {
scope @0 [1:8] deps=[read a$8.length, read b$9] {
[1] Const mutate x$10_@0:TFunction[1:8] = Array []
[2] Const mutate $11:TPrimitive = 1
[3] Const mutate $12:TPrimitive = Binary read a$8.length === read $11:TPrimitive
@@ -62,7 +62,7 @@ function f(
}
}
[8] Const mutate $13:TPrimitive = "div"
scope @1 [9:10] deps=[read $13:TPrimitive, freeze x$10_@0:TFunction] {
scope @1 [9:10] deps=[freeze x$10_@0:TFunction] {
[9] Const mutate $15_@1 = JSX <read $13:TPrimitive>{freeze x$10_@0:TFunction}</read $13:TPrimitive>
}
return read $15_@1
@@ -63,11 +63,11 @@ function Component(
[5] Reassign mutate x$7_@0:TFunction[1:7] = Array []
}
}
scope @1 [7:8] deps=[read Component$0, freeze x$7_@0:TFunction] {
scope @1 [7:8] deps=[freeze x$7_@0:TFunction] {
[7] Const mutate _$12_@1 = JSX <read Component$0 x={freeze x$7_@0:TFunction} ></read Component$0>
}
[8] Call read y$8.push(read props$6.p2)
scope @2 [9:10] deps=[read Component$0, read x$7_@0:TFunction, read y$8:TFunction] {
scope @2 [9:10] deps=[read x$7_@0:TFunction, read y$8:TFunction] {
[9] Const mutate $15_@2 = JSX <read Component$0 x={read x$7_@0:TFunction} y={read y$8:TFunction} ></read Component$0>
}
return read $15_@2
@@ -95,18 +95,18 @@ function foo(
b,
c,
) {
scope @0 [1:5] deps=[read a$13, read a$13] {
scope @0 [1:5] deps=[read a$13] {
[1] Const mutate x$16_@0:TFunction[1:5] = Array []
if (read a$13) {
[3] Call mutate x$16_@0.push(read a$13)
}
}
[5] Const mutate $17:TPrimitive = "div"
scope @1 [6:7] deps=[read $17:TPrimitive, freeze x$16_@0:TFunction] {
scope @1 [6:7] deps=[freeze x$16_@0:TFunction] {
[6] Const mutate y$19_@1 = JSX <read $17:TPrimitive>{freeze x$16_@0:TFunction}</read $17:TPrimitive>
}
[7] Const mutate $20:TPrimitive = 0
scope @2 [8:15] deps=[read c$15, read b$14, read b$14] {
scope @2 [8:15] deps=[read b$14, read c$15] {
[8] Let mutate x$22_@2:TFunction[8:15] = undefined
switch (read b$14) {
case read $20:TPrimitive: {
@@ -124,7 +124,7 @@ function foo(
[16] Const mutate $26 = "\n "
[17] Const mutate $27 = "\n "
[18] Const mutate $28 = "\n "
scope @3 [19:20] deps=[read $25:TPrimitive, read $26, read y$19_@1, read $27, freeze x$22_@2:TFunction, read $28] {
scope @3 [19:20] deps=[read y$19_@1] {
[19] Const mutate $31_@3 = JSX <read $25:TPrimitive>{read $26}{read y$19_@1}{read $27}{freeze x$22_@2:TFunction}{read $28}</read $25:TPrimitive>
}
return read $31_@3
@@ -32,8 +32,6 @@ bb0:
scope0 [1:7]:
- dependency: read props$6.p0
- dependency: read props$6.p1
- dependency: read Component$0
- dependency: freeze x$9_@1
scope2 [5:6]:
- dependency: read Component$0
- dependency: freeze x$9_@1
@@ -49,19 +47,19 @@ scope3 [7:8]:
function Component(
props,
) {
scope @0 [1:7] deps=[read props$6.p0, read props$6.p1, read Component$0, freeze x$9_@1] {
scope @0 [1:7] deps=[read props$6.p0, read props$6.p1] {
[1] Const mutate x$7_@0:TFunction[1:7] = Array []
[2] Call mutate x$7_@0.push(read props$6.p0)
[3] Const mutate y$8_@0:TFunction[1:7] = read x$7_@0:TFunction
scope @1 [4:5] deps=[] {
[4] Const mutate x$9_@1 = Array []
}
scope @2 [5:6] deps=[read Component$0, freeze x$9_@1] {
scope @2 [5:6] deps=[freeze x$9_@1] {
[5] Const mutate _$10_@2 = JSX <read Component$0 x={freeze x$9_@1} ></read Component$0>
}
[6] Call mutate y$8_@0.push(read props$6.p1)
}
scope @3 [7:8] deps=[read Component$0, read x$9_@1, freeze y$8_@0:TFunction] {
scope @3 [7:8] deps=[read x$9_@1, freeze y$8_@0:TFunction] {
[7] Const mutate $11_@3 = JSX <read Component$0 x={read x$9_@1} y={freeze y$8_@0:TFunction} ></read Component$0>
}
return read $11_@3
@@ -95,7 +95,7 @@ function Component(
props,
) {
[1] Const mutate x$7:TPrimitive = undefined
scope @0 [2:18] deps=[read props$6.v2, read props$6.v1, read props$6.v0, read props$6.test, read props$6.b, read props$6.c, read props$6.cond2, read props$6.cond] {
scope @0 [2:18] deps=[read props$6.cond, read props$6.test, read props$6.v0, read props$6.v1, read props$6.v2, read props$6.cond2, read props$6.b, read props$6.c] {
[2] Let mutate x$11_@0:TProp[2:18] = undefined
if (read props$6.cond) {
[3] Const mutate $8:TPrimitive = 2
@@ -44,14 +44,14 @@ function foo(
) {
if (read x$8) {
[2] Const mutate $10:TPrimitive = false
scope @0 [3:4] deps=[read foo$0:TFunction, read $10:TPrimitive, read y$9:TPrimitive] {
scope @0 [3:4] deps=[read y$9:TPrimitive] {
[3] Const mutate $11_@0 = Call read foo$0:TFunction(read $10:TPrimitive, read y$9:TPrimitive)
}
return freeze $11_@0
}
[5] Const mutate $12:TPrimitive = 10
[6] Const mutate $13:TPrimitive = Binary read y$9:TPrimitive * read $12:TPrimitive
scope @1 [7:8] deps=[read $13:TPrimitive] {
scope @1 [7:8] deps=[] {
[7] Const mutate $14_@1 = Array [read $13:TPrimitive]
}
return freeze $14_@1
@@ -32,7 +32,7 @@ function Component(
) {
[1] Const mutate a$6:TPrimitive = 1
[2] Const mutate b$7:TPrimitive = 2
scope @0 [3:4] deps=[read a$6:TPrimitive, read b$7:TPrimitive] {
scope @0 [3:4] deps=[] {
[3] Const mutate x$8_@0 = Array [read a$6:TPrimitive, read b$7:TPrimitive]
}
return freeze x$8_@0
@@ -62,8 +62,6 @@ bb1:
[10] Const mutate $19:TPrimitive = "div"
[11] Const mutate $20_@3 = JSX <read $19:TPrimitive a={freeze a$11_@0} b={freeze b$12_@0:TObject} ></read $19:TPrimitive>
[12] Return read $20_@3
scope0 [1:10]:
- dependency: read $14:TPrimitive
scope2 [7:8]:
- dependency: read $14:TPrimitive
scope3 [11:12]:
@@ -78,7 +76,7 @@ scope3 [11:12]:
function Component(
props,
) {
scope @0 [1:10] deps=[read $14:TPrimitive] {
scope @0 [1:10] deps=[] {
[1] Const mutate a$11_@0[1:10] = Array []
[2] Const mutate b$12_@0:TObject[1:10] = Object { }
[3] Call mutate foo$4:TFunction(mutate a$11_@0, mutate b$12_@0:TObject)
@@ -87,14 +85,14 @@ function Component(
}
if (read $13_@1) {
[6] Const mutate $14:TPrimitive = "div"
scope @2 [7:8] deps=[read $14:TPrimitive] {
scope @2 [7:8] deps=[freeze a$11_@0] {
[7] Const mutate _$15_@2 = JSX <read $14:TPrimitive a={freeze a$11_@0} ></read $14:TPrimitive>
}
}
[9] Call mutate foo$4:TFunction(read a$11_@0, mutate b$12_@0:TObject)
}
[10] Const mutate $19:TPrimitive = "div"
scope @3 [11:12] deps=[read $19:TPrimitive, freeze a$11_@0, freeze b$12_@0:TObject] {
scope @3 [11:12] deps=[freeze a$11_@0, freeze b$12_@0:TObject] {
[11] Const mutate $20_@3 = JSX <read $19:TPrimitive a={freeze a$11_@0} b={freeze b$12_@0:TObject} ></read $19:TPrimitive>
}
return read $20_@3
@@ -52,8 +52,6 @@ bb0:
[7] Const mutate $14:TPrimitive = "div"
[8] Const mutate $15_@2 = JSX <read $14:TPrimitive a={read a$10_@0} b={freeze b$11_@0:TObject} ></read $14:TPrimitive>
[9] Return read $15_@2
scope0 [1:7]:
- dependency: read $12:TPrimitive
scope1 [5:6]:
- dependency: read $12:TPrimitive
scope2 [8:9]:
@@ -68,18 +66,18 @@ scope2 [8:9]:
function Component(
props,
) {
scope @0 [1:7] deps=[read $12:TPrimitive] {
scope @0 [1:7] deps=[] {
[1] Const mutate a$10_@0[1:7] = Array []
[2] Const mutate b$11_@0:TObject[1:7] = Object { }
[3] Call mutate foo$4:TFunction(mutate a$10_@0, mutate b$11_@0:TObject)
[4] Const mutate $12:TPrimitive = "div"
scope @1 [5:6] deps=[read $12:TPrimitive] {
scope @1 [5:6] deps=[freeze a$10_@0] {
[5] Const mutate _$13_@1 = JSX <read $12:TPrimitive a={freeze a$10_@0} ></read $12:TPrimitive>
}
[6] Call mutate foo$4:TFunction(read a$10_@0, mutate b$11_@0:TObject)
}
[7] Const mutate $14:TPrimitive = "div"
scope @2 [8:9] deps=[read $14:TPrimitive, read a$10_@0, freeze b$11_@0:TObject] {
scope @2 [8:9] deps=[read a$10_@0, freeze b$11_@0:TObject] {
[8] Const mutate $15_@2 = JSX <read $14:TPrimitive a={read a$10_@0} b={freeze b$11_@0:TObject} ></read $14:TPrimitive>
}
return read $15_@2
@@ -87,7 +87,7 @@ function foo(
) {
[1] Const mutate x$13:TPrimitive = 0
[2] Const mutate $14:TPrimitive = true
scope @0 [3:20] deps=[read a$9, read b$10, read c$11, read d$12, read $14:TPrimitive] {
scope @0 [3:20] deps=[read a$9, read b$10, read c$11, read d$12] {
[3] Let mutate x$18_@0[3:20] = undefined
if (read $14:TPrimitive) {
[4] Const mutate $15:TPrimitive = true
@@ -49,7 +49,7 @@ function foo(
b,
c,
) {
scope @0 [1:8] deps=[read a$5, read c$7, read c$7, read b$6] {
scope @0 [1:8] deps=[read a$5, read b$6, read c$7] {
[1] Const mutate x$8_@0[1:8] = read a$5
if (read b$6) {
if (read c$7) {
@@ -53,7 +53,7 @@ function foo(
d,
e,
) {
scope @0 [1:8] deps=[read b$8, read d$10, read c$9, read a$7] {
scope @0 [1:8] deps=[read a$7, read b$8, read c$9, read d$10] {
[1] Let mutate x$12_@0:TPrimitive[1:8] = null
if (read a$7) {
[3] Reassign mutate x$12_@0:TPrimitive[1:8] = read b$8
@@ -60,7 +60,7 @@ function foo(
[8] Reassign mutate y$7_@0:TPrimitive[1:10] = 3
}
}
scope @2 [10:11] deps=[read x$6_@0:TPrimitive, read y$7_@0:TPrimitive] {
scope @2 [10:11] deps=[] {
[10] Const mutate t$14_@2:TObject = Object { x: read x$6_@0:TPrimitive, y: read y$7_@0:TPrimitive }
}
return freeze t$14_@2:TObject
@@ -32,7 +32,7 @@ function Component(
) {
[1] Const mutate a$6:TPrimitive = 1
[2] Const mutate b$7:TPrimitive = 2
scope @0 [3:4] deps=[read a$6:TPrimitive, read b$7:TPrimitive] {
scope @0 [3:4] deps=[] {
[3] Const mutate x$8_@0:TObject = Object { a: read a$6:TPrimitive, b: read b$7:TPrimitive }
}
return freeze x$8_@0:TObject
@@ -91,7 +91,7 @@ function foo(
[2] Const mutate $14:TPrimitive = true
if (read $14:TPrimitive) {
[4] Const mutate $15:TPrimitive = true
scope @0 [5:10] deps=[read a$9, read b$10, read $15:TPrimitive] {
scope @0 [5:10] deps=[read a$9, read b$10] {
[5] Let mutate x$16_@0[5:10] = undefined
if (read $15:TPrimitive) {
[6] Reassign mutate x$16_@0[5:10] = read a$9
@@ -102,7 +102,7 @@ function foo(
[10] read x$16_@0
} else {
[12] Const mutate $19:TPrimitive = true
scope @1 [13:18] deps=[read c$11, read d$12, read $19:TPrimitive] {
scope @1 [13:18] deps=[read c$11, read d$12] {
[13] Let mutate x$20_@1[13:18] = undefined
if (read $19:TPrimitive) {
[14] Reassign mutate x$20_@1[13:18] = read c$11
@@ -49,7 +49,7 @@ function foo(
[1] Const mutate y$5:TPrimitive = 2
[2] Const mutate $6:TPrimitive = 1
[3] Const mutate $7:TPrimitive = Binary read y$5:TPrimitive > read $6:TPrimitive
scope @0 [4:9] deps=[read $7:TPrimitive] {
scope @0 [4:9] deps=[] {
[4] Let mutate y$8_@0:TPrimitive[4:9] = undefined
if (read $7:TPrimitive) {
[5] Reassign mutate y$8_@0:TPrimitive[4:9] = 1
@@ -75,7 +75,7 @@ function foo(
[3] Const mutate $12:TPrimitive = Binary read x$10:TPrimitive === read $11:TPrimitive
[4] Const mutate $13:TPrimitive = 1
[5] Const mutate $14:TPrimitive = Binary read x$10:TPrimitive === read $13:TPrimitive
scope @0 [6:16] deps=[read x$10:TPrimitive, read x$10:TPrimitive, read x$10:TPrimitive, read x$10:TPrimitive] {
scope @0 [6:16] deps=[] {
[6] Let mutate x$16_@0:TPrimitive[6:16] = undefined
switch (read x$10:TPrimitive) {
case read $14:TPrimitive: {
@@ -73,7 +73,7 @@ scope3 [14:15]:
function Component(
props,
) {
scope @1 [1:12] deps=[] {
scope @1 [1:12] deps=[read props$9.p0, read props$9.p2] {
[1] Const mutate x$10_@1:TFunction[1:12] = Array []
[2] Let mutate y$11_@1:TPrimitive[1:12] = undefined
[3] Const mutate $12:TPrimitive = false
@@ -96,11 +96,11 @@ function Component(
}
}
}
scope @2 [12:13] deps=[read Component$0, freeze x$10_@1:TFunction] {
scope @2 [12:13] deps=[freeze x$10_@1:TFunction] {
[12] Const mutate child$19_@2 = JSX <read Component$0 data={freeze x$10_@1:TFunction} ></read Component$0>
}
[13] Call read y$11_@1.push(read props$9.p4)
scope @3 [14:15] deps=[read Component$0, freeze y$11_@1:TPrimitive, read child$19_@2] {
scope @3 [14:15] deps=[read child$19_@2] {
[14] Const mutate $22_@3 = JSX <read Component$0 data={freeze y$11_@1:TPrimitive} >{read child$19_@2}</read Component$0>
}
return read $22_@3
@@ -2,7 +2,6 @@
## Input
```javascript
// @Out DefUseGraph
function Component(props) {
let x = [];
let y;
@@ -68,7 +67,7 @@ scope4 [14:15]:
function Component(
props,
) {
scope @1 [1:12] deps=[] {
scope @1 [1:12] deps=[read props$8.p0, read props$8.p2, read props$8.p3] {
[1] Const mutate x$9_@1:TFunction[1:12] = Array []
[2] Let mutate y$10_@1:TPrimitive[1:12] = undefined
[3] Const mutate $11:TPrimitive = false
@@ -86,11 +85,11 @@ function Component(
}
}
}
scope @3 [12:13] deps=[read Component$0, freeze x$9_@1:TFunction] {
scope @3 [12:13] deps=[freeze x$9_@1:TFunction] {
[12] Const mutate child$19_@3 = JSX <read Component$0 data={freeze x$9_@1:TFunction} ></read Component$0>
}
[13] Call read y$10_@1.push(read props$8.p4)
scope @4 [14:15] deps=[read Component$0, read y$10_@1:TPrimitive, read child$19_@3] {
scope @4 [14:15] deps=[read child$19_@3] {
[14] Const mutate $23_@4 = JSX <read Component$0 data={read y$10_@1:TPrimitive} >{read child$19_@3}</read Component$0>
}
return read $23_@4
@@ -1,4 +1,3 @@
// @Out DefUseGraph
function Component(props) {
let x = [];
let y;
@@ -27,7 +27,7 @@ scope0 [2:3]:
function component(
) {
[1] Const mutate $4:TPrimitive = 1
scope @0 [2:3] deps=[read $4:TPrimitive] {
scope @0 [2:3] deps=[] {
[2] Const mutate x$5_@0:TObject = Object { t: read $4:TPrimitive }
}
[3] Const mutate p$6:TPrimitive = read x$5_@0.t