[rfc] Desugar FunctionDeclaration to a FunctionExpression

This commit is contained in:
Sathya Gunasekaran
2023-03-30 15:48:54 +01:00
parent 05f48e2aac
commit e81063e5ef
12 changed files with 237 additions and 10 deletions
+36 -1
View File
@@ -678,6 +678,42 @@ function lowerStatement(
builder.terminateWithContinuation(terminal, continuationBlock);
return;
}
case "FunctionDeclaration": {
const stmt = stmtPath as NodePath<t.FunctionDeclaration>;
stmt.skip();
invariant(
stmt.get("id").type === "Identifier",
"function declarations must have a name"
);
const id = stmt.get("id") as NodePath<t.Identifier>;
// Desugar FunctionDeclaration to FunctionExpression.
//
// For example:
// function foo() {};
// becomes
// let foo = function foo() {};
const desugared = stmt.replaceWith(
t.variableDeclaration("let", [
t.variableDeclarator(
id.node,
t.functionExpression(
id.node,
stmt.node.params,
stmt.node.body,
stmt.node.generator,
stmt.node.async
)
),
])
);
invariant(
desugared.length === 1,
"only one declaration is created from desugaring function declaration"
);
lowerStatement(builder, desugared.at(0)!);
return;
}
case "ForOfStatement":
case "ForInStatement":
case "ClassDeclaration":
@@ -697,7 +733,6 @@ function lowerStatement(
case "ExportAllDeclaration":
case "ExportDefaultDeclaration":
case "ExportNamedDeclaration":
case "FunctionDeclaration":
case "ImportDeclaration":
case "InterfaceDeclaration":
case "OpaqueType":
@@ -0,0 +1,38 @@
## Input
```javascript
function component(a) {
let t = { a };
function x() {
t.foo();
}
x(t);
return t;
}
```
## Code
```javascript
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
let t;
if (c_0) {
t = { a };
const x = function x() {
t.foo();
};
x(t);
$[0] = a;
$[1] = t;
} else {
t = $[1];
}
return t;
}
```
@@ -0,0 +1,8 @@
function component(a) {
let t = { a };
function x() {
t.foo();
}
x(t);
return t;
}
@@ -0,0 +1,23 @@
## Input
```javascript
function component(a) {
let t = { a };
x(t); // hoisted call
function x(p) {
p.foo();
}
return t;
}
```
## Error
```
[ReactForget] Invariant: identifier x$6 should have been defined before use (4:4)
```
@@ -0,0 +1,8 @@
function component(a) {
let t = { a };
x(t); // hoisted call
function x(p) {
p.foo();
}
return t;
}
@@ -292,15 +292,6 @@ let moduleLocal = false;
62 |
63 | function component(a) {
64 | // Add support for function declarations once we support `var` hoisting.
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle FunctionDeclaration statements
61 | moduleLocal = true;
62 |
> 63 | function component(a) {
| ^
64 | // Add support for function declarations once we support `var` hoisting.
65 | function t() {}
66 | t();
```
@@ -0,0 +1,32 @@
## Input
```javascript
function component() {
function x(a) {
a.foo();
}
x = {};
return x;
}
```
## Code
```javascript
function component() {
const $ = React.unstable_useMemoCache(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {};
$[0] = t0;
} else {
t0 = $[0];
}
const x = t0;
return x;
}
```
@@ -0,0 +1,7 @@
function component() {
function x(a) {
a.foo();
}
x = {};
return x;
}
@@ -0,0 +1,32 @@
## Input
```javascript
function component() {
function x(a) {
a.foo();
}
function x() {}
return x;
}
```
## Code
```javascript
function component() {
const $ = React.unstable_useMemoCache(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = function x() {};
$[0] = t0;
} else {
t0 = $[0];
}
const x = t0;
return x;
}
```
@@ -0,0 +1,7 @@
function component() {
function x(a) {
a.foo();
}
function x() {}
return x;
}
@@ -0,0 +1,38 @@
## Input
```javascript
function component(a) {
let t = { a };
function x(p) {
p.foo();
}
x(t);
return t;
}
```
## Code
```javascript
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
let t;
if (c_0) {
t = { a };
const x = function x(p) {
p.foo();
};
x(t);
$[0] = a;
$[1] = t;
} else {
t = $[1];
}
return t;
}
```
@@ -0,0 +1,8 @@
function component(a) {
let t = { a };
function x(p) {
p.foo();
}
x(t);
return t;
}