mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Allow accessing properties of globals in switch test values
We limit the types of expressions allowed as switch case test values because we
our HIR doesn't yet preserve order-of-evaluation for switch test values (we
model them as being evaluated prior to entering the switch, as opposed to
lazily, when the case is reached). One common pattern internally is test case
values that are properties of a global, eg you have some bag of enum values and
are comparing against that:
```javascript
// at module scope, or imported from another module:
const OPTIONS = {FOO: 'foo'};
// in a component
switch (value) {
case OPTIONS.FOO: { ... }
}
```
This PR allows this specific case, ie member expressions where the innermost
object is a global identifier.
This commit is contained in:
@@ -524,6 +524,31 @@ function lowerStatement(
|
||||
// ok
|
||||
break;
|
||||
}
|
||||
case "MemberExpression": {
|
||||
// A common pattern is switch statements where the case test values are properties of a global,
|
||||
// eg `case ProductOptions.Option: { ... }`
|
||||
// We therefore allow expressions where the innermost object is a global identifier, and reject
|
||||
// all other member expressions (for now).
|
||||
const test = testExpr as NodePath<t.MemberExpression>;
|
||||
let innerObject: NodePath<t.Expression> = test;
|
||||
while (innerObject.isMemberExpression()) {
|
||||
innerObject = innerObject.get("object");
|
||||
}
|
||||
if (
|
||||
innerObject.isIdentifier() &&
|
||||
builder.resolveIdentifier(innerObject) === null // null means global
|
||||
) {
|
||||
// This is a property/computed load from a global, that's safe to evaluate as a test expression
|
||||
break;
|
||||
}
|
||||
builder.errors.push({
|
||||
reason:
|
||||
"(BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported",
|
||||
severity: ErrorSeverity.Todo,
|
||||
nodePath: testExpr,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
builder.errors.push({
|
||||
reason:
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
switch (props.value) {
|
||||
case Global.Property: {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
switch (props.value) {
|
||||
case Global.Property: {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
function Component(props) {
|
||||
switch (props.value) {
|
||||
case Global.Property: {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user