mirror of
https://github.com/marko-js/marko.git
synced 2026-02-01 16:07:13 +00:00
feat: move non-serialized internal values out of scope array and into props
This commit is contained in:
parent
d2e723b5df
commit
0bda22cd98
@ -6,9 +6,9 @@
|
||||
{
|
||||
"name": "*",
|
||||
"individual": {
|
||||
"min": 11962,
|
||||
"gzip": 5140,
|
||||
"brotli": 4628
|
||||
"min": 11615,
|
||||
"gzip": 5073,
|
||||
"brotli": 4574
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Write
|
||||
<!M^ROOT><body><!M#6 ROOT 6><button><!M#1 ROOT 7>0</button></body><!M/ROOT><script>(M$h=[]).push((b,s)=>({ROOT:["ROOT",,,,,,,,0]}),["counter",6,"ROOT",])</script>
|
||||
<!M^ROOT><body><!M#2 ROOT 2><button><!M#1 ROOT 3>0</button></body><!M/ROOT><script>(M$h=[]).push((b,s)=>({ROOT:[,,,,0]}),["counter",2,"ROOT",])</script>
|
||||
|
||||
|
||||
# Render "End"
|
||||
@ -8,13 +8,13 @@
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<!--M#6 ROOT 6-->
|
||||
<!--M#2 ROOT 2-->
|
||||
<button>
|
||||
<!--M#1 ROOT 7-->
|
||||
<!--M#1 ROOT 3-->
|
||||
0
|
||||
</button>
|
||||
<script>
|
||||
(M$h=[]).push((b,s)=>({ROOT:["ROOT",,,,,,,,0]}),["counter",6,"ROOT",])
|
||||
(M$h=[]).push((b,s)=>({ROOT:[,,,,0]}),["counter",2,"ROOT",])
|
||||
</script>
|
||||
</body>
|
||||
<!--M/ROOT-->
|
||||
@ -43,13 +43,13 @@ inserted #document/html1/body1/script2/#text0
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<!--M#6 ROOT 6-->
|
||||
<!--M#2 ROOT 2-->
|
||||
<button>
|
||||
<!--M#1 ROOT 7-->
|
||||
<!--M#1 ROOT 3-->
|
||||
0
|
||||
</button>
|
||||
<script>
|
||||
(M$h=[]).push((b,s)=>({ROOT:["ROOT",,,,,,,,0]}),["counter",6,"ROOT",])
|
||||
(M$h=[]).push((b,s)=>({ROOT:[,,,,0]}),["counter",2,"ROOT",])
|
||||
</script>
|
||||
</body>
|
||||
<!--M/ROOT-->
|
||||
@ -70,13 +70,13 @@ container.querySelector("button").click();
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<!--M#6 ROOT 6-->
|
||||
<!--M#2 ROOT 2-->
|
||||
<button>
|
||||
<!--M#1 ROOT 7-->
|
||||
<!--M#1 ROOT 3-->
|
||||
1
|
||||
</button>
|
||||
<script>
|
||||
(M$h=[]).push((b,s)=>({ROOT:["ROOT",,,,,,,,0]}),["counter",6,"ROOT",])
|
||||
(M$h=[]).push((b,s)=>({ROOT:[,,,,0]}),["counter",2,"ROOT",])
|
||||
</script>
|
||||
</body>
|
||||
<!--M/ROOT-->
|
||||
@ -97,13 +97,13 @@ container.querySelector("button").click();
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<!--M#6 ROOT 6-->
|
||||
<!--M#2 ROOT 2-->
|
||||
<button>
|
||||
<!--M#1 ROOT 7-->
|
||||
<!--M#1 ROOT 3-->
|
||||
2
|
||||
</button>
|
||||
<script>
|
||||
(M$h=[]).push((b,s)=>({ROOT:["ROOT",,,,,,,,0]}),["counter",6,"ROOT",])
|
||||
(M$h=[]).push((b,s)=>({ROOT:[,,,,0]}),["counter",2,"ROOT",])
|
||||
</script>
|
||||
</body>
|
||||
<!--M/ROOT-->
|
||||
@ -124,13 +124,13 @@ container.querySelector("button").click();
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<!--M#6 ROOT 6-->
|
||||
<!--M#2 ROOT 2-->
|
||||
<button>
|
||||
<!--M#1 ROOT 7-->
|
||||
<!--M#1 ROOT 3-->
|
||||
3
|
||||
</button>
|
||||
<script>
|
||||
(M$h=[]).push((b,s)=>({ROOT:["ROOT",,,,,,,,0]}),["counter",6,"ROOT",])
|
||||
(M$h=[]).push((b,s)=>({ROOT:[,,,,0]}),["counter",2,"ROOT",])
|
||||
</script>
|
||||
</body>
|
||||
<!--M/ROOT-->
|
||||
|
||||
@ -6,7 +6,6 @@ export default (
|
||||
currentScope: Scope,
|
||||
currentOffset: number
|
||||
) => {
|
||||
currentScope[0] = "ROOT";
|
||||
write("<body>");
|
||||
counter(_input, currentScope, currentOffset);
|
||||
write("</body>");
|
||||
@ -27,5 +26,5 @@ const counter = (
|
||||
)}${count}</button>`
|
||||
);
|
||||
writeScope(currentScope);
|
||||
writeCall("counter", currentOffset, currentScope[0]);
|
||||
writeCall("counter", currentOffset, currentScope.___id);
|
||||
};
|
||||
|
||||
@ -9,14 +9,15 @@ export type HydrateInstance = [
|
||||
];
|
||||
|
||||
export type Scope = [
|
||||
string, // ID
|
||||
Node | number | undefined, // START_NODE
|
||||
Node | number | undefined, // END_NODE
|
||||
Set<number | Scope> | undefined, // CLEANUP
|
||||
Scope | undefined, // OWNER_SCOPE
|
||||
number | undefined, // OWNER_OFFSET
|
||||
...unknown[]
|
||||
] & {
|
||||
___id: string;
|
||||
___startNode: Node | number | undefined;
|
||||
___endNode: Node | number | undefined;
|
||||
___cleanup: Set<number | Scope> | undefined;
|
||||
} & {
|
||||
___insertBefore: (
|
||||
this: Scope,
|
||||
parent: Node & ParentNode,
|
||||
@ -30,13 +31,9 @@ export type Scope = [
|
||||
};
|
||||
|
||||
export const enum ScopeOffsets {
|
||||
ID = 0,
|
||||
START_NODE = 1,
|
||||
END_NODE = 2,
|
||||
CLEANUP = 3,
|
||||
OWNER_SCOPE = 4,
|
||||
OWNER_OFFSET = 5,
|
||||
BEGIN_DATA = 6,
|
||||
OWNER_SCOPE = 0,
|
||||
OWNER_OFFSET = 1,
|
||||
BEGIN_DATA = 2,
|
||||
}
|
||||
|
||||
export const enum HydrateSymbols {
|
||||
|
||||
@ -46,7 +46,7 @@ export function queueInBranch(
|
||||
|
||||
export function getConditionalFirstNode(
|
||||
this: Scope,
|
||||
conditionalIndex: number = this[ScopeOffsets.START_NODE] as number,
|
||||
conditionalIndex: number = this.___startNode as number,
|
||||
last?: boolean
|
||||
) {
|
||||
const scope = this[
|
||||
@ -62,11 +62,7 @@ export function getConditionalFirstNode(
|
||||
}
|
||||
|
||||
export function getConditionalLastNode(this: Scope) {
|
||||
return getConditionalFirstNode.call(
|
||||
this,
|
||||
this[ScopeOffsets.END_NODE] as number,
|
||||
true
|
||||
);
|
||||
return getConditionalFirstNode.call(this, this.___endNode as number, true);
|
||||
}
|
||||
|
||||
export function setConditionalRenderer(
|
||||
@ -179,7 +175,7 @@ export function queueForEach(
|
||||
|
||||
export function getLoopFirstNode(
|
||||
this: Scope,
|
||||
loopIndex: number = this[ScopeOffsets.START_NODE] as number,
|
||||
loopIndex: number = this.___startNode as number,
|
||||
last?: boolean
|
||||
) {
|
||||
const scopes = this[
|
||||
@ -195,11 +191,7 @@ export function getLoopFirstNode(
|
||||
}
|
||||
|
||||
export function getLoopLastNode(this: Scope) {
|
||||
return getLoopFirstNode.call(
|
||||
this,
|
||||
this[ScopeOffsets.END_NODE] as number,
|
||||
true
|
||||
);
|
||||
return getLoopFirstNode.call(this, this.___endNode as number, true);
|
||||
}
|
||||
|
||||
export function setLoopOf<T>(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { Renderer } from "./renderer";
|
||||
import { Scope, ScopeOffsets } from "../common/types";
|
||||
import { Scope } from "../common/types";
|
||||
import { onDestroy, read, write } from "./scope";
|
||||
import { withQueueNext } from "./queue";
|
||||
|
||||
@ -25,10 +25,10 @@ export type DOMMethods = {
|
||||
|
||||
export const staticNodeMethods: DOMMethods = {
|
||||
___insertBefore(parent, nextSibling) {
|
||||
parent.insertBefore(this[ScopeOffsets.START_NODE] as Node, nextSibling);
|
||||
parent.insertBefore(this.___startNode as Node, nextSibling);
|
||||
},
|
||||
___remove() {
|
||||
(this[ScopeOffsets.START_NODE] as ChildNode).remove();
|
||||
(this.___startNode as ChildNode).remove();
|
||||
},
|
||||
___getParentNode() {
|
||||
return this.___getFirstNode().parentNode!;
|
||||
@ -37,27 +37,27 @@ export const staticNodeMethods: DOMMethods = {
|
||||
return this.___getLastNode().nextSibling;
|
||||
},
|
||||
___getFirstNode() {
|
||||
return this[ScopeOffsets.START_NODE] as ChildNode;
|
||||
return this.___startNode as ChildNode;
|
||||
},
|
||||
___getLastNode() {
|
||||
return this[ScopeOffsets.END_NODE] as ChildNode;
|
||||
return this.___endNode as ChildNode;
|
||||
},
|
||||
};
|
||||
|
||||
// export const staticNodePropertiesDef = {
|
||||
// ___insertBefore: {
|
||||
// value(parent, nextSibling) {
|
||||
// parent.insertBefore(this[ScopeOffsets.START_NODE] as Node, nextSibling);
|
||||
// parent.insertBefore(this.___startNode as Node, nextSibling);
|
||||
// }
|
||||
// },
|
||||
// ___remove: {
|
||||
// value() {
|
||||
// (this[ScopeOffsets.START_NODE] as ChildNode).remove();
|
||||
// (this.___startNode as ChildNode).remove();
|
||||
// }
|
||||
// },
|
||||
// ___parentNode: {
|
||||
// get() {
|
||||
// return this[ScopeOffsets.START_NODE].parentNode;
|
||||
// return this.___startNode.parentNode;
|
||||
// },
|
||||
// },
|
||||
// ___afterNode: {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Scope, ScopeOffsets, HydrateSymbols } from "../common/types";
|
||||
import { Scope, HydrateSymbols } from "../common/types";
|
||||
import { bind, runWithScope } from "./scope";
|
||||
|
||||
type HydrateFn = () => void;
|
||||
@ -66,8 +66,10 @@ export function init(runtimeId = "M" /* [a-zA-Z0-9]+ */) {
|
||||
if (storedScope !== scope) {
|
||||
if (storedScope) {
|
||||
Object.assign(scope, storedScope);
|
||||
} else {
|
||||
scope.___id = scopeId;
|
||||
scopeLookup[scopeId] = scope;
|
||||
}
|
||||
scopeLookup[scopeId] = scope;
|
||||
if (currentScope === storedScope) {
|
||||
currentScope = scope;
|
||||
}
|
||||
@ -83,7 +85,7 @@ export function init(runtimeId = "M" /* [a-zA-Z0-9]+ */) {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
if ("MARKO_DEBUG") {
|
||||
const [offset, scopeId, index] = data.split(" ");
|
||||
if (scopeId !== currentScope[ScopeOffsets.ID]) {
|
||||
if (scopeId !== currentScope.___id) {
|
||||
throw new Error("INVALID_MARKER_NESTING: " + nodeValue);
|
||||
}
|
||||
if (parseInt(offset) + currentOffset !== parseInt(index)) {
|
||||
@ -96,22 +98,23 @@ export function init(runtimeId = "M" /* [a-zA-Z0-9]+ */) {
|
||||
currentScope[(currentOffset += offset)] = node;
|
||||
} else if (token === HydrateSymbols.SCOPE_START) {
|
||||
if (currentScope) {
|
||||
stack.push(currentScope[ScopeOffsets.ID] as string, currentOffset);
|
||||
stack.push(currentScope.___id, currentOffset);
|
||||
}
|
||||
currentScope = scopeLookup[data]!;
|
||||
currentOffset = 0;
|
||||
if (!currentScope) {
|
||||
scopeLookup[data] = currentScope = [data] as unknown as Scope;
|
||||
scopeLookup[data] = currentScope = [] as unknown as Scope;
|
||||
currentScope.___id = data;
|
||||
}
|
||||
currentScope[ScopeOffsets.START_NODE] = currentNode;
|
||||
currentScope.___startNode = currentNode;
|
||||
} else if (token === HydrateSymbols.SCOPE_END) {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
if ("MARKO_DEBUG") {
|
||||
if (data !== currentScope[ScopeOffsets.ID]) {
|
||||
if (data !== currentScope.___id) {
|
||||
throw new Error("SCOPE_END_MISMATCH: " + nodeValue);
|
||||
}
|
||||
}
|
||||
currentScope[ScopeOffsets.END_NODE] = currentNode;
|
||||
currentScope.___endNode = currentNode;
|
||||
currentOffset = stack.pop() as number;
|
||||
currentScope = scopeLookup[stack.pop() as string]!;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Scope, ScopeOffsets } from "../common/types";
|
||||
import { Scope } from "../common/types";
|
||||
import {
|
||||
runWithScope,
|
||||
currentScope,
|
||||
@ -129,8 +129,8 @@ function findQueueIndex(scope: Scope, sortValue: number) {
|
||||
function compareQueue(index: number, scope: Scope, sortValue: number) {
|
||||
return (
|
||||
compare(
|
||||
(queuedFns[index + QueueOffsets.SCOPE] as Scope)[ScopeOffsets.ID],
|
||||
scope[ScopeOffsets.ID]
|
||||
(queuedFns[index + QueueOffsets.SCOPE] as Scope).___id,
|
||||
scope.___id
|
||||
) || (queuedFns[index + QueueOffsets.SORT_VALUE] as number) - sortValue
|
||||
);
|
||||
}
|
||||
|
||||
@ -36,21 +36,21 @@ type RenderResult<I extends Input> = Node & {
|
||||
|
||||
export function initRenderer(renderer: Renderer, scope: Scope) {
|
||||
const dom = renderer.___clone();
|
||||
scope[ScopeOffsets.START_NODE] =
|
||||
scope.___startNode =
|
||||
dom.nodeType === NodeType.DocumentFragment ? dom.firstChild! : dom;
|
||||
scope[ScopeOffsets.END_NODE] =
|
||||
scope.___endNode =
|
||||
dom.nodeType === NodeType.DocumentFragment ? dom.lastChild! : dom;
|
||||
walk(scope[ScopeOffsets.START_NODE] as Node, renderer.___walks!, scope);
|
||||
walk(scope.___startNode as Node, renderer.___walks!, scope);
|
||||
if (renderer.___render) {
|
||||
runWithScope(renderer.___render, ScopeOffsets.BEGIN_DATA, scope);
|
||||
}
|
||||
if (renderer.___dynamicStartNodeMethod) {
|
||||
scope.___getFirstNode = renderer.___dynamicStartNodeMethod;
|
||||
scope[ScopeOffsets.START_NODE] = renderer.___dynamicStartNodeOffset!;
|
||||
scope.___startNode = renderer.___dynamicStartNodeOffset!;
|
||||
}
|
||||
if (renderer.___dynamicEndNodeMethod) {
|
||||
scope.___getLastNode = renderer.___dynamicEndNodeMethod;
|
||||
scope[ScopeOffsets.END_NODE] = renderer.___dynamicEndNodeOffset!;
|
||||
scope.___endNode = renderer.___dynamicEndNodeOffset!;
|
||||
}
|
||||
return dom;
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ let scopeId = 0;
|
||||
|
||||
export function createScope(size: number, methods: DOMMethods): Scope {
|
||||
const scope = new Array(size) as Scope;
|
||||
scope[ScopeOffsets.ID] = "" + scopeId++;
|
||||
scope.___id = "" + scopeId++;
|
||||
scope[ScopeOffsets.OWNER_SCOPE] = currentScope;
|
||||
scope[ScopeOffsets.OWNER_OFFSET] = currentOffset;
|
||||
return Object.assign(scope, methods);
|
||||
@ -17,8 +17,7 @@ export function createScope(size: number, methods: DOMMethods): Scope {
|
||||
|
||||
const emptyScope = createScope(0, staticNodeMethods);
|
||||
export function getEmptyScope(marker?: Comment) {
|
||||
emptyScope[ScopeOffsets.START_NODE] = emptyScope[ScopeOffsets.END_NODE] =
|
||||
marker;
|
||||
emptyScope.___startNode = emptyScope.___endNode = marker;
|
||||
return emptyScope;
|
||||
}
|
||||
|
||||
@ -106,9 +105,9 @@ export function runInChild(fn: () => void, offset: number) {
|
||||
}
|
||||
|
||||
export function destroyScope(scope: Scope) {
|
||||
scope[ScopeOffsets.OWNER_SCOPE]?.[ScopeOffsets.CLEANUP]?.delete(scope);
|
||||
scope[ScopeOffsets.OWNER_SCOPE]?.___cleanup?.delete(scope);
|
||||
|
||||
const cleanup = scope[ScopeOffsets.CLEANUP];
|
||||
const cleanup = scope.___cleanup;
|
||||
if (cleanup) {
|
||||
for (const instance of cleanup) {
|
||||
if (typeof instance === "number") {
|
||||
@ -124,11 +123,11 @@ export function destroyScope(scope: Scope) {
|
||||
export function onDestroy(localIndex: number) {
|
||||
const parentScope = currentScope[ScopeOffsets.OWNER_SCOPE];
|
||||
if (parentScope) {
|
||||
(parentScope[ScopeOffsets.CLEANUP] =
|
||||
parentScope[ScopeOffsets.CLEANUP] || new Set()).add(currentScope);
|
||||
(parentScope.___cleanup = parentScope.___cleanup || new Set()).add(
|
||||
currentScope
|
||||
);
|
||||
}
|
||||
(currentScope[ScopeOffsets.CLEANUP] =
|
||||
currentScope[ScopeOffsets.CLEANUP] || new Set()).add(
|
||||
(currentScope.___cleanup = currentScope.___cleanup || new Set()).add(
|
||||
currentOffset + localIndex
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,7 +43,9 @@ export function createRenderer(renderer: Renderer, hydrateRoot?: boolean) {
|
||||
try {
|
||||
let renderedPromises: typeof $_promises;
|
||||
try {
|
||||
const scope = hydrateRoot ? (["ROOT"] as any as Scope) : nullScope;
|
||||
const scope = hydrateRoot
|
||||
? (Object.assign([], { ___id: "ROOT" }) as any as Scope)
|
||||
: nullScope;
|
||||
hydrateRoot && write(markScopeStart(scope));
|
||||
renderer(input, scope, ScopeOffsets.BEGIN_DATA);
|
||||
hydrateRoot && write(markScopeEnd(scope));
|
||||
@ -74,7 +76,7 @@ export function writeCall(fnId: string, offset: number, scopeId: string) {
|
||||
|
||||
export function writeScope(scope: Scope) {
|
||||
$_buffer!.scopes = $_buffer!.scopes || {};
|
||||
$_buffer!.scopes[scope[ScopeOffsets.ID]] = scope;
|
||||
$_buffer!.scopes[scope.___id] = scope;
|
||||
}
|
||||
|
||||
export function fork<T>(
|
||||
@ -254,25 +256,19 @@ export function markScopeOffset(index: number, scope: Scope) {
|
||||
lastIndex.set(scope, index);
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
if ("MARKO_DEBUG") {
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_OFFSET}${offset} ${
|
||||
scope[ScopeOffsets.ID]
|
||||
} ${index}>`;
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_OFFSET}${offset} ${scope.___id} ${index}>`;
|
||||
}
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_OFFSET}${offset}>`;
|
||||
}
|
||||
|
||||
export function markScopeStart(scope: Scope) {
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_START}${
|
||||
scope[ScopeOffsets.ID]
|
||||
}>`;
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_START}${scope.___id}>`;
|
||||
}
|
||||
|
||||
export function markScopeEnd(scope: Scope) {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
if ("MARKO_DEBUG") {
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_END}${
|
||||
scope[ScopeOffsets.ID]
|
||||
}>`;
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_END}${scope.___id}>`;
|
||||
}
|
||||
return `<!${runtimeId}${HydrateSymbols.SCOPE_END}>`;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user