mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
feat: flatten conditionals and loops into parent scope
This commit is contained in:
parent
96fbeaf260
commit
f97a8262b9
@ -6,9 +6,9 @@
|
||||
{
|
||||
"name": "*",
|
||||
"individual": {
|
||||
"min": 10252,
|
||||
"gzip": 4379,
|
||||
"brotli": 3991
|
||||
"min": 9959,
|
||||
"gzip": 4316,
|
||||
"brotli": 3947
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -5,74 +5,94 @@ import {
|
||||
Scope,
|
||||
createScope,
|
||||
getEmptyScope,
|
||||
set,
|
||||
destroyScope,
|
||||
read,
|
||||
runWithScope
|
||||
runWithScope,
|
||||
write
|
||||
} from "./scope";
|
||||
import { NodeType } from "./dom";
|
||||
|
||||
export type Conditional = (
|
||||
| {
|
||||
scope: Scope;
|
||||
renderer: Renderer;
|
||||
}
|
||||
| {
|
||||
scope: undefined;
|
||||
renderer: undefined;
|
||||
}
|
||||
) & {
|
||||
___referenceNode: Comment | Element;
|
||||
___context: typeof Context;
|
||||
___getFirstNode: () => Node;
|
||||
___getLastNode: () => Node;
|
||||
};
|
||||
|
||||
export function conditional(referenceNode: Comment | Element): Conditional {
|
||||
return {
|
||||
scope: undefined,
|
||||
renderer: undefined,
|
||||
___referenceNode: referenceNode,
|
||||
___context: Context,
|
||||
___getFirstNode: getFirstNodeConditional,
|
||||
___getLastNode: getLastNodeConditional
|
||||
};
|
||||
const enum ConditionalIndex {
|
||||
REFERENCE_NODE = 0,
|
||||
SCOPE = 1,
|
||||
RENDERER = 2,
|
||||
CONTEXT = 3
|
||||
}
|
||||
|
||||
type Conditional = {
|
||||
[ConditionalIndex.REFERENCE_NODE]: Element | Comment;
|
||||
[ConditionalIndex.SCOPE]: Scope;
|
||||
[ConditionalIndex.RENDERER]: Renderer;
|
||||
[ConditionalIndex.CONTEXT]: typeof Context;
|
||||
};
|
||||
|
||||
export function runInBranch(
|
||||
conditionalIndex: number,
|
||||
branch: Renderer,
|
||||
fn: () => void
|
||||
) {
|
||||
const cond = read(conditionalIndex) as Conditional;
|
||||
if (cond.renderer === branch) {
|
||||
runWithScope(fn, 0, cond.scope!);
|
||||
if (read(conditionalIndex + ConditionalIndex.RENDERER) === branch) {
|
||||
runWithScope(
|
||||
fn,
|
||||
0,
|
||||
read(conditionalIndex + ConditionalIndex.SCOPE) as Scope
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function getConditionalFirstNode(
|
||||
this: Scope,
|
||||
conditionalIndex: number = this.___startNode as number,
|
||||
last?: boolean
|
||||
) {
|
||||
const scope = this[conditionalIndex + ConditionalIndex.SCOPE] as Scope;
|
||||
return scope
|
||||
? scope[last ? "___getLastNode" : "___getFirstNode"]()
|
||||
: (this[conditionalIndex + ConditionalIndex.REFERENCE_NODE] as Comment);
|
||||
}
|
||||
|
||||
export function getConditionalLastNode(this: Scope) {
|
||||
return getConditionalFirstNode.call(this, this.___endNode as number, true);
|
||||
}
|
||||
|
||||
export function setConditionalRenderer(
|
||||
conditionalIndex: number,
|
||||
newRenderer: Renderer | undefined
|
||||
) {
|
||||
const conditonal = read(conditionalIndex) as Conditional;
|
||||
if (conditonal.renderer !== (conditonal.renderer = newRenderer)) {
|
||||
if (read(conditionalIndex + ConditionalIndex.RENDERER) !== newRenderer) {
|
||||
write(conditionalIndex + ConditionalIndex.RENDERER, newRenderer);
|
||||
let newScope: Scope;
|
||||
let prevScope = conditonal.scope!;
|
||||
let prevScope = read<Conditional, ConditionalIndex.SCOPE>(
|
||||
conditionalIndex + ConditionalIndex.SCOPE
|
||||
);
|
||||
|
||||
if (newRenderer) {
|
||||
setContext(conditonal.___context);
|
||||
newScope = conditonal.scope = createScope(
|
||||
newRenderer.___size,
|
||||
newRenderer.___domMethods!
|
||||
setContext(
|
||||
read(conditionalIndex + ConditionalIndex.CONTEXT) as typeof Context
|
||||
);
|
||||
write(
|
||||
conditionalIndex + ConditionalIndex.SCOPE,
|
||||
(newScope = createScope(
|
||||
newRenderer.___size,
|
||||
newRenderer.___domMethods!
|
||||
))
|
||||
);
|
||||
initRenderer(newRenderer, newScope);
|
||||
prevScope =
|
||||
prevScope || getEmptyScope(conditonal.___referenceNode as Comment);
|
||||
prevScope ||
|
||||
getEmptyScope(
|
||||
read<Conditional, ConditionalIndex.REFERENCE_NODE>(
|
||||
conditionalIndex + ConditionalIndex.REFERENCE_NODE
|
||||
) as Comment
|
||||
);
|
||||
setContext(null);
|
||||
} else {
|
||||
newScope = getEmptyScope(conditonal.___referenceNode as Comment);
|
||||
conditonal.scope = undefined;
|
||||
newScope = getEmptyScope(
|
||||
read<Conditional, ConditionalIndex.REFERENCE_NODE>(
|
||||
conditionalIndex + ConditionalIndex.REFERENCE_NODE
|
||||
) as Comment
|
||||
);
|
||||
write(conditionalIndex + ConditionalIndex.SCOPE, undefined);
|
||||
}
|
||||
|
||||
newScope.___insertBefore(
|
||||
@ -87,128 +107,118 @@ export function setConditionalRendererOnlyChild(
|
||||
conditionalIndex: number,
|
||||
newRenderer: Renderer | undefined
|
||||
) {
|
||||
const conditonal = read(conditionalIndex) as Conditional;
|
||||
if (conditonal.renderer !== (conditonal.renderer = newRenderer)) {
|
||||
(conditonal.___referenceNode as Element).textContent = "";
|
||||
if (read(conditionalIndex + ConditionalIndex.RENDERER) !== newRenderer) {
|
||||
write(conditionalIndex + ConditionalIndex.RENDERER, newRenderer);
|
||||
const referenceNode = read<Conditional, ConditionalIndex.REFERENCE_NODE>(
|
||||
conditionalIndex + ConditionalIndex.REFERENCE_NODE
|
||||
) as Element;
|
||||
referenceNode.textContent = "";
|
||||
|
||||
if (newRenderer) {
|
||||
setContext(conditonal.___context);
|
||||
const newScope = (conditonal.scope = createScope(
|
||||
newRenderer.___size,
|
||||
newRenderer.___domMethods!
|
||||
));
|
||||
setContext(
|
||||
read(conditionalIndex + ConditionalIndex.CONTEXT) as typeof Context
|
||||
);
|
||||
let newScope: Scope;
|
||||
write(
|
||||
conditionalIndex + ConditionalIndex.SCOPE,
|
||||
(newScope = createScope(
|
||||
newRenderer.___size,
|
||||
newRenderer.___domMethods!
|
||||
))
|
||||
);
|
||||
initRenderer(newRenderer, newScope);
|
||||
newScope.___insertBefore(conditonal.___referenceNode as Element, null);
|
||||
newScope.___insertBefore(referenceNode, null);
|
||||
setContext(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstNodeConditional(this: Conditional) {
|
||||
return this.scope
|
||||
? this.scope.___getFirstNode()
|
||||
: (this.___referenceNode as Comment);
|
||||
}
|
||||
|
||||
function getLastNodeConditional(this: Conditional) {
|
||||
return this.scope
|
||||
? this.scope.___getLastNode()
|
||||
: (this.___referenceNode as Comment);
|
||||
}
|
||||
|
||||
const emptyMarkerMap = new Map();
|
||||
const emptyMarkerArray = [getEmptyScope()];
|
||||
emptyMarkerMap.set(Symbol("empty"), getEmptyScope());
|
||||
const emptyMap = new Map();
|
||||
const emptyArray = [];
|
||||
|
||||
export type Loop = {
|
||||
___scopeMap: Map<unknown, Scope>;
|
||||
___scopeArray: Scope[];
|
||||
___referenceNode: Comment | Element;
|
||||
___referenceIsMarker: boolean;
|
||||
___renderer: Renderer;
|
||||
___keyFn: undefined | ((item: unknown, index: number) => unknown);
|
||||
___context: typeof Context;
|
||||
___getFirstNode: () => Node;
|
||||
___getLastNode: () => Node;
|
||||
[Symbol.iterator]: () => IterableIterator<Scope>;
|
||||
};
|
||||
|
||||
export function loop(
|
||||
referenceNode: Comment | Element,
|
||||
renderer: Renderer,
|
||||
keyFn: (item: unknown) => unknown
|
||||
): Loop {
|
||||
const referenceIsMarker = referenceNode.nodeType === NodeType.Comment;
|
||||
return {
|
||||
___scopeMap: referenceIsMarker ? emptyMarkerMap : emptyMap,
|
||||
___scopeArray: referenceIsMarker ? emptyMarkerArray : emptyArray,
|
||||
___referenceNode: referenceNode,
|
||||
___referenceIsMarker: referenceIsMarker,
|
||||
___renderer: renderer,
|
||||
___keyFn: keyFn,
|
||||
___context: Context,
|
||||
___getFirstNode: getFirstNodeLoop,
|
||||
___getLastNode: getLastNodeLoop,
|
||||
[Symbol.iterator]: loopIterator
|
||||
};
|
||||
const enum LoopIndex {
|
||||
REFERENCE_NODE = 0,
|
||||
SCOPE_MAP = 1,
|
||||
SCOPE_ARRAY = 2,
|
||||
CONTEXT = 3
|
||||
}
|
||||
|
||||
type Loop = {
|
||||
[LoopIndex.REFERENCE_NODE]: Element | Comment;
|
||||
[LoopIndex.SCOPE_MAP]: Map<unknown, Scope>;
|
||||
[LoopIndex.SCOPE_ARRAY]: Scope[];
|
||||
[LoopIndex.CONTEXT]: typeof Context;
|
||||
};
|
||||
|
||||
export function runForEach(loopIndex: number, fn: () => void) {
|
||||
for (const scope of (read(loopIndex) as Loop).___scopeArray) {
|
||||
for (const scope of read<Loop, LoopIndex.SCOPE_ARRAY>(
|
||||
loopIndex + LoopIndex.SCOPE_ARRAY
|
||||
)) {
|
||||
runWithScope(fn, 0, scope);
|
||||
}
|
||||
}
|
||||
|
||||
function loopIterator(this: Loop) {
|
||||
return (this.___scopeArray === emptyMarkerArray
|
||||
? emptyArray
|
||||
: this.___scopeArray
|
||||
).values();
|
||||
export function getLoopFirstNode(
|
||||
this: Scope,
|
||||
loopIndex: number = this.___startNode as number,
|
||||
last?: boolean
|
||||
) {
|
||||
const scopes = this[loopIndex + LoopIndex.SCOPE_ARRAY] as Scope[];
|
||||
return scopes === emptyMarkerArray
|
||||
? (this[loopIndex + LoopIndex.REFERENCE_NODE] as Comment)
|
||||
: scopes[last ? scopes.length - 1 : 0][
|
||||
last ? "___getLastNode" : "___getFirstNode"
|
||||
]();
|
||||
}
|
||||
|
||||
function getFirstNodeLoop(this: Loop) {
|
||||
return this.___scopeArray[0].___getFirstNode();
|
||||
export function getLoopLastNode(this: Scope) {
|
||||
return getLoopFirstNode.call(this, this.___endNode as number, true);
|
||||
}
|
||||
|
||||
function getLastNodeLoop(this: Loop) {
|
||||
return this.___scopeArray[this.___scopeArray.length - 1].___getLastNode();
|
||||
}
|
||||
|
||||
export function setLoopOf(loopIndex: number, newValues: unknown[]) {
|
||||
const loop = read(loopIndex) as Loop;
|
||||
export function setLoopOf(
|
||||
loopIndex: number,
|
||||
newValues: unknown[],
|
||||
renderer: Renderer,
|
||||
keyFn?: (item: unknown) => unknown
|
||||
) {
|
||||
let newMap: Map<unknown, Scope>;
|
||||
let newArray: Scope[];
|
||||
const len = newValues.length;
|
||||
const oldMap = loop.___scopeMap;
|
||||
const oldArray = loop.___scopeArray;
|
||||
const referenceNode = read<Loop, LoopIndex.REFERENCE_NODE>(
|
||||
loopIndex + LoopIndex.REFERENCE_NODE
|
||||
);
|
||||
const referenceIsMarker = referenceNode.nodeType === 8; /* Comment */
|
||||
const oldMap =
|
||||
read<Loop, LoopIndex.SCOPE_MAP>(loopIndex + LoopIndex.SCOPE_MAP) ||
|
||||
(referenceIsMarker ? emptyMarkerMap : emptyMap);
|
||||
const oldArray =
|
||||
read<Loop, LoopIndex.SCOPE_ARRAY>(loopIndex + LoopIndex.SCOPE_ARRAY) ||
|
||||
(referenceIsMarker ? emptyMarkerArray : emptyArray);
|
||||
let inserts = 0;
|
||||
let moves = 0;
|
||||
const referenceIsMarker = loop.___referenceIsMarker;
|
||||
let afterReference: Node | null;
|
||||
let parentNode: Node & ParentNode;
|
||||
|
||||
if (len > 0) {
|
||||
newMap = new Map();
|
||||
setContext(loop.___context);
|
||||
setContext(read(loopIndex + LoopIndex.CONTEXT) as typeof Context);
|
||||
for (let index = 0; index < len; index++) {
|
||||
const item = newValues[index];
|
||||
const key = loop.___keyFn ? loop.___keyFn(item, index) : "" + index;
|
||||
const key = keyFn ? keyFn(item) : index;
|
||||
let childScope = oldMap.get(key);
|
||||
if (!childScope) {
|
||||
childScope = createScope(
|
||||
loop.___renderer.___size,
|
||||
loop.___renderer.___domMethods!
|
||||
);
|
||||
childScope = createScope(renderer.___size, renderer.___domMethods!);
|
||||
childScope[0] = item;
|
||||
childScope[1] = index;
|
||||
initRenderer(loop.___renderer, childScope);
|
||||
initRenderer(renderer, childScope);
|
||||
inserts++;
|
||||
} else {
|
||||
if (childScope[1] !== index) moves++;
|
||||
set(childScope, 0, item);
|
||||
set(childScope, 1, index);
|
||||
write(0, item, childScope, 0);
|
||||
write(1, index, childScope, 0);
|
||||
}
|
||||
newMap.set(key, childScope);
|
||||
}
|
||||
@ -218,16 +228,16 @@ export function setLoopOf(loopIndex: number, newValues: unknown[]) {
|
||||
if (referenceIsMarker) {
|
||||
newMap = emptyMarkerMap;
|
||||
newArray = emptyMarkerArray;
|
||||
getEmptyScope(loop.___referenceNode as Comment);
|
||||
getEmptyScope(referenceNode as Comment);
|
||||
} else {
|
||||
if (loop.___renderer.___hasUserEffects) {
|
||||
if (renderer.___hasUserEffects) {
|
||||
for (let i = 0; i < oldArray.length; i++) {
|
||||
destroyScope(oldArray[i]);
|
||||
}
|
||||
}
|
||||
loop.___referenceNode.textContent = "";
|
||||
loop.___scopeMap = emptyMap;
|
||||
loop.___scopeArray = emptyArray;
|
||||
referenceNode.textContent = "";
|
||||
write(loopIndex + LoopIndex.SCOPE_MAP, emptyMap);
|
||||
write(loopIndex + LoopIndex.SCOPE_ARRAY, emptyArray);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -235,28 +245,29 @@ export function setLoopOf(loopIndex: number, newValues: unknown[]) {
|
||||
if (inserts || moves || len !== oldArray.length) {
|
||||
if (referenceIsMarker) {
|
||||
if (oldMap === emptyMarkerMap) {
|
||||
getEmptyScope(loop.___referenceNode as Comment);
|
||||
getEmptyScope(referenceNode as Comment);
|
||||
}
|
||||
const oldLastChild = oldArray[oldArray.length - 1];
|
||||
afterReference = oldLastChild.___getAfterNode();
|
||||
parentNode = oldLastChild.___getParentNode();
|
||||
} else {
|
||||
afterReference = null;
|
||||
parentNode = loop.___referenceNode as Element;
|
||||
parentNode = referenceNode as Element;
|
||||
}
|
||||
|
||||
reconcile(parentNode, oldArray, newArray!, afterReference);
|
||||
}
|
||||
|
||||
loop.___scopeArray = newArray!;
|
||||
loop.___scopeMap = newMap!;
|
||||
write(loopIndex + LoopIndex.SCOPE_MAP, newMap);
|
||||
write(loopIndex + LoopIndex.SCOPE_ARRAY, newArray);
|
||||
}
|
||||
|
||||
export function setLoopFromTo(
|
||||
loopIndex: number,
|
||||
from: number,
|
||||
to: number,
|
||||
step: number
|
||||
step: number,
|
||||
renderer: Renderer
|
||||
) {
|
||||
const range: number[] = [];
|
||||
|
||||
@ -264,9 +275,21 @@ export function setLoopFromTo(
|
||||
range.push(i);
|
||||
}
|
||||
|
||||
setLoopOf(loopIndex, range);
|
||||
setLoopOf(loopIndex, range, renderer, keyFromTo);
|
||||
}
|
||||
|
||||
export function setLoopIn(loopIndex: number, object: Record<string, unknown>) {
|
||||
setLoopOf(loopIndex, Object.entries(object));
|
||||
function keyFromTo(item: unknown) {
|
||||
return item;
|
||||
}
|
||||
|
||||
export function setLoopIn(
|
||||
loopIndex: number,
|
||||
object: Record<string, unknown>,
|
||||
renderer: Renderer
|
||||
) {
|
||||
setLoopOf(loopIndex, Object.entries(object), renderer, keyIn);
|
||||
}
|
||||
|
||||
function keyIn(item: [string, unknown]) {
|
||||
return item[0];
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Conditional, Loop } from "./control-flow";
|
||||
import { Renderer } from "./renderer";
|
||||
import { onDestroy, Scope, bind, read, write } from "./scope";
|
||||
import { onDestroy, Scope, read, write } from "./scope";
|
||||
|
||||
export const enum NodeType {
|
||||
Element = 1,
|
||||
@ -66,7 +65,7 @@ export const staticNodeMethods = {
|
||||
// }
|
||||
// };
|
||||
|
||||
export const staticFragmentMethods = {
|
||||
export const fragmentMethods = {
|
||||
...staticNodeMethods,
|
||||
___insertBefore(parent, nextSibling) {
|
||||
let current: Node = this.___getFirstNode();
|
||||
@ -88,30 +87,6 @@ export const staticFragmentMethods = {
|
||||
}
|
||||
} as DOMMethods;
|
||||
|
||||
export const dynamicStartFragmentMethods = {
|
||||
...staticFragmentMethods,
|
||||
___getFirstNode() {
|
||||
return (this.___startNode as Conditional | Loop).___getFirstNode();
|
||||
}
|
||||
} as DOMMethods;
|
||||
|
||||
export const dynamicEndFragmentMethods = {
|
||||
...staticFragmentMethods,
|
||||
___getLastNode() {
|
||||
return (this.___endNode as Conditional | Loop).___getLastNode();
|
||||
}
|
||||
} as DOMMethods;
|
||||
|
||||
export const dynamicFragmentMethods = {
|
||||
...staticFragmentMethods,
|
||||
___getFirstNode() {
|
||||
return (this.___startNode as Conditional | Loop).___getFirstNode();
|
||||
},
|
||||
___getLastNode() {
|
||||
return (this.___endNode as Conditional | Loop).___getLastNode();
|
||||
}
|
||||
} as DOMMethods;
|
||||
|
||||
export function isDocumentFragment(node: Node): node is DocumentFragment {
|
||||
return node.nodeType === NodeType.DocumentFragment;
|
||||
}
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
export {
|
||||
Conditional,
|
||||
Loop,
|
||||
conditional,
|
||||
setConditionalRenderer,
|
||||
setConditionalRendererOnlyChild,
|
||||
getConditionalFirstNode,
|
||||
getConditionalLastNode,
|
||||
runInBranch,
|
||||
loop,
|
||||
setLoopOf,
|
||||
setLoopFromTo,
|
||||
setLoopIn,
|
||||
getLoopFirstNode,
|
||||
getLoopLastNode,
|
||||
runForEach
|
||||
} from "./control-flow";
|
||||
|
||||
@ -21,8 +21,7 @@ export {
|
||||
props,
|
||||
dynamicTag,
|
||||
staticNodeMethods,
|
||||
staticFragmentMethods,
|
||||
dynamicFragmentMethods,
|
||||
fragmentMethods,
|
||||
userEffect
|
||||
} from "./dom";
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Conditional, Loop } from "./control-flow";
|
||||
import { DOMMethods } from "./dom";
|
||||
import { DOMMethods, staticNodeMethods } from "./dom";
|
||||
import { createScope, Scope, cleanScopes, runWithScope } from "./scope";
|
||||
import { WalkCodes, detachedWalk } from "./walker";
|
||||
|
||||
@ -19,7 +18,9 @@ export type Renderer = {
|
||||
___hasUserEffects: 0 | 1;
|
||||
___sourceNode: Node | undefined;
|
||||
___domMethods: DOMMethods | undefined;
|
||||
___dynamicStartNodeMethod: ((this: Scope) => Node & ChildNode) | undefined;
|
||||
___dynamicStartNodeOffset: number | undefined;
|
||||
___dynamicEndNodeMethod: ((this: Scope) => Node & ChildNode) | undefined;
|
||||
___dynamicEndNodeOffset: number | undefined;
|
||||
};
|
||||
|
||||
@ -47,15 +48,13 @@ export function initRenderer(renderer: Renderer, scope: Scope) {
|
||||
scope.___endNode =
|
||||
dom.nodeType === NodeType.DocumentFragment ? dom.lastChild! : dom;
|
||||
detachedWalk(scope.___startNode, renderer, scope);
|
||||
if (renderer.___dynamicStartNodeOffset !== undefined) {
|
||||
scope.___startNode = scope[renderer.___dynamicStartNodeOffset] as
|
||||
| Conditional
|
||||
| Loop;
|
||||
if (renderer.___dynamicStartNodeMethod) {
|
||||
scope.___getFirstNode = renderer.___dynamicStartNodeMethod;
|
||||
scope.___startNode = renderer.___dynamicStartNodeOffset!;
|
||||
}
|
||||
if (renderer.___dynamicEndNodeOffset !== undefined) {
|
||||
scope.___endNode = scope[renderer.___dynamicEndNodeOffset] as
|
||||
| Conditional
|
||||
| Loop;
|
||||
if (renderer.___dynamicEndNodeMethod) {
|
||||
scope.___getLastNode = renderer.___dynamicEndNodeMethod;
|
||||
scope.___endNode = renderer.___dynamicEndNodeOffset!;
|
||||
}
|
||||
return dom;
|
||||
}
|
||||
@ -66,9 +65,11 @@ export function createRenderFn<I extends Input>(
|
||||
hydrate?: HydrateFn,
|
||||
size?: number,
|
||||
dynamicInput?: DynamicInputFn<I>,
|
||||
domMethods?: DOMMethods,
|
||||
hasUserEffects?: 0 | 1,
|
||||
domMethods?: DOMMethods,
|
||||
dynamicStartNodeMethod?: (this: Scope) => Node & ChildNode,
|
||||
dynamicStartNodeOffset?: number,
|
||||
dynamicEndNodeMethod?: (this: Scope) => Node & ChildNode,
|
||||
dynamicEndNodeOffset?: number
|
||||
) {
|
||||
const renderer = createRenderer(
|
||||
@ -76,9 +77,11 @@ export function createRenderFn<I extends Input>(
|
||||
walks,
|
||||
hydrate,
|
||||
size,
|
||||
domMethods,
|
||||
hasUserEffects,
|
||||
domMethods,
|
||||
dynamicStartNodeMethod,
|
||||
dynamicStartNodeOffset,
|
||||
dynamicEndNodeMethod,
|
||||
dynamicEndNodeOffset
|
||||
);
|
||||
return (input: I): RenderResult => {
|
||||
@ -104,10 +107,12 @@ export function createRenderer<H extends HydrateFn>(
|
||||
template: string,
|
||||
walks?: string,
|
||||
hydrate?: H,
|
||||
size?: number,
|
||||
domMethods?: DOMMethods,
|
||||
hasUserEffects?: 0 | 1,
|
||||
size = 0,
|
||||
hasUserEffects: 0 | 1 = 0,
|
||||
domMethods: DOMMethods = staticNodeMethods,
|
||||
dynamicStartNodeMethod?: (this: Scope) => Node & ChildNode,
|
||||
dynamicStartNodeOffset?: number,
|
||||
dynamicEndNodeMethod?: (this: Scope) => Node & ChildNode,
|
||||
dynamicEndNodeOffset?: number
|
||||
): Renderer {
|
||||
return {
|
||||
@ -115,11 +120,13 @@ export function createRenderer<H extends HydrateFn>(
|
||||
___walks: walks,
|
||||
___hydrate: hydrate,
|
||||
___clone: _clone,
|
||||
___size: size || 0,
|
||||
___hasUserEffects: hasUserEffects || 0,
|
||||
___size: size,
|
||||
___hasUserEffects: hasUserEffects,
|
||||
___sourceNode: undefined,
|
||||
___domMethods: domMethods,
|
||||
___dynamicStartNodeMethod: dynamicStartNodeMethod,
|
||||
___dynamicStartNodeOffset: dynamicStartNodeOffset,
|
||||
___dynamicEndNodeMethod: dynamicEndNodeMethod,
|
||||
___dynamicEndNodeOffset: dynamicEndNodeOffset
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { Conditional, Loop } from "./control-flow";
|
||||
import { DOMMethods, staticNodeMethods } from "./dom";
|
||||
import { setQueued } from "./queue";
|
||||
|
||||
@ -12,8 +11,8 @@ export type Scope = unknown[] &
|
||||
DOMMethods & {
|
||||
___parentScope: Scope | undefined;
|
||||
___parentOffset: number | undefined;
|
||||
___startNode: Conditional | Loop | Node | undefined;
|
||||
___endNode: Conditional | Loop | Node | undefined;
|
||||
___startNode: Node | number | undefined;
|
||||
___endNode: Node | number | undefined;
|
||||
___dirty: Record<number, true> | true | undefined;
|
||||
___cleanup: Set<number | Scope> | undefined;
|
||||
};
|
||||
|
||||
@ -50,7 +50,7 @@ export function walkMany(scope: Scope, offset: number, count: number) {
|
||||
export let walk = walkNormal;
|
||||
// TODO: in some cases (including hydrate) we may get an existing node
|
||||
// ideally we wouldn't create the newNode unless it was actually needed
|
||||
function walkNormal<T extends Node>(newNode?: T) {
|
||||
function walkNormal() {
|
||||
if ("MARKO_DEBUG" && !currentWalks) {
|
||||
throw new Error("Missing encoded walk string");
|
||||
}
|
||||
@ -83,7 +83,7 @@ function walkNormal<T extends Node>(newNode?: T) {
|
||||
if ("MARKO_DEBUG" && extendedWalk === undefined) {
|
||||
throw new Error("Extended walk was not enabled");
|
||||
}
|
||||
return extendedWalk(value, newNode);
|
||||
return extendedWalk(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,8 +93,8 @@ export function enableExtendedWalk() {
|
||||
}
|
||||
|
||||
let extendedWalk: typeof actualExtendedWalk;
|
||||
function actualExtendedWalk<T extends Node>(value: number, newNode?: T) {
|
||||
newNode = newNode || ((document.createTextNode("") as unknown) as T);
|
||||
function actualExtendedWalk(value: number) {
|
||||
const newNode = document.createTextNode("");
|
||||
|
||||
const current = walker.currentNode;
|
||||
if (value === WalkCodes.Inside) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import {
|
||||
on,
|
||||
walk,
|
||||
conditional,
|
||||
Conditional,
|
||||
register,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
@ -10,7 +8,6 @@ import {
|
||||
data,
|
||||
queue,
|
||||
ensureDelegated,
|
||||
staticNodeMethods,
|
||||
write,
|
||||
read,
|
||||
bind,
|
||||
@ -29,18 +26,18 @@ export const inputs = [{}, click] as const;
|
||||
|
||||
const enum Index {
|
||||
BUTTON = 0,
|
||||
COMMENT = 1,
|
||||
SHOW = 2,
|
||||
MESSAGE = 3,
|
||||
CONDITIONAL = 4
|
||||
SHOW = 1,
|
||||
MESSAGE = 2,
|
||||
COMMENT = 3,
|
||||
CONDITIONAL = 3
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.BUTTON]: HTMLButtonElement;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.SHOW]: boolean;
|
||||
[Index.MESSAGE]: string;
|
||||
[Index.CONDITIONAL]: Conditional;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.CONDITIONAL]: Comment;
|
||||
};
|
||||
|
||||
// <let/show = true/>
|
||||
@ -63,7 +60,7 @@ export const hydrate = register("", () => {
|
||||
queue(execShowMessage);
|
||||
})
|
||||
);
|
||||
write(Index.CONDITIONAL, conditional(walk() as Comment));
|
||||
write(Index.COMMENT, walk());
|
||||
|
||||
execShowMessage();
|
||||
});
|
||||
@ -100,6 +97,5 @@ const branch0 = createRenderer(
|
||||
() => {
|
||||
write(Branch0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
loop,
|
||||
setLoopFromTo,
|
||||
Loop,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
isDirty,
|
||||
staticNodeMethods,
|
||||
write,
|
||||
read,
|
||||
runForEach
|
||||
@ -35,19 +32,19 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
DIV = 0,
|
||||
INPUT_FROM = 1,
|
||||
INPUT_TO = 2,
|
||||
INPUT_STEP = 3,
|
||||
LOOP = 4
|
||||
INPUT_FROM = 0,
|
||||
INPUT_TO = 1,
|
||||
INPUT_STEP = 2,
|
||||
DIV = 3,
|
||||
LOOP = 3
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.INPUT_FROM]: Input["from"];
|
||||
[Index.INPUT_TO]: Input["to"];
|
||||
[Index.INPUT_STEP]: Input["step"];
|
||||
[Index.LOOP]: Loop;
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.LOOP]: HTMLDivElement;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -59,10 +56,7 @@ type scope = {
|
||||
export const template = `<div></div>`;
|
||||
export const walks = get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(
|
||||
Index.LOOP,
|
||||
loop(walk() as Comment, iter0, i => i)
|
||||
);
|
||||
write(Index.DIV, walk());
|
||||
};
|
||||
|
||||
export const execInputFromToStep = () => {
|
||||
@ -70,7 +64,8 @@ export const execInputFromToStep = () => {
|
||||
Index.LOOP,
|
||||
read<scope, Index.INPUT_FROM>(Index.INPUT_FROM),
|
||||
read<scope, Index.INPUT_TO>(Index.INPUT_TO),
|
||||
read<scope, Index.INPUT_STEP>(Index.INPUT_STEP)
|
||||
read<scope, Index.INPUT_STEP>(Index.INPUT_STEP),
|
||||
iter0
|
||||
);
|
||||
runForEach(Index.LOOP, iter0_execItem);
|
||||
};
|
||||
@ -99,8 +94,7 @@ const iter0 = createRenderer(
|
||||
() => {
|
||||
write(Iter0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const iter0_execItem = () => {
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
loop,
|
||||
read,
|
||||
write,
|
||||
setLoopIn,
|
||||
Loop,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
isDirty,
|
||||
staticNodeMethods,
|
||||
runForEach
|
||||
} from "../../../../src/dom/index";
|
||||
import { over, get, next } from "../../utils/walks";
|
||||
@ -37,15 +34,15 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
DIV = 0,
|
||||
INPUT_CHILDREN = 1,
|
||||
LOOP = 2
|
||||
INPUT_CHILDREN = 0,
|
||||
DIV = 1,
|
||||
LOOP = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.INPUT_CHILDREN]: Input["children"];
|
||||
[Index.LOOP]: Loop;
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.LOOP]: HTMLDivElement;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -57,16 +54,14 @@ type scope = {
|
||||
export const template = `<div></div>`;
|
||||
export const walks = get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(
|
||||
Index.LOOP,
|
||||
loop(walk() as HTMLDivElement, iter0, item => item[0])
|
||||
);
|
||||
write(Index.DIV, walk());
|
||||
};
|
||||
|
||||
export const execInputChildren = () => {
|
||||
setLoopIn(
|
||||
Index.LOOP,
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN)
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN),
|
||||
iter0
|
||||
);
|
||||
runForEach(Index.LOOP, iter0_execItem);
|
||||
};
|
||||
@ -103,8 +98,7 @@ const iter0 = createRenderer(
|
||||
() => {
|
||||
write(Iter0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const iter0_execItem = () => {
|
||||
|
||||
@ -1,16 +1,13 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
loop,
|
||||
read,
|
||||
write,
|
||||
setLoopOf,
|
||||
Loop,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
isDirty,
|
||||
runForEach,
|
||||
staticNodeMethods
|
||||
runForEach
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, over, get } from "../../utils/walks";
|
||||
|
||||
@ -55,15 +52,15 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
DIV = 0,
|
||||
INPUT_CHILDREN = 1,
|
||||
LOOP = 2
|
||||
INPUT_CHILDREN = 0,
|
||||
DIV = 1,
|
||||
LOOP = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.INPUT_CHILDREN]: Input["children"];
|
||||
[Index.LOOP]: Loop;
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.LOOP]: HTMLDivElement;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -75,20 +72,15 @@ type scope = {
|
||||
export const template = `<div></div>`;
|
||||
export const walks = get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(
|
||||
Index.LOOP,
|
||||
loop(
|
||||
walk() as HTMLDivElement,
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
)
|
||||
);
|
||||
write(Index.DIV, walk());
|
||||
};
|
||||
|
||||
export const execInputChildren = () => {
|
||||
setLoopOf(
|
||||
Index.LOOP,
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN)
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN),
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
);
|
||||
runForEach(Index.LOOP, iter0_execItem);
|
||||
};
|
||||
@ -122,8 +114,7 @@ const iter0 = createRenderer(
|
||||
() => {
|
||||
write(Iter0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const iter0_execItem = () => {
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
loop,
|
||||
read,
|
||||
write,
|
||||
setLoopOf,
|
||||
Loop,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
isDirty,
|
||||
runForEach
|
||||
} from "../../../../src/dom/index";
|
||||
@ -55,15 +52,15 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
DIV = 0,
|
||||
INPUT_CHILDREN = 1,
|
||||
LOOP = 2
|
||||
INPUT_CHILDREN = 0,
|
||||
DIV = 1,
|
||||
LOOP = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.INPUT_CHILDREN]: Input["children"];
|
||||
[Index.LOOP]: Loop;
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.LOOP]: HTMLDivElement;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -75,20 +72,15 @@ type scope = {
|
||||
export const template = `<div></div>`;
|
||||
export const walks = get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(
|
||||
Index.LOOP,
|
||||
loop(
|
||||
walk() as HTMLDivElement,
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
)
|
||||
);
|
||||
write(Index.DIV, walk());
|
||||
};
|
||||
|
||||
export const execInputChildren = () => {
|
||||
setLoopOf(
|
||||
Index.LOOP,
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN)
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN),
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
);
|
||||
runForEach(Index.LOOP, iter0_execItem);
|
||||
};
|
||||
@ -122,8 +114,7 @@ const iter0 = createRenderer(
|
||||
() => {
|
||||
write(Iter0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const iter0_execItem = () => {
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
loop,
|
||||
read,
|
||||
write,
|
||||
setLoopOf,
|
||||
Loop,
|
||||
isDirty,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
runForEach
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, over, get } from "../../utils/walks";
|
||||
@ -55,15 +52,15 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
COMMENT = 0,
|
||||
INPUT_CHILDREN = 1,
|
||||
LOOP = 2
|
||||
INPUT_CHILDREN = 0,
|
||||
COMMENT = 1,
|
||||
LOOP = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.INPUT_CHILDREN]: Input["children"];
|
||||
[Index.LOOP]: Loop;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.LOOP]: Comment;
|
||||
};
|
||||
|
||||
// <for|child| of=input.children by(c) { return c.id }>
|
||||
@ -73,20 +70,15 @@ type scope = {
|
||||
export const template = `<!>`;
|
||||
export const walks = get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(
|
||||
Index.LOOP,
|
||||
loop(
|
||||
walk() as Comment,
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
)
|
||||
);
|
||||
write(Index.COMMENT, walk());
|
||||
};
|
||||
|
||||
export const execInputChildren = () => {
|
||||
setLoopOf(
|
||||
Index.LOOP,
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN)
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN),
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
);
|
||||
runForEach(Index.LOOP, iter0_execItem);
|
||||
};
|
||||
@ -120,8 +112,7 @@ const iter0 = createRenderer(
|
||||
() => {
|
||||
write(Iter0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const iter0_execItem = () => {
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
loop,
|
||||
read,
|
||||
write,
|
||||
setLoopOf,
|
||||
Loop,
|
||||
isDirty,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
runForEach
|
||||
} from "../../../../src/dom/index";
|
||||
import { get, next } from "../../utils/walks";
|
||||
@ -60,15 +57,15 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
DIV = 0,
|
||||
INPUT_CHILDREN = 1,
|
||||
LOOP = 2
|
||||
INPUT_CHILDREN = 0,
|
||||
DIV = 1,
|
||||
LOOP = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.INPUT_CHILDREN]: Input["children"];
|
||||
[Index.LOOP]: Loop;
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.LOOP]: HTMLDivElement;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -80,20 +77,15 @@ type scope = {
|
||||
export const template = `<div></div>`;
|
||||
export const walks = get + next(1);
|
||||
export const hydrate = () => {
|
||||
write(
|
||||
Index.LOOP,
|
||||
loop(
|
||||
walk() as HTMLDivElement,
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
)
|
||||
);
|
||||
write(Index.DIV, walk());
|
||||
};
|
||||
|
||||
export const execInputChildren = () => {
|
||||
setLoopOf(
|
||||
Index.LOOP,
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN)
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN),
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
);
|
||||
runForEach(Index.LOOP, iter0_execItem);
|
||||
};
|
||||
@ -127,8 +119,7 @@ const iter0 = createRenderer(
|
||||
() => {
|
||||
write(Iter0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const iter0_execItem = () => {
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
loop,
|
||||
read,
|
||||
write,
|
||||
isDirty,
|
||||
setLoopOf,
|
||||
Loop,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
runForEach
|
||||
} from "../../../../src/dom/index";
|
||||
import { get, next } from "../../utils/walks";
|
||||
@ -56,15 +53,15 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
DIV = 0,
|
||||
INPUT_CHILDREN = 1,
|
||||
LOOP = 2
|
||||
INPUT_CHILDREN = 0,
|
||||
DIV = 1,
|
||||
LOOP = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.INPUT_CHILDREN]: Input["children"];
|
||||
[Index.LOOP]: Loop;
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.LOOP]: HTMLDivElement;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -76,20 +73,15 @@ type scope = {
|
||||
export const template = `<div></div>`;
|
||||
export const walks = get + next(1);
|
||||
export const hydrate = () => {
|
||||
write(
|
||||
Index.LOOP,
|
||||
loop(
|
||||
walk() as HTMLDivElement,
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
)
|
||||
);
|
||||
write(Index.DIV, walk());
|
||||
};
|
||||
|
||||
export const execInputChildren = () => {
|
||||
setLoopOf(
|
||||
Index.LOOP,
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN)
|
||||
read<scope, Index.INPUT_CHILDREN>(Index.INPUT_CHILDREN),
|
||||
iter0,
|
||||
i => "" + (i as Input["children"][number]).id
|
||||
);
|
||||
runForEach(Index.LOOP, iter0_execItem);
|
||||
};
|
||||
@ -123,8 +115,7 @@ const iter0 = createRenderer(
|
||||
() => {
|
||||
write(Iter0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const iter0_execItem = () => {
|
||||
|
||||
@ -4,12 +4,9 @@ import {
|
||||
read,
|
||||
write,
|
||||
readInOwner,
|
||||
conditional,
|
||||
setConditionalRenderer,
|
||||
Conditional,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
runInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
import { next, get, over } from "../../utils/walks";
|
||||
@ -32,17 +29,17 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
COMMENT = 0,
|
||||
INPUT_VISIBLE = 1,
|
||||
INPUT_VALUE = 2,
|
||||
CONDITIONAL = 3
|
||||
INPUT_VISIBLE = 0,
|
||||
INPUT_VALUE = 1,
|
||||
COMMENT = 2,
|
||||
CONDITIONAL = 2
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.INPUT_VISIBLE]: Input["visible"];
|
||||
[Index.INPUT_VALUE]: Input["value"];
|
||||
[Index.CONDITIONAL]: Conditional;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.CONDITIONAL]: Comment;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -54,7 +51,7 @@ type scope = {
|
||||
export const template = `<div><!></div>`;
|
||||
export const walks = next(1) + get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(Index.CONDITIONAL, conditional(walk() as Comment));
|
||||
write(Index.COMMENT, walk());
|
||||
};
|
||||
|
||||
export const execInputValue = () => {
|
||||
@ -92,6 +89,5 @@ const branch0 = createRenderer(
|
||||
() => {
|
||||
write(Branch0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
conditional,
|
||||
setConditionalRenderer,
|
||||
Conditional,
|
||||
write,
|
||||
read,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
@ -30,15 +27,15 @@ export const inputs = [
|
||||
];
|
||||
|
||||
const enum Index {
|
||||
COMMENT = 0,
|
||||
INPUT_VALUE = 1,
|
||||
CONDITIONAL = 2
|
||||
INPUT_VALUE = 0,
|
||||
COMMENT = 1,
|
||||
CONDITIONAL = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.INPUT_VALUE]: typeof inputs[number]["value"];
|
||||
[Index.CONDITIONAL]: Conditional;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.CONDITIONAL]: Comment;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -52,7 +49,7 @@ type scope = {
|
||||
export const template = `<div><!><span></span><span></span></div>`;
|
||||
export const walks = next(1) + get + over(3);
|
||||
export const hydrate = () => {
|
||||
write(Index.CONDITIONAL, conditional(walk() as Comment));
|
||||
write(Index.COMMENT, walk());
|
||||
};
|
||||
|
||||
export const execInputValue = () => {
|
||||
@ -89,6 +86,5 @@ const branch0 = createRenderer(
|
||||
() => {
|
||||
write(Branch0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
conditional,
|
||||
setConditionalRenderer,
|
||||
Conditional,
|
||||
read,
|
||||
write,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
@ -30,15 +27,15 @@ export const inputs = [
|
||||
];
|
||||
|
||||
const enum Index {
|
||||
COMMENT = 0,
|
||||
INPUT_VALUE = 1,
|
||||
CONDITIONAL = 2
|
||||
INPUT_VALUE = 0,
|
||||
COMMENT = 1,
|
||||
CONDITIONAL = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.INPUT_VALUE]: typeof inputs[number]["value"];
|
||||
[Index.CONDITIONAL]: Conditional;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.CONDITIONAL]: Comment;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -52,7 +49,7 @@ type scope = {
|
||||
export const template = `<div><span></span><span></span><!></div>`;
|
||||
export const walks = next(3) + get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(Index.CONDITIONAL, conditional(walk() as Comment));
|
||||
write(Index.CONDITIONAL, walk());
|
||||
};
|
||||
|
||||
export const execInputValue = () => {
|
||||
@ -89,6 +86,5 @@ const branch0 = createRenderer(
|
||||
() => {
|
||||
write(Branch0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
conditional,
|
||||
setConditionalRenderer,
|
||||
Conditional,
|
||||
read,
|
||||
write,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
readInOwner,
|
||||
runInBranch
|
||||
} from "../../../../src/dom/index";
|
||||
@ -30,15 +27,15 @@ export const inputs = [
|
||||
];
|
||||
|
||||
const enum Index {
|
||||
COMMENT = 0,
|
||||
INPUT_VALUE = 1,
|
||||
CONDITIONAL = 2
|
||||
INPUT_VALUE = 0,
|
||||
COMMENT = 1,
|
||||
CONDITIONAL = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.INPUT_VALUE]: typeof inputs[number]["value"];
|
||||
[Index.CONDITIONAL]: Conditional;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.CONDITIONAL]: Comment;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -52,7 +49,7 @@ type scope = {
|
||||
export const template = `<div><span></span><!><span></span></div>`;
|
||||
export const walks = next(2) + get + over(2);
|
||||
export const hydrate = () => {
|
||||
write(Index.CONDITIONAL, conditional(walk() as Comment));
|
||||
write(Index.COMMENT, walk());
|
||||
};
|
||||
|
||||
export const execInputValue = () => {
|
||||
@ -89,6 +86,5 @@ const branch0 = createRenderer(
|
||||
() => {
|
||||
write(Branch0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
conditional,
|
||||
setConditionalRenderer,
|
||||
Conditional,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
dynamicFragmentMethods,
|
||||
fragmentMethods,
|
||||
getConditionalFirstNode,
|
||||
getConditionalLastNode,
|
||||
write,
|
||||
isDirty,
|
||||
read,
|
||||
@ -48,17 +47,19 @@ export const inputs = [
|
||||
type Input = typeof inputs[number];
|
||||
|
||||
const enum Index {
|
||||
INPUT_SHOW = 1,
|
||||
INPUT_VALUE1 = 2,
|
||||
INPUT_VALUE2 = 3,
|
||||
CONDITIONAL = 4
|
||||
INPUT_SHOW = 0,
|
||||
INPUT_VALUE1 = 1,
|
||||
INPUT_VALUE2 = 2,
|
||||
COMMENT = 3,
|
||||
CONDITIONAL = 3
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.INPUT_SHOW]: Input["show"];
|
||||
[Index.INPUT_VALUE1]: Input["value1"];
|
||||
[Index.INPUT_VALUE2]: Input["value2"];
|
||||
[Index.CONDITIONAL]: Conditional;
|
||||
[Index.COMMENT]: Comment;
|
||||
[Index.CONDITIONAL]: Comment;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -71,7 +72,7 @@ type scope = {
|
||||
export const template = `<div><!></div>`;
|
||||
export const walks = next(1) + get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(Index.CONDITIONAL, conditional(walk() as Comment));
|
||||
write(Index.COMMENT, walk());
|
||||
};
|
||||
|
||||
export const execInputShowValue1Value2 = () => {
|
||||
@ -87,17 +88,17 @@ export const execInputShowValue1Value2 = () => {
|
||||
const execInputShowValue1Value2Branch0 = () => {
|
||||
if (isDirtyInOwner(Index.INPUT_SHOW) || isDirtyInOwner(Index.INPUT_VALUE1)) {
|
||||
setConditionalRenderer(
|
||||
Branch0Index.COND1,
|
||||
Branch0Index.CONDITIONAL1,
|
||||
readInOwner(Index.INPUT_VALUE1) ? branch0_0 : undefined
|
||||
);
|
||||
runInBranch(Branch0Index.COND1, branch0_0, execInputValue1Branch0_0);
|
||||
runInBranch(Branch0Index.CONDITIONAL1, branch0_0, execInputValue1Branch0_0);
|
||||
}
|
||||
if (isDirtyInOwner(Index.INPUT_SHOW) || isDirtyInOwner(Index.INPUT_VALUE2)) {
|
||||
setConditionalRenderer(
|
||||
Branch0Index.COND2,
|
||||
Branch0Index.CONDITIONAL2,
|
||||
readInOwner(Index.INPUT_VALUE2) ? branch0_1 : undefined
|
||||
);
|
||||
runInBranch(Branch0Index.COND2, branch0_1, execInputValue2Branch0_1);
|
||||
runInBranch(Branch0Index.CONDITIONAL2, branch0_1, execInputValue2Branch0_1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -119,31 +120,42 @@ export const execDynamicInput = (input: Input) => {
|
||||
export default createRenderFn(template, walks, hydrate, 0, execDynamicInput);
|
||||
|
||||
const enum Branch0Index {
|
||||
COND1 = 0,
|
||||
COND2 = 1
|
||||
COMMENT1 = 0,
|
||||
CONDITIONAL1 = 0,
|
||||
COMMENT2 = 4,
|
||||
CONDITIONAL2 = 4
|
||||
}
|
||||
|
||||
type Branch0Scope = [Conditional, Conditional];
|
||||
type Branch0Scope = {
|
||||
[Branch0Index.COMMENT1]: Comment;
|
||||
[Branch0Index.CONDITIONAL1]: Comment;
|
||||
[Branch0Index.COMMENT2]: Comment;
|
||||
[Branch0Index.CONDITIONAL2]: Comment;
|
||||
};
|
||||
|
||||
const branch0 = createRenderer(
|
||||
"<!><!>",
|
||||
get + over(1) + get + over(1),
|
||||
() => {
|
||||
write(Branch0Index.COND1, conditional(walk() as Comment));
|
||||
write(Branch0Index.COND2, conditional(walk() as Comment));
|
||||
write(Branch0Index.COMMENT1, walk());
|
||||
write(Branch0Index.COMMENT2, walk());
|
||||
},
|
||||
0,
|
||||
dynamicFragmentMethods,
|
||||
0,
|
||||
fragmentMethods,
|
||||
getConditionalFirstNode,
|
||||
0,
|
||||
1
|
||||
getConditionalLastNode,
|
||||
4
|
||||
);
|
||||
|
||||
const enum Branch0_0Index {
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
type Branch0_0Scope = [Text];
|
||||
type Branch0_0Scope = {
|
||||
[Branch0_0Index.TEXT]: Text;
|
||||
};
|
||||
|
||||
const branch0_0 = createRenderer(
|
||||
"<span> </span>",
|
||||
@ -151,15 +163,16 @@ const branch0_0 = createRenderer(
|
||||
() => {
|
||||
write(Branch0_0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
const enum Branch0_1Index {
|
||||
TEXT = 0
|
||||
}
|
||||
|
||||
type Branch0_1Scope = [Text];
|
||||
type Branch0_1Scope = {
|
||||
[Branch0_1Index.TEXT]: Text;
|
||||
};
|
||||
|
||||
// OPTIMIZATION: these two branches have the same renderer arguments
|
||||
// so they could share the same renderer instance
|
||||
@ -169,6 +182,5 @@ const branch0_1 = createRenderer(
|
||||
() => {
|
||||
write(Branch0_1Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
import {
|
||||
walk,
|
||||
data,
|
||||
conditional,
|
||||
setConditionalRendererOnlyChild,
|
||||
Conditional,
|
||||
createRenderer,
|
||||
createRenderFn,
|
||||
staticNodeMethods,
|
||||
read,
|
||||
write,
|
||||
readInOwner,
|
||||
@ -30,15 +27,15 @@ export const inputs = [
|
||||
];
|
||||
|
||||
const enum Index {
|
||||
DIV = 0,
|
||||
INPUT_VALUE = 1,
|
||||
CONDITIONAL = 2
|
||||
INPUT_VALUE = 0,
|
||||
DIV = 1,
|
||||
CONDITIONAL = 1
|
||||
}
|
||||
|
||||
type scope = {
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.INPUT_VALUE]: typeof inputs[number]["value"];
|
||||
[Index.CONDITIONAL]: Conditional;
|
||||
[Index.DIV]: HTMLDivElement;
|
||||
[Index.CONDITIONAL]: HTMLDivElement;
|
||||
};
|
||||
|
||||
// <div>
|
||||
@ -50,7 +47,7 @@ type scope = {
|
||||
export const template = `<div></div>`;
|
||||
export const walks = get + over(1);
|
||||
export const hydrate = () => {
|
||||
write(Index.CONDITIONAL, conditional(walk() as HTMLDivElement));
|
||||
write(Index.DIV, walk());
|
||||
};
|
||||
|
||||
export const execInputValue = () => {
|
||||
@ -87,6 +84,5 @@ const branch0 = createRenderer(
|
||||
() => {
|
||||
write(Branch0Index.TEXT, walk());
|
||||
},
|
||||
0,
|
||||
staticNodeMethods
|
||||
0
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user