-
Notifications
You must be signed in to change notification settings - Fork 47.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[compiler] Patch array and argument spread mutability
Array and argument spreads may mutate stateful iterables. Spread sites should have `ConditionallyMutate` effects (e.g. mutate if the ValueKind is mutable, otherwise read). See - [ecma spec (13.2.4.1 Runtime Semantics: ArrayAccumulation. SpreadElement : ... AssignmentExpression)](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-runtime-semantics-arrayaccumulation). - [ecma spec 13.3.8.1 Runtime Semantics: ArgumentListEvaluation](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-runtime-semantics-argumentlistevaluation) Note that - Object and JSX Attribute spreads do not evaluate iterables (srcs [mozilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#description), [ecma](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-runtime-semantics-propertydefinitionevaluation)) - An ideal mutability inference system could model known collections (i.e. Arrays or Sets) as a "mutated collection of non-mutable objects" (see `todo-granular-iterator-semantics`), but this is not what we do today. As such, an array / argument spread will always extend the range of built-in arrays, sets, etc - Due to HIR limitations, call expressions with argument spreads may cause unnecessary bailouts and/or scope merging when we know the call itself has `freeze`, `capture`, or `read` semantics (e.g. `useHook(...mutableValue)`) We can deal with this by rewriting these call instructions to (1) create an intermediate array to consume the iterator and (2) capture and spread the array at the callsite
- Loading branch information
Showing
10 changed files
with
238 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
...t-compiler/src/__tests__/fixtures/compiler/array-spread-later-mutated.expect.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
|
||
## Input | ||
|
||
```javascript | ||
function useBar({arg}) { | ||
/** | ||
* Note that mutableIterator is mutated by the later object spread. Therefore, | ||
* `s.values()` should be memoized within the same block as the object spread. | ||
* In terms of compiler internals, they should have the same reactive scope. | ||
*/ | ||
const obj = {}; | ||
const s = new Set([obj, 5, 4]); | ||
const mutableIterator = s.values(); | ||
const arr = [...mutableIterator]; | ||
|
||
obj.x = arg; | ||
return arr; | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: useBar, | ||
params: [{arg: 3}], | ||
sequentialRenders: [{arg: 3}, {arg: 3}, {arg: 4}], | ||
}; | ||
|
||
``` | ||
|
||
## Code | ||
|
||
```javascript | ||
import { c as _c } from "react/compiler-runtime"; | ||
function useBar(t0) { | ||
const $ = _c(2); | ||
const { arg } = t0; | ||
let arr; | ||
if ($[0] !== arg) { | ||
const obj = {}; | ||
const s = new Set([obj, 5, 4]); | ||
const mutableIterator = s.values(); | ||
arr = [...mutableIterator]; | ||
|
||
obj.x = arg; | ||
$[0] = arg; | ||
$[1] = arr; | ||
} else { | ||
arr = $[1]; | ||
} | ||
return arr; | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: useBar, | ||
params: [{ arg: 3 }], | ||
sequentialRenders: [{ arg: 3 }, { arg: 3 }, { arg: 4 }], | ||
}; | ||
|
||
``` | ||
### Eval output | ||
(kind: ok) [{"x":3},5,4] | ||
[{"x":3},5,4] | ||
[{"x":4},5,4] |
20 changes: 20 additions & 0 deletions
20
...babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-spread-later-mutated.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
function useBar({arg}) { | ||
/** | ||
* Note that mutableIterator is mutated by the later object spread. Therefore, | ||
* `s.values()` should be memoized within the same block as the object spread. | ||
* In terms of compiler internals, they should have the same reactive scope. | ||
*/ | ||
const obj = {}; | ||
const s = new Set([obj, 5, 4]); | ||
const mutableIterator = s.values(); | ||
const arr = [...mutableIterator]; | ||
|
||
obj.x = arg; | ||
return arr; | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: useBar, | ||
params: [{arg: 3}], | ||
sequentialRenders: [{arg: 3}, {arg: 3}, {arg: 4}], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
42 changes: 42 additions & 0 deletions
42
...src/__tests__/fixtures/compiler/call-spread-argument-mutable-iterator.expect.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
|
||
## Input | ||
|
||
```javascript | ||
import {useIdentity} from 'shared-runtime'; | ||
|
||
function useFoo() { | ||
const it = new Set([1, 2]).values(); | ||
useIdentity(); | ||
return Math.max(...it); | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: useFoo, | ||
params: [{}], | ||
sequentialRenders: [{}, {}], | ||
}; | ||
|
||
``` | ||
|
||
## Code | ||
|
||
```javascript | ||
import { useIdentity } from "shared-runtime"; | ||
|
||
function useFoo() { | ||
const it = new Set([1, 2]).values(); | ||
useIdentity(); | ||
return Math.max(...it); | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: useFoo, | ||
params: [{}], | ||
sequentialRenders: [{}, {}], | ||
}; | ||
|
||
``` | ||
### Eval output | ||
(kind: ok) 2 | ||
2 |
13 changes: 13 additions & 0 deletions
13
...n-react-compiler/src/__tests__/fixtures/compiler/call-spread-argument-mutable-iterator.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import {useIdentity} from 'shared-runtime'; | ||
|
||
function useFoo() { | ||
const it = new Set([1, 2]).values(); | ||
useIdentity(); | ||
return Math.max(...it); | ||
} | ||
|
||
export const FIXTURE_ENTRYPOINT = { | ||
fn: useFoo, | ||
params: [{}], | ||
sequentialRenders: [{}, {}], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 3 additions & 2 deletions
5
...__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters