compiler: fix jsx text attributes with double quotes (#29079)
Fixes #29069 by detecting the presence of double-quotes in JSX attribute strings and falling back to using an expression container.
Joseph Savona committed
May 15, 2024 at 14:40 UTC
3adca7a477f7dd025ea02599b59433b86ac8fd59
8 files changed
+192
compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts
+3
@@ -2040,6 +2040,9 @@ function codegenJsxAttribute(
2040
switch (innerValue.type) {
2041
case "StringLiteral": {
2042
value = innerValue;
2043
+ if (value.value.indexOf('"') !== -1) {
2044
+ value = createJsxExpressionContainer(value.loc, value);
2045
+ }
2046
break;
2047
}
2048
default: {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute-escaped.expect.md
new
+48
@@ -0,0 +1,48 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+export function Component() {
6
+ return <Child text='Some \"text\"' />;
7
+}
8
+
9
+function Child(props) {
10
+ return props.text;
11
+}
12
+
13
+export const FIXTURE_ENTRYPOINT = {
14
+ fn: Component,
15
+ params: [{}],
16
+};
17
+
18
+```
19
+
20
+## Code
21
+
22
+```javascript
23
+import { c as _c } from "react/compiler-runtime";
24
+export function Component() {
25
+ const $ = _c(1);
26
+ let t0;
27
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28
+ t0 = <Child text={'Some \\"text\\"'} />;
29
+ $[0] = t0;
30
+ } else {
31
+ t0 = $[0];
32
+ }
33
+ return t0;
34
+}
35
+
36
+function Child(props) {
37
+ return props.text;
38
+}
39
+
40
+export const FIXTURE_ENTRYPOINT = {
41
+ fn: Component,
42
+ params: [{}],
43
+};
44
+
45
+```
46
+
47
+### Eval output
48
+(kind: ok) Some \"text\"
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute-escaped.js
new
+12
@@ -0,0 +1,12 @@
1
+export function Component() {
2
+ return <Child text='Some \"text\"' />;
3
+}
4
+
5
+function Child(props) {
6
+ return props.text;
7
+}
8
+
9
+export const FIXTURE_ENTRYPOINT = {
10
+ fn: Component,
11
+ params: [{}],
12
+};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute.expect.md
new
+48
@@ -0,0 +1,48 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+export function Component() {
6
+ return <Child text='Some "text"' />;
7
+}
8
+
9
+function Child(props) {
10
+ return props.text;
11
+}
12
+
13
+export const FIXTURE_ENTRYPOINT = {
14
+ fn: Component,
15
+ params: [{}],
16
+};
17
+
18
+```
19
+
20
+## Code
21
+
22
+```javascript
23
+import { c as _c } from "react/compiler-runtime";
24
+export function Component() {
25
+ const $ = _c(1);
26
+ let t0;
27
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28
+ t0 = <Child text={'Some "text"'} />;
29
+ $[0] = t0;
30
+ } else {
31
+ t0 = $[0];
32
+ }
33
+ return t0;
34
+}
35
+
36
+function Child(props) {
37
+ return props.text;
38
+}
39
+
40
+export const FIXTURE_ENTRYPOINT = {
41
+ fn: Component,
42
+ params: [{}],
43
+};
44
+
45
+```
46
+
47
+### Eval output
48
+(kind: ok) Some "text"
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-in-jsx-attribute.js
new
+12
@@ -0,0 +1,12 @@
1
+export function Component() {
2
+ return <Child text='Some "text"' />;
3
+}
4
+
5
+function Child(props) {
6
+ return props.text;
7
+}
8
+
9
+export const FIXTURE_ENTRYPOINT = {
10
+ fn: Component,
11
+ params: [{}],
12
+};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-jsx-attribute-escaped-constant-propagation.expect.md
new
+50
@@ -0,0 +1,50 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+export function Component() {
6
+ // Test what happens if a string with double-quotes is interpolated via constant propagation
7
+ const text = 'Some "text"';
8
+ return <Child text={text} />;
9
+}
10
+
11
+function Child(props) {
12
+ return props.text;
13
+}
14
+
15
+export const FIXTURE_ENTRYPOINT = {
16
+ fn: Component,
17
+ params: [{}],
18
+};
19
+
20
+```
21
+
22
+## Code
23
+
24
+```javascript
25
+import { c as _c } from "react/compiler-runtime";
26
+export function Component() {
27
+ const $ = _c(1);
28
+ let t0;
29
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30
+ t0 = <Child text={'Some "text"'} />;
31
+ $[0] = t0;
32
+ } else {
33
+ t0 = $[0];
34
+ }
35
+ return t0;
36
+}
37
+
38
+function Child(props) {
39
+ return props.text;
40
+}
41
+
42
+export const FIXTURE_ENTRYPOINT = {
43
+ fn: Component,
44
+ params: [{}],
45
+};
46
+
47
+```
48
+
49
+### Eval output
50
+(kind: ok) Some "text"
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/quoted-strings-jsx-attribute-escaped-constant-propagation.js
new
+14
@@ -0,0 +1,14 @@
1
+export function Component() {
2
+ // Test what happens if a string with double-quotes is interpolated via constant propagation
3
+ const text = 'Some "text"';
4
+ return <Child text={text} />;
5
+}
6
+
7
+function Child(props) {
8
+ return props.text;
9
+}
10
+
11
+export const FIXTURE_ENTRYPOINT = {
12
+ fn: Component,
13
+ params: [{}],
14
+};
compiler/yarn.lock
+5
@@ -3745,6 +3745,11 @@ babel-plugin-polyfill-regenerator@^0.5.0:
3745
dependencies:
3746
"@babel/helper-define-polyfill-provider" "^0.4.0"
3747
3748
+babel-plugin-react-compiler@*:
3749
+ version "0.0.0"
3750
+ resolved "https://registry.yarnpkg.com/babel-plugin-react-compiler/-/babel-plugin-react-compiler-0.0.0.tgz#1a1f9867fad83f217f0b3fe6f1b94cca0b77b68b"
3751
+ integrity sha512-Kigl0V36a/6hLVH7+CCe1CCtU3mFBqBd829V//VtuG7I/pyq+B2QZJqOefd63snQmdfCryNhO9XW1FbGPBvYDA==
3752
+
3753
babel-plugin-syntax-hermes-parser@^0.15.1:
3754
version "0.15.1"
3755
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.15.1.tgz#d115ee9761a808af590a9b2a0b568115e25ea743"