Fix duplicate declaration from MergeConsecutiveScopes

This is a distilled version of the duplicate declaration @mofeiZ and I saw when 
trying to sync latest Forget internally, plus a fix to avoid the duplicate 
instruction.
This commit is contained in:
Joe Savona
2023-10-02 16:40:33 -07:00
parent 4779fa0f81
commit 41cb3c722e
3 changed files with 95 additions and 1 deletions
@@ -108,6 +108,9 @@ class Transform extends ReactiveFunctionTransform<void> {
// The updated set of instructions for the block. Stays null until
// we make changes (ie merge scopes)
let nextInstructions: ReactiveBlock | null = null;
// The maximum index within the original instructions that we have reached.
// Used to avoid emitting duplicate instructions
let maxIndex: number = 0;
// Called when we find some instruction that cannot be merged into a
// preceding scope, or we otherwise need to reset and not consider
@@ -121,8 +124,14 @@ class Transform extends ReactiveFunctionTransform<void> {
if (currentScope !== null) {
nextInstructions.push(...block.slice(currentScope.to, index));
}
if (index < block.length) {
// We can sometimes call resetCurrentScope twice for the same index,
// such as when an instruction resets and then a subsequent scope also resets.
// This is the only case in which we push instructions w/o gating on
// `currentScope != null`, so we avoid duplicates by checking the max index
// already emitted.
if (index < block.length && index > maxIndex) {
nextInstructions.push(block[index]!);
maxIndex = index;
}
}
currentScope = null;
@@ -0,0 +1,69 @@
## Input
```javascript
// @enableMergeConsecutiveScopes
function Component(id) {
const bar = (() => {})();
return (
<>
<Bar title={bar} />
<Bar title={id ? true : false} />
</>
);
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [null],
};
```
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react"; // @enableMergeConsecutiveScopes
function Component(id) {
const $ = useMemoCache(4);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = (() => {})();
$[0] = t0;
} else {
t0 = $[0];
}
const bar = t0;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <Bar title={bar} />;
$[1] = t1;
} else {
t1 = $[1];
}
const t2 = id ? true : false;
const c_2 = $[2] !== t2;
let t3;
if (c_2) {
t3 = (
<>
{t1}
<Bar title={t2} />
</>
);
$[2] = t2;
$[3] = t3;
} else {
t3 = $[3];
}
return t3;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [null],
};
```
@@ -0,0 +1,16 @@
// @enableMergeConsecutiveScopes
function Component(id) {
const bar = (() => {})();
return (
<>
<Bar title={bar} />
<Bar title={id ? true : false} />
</>
);
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [null],
};