fix: set parent branch on async branches

This commit is contained in:
Ryan Turnquist 2025-12-05 12:52:52 -08:00
parent 23f46f77e1
commit 1085a19fd2
18 changed files with 1223 additions and 315 deletions

View File

@ -0,0 +1,5 @@
---
"@marko/runtime-tags": patch
---
Ensure parent branch is set on async branches

View File

@ -7,8 +7,8 @@
{
"name": "*",
"total": {
"min": 20366,
"brotli": 7839
"min": 20363,
"brotli": 7810
}
},
{
@ -18,12 +18,12 @@
"brotli": 140
},
"runtime": {
"min": 4076,
"brotli": 1832
"min": 4084,
"brotli": 1846
},
"total": {
"min": 4250,
"brotli": 1972
"min": 4258,
"brotli": 1986
}
},
{
@ -34,11 +34,11 @@
},
"runtime": {
"min": 2209,
"brotli": 1163
"brotli": 1160
},
"total": {
"min": 2305,
"brotli": 1250
"brotli": 1247
}
},
{
@ -48,12 +48,12 @@
"brotli": 398
},
"runtime": {
"min": 7132,
"brotli": 3114
"min": 7140,
"brotli": 3125
},
"total": {
"min": 7867,
"brotli": 3512
"min": 7875,
"brotli": 3523
}
},
{
@ -64,11 +64,11 @@
},
"runtime": {
"min": 2361,
"brotli": 1204
"brotli": 1208
},
"total": {
"min": 2491,
"brotli": 1319
"brotli": 1323
}
}
]

View File

