mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
[compiler][optim] Add shape for Array.from (#32522)
(see title) --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32522). * #32596 * #32595 * #32594 * #32593 * __->__ #32522 * #32521
This commit is contained in:
parent
ed1264f077
commit
38a7600920
|
|
@ -119,8 +119,8 @@ const TYPED_GLOBALS: Array<[string, BuiltInType]> = [
|
|||
],
|
||||
/*
|
||||
* https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.from
|
||||
* Array.from(arrayLike, optionalFn, optionalThis) not added because
|
||||
* the Effect of `arrayLike` is polymorphic i.e.
|
||||
* Array.from(arrayLike, optionalFn, optionalThis)
|
||||
* Note that the Effect of `arrayLike` is polymorphic i.e.
|
||||
* - Effect.read if
|
||||
* - it does not have an @iterator property and is array-like
|
||||
* (i.e. has a length property)
|
||||
|
|
@ -128,6 +128,20 @@ const TYPED_GLOBALS: Array<[string, BuiltInType]> = [
|
|||
* - Effect.mutate if it is a self-mutative iterator (e.g. a generator
|
||||
* function)
|
||||
*/
|
||||
[
|
||||
'from',
|
||||
addFunction(DEFAULT_SHAPES, [], {
|
||||
positionalParams: [
|
||||
Effect.ConditionallyMutate,
|
||||
Effect.ConditionallyMutate,
|
||||
Effect.ConditionallyMutate,
|
||||
],
|
||||
restParam: Effect.Read,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'of',
|
||||
// Array.of(element0, ..., elementN)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {useIdentity, Stringify} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
* TODO: Note that this `Array.from` is inferred to be mutating its first
|
||||
* argument. This is because React Compiler's typing system does not yet support
|
||||
* annotating a function with a set of argument match cases + distinct
|
||||
* definitions (polymorphism).
|
||||
*
|
||||
* In this case, we should be able to infer that the `Array.from` call is
|
||||
* not mutating its 0th argument.
|
||||
* The 0th argument should be typed as having `effect:Mutate` only when
|
||||
* (1) it might be a mutable iterable or
|
||||
* (2) the 1st argument might mutate its callee
|
||||
*/
|
||||
function Component({value}) {
|
||||
const arr = [{value: 'foo'}, {value: 'bar'}, {value}];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr, (x, idx) => ({...x, id: idx}));
|
||||
return <Stringify>{derived.at(-1)}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: 5}],
|
||||
sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { useIdentity, Stringify } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* TODO: Note that this `Array.from` is inferred to be mutating its first
|
||||
* argument. This is because React Compiler's typing system does not yet support
|
||||
* annotating a function with a set of argument match cases + distinct
|
||||
* definitions (polymorphism).
|
||||
*
|
||||
* In this case, we should be able to infer that the `Array.from` call is
|
||||
* not mutating its 0th argument.
|
||||
* The 0th argument should be typed as having `effect:Mutate` only when
|
||||
* (1) it might be a mutable iterable or
|
||||
* (2) the 1st argument might mutate its callee
|
||||
*/
|
||||
function Component(t0) {
|
||||
const $ = _c(4);
|
||||
const { value } = t0;
|
||||
const arr = [{ value: "foo" }, { value: "bar" }, { value }];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr, _temp);
|
||||
let t1;
|
||||
if ($[0] !== derived) {
|
||||
t1 = derived.at(-1);
|
||||
$[0] = derived;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
let t2;
|
||||
if ($[2] !== t1) {
|
||||
t2 = <Stringify>{t1}</Stringify>;
|
||||
$[2] = t1;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
function _temp(x, idx) {
|
||||
return { ...x, id: idx };
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ value: 5 }],
|
||||
sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"children":{"value":5,"id":2}}</div>
|
||||
<div>{"children":{"value":6,"id":2}}</div>
|
||||
<div>{"children":{"value":6,"id":2}}</div>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import {useIdentity, Stringify} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
* TODO: Note that this `Array.from` is inferred to be mutating its first
|
||||
* argument. This is because React Compiler's typing system does not yet support
|
||||
* annotating a function with a set of argument match cases + distinct
|
||||
* definitions (polymorphism).
|
||||
*
|
||||
* In this case, we should be able to infer that the `Array.from` call is
|
||||
* not mutating its 0th argument.
|
||||
* The 0th argument should be typed as having `effect:Mutate` only when
|
||||
* (1) it might be a mutable iterable or
|
||||
* (2) the 1st argument might mutate its callee
|
||||
*/
|
||||
function Component({value}) {
|
||||
const arr = [{value: 'foo'}, {value: 'bar'}, {value}];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr, (x, idx) => ({...x, id: idx}));
|
||||
return <Stringify>{derived.at(-1)}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: 5}],
|
||||
sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {useIdentity, Stringify} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
* TODO: Note that this `Array.from` is inferred to be mutating its first
|
||||
* argument. This is because React Compiler's typing system does not yet support
|
||||
* annotating a function with a set of argument match cases + distinct
|
||||
* definitions (polymorphism)
|
||||
*
|
||||
* In this case, we should be able to infer that the `Array.from` call is
|
||||
* not mutating its 0th argument.
|
||||
* The 0th argument should be typed as having `effect:Mutate` only when
|
||||
* (1) it might be a mutable iterable or
|
||||
* (2) the 1st argument might mutate its callee
|
||||
*/
|
||||
function Component({value}) {
|
||||
const arr = [{value: 'foo'}, {value: 'bar'}, {value}];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr);
|
||||
return <Stringify>{derived.at(-1)}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: 5}],
|
||||
sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { useIdentity, Stringify } from "shared-runtime";
|
||||
|
||||
/**
|
||||
* TODO: Note that this `Array.from` is inferred to be mutating its first
|
||||
* argument. This is because React Compiler's typing system does not yet support
|
||||
* annotating a function with a set of argument match cases + distinct
|
||||
* definitions (polymorphism)
|
||||
*
|
||||
* In this case, we should be able to infer that the `Array.from` call is
|
||||
* not mutating its 0th argument.
|
||||
* The 0th argument should be typed as having `effect:Mutate` only when
|
||||
* (1) it might be a mutable iterable or
|
||||
* (2) the 1st argument might mutate its callee
|
||||
*/
|
||||
function Component(t0) {
|
||||
const $ = _c(4);
|
||||
const { value } = t0;
|
||||
const arr = [{ value: "foo" }, { value: "bar" }, { value }];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr);
|
||||
let t1;
|
||||
if ($[0] !== derived) {
|
||||
t1 = derived.at(-1);
|
||||
$[0] = derived;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
let t2;
|
||||
if ($[2] !== t1) {
|
||||
t2 = <Stringify>{t1}</Stringify>;
|
||||
$[2] = t1;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ value: 5 }],
|
||||
sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"children":{"value":5}}</div>
|
||||
<div>{"children":{"value":6}}</div>
|
||||
<div>{"children":{"value":6}}</div>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import {useIdentity, Stringify} from 'shared-runtime';
|
||||
|
||||
/**
|
||||
* TODO: Note that this `Array.from` is inferred to be mutating its first
|
||||
* argument. This is because React Compiler's typing system does not yet support
|
||||
* annotating a function with a set of argument match cases + distinct
|
||||
* definitions (polymorphism)
|
||||
*
|
||||
* In this case, we should be able to infer that the `Array.from` call is
|
||||
* not mutating its 0th argument.
|
||||
* The 0th argument should be typed as having `effect:Mutate` only when
|
||||
* (1) it might be a mutable iterable or
|
||||
* (2) the 1st argument might mutate its callee
|
||||
*/
|
||||
function Component({value}) {
|
||||
const arr = [{value: 'foo'}, {value: 'bar'}, {value}];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr);
|
||||
return <Stringify>{derived.at(-1)}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: 5}],
|
||||
sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],
|
||||
};
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';
|
||||
|
||||
function Component({value}) {
|
||||
const arr = [{value: 'foo'}, {value: 'bar'}, {value}];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr, mutateAndReturn);
|
||||
return <Stringify>{derived.at(-1)}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: 5}],
|
||||
sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { mutateAndReturn, Stringify, useIdentity } from "shared-runtime";
|
||||
|
||||
function Component(t0) {
|
||||
const $ = _c(4);
|
||||
const { value } = t0;
|
||||
const arr = [{ value: "foo" }, { value: "bar" }, { value }];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr, mutateAndReturn);
|
||||
let t1;
|
||||
if ($[0] !== derived) {
|
||||
t1 = derived.at(-1);
|
||||
$[0] = derived;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
let t2;
|
||||
if ($[2] !== t1) {
|
||||
t2 = <Stringify>{t1}</Stringify>;
|
||||
$[2] = t1;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ value: 5 }],
|
||||
sequentialRenders: [{ value: 5 }, { value: 6 }, { value: 6 }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <div>{"children":{"value":5,"wat0":"joe"}}</div>
|
||||
<div>{"children":{"value":6,"wat0":"joe"}}</div>
|
||||
<div>{"children":{"value":6,"wat0":"joe"}}</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import {mutateAndReturn, Stringify, useIdentity} from 'shared-runtime';
|
||||
|
||||
function Component({value}) {
|
||||
const arr = [{value: 'foo'}, {value: 'bar'}, {value}];
|
||||
useIdentity();
|
||||
const derived = Array.from(arr, mutateAndReturn);
|
||||
return <Stringify>{derived.at(-1)}</Stringify>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{value: 5}],
|
||||
sequentialRenders: [{value: 5}, {value: 6}, {value: 6}],
|
||||
};
|
||||
|
|
@ -68,21 +68,29 @@ function Validate({ x, input }) {
|
|||
}
|
||||
function useFoo(input) {
|
||||
"use memo";
|
||||
const $ = _c(3);
|
||||
const $ = _c(5);
|
||||
|
||||
const x = Array.from([{}]);
|
||||
useIdentity();
|
||||
x.push([input]);
|
||||
let t0;
|
||||
if ($[0] !== input || $[1] !== x) {
|
||||
t0 = <Validate x={x} input={input} />;
|
||||
if ($[0] !== input) {
|
||||
t0 = [input];
|
||||
$[0] = input;
|
||||
$[1] = x;
|
||||
$[2] = t0;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
x.push(t0);
|
||||
let t1;
|
||||
if ($[2] !== input || $[3] !== x) {
|
||||
t1 = <Validate x={x} input={input} />;
|
||||
$[2] = input;
|
||||
$[3] = x;
|
||||
$[4] = t1;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ function useFoo({val1, val2}) {
|
|||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{val1: 1, val2: 2}],
|
||||
params: [
|
||||
{val1: 1, val2: 2},
|
||||
{val1: 1, val2: 2},
|
||||
{val1: 1, val2: 3},
|
||||
{val1: 4, val2: 2},
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
|
@ -71,29 +77,51 @@ function Validate({ x, val1, val2 }) {
|
|||
}
|
||||
function useFoo(t0) {
|
||||
"use memo";
|
||||
const $ = _c(4);
|
||||
const $ = _c(8);
|
||||
const { val1, val2 } = t0;
|
||||
|
||||
const x = Array.from([]);
|
||||
useIdentity();
|
||||
x.push([val1]);
|
||||
x.push([val2]);
|
||||
let t1;
|
||||
if ($[0] !== val1 || $[1] !== val2 || $[2] !== x) {
|
||||
t1 = <Validate x={x} val1={val1} val2={val2} />;
|
||||
if ($[0] !== val1) {
|
||||
t1 = [val1];
|
||||
$[0] = val1;
|
||||
$[1] = val2;
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
x.push(t1);
|
||||
let t2;
|
||||
if ($[2] !== val2) {
|
||||
t2 = [val2];
|
||||
$[2] = val2;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t2 = $[3];
|
||||
}
|
||||
x.push(t2);
|
||||
let t3;
|
||||
if ($[4] !== val1 || $[5] !== val2 || $[6] !== x) {
|
||||
t3 = <Validate x={x} val1={val1} val2={val2} />;
|
||||
$[4] = val1;
|
||||
$[5] = val2;
|
||||
$[6] = x;
|
||||
$[7] = t3;
|
||||
} else {
|
||||
t3 = $[7];
|
||||
}
|
||||
return t3;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{ val1: 1, val2: 2 }],
|
||||
params: [
|
||||
{ val1: 1, val2: 2 },
|
||||
{ val1: 1, val2: 2 },
|
||||
{ val1: 1, val2: 3 },
|
||||
{ val1: 4, val2: 2 },
|
||||
],
|
||||
};
|
||||
|
||||
```
|
||||
|
|
@ -33,4 +33,10 @@ function useFoo({val1, val2}) {
|
|||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: useFoo,
|
||||
params: [{val1: 1, val2: 2}],
|
||||
params: [
|
||||
{val1: 1, val2: 2},
|
||||
{val1: 1, val2: 2},
|
||||
{val1: 1, val2: 3},
|
||||
{val1: 4, val2: 2},
|
||||
],
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user