mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
fix: simplify resume by walking after scopes are deserialized
This commit is contained in:
parent
c508712dc2
commit
1ce6f1b9a3
28
.sizes.json
28
.sizes.json
@ -7,8 +7,8 @@
|
||||
{
|
||||
"name": "*",
|
||||
"total": {
|
||||
"min": 19557,
|
||||
"brotli": 7455
|
||||
"min": 19435,
|
||||
"brotli": 7443
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -19,11 +19,11 @@
|
||||
},
|
||||
"runtime": {
|
||||
"min": 4050,
|
||||
"brotli": 1826
|
||||
"brotli": 1827
|
||||
},
|
||||
"total": {
|
||||
"min": 4224,
|
||||
"brotli": 1971
|
||||
"brotli": 1972
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -33,12 +33,12 @@
|
||||
"brotli": 92
|
||||
},
|
||||
"runtime": {
|
||||
"min": 2171,
|
||||
"brotli": 1136
|
||||
"min": 2125,
|
||||
"brotli": 1116
|
||||
},
|
||||
"total": {
|
||||
"min": 2267,
|
||||
"brotli": 1228
|
||||
"min": 2221,
|
||||
"brotli": 1208
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -49,11 +49,11 @@
|
||||
},
|
||||
"runtime": {
|
||||
"min": 7047,
|
||||
"brotli": 3062
|
||||
"brotli": 3060
|
||||
},
|
||||
"total": {
|
||||
"min": 7804,
|
||||
"brotli": 3478
|
||||
"brotli": 3476
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -63,12 +63,12 @@
|
||||
"brotli": 112
|
||||
},
|
||||
"runtime": {
|
||||
"min": 2323,
|
||||
"brotli": 1175
|
||||
"min": 2277,
|
||||
"brotli": 1160
|
||||
},
|
||||
"total": {
|
||||
"min": 2453,
|
||||
"brotli": 1287
|
||||
"min": 2407,
|
||||
"brotli": 1272
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
167
.sizes/dom.js
167
.sizes/dom.js
@ -1,4 +1,4 @@
|
||||
// size: 19557 (min) 7455 (brotli)
|
||||
// size: 19435 (min) 7443 (brotli)
|
||||
var empty = [],
|
||||
rest = Symbol();
|
||||
function attrTag(attrs) {
|
||||
@ -76,7 +76,7 @@ function normalizeDynamicRenderer(value) {
|
||||
if (value) {
|
||||
if ("string" == typeof value) return value;
|
||||
let normalized = value.content || value.default || value;
|
||||
if ("f" in normalized) return normalized;
|
||||
if ("e" in normalized) return normalized;
|
||||
}
|
||||
}
|
||||
var decodeAccessor = (num) =>
|
||||
@ -207,7 +207,6 @@ function init(runtimeId = "M") {
|
||||
lastEffect,
|
||||
visits,
|
||||
resumes,
|
||||
scopeId,
|
||||
visit,
|
||||
visitText,
|
||||
visitType,
|
||||
@ -219,22 +218,24 @@ function init(runtimeId = "M") {
|
||||
walk2 = render.w,
|
||||
scopeLookup = (render.s = {}),
|
||||
serializeContext = { _: registeredValues },
|
||||
branches =
|
||||
visitBranches =
|
||||
branchesEnabled &&
|
||||
(() => {
|
||||
let branchParents = new Map(),
|
||||
branchStarts = [],
|
||||
let branchStarts = [],
|
||||
orphanBranches = [],
|
||||
endBranch = (singleNode) => {
|
||||
let branchId,
|
||||
branch,
|
||||
childBranch,
|
||||
parent = visit.parentNode,
|
||||
endedBranches = [],
|
||||
startVisit = visit,
|
||||
i = orphanBranches.length,
|
||||
claimed = 0;
|
||||
i = orphanBranches.length;
|
||||
for (; (branchId = +lastToken); ) {
|
||||
if (
|
||||
((branch = scopeLookup[branchId] ||= {}), singleNode)
|
||||
(endedBranches.push((branch = scopeLookup[branchId])),
|
||||
(branch.G = branch),
|
||||
singleNode)
|
||||
) {
|
||||
for (
|
||||
;
|
||||
@ -255,39 +256,27 @@ function init(runtimeId = "M") {
|
||||
visit.previousSibling === startVisit
|
||||
? startVisit
|
||||
: parent.insertBefore(new Text(), visit)));
|
||||
for (; i-- && orphanBranches[i] > branchId; )
|
||||
(branchParents.set(orphanBranches[i], branchId),
|
||||
claimed++);
|
||||
(orphanBranches.push(branchId),
|
||||
branchParents.set(branchId, 0),
|
||||
nextToken());
|
||||
for (; i && orphanBranches[--i].M > branchId; )
|
||||
(((childBranch = orphanBranches.pop()).N = branch),
|
||||
(branch.E ||= new Set()).add(childBranch));
|
||||
nextToken();
|
||||
}
|
||||
orphanBranches.splice(i, claimed);
|
||||
orphanBranches.push(...endedBranches);
|
||||
};
|
||||
return {
|
||||
n() {
|
||||
"[" === visitType
|
||||
? (endBranch(), branchStarts.push(visit))
|
||||
: ((visitScope["J" + nextToken()] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)(
|
||||
(visitScope[lastToken] =
|
||||
")" === visitType || "}" === visitType
|
||||
? visit.parentNode
|
||||
: visit),
|
||||
)),
|
||||
nextToken(),
|
||||
endBranch("]" !== visitType && ")" !== visitType));
|
||||
},
|
||||
c(scope) {
|
||||
((scope.G =
|
||||
scopeLookup[scope.H || branchParents.get(scopeId)]),
|
||||
branchParents.has(scopeId) &&
|
||||
(scope.G &&
|
||||
((scope.N = scope.G).E ||= new Set()).add(scope),
|
||||
(scope.G = scope)));
|
||||
},
|
||||
return () => {
|
||||
"[" === visitType
|
||||
? (lastToken && endBranch(), branchStarts.push(visit))
|
||||
: ((visitScope["J" + nextToken()] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)(
|
||||
(visitScope[lastToken] =
|
||||
")" === visitType || "}" === visitType
|
||||
? visit.parentNode
|
||||
: visit),
|
||||
)),
|
||||
nextToken(),
|
||||
endBranch("]" !== visitType && ")" !== visitType));
|
||||
};
|
||||
})(),
|
||||
lastScopeId = 0,
|
||||
@ -301,41 +290,37 @@ function init(runtimeId = "M") {
|
||||
return (
|
||||
(render.w = () => {
|
||||
try {
|
||||
for (visit of (walk2(), (isResuming = 1), (visits = render.v)))
|
||||
((lastTokenIndex = render.i.length),
|
||||
(visitText = visit.data),
|
||||
(visitType = visitText[lastTokenIndex++]),
|
||||
(scopeId = +nextToken()) &&
|
||||
(visitScope = scopeLookup[scopeId] ||= { M: scopeId }),
|
||||
"*" === visitType
|
||||
? (visitScope["J" + nextToken()] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)((visitScope[lastToken] = visit.previousSibling)))
|
||||
: branchesEnabled && branches.n());
|
||||
(walk2(), (isResuming = 1));
|
||||
for (let serialized of (resumes = render.r || []))
|
||||
if ("string" == typeof serialized) lastEffect = serialized;
|
||||
else if ("number" == typeof serialized)
|
||||
registeredValues[lastEffect](
|
||||
(scopeLookup[serialized] ||= { M: scopeId }),
|
||||
queueEffect(
|
||||
(scopeLookup[serialized] ||= { M: serialized }),
|
||||
registeredValues[lastEffect],
|
||||
);
|
||||
else
|
||||
for (let scope of serialized(serializeContext))
|
||||
$global
|
||||
? "number" == typeof scope
|
||||
? (lastScopeId += scope)
|
||||
: ((scopeId = ++lastScopeId),
|
||||
: ((scopeLookup[(scope.M = ++lastScopeId)] = scope),
|
||||
(scope.$ = $global),
|
||||
(scope.M = scopeId),
|
||||
scopeLookup[scopeId] !== scope &&
|
||||
(scopeLookup[scopeId] = Object.assign(
|
||||
scope,
|
||||
scopeLookup[scopeId],
|
||||
)),
|
||||
branchesEnabled && branches.c(scope))
|
||||
branchesEnabled && (scope.G = scopeLookup[scope.H]))
|
||||
: (($global = scope || {}),
|
||||
($global.runtimeId = runtimeId),
|
||||
($global.renderId = renderId));
|
||||
for (visit of (visits = render.v))
|
||||
((lastTokenIndex = render.i.length),
|
||||
(visitText = visit.data),
|
||||
(visitType = visitText[lastTokenIndex++]),
|
||||
(visitScope = scopeLookup[+nextToken()]),
|
||||
"*" === visitType
|
||||
? (visitScope["J" + nextToken()] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)((visitScope[lastToken] = visit.previousSibling)))
|
||||
: branchesEnabled && visitBranches());
|
||||
run();
|
||||
} finally {
|
||||
isResuming = visits.length = resumes.length = 0;
|
||||
}
|
||||
@ -721,7 +706,7 @@ function subscribeToScopeSet(ownerScope, accessor, scope) {
|
||||
function _closure(...closureSignals) {
|
||||
let [{ j: ___scopeInstancesAccessor, k: ___signalIndexAccessor }] =
|
||||
closureSignals;
|
||||
for (let i = closureSignals.length; i--; ) closureSignals[i].o = i;
|
||||
for (let i = closureSignals.length; i--; ) closureSignals[i].n = i;
|
||||
return (scope) => {
|
||||
if (scope[___scopeInstancesAccessor])
|
||||
for (let childScope of scope[___scopeInstancesAccessor])
|
||||
@ -736,7 +721,7 @@ function _closure(...closureSignals) {
|
||||
function _closure_get(valueAccessor, fn, getOwnerScope) {
|
||||
valueAccessor = decodeAccessor(valueAccessor);
|
||||
let closureSignal = (scope) => {
|
||||
((scope[closureSignal.k] = closureSignal.o),
|
||||
((scope[closureSignal.k] = closureSignal.n),
|
||||
fn(scope),
|
||||
subscribeToScopeSet(
|
||||
getOwnerScope ? getOwnerScope(scope) : scope._,
|
||||
@ -813,11 +798,11 @@ function createBranch($global, renderer, parentScope, parentNode) {
|
||||
let branch = createScope($global),
|
||||
parentBranch = parentScope?.G;
|
||||
return (
|
||||
(branch._ = renderer.d || parentScope),
|
||||
(branch._ = renderer.c || parentScope),
|
||||
(branch.G = branch),
|
||||
parentBranch &&
|
||||
((branch.N = parentBranch), (parentBranch.E ||= new Set()).add(branch)),
|
||||
renderer.g?.(branch, parentNode.namespaceURI),
|
||||
renderer.f?.(branch, parentNode.namespaceURI),
|
||||
branch
|
||||
);
|
||||
}
|
||||
@ -828,7 +813,7 @@ function createAndSetupBranch($global, renderer, parentScope, parentNode) {
|
||||
);
|
||||
}
|
||||
function setupBranch(renderer, branch) {
|
||||
return (renderer.h && queueRender(branch, renderer.h, -1), branch);
|
||||
return (renderer.g && queueRender(branch, renderer.g, -1), branch);
|
||||
}
|
||||
function _content(id, template, walks, setup, params, dynamicScopesAccessor) {
|
||||
((walks = walks ? walks.replace(/[^\0-1]+$/, "") : ""),
|
||||
@ -865,10 +850,10 @@ function _content(id, template, walks, setup, params, dynamicScopesAccessor) {
|
||||
walk((branch.S = branch.L = new Text()), walks, branch);
|
||||
};
|
||||
return (owner) => ({
|
||||
f: id,
|
||||
g: clone,
|
||||
d: owner,
|
||||
h: setup,
|
||||
e: id,
|
||||
f: clone,
|
||||
c: owner,
|
||||
g: setup,
|
||||
a: params,
|
||||
b: dynamicScopesAccessor,
|
||||
});
|
||||
@ -894,7 +879,7 @@ function _content_closures(renderer, closureFns) {
|
||||
let instance = renderer(owner);
|
||||
return (
|
||||
(instance.l = closureSignals),
|
||||
(instance.p = closureValues),
|
||||
(instance.o = closureValues),
|
||||
instance
|
||||
);
|
||||
};
|
||||
@ -1068,13 +1053,13 @@ function attrsInternal(scope, nodeAccessor, nextAttrs) {
|
||||
function _attr_content(scope, nodeAccessor, value) {
|
||||
let content = (function (value) {
|
||||
let renderer = normalizeDynamicRenderer(value);
|
||||
if (renderer && renderer.f) return renderer;
|
||||
if (renderer && renderer.e) return renderer;
|
||||
})(value),
|
||||
rendererAccessor = "C" + nodeAccessor;
|
||||
scope[rendererAccessor] !== (scope[rendererAccessor] = content?.f) &&
|
||||
scope[rendererAccessor] !== (scope[rendererAccessor] = content?.e) &&
|
||||
(setConditionalRenderer(scope, nodeAccessor, content, createAndSetupBranch),
|
||||
content?.b &&
|
||||
subscribeToScopeSet(content.d, content.b, scope["D" + nodeAccessor]));
|
||||
subscribeToScopeSet(content.c, content.b, scope["D" + nodeAccessor]));
|
||||
}
|
||||
function _attrs_script(scope, nodeAccessor) {
|
||||
let el = scope[nodeAccessor],
|
||||
@ -1312,7 +1297,7 @@ var _dynamic_tag = function (nodeAccessor, getContent, getTagVar, inputIsArgs) {
|
||||
if (
|
||||
scope[rendererAccessor] !==
|
||||
(scope[rendererAccessor] =
|
||||
normalizedRenderer?.f || normalizedRenderer) ||
|
||||
normalizedRenderer?.e || normalizedRenderer) ||
|
||||
(getContent && !normalizedRenderer && !scope[childScopeAccessor])
|
||||
)
|
||||
if (
|
||||
@ -1337,7 +1322,7 @@ var _dynamic_tag = function (nodeAccessor, getContent, getTagVar, inputIsArgs) {
|
||||
),
|
||||
content.b &&
|
||||
subscribeToScopeSet(
|
||||
content.d,
|
||||
content.c,
|
||||
content.b,
|
||||
scope[childScopeAccessor].Da,
|
||||
));
|
||||
@ -1345,7 +1330,7 @@ var _dynamic_tag = function (nodeAccessor, getContent, getTagVar, inputIsArgs) {
|
||||
} else
|
||||
normalizedRenderer?.b &&
|
||||
subscribeToScopeSet(
|
||||
normalizedRenderer.d,
|
||||
normalizedRenderer.c,
|
||||
normalizedRenderer.b,
|
||||
scope[childScopeAccessor],
|
||||
);
|
||||
@ -1364,7 +1349,7 @@ var _dynamic_tag = function (nodeAccessor, getContent, getTagVar, inputIsArgs) {
|
||||
for (let accessor in normalizedRenderer.l)
|
||||
normalizedRenderer.l[accessor](
|
||||
childScope,
|
||||
normalizedRenderer.p[accessor],
|
||||
normalizedRenderer.o[accessor],
|
||||
);
|
||||
if (normalizedRenderer.a)
|
||||
if (inputIsArgs)
|
||||
@ -1660,12 +1645,12 @@ function queueRender(scope, signal, signalKey, value, scopeKey = scope.M) {
|
||||
existingRender = signalKey >= 0 && pendingRendersLookup.get(key);
|
||||
if (existingRender) existingRender.m = value;
|
||||
else {
|
||||
let render = { e: key, c: scope, q: signal, m: value },
|
||||
let render = { d: key, h: scope, p: signal, m: value },
|
||||
i = pendingRenders.push(render) - 1;
|
||||
for (; i; ) {
|
||||
let parentIndex = (i - 1) >> 1,
|
||||
parent = pendingRenders[parentIndex];
|
||||
if (key - parent.e >= 0) break;
|
||||
if (key - parent.d >= 0) break;
|
||||
((pendingRenders[i] = parent), (i = parentIndex));
|
||||
}
|
||||
(signalKey >= 0 && pendingRendersLookup.set(key, render),
|
||||
@ -1713,27 +1698,27 @@ function runRenders() {
|
||||
if (render !== item) {
|
||||
let i = 0,
|
||||
mid = pendingRenders.length >> 1,
|
||||
key = (pendingRenders[0] = item).e;
|
||||
key = (pendingRenders[0] = item).d;
|
||||
for (; i < mid; ) {
|
||||
let bestChild = 1 + (i << 1),
|
||||
right = bestChild + 1;
|
||||
if (
|
||||
(right < pendingRenders.length &&
|
||||
pendingRenders[right].e - pendingRenders[bestChild].e < 0 &&
|
||||
pendingRenders[right].d - pendingRenders[bestChild].d < 0 &&
|
||||
(bestChild = right),
|
||||
pendingRenders[bestChild].e - key >= 0)
|
||||
pendingRenders[bestChild].d - key >= 0)
|
||||
)
|
||||
break;
|
||||
((pendingRenders[i] = pendingRenders[bestChild]), (i = bestChild));
|
||||
}
|
||||
pendingRenders[i] = item;
|
||||
}
|
||||
render.c.G?.J || runRender(render);
|
||||
render.h.G?.J || runRender(render);
|
||||
}
|
||||
for (let scope of pendingScopes) scope.I = 0;
|
||||
pendingScopes = [];
|
||||
}
|
||||
var runRender = (render) => render.q(render.c, render.m),
|
||||
var runRender = (render) => render.p(render.h, render.m),
|
||||
_enable_catch = () => {
|
||||
((_enable_catch = () => {}), enableBranches());
|
||||
let handlePendingTry = (fn, scope, branch) => {
|
||||
@ -1764,7 +1749,7 @@ var runRender = (render) => render.q(render.c, render.m),
|
||||
try {
|
||||
runRender2(render);
|
||||
} catch (error) {
|
||||
renderCatch(render.c, error);
|
||||
renderCatch(render.h, error);
|
||||
}
|
||||
})(runRender)));
|
||||
};
|
||||
@ -1796,7 +1781,7 @@ var classIdToBranch = new Map(),
|
||||
registerRenderer(fn) {
|
||||
_resume("$C_r", fn);
|
||||
},
|
||||
isRenderer: (renderer) => renderer.g,
|
||||
isRenderer: (renderer) => renderer.f,
|
||||
getStartNode: (branch) => branch.S,
|
||||
setScopeNodes(branch, startNode, endNode) {
|
||||
((branch.S = startNode), (branch.L = endNode));
|
||||
@ -1821,7 +1806,7 @@ var classIdToBranch = new Map(),
|
||||
createRenderer(params, clone) {
|
||||
let renderer = _content_branch(0, 0, 0, params);
|
||||
return (
|
||||
(renderer.g = (branch) => {
|
||||
(renderer.f = (branch) => {
|
||||
let cloned = clone();
|
||||
((branch.S = cloned.startNode), (branch.L = cloned.endNode));
|
||||
}),
|
||||
@ -1850,7 +1835,7 @@ var classIdToBranch = new Map(),
|
||||
createAndSetupBranch(
|
||||
out.global,
|
||||
renderer,
|
||||
renderer.d,
|
||||
renderer.c,
|
||||
document.body,
|
||||
))),
|
||||
renderer.a?.(branch, renderer._ ? args[0] : args));
|
||||
@ -1897,7 +1882,7 @@ function mount(input = {}, reference, position) {
|
||||
(branch.T = (newValue) => {
|
||||
curValue = newValue;
|
||||
}),
|
||||
this.h?.(branch),
|
||||
this.g?.(branch),
|
||||
args?.(branch, input));
|
||||
});
|
||||
return (
|
||||
|
||||
@ -23,6 +23,7 @@ export interface Scope {
|
||||
| Record<string | number, AbortController | void>
|
||||
| undefined;
|
||||
[AccessorProp.ClosestBranch]: BranchScope | undefined;
|
||||
[AccessorProp.ClosestBranchId]: number | undefined;
|
||||
[x: `___${string}`]: never;
|
||||
[x: string | number]: any;
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
ResumeSymbol,
|
||||
type Scope,
|
||||
} from "../common/types";
|
||||
import { queueEffect, run } from "./queue";
|
||||
import type { Signal } from "./signals";
|
||||
import { getDebugKey } from "./walker";
|
||||
|
||||
@ -60,23 +61,25 @@ export function init(runtimeId = DEFAULT_RUNTIME_ID) {
|
||||
const serializeContext: Record<string, unknown> = {
|
||||
_: registeredValues,
|
||||
};
|
||||
const branches =
|
||||
const visitBranches =
|
||||
branchesEnabled &&
|
||||
(() => {
|
||||
const branchParents = new Map<number, number>();
|
||||
const branchStarts: Comment[] = [];
|
||||
const orphanBranches: number[] = [];
|
||||
const orphanBranches: BranchScope[] = [];
|
||||
const endBranch = (singleNode?: boolean) => {
|
||||
const parent = visit.parentNode!;
|
||||
const endedBranches: BranchScope[] = [];
|
||||
let startVisit: ChildNode = visit;
|
||||
let i = orphanBranches.length;
|
||||
let claimed = 0;
|
||||
let branchId: number;
|
||||
let branch: BranchScope;
|
||||
let childBranch: BranchScope;
|
||||
|
||||
while ((branchId = +lastToken)) {
|
||||
branch = (scopeLookup[branchId] ||=
|
||||
{} as BranchScope) as BranchScope;
|
||||
endedBranches.push(
|
||||
(branch = scopeLookup[branchId] as BranchScope),
|
||||
);
|
||||
branch[AccessorProp.ClosestBranch] = branch;
|
||||
|
||||
if (singleNode) {
|
||||
while (
|
||||
@ -104,62 +107,45 @@ export function init(runtimeId = DEFAULT_RUNTIME_ID) {
|
||||
: parent.insertBefore(new Text(), visit);
|
||||
}
|
||||
|
||||
while (i-- && orphanBranches[i] > branchId) {
|
||||
branchParents.set(orphanBranches[i], branchId);
|
||||
claimed++;
|
||||
while (i && orphanBranches[--i][AccessorProp.Id] > branchId) {
|
||||
(childBranch = orphanBranches.pop()!)[
|
||||
AccessorProp.ParentBranch
|
||||
] = branch;
|
||||
(branch[AccessorProp.BranchScopes] ||= new Set()).add(
|
||||
childBranch,
|
||||
);
|
||||
}
|
||||
|
||||
orphanBranches.push(branchId);
|
||||
branchParents.set(branchId, 0);
|
||||
|
||||
nextToken(); // read optional next branchId
|
||||
}
|
||||
|
||||
orphanBranches.splice(i, claimed);
|
||||
orphanBranches.push(...endedBranches);
|
||||
};
|
||||
|
||||
return {
|
||||
___visit() {
|
||||
if (visitType === ResumeSymbol.BranchStart) {
|
||||
endBranch();
|
||||
branchStarts.push(visit);
|
||||
} else {
|
||||
visitScope[
|
||||
AccessorPrefix.Getter + nextToken() /* read accessor */
|
||||
] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)(
|
||||
(visitScope[lastToken] =
|
||||
visitType === ResumeSymbol.BranchEndOnlyChildInParent ||
|
||||
visitType ===
|
||||
ResumeSymbol.BranchEndSingleNodeOnlyChildInParent
|
||||
? visit.parentNode
|
||||
: visit),
|
||||
);
|
||||
nextToken(); // read optional first branchId
|
||||
endBranch(
|
||||
visitType !== ResumeSymbol.BranchEnd &&
|
||||
visitType !== ResumeSymbol.BranchEndOnlyChildInParent,
|
||||
);
|
||||
}
|
||||
},
|
||||
___scope(scope: Scope) {
|
||||
scope[AccessorProp.ClosestBranch] = scopeLookup[
|
||||
(scope[AccessorProp.ClosestBranchId] as number | undefined) ||
|
||||
branchParents.get(scopeId)!
|
||||
] as BranchScope;
|
||||
|
||||
if (branchParents.has(scopeId)) {
|
||||
if (scope[AccessorProp.ClosestBranch]) {
|
||||
(((scope as BranchScope)[AccessorProp.ParentBranch] =
|
||||
scope[AccessorProp.ClosestBranch])[
|
||||
AccessorProp.BranchScopes
|
||||
] ||= new Set()).add(scope as BranchScope);
|
||||
}
|
||||
scope[AccessorProp.ClosestBranch] = scope as BranchScope;
|
||||
}
|
||||
},
|
||||
return () => {
|
||||
if (visitType === ResumeSymbol.BranchStart) {
|
||||
lastToken && endBranch();
|
||||
branchStarts.push(visit);
|
||||
} else {
|
||||
visitScope[
|
||||
AccessorPrefix.Getter + nextToken() /* read accessor */
|
||||
] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)(
|
||||
(visitScope[lastToken] =
|
||||
visitType === ResumeSymbol.BranchEndOnlyChildInParent ||
|
||||
visitType ===
|
||||
ResumeSymbol.BranchEndSingleNodeOnlyChildInParent
|
||||
? visit.parentNode
|
||||
: visit),
|
||||
);
|
||||
nextToken(); // read optional first branchId
|
||||
endBranch(
|
||||
visitType !== ResumeSymbol.BranchEnd &&
|
||||
visitType !== ResumeSymbol.BranchEndOnlyChildInParent,
|
||||
);
|
||||
}
|
||||
};
|
||||
})();
|
||||
let $global: Scope[AccessorProp.Global] | undefined;
|
||||
@ -167,7 +153,6 @@ export function init(runtimeId = DEFAULT_RUNTIME_ID) {
|
||||
let lastEffect: string | undefined;
|
||||
let visits: RenderData["v"];
|
||||
let resumes: NonNullable<RenderData["r"]>;
|
||||
let scopeId: number;
|
||||
let visit: Comment;
|
||||
let visitText: string;
|
||||
let visitType: ResumeSymbol;
|
||||
@ -188,37 +173,15 @@ export function init(runtimeId = DEFAULT_RUNTIME_ID) {
|
||||
walk();
|
||||
isResuming = 1;
|
||||
|
||||
for (visit of (visits = render.v)) {
|
||||
lastTokenIndex = render.i.length;
|
||||
visitText = visit.data!;
|
||||
visitType = visitText[lastTokenIndex++] as ResumeSymbol;
|
||||
|
||||
if ((scopeId = +nextToken()) /* read scope id */) {
|
||||
visitScope = scopeLookup[scopeId] ||= {
|
||||
[AccessorProp.Id]: scopeId,
|
||||
} as Scope;
|
||||
}
|
||||
|
||||
// TODO: switch?
|
||||
if (visitType === ResumeSymbol.Node) {
|
||||
// TODO: could we use attr marker?
|
||||
visitScope[AccessorPrefix.Getter + nextToken()] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)((visitScope[lastToken] = visit.previousSibling));
|
||||
} else if (branchesEnabled) {
|
||||
branches!.___visit();
|
||||
}
|
||||
}
|
||||
|
||||
for (const serialized of (resumes = render.r || [])) {
|
||||
if (typeof serialized === "string") {
|
||||
lastEffect = serialized;
|
||||
} else if (typeof serialized === "number") {
|
||||
(registeredValues[lastEffect!] as any)(
|
||||
queueEffect(
|
||||
(scopeLookup[serialized] ||= {
|
||||
[AccessorProp.Id]: scopeId,
|
||||
[AccessorProp.Id]: serialized,
|
||||
} as Scope),
|
||||
registeredValues[lastEffect!] as any,
|
||||
);
|
||||
} else {
|
||||
for (const scope of serialized(serializeContext)) {
|
||||
@ -229,23 +192,38 @@ export function init(runtimeId = DEFAULT_RUNTIME_ID) {
|
||||
} else if (typeof scope === "number") {
|
||||
lastScopeId += scope;
|
||||
} else {
|
||||
scopeId = ++lastScopeId;
|
||||
scopeLookup[(scope[AccessorProp.Id] = ++lastScopeId)] =
|
||||
scope;
|
||||
scope[AccessorProp.Global] = $global;
|
||||
scope[AccessorProp.Id] = scopeId;
|
||||
if (scopeLookup[scopeId] !== scope) {
|
||||
scopeLookup[scopeId] = Object.assign(
|
||||
scope,
|
||||
scopeLookup[scopeId],
|
||||
) as Scope;
|
||||
}
|
||||
|
||||
if (branchesEnabled) {
|
||||
branches!.___scope(scope);
|
||||
scope[AccessorProp.ClosestBranch] = scopeLookup[
|
||||
scope[AccessorProp.ClosestBranchId]!
|
||||
] as BranchScope;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (visit of (visits = render.v)) {
|
||||
lastTokenIndex = render.i.length;
|
||||
visitText = visit.data!;
|
||||
visitType = visitText[lastTokenIndex++] as ResumeSymbol;
|
||||
visitScope = scopeLookup[+nextToken()] as Scope;
|
||||
|
||||
// TODO: switch?
|
||||
if (visitType === ResumeSymbol.Node) {
|
||||
// TODO: could we use attr marker?
|
||||
visitScope[AccessorPrefix.Getter + nextToken()] = (
|
||||
(node) => () =>
|
||||
node
|
||||
)((visitScope[lastToken] = visit.previousSibling));
|
||||
} else if (branchesEnabled) {
|
||||
visitBranches!();
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
} finally {
|
||||
isResuming = visits.length = resumes.length = 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user