@ -1,4 +1,4 @@
// size: 20366 (min) 7839 (brotli)
// size: 20363 (min) 7810 (brotli)
var empty = [],
rest = Symbol();
function attrTag(attrs) {
@ -113,7 +113,14 @@ function handleDelegated(ev) {
function stripSpacesAndPunctuation(str) {
return str.replace(/[^\p{L}\p{N}]/gu, "");
}
var nextScopeId = 1e6;
var parsers = {};
function parseHTML(html, ns) {
let parser = (parsers[ns] ||= document.createElementNS(ns, "template"));
return ((parser.innerHTML = html), parser.content || parser);
}
var isScheduled,
channel,
nextScopeId = 1e6;
function createScope($global, closestBranch) {
let scope = { L: nextScopeId++, H: 1, F: closestBranch, $: $global };
return (pendingScopes.push(scope), scope);
@ -147,6 +154,188 @@ function tempDetachBranch(branch) {
((fragment.namespaceURI = branch.S.parentNode.namespaceURI),
insertChildNodes(fragment, null, branch.S, branch.K));
}
function schedule() {
isScheduled || ((isScheduled = 1), queueMicrotask(flushAndWaitFrame));
}
function flushAndWaitFrame() {
(run(), requestAnimationFrame(triggerMacroTask));
}
function triggerMacroTask() {
(channel ||
((channel = new MessageChannel()).port1.onmessage = () => {
((isScheduled = 0), run());
}),
channel.port2.postMessage(0));
}
function _let(id, fn) {
let valueAccessor = decodeAccessor(id),
valueChangeAccessor = "M" + valueAccessor;
return (scope, value, valueChange) => (
rendering
? (((scope[valueChangeAccessor] = valueChange) &&
scope[valueAccessor] !== value) ||
scope.H) &&
((scope[valueAccessor] = value), fn?.(scope))
: scope[valueChangeAccessor]
? scope[valueChangeAccessor](value)
: scope[valueAccessor] !== (scope[valueAccessor] = value) &&
fn &&
(schedule(), queueRender(scope, fn, id)),
value
);
}
function _const(valueAccessor, fn) {
return (
(valueAccessor = decodeAccessor(valueAccessor)),
(scope, value) => {
(!(valueAccessor in scope) || scope[valueAccessor] !== value) &&
((scope[valueAccessor] = value), fn?.(scope));
}
);
}
function _or(id, fn, defaultPending = 1, scopeIdAccessor = "L") {
return (scope) => {
scope.H
? id in scope
? --scope[id] || fn(scope)
: (scope[id] = defaultPending)
: queueRender(scope, fn, id, 0, scope[scopeIdAccessor]);
};
}
function _for_closure(ownerLoopNodeAccessor, fn) {
let scopeAccessor =
"A" + (ownerLoopNodeAccessor = decodeAccessor(ownerLoopNodeAccessor)),
ownerSignal = (ownerScope) => {
let scopes = toArray(ownerScope[scopeAccessor]);
scopes.length &&
queueRender(
ownerScope,
() => {
for (let scope of scopes) !scope.H && !scope.I && fn(scope);
},
-1,
0,
scopes[0].L,
);
};
return ((ownerSignal._ = fn), ownerSignal);
}
function _if_closure(ownerConditionalNodeAccessor, branch, fn) {
let scopeAccessor =
"A" +
(ownerConditionalNodeAccessor = decodeAccessor(
ownerConditionalNodeAccessor,
)),
branchAccessor = "D" + ownerConditionalNodeAccessor,
ownerSignal = (scope) => {
let ifScope = scope[scopeAccessor];
ifScope &&
!ifScope.H &&
(scope[branchAccessor] || 0) === branch &&
queueRender(ifScope, fn, -1);
};
return ((ownerSignal._ = fn), ownerSignal);
}
function subscribeToScopeSet(ownerScope, accessor, scope) {
let subscribers = (ownerScope[accessor] ||= new Set());
subscribers.has(scope) ||
(subscribers.add(scope),
$signal(scope, -1).addEventListener("abort", () =>
ownerScope[accessor].delete(scope),
));
}
function _closure(...closureSignals) {
let [{ k: ___scopeInstancesAccessor, l: ___signalIndexAccessor }] =
closureSignals;
for (let i = closureSignals.length; i--; ) closureSignals[i].q = i;
return (scope) => {
if (scope[___scopeInstancesAccessor])
for (let childScope of scope[___scopeInstancesAccessor])
childScope.H ||
queueRender(
childScope,
closureSignals[childScope[___signalIndexAccessor]],
-1,
);
};
}
function _closure_get(valueAccessor, fn, getOwnerScope, resumeId) {
valueAccessor = decodeAccessor(valueAccessor);
let closureSignal = (scope) => {
((scope[closureSignal.l] = closureSignal.q),
fn(scope),
subscribeToScopeSet(
getOwnerScope ? getOwnerScope(scope) : scope._,
closureSignal.k,
scope,
));
};
return (
(closureSignal.k = "B" + valueAccessor),
(closureSignal.l = "C" + valueAccessor),
resumeId && _resume(resumeId, closureSignal),
closureSignal
);
}
function _child_setup(setup) {
return (
(setup._ = (scope, owner) => {
((scope._ = owner), queueRender(scope, setup, -1));
}),
setup
);
}
function _var(scope, childAccessor, signal) {
scope[decodeAccessor(childAccessor)].T = (value) => signal(scope, value);
}
var _return = (scope, value) => scope.T?.(value);
function _return_change(scope, changeHandler) {
changeHandler && (scope.U = changeHandler);
}
var _var_change = (scope, value) => scope.U?.(value),
tagIdsByGlobal = new WeakMap();
function _id({ $: $global }) {
let id = tagIdsByGlobal.get($global) || 0;
return (
tagIdsByGlobal.set($global, id + 1),
"c" + $global.runtimeId + $global.renderId + id.toString(36)
);
}
function _script(id, fn) {
return (
_resume(id, fn),
(scope) => {
queueEffect(scope, fn);
}
);
}
function _el_read(value) {
return value;
}
function* traverseAllHoisted(scope, path, curIndex = path.length - 1) {
if (scope)
if (Symbol.iterator in scope)
for (let s of scope instanceof Map ? scope.values() : scope)
yield* traverseAllHoisted(s, path, curIndex);
else
curIndex
? yield* traverseAllHoisted(scope[path[curIndex]], path, curIndex - 1)
: yield scope[path[0]];
}
function _hoist(...path) {
return (
(path = path.map((p) => ("string" == typeof p ? p : decodeAccessor(p)))),
(scope) => {
let getOne = (...args) =>
iterator()
.next()
.value?.(...args),
iterator = (getOne[Symbol.iterator] = () =>
traverseAllHoisted(scope, path));
return getOne;
}
);
}
var walker = document.createTreeWalker(document);
function walk(startNode, walkCodes, branch) {
((walker.currentNode = startNode), walkInternal(0, walkCodes, branch));
@ -200,6 +389,99 @@ function walkInternal(currentWalkIndex, walkCodes, scope) {
} else storedMultiplier = 10 * currentMultiplier + value - 117;
}
}
function createBranch($global, renderer, parentScope, parentNode) {
let branch = createScope($global);
return (
(branch._ = renderer.e || parentScope),
setParentBranch(branch, parentScope?.F),
renderer.h?.(branch, parentNode.namespaceURI),
branch
);
}
function setParentBranch(branch, parentBranch) {
(parentBranch &&
((branch.N = parentBranch), (parentBranch.D ||= new Set()).add(branch)),
(branch.F = branch));
}
function createAndSetupBranch($global, renderer, parentScope, parentNode) {
return setupBranch(
renderer,
createBranch($global, renderer, parentScope, parentNode),
);
}
function setupBranch(renderer, branch) {
return (renderer.j && queueRender(branch, renderer.j, -1), branch);
}
function _content(id, template, walks, setup, params, dynamicScopesAccessor) {
((walks = walks ? walks.replace(/[^\0-1]+$/, "") : ""),
(setup = setup ? setup._ || setup : void 0),
(params ||= void 0));
let clone = template
? (branch, ns) => {
((cloneCache[ns] ||= {})[template] ||= (function (html, ns) {
let { firstChild: firstChild, lastChild: lastChild } = parseHTML(
html,
ns,
),
parent = document.createElementNS(ns, "t");
return (
insertChildNodes(parent, null, firstChild, lastChild),
firstChild === lastChild && firstChild.nodeType < 8
? (branch, walks) => {
walk(
(branch.S = branch.K = firstChild.cloneNode(!0)),
walks,
branch,
);
}
: (branch, walks) => {
let clone = parent.cloneNode(!0);
(walk(clone.firstChild, walks, branch),
(branch.S = clone.firstChild),
(branch.K = clone.lastChild));
}
);
})(template, ns))(branch, walks);
}
: (branch) => {
walk((branch.S = branch.K = new Text()), walks, branch);
};
return (owner) => ({
f: id,
h: clone,
e: owner,
j: setup,
b: params,
d: dynamicScopesAccessor,
});
}
function _content_resume(
id,
template,
walks,
setup,
params,
dynamicScopesAccessor,
) {
return _resume(
id,
_content(id, template, walks, setup, params, dynamicScopesAccessor),
);
}
function _content_closures(renderer, closureFns) {
let closureSignals = {};
for (let key in closureFns)
closureSignals[key] = _const(+key, closureFns[key]);
return (owner, closureValues) => {
let instance = renderer(owner);
return (
(instance.n = closureSignals),
(instance.t = closureValues),
instance
);
};
}
var cloneCache = {};
var branchesEnabled,
isResuming,
registeredValues = {};
@ -268,7 +550,7 @@ function init(runtimeId = "M") {
((endedBranches ||= []).push(
(branch = scopeLookup[branchId] ||= { L: branchId }),
),
(branch.F = branch),
setParentBranch(branch, branch.F),
(branch.O = render.p?.[branchId]) &&
(branch.O.m = render.m),
singleNode)
@ -297,8 +579,7 @@ function init(runtimeId = "M") {
? startVisit
: parent.insertBefore(new Text(), visit)));
for (; i && orphanBranches[--i].L > branchId; )
((orphanBranches[i].N = branch),
(branch.D ||= new Set()).add(orphanBranches.pop()));
setParentBranch(orphanBranches.pop(), branch);
nextToken();
}
(endedBranches &&
@ -648,286 +929,6 @@ function normalizeBoolProp(value) {
function toValueProp(it) {
return it.value;
}
var isScheduled,
channel,
parsers = {};
function parseHTML(html, ns) {
let parser = (parsers[ns] ||= document.createElementNS(ns, "template"));
return ((parser.innerHTML = html), parser.content || parser);
}
function schedule() {
isScheduled || ((isScheduled = 1), queueMicrotask(flushAndWaitFrame));
}
function flushAndWaitFrame() {
(run(), requestAnimationFrame(triggerMacroTask));
}
function triggerMacroTask() {
(channel ||
((channel = new MessageChannel()).port1.onmessage = () => {
((isScheduled = 0), run());
}),
channel.port2.postMessage(0));
}
function _let(id, fn) {
let valueAccessor = decodeAccessor(id),
valueChangeAccessor = "M" + valueAccessor;
return (scope, value, valueChange) => (
rendering
? (((scope[valueChangeAccessor] = valueChange) &&
scope[valueAccessor] !== value) ||
scope.H) &&
((scope[valueAccessor] = value), fn?.(scope))
: scope[valueChangeAccessor]
? scope[valueChangeAccessor](value)
: scope[valueAccessor] !== (scope[valueAccessor] = value) &&
fn &&
(schedule(), queueRender(scope, fn, id)),
value
);
}
function _const(valueAccessor, fn) {
return (
(valueAccessor = decodeAccessor(valueAccessor)),
(scope, value) => {
(!(valueAccessor in scope) || scope[valueAccessor] !== value) &&
((scope[valueAccessor] = value), fn?.(scope));
}
);
}
function _or(id, fn, defaultPending = 1, scopeIdAccessor = "L") {
return (scope) => {
scope.H
? id in scope
? --scope[id] || fn(scope)
: (scope[id] = defaultPending)
: queueRender(scope, fn, id, 0, scope[scopeIdAccessor]);
};
}
function _for_closure(ownerLoopNodeAccessor, fn) {
let scopeAccessor =
"A" + (ownerLoopNodeAccessor = decodeAccessor(ownerLoopNodeAccessor)),
ownerSignal = (ownerScope) => {
let scopes = toArray(ownerScope[scopeAccessor]);
scopes.length &&
queueRender(
ownerScope,
() => {
for (let scope of scopes) !scope.H && !scope.I && fn(scope);
},
-1,
0,
scopes[0].L,
);
};
return ((ownerSignal._ = fn), ownerSignal);
}
function _if_closure(ownerConditionalNodeAccessor, branch, fn) {
let scopeAccessor =
"A" +
(ownerConditionalNodeAccessor = decodeAccessor(
ownerConditionalNodeAccessor,
)),
branchAccessor = "D" + ownerConditionalNodeAccessor,
ownerSignal = (scope) => {
let ifScope = scope[scopeAccessor];
ifScope &&
!ifScope.H &&
(scope[branchAccessor] || 0) === branch &&
queueRender(ifScope, fn, -1);
};
return ((ownerSignal._ = fn), ownerSignal);
}
function subscribeToScopeSet(ownerScope, accessor, scope) {
let subscribers = (ownerScope[accessor] ||= new Set());
subscribers.has(scope) ||
(subscribers.add(scope),
$signal(scope, -1).addEventListener("abort", () =>
ownerScope[accessor].delete(scope),
));
}
function _closure(...closureSignals) {
let [{ k: ___scopeInstancesAccessor, l: ___signalIndexAccessor }] =
closureSignals;
for (let i = closureSignals.length; i--; ) closureSignals[i].q = i;
return (scope) => {
if (scope[___scopeInstancesAccessor])
for (let childScope of scope[___scopeInstancesAccessor])
childScope.H ||
queueRender(
childScope,
closureSignals[childScope[___signalIndexAccessor]],
-1,
);
};
}
function _closure_get(valueAccessor, fn, getOwnerScope, resumeId) {
valueAccessor = decodeAccessor(valueAccessor);
let closureSignal = (scope) => {
((scope[closureSignal.l] = closureSignal.q),
fn(scope),
subscribeToScopeSet(
getOwnerScope ? getOwnerScope(scope) : scope._,
closureSignal.k,
scope,
));
};
return (
(closureSignal.k = "B" + valueAccessor),
(closureSignal.l = "C" + valueAccessor),
resumeId && _resume(resumeId, closureSignal),
closureSignal
);
}
function _child_setup(setup) {
return (
(setup._ = (scope, owner) => {
((scope._ = owner), queueRender(scope, setup, -1));
}),
setup
);
}
function _var(scope, childAccessor, signal) {
scope[decodeAccessor(childAccessor)].T = (value) => signal(scope, value);
}
var _return = (scope, value) => scope.T?.(value);
function _return_change(scope, changeHandler) {
changeHandler && (scope.U = changeHandler);
}
var _var_change = (scope, value) => scope.U?.(value),
tagIdsByGlobal = new WeakMap();
function _id({ $: $global }) {
let id = tagIdsByGlobal.get($global) || 0;
return (
tagIdsByGlobal.set($global, id + 1),
"c" + $global.runtimeId + $global.renderId + id.toString(36)
);
}
function _script(id, fn) {
return (
_resume(id, fn),
(scope) => {
queueEffect(scope, fn);
}
);
}
function _el_read(value) {
return value;
}
function* traverseAllHoisted(scope, path, curIndex = path.length - 1) {
if (scope)
if (Symbol.iterator in scope)
for (let s of scope instanceof Map ? scope.values() : scope)
yield* traverseAllHoisted(s, path, curIndex);
else
curIndex
? yield* traverseAllHoisted(scope[path[curIndex]], path, curIndex - 1)
: yield scope[path[0]];
}
function _hoist(...path) {
return (
(path = path.map((p) => ("string" == typeof p ? p : decodeAccessor(p)))),
(scope) => {
let getOne = (...args) =>
iterator()
.next()
.value?.(...args),
iterator = (getOne[Symbol.iterator] = () =>
traverseAllHoisted(scope, path));
return getOne;
}
);
}
function createBranch($global, renderer, parentScope, parentNode) {
let branch = createScope($global),
parentBranch = parentScope?.F;
return (
(branch._ = renderer.e || parentScope),
(branch.F = branch),
parentBranch &&
((branch.N = parentBranch), (parentBranch.D ||= new Set()).add(branch)),
renderer.h?.(branch, parentNode.namespaceURI),
branch
);
}
function createAndSetupBranch($global, renderer, parentScope, parentNode) {
return setupBranch(
renderer,
createBranch($global, renderer, parentScope, parentNode),
);
}
function setupBranch(renderer, branch) {
return (renderer.j && queueRender(branch, renderer.j, -1), branch);
}
function _content(id, template, walks, setup, params, dynamicScopesAccessor) {
((walks = walks ? walks.replace(/[^\0-1]+$/, "") : ""),
(setup = setup ? setup._ || setup : void 0),
(params ||= void 0));
let clone = template
? (branch, ns) => {
((cloneCache[ns] ||= {})[template] ||= (function (html, ns) {
let { firstChild: firstChild, lastChild: lastChild } = parseHTML(
html,
ns,
),
parent = document.createElementNS(ns, "t");
return (
insertChildNodes(parent, null, firstChild, lastChild),
firstChild === lastChild && firstChild.nodeType < 8
? (branch, walks) => {
walk(
(branch.S = branch.K = firstChild.cloneNode(!0)),
walks,
branch,
);
}
: (branch, walks) => {
let clone = parent.cloneNode(!0);
(walk(clone.firstChild, walks, branch),
(branch.S = clone.firstChild),
(branch.K = clone.lastChild));
}
);
})(template, ns))(branch, walks);
}
: (branch) => {
walk((branch.S = branch.K = new Text()), walks, branch);
};
return (owner) => ({
f: id,
h: clone,
e: owner,
j: setup,
b: params,
d: dynamicScopesAccessor,
});
}
function _content_resume(
id,
template,
walks,
setup,
params,
dynamicScopesAccessor,
) {
return _resume(
id,
_content(id, template, walks, setup, params, dynamicScopesAccessor),
);
}
function _content_closures(renderer, closureFns) {
let closureSignals = {};
for (let key in closureFns)
closureSignals[key] = _const(+key, closureFns[key]);
return (owner, closureValues) => {
let instance = renderer(owner);
return (
(instance.n = closureSignals),
(instance.t = closureValues),
instance
);
};
}
var cloneCache = {};
function _to_text(value) {
return value || 0 === value ? value + "" : "";
}

View File

@ -1 +1 @@
{"vars":{"props":{"$empty":"e","$rest":"t","$attrTag":"n","$attrTags":"r","$attrTagIterator":"i","$_assert_hoist":"o","$forIn":"l","$forOf":"u","$forTo":"f","$forUntil":"a","$_call":"c","$stringifyClassObject":"s","$stringifyStyleObject":"d","$toDelimitedString":"h","$isEventHandler":"p","$getEventHandlerName":"g","$normalizeDynamicRenderer":"v","$decodeAccessor":"b","$toArray":"m","$push":"S","$defaultDelegator":"y","$_on":"A","$createDelegator":"N","$handleDelegated":"k","$stripSpacesAndPunctuation":"C","$nextScopeId":"_","$createScope":"w","$skipScope":"E","$findBranchWithKey":"T","$destroyBranch":"I","$destroyNestedBranches":"F","$removeAndDestroyBranch":"M","$insertBranchBefore":"x","$tempDetachBranch":"L","$walker":"$","$walk":"O","$walkInternal":"D","$branchesEnabled":"K","$isResuming":"V","$registeredValues":"G","$enableBranches":"R","$init":"B","$runResumeEffects":"H","$_resume":"U","$_var_resume":"q","$_el":"P","$_attr_input_checked":"j","$_attr_input_checked_script":"W","$_attr_input_checkedValue":"J","$_attr_input_checkedValue_script":"Q","$_attr_input_value":"X","$_attr_input_value_script":"Z","$_attr_select_value":"z","$_attr_select_value_script":"Y","$setSelectOptions":"ee","$_attr_details_or_dialog_open":"te","$_attr_details_or_dialog_open_script":"ne","$inputType":"re","$setValueAndUpdateSelection":"ie","$setCheckboxValue":"oe","$controllableDelegate":"le","$syncControllable":"ue","$handleChange":"fe","$handleFormReset":"ae","$hasValueChanged":"ce","$hasCheckboxChanged":"se","$hasSelectChanged":"de","$hasFormElementChanged":"he","$normalizeStrProp":"pe","$normalizeBoolProp":"ge","$toValueProp":"ve","$isScheduled":"be","$channel":"me","$parsers":"Se","$parseHTML":"ye","$schedule":"Ae","$flushAndWaitFrame":"Ne","$triggerMacroTask":"ke","$_let":"Ce","$_const":"_e","$_or":"we","$_for_closure":"Ee","$_if_closure":"Te","$subscribeToScopeSet":"Ie","$_closure":"Fe","$_closure_get":"Me","$_child_setup":"xe","$_var":"Le","$_return":"$e","$_return_change":"Oe","$_var_change":"De","$tagIdsByGlobal":"Ke","$_id":"Ve","$_script":"Ge","$_el_read":"Re","$traverseAllHoisted":"Be","$_hoist":"He","$createBranch":"Ue","$createAndSetupBranch":"qe","$setupBranch":"Pe","$_content":"je","$_content_resume":"We","$_content_closures":"Je","$cloneCache":"Qe","$_to_text":"Xe","$_attr":"Ze","$setAttribute":"ze","$_attr_class":"Ye","$_attr_class_items":"et","$_attr_class_item":"tt","$_attr_style":"nt","$_attr_style_items":"rt","$_attr_style_item":"it","$_text":"ot","$_text_content":"lt","$_attrs":"ut","$_attrs_content":"ft","$hasAttrAlias":"at","$_attrs_partial":"ct","$_attrs_partial_content":"st","$attrsInternal":"dt","$_attr_content":"ht","$_attrs_script":"pt","$_html":"gt","$normalizeAttrValue":"vt","$normalizeString":"bt","$_lifecycle":"mt","$removeChildNodes":"St","$insertChildNodes":"yt","$toInsertNode":"At","$_await_promise":"Nt","$_await_content":"kt","$_try":"Ct","$renderCatch":"_t","$_if":"wt","$_dynamic_tag":"Et","$_resume_dynamic_tag":"Tt","$dynamicTagScript":"It","$setConditionalRenderer":"Ft","$_for_of":"Mt","$_for_in":"xt","$_for_to":"Lt","$_for_until":"$t","$loop":"Ot","$createBranchWithTagNameOrRenderer":"Dt","$bySecondArg":"Kt","$byFirstArg":"Vt","$asyncRendersLookup":"Gt","$rendering":"Rt","$pendingRenders":"Bt","$pendingRendersLookup":"Ht","$caughtError":"Ut","$placeholderShown":"qt","$pendingEffects":"Pt","$pendingScopes":"jt","$scopeKeyOffset":"Wt","$queueRender":"Jt","$queuePendingRender":"Qt","$queueEffect":"Xt","$run":"Zt","$prepareEffects":"zt","$runEffects":"Yt","$runRenders":"en","$runRender":"tn","$_enable_catch":"nn","$$signalReset":"rn","$$signal":"on","$abort":"ln","$classIdToBranch":"un","$compat":"fn","$_template":"an","$mount":"cn","$$clickCount__script":"ta","$$clickCount":"aa","$$setup":"na","$forEach":"sn","$$if_content__setup":"sa","$$if_content__comment_comments":"ia","$$if_content__id":"ca","$$for_content__id":"la","$$for_content__input_path__OR__i":"ma","$$for_content__input_path":"oa","$$for_content__i":"ua","$$for_content__open__script":"ba","$$for_content__open":"ea","$$for_content__setup":"_a","$$for_content__comment_text":"da","$$for_content__if":"fa","$$for_content__comment_comments":"ha","$$for_content__$params":"ja","$$for_content__comment":"pa","$$for":"ra","$$input_comments":"ga","$$input_path":"ka","$_attr_nonce":"dn"}}}
{"vars":{"props":{"$empty":"e","$rest":"t","$attrTag":"n","$attrTags":"r","$attrTagIterator":"i","$_assert_hoist":"o","$forIn":"l","$forOf":"u","$forTo":"f","$forUntil":"a","$_call":"c","$stringifyClassObject":"s","$stringifyStyleObject":"d","$toDelimitedString":"h","$isEventHandler":"p","$getEventHandlerName":"g","$normalizeDynamicRenderer":"v","$decodeAccessor":"b","$toArray":"m","$push":"S","$defaultDelegator":"y","$_on":"A","$createDelegator":"N","$handleDelegated":"k","$stripSpacesAndPunctuation":"C","$nextScopeId":"_","$createScope":"w","$skipScope":"E","$findBranchWithKey":"T","$destroyBranch":"I","$destroyNestedBranches":"F","$removeAndDestroyBranch":"M","$insertBranchBefore":"x","$tempDetachBranch":"L","$walker":"$","$walk":"O","$walkInternal":"D","$branchesEnabled":"K","$isResuming":"V","$registeredValues":"G","$enableBranches":"R","$init":"B","$runResumeEffects":"H","$_resume":"U","$_var_resume":"q","$_el":"P","$_attr_input_checked":"j","$_attr_input_checked_script":"W","$_attr_input_checkedValue":"J","$_attr_input_checkedValue_script":"Q","$_attr_input_value":"X","$_attr_input_value_script":"Z","$_attr_select_value":"z","$_attr_select_value_script":"Y","$setSelectOptions":"ee","$_attr_details_or_dialog_open":"te","$_attr_details_or_dialog_open_script":"ne","$inputType":"re","$setValueAndUpdateSelection":"ie","$setCheckboxValue":"oe","$controllableDelegate":"le","$syncControllable":"ue","$handleChange":"fe","$handleFormReset":"ae","$hasValueChanged":"ce","$hasCheckboxChanged":"se","$hasSelectChanged":"de","$hasFormElementChanged":"he","$normalizeStrProp":"pe","$normalizeBoolProp":"ge","$toValueProp":"ve","$isScheduled":"be","$channel":"me","$parsers":"Se","$parseHTML":"ye","$schedule":"Ae","$flushAndWaitFrame":"Ne","$triggerMacroTask":"ke","$_let":"Ce","$_const":"_e","$_or":"we","$_for_closure":"Ee","$_if_closure":"Te","$subscribeToScopeSet":"Ie","$_closure":"Fe","$_closure_get":"Me","$_child_setup":"xe","$_var":"Le","$_return":"$e","$_return_change":"Oe","$_var_change":"De","$tagIdsByGlobal":"Ke","$_id":"Ve","$_script":"Ge","$_el_read":"Re","$traverseAllHoisted":"Be","$_hoist":"He","$createBranch":"Ue","$createAndSetupBranch":"qe","$setupBranch":"Pe","$_content":"je","$_content_resume":"We","$_content_closures":"Je","$cloneCache":"Qe","$_to_text":"Xe","$_attr":"Ze","$setAttribute":"ze","$_attr_class":"Ye","$_attr_class_items":"et","$_attr_class_item":"tt","$_attr_style":"nt","$_attr_style_items":"rt","$_attr_style_item":"it","$_text":"ot","$_text_content":"lt","$_attrs":"ut","$_attrs_content":"ft","$hasAttrAlias":"at","$_attrs_partial":"ct","$_attrs_partial_content":"st","$attrsInternal":"dt","$_attr_content":"ht","$_attrs_script":"pt","$_html":"gt","$normalizeAttrValue":"vt","$normalizeString":"bt","$_lifecycle":"mt","$removeChildNodes":"St","$insertChildNodes":"yt","$toInsertNode":"At","$_await_promise":"Nt","$_await_content":"kt","$_try":"Ct","$renderCatch":"_t","$_if":"wt","$_dynamic_tag":"Et","$_resume_dynamic_tag":"Tt","$dynamicTagScript":"It","$setConditionalRenderer":"Ft","$_for_of":"Mt","$_for_in":"xt","$_for_to":"Lt","$_for_until":"$t","$loop":"Ot","$createBranchWithTagNameOrRenderer":"Dt","$bySecondArg":"Kt","$byFirstArg":"Vt","$asyncRendersLookup":"Gt","$rendering":"Rt","$pendingRenders":"Bt","$pendingRendersLookup":"Ht","$caughtError":"Ut","$placeholderShown":"qt","$pendingEffects":"Pt","$pendingScopes":"jt","$scopeKeyOffset":"Wt","$queueRender":"Jt","$queuePendingRender":"Qt","$queueEffect":"Xt","$run":"Zt","$prepareEffects":"zt","$runEffects":"Yt","$runRenders":"en","$runRender":"tn","$_enable_catch":"nn","$$signalReset":"rn","$$signal":"on","$abort":"ln","$classIdToBranch":"un","$compat":"fn","$_template":"an","$mount":"cn","$$clickCount__script":"ta","$$clickCount":"aa","$$setup":"na","$forEach":"sn","$$if_content__setup":"sa","$$if_content__comment_comments":"ia","$$if_content__id":"ca","$$for_content__id":"la","$$for_content__input_path__OR__i":"ma","$$for_content__input_path":"oa","$$for_content__i":"ua","$$for_content__open__script":"ba","$$for_content__open":"ea","$$for_content__setup":"_a","$$for_content__comment_text":"da","$$for_content__if":"fa","$$for_content__comment_comments":"ha","$$for_content__$params":"ja","$$for_content__comment":"pa","$$for":"ra","$$input_comments":"ga","$$input_path":"ka","$_attr_nonce":"dn","$setParentBranch":"hn"}}}

View File

@ -0,0 +1,29 @@
{
"vars": {
"props": {
"$_": "t",
"$init": "o",
"$resolveAfter": "e",
"$$await_content__setup__script": "a",
"$$await_content__setup": "r",
"$$placeholder_content": "n",
"$$await_content": "i",
"$$try_content__await_promise": "c",
"$$try_content__setup": "s",
"$$if_content__try": "m",
"$$if_content__setup": "_",
"$$if": "l",
"$$show": "u",
"$$await_content__show": "d",
"$$show__closure": "g",
"$$try_content__show": "p",
"$$await_content2__setup__script": "b",
"$$await_content2__setup": "f",
"$$await_content2": "w",
"$$try_content__await_promise2": "$",
"$$try_content__v": "k",
"$$v__closure": "x",
"$$v": "y"
}
}
}

View File

@ -0,0 +1,67 @@
# Render
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
```
# Render ASYNC
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
loading...
```
# Render ASYNC
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
1
```
# Render
```js
container.querySelector("button").click();
```
```html
<button />
<div
id="one"
>
Pass
</div>
<div
id="two"
>
Pass
</div>
```

View File

@ -0,0 +1,114 @@
# Render
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
<!---->
<!---->
<!---->
<!---->
<!---->
```
# Mutations
```
INSERT button, div0, div1, #comment0, #comment1, #text0, #text1, #comment2, #comment3, #comment4
```
# Render ASYNC
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
<!---->
loading...
<!---->
<!---->
```
# Mutations
```
INSERT #text
REMOVE #document-fragment/#comment0 after #text
REMOVE #document-fragment/#text0 after #text
REMOVE #document-fragment/#text1 after #text
REMOVE #document-fragment/#comment1 after #text
```
# Render ASYNC
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
<!---->
<!---->
1
<!---->
<!---->
<!---->
```
# Mutations
```
INSERT #comment1, #text0, #text1, #comment2
REMOVE #text after #comment2
UPDATE #text0 " " => "1"
```
# Render
```js
container.querySelector("button").click();
```
```html
<button />
<div
id="one"
>
Pass
</div>
<div
id="two"
>
Pass
</div>
<!---->
```
# Mutations
```
INSERT #text
REMOVE #comment after #text
REMOVE #comment after #text
REMOVE #text after #text
REMOVE #text after #text
REMOVE #comment after #text
REMOVE #comment after #text
REMOVE #text in div0
INSERT div0/#text
REMOVE #text in div1
INSERT div1/#text
```

View File

@ -0,0 +1,56 @@
// size: 772 (min) 368 (brotli)
_._enable_catch();
const $await_content2__setup__script = _._script(
"a0",
($scope) =>
(_.$signal($scope, 0).onabort = () =>
(document.querySelector("#two").textContent = "Pass")),
),
$await_content2__setup = ($scope) => {
(_.$signalReset($scope, 0), $await_content2__setup__script($scope));
},
$placeholder_content = _._content_resume("a1", "loading...", "b"),
$await_content__show = _._closure_get(
2,
($scope) => _._text($scope.a, $scope._._._.c),
($scope) => $scope._._._,
"a2",
),
$await_content__setup__script = _._script(
"a3",
($scope) =>
(_.$signal($scope, 0).onabort = () =>
(document.querySelector("#one").textContent = "Pass")),
),
$await_content__setup = ($scope) => {
(_.$signalReset($scope, 0),
$await_content__show($scope),
$await_content__setup__script($scope));
},
$await_content = _._await_content(0, " ", " b", $await_content__setup),
$try_content__await_promise = _._await_promise(0),
$await_content2 = _._await_content(1, 0, 0, $await_content2__setup),
$try_content__await_promise2 = _._await_promise(1),
$try_content__setup = ($scope) => {
($await_content($scope),
$await_content2($scope),
$try_content__await_promise($scope, resolveAfter(0, 1)),
$try_content__await_promise2($scope, resolveAfter(0, 1)));
},
$if_content__try = _._try(0, "<!><!><!><!>", "b%b%c", $try_content__setup),
$if_content__setup = ($scope) => {
$if_content__try($scope, {
placeholder: _.attrTag({ content: $placeholder_content($scope) }),
});
},
$if = _._if(1, "<!><!><!>", "b%c", $if_content__setup),
$show__closure = _._closure($await_content__show),
$show = _._let(2, ($scope) => {
($if($scope, $scope.c ? 0 : 1), $show__closure($scope));
});
(_._script("a4", ($scope) =>
_._on($scope.a, "click", function () {
$show($scope, 0);
}),
),
init());

View File

@ -0,0 +1,50 @@
export const $template = "<button></button><div id=one>Fail</div><div id=two>Fail</div><!><!>";
export const $walks = /* get, over(3), replace, over(2) */" d%c";
import { resolveAfter } from "../../utils/resolve";
import * as _ from "@marko/runtime-tags/debug/dom";
_._enable_catch();
const $await_content2__setup__script = _._script("__tests__/template.marko_5", $scope => (_.$signal($scope, 0).onabort = () => document.querySelector('#two').textContent = "Pass"));
const $await_content2__setup = $scope => {
_.$signalReset($scope, 0);
$await_content2__setup__script($scope);
};
const $placeholder_content = _._content_resume("__tests__/template.marko_4_content", "loading...", /* over(1) */"b");
const $await_content__show = /* @__PURE__ */_._closure_get("show", $scope => _._text($scope["#text/0"], $scope._._._.show), $scope => $scope._._._, "__tests__/template.marko_3_show");
const $await_content__setup__script = _._script("__tests__/template.marko_3", $scope => (_.$signal($scope, 0).onabort = () => document.querySelector('#one').textContent = "Pass"));
const $await_content__setup = $scope => {
_.$signalReset($scope, 0);
$await_content__show($scope);
$await_content__setup__script($scope);
};
const $await_content = /* @__PURE__ */_._await_content("#text/0", " ", /* get, over(1) */" b", $await_content__setup);
const $try_content__await_promise = /* @__PURE__ */_._await_promise("#text/0");
const $await_content2 = /* @__PURE__ */_._await_content("#text/1", 0, 0, $await_content2__setup);
const $try_content__await_promise2 = /* @__PURE__ */_._await_promise("#text/1");
const $try_content__setup = $scope => {
$await_content($scope);
$await_content2($scope);
$try_content__await_promise($scope, resolveAfter(0, 1));
$try_content__await_promise2($scope, resolveAfter(0, 1));
};
const $if_content__try = /* @__PURE__ */_._try("#text/0", "<!><!><!><!>", /* over(1), replace, over(1), replace, over(2) */"b%b%c", $try_content__setup);
const $if_content__setup = $scope => {
$if_content__try($scope, {
placeholder: _.attrTag({
content: $placeholder_content($scope)
})
});
};
const $if = /* @__PURE__ */_._if("#text/1", "<!><!><!>", /* over(1), replace, over(2) */"b%c", $if_content__setup);
const $show__closure = /* @__PURE__ */_._closure($await_content__show);
const $show = /* @__PURE__ */_._let("show/2", $scope => {
$if($scope, $scope.show ? 0 : 1);
$show__closure($scope);
});
const $setup__script = _._script("__tests__/template.marko_0", $scope => _._on($scope["#button/0"], "click", function () {
$show($scope, 0);
}));
export function $setup($scope) {
$show($scope, 1);
$setup__script($scope);
}
export default /* @__PURE__ */_._template("__tests__/template.marko", $template, $walks, $setup);

View File

@ -0,0 +1,54 @@
import { resolveAfter } from "../../utils/resolve";
import * as _ from "@marko/runtime-tags/debug/html";
export default _._template("__tests__/template.marko", input => {
const $scope0_id = _._scope_id();
const $show__closures = new Set();
let show = 1;
_._html(`<button></button>${_._el_resume($scope0_id, "#button/0")}<div id=one>Fail</div><div id=two>Fail</div>`);
_._if(() => {
if (show) {
const $scope1_id = _._scope_id();
_._try($scope1_id, "#text/0", _._content_resume("__tests__/template.marko_2_content", () => {
const $scope2_id = _._scope_id();
_._await($scope2_id, "#text/0", resolveAfter(0, 1), () => {
const $scope3_id = _._scope_id();
_._script($scope3_id, "__tests__/template.marko_3_show");
_._html(`${_._escape(show)}${_._el_resume($scope3_id, "#text/0")}`);
_._script($scope3_id, "__tests__/template.marko_3");
_._scope($scope3_id, {
_: _._scope_with_id($scope2_id),
"ClosureSignalIndex:show": 0
}, "__tests__/template.marko", "9:5");
_._resume_branch($scope3_id);
});
_._await($scope2_id, "#text/1", resolveAfter(0, 1), () => {
const $scope5_id = _._scope_id();
_._script($scope5_id, "__tests__/template.marko_5");
_._resume_branch($scope5_id);
}, 0);
_._scope($scope2_id, {
_: _._scope_with_id($scope1_id)
}, "__tests__/template.marko", "7:3");
}, $scope1_id), {
placeholder: _.attrTag({
content: _._content_resume("__tests__/template.marko_4_content", () => {
const $scope4_id = _._scope_id();
_._html("loading...");
}, $scope1_id)
})
});
_._scope($scope1_id, {
_: _._scope_with_id($scope0_id)
}, "__tests__/template.marko", "6:1");
return 0;
}
}, $scope0_id, "#text/1");
_._script($scope0_id, "__tests__/template.marko_0");
_._scope($scope0_id, {
show,
"ClosureScopes:show": $show__closures
}, "__tests__/template.marko", 0, {
show: "2:5"
});
_._resume_branch($scope0_id);
});

View File

@ -0,0 +1,51 @@
# Render
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
loading...
```
# Render FLUSH
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
1
```
# Render
```js
container.querySelector("button").click();
```
```html
<button />
<div
id="one"
>
Pass
</div>
<div
id="two"
>
Pass
</div>
```

View File

@ -0,0 +1,245 @@
# Render
```html
<html>
<head>
<style
m_=""
>
t{display:none}
</style>
</head>
<body>
<button />
<!--M_*1 #button/0-->
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
<!--M_[-->
<!--M_[-->
<!--M_!^3-->
loading...
<!--M_!3-->
<!--M_]2 #text/0 3-->
<!--M_]1 #text/1 2-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
show: 1,
"ClosureScopes:show": new Set
}, _.b = {
_: _.a
}, _.c = {
_: _.b,
"#BranchAccessor": "#text/0"
}], _.c["#PlaceholderContent"] = _._[
"__tests__/template.marko_4_content"
](_.b), _.d),
"__tests__/template.marko_0 1"
];
REORDER_RUNTIME(M._);
M._.w()
</script>
</body>
</html>
```
# Mutations
```
INSERT html/body/#text1
INSERT html/body/#text2
```
# Render FLUSH
```html
<html>
<head>
<style
m_=""
>
t{display:none}
</style>
</head>
<body>
<button />
<!--M_*1 #button/0-->
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
<!--M_[-->
<!--M_[-->
<!--M_[-->
1
<!--M_*5 #text/0-->
<!--M_]3 #text/0 5-->
<!--M_]2 #text/0 3-->
<!--M_]1 #text/1 2-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
show: 1,
"ClosureScopes:show": new Set
}, _.b = {
_: _.a
}, _.c = {
_: _.b,
"#BranchAccessor": "#text/0"
}], _.c["#PlaceholderContent"] = _._[
"__tests__/template.marko_4_content"
](_.b), _.d),
"__tests__/template.marko_0 1"
];
REORDER_RUNTIME(M._);
M._.w()
</script>
<script>
M._.r.push(_ =&gt; (_.e = [1,
{
"#ClosestBranchId": 2,
_: _.c,
"ClosureSignalIndex:show": 0
}]), _ =&gt; (_.f = [
{
"#ClosestBranchId": 2
}]));
M._.j.b = _ =&gt;
{
_.push(
"__tests__/template.marko_3_show 5 __tests__/template.marko_3 5"
)
};
M._.j.c = _ =&gt;
{
_.push(
"__tests__/template.marko_5 6"
)
};
M._.w()
</script>
</body>
</html>
```
# Mutations
```
INSERT t
INSERT html/body/#comment3
INSERT html/body/#text0
INSERT html/body/#comment4
INSERT html/body/#comment5
INSERT t
REMOVE t after html/body/script0
REMOVE t after html/body/script0
REMOVE #text after #comment
REMOVE #comment after html/body/#comment2
REMOVE #comment after html/body/#comment2
INSERT html/body/#comment3, html/body/#text0, html/body/#comment4, html/body/#comment5
INSERT html/body/#text1
INSERT html/body/script1
```
# Render
```js
container.querySelector("button").click();
```
```html
<html>
<head>
<style
m_=""
>
t{display:none}
</style>
</head>
<body>
<button />
<!--M_*1 #button/0-->
<div
id="one"
>
Pass
</div>
<div
id="two"
>
Pass
</div>
<!--M_]1 #text/1 2-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
show: 1,
"ClosureScopes:show": new Set
}, _.b = {
_: _.a
}, _.c = {
_: _.b,
"#BranchAccessor": "#text/0"
}], _.c["#PlaceholderContent"] = _._[
"__tests__/template.marko_4_content"
](_.b), _.d),
"__tests__/template.marko_0 1"
];
REORDER_RUNTIME(M._);
M._.w()
</script>
<script>
M._.r.push(_ =&gt; (_.e = [1,
{
"#ClosestBranchId": 2,
_: _.c,
"ClosureSignalIndex:show": 0
}]), _ =&gt; (_.f = [
{
"#ClosestBranchId": 2
}]));
M._.j.b = _ =&gt;
{
_.push(
"__tests__/template.marko_3_show 5 __tests__/template.marko_3 5"
)
};
M._.j.c = _ =&gt;
{
_.push(
"__tests__/template.marko_5 6"
)
};
M._.w()
</script>
</body>
</html>
```
# Mutations
```
REMOVE html/body/#comment1 after #text
INSERT html/body/#comment1
REMOVE #comment after html/body/#comment1
REMOVE #comment after html/body/#comment1
REMOVE #comment after html/body/#comment1
REMOVE #text after html/body/#comment1
REMOVE #comment after html/body/#comment1
REMOVE #text after html/body/#comment1
REMOVE #comment after html/body/#comment1
REMOVE #text after html/body/#comment1
REMOVE #comment after html/body/#comment1
REMOVE #text after html/body/#comment1
REMOVE #text in html/body/div0
INSERT html/body/div0/#text
REMOVE #text in html/body/div1
INSERT html/body/div1/#text
```

View File

@ -0,0 +1,32 @@
# Render ASYNC
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
loading...
```
# Render End
```html
<button />
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
1
```

View File

@ -0,0 +1,184 @@
# Write
```html
<button></button><!--M_*1 #button/0--><div id=one>Fail</div><div id=two>Fail</div><!--M_[--><!--M_[--><!--M_!^3-->loading...<!--M_!3--><!--M_]2 #text/0 3--><!--M_]1 #text/1 2--><style M_>t{display:none}</style><t M_=3><!--M_#b--><!--M_#c--></t><script>WALKER_RUNTIME("M")("_");M._.r=[_=>(_.d=[0,_.a={show:1,"ClosureScopes:show":new Set},_.b={_:_.a},_.c={_:_.b,"#BranchAccessor":"#text/0"}],_.c["#PlaceholderContent"]=_._["__tests__/template.marko_4_content"](_.b),_.d),"__tests__/template.marko_0 1"];REORDER_RUNTIME(M._);M._.w()</script>
```
# Write
```html
<t M_=b><!--M_[-->1<!--M_*5 #text/0--><!--M_]3 #text/0 5--></t><t M_=c></t><script>M._.r.push(_=>(_.e=[1,{"#ClosestBranchId":2,_:_.c,"ClosureSignalIndex:show":0}]),_=>(_.f=[{"#ClosestBranchId":2}]));M._.j.b=_=>{_.push("__tests__/template.marko_3_show 5 __tests__/template.marko_3 5")};M._.j.c=_=>{_.push("__tests__/template.marko_5 6")};M._.w()</script>
```
# Render ASYNC
```html
<html>
<head>
<style
m_=""
>
t{display:none}
</style>
</head>
<body>
<button />
<!--M_*1 #button/0-->
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
<!--M_[-->
<!--M_[-->
<!--M_!^3-->
loading...
<!--M_!3-->
<!--M_]2 #text/0 3-->
<!--M_]1 #text/1 2-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
show: 1,
"ClosureScopes:show": new Set
}, _.b = {
_: _.a
}, _.c = {
_: _.b,
"#BranchAccessor": "#text/0"
}], _.c["#PlaceholderContent"] = _._[
"__tests__/template.marko_4_content"
](_.b), _.d),
"__tests__/template.marko_0 1"
];
REORDER_RUNTIME(M._);
M._.w()
</script>
</body>
</html>
```
# Mutations
```
INSERT html
INSERT html/head
INSERT html/body
INSERT html/body/button
INSERT html/body/#comment0
INSERT html/body/div0
INSERT html/body/div0/#text
INSERT html/body/div1
INSERT html/body/div1/#text
INSERT html/body/#comment1
INSERT html/body/#comment2
INSERT html/body/#comment3
INSERT html/body/#text
INSERT html/body/#comment4
INSERT html/body/#comment5
INSERT html/body/#comment6
INSERT html/head/style
INSERT html/head/style/#text
INSERT t
INSERT t/#comment0
INSERT t/#comment1
REMOVE html/head/style after html/body/#comment6
INSERT html/head/style
REMOVE t after html/body/#comment6
INSERT html/body/script
```
# Render End
```html
<html>
<head>
<style
m_=""
>
t{display:none}
</style>
</head>
<body>
<button />
<!--M_*1 #button/0-->
<div
id="one"
>
Fail
</div>
<div
id="two"
>
Fail
</div>
<!--M_[-->
<!--M_[-->
<!--M_[-->
1
<!--M_*5 #text/0-->
<!--M_]3 #text/0 5-->
<!--M_]2 #text/0 3-->
<!--M_]1 #text/1 2-->
<script>
WALKER_RUNTIME("M")("_");
M._.r = [_ =&gt; (_.d = [0, _.a = {
show: 1,
"ClosureScopes:show": new Set
}, _.b = {
_: _.a
}, _.c = {
_: _.b,
"#BranchAccessor": "#text/0"
}], _.c["#PlaceholderContent"] = _._[
"__tests__/template.marko_4_content"
](_.b), _.d),
"__tests__/template.marko_0 1"
];
REORDER_RUNTIME(M._);
M._.w()
</script>
<script>
M._.r.push(_ =&gt; (_.e = [1,
{
"#ClosestBranchId": 2,
_: _.c,
"ClosureSignalIndex:show": 0
}]), _ =&gt; (_.f = [
{
"#ClosestBranchId": 2
}]));
M._.j.b = _ =&gt;
{
_.push(
"__tests__/template.marko_3_show 5 __tests__/template.marko_3 5"
)
};
M._.j.c = _ =&gt;
{
_.push(
"__tests__/template.marko_5 6"
)
};
M._.w()
</script>
</body>
</html>
```
# Mutations
```
INSERT t
INSERT html/body/#comment3
INSERT html/body/#text
INSERT html/body/#comment4
INSERT html/body/#comment5
INSERT t
REMOVE t after html/body/script0
REMOVE t after html/body/script0
REMOVE #text after #comment
REMOVE #comment after html/body/#comment2
REMOVE #comment after html/body/#comment2
INSERT html/body/#comment3, html/body/#text, html/body/#comment4, html/body/#comment5
INSERT html/body/script1
```

View File

@ -0,0 +1,13 @@
import { resolveAfter } from "../../utils/resolve";
let/show=1
button onClick() { show = 0 }
div#one -- Fail
div#two -- Fail
if=show
try
@placeholder -- loading...
await=resolveAfter(0, 1)
-- ${show}
script -- $signal.onabort = () => document.querySelector('#one')!.textContent = "Pass"
await=resolveAfter(0, 1)
script -- $signal.onabort = () => document.querySelector('#two')!.textContent = "Pass"

View File

@ -0,0 +1,7 @@
import { flush, wait } from "../../utils/resolve";
export const steps = [{}, flush, wait, click];
function click(container: Element) {
container.querySelector("button")!.click();
}

View File

@ -33,14 +33,8 @@ export function createBranch(
parentNode: ParentNode,
) {
const branch = createScope($global) as BranchScope;
const parentBranch = parentScope?.[AccessorProp.ClosestBranch];
branch[AccessorProp.Owner] = (renderer as Renderer).___owner || parentScope;
branch[AccessorProp.ClosestBranch] = branch;
if (parentBranch) {
branch[AccessorProp.ParentBranch] = parentBranch;
(parentBranch[AccessorProp.BranchScopes] ||= new Set()).add(branch);
}
setParentBranch(branch, parentScope?.[AccessorProp.ClosestBranch]);
if (MARKO_DEBUG) {
branch[AccessorProp.Renderer] = renderer;
@ -54,6 +48,17 @@ export function createBranch(
return branch;
}
export function setParentBranch(
branch: BranchScope,
parentBranch: BranchScope | undefined,
) {
if (parentBranch) {
branch[AccessorProp.ParentBranch] = parentBranch;
(parentBranch[AccessorProp.BranchScopes] ||= new Set()).add(branch);
}
branch[AccessorProp.ClosestBranch] = branch;
}
export function createAndSetupBranch(
$global: Scope[AccessorProp.Global],
renderer: Renderer,

View File

@ -11,6 +11,7 @@ import {
type Scope,
} from "../common/types";
import { runEffects } from "./queue";
import { setParentBranch } from "./renderer";
import type { Signal } from "./signals";
import { getDebugKey } from "./walker";
@ -123,7 +124,7 @@ export function init(runtimeId = DEFAULT_RUNTIME_ID) {
[AccessorProp.Id]: branchId,
} as BranchScope) as BranchScope),
);
branch[AccessorProp.ClosestBranch] = branch;
setParentBranch(branch, branch[AccessorProp.ClosestBranch]);
if (
(branch[AccessorProp.AwaitCounter] = render.p?.[branchId])
) {
@ -161,14 +162,8 @@ export function init(runtimeId = DEFAULT_RUNTIME_ID) {
: parent.insertBefore(new Text(), visit);
}
// TODO: when branch is part of a separate flush than it's parent, we
// may need to set branch parent to accessor when visitScope is a branch
while (i && orphanBranches[--i][AccessorProp.Id] > branchId) {
orphanBranches[i][AccessorProp.ParentBranch] = branch;
(branch[AccessorProp.BranchScopes] ||= new Set()).add(
orphanBranches.pop()!,
);
setParentBranch(orphanBranches.pop()!, branch);
}
nextToken(/* read optional next branchId */);