Compare commits
1 Commits
asserts-st
...
pr34424
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8219b34b60 |
@@ -748,10 +748,14 @@ function applyEffect(
|
|||||||
case 'Alias':
|
case 'Alias':
|
||||||
case 'Capture': {
|
case 'Capture': {
|
||||||
CompilerError.invariant(
|
CompilerError.invariant(
|
||||||
effect.kind === 'Capture' || initialized.has(effect.into.identifier.id),
|
effect.kind === 'Capture' ||
|
||||||
|
effect.kind === 'MaybeAlias' ||
|
||||||
|
initialized.has(effect.into.identifier.id),
|
||||||
{
|
{
|
||||||
reason: `Expected destination value to already be initialized within this instruction for Alias effect`,
|
reason: `Expected destination to already be initialized within this instruction`,
|
||||||
description: `Destination ${printPlace(effect.into)} is not initialized in this instruction`,
|
description:
|
||||||
|
`Destination ${printPlace(effect.into)} is not initialized in this ` +
|
||||||
|
`instruction for effect ${printAliasingEffect(effect)}`,
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
kind: 'error',
|
kind: 'error',
|
||||||
@@ -767,29 +771,40 @@ function applyEffect(
|
|||||||
* copy-on-write semantics, then we can prune the effect
|
* copy-on-write semantics, then we can prune the effect
|
||||||
*/
|
*/
|
||||||
const intoKind = state.kind(effect.into).kind;
|
const intoKind = state.kind(effect.into).kind;
|
||||||
let isMutableDesination: boolean;
|
let destinationType: 'context' | 'mutable' | null = null;
|
||||||
switch (intoKind) {
|
switch (intoKind) {
|
||||||
case ValueKind.Context:
|
case ValueKind.Context: {
|
||||||
case ValueKind.Mutable:
|
destinationType = 'context';
|
||||||
case ValueKind.MaybeFrozen: {
|
|
||||||
isMutableDesination = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
case ValueKind.Mutable:
|
||||||
isMutableDesination = false;
|
case ValueKind.MaybeFrozen: {
|
||||||
|
destinationType = 'mutable';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const fromKind = state.kind(effect.from).kind;
|
const fromKind = state.kind(effect.from).kind;
|
||||||
let isMutableReferenceType: boolean;
|
let sourceType: 'context' | 'mutable' | 'frozen' | null = null;
|
||||||
switch (fromKind) {
|
switch (fromKind) {
|
||||||
|
case ValueKind.Context: {
|
||||||
|
sourceType = 'context';
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ValueKind.Global:
|
case ValueKind.Global:
|
||||||
case ValueKind.Primitive: {
|
case ValueKind.Primitive: {
|
||||||
isMutableReferenceType = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ValueKind.Frozen: {
|
case ValueKind.Frozen: {
|
||||||
isMutableReferenceType = false;
|
sourceType = 'frozen';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
sourceType = 'mutable';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType === 'frozen') {
|
||||||
applyEffect(
|
applyEffect(
|
||||||
context,
|
context,
|
||||||
state,
|
state,
|
||||||
@@ -801,15 +816,22 @@ function applyEffect(
|
|||||||
initialized,
|
initialized,
|
||||||
effects,
|
effects,
|
||||||
);
|
);
|
||||||
break;
|
} else if (
|
||||||
}
|
(sourceType === 'mutable' && destinationType === 'mutable') ||
|
||||||
default: {
|
effect.kind === 'MaybeAlias'
|
||||||
isMutableReferenceType = true;
|
) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isMutableDesination && isMutableReferenceType) {
|
|
||||||
effects.push(effect);
|
effects.push(effect);
|
||||||
|
} else if (
|
||||||
|
(sourceType === 'context' && destinationType != null) ||
|
||||||
|
(sourceType === 'mutable' && destinationType === 'context')
|
||||||
|
) {
|
||||||
|
applyEffect(
|
||||||
|
context,
|
||||||
|
state,
|
||||||
|
{kind: 'MaybeAlias', from: effect.from, into: effect.into},
|
||||||
|
initialized,
|
||||||
|
effects,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -779,7 +779,13 @@ class AliasingState {
|
|||||||
if (edge.index >= index) {
|
if (edge.index >= index) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
queue.push({place: edge.node, transitive, direction: 'forwards', kind});
|
queue.push({
|
||||||
|
place: edge.node,
|
||||||
|
transitive,
|
||||||
|
direction: 'forwards',
|
||||||
|
// Traversing a maybeAlias edge always downgrades to conditional mutation
|
||||||
|
kind: edge.kind === 'maybeAlias' ? MutationKind.Conditional : kind,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
for (const [alias, when] of node.createdFrom) {
|
for (const [alias, when] of node.createdFrom) {
|
||||||
if (when >= index) {
|
if (when >= index) {
|
||||||
@@ -807,7 +813,12 @@ class AliasingState {
|
|||||||
if (when >= index) {
|
if (when >= index) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
queue.push({place: alias, transitive, direction: 'backwards', kind});
|
queue.push({
|
||||||
|
place: alias,
|
||||||
|
transitive,
|
||||||
|
direction: 'backwards',
|
||||||
|
kind,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* MaybeAlias indicates potential data flow from unknown function calls,
|
* MaybeAlias indicates potential data flow from unknown function calls,
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// @compilationMode:"infer"
|
||||||
|
function Component() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
// const [state, setState] = useState(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
onChange={event => {
|
||||||
|
dispatch(...event.target);
|
||||||
|
event.target.value = '';
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function useDispatch() {
|
||||||
|
'use no memo';
|
||||||
|
// skip compilation to make it easier to debug the above function
|
||||||
|
return (...values) => {
|
||||||
|
console.log(...values);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{}],
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { c as _c } from "react/compiler-runtime"; // @compilationMode:"infer"
|
||||||
|
function Component() {
|
||||||
|
const $ = _c(2);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
let t0;
|
||||||
|
if ($[0] !== dispatch) {
|
||||||
|
t0 = (
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
onChange={(event) => {
|
||||||
|
dispatch(...event.target);
|
||||||
|
event.target.value = "";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
$[0] = dispatch;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function useDispatch() {
|
||||||
|
"use no memo";
|
||||||
|
// skip compilation to make it easier to debug the above function
|
||||||
|
return (...values) => {
|
||||||
|
console.log(...values);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{}],
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eval output
|
||||||
|
(kind: ok) <div><input type="file"></div>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// @compilationMode:"infer"
|
||||||
|
function Component() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
// const [state, setState] = useState(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
onChange={event => {
|
||||||
|
dispatch(...event.target);
|
||||||
|
event.target.value = '';
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function useDispatch() {
|
||||||
|
'use no memo';
|
||||||
|
// skip compilation to make it easier to debug the above function
|
||||||
|
return (...values) => {
|
||||||
|
console.log(...values);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{}],
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user