mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
feat: queue w/ argument, plus additional queue fixes
This commit is contained in:
parent
a0e59440cb
commit
12dd67ad80
@ -6,9 +6,9 @@
|
||||
{
|
||||
"name": "*",
|
||||
"individual": {
|
||||
"min": 10028,
|
||||
"gzip": 4392,
|
||||
"brotli": 4033
|
||||
"min": 9986,
|
||||
"gzip": 4401,
|
||||
"brotli": 4020
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Context, setContext } from "../common/context";
|
||||
import { Scope, ScopeOffsets } from "../common/types";
|
||||
import { queue } from "./queue";
|
||||
import { reconcile } from "./reconcile";
|
||||
import { Renderer, initRenderer } from "./renderer";
|
||||
import {
|
||||
@ -25,16 +26,19 @@ type Conditional = {
|
||||
[ConditionalIndex.CONTEXT]: typeof Context;
|
||||
};
|
||||
|
||||
export function runInBranch(
|
||||
export function queueInBranch(
|
||||
conditionalIndex: number,
|
||||
branch: Renderer,
|
||||
fn: () => void
|
||||
fn: () => void,
|
||||
sortValue: number
|
||||
) {
|
||||
if (read(conditionalIndex + ConditionalIndex.RENDERER) === branch) {
|
||||
runWithScope(
|
||||
queue(
|
||||
fn,
|
||||
ScopeOffsets.BEGIN_DATA,
|
||||
read(conditionalIndex + ConditionalIndex.SCOPE) as Scope
|
||||
sortValue,
|
||||
undefined,
|
||||
read(conditionalIndex + ConditionalIndex.SCOPE) as Scope,
|
||||
ScopeOffsets.BEGIN_DATA
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
@ -109,8 +113,6 @@ export function setConditionalRenderer(
|
||||
prevScope.___getFirstNode()
|
||||
);
|
||||
prevScope.___remove();
|
||||
|
||||
return newRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,8 +141,6 @@ export function setConditionalRendererOnlyChild(
|
||||
initRenderer(newRenderer, newScope);
|
||||
newScope.___insertBefore(referenceNode, null);
|
||||
setContext(null);
|
||||
|
||||
return newRenderer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,11 +165,15 @@ type Loop = {
|
||||
[LoopIndex.CONTEXT]: typeof Context;
|
||||
};
|
||||
|
||||
export function runForEach(loopIndex: number, fn: () => void) {
|
||||
export function queueForEach(
|
||||
loopIndex: number,
|
||||
fn: () => void,
|
||||
sortValue: number
|
||||
) {
|
||||
for (const scope of read<Loop, LoopIndex.SCOPE_ARRAY>(
|
||||
loopIndex + LoopIndex.SCOPE_ARRAY
|
||||
)) {
|
||||
runWithScope(fn, ScopeOffsets.BEGIN_DATA, scope);
|
||||
queue(fn, sortValue, undefined, scope, ScopeOffsets.BEGIN_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Renderer } from "./renderer";
|
||||
import { onDestroy, Scope, ScopeOffsets, read, write } from "./scope";
|
||||
import { withQueueNext } from "./queue";
|
||||
|
||||
export const enum NodeType {
|
||||
Element = 1,
|
||||
@ -206,9 +207,9 @@ function normalizeString(value: unknown) {
|
||||
type EffectFn = () => void | (() => void);
|
||||
export function userEffect(index: number, fn: EffectFn) {
|
||||
const cleanup = read(index) as ReturnType<EffectFn>;
|
||||
const nextCleanup = fn();
|
||||
const nextCleanup = withQueueNext(fn);
|
||||
if (cleanup) {
|
||||
cleanup();
|
||||
withQueueNext(cleanup);
|
||||
} else {
|
||||
onDestroy(index);
|
||||
}
|
||||
@ -223,7 +224,7 @@ export function lifecycle(
|
||||
) {
|
||||
const mounted = read(index);
|
||||
if (!mounted) {
|
||||
if (mount) mount();
|
||||
if (mount) withQueueNext(mount);
|
||||
onDestroy(index + 1);
|
||||
}
|
||||
if (mounted && update) update();
|
||||
|
||||
@ -3,7 +3,8 @@ export {
|
||||
setConditionalRendererOnlyChild,
|
||||
getConditionalFirstNode,
|
||||
getConditionalLastNode,
|
||||
runInBranch,
|
||||
queueInBranch,
|
||||
queueForEach,
|
||||
setLoopOf,
|
||||
setLoopFromTo,
|
||||
setLoopIn,
|
||||
@ -40,10 +41,8 @@ export {
|
||||
readInOwner,
|
||||
writeInOwner,
|
||||
bind,
|
||||
writeQueued,
|
||||
runWithScope,
|
||||
runInChild,
|
||||
writeQueuedInOwner
|
||||
runInChild
|
||||
} from "./scope";
|
||||
|
||||
export { Scope } from "../common/types";
|
||||
|
||||
@ -4,12 +4,11 @@ import {
|
||||
runWithScope,
|
||||
currentScope,
|
||||
currentOffset,
|
||||
write,
|
||||
getOwnerScope,
|
||||
ownerOffset
|
||||
} from "./scope";
|
||||
|
||||
type ExecFn = (scope: Scope, offset: number) => void;
|
||||
type ExecFn = (...args: unknown[]) => void;
|
||||
|
||||
const { port1, port2 } = new MessageChannel();
|
||||
let queued: boolean;
|
||||
@ -29,11 +28,21 @@ function triggerMacroTask() {
|
||||
}
|
||||
|
||||
let queuedFns: unknown[] = [];
|
||||
// [fn, scope, offset, sourceCount]
|
||||
let queuedNext: unknown[] = [];
|
||||
|
||||
const enum QueueOffsets {
|
||||
FN = 0,
|
||||
SCOPE = 1,
|
||||
OFFSET = 2,
|
||||
SORT_VALUE = 3,
|
||||
ARGUMENT = 4,
|
||||
TOTAL = 5
|
||||
}
|
||||
|
||||
export function queue(
|
||||
fn: ExecFn,
|
||||
localIndex = 0,
|
||||
argument: unknown = undefined,
|
||||
scope = currentScope,
|
||||
offset = currentOffset
|
||||
) {
|
||||
@ -42,9 +51,9 @@ export function queue(
|
||||
// index is where the function should be in the queue
|
||||
// but if it already exists, we should not add it again
|
||||
if (
|
||||
queuedFns[index] !== fn ||
|
||||
queuedFns[index + 1] !== scope ||
|
||||
queuedFns[index + 2] !== offset
|
||||
queuedFns[index + QueueOffsets.FN] !== fn ||
|
||||
queuedFns[index + QueueOffsets.SCOPE] !== scope ||
|
||||
queuedFns[index + QueueOffsets.OFFSET] !== offset
|
||||
) {
|
||||
if (!queued) {
|
||||
queued = true;
|
||||
@ -52,80 +61,78 @@ export function queue(
|
||||
}
|
||||
|
||||
for (let i = queuedFns.length - 1; i >= index; i--) {
|
||||
queuedFns[i + 4] = queuedFns[i];
|
||||
queuedFns[i + QueueOffsets.TOTAL] = queuedFns[i];
|
||||
}
|
||||
|
||||
queuedFns[index] = fn;
|
||||
queuedFns[index + 1] = scope;
|
||||
queuedFns[index + 2] = offset;
|
||||
queuedFns[index + 3] = offset + localIndex;
|
||||
queuedFns[index + QueueOffsets.FN] = fn;
|
||||
queuedFns[index + QueueOffsets.SCOPE] = scope;
|
||||
queuedFns[index + QueueOffsets.OFFSET] = offset;
|
||||
queuedFns[index + QueueOffsets.SORT_VALUE] = offset + localIndex;
|
||||
}
|
||||
queuedFns[index + QueueOffsets.ARGUMENT] = argument;
|
||||
}
|
||||
|
||||
export function queueInOwner(
|
||||
fn: ExecFn,
|
||||
sourceCount?: number,
|
||||
localIndex?: number,
|
||||
argument?: unknown,
|
||||
ownerLevel?: number
|
||||
) {
|
||||
queue(fn, sourceCount, getOwnerScope(ownerLevel), ownerOffset);
|
||||
queue(fn, localIndex, argument, getOwnerScope(ownerLevel), ownerOffset);
|
||||
}
|
||||
|
||||
let queuedValues: unknown[] = [];
|
||||
export function setQueued(scope: Scope, index: number, value: unknown) {
|
||||
// TODO: if the same index is set twice for a scope,
|
||||
// the first one should be removed from the queue
|
||||
queuedValues.push(scope, index, value);
|
||||
export function withQueueNext(fn: () => unknown) {
|
||||
const current = queuedFns;
|
||||
queuedFns = queuedNext;
|
||||
const result = fn();
|
||||
queuedFns = current;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function run() {
|
||||
if (queuedFns.length) {
|
||||
const runningFns = queuedFns;
|
||||
const runningValues = queuedValues;
|
||||
queuedFns = [];
|
||||
queuedValues = [];
|
||||
for (let i = 0; i < runningValues.length; i += 3) {
|
||||
write(
|
||||
0,
|
||||
runningValues[i + 2] as unknown,
|
||||
runningValues[i] as Scope,
|
||||
runningValues[i + 1] as number
|
||||
);
|
||||
}
|
||||
for (let i = 0; i < runningFns.length; i += 4) {
|
||||
for (let i = 0; i < queuedFns.length; i += QueueOffsets.TOTAL) {
|
||||
runWithScope(
|
||||
runningFns[i] as ExecFn,
|
||||
runningFns[i + 2] as number,
|
||||
runningFns[i + 1] as Scope
|
||||
queuedFns[i + QueueOffsets.FN] as ExecFn,
|
||||
queuedFns[i + QueueOffsets.OFFSET] as number,
|
||||
queuedFns[i + QueueOffsets.SCOPE] as Scope,
|
||||
[queuedFns[i + QueueOffsets.ARGUMENT]]
|
||||
);
|
||||
}
|
||||
queuedFns = queuedNext;
|
||||
queuedNext = [];
|
||||
}
|
||||
}
|
||||
|
||||
function findQueueIndex(scope: Scope, offset: number) {
|
||||
function findQueueIndex(scope: Scope, sortValue: number) {
|
||||
let index = 0;
|
||||
let max = queuedFns.length >>> 2;
|
||||
let max = queuedFns.length / QueueOffsets.TOTAL;
|
||||
|
||||
while (index < max) {
|
||||
const mid = (index + max) >>> 1;
|
||||
const compareResult = compareQueue(mid * 4, scope, offset);
|
||||
const compareResult = compareQueue(
|
||||
mid * QueueOffsets.TOTAL,
|
||||
scope,
|
||||
sortValue
|
||||
);
|
||||
if (compareResult > 0) {
|
||||
max = mid;
|
||||
} else if (compareResult < 0) {
|
||||
index = mid + 1;
|
||||
} else {
|
||||
return mid * 4;
|
||||
return mid * QueueOffsets.TOTAL;
|
||||
}
|
||||
}
|
||||
|
||||
return index * 4;
|
||||
return index * QueueOffsets.TOTAL;
|
||||
}
|
||||
|
||||
function compareQueue(index: number, scope: Scope, offset: number) {
|
||||
function compareQueue(index: number, scope: Scope, sortValue: number) {
|
||||
return (
|
||||
compare(
|
||||
(queuedFns[index + 1] as Scope)[ScopeOffsets.ID],
|
||||
(queuedFns[index + QueueOffsets.SCOPE] as Scope)[ScopeOffsets.ID],
|
||||
scope[ScopeOffsets.ID]
|
||||
) || (queuedFns[index + 3] as number) - offset
|
||||
) || (queuedFns[index + QueueOffsets.SORT_VALUE] as number) - sortValue
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { ScopeOffsets } from "../common/types";
|
||||
import { DOMMethods, staticNodeMethods } from "./dom";
|
||||
import { createScope, Scope, runWithScope } from "./scope";
|
||||
import { WalkCodes, walk, trimWalkString } from "./walker";
|
||||
import { queue, run } from "./queue";
|
||||
|
||||
const enum NodeType {
|
||||
Element = 1,
|
||||
@ -82,12 +83,18 @@ export function createRenderFn<I extends Input>(
|
||||
return (input: I): RenderResult => {
|
||||
const scope = createScope(size!, domMethods!);
|
||||
const dom = initRenderer(renderer, scope) as RenderResult;
|
||||
dynamicInput &&
|
||||
runWithScope(dynamicInput, ScopeOffsets.BEGIN_DATA, scope, [input]);
|
||||
|
||||
if (dynamicInput) {
|
||||
queue(dynamicInput, -1, input, scope, ScopeOffsets.BEGIN_DATA);
|
||||
}
|
||||
|
||||
run();
|
||||
|
||||
dom.update = (newInput: I) => {
|
||||
dynamicInput &&
|
||||
runWithScope(dynamicInput, ScopeOffsets.BEGIN_DATA, scope, [newInput]);
|
||||
if (dynamicInput) {
|
||||
queue(dynamicInput, -1, newInput, scope, ScopeOffsets.BEGIN_DATA);
|
||||
run();
|
||||
}
|
||||
};
|
||||
|
||||
dom.destroy = () => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { DOMMethods, staticNodeMethods } from "./dom";
|
||||
import { setQueued } from "./queue";
|
||||
import { withQueueNext } from "./queue";
|
||||
import { Scope, ScopeOffsets } from "../common/types";
|
||||
|
||||
export { Scope, ScopeOffsets };
|
||||
@ -105,23 +105,6 @@ export function runInChild(fn: () => void, offset: number) {
|
||||
}
|
||||
}
|
||||
|
||||
export function writeQueued(
|
||||
localIndex: number,
|
||||
value: unknown,
|
||||
scope = currentScope,
|
||||
offset = currentOffset
|
||||
) {
|
||||
setQueued(scope, offset + localIndex, value);
|
||||
}
|
||||
|
||||
export function writeQueuedInOwner(
|
||||
localIndex: number,
|
||||
value: unknown,
|
||||
ownerLevel?: number
|
||||
) {
|
||||
writeQueued(localIndex, value, getOwnerScope(ownerLevel), ownerOffset);
|
||||
}
|
||||
|
||||
export function destroyScope(scope: Scope) {
|
||||
scope[ScopeOffsets.OWNER_SCOPE]?.[ScopeOffsets.CLEANUP]?.delete(scope);
|
||||
|
||||
@ -129,7 +112,7 @@ export function destroyScope(scope: Scope) {
|
||||
if (cleanup) {
|
||||
for (const instance of cleanup) {
|
||||
if (typeof instance === "number") {
|
||||
(scope[instance] as () => void)();
|
||||
withQueueNext(scope[instance] as () => void);
|
||||
} else {
|
||||
destroyScope(instance);
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
read,
|
||||
bind,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
queueInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
|
||||
import { get, next, over, open, close } from "../../utils/walks";
|
||||
@ -46,10 +46,8 @@ type scope = {
|
||||
export const template = `<button></button><!>`;
|
||||
export const walks = open(7) + get + over(1) + get + over(1) + close;
|
||||
export const render = () => {
|
||||
write(Index.SHOW, true);
|
||||
write(Index.MESSAGE, "hi");
|
||||
execShow();
|
||||
execMessage();
|
||||
execShow(true);
|
||||
execMessage("hi");
|
||||
hydrate();
|
||||
};
|
||||
|
||||
@ -58,23 +56,25 @@ export const hydrate = register("", () => {
|
||||
});
|
||||
|
||||
const clickHandler = () => {
|
||||
if (write(Index.MESSAGE, "bye")) {
|
||||
queue(execMessage, 6);
|
||||
}
|
||||
if (write(Index.SHOW, !read(Index.SHOW))) {
|
||||
queue(execShow, 5);
|
||||
queue(execMessage, Index.MESSAGE, "bye");
|
||||
queue(execShow, Index.SHOW, !read(Index.SHOW));
|
||||
};
|
||||
|
||||
const execShow = value => {
|
||||
if (write(Index.SHOW, value)) {
|
||||
setConditionalRenderer(Index.CONDITIONAL, value ? branch0 : undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const execShow = () => {
|
||||
setConditionalRenderer(
|
||||
Index.CONDITIONAL,
|
||||
read(Index.SHOW) ? branch0 : undefined
|
||||
);
|
||||
};
|
||||
|
||||
const execMessage = () => {
|
||||
runInBranch(Index.CONDITIONAL, branch0, execMessageBranch0);
|
||||
const execMessage = value => {
|
||||
if (write(Index.MESSAGE, value)) {
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execMessageBranch0,
|
||||
Branch0Index.CLOSURE_MESSAGE
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const execMessageBranch0 = () => {
|
||||
@ -86,6 +86,7 @@ export default createRenderFn(template, walks, render, 0);
|
||||
ensureDelegated("click");
|
||||
|
||||
const enum Branch0Index {
|
||||
CLOSURE_MESSAGE = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
@ -94,6 +95,8 @@ type Branch0Scope = [Text];
|
||||
const branch0 = createRenderer(
|
||||
"<span> </span>",
|
||||
next(1) + get + next(1),
|
||||
undefined,
|
||||
() => {
|
||||
queue(execMessageBranch0, Branch0Index.CLOSURE_MESSAGE);
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
@ -21,7 +21,8 @@ const enum Index {
|
||||
BUTTON = 0,
|
||||
TEXT = 1,
|
||||
A = 2,
|
||||
B = 3
|
||||
B = 3,
|
||||
SUM_AB = 4
|
||||
}
|
||||
|
||||
type scope = {
|
||||
@ -29,6 +30,7 @@ type scope = {
|
||||
[Index.TEXT]: Text;
|
||||
[Index.A]: number;
|
||||
[Index.B]: number;
|
||||
[Index.SUM_AB]: number;
|
||||
};
|
||||
|
||||
// <let/a = 0/>
|
||||
@ -38,9 +40,8 @@ type scope = {
|
||||
export const template = `<button> </button>`;
|
||||
export const walks = open(4) + get + next(1) + get + next(1) + close;
|
||||
export const render = () => {
|
||||
write(Index.A, 0);
|
||||
write(Index.B, 0);
|
||||
execAB();
|
||||
execA(0);
|
||||
execB(0);
|
||||
hydrate();
|
||||
};
|
||||
|
||||
@ -49,19 +50,30 @@ export const hydrate = register("", () => {
|
||||
});
|
||||
|
||||
const clickHandler = () => {
|
||||
if (
|
||||
write(Index.A, read<scope, Index.A>(Index.A) + 1) |
|
||||
write(Index.B, read<scope, Index.B>(Index.B) + 1)
|
||||
) {
|
||||
queue(execAB);
|
||||
queue(execA, Index.A, read<scope, Index.A>(Index.A) + 1);
|
||||
queue(execB, Index.B, read<scope, Index.B>(Index.B) + 1);
|
||||
};
|
||||
|
||||
const execA = (value: number) => {
|
||||
if (write(Index.A, value)) {
|
||||
queue(execAB, Index.SUM_AB);
|
||||
}
|
||||
};
|
||||
|
||||
const execB = (value: number) => {
|
||||
if (write(Index.B, value)) {
|
||||
queue(execAB, Index.SUM_AB);
|
||||
}
|
||||
};
|
||||
|
||||
const execAB = () => {
|
||||
data(
|
||||
Index.TEXT,
|
||||
read<scope, Index.A>(Index.A) + read<scope, Index.B>(Index.B)
|
||||
);
|
||||
execSumAB(read<scope, Index.A>(Index.A) + read<scope, Index.B>(Index.B));
|
||||
};
|
||||
|
||||
const execSumAB = (value: number) => {
|
||||
if (write(Index.SUM_AB, value)) {
|
||||
data(Index.TEXT, value);
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, render, 0);
|
||||
|
||||
@ -61,8 +61,9 @@ export const execInputChildren = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: Input) => {
|
||||
write(Index.INPUT_CHILDREN, input.children);
|
||||
execInputChildren();
|
||||
if (write(Index.INPUT_CHILDREN, input.children)) {
|
||||
execInputChildren();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -80,8 +80,9 @@ export const execInputChildren = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: Input) => {
|
||||
write(Index.INPUT_CHILDREN, input.children);
|
||||
execInputChildren();
|
||||
if (write(Index.INPUT_CHILDREN, input.children)) {
|
||||
execInputChildren();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -80,8 +80,9 @@ export const execInputChildren = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: Input) => {
|
||||
write(Index.INPUT_CHILDREN, input.children);
|
||||
execInputChildren();
|
||||
if (write(Index.INPUT_CHILDREN, input.children)) {
|
||||
execInputChildren();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -78,8 +78,9 @@ export const execInputChildren = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: Input) => {
|
||||
write(Index.INPUT_CHILDREN, input.children);
|
||||
execInputChildren();
|
||||
if (write(Index.INPUT_CHILDREN, input.children)) {
|
||||
execInputChildren();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -85,8 +85,9 @@ export const execInputChildren = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: Input) => {
|
||||
write(Index.INPUT_CHILDREN, input.children);
|
||||
execInputChildren();
|
||||
if (write(Index.INPUT_CHILDREN, input.children)) {
|
||||
execInputChildren();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -81,8 +81,9 @@ export const execInputChildren = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: Input) => {
|
||||
write(Index.INPUT_CHILDREN, input.children);
|
||||
execInputChildren();
|
||||
if (write(Index.INPUT_CHILDREN, input.children)) {
|
||||
execInputChildren();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -2,11 +2,12 @@ import {
|
||||
data,
|
||||
read,
|
||||
write,
|
||||
queue,
|
||||
readInOwner,
|
||||
setConditionalRenderer,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
runInBranch
|
||||
queueInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, get, over, open, close } from "../../utils/walks";
|
||||
|
||||
@ -50,15 +51,23 @@ type scope = {
|
||||
export const template = `<div><!></div>`;
|
||||
export const walks = open(6) + next(1) + get + over(1) + close;
|
||||
|
||||
export const execInputValue = () => {
|
||||
export const execInputVisible = () => {
|
||||
setConditionalRenderer(
|
||||
Index.CONDITIONAL,
|
||||
read(Index.INPUT_VISIBLE) ? branch0 : undefined
|
||||
);
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputBranch0);
|
||||
};
|
||||
|
||||
function execInputBranch0() {
|
||||
export const execInputValue = () => {
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execInputValueBranch0,
|
||||
Branch0Index.CLOSURE_VALUE
|
||||
);
|
||||
};
|
||||
|
||||
function execInputValueBranch0() {
|
||||
data(
|
||||
Branch0Index.TEXT,
|
||||
readInOwner<scope, Index.INPUT_VALUE>(Index.INPUT_VALUE)!.name
|
||||
@ -66,14 +75,18 @@ function execInputBranch0() {
|
||||
}
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VISIBLE, input.visible);
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VISIBLE, input.visible)) {
|
||||
execInputVisible();
|
||||
}
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
const enum Branch0Index {
|
||||
CLOSURE_VALUE = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
@ -82,6 +95,8 @@ type Branch0Scope = [Text];
|
||||
const branch0 = createRenderer(
|
||||
"<span> </span>",
|
||||
open(1) + next(1) + get + next(1) + close,
|
||||
undefined,
|
||||
() => {
|
||||
queue(execInputValueBranch0, Branch0Index.CLOSURE_VALUE);
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
queueInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, over, get, open, close } from "../../utils/walks";
|
||||
|
||||
@ -53,7 +53,12 @@ export const execInputValue = () => {
|
||||
Index.CONDITIONAL,
|
||||
read(Index.INPUT_VALUE) ? branch0 : undefined
|
||||
);
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputBranch0);
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execInputBranch0,
|
||||
Branch0Index.CLOSURE_VALUE
|
||||
);
|
||||
};
|
||||
|
||||
function execInputBranch0() {
|
||||
@ -64,13 +69,15 @@ function execInputBranch0() {
|
||||
}
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
const enum Branch0Index {
|
||||
CLOSURE_VALUE = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
@ -79,6 +86,6 @@ type Branch0Scope = [Text];
|
||||
const branch0 = createRenderer(
|
||||
"<span> </span>",
|
||||
open(1) + next(1) + get + next(1) + close,
|
||||
undefined,
|
||||
undefined, // optimization
|
||||
0
|
||||
);
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
queueInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, over, get, open, close } from "../../utils/walks";
|
||||
|
||||
@ -53,7 +53,12 @@ export const execInputValue = () => {
|
||||
Index.CONDITIONAL,
|
||||
read(Index.INPUT_VALUE) ? branch0 : undefined
|
||||
);
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputBranch0);
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execInputBranch0,
|
||||
Branch0Index.CLOSURE_VALUE
|
||||
);
|
||||
};
|
||||
|
||||
function execInputBranch0() {
|
||||
@ -64,13 +69,15 @@ function execInputBranch0() {
|
||||
}
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
const enum Branch0Index {
|
||||
CLOSURE_VALUE = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
@ -79,6 +86,6 @@ type Branch0Scope = [Text];
|
||||
const branch0 = createRenderer(
|
||||
"<span> </span>",
|
||||
open(1) + next(1) + get + next(1) + close,
|
||||
undefined,
|
||||
undefined, // optimization
|
||||
0
|
||||
);
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
queueInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, over, get, open, close } from "../../utils/walks";
|
||||
|
||||
@ -53,7 +53,12 @@ export const execInputValue = () => {
|
||||
Index.CONDITIONAL,
|
||||
read(Index.INPUT_VALUE) ? branch0 : undefined
|
||||
);
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputBranch0);
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execInputBranch0,
|
||||
Branch0Index.CLOSURE_VALUE
|
||||
);
|
||||
};
|
||||
|
||||
function execInputBranch0() {
|
||||
@ -64,13 +69,15 @@ function execInputBranch0() {
|
||||
}
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
const enum Branch0Index {
|
||||
CLOSURE_VALUE = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
@ -79,6 +86,6 @@ type Branch0Scope = [Text];
|
||||
const branch0 = createRenderer(
|
||||
"<span> </span>",
|
||||
open(1) + next(1) + get + next(1) + close,
|
||||
undefined,
|
||||
undefined, // optimization
|
||||
0
|
||||
);
|
||||
|
||||
@ -8,8 +8,9 @@ import {
|
||||
getConditionalLastNode,
|
||||
write,
|
||||
read,
|
||||
queue,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
queueInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, over, get, open, close, skip } from "../../utils/walks";
|
||||
|
||||
@ -70,19 +71,19 @@ export const template = `<div><!></div>`;
|
||||
export const walks = open(7) + next(1) + get + over(1) + close;
|
||||
|
||||
export const execInputShow = () => {
|
||||
if (
|
||||
setConditionalRenderer(
|
||||
Index.CONDITIONAL,
|
||||
read(Index.INPUT_SHOW) ? branch0 : undefined
|
||||
)
|
||||
) {
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputValue1Branch0);
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputValue2Branch0);
|
||||
}
|
||||
setConditionalRenderer(
|
||||
Index.CONDITIONAL,
|
||||
read(Index.INPUT_SHOW) ? branch0 : undefined
|
||||
);
|
||||
};
|
||||
|
||||
export const execInputValue1 = () => {
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputValue1Branch0);
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execInputValue1Branch0,
|
||||
Branch0Index.CLOSURE_VALUE1
|
||||
);
|
||||
};
|
||||
|
||||
export const execInputValue1Branch0 = () => {
|
||||
@ -90,11 +91,21 @@ export const execInputValue1Branch0 = () => {
|
||||
Branch0Index.CONDITIONAL1,
|
||||
readInOwner(Index.INPUT_VALUE1) ? branch0_0 : undefined
|
||||
);
|
||||
runInBranch(Branch0Index.CONDITIONAL1, branch0_0, execInputValue1Branch0_0);
|
||||
queueInBranch(
|
||||
Branch0Index.CONDITIONAL1,
|
||||
branch0_0,
|
||||
execInputValue1Branch0_0,
|
||||
Branch0_0Index.CLOSURE_VALUE1
|
||||
);
|
||||
};
|
||||
|
||||
export const execInputValue2 = () => {
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputValue2Branch0);
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execInputValue2Branch0,
|
||||
Branch0Index.CLOSURE_VALUE2
|
||||
);
|
||||
};
|
||||
|
||||
export const execInputValue2Branch0 = () => {
|
||||
@ -102,7 +113,12 @@ export const execInputValue2Branch0 = () => {
|
||||
Branch0Index.CONDITIONAL2,
|
||||
readInOwner(Index.INPUT_VALUE2) ? branch0_1 : undefined
|
||||
);
|
||||
runInBranch(Branch0Index.CONDITIONAL2, branch0_1, execInputValue2Branch0_1);
|
||||
queueInBranch(
|
||||
Branch0Index.CONDITIONAL2,
|
||||
branch0_1,
|
||||
execInputValue2Branch0_1,
|
||||
Branch0_1Index.CLOSURE_VALUE2
|
||||
);
|
||||
};
|
||||
|
||||
const execInputValue1Branch0_0 = () => {
|
||||
@ -122,6 +138,8 @@ export const execDynamicInput = (input: Input) => {
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
const enum Branch0Index {
|
||||
CLOSURE_VALUE1 = -2,
|
||||
CLOSURE_VALUE2 = -1,
|
||||
COMMENT1 = 0,
|
||||
CONDITIONAL1 = 0,
|
||||
COMMENT2 = 4,
|
||||
@ -138,7 +156,10 @@ type Branch0Scope = {
|
||||
const branch0 = createRenderer(
|
||||
"<!><!>",
|
||||
open(8) + get + over(1) + skip(3) + get + over(1) + close,
|
||||
undefined,
|
||||
() => {
|
||||
queue(execInputValue1Branch0, Branch0Index.CLOSURE_VALUE1);
|
||||
queue(execInputValue2Branch0, Branch0Index.CLOSURE_VALUE2);
|
||||
},
|
||||
0,
|
||||
0,
|
||||
fragmentMethods,
|
||||
@ -149,6 +170,7 @@ const branch0 = createRenderer(
|
||||
);
|
||||
|
||||
const enum Branch0_0Index {
|
||||
CLOSURE_VALUE1 = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
@ -164,6 +186,7 @@ const branch0_0 = createRenderer(
|
||||
);
|
||||
|
||||
const enum Branch0_1Index {
|
||||
CLOSURE_VALUE2 = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
|
||||
@ -30,9 +30,9 @@ inserted #comment
|
||||
removed #comment after #comment
|
||||
inserted div0/span0
|
||||
removed #comment after div0/span0
|
||||
div0/span0/#text0: " " => "Hello"
|
||||
inserted div0/span1
|
||||
removed #comment after div0/span1
|
||||
div0/span0/#text0: " " => "Hello"
|
||||
div0/span1/#text0: " " => "World"
|
||||
```
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
read,
|
||||
write,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
queueInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
import { get, next, over, open, close } from "../../utils/walks";
|
||||
|
||||
@ -51,7 +51,12 @@ export const execInputValue = () => {
|
||||
Index.CONDITIONAL,
|
||||
read(Index.INPUT_VALUE) ? branch0 : undefined
|
||||
);
|
||||
runInBranch(Index.CONDITIONAL, branch0, execInputBranch0);
|
||||
queueInBranch(
|
||||
Index.CONDITIONAL,
|
||||
branch0,
|
||||
execInputBranch0,
|
||||
Branch0Index.CLOSURE_VALUE
|
||||
);
|
||||
};
|
||||
|
||||
function execInputBranch0() {
|
||||
@ -62,13 +67,15 @@ function execInputBranch0() {
|
||||
}
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
const enum Branch0Index {
|
||||
CLOSURE_VALUE = -1,
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
|
||||
@ -41,8 +41,9 @@ export const execInputValue = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -38,8 +38,9 @@ export const execInputValue = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -34,8 +34,9 @@ export const execInputValue = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -32,8 +32,9 @@ export const execInputValue = () => {
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[number]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
execInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
execInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, undefined, 0, execDynamicInput);
|
||||
|
||||
@ -10,14 +10,15 @@ import {
|
||||
import { wait } from "../../../utils/resolve";
|
||||
import { get, next, open, close } from "../../utils/walks";
|
||||
|
||||
export const inputs = [{ value: 0 }, wait(2), { value: 1 }, wait(2)] as const;
|
||||
export const inputs = [{ value: 0 }, wait(4), { value: 1 }, wait(4)] as const;
|
||||
|
||||
const enum Index {
|
||||
DIV_TEXT = 0,
|
||||
INPUT_VALUE = 1,
|
||||
A = 2,
|
||||
B = 3,
|
||||
EFFECT_CLEANUP = 4
|
||||
CONCAT_AB = 4,
|
||||
EFFECT_CLEANUP = 5
|
||||
}
|
||||
|
||||
type scope = {
|
||||
@ -25,6 +26,7 @@ type scope = {
|
||||
[Index.INPUT_VALUE]: typeof inputs[0 | 2]["value"];
|
||||
[Index.A]: number;
|
||||
[Index.B]: number;
|
||||
[Index.CONCAT_AB]: string;
|
||||
[Index.EFFECT_CLEANUP]: () => void;
|
||||
};
|
||||
|
||||
@ -38,13 +40,30 @@ type scope = {
|
||||
export const template = `<div> </div>`;
|
||||
export const walks = open(5) + next(1) + get + next(1) + close;
|
||||
export const render = () => {
|
||||
write(Index.A, 0);
|
||||
write(Index.B, 0);
|
||||
execAB();
|
||||
execA(0);
|
||||
execB(0);
|
||||
};
|
||||
|
||||
function execA(value) {
|
||||
if (write(Index.A, value)) {
|
||||
queue(execAB, Index.CONCAT_AB);
|
||||
}
|
||||
}
|
||||
|
||||
function execB(value) {
|
||||
if (write(Index.B, value)) {
|
||||
queue(execAB, Index.CONCAT_AB);
|
||||
}
|
||||
}
|
||||
|
||||
function execAB() {
|
||||
data(Index.DIV_TEXT, "" + read(Index.A) + read(Index.B));
|
||||
execConcatAB("" + read(Index.A) + read(Index.B));
|
||||
}
|
||||
|
||||
function execConcatAB(value) {
|
||||
if (write(Index.CONCAT_AB, value)) {
|
||||
data(Index.DIV_TEXT, value);
|
||||
}
|
||||
}
|
||||
|
||||
export const hydrateInputValue = () => {
|
||||
@ -53,19 +72,16 @@ export const hydrateInputValue = () => {
|
||||
|
||||
const effectFn = () => {
|
||||
const previousValue = read<scope, Index.INPUT_VALUE>(Index.INPUT_VALUE) + 1;
|
||||
if (write(Index.A, previousValue)) {
|
||||
queue(execAB);
|
||||
}
|
||||
queue(execA, Index.A, previousValue);
|
||||
return bind(() => {
|
||||
if (write(Index.B, previousValue)) {
|
||||
queue(execAB);
|
||||
}
|
||||
queue(execB, Index.B, previousValue);
|
||||
});
|
||||
};
|
||||
|
||||
export const execDynamicInput = (input: typeof inputs[0]) => {
|
||||
write(Index.INPUT_VALUE, input.value);
|
||||
hydrateInputValue();
|
||||
if (write(Index.INPUT_VALUE, input.value)) {
|
||||
hydrateInputValue();
|
||||
}
|
||||
};
|
||||
|
||||
export default createRenderFn(template, walks, render, 0, execDynamicInput);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user