[patch] Make holey array handling compatible with older babel versions

--- 

Copied from comments 

Older versions of babel have a validation bug fixed by 

- https://github.com/babel/babel/pull/10917 

- (code pointer) 
https://github.com/babel/babel/commit/e7b80a2cb93cf28010207fc3cdd19b4568ca35b9#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52 

Link to buggy older version (observe that elements must be PatternLikes here) 


https://github.com/babel/babel/blob/v7.7.4/packages/babel-types/src/definitions/es2015.js#L50-L53 

Link to newer versions with correct validation (observe elements can be 
PatternLike | null) 


https://github.com/babel/babel/blob/v7.23.0/packages/babel-types/src/definitions/core.ts#L1306-L1311 

Tested on 3000+ components in fb: 

P898166848 

> Unexpected Errors 

> (count = 0) 

[patch] Make holey array handling compatible with older babel versions 

--- 

Copied from comments 

Older versions of babel have a validation bug fixed by 

- https://github.com/babel/babel/pull/10917 

- (code pointer) 
https://github.com/babel/babel/commit/e7b80a2cb93cf28010207fc3cdd19b4568ca35b9#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52 

Link to buggy older version (observe that elements must be PatternLikes here) 


https://github.com/babel/babel/blob/v7.7.4/packages/babel-types/src/definitions/es2015.js#L50-L53 

Link to newer versions with correct validation (observe elements can be 
PatternLike | null) 


https://github.com/babel/babel/blob/v7.23.0/packages/babel-types/src/definitions/core.ts#L1306-L1311 

Tested on 3000+ components in fb: 

P898166848 

> Unexpected Errors 

> (count = 0)
This commit is contained in:
Mofei Zhang
2023-12-06 13:20:49 -05:00
parent 01c1b16db4
commit 7e9f6ecfea
5 changed files with 40 additions and 74 deletions
@@ -1456,14 +1456,6 @@ function lowerExpression(
elements.push({
kind: "Hole",
});
if (builder.environment.config.bailoutOnHoleyArrays) {
builder.errors.push({
reason: `(BuildHIR::lower) Fix babel holey array backward compatibility.`,
severity: ErrorSeverity.Todo,
loc: expr.node.loc ?? null,
suggestions: null,
});
}
continue;
} else if (element.isExpression()) {
elements.push(lowerExpressionToTemporary(builder, element));
@@ -3289,15 +3281,6 @@ function lowerAssignment(
items.push({
kind: "Hole",
});
if (builder.environment.config.bailoutOnHoleyArrays) {
builder.errors.push({
reason: `(BuildHIR::lower) Fix babel holey array backward compatibility.`,
severity: ErrorSeverity.Todo,
loc: lvalue.node.loc ?? null,
suggestions: null,
});
}
continue;
}
if (element.isRestElement()) {
@@ -256,30 +256,6 @@ const EnvironmentConfigSchema = z.object({
// Enable validation of mutable ranges
assertValidMutableRanges: z.boolean().default(false),
/*
*
* Instead of handling holey arrays, bail out with a TODO error.
*
* Older versions of babel seem to have inconsistent handling of holey arrays,
* at least when paired with HermesParser. When using these versions, we should
* bail out instead of throwing a Babel validation error.
*
* The babel ast definition for array elements changed from Array<PatternLike>
* to Array<PatternLike | null>. Older versions does not expect null in the
* ArrayPattern ast and will throw a validation error.
*
* - HermesParser will parse [, b] into [NodePath<null>, NodePath<Identifier>]
* - Forget will try to preserve this holey array when we codegen back to js
* (e.g. we call a babel builder function arrayPattern([null, identifier]))
* - Babel will fail with `TypeError: Property elements[0] of ArrayPattern
* expected node to be of a type ["PatternLike"] but instead got null`
*
* PR that changed the AST definition
* https://github.com/babel/babel/pull/10917/files#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52-R56
*
*/
bailoutOnHoleyArrays: z.boolean().default(false),
/*
* Enable emitting "change variables" which store the result of whether a particular
* reactive scope dependency has changed since the scope was last executed.
@@ -10,6 +10,7 @@ import { pruneUnusedLValues, pruneUnusedLabels, renameVariables } from ".";
import { CompilerError, ErrorSeverity } from "../CompilerError";
import { Environment, EnvironmentConfig, ExternalFunction } from "../HIR";
import {
ArrayPattern,
BlockId,
GeneratedSource,
Identifier,
@@ -1827,20 +1828,51 @@ function codegenObjectPropertyKey(
}
}
function codegenArrayPattern(
cx: Context,
pattern: ArrayPattern
): t.ArrayPattern {
const hasHoles = !pattern.items.every((e) => e.kind !== "Hole");
if (hasHoles) {
const result = t.arrayPattern([]);
/*
* Older versions of babel have a validation bug fixed by
* https://github.com/babel/babel/pull/10917
* https://github.com/babel/babel/commit/e7b80a2cb93cf28010207fc3cdd19b4568ca35b9#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52
*
* Link to buggy older version (observe that elements must be PatternLikes here)
* https://github.com/babel/babel/blob/v7.7.4/packages/babel-types/src/definitions/es2015.js#L50-L53
*
* Link to newer versions with correct validation (observe elements can be PatternLike | null)
* https://github.com/babel/babel/blob/v7.23.0/packages/babel-types/src/definitions/core.ts#L1306-L1311
*/
for (const item of pattern.items) {
if (item.kind === "Hole") {
result.elements.push(null);
} else {
result.elements.push(codegenLValue(cx, item));
}
}
return result;
} else {
return t.arrayPattern(
pattern.items.map((item) => {
if (item.kind === "Hole") {
return null;
}
return codegenLValue(cx, item);
})
);
}
}
function codegenLValue(
cx: Context,
pattern: Pattern | Place | SpreadPattern
): t.ArrayPattern | t.ObjectPattern | t.RestElement | t.Identifier {
switch (pattern.kind) {
case "ArrayPattern": {
return t.arrayPattern(
pattern.items.map((item) => {
if (item.kind === "Hole") {
return null;
}
return codegenLValue(cx, item);
})
);
return codegenArrayPattern(cx, pattern);
}
case "ObjectPattern": {
return t.objectPattern(
@@ -1,20 +0,0 @@
## Input
```javascript
// @bailoutOnHoleyArrays
function Component() {
return [1, , 3];
}
```
## Error
```
[ReactForget] Todo: (BuildHIR::lower) Fix babel holey array backward compatibility. (4:4)
```
@@ -1,5 +0,0 @@
// @bailoutOnHoleyArrays
function Component() {
return [1, , 3];
}