Make function name a string not an identifier

Fixes #1751. Function ids can be plain strings, and we can refer to them as 
globals rather than via a local identifier. In addition to the bug from $1751 
this also cleans up an existing todo.
This commit is contained in:
Joe Savona
2023-06-20 15:16:55 -07:00
parent 4a36b83796
commit 6efd1f99d7
54 changed files with 111 additions and 149 deletions
@@ -23,7 +23,6 @@ import {
GeneratedSource,
GotoVariant,
HIRFunction,
Identifier,
IfTerminal,
InstructionKind,
InstructionValue,
@@ -77,9 +76,9 @@ export function lower(
// Internal babel is on an older version that does not have hasNode (v7.17)
// See https://github.com/babel/babel/pull/13940/files for impl
// TODO: write helper function for NodePath.node != null
let id: Identifier | null = null;
let id: string | null = null;
if (func.isFunctionDeclaration() && func.get("id").node != null) {
id = builder.resolveIdentifier(func.get("id") as NodePath<t.Identifier>);
id = (func.get("id") as NodePath<t.Identifier>).node.name;
}
const params: Array<Place> = [];
func.get("params").forEach((param) => {
@@ -48,7 +48,7 @@ export type SourceLocation = t.SourceLocation | typeof GeneratedSource;
*/
export type ReactiveFunction = {
loc: SourceLocation;
id: Identifier | null;
id: string | null;
params: Array<Place>;
generator: boolean;
async: boolean;
@@ -216,7 +216,7 @@ export type ReactiveLabelTerminal = {
*/
export type HIRFunction = {
loc: SourceLocation;
id: Identifier | null;
id: string | null;
env: Environment;
params: Array<Place>;
context: Array<Place>;
@@ -171,23 +171,11 @@ export default class HIRBuilder {
if (binding == null) {
return null;
}
// If the binding is from the parent function's outer scope, then
// we treat it equivalently to a global.
//
// TODO: remove the exception that resolves references to the
// parent function itself. We don't need to support self-recursion,
// so we can treat such references as globals.
// Check if the binding is from module scope, if so return null
const outerBinding =
this.parentFunction.scope.parent.getBinding(originalName);
if (binding === outerBinding) {
const func = this.parentFunction;
const isParentFunctionReference =
func.isFunctionDeclaration() &&
func.get("id").node != null &&
func.get("id").node!.name === originalName;
if (!isParentFunctionReference) {
return null;
}
return null;
}
return binding;
}
@@ -96,15 +96,6 @@ export default function inferReferenceEffects(
value: undefined,
};
initialState.initialize(value, ValueKind.Frozen);
if (fn.id !== null) {
const id: Place = {
kind: "Identifier",
identifier: fn.id,
loc: fn.loc,
effect: Effect.Freeze,
};
initialState.define(id, value);
}
for (const ref of fn.context) {
// TODO(gsn): This is a hack.
@@ -38,10 +38,7 @@ import { buildReactiveFunction } from "./BuildReactiveFunction";
export function codegenReactiveFunction(
fn: ReactiveFunction
): Result<t.FunctionDeclaration, CompilerError> {
const cx = new Context(fn.env, fn.id?.name ?? "[[ anonymous ]]");
if (fn.id !== null) {
cx.temp.set(fn.id.id, null);
}
const cx = new Context(fn.env, fn.id ?? "[[ anonymous ]]");
for (const param of fn.params) {
cx.temp.set(param.identifier.id, null);
}
@@ -77,7 +74,7 @@ export function codegenReactiveFunction(
return Ok(
createFunctionDeclaration(
fn.loc,
fn.id !== null ? convertIdentifier(fn.id) : null,
fn.id !== null ? t.identifier(fn.id) : null,
params,
body,
fn.generator,
@@ -24,9 +24,7 @@ import { assertExhaustive } from "../Utils/utils";
export function printReactiveFunction(fn: ReactiveFunction): string {
const writer = new Writer();
writer.writeLine(
`function ${fn.id !== null ? printIdentifier(fn.id) : "<unknown>"}(`
);
writer.writeLine(`function ${fn.id !== null ? fn.id : "<unknown>"}(`);
writer.indented(() => {
for (const param of fn.params) {
writer.writeLine(`${printPlace(param)},`);
@@ -49,12 +49,6 @@ export function propagateScopeDependencies(fn: ReactiveFunction): void {
visitReactiveFunction(fn, new FindPromotedTemporaries(), escapingTemporaries);
const context = new Context(escapingTemporaries.usedOutsideDeclaringScope);
if (fn.id !== null) {
context.declare(fn.id, {
id: makeInstructionId(0),
scope: empty(),
});
}
for (const param of fn.params) {
context.declare(param.identifier, {
id: makeInstructionId(0),
@@ -117,9 +117,6 @@ export function pruneNonEscapingScopes(
// First build up a map of which instructions are involved in creating which values,
// and which values are returned.
const state = new State(fn.env);
if (fn.id !== null) {
state.declare(fn.id.id);
}
for (const param of fn.params) {
state.declare(param.identifier.id);
}
@@ -33,9 +33,6 @@ import {
export function renameVariables(fn: ReactiveFunction): void {
const scopes = new Scopes();
scopes.enter(() => {
if (fn.id !== null) {
scopes.visit(fn.id);
}
for (const param of fn.params) {
scopes.visit(param.identifier);
}
@@ -14,9 +14,9 @@ function component([a, b]) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function component(t17) {
function component(t16) {
const $ = useMemoCache(7);
const [a, b] = t17;
const [a, b] = t16;
const c_0 = $[0] !== a;
let t0;
if (c_0) {
@@ -41,8 +41,8 @@ function Component(props) {
} else {
t0 = $[1];
}
const t16 = t0;
const expensiveNumber = t16;
const t15 = t0;
const expensiveNumber = t15;
const c_2 = $[2] !== expensiveNumber;
let t1;
if (c_2) {
@@ -67,8 +67,8 @@ function Component2(props) {
} else {
t0 = $[1];
}
const t16 = t0;
const expensiveNumber = t16;
const t15 = t0;
const expensiveNumber = t15;
const c_2 = $[2] !== expensiveNumber;
let t1;
if (c_2) {
@@ -20,9 +20,9 @@ function component({ mutator }) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function component(t27) {
function component(t26) {
const $ = useMemoCache(7);
const { mutator } = t27;
const { mutator } = t26;
const c_0 = $[0] !== mutator;
let t0;
if (c_0) {
@@ -11,9 +11,9 @@ function Component([a = 2]) {
## Code
```javascript
function Component(t14) {
const [t15] = t14;
const a = t15 === undefined ? 2 : t15;
function Component(t13) {
const [t14] = t13;
const a = t14 === undefined ? 2 : t14;
return a;
}
@@ -30,14 +30,14 @@ import { unstable_useMemoCache as useMemoCache } from "react";
function foo(a, b, c) {
const $ = useMemoCache(5);
const [d, t47] = a;
const [t49] = t47;
const { e: t51 } = t49;
const { f: g } = t51;
const { l: t56, o } = b;
const { m: t59 } = t56;
const [t61] = t59;
const [n] = t61;
const [d, t46] = a;
const [t48] = t46;
const { e: t50 } = t48;
const { f: g } = t50;
const { l: t55, o } = b;
const { m: t58 } = t55;
const [t60] = t58;
const [n] = t60;
const c_0 = $[0] !== d;
const c_1 = $[1] !== g;
const c_2 = $[2] !== n;
@@ -38,7 +38,7 @@ function Component(props) {
if (c_0) {
const allUrls = [];
const { media: t0, comments: t2, urls: t82 } = post;
const { media: t0, comments: t2, urls: t81 } = post;
const c_3 = $[3] !== t0;
let t1;
if (c_3) {
@@ -59,7 +59,7 @@ function Component(props) {
t3 = $[6];
}
const comments = t3;
const urls = t82 === undefined ? [] : t82;
const urls = t81 === undefined ? [] : t81;
const c_7 = $[7] !== comments.length;
let t4;
if (c_7) {
@@ -38,8 +38,8 @@ function Component(props) {
if (c_0) {
const allUrls = [];
const { media: t85, comments, urls } = post;
media = t85;
const { media: t84, comments, urls } = post;
media = t84;
const c_3 = $[3] !== comments.length;
let t0;
if (c_3) {
@@ -11,9 +11,9 @@ function Component({ a = 2 }) {
## Code
```javascript
function Component(t14) {
const { a: t15 } = t14;
const a = t15 === undefined ? 2 : t15;
function Component(t13) {
const { a: t14 } = t13;
const a = t14 === undefined ? 2 : t14;
return a;
}
@@ -59,8 +59,8 @@ function foo(a, b, c) {
g = $[6];
}
const { f } = t2;
const { l: t52, p } = b;
const { m: t3 } = t52;
const { l: t51, p } = b;
const { m: t3 } = t51;
const c_7 = $[7] !== t3;
let t4;
let o;
@@ -17,7 +17,7 @@ function component(a) {
## Error
```
[ReactForget] Invariant: EnterSSA: Expected identifier to be defined before being used. Identifier x$6 is undefined
[ReactForget] Invariant: EnterSSA: Expected identifier to be defined before being used. Identifier x$5 is undefined
```
@@ -15,7 +15,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $23:TObject<BuiltInRefValue> (5:5)
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $22:TObject<BuiltInRefValue> (5:5)
```
@@ -15,7 +15,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $20:TObject<BuiltInArray> (frozen) (4:4)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $19:TObject<BuiltInArray> (frozen) (4:4)
```
@@ -16,7 +16,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $22 (frozen) (5:5)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $21 (frozen) (5:5)
```
@@ -16,7 +16,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $20 (frozen) (5:5)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $19 (frozen) (5:5)
```
@@ -16,7 +16,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $19 (frozen) (5:5)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $18 (frozen) (5:5)
```
@@ -18,7 +18,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $40 (frozen) (5:5)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $39 (frozen) (5:5)
```
@@ -25,7 +25,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $46:TObject<BuiltInArray> (frozen) (13:13)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $44:TObject<BuiltInArray> (frozen) (13:13)
```
@@ -19,7 +19,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $27:TObject<BuiltInArray> (frozen) (7:7)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $26:TObject<BuiltInArray> (frozen) (7:7)
```
@@ -14,7 +14,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at mutate? $22[6:8]:TObject<BuiltInUseRefId> (3:3)
[ReactForget] InvalidInput: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at mutate? $21[6:8]:TObject<BuiltInUseRefId> (3:3)
```
@@ -16,7 +16,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $21 (frozen) (5:5)
[ReactForget] InvalidInput: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $20 (frozen) (5:5)
```
@@ -18,7 +18,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at capture $43[6:16]:TObject<BuiltInRefValue> (5:5)
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at capture $42[6:16]:TObject<BuiltInRefValue> (5:5)
```
@@ -13,7 +13,7 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $20:TObject<BuiltInRefValue> (3:3)
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $19:TObject<BuiltInRefValue> (3:3)
```
@@ -14,9 +14,9 @@ function Component(props) {
## Error
```
[ReactForget] InvalidInput: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at store $22[7:9]:TObject<BuiltInUseRefId> (3:3)
[ReactForget] InvalidInput: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at store $21[7:9]:TObject<BuiltInUseRefId> (3:3)
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $25:TObject<BuiltInRefValue> (4:4)
[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $24:TObject<BuiltInRefValue> (4:4)
```
@@ -21,7 +21,7 @@ function Foo({ a }) {
## Error
```
[ReactForget] InvalidInput: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at capture $30:TObject<BuiltInUseRefId> (4:4)
[ReactForget] InvalidInput: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at capture $29:TObject<BuiltInUseRefId> (4:4)
```
@@ -19,7 +19,7 @@ function component(a) {
## Error
```
[ReactForget] Invariant: EnterSSA: Expected identifier to be defined before being used. Identifier x$2 is undefined (7:7)
[ReactForget] Invariant: EnterSSA: Expected identifier to be defined before being used. Identifier x$1 is undefined (7:7)
```
@@ -21,8 +21,8 @@ function Component(props) {
const c_0 = $[0] !== props.a;
let b;
if (c_0) {
const { a, ...t30 } = props.a;
b = t30;
const { a, ...t29 } = props.a;
b = t29;
$[0] = props.a;
$[1] = b;
} else {
@@ -31,8 +31,8 @@ function Component(props) {
const c_2 = $[2] !== props.c;
let d;
if (c_2) {
const [c, ...t31] = props.c;
d = t31;
const [c, ...t30] = props.c;
d = t30;
$[2] = props.c;
$[3] = d;
} else {
@@ -12,9 +12,9 @@ function Component(x = "default", y = [{}]) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(t24, t0) {
function Component(t23, t0) {
const $ = useMemoCache(5);
const x = t24 === undefined ? "default" : t24;
const x = t23 === undefined ? "default" : t23;
const c_0 = $[0] !== t0;
let t1;
if (c_0) {
@@ -14,9 +14,9 @@ function component({ a, b }) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function component(t17) {
function component(t16) {
const $ = useMemoCache(7);
const { a, b } = t17;
const { a, b } = t16;
const c_0 = $[0] !== a;
let t0;
if (c_0) {
@@ -8,11 +8,12 @@ function foo() {
```
## Code
## Error
```javascript
function foo() {
(() => foo())();
}
```
Expected value for identifier `0` to be initialized.
```
@@ -17,9 +17,9 @@ function Foo({ a }) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react"; // @validateRefAccessDuringRender false
function Foo(t21) {
function Foo(t20) {
const $ = useMemoCache(4);
const { a } = t21;
const { a } = t20;
const ref = useRef();
const val = ref.current;
const c_0 = $[0] !== a;
@@ -16,9 +16,9 @@ function Foo({ a }) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react"; // @validateRefAccessDuringRender false
function Foo(t18) {
function Foo(t17) {
const $ = useMemoCache(4);
const { a } = t18;
const { a } = t17;
const ref = useRef();
const c_0 = $[0] !== a;
let t0;
@@ -29,8 +29,8 @@ function Component(props) {
const object = { x, onChange };
const { x: x_0, onChange: onChange_0 } = object;
const t44 = <input value={x_0} onChange={onChange_0} />;
return t44;
const t43 = <input value={x_0} onChange={onChange_0} />;
return t43;
}
```
@@ -19,8 +19,8 @@ function Foo(props) {
const c_0 = $[0] !== props.a;
let rest;
if (c_0) {
const { unused, ...t16 } = props.a;
rest = t16;
const { unused, ...t15 } = props.a;
rest = t15;
$[0] = props.a;
$[1] = rest;
} else {
@@ -20,7 +20,7 @@ function Component(props) {
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(props) {
const $ = useMemoCache(4);
let t21 = undefined;
let t20 = undefined;
bb7: {
if (props.cond) {
const c_0 = $[0] !== props.a;
@@ -32,7 +32,7 @@ function Component(props) {
} else {
t0 = $[1];
}
t21 = t0;
t20 = t0;
break bb7;
}
const c_2 = $[2] !== props.b;
@@ -44,9 +44,9 @@ function Component(props) {
} else {
t1 = $[3];
}
t21 = t1;
t20 = t1;
}
const x = t21;
const x = t20;
return x;
}
@@ -51,8 +51,8 @@ function Component(props) {
} else {
t2 = $[6];
}
const t27 = t2;
const [a_0, b_0] = t27;
const t26 = t2;
const [a_0, b_0] = t26;
const c_7 = $[7] !== a_0;
const c_8 = $[8] !== b_0;
let t3;
@@ -19,7 +19,7 @@ function component(a, b) {
import { unstable_useMemoCache as useMemoCache } from "react";
function component(a, b) {
const $ = useMemoCache(2);
let t14 = undefined;
let t13 = undefined;
bb6: {
if (a) {
const c_0 = $[0] !== b;
@@ -31,12 +31,12 @@ function component(a, b) {
} else {
t0 = $[1];
}
t14 = t0;
t13 = t0;
break bb6;
}
t14 = undefined;
t13 = undefined;
}
const x = t14;
const x = t13;
return x;
}
@@ -21,20 +21,20 @@ function Component(props) {
```javascript
function Component(props) {
let t17 = undefined;
let t16 = undefined;
bb10: {
bb5: {
if (props.cond) {
break bb5;
}
t17 = props.a;
t16 = props.a;
break bb10;
}
t17 = props.b;
t16 = props.b;
}
const x = t17;
const x = t16;
return x;
}
@@ -17,8 +17,8 @@ function Component(props) {
```javascript
function Component(props) {
const t9 = props.value;
const x = t9;
const t8 = props.value;
const x = t8;
return x;
}
@@ -13,8 +13,8 @@ function Component(props) {
```javascript
function Component(props) {
const t17 = props.a && props.b;
const x = t17;
const t16 = props.a && props.b;
const x = t16;
return x;
}
@@ -25,7 +25,7 @@ function Component(props) {
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(props) {
const $ = useMemoCache(3);
let t32 = undefined;
let t31 = undefined;
bb9: {
const c_0 = $[0] !== props;
let y;
@@ -35,21 +35,21 @@ function Component(props) {
y.push(props.a);
}
if (props.cond2) {
t32 = y;
t31 = y;
break bb9;
}
y.push(props.b);
$[0] = props;
$[1] = y;
$[2] = t32;
$[2] = t31;
} else {
y = $[1];
t32 = $[2];
t31 = $[2];
}
t32 = y;
t31 = y;
}
const x = t32;
const x = t31;
return x;
}
@@ -24,8 +24,8 @@ function component(a) {
} else {
t0 = $[1];
}
const t10 = t0;
const x = t10;
const t9 = t0;
const x = t9;
const c_2 = $[2] !== x;
let t1;
if (c_2) {
@@ -22,17 +22,17 @@ function Component(props) {
```javascript
function Component(props) {
let t18 = undefined;
let t17 = undefined;
bb8: switch (props.key) {
case "key": {
t18 = props.value;
t17 = props.value;
break bb8;
}
default: {
t18 = props.defaultValue;
t17 = props.defaultValue;
}
}
const x = t18;
const x = t17;
return x;
}
@@ -28,12 +28,12 @@ function Component(props) {
```javascript
function Component(props) {
let t22 = undefined;
let t21 = undefined;
bb10: {
let y = undefined;
bb2: switch (props.switch) {
case "foo": {
t22 = "foo";
t21 = "foo";
break bb10;
}
case "bar": {
@@ -45,9 +45,9 @@ function Component(props) {
}
}
t22 = y;
t21 = y;
}
const x = t22;
const x = t21;
return x;
}
@@ -56,7 +56,7 @@ const tests: ForgetTestCases = {
errors: [
{
message:
"[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $23:TObject<BuiltInRefValue> (6:6)",
"[ReactForget] InvalidInput: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $22:TObject<BuiltInRefValue> (6:6)",
line: 6,
column: 10,
endColumn: 15,
@@ -81,7 +81,7 @@ const tests: ForgetTestCases = {
errors: [
{
message:
"[ReactForget] Invariant: EnterSSA: Expected identifier to be defined before being used. Identifier x$2 is undefined (8:8)",
"[ReactForget] Invariant: EnterSSA: Expected identifier to be defined before being used. Identifier x$1 is undefined (8:8)",
line: 8,
column: 3,
endColumn: 17,