mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Support RegExp literals
New InstructionValue variant since RegExp literals are valid expressions.
This commit is contained in:
@@ -1810,6 +1810,15 @@ function lowerExpression(
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "RegExpLiteral": {
|
||||
let expr = exprPath as NodePath<t.RegExpLiteral>;
|
||||
return {
|
||||
kind: "RegExpLiteral",
|
||||
pattern: expr.node.pattern,
|
||||
flags: expr.node.flags,
|
||||
loc: expr.node.loc ?? GeneratedSource,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerExpression) Handle ${exprPath.type} expressions`,
|
||||
|
||||
@@ -565,6 +565,12 @@ export type InstructionValue =
|
||||
loc: SourceLocation;
|
||||
}
|
||||
| { kind: "JsxFragment"; children: Array<Place>; loc: SourceLocation }
|
||||
| {
|
||||
kind: "RegExpLiteral";
|
||||
pattern: string;
|
||||
flags: string;
|
||||
loc: SourceLocation;
|
||||
}
|
||||
|
||||
// store `object.property = value`
|
||||
| {
|
||||
|
||||
@@ -444,6 +444,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
value = `OptionalCall ${printInstructionValue(instrValue.call)}`;
|
||||
break;
|
||||
}
|
||||
case "RegExpLiteral": {
|
||||
value = `RegExp /${instrValue.pattern}/${instrValue.flags}`;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
instrValue,
|
||||
|
||||
@@ -170,6 +170,7 @@ export function* eachInstructionValueOperand(
|
||||
yield* instrValue.subexprs;
|
||||
break;
|
||||
}
|
||||
case "RegExpLiteral":
|
||||
case "LoadGlobal":
|
||||
case "UnsupportedNode":
|
||||
case "Primitive":
|
||||
@@ -422,6 +423,7 @@ export function mapInstructionOperands(
|
||||
instrValue.subexprs = instrValue.subexprs.map(fn);
|
||||
break;
|
||||
}
|
||||
case "RegExpLiteral":
|
||||
case "LoadGlobal":
|
||||
case "UnsupportedNode":
|
||||
case "Primitive":
|
||||
|
||||
@@ -666,6 +666,12 @@ function inferBlock(
|
||||
effectKind = Effect.Read;
|
||||
break;
|
||||
}
|
||||
case "RegExpLiteral": {
|
||||
// RegExp instances are mutable objects
|
||||
valueKind = ValueKind.Mutable;
|
||||
effectKind = Effect.Mutate;
|
||||
break;
|
||||
}
|
||||
case "LoadGlobal":
|
||||
case "JSXText":
|
||||
case "Primitive": {
|
||||
|
||||
@@ -207,6 +207,7 @@ function pruneableValue(value: InstructionValue, state: State): boolean {
|
||||
// Potentially safe to prune, since they should just be creating new values
|
||||
return false;
|
||||
}
|
||||
case "RegExpLiteral":
|
||||
case "LoadGlobal":
|
||||
case "ArrayExpression":
|
||||
case "BinaryExpression":
|
||||
|
||||
@@ -903,6 +903,10 @@ function codegenInstructionValue(
|
||||
value = t.identifier(instrValue.name);
|
||||
break;
|
||||
}
|
||||
case "RegExpLiteral": {
|
||||
value = t.regExpLiteral(instrValue.pattern, instrValue.flags);
|
||||
break;
|
||||
}
|
||||
case "DeclareLocal":
|
||||
case "Destructure":
|
||||
case "StoreLocal": {
|
||||
|
||||
@@ -235,6 +235,7 @@ function mayAllocate(value: InstructionValue): boolean {
|
||||
case "Primitive": {
|
||||
return false;
|
||||
}
|
||||
case "RegExpLiteral":
|
||||
case "MethodCall":
|
||||
case "PropertyStore":
|
||||
case "ComputedStore":
|
||||
|
||||
@@ -509,6 +509,7 @@ function computeMemoizationInputs(
|
||||
};
|
||||
}
|
||||
case "OptionalCall":
|
||||
case "RegExpLiteral":
|
||||
case "FunctionExpression":
|
||||
case "TaggedTemplateExpression":
|
||||
case "CallExpression":
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const pattern = /foo/g;
|
||||
const value = makeValue();
|
||||
// We treat RegExp instances as mutable objects (bc they are)
|
||||
// so by default we assume this could be mutating `value`:
|
||||
if (pattern.test(value)) {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
return <div>Default</div>;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(4);
|
||||
let t0;
|
||||
let value;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
const pattern = /foo/g;
|
||||
value = makeValue();
|
||||
|
||||
t0 = pattern.test(value);
|
||||
$[0] = t0;
|
||||
$[1] = value;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
value = $[1];
|
||||
}
|
||||
if (t0) {
|
||||
let t1;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = <div>{value}</div>;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
let t2;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = <div>Default</div>;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function Component(props) {
|
||||
const pattern = /foo/g;
|
||||
const value = makeValue();
|
||||
// We treat RegExp instances as mutable objects (bc they are)
|
||||
// so by default we assume this could be mutating `value`:
|
||||
if (pattern.test(value)) {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
return <div>Default</div>;
|
||||
}
|
||||
Reference in New Issue
Block a user