mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[compiler][patch] Don't wrap non-ascii fbt operands in JSXExpressionContainer
ghstack-source-id: 4b5505aa5e
Pull Request resolved: https://github.com/facebook/react/pull/30389
This commit is contained in:
@@ -262,7 +262,7 @@ function* runWithEnvironment(
|
||||
value: hir,
|
||||
});
|
||||
|
||||
memoizeFbtOperandsInSameScope(hir);
|
||||
const fbtOperands = memoizeFbtOperandsInSameScope(hir);
|
||||
yield log({
|
||||
kind: "hir",
|
||||
name: "MemoizeFbtAndMacroOperandsInSameScope",
|
||||
@@ -484,7 +484,10 @@ function* runWithEnvironment(
|
||||
validatePreservedManualMemoization(reactiveFunction);
|
||||
}
|
||||
|
||||
const ast = codegenFunction(reactiveFunction, uniqueIdentifiers).unwrap();
|
||||
const ast = codegenFunction(reactiveFunction, {
|
||||
uniqueIdentifiers,
|
||||
fbtOperands,
|
||||
}).unwrap();
|
||||
yield log({ kind: "ast", name: "Codegen", value: ast });
|
||||
for (const outlined of ast.outlined) {
|
||||
yield log({ kind: "ast", name: "Codegen (outlined)", value: outlined.fn });
|
||||
|
||||
+19
-3
@@ -100,12 +100,19 @@ export type CodegenFunction = {
|
||||
|
||||
export function codegenFunction(
|
||||
fn: ReactiveFunction,
|
||||
uniqueIdentifiers: Set<string>
|
||||
{
|
||||
uniqueIdentifiers,
|
||||
fbtOperands,
|
||||
}: {
|
||||
uniqueIdentifiers: Set<string>;
|
||||
fbtOperands: Set<IdentifierId>;
|
||||
}
|
||||
): Result<CodegenFunction, CompilerError> {
|
||||
const cx = new Context(
|
||||
fn.env,
|
||||
fn.id ?? "[[ anonymous ]]",
|
||||
uniqueIdentifiers,
|
||||
fbtOperands,
|
||||
null
|
||||
);
|
||||
|
||||
@@ -281,7 +288,8 @@ export function codegenFunction(
|
||||
new Context(
|
||||
cx.env,
|
||||
reactiveFunction.id ?? "[[ anonymous ]]",
|
||||
identifiers
|
||||
identifiers,
|
||||
cx.fbtOperands
|
||||
),
|
||||
reactiveFunction
|
||||
);
|
||||
@@ -391,17 +399,20 @@ class Context {
|
||||
errors: CompilerError = new CompilerError();
|
||||
objectMethods: Map<IdentifierId, ObjectMethod> = new Map();
|
||||
uniqueIdentifiers: Set<string>;
|
||||
fbtOperands: Set<IdentifierId>;
|
||||
synthesizedNames: Map<string, ValidIdentifierName> = new Map();
|
||||
|
||||
constructor(
|
||||
env: Environment,
|
||||
fnName: string,
|
||||
uniqueIdentifiers: Set<string>,
|
||||
fbtOperands: Set<IdentifierId>,
|
||||
temporaries: Temporaries | null = null
|
||||
) {
|
||||
this.env = env;
|
||||
this.fnName = fnName;
|
||||
this.uniqueIdentifiers = uniqueIdentifiers;
|
||||
this.fbtOperands = fbtOperands;
|
||||
this.temp = temporaries !== null ? new Map(temporaries) : new Map();
|
||||
}
|
||||
get nextCacheIndex(): number {
|
||||
@@ -1776,6 +1787,7 @@ function codegenInstructionValue(
|
||||
cx.env,
|
||||
reactiveFunction.id ?? "[[ anonymous ]]",
|
||||
cx.uniqueIdentifiers,
|
||||
cx.fbtOperands,
|
||||
cx.temp
|
||||
),
|
||||
reactiveFunction
|
||||
@@ -1979,6 +1991,7 @@ function codegenInstructionValue(
|
||||
cx.env,
|
||||
reactiveFunction.id ?? "[[ anonymous ]]",
|
||||
cx.uniqueIdentifiers,
|
||||
cx.fbtOperands,
|
||||
cx.temp
|
||||
),
|
||||
reactiveFunction
|
||||
@@ -2229,7 +2242,10 @@ function codegenJsxAttribute(
|
||||
switch (innerValue.type) {
|
||||
case "StringLiteral": {
|
||||
value = innerValue;
|
||||
if (STRING_REQUIRES_EXPR_CONTAINER_PATTERN.test(value.value)) {
|
||||
if (
|
||||
STRING_REQUIRES_EXPR_CONTAINER_PATTERN.test(value.value) &&
|
||||
!cx.fbtOperands.has(attribute.place.identifier.id)
|
||||
) {
|
||||
value = createJsxExpressionContainer(value.loc, value);
|
||||
}
|
||||
break;
|
||||
|
||||
+4
-1
@@ -39,7 +39,9 @@ import { eachReactiveValueOperand } from "./visitors";
|
||||
* Users can also specify their own functions to be treated similarly to fbt via the
|
||||
* `customMacros` environment configuration.
|
||||
*/
|
||||
export function memoizeFbtAndMacroOperandsInSameScope(fn: HIRFunction): void {
|
||||
export function memoizeFbtAndMacroOperandsInSameScope(
|
||||
fn: HIRFunction
|
||||
): Set<IdentifierId> {
|
||||
const fbtMacroTags = new Set([
|
||||
...FBT_TAGS,
|
||||
...(fn.env.config.customMacros ?? []),
|
||||
@@ -52,6 +54,7 @@ export function memoizeFbtAndMacroOperandsInSameScope(fn: HIRFunction): void {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fbtValues;
|
||||
}
|
||||
|
||||
export const FBT_TAGS: Set<string> = new Set([
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const element = (
|
||||
<fbt desc={"Dialog to show to user"}>
|
||||
Hello{" "}
|
||||
<fbt:param
|
||||
name="a really long description
|
||||
that got split into multiple lines"
|
||||
>
|
||||
{props.name}
|
||||
</fbt:param>
|
||||
</fbt>
|
||||
);
|
||||
return element.toString();
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Cannot read properties of undefined (reading 'replace')
|
||||
```
|
||||
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const element = (
|
||||
<fbt desc={"Dialog to show to user"}>
|
||||
Hello <fbt:param name='"user" name'>{props.name}</fbt:param>
|
||||
</fbt>
|
||||
);
|
||||
return element.toString();
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Property arguments[0] of CallExpression expected node to be of a type ["Expression","SpreadElement","JSXNamespacedName","ArgumentPlaceholder"] but instead got "JSXExpressionContainer"
|
||||
```
|
||||
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const element = (
|
||||
<fbt desc={"Dialog to show to user"}>
|
||||
Hello <fbt:param name="user name ☺">{props.name}</fbt:param>
|
||||
</fbt>
|
||||
);
|
||||
return element.toString();
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
Property arguments[0] of CallExpression expected node to be of a type ["Expression","SpreadElement","JSXNamespacedName","ArgumentPlaceholder"] but instead got "JSXExpressionContainer"
|
||||
```
|
||||
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const element = (
|
||||
<fbt desc={"Dialog to show to user"}>
|
||||
Hello{" "}
|
||||
<fbt:param
|
||||
name="a really long description
|
||||
that got split into multiple lines"
|
||||
>
|
||||
{props.name}
|
||||
</fbt:param>
|
||||
</fbt>
|
||||
);
|
||||
return element.toString();
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
let t0;
|
||||
if ($[0] !== props.name) {
|
||||
t0 = fbt._(
|
||||
"Hello {a really long description that got split into multiple lines}",
|
||||
[
|
||||
fbt._param(
|
||||
"a really long description that got split into multiple lines",
|
||||
|
||||
props.name,
|
||||
),
|
||||
],
|
||||
{ hk: "1euPUp" },
|
||||
);
|
||||
$[0] = props.name;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const element = t0;
|
||||
let t1;
|
||||
if ($[2] !== element) {
|
||||
t1 = element.toString();
|
||||
$[2] = element;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) "Hello Jason"
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const element = (
|
||||
<fbt desc={"Dialog to show to user"}>
|
||||
Hello <fbt:param name='"user" name'>{props.name}</fbt:param>
|
||||
</fbt>
|
||||
);
|
||||
return element.toString();
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
let t0;
|
||||
if ($[0] !== props.name) {
|
||||
t0 = fbt._('Hello {"user" name}', [fbt._param('"user" name', props.name)], {
|
||||
hk: "S0vMe",
|
||||
});
|
||||
$[0] = props.name;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const element = t0;
|
||||
let t1;
|
||||
if ($[2] !== element) {
|
||||
t1 = element.toString();
|
||||
$[2] = element;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) "Hello Jason"
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const element = (
|
||||
<fbt desc={"Dialog to show to user"}>
|
||||
Hello <fbt:param name="user name ☺">{props.name}</fbt:param>
|
||||
</fbt>
|
||||
);
|
||||
return element.toString();
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import fbt from "fbt";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
let t0;
|
||||
if ($[0] !== props.name) {
|
||||
t0 = fbt._(
|
||||
"Hello {user name ☺}",
|
||||
[fbt._param("user name \u263A", props.name)],
|
||||
{ hk: "1En1lp" },
|
||||
);
|
||||
$[0] = props.name;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const element = t0;
|
||||
let t1;
|
||||
if ($[2] !== element) {
|
||||
t1 = element.toString();
|
||||
$[2] = element;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ name: "Jason" }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) "Hello Jason"
|
||||
Reference in New Issue
Block a user