mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Propagate scope dependencies upwards
Initial, partial implementation of dependency propagation. This lays the groundwork, #876 completes it after some other fixes this uncovered.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import { Place, ReactiveBasicBlock, ReactiveFunction } from "./HIR";
|
||||
|
||||
/**
|
||||
* Propagates the dependencies of each scope to its parent scope(s).
|
||||
*/
|
||||
export function propagateScopeDependencies(fn: ReactiveFunction): void {
|
||||
const dependencies: Set<Place> = new Set();
|
||||
visit(fn.body, dependencies);
|
||||
}
|
||||
|
||||
function visit(block: ReactiveBasicBlock, dependencies: Set<Place>): 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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "instruction": {
|
||||
break;
|
||||
}
|
||||
case "terminal": {
|
||||
const terminal = item.terminal;
|
||||
switch (terminal.kind) {
|
||||
case "break":
|
||||
case "continue":
|
||||
case "return":
|
||||
case "throw": {
|
||||
break;
|
||||
}
|
||||
case "for": {
|
||||
visit(terminal.loop, dependencies);
|
||||
break;
|
||||
}
|
||||
case "while": {
|
||||
visit(terminal.loop, dependencies);
|
||||
break;
|
||||
}
|
||||
case "if": {
|
||||
visit(terminal.consequent, dependencies);
|
||||
if (terminal.alternate !== null) {
|
||||
visit(terminal.alternate, dependencies);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "switch": {
|
||||
for (const case_ of terminal.cases) {
|
||||
if (case_.block !== undefined) {
|
||||
visit(case_.block, dependencies);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
terminal,
|
||||
`Unexpected terminal kind '${(terminal as any).kind}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(item, `Unexpected item`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,8 @@ 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]:
|
||||
@@ -66,7 +68,7 @@ scope2 [8:9]:
|
||||
function Component(
|
||||
props,
|
||||
) {
|
||||
scope @0 [1:7] deps=[] {
|
||||
scope @0 [1:7] deps=[read $12:TPrimitive] {
|
||||
[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)
|
||||
|
||||
@@ -100,6 +100,9 @@ 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
|
||||
@@ -126,7 +129,7 @@ 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=[] {
|
||||
scope @0 [3:33] deps=[read $34:TPrimitive, read maxItems$31:TProp] {
|
||||
[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
|
||||
|
||||
@@ -52,6 +52,8 @@ 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]:
|
||||
@@ -66,7 +68,7 @@ scope2 [8:9]:
|
||||
function Component(
|
||||
props,
|
||||
) {
|
||||
scope @0 [1:7] deps=[] {
|
||||
scope @0 [1:7] deps=[read $12:TPrimitive] {
|
||||
[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)
|
||||
|
||||
@@ -47,6 +47,8 @@ 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
|
||||
@@ -60,7 +62,7 @@ function foo(
|
||||
y,
|
||||
z,
|
||||
) {
|
||||
scope @0 [1:10] deps=[read z$8, read x$6, read x$6, read y$7] {
|
||||
scope @0 [1:10] deps=[read z$8, read x$6, read x$6, read y$7, read y$7, read x$6] {
|
||||
[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] {
|
||||
|
||||
@@ -20,6 +20,9 @@ bb0:
|
||||
[3] Call mutate y$8_@1.push(read b$6)
|
||||
[4] Call mutate x$7_@0.push(read a$5)
|
||||
[5] Return
|
||||
scope0 [1:5]:
|
||||
- dependency: read b$6
|
||||
- dependency: read a$5
|
||||
scope1 [2:4]:
|
||||
- dependency: read b$6
|
||||
- dependency: read a$5
|
||||
@@ -32,7 +35,7 @@ function foo(
|
||||
a,
|
||||
b,
|
||||
) {
|
||||
scope @0 [1:5] deps=[] {
|
||||
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, read a$5] {
|
||||
[2] Const mutate y$8_@1:TFunction[2:4] = Array []
|
||||
|
||||
+5
-1
@@ -42,6 +42,10 @@ 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
|
||||
@@ -58,7 +62,7 @@ function foo(
|
||||
b,
|
||||
c,
|
||||
) {
|
||||
scope @0 [1:11] deps=[read a$8] {
|
||||
scope @0 [1:11] deps=[read a$8, read c$10, read b$9, read $13:TPrimitive, freeze y$12_@1:TFunction] {
|
||||
[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] {
|
||||
|
||||
@@ -24,6 +24,8 @@ bb0:
|
||||
[4] Call mutate y$5_@1.push(mutate z$6_@1:TObject)
|
||||
[5] Reassign mutate x$4_@0.y[1:6] = read y$5_@1:TFunction
|
||||
[6] Return freeze x$4_@0:TObject
|
||||
scope0 [1:6]:
|
||||
- dependency: mutate x$4_@0.y
|
||||
scope1 [2:5]:
|
||||
- dependency: mutate x$4_@0.y
|
||||
```
|
||||
@@ -33,7 +35,7 @@ scope1 [2:5]:
|
||||
```
|
||||
function foo(
|
||||
) {
|
||||
scope @0 [1:6] deps=[] {
|
||||
scope @0 [1:6] deps=[mutate x$4_@0.y] {
|
||||
[1] Const mutate x$4_@0:TObject[1:6] = Object { }
|
||||
scope @1 [2:5] deps=[mutate x$4_@0.y] {
|
||||
[2] Const mutate y$5_@1:TFunction[2:5] = Array []
|
||||
|
||||
@@ -40,6 +40,9 @@ 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]:
|
||||
@@ -55,7 +58,7 @@ function foo(
|
||||
b,
|
||||
c,
|
||||
) {
|
||||
scope @0 [1:11] deps=[read c$10, read a$8] {
|
||||
scope @0 [1:11] deps=[read c$10, read a$8, read b$9, read $13:TPrimitive, freeze y$12_@1:TFunction] {
|
||||
[1] Const mutate x$11_@0:TFunction[1:11] = Array []
|
||||
if (read a$8) {
|
||||
scope @1 [3:5] deps=[read b$9] {
|
||||
|
||||
@@ -31,6 +31,9 @@ bb0:
|
||||
[8] Return read $11_@3
|
||||
scope0 [1:7]:
|
||||
- dependency: read props$6.p0
|
||||
- dependency: read Component$0
|
||||
- dependency: freeze x$9_@1
|
||||
- dependency: read props$6.p1
|
||||
scope2 [5:6]:
|
||||
- dependency: read Component$0
|
||||
- dependency: freeze x$9_@1
|
||||
@@ -47,7 +50,7 @@ scope3 [7:8]:
|
||||
function Component(
|
||||
props,
|
||||
) {
|
||||
scope @0 [1:7] deps=[read props$6.p0] {
|
||||
scope @0 [1:7] deps=[read props$6.p0, read Component$0, freeze x$9_@1, 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
|
||||
|
||||
@@ -62,6 +62,8 @@ 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]:
|
||||
@@ -76,7 +78,7 @@ scope3 [11:12]:
|
||||
function Component(
|
||||
props,
|
||||
) {
|
||||
scope @0 [1:10] deps=[] {
|
||||
scope @0 [1:10] deps=[read $14:TPrimitive] {
|
||||
[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)
|
||||
|
||||
@@ -52,6 +52,8 @@ 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]:
|
||||
@@ -66,7 +68,7 @@ scope2 [8:9]:
|
||||
function Component(
|
||||
props,
|
||||
) {
|
||||
scope @0 [1:7] deps=[] {
|
||||
scope @0 [1:7] deps=[read $12:TPrimitive] {
|
||||
[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)
|
||||
|
||||
@@ -37,6 +37,8 @@ bb1:
|
||||
[9] Return freeze x$6_@0:TObject
|
||||
scope0 [1:9]:
|
||||
- dependency: read a$5
|
||||
- dependency: mutate x$6_@0.y
|
||||
- dependency: mutate x$6_@0.z
|
||||
scope1 [3:4]:
|
||||
- dependency: mutate x$6_@0.y
|
||||
scope2 [6:7]:
|
||||
@@ -49,7 +51,7 @@ scope2 [6:7]:
|
||||
function foo(
|
||||
a,
|
||||
) {
|
||||
scope @0 [1:9] deps=[read a$5] {
|
||||
scope @0 [1:9] deps=[read a$5, mutate x$6_@0.y, mutate x$6_@0.z] {
|
||||
[1] Const mutate x$6_@0:TObject[1:9] = Object { }
|
||||
if (read a$5) {
|
||||
scope @1 [3:4] deps=[mutate x$6_@0.y] {
|
||||
|
||||
+2
-1
@@ -39,6 +39,7 @@ bb1:
|
||||
[10] Return freeze x$7_@0:TObject
|
||||
scope0 [1:10]:
|
||||
- dependency: read a$6
|
||||
- dependency: mutate x$7_@0.z
|
||||
scope1 [7:8]:
|
||||
- dependency: mutate x$7_@0.z
|
||||
```
|
||||
@@ -49,7 +50,7 @@ scope1 [7:8]:
|
||||
function foo(
|
||||
a,
|
||||
) {
|
||||
scope @0 [1:10] deps=[read a$6] {
|
||||
scope @0 [1:10] deps=[read a$6, mutate x$7_@0.z] {
|
||||
[1] Const mutate x$7_@0:TObject[1:10] = Object { }
|
||||
if (read a$6) {
|
||||
[3] Const mutate y$8_@0:TObject[1:10] = Object { }
|
||||
|
||||
@@ -20,6 +20,8 @@ bb0:
|
||||
[3] Reassign mutate x$4_@0.t[1:4] = read q$5_@1:TObject
|
||||
[4] Const mutate z$6:TObject = read x$4_@0.t
|
||||
[5] Return
|
||||
scope0 [1:4]:
|
||||
- dependency: mutate x$4_@0.t
|
||||
scope1 [2:3]:
|
||||
- dependency: mutate x$4_@0.t
|
||||
```
|
||||
@@ -29,7 +31,7 @@ scope1 [2:3]:
|
||||
```
|
||||
function component(
|
||||
) {
|
||||
scope @0 [1:4] deps=[] {
|
||||
scope @0 [1:4] deps=[mutate x$4_@0.t] {
|
||||
[1] Const mutate x$4_@0:TObject[1:4] = Object { }
|
||||
scope @1 [2:3] deps=[mutate x$4_@0.t] {
|
||||
[2] Const mutate q$5_@1:TObject = Object { }
|
||||
|
||||
@@ -20,6 +20,7 @@ import { toggleLogging } from "../HIR/logger";
|
||||
import run from "../HIR/Pipeline";
|
||||
import { printFunction } from "../HIR/PrintHIR";
|
||||
import { printReactiveFunction } from "../HIR/PrintReactiveFunction";
|
||||
import { propagateScopeDependencies } from "../HIR/PropagateScopeDependencies";
|
||||
import generateTestsFromFixtures from "./test-utils/generateTestsFromFixtures";
|
||||
|
||||
function wrapWithTripleBackticks(s: string, ext?: string) {
|
||||
@@ -150,6 +151,7 @@ function transform(text: string, file: string): Array<TestOutput> {
|
||||
|
||||
const reactiveFunction = buildReactiveFunction(ir);
|
||||
flattenReactiveLoops(reactiveFunction);
|
||||
propagateScopeDependencies(reactiveFunction);
|
||||
const scopes = printReactiveFunction(reactiveFunction);
|
||||
|
||||
const textHIR = printFunction(ir);
|
||||
|
||||
Reference in New Issue
Block a user