Compare commits

...

5 Commits

Author SHA1 Message Date
Mofei Zhang
1a24f30af8 [compiler][patch] Throw todo when encountering fbt param with unicode or double quote
[ghstack-poisoned]
2024-07-18 14:38:56 -04:00
Mofei Zhang
f62cedc900 Update on "[compiler][patch] Fix jsx non-ascii regex pattern"
[ghstack-poisoned]
2024-07-18 14:32:00 -04:00
Mofei Zhang
5768a14a8d Update on "[compiler][patch] Fix jsx non-ascii regex pattern"
[ghstack-poisoned]
2024-07-18 14:21:49 -04:00
Mofei Zhang
8fc521debd Update on "[compiler][patch] Fix jsx non-ascii regex pattern"
[ghstack-poisoned]
2024-07-18 14:19:41 -04:00
Mofei Zhang
13640daf03 [compiler][patch] Fix jsx non-ascii regex pattern
[ghstack-poisoned]
2024-07-18 14:11:07 -04:00
8 changed files with 169 additions and 10 deletions

View File

@@ -2205,8 +2205,8 @@ function codegenInstructionValue(
* u00A0 to uFFFF: All non-basic Latin characters
* https://en.wikipedia.org/wiki/List_of_Unicode_characters#Control_codes
*/
const STRING_REQUIRES_EXPR_CONTAINER_PATTERN =
/[\u{0000}-\u{001F}|\u{007F}|\u{0080}-\u{FFFF}]|"/u;
export const STRING_REQUIRES_EXPR_CONTAINER_PATTERN =
/[\u{0000}-\u{001F}\u{007F}\u{0080}-\u{FFFF}]|"/u;
function codegenJsxAttribute(
cx: Context,
attribute: JsxAttribute

View File

@@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import { CompilerError } from "..";
import {
HIRFunction,
IdentifierId,
@@ -12,6 +13,7 @@ import {
Place,
ReactiveValue,
} from "../HIR";
import { STRING_REQUIRES_EXPR_CONTAINER_PATTERN } from "./CodegenReactiveFunction";
import { eachReactiveValueOperand } from "./visitors";
/**
@@ -52,6 +54,25 @@ export function memoizeFbtAndMacroOperandsInSameScope(fn: HIRFunction): void {
break;
}
}
/**
* Hack in a check to ensure that we don't produce invalid ASTs in codegen
* (see https://github.com/facebook/react/pull/29997 and `fbt-param-with-quotes` fixture)
*/
for (const [, block] of fn.body.blocks) {
for (const { lvalue, value } of block.instructions) {
if (fbtValues.has(lvalue.identifier.id) && value.kind === "Primitive") {
if (typeof value.value === "string") {
if (STRING_REQUIRES_EXPR_CONTAINER_PATTERN.test(value.value)) {
CompilerError.throwTodo({
reason: "Handle non-ascii character in fbt-like macro operand",
loc: value.loc,
});
}
}
}
}
}
}
export const FBT_TAGS: Set<string> = new Set([

View File

@@ -0,0 +1,36 @@
## 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
```
4 | const element = (
5 | <fbt desc={"Dialog to show to user"}>
> 6 | Hello <fbt:param name='"user" name'>{props.name}</fbt:param>
| ^^^^^^^^^^^^^ Todo: Handle non-ascii character in fbt-like macro operand (6:6)
7 | </fbt>
8 | );
9 | return element.toString();
```

View File

@@ -0,0 +1,15 @@
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" }],
};

View File

@@ -0,0 +1,36 @@
## 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
```
4 | const element = (
5 | <fbt desc={"Dialog to show to user"}>
> 6 | Hello <fbt:param name="user name ☺">{props.name}</fbt:param>
| ^^^^^^^^^^^^^ Todo: Handle non-ascii character in fbt-like macro operand (6:6)
7 | </fbt>
8 | );
9 | return element.toString();
```

View File

@@ -0,0 +1,15 @@
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" }],
};

View File

@@ -6,9 +6,14 @@ import fbt from "fbt";
function Component(props) {
return (
<fbt desc={"Dialog to show to user"}>
Hello <fbt:param name="user name">{props.name}</fbt:param>
</fbt>
<div>
<fbt desc={"Dialog to show to user"}>
Hello <fbt:param name="user name">{props.name}</fbt:param>
</fbt>
<fbt desc={"Available actions|response"}>
<fbt:param name="actions|response">{props.actions}</fbt:param>
</fbt>
</div>
);
}
@@ -27,7 +32,7 @@ import { c as _c } from "react/compiler-runtime";
import fbt from "fbt";
function Component(props) {
const $ = _c(2);
const $ = _c(7);
let t0;
if ($[0] !== props.name) {
t0 = fbt._("Hello {user name}", [fbt._param("user name", props.name)], {
@@ -38,7 +43,33 @@ function Component(props) {
} else {
t0 = $[1];
}
return t0;
let t1;
if ($[2] !== props.actions) {
t1 = fbt._(
"{actions|response}",
[fbt._param("actions|response", props.actions)],
{ hk: "1cjfbg" },
);
$[2] = props.actions;
$[3] = t1;
} else {
t1 = $[3];
}
let t2;
if ($[4] !== t0 || $[5] !== t1) {
t2 = (
<div>
{t0}
{t1}
</div>
);
$[4] = t0;
$[5] = t1;
$[6] = t2;
} else {
t2 = $[6];
}
return t2;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -2,9 +2,14 @@ import fbt from "fbt";
function Component(props) {
return (
<fbt desc={"Dialog to show to user"}>
Hello <fbt:param name="user name">{props.name}</fbt:param>
</fbt>
<div>
<fbt desc={"Dialog to show to user"}>
Hello <fbt:param name="user name">{props.name}</fbt:param>
</fbt>
<fbt desc={"Available actions|response"}>
<fbt:param name="actions|response">{props.actions}</fbt:param>
</fbt>
</div>
);
}