Skip to content

Commit f5af92d

Browse files
authored
feat(compiler): Support MetaProperty (#29752)
## Summary See #29737 ## How did you test this change? As the feature requires module support and the test runner does currently not support running tests as modules, I could only test it via playground.
1 parent c2ae9e2 commit f5af92d

17 files changed

+202
-2
lines changed

compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,6 +2427,28 @@ function lowerExpression(
24272427
let expr = exprPath as NodePath<t.TSNonNullExpression>;
24282428
return lowerExpression(builder, expr.get("expression"));
24292429
}
2430+
case "MetaProperty": {
2431+
let expr = exprPath as NodePath<t.MetaProperty>;
2432+
if (
2433+
expr.node.meta.name === "import" &&
2434+
expr.node.property.name === "meta"
2435+
) {
2436+
return {
2437+
kind: "MetaProperty",
2438+
meta: expr.node.meta.name,
2439+
property: expr.node.property.name,
2440+
loc: expr.node.loc ?? GeneratedSource,
2441+
};
2442+
}
2443+
2444+
builder.errors.push({
2445+
reason: `(BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta`,
2446+
severity: ErrorSeverity.Todo,
2447+
loc: exprPath.node.loc ?? null,
2448+
suggestions: null,
2449+
});
2450+
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
2451+
}
24302452
default: {
24312453
builder.errors.push({
24322454
reason: `(BuildHIR::lowerExpression) Handle ${exprPath.type} expressions`,

compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,12 @@ export type InstructionValue =
898898
flags: string;
899899
loc: SourceLocation;
900900
}
901+
| {
902+
kind: "MetaProperty";
903+
meta: string;
904+
property: string;
905+
loc: SourceLocation;
906+
}
901907

902908
// store `object.property = value`
903909
| {

compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
636636
value = `RegExp /${instrValue.pattern}/${instrValue.flags}`;
637637
break;
638638
}
639+
case "MetaProperty": {
640+
value = `MetaProperty ${instrValue.meta}.${instrValue.property}`;
641+
break;
642+
}
639643
case "Await": {
640644
value = `Await ${printPlace(instrValue.value)}`;
641645
break;

compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ export function* eachInstructionValueOperand(
242242
}
243243
case "Debugger":
244244
case "RegExpLiteral":
245+
case "MetaProperty":
245246
case "LoadGlobal":
246247
case "UnsupportedNode":
247248
case "Primitive":
@@ -566,6 +567,7 @@ export function mapInstructionValueOperands(
566567
}
567568
case "Debugger":
568569
case "RegExpLiteral":
570+
case "MetaProperty":
569571
case "LoadGlobal":
570572
case "UnsupportedNode":
571573
case "Primitive":

compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,18 @@ function inferBlock(
12161216
};
12171217
break;
12181218
}
1219+
case "MetaProperty": {
1220+
if (instrValue.meta !== "import" || instrValue.property !== "meta") {
1221+
continue;
1222+
}
1223+
1224+
valueKind = {
1225+
kind: ValueKind.Global,
1226+
reason: new Set([ValueReason.Global]),
1227+
context: new Set(),
1228+
};
1229+
break;
1230+
}
12191231
case "LoadGlobal":
12201232
valueKind = {
12211233
kind: ValueKind.Global,

compiler/packages/babel-plugin-react-compiler/src/Optimization/DeadCodeElimination.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ function pruneableValue(value: InstructionValue, state: State): boolean {
350350
return false;
351351
}
352352
case "RegExpLiteral":
353+
case "MetaProperty":
353354
case "LoadGlobal":
354355
case "ArrayExpression":
355356
case "BinaryExpression":

compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,13 @@ function codegenInstructionValue(
20212021
value = t.regExpLiteral(instrValue.pattern, instrValue.flags);
20222022
break;
20232023
}
2024+
case "MetaProperty": {
2025+
value = t.metaProperty(
2026+
t.identifier(instrValue.meta),
2027+
t.identifier(instrValue.property)
2028+
);
2029+
break;
2030+
}
20242031
case "Await": {
20252032
value = t.awaitExpression(codegenPlaceToExpression(cx, instrValue.value));
20262033
break;

compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/InferReactiveScopeVariables.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ function mayAllocate(env: Environment, instruction: Instruction): boolean {
199199
case "DeclareContext":
200200
case "StoreLocal":
201201
case "LoadGlobal":
202+
case "MetaProperty":
202203
case "TypeCastExpression":
203204
case "LoadLocal":
204205
case "LoadContext":

compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneNonEscapingScopes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ function computeMemoizationInputs(
459459
case "ComputedDelete":
460460
case "PropertyDelete":
461461
case "LoadGlobal":
462+
case "MetaProperty":
462463
case "TemplateLiteral":
463464
case "Primitive":
464465
case "JSXText":

compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ function* generateInstructionTypes(
338338
case "DeclareLocal":
339339
case "NewExpression":
340340
case "RegExpLiteral":
341+
case "MetaProperty":
341342
case "PropertyStore":
342343
case "ComputedStore":
343344
case "ComputedLoad":
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
## Input
3+
4+
```javascript
5+
import { Stringify } from "shared-runtime";
6+
7+
function foo() {
8+
const nt = new.target;
9+
return <Stringify value={nt} />;
10+
}
11+
12+
```
13+
14+
15+
## Error
16+
17+
```
18+
2 |
19+
3 | function foo() {
20+
> 4 | const nt = new.target;
21+
| ^^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta (4:4)
22+
5 | return <Stringify value={nt} />;
23+
6 | }
24+
7 |
25+
```
26+
27+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Stringify } from "shared-runtime";
2+
3+
function foo() {
4+
const nt = new.target;
5+
return <Stringify value={nt} />;
6+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
## Input
3+
4+
```javascript
5+
function a() {
6+
return import.meta.url;
7+
}
8+
9+
function b() {
10+
let a = 0;
11+
if (import.meta.url) {
12+
a = 1;
13+
}
14+
return a;
15+
}
16+
17+
function c() {
18+
let a = 0;
19+
if (import.meta.foo) {
20+
a = 1;
21+
}
22+
return a;
23+
}
24+
25+
function d() {
26+
let a = 0;
27+
if (import.meta) {
28+
a = 1;
29+
}
30+
return a;
31+
}
32+
33+
```
34+
35+
## Code
36+
37+
```javascript
38+
function a() {
39+
return import.meta.url;
40+
}
41+
42+
function b() {
43+
let a = 0;
44+
if (import.meta.url) {
45+
a = 1;
46+
}
47+
return a;
48+
}
49+
50+
function c() {
51+
let a = 0;
52+
if (import.meta.foo) {
53+
a = 1;
54+
}
55+
return a;
56+
}
57+
58+
function d() {
59+
let a = 0;
60+
if (import.meta) {
61+
a = 1;
62+
}
63+
return a;
64+
}
65+
66+
```
67+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
function a() {
2+
return import.meta.url;
3+
}
4+
5+
function b() {
6+
let a = 0;
7+
if (import.meta.url) {
8+
a = 1;
9+
}
10+
return a;
11+
}
12+
13+
function c() {
14+
let a = 0;
15+
if (import.meta.foo) {
16+
a = 1;
17+
}
18+
return a;
19+
}
20+
21+
function d() {
22+
let a = 0;
23+
if (import.meta) {
24+
a = 1;
25+
}
26+
return a;
27+
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/tsconfig.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323
},
2424
"include": [
2525
"./compiler/**/*.js",
26-
"./compiler/**/*.jsx",
26+
"./compiler/**/*.mjs",
27+
"./compiler/**/*.cjs",
2728
"./compiler/**/*.ts",
29+
"./compiler/**/*.mts",
30+
"./compiler/**/*.cts",
31+
"./compiler/**/*.jsx",
2832
"./compiler/**/*.tsx"
2933
]
3034
}

compiler/packages/snap/src/SproutTodoFilter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,9 @@ const skipFilter = new Set([
499499
"useState-unpruned-dependency",
500500
"useState-and-other-hook-unpruned-dependency",
501501
"change-detect-reassign",
502+
503+
// needs to be executed as a module
504+
"meta-property",
502505
]);
503506

504507
export default skipFilter;

compiler/packages/snap/src/fixture-utils.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,16 @@ import * as glob from "glob";
1010
import path from "path";
1111
import { FILTER_PATH, FIXTURES_PATH, SNAPSHOT_EXTENSION } from "./constants";
1212

13-
const INPUT_EXTENSIONS = [".js", ".ts", ".jsx", ".tsx"];
13+
const INPUT_EXTENSIONS = [
14+
".js",
15+
".cjs",
16+
".mjs",
17+
".ts",
18+
".cts",
19+
".mts",
20+
".jsx",
21+
".tsx",
22+
];
1423

1524
export type TestFilter = {
1625
debug: boolean;

0 commit comments

Comments
 (0)