mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[compiler][patch] Emit unary expressions instead of negative numbers
This is a babel bug + edge case. Babel compact mode produces invalid JavaScript (i.e. parse error) when given a `NumericLiteral` with a negative value. See https://codesandbox.io/p/devbox/5d47fr for repro. As a followup, we could change our test infra parse babel options (e.g. a babel transform options pragma) which could let us track regressions. We may add an "exhaustive" mode to the compiler test runner to test (1) different babel options and (2) commonly used versions.
This commit is contained in:
+11
-2
@@ -1726,7 +1726,7 @@ function codegenInstructionValue(
|
||||
}
|
||||
case 'UnaryExpression': {
|
||||
value = t.unaryExpression(
|
||||
instrValue.operator as 'throw', // todo
|
||||
instrValue.operator,
|
||||
codegenPlaceToExpression(cx, instrValue.value),
|
||||
);
|
||||
break;
|
||||
@@ -2582,7 +2582,16 @@ function codegenValue(
|
||||
value: boolean | number | string | null | undefined,
|
||||
): t.Expression {
|
||||
if (typeof value === 'number') {
|
||||
return t.numericLiteral(value);
|
||||
if (value < 0) {
|
||||
/**
|
||||
* Babel's code generator produces invalid JS for negative numbers when
|
||||
* run with { compact: true }.
|
||||
* See repro https://codesandbox.io/p/devbox/5d47fr
|
||||
*/
|
||||
return t.unaryExpression('-', t.numericLiteral(-value), false);
|
||||
} else {
|
||||
return t.numericLiteral(value);
|
||||
}
|
||||
} else if (typeof value === 'boolean') {
|
||||
return t.booleanLiteral(value);
|
||||
} else if (typeof value === 'string') {
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
function Repro(props) {
|
||||
const MY_CONST = -2;
|
||||
return <Stringify>{props.arg - MY_CONST}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Repro,
|
||||
params: [
|
||||
{
|
||||
arg: 3,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { Stringify } from "shared-runtime";
|
||||
|
||||
function Repro(props) {
|
||||
const $ = _c(2);
|
||||
|
||||
const t0 = props.arg - -2;
|
||||
let t1;
|
||||
if ($[0] !== t0) {
|
||||
t1 = <Stringify>{t0}</Stringify>;
|
||||
$[0] = t0;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Repro,
|
||||
params: [
|
||||
{
|
||||
arg: 3,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"children":5}</div>
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import {Stringify} from 'shared-runtime';
|
||||
|
||||
function Repro(props) {
|
||||
const MY_CONST = -2;
|
||||
return <Stringify>{props.arg - MY_CONST}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Repro,
|
||||
params: [
|
||||
{
|
||||
arg: 3,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -242,6 +242,7 @@ export async function transformFixtureInput(
|
||||
filename: virtualFilepath,
|
||||
highlightCode: false,
|
||||
retainLines: true,
|
||||
compact: true,
|
||||
plugins: [
|
||||
[plugin, options],
|
||||
'babel-plugin-fbt',
|
||||
|
||||
Reference in New Issue
Block a user