marko 6.1.23 → 6.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,6 +9,7 @@ export declare enum AccessorPrefix {
9
9
  DynamicHTMLLastChild = "H",
10
10
  EventAttributes = "I",
11
11
  Getter = "J",
12
+ KeyedScopes = "O",
12
13
  Lifecycle = "K",
13
14
  Promise = "L",
14
15
  TagVariableChange = "M"
@@ -65,6 +66,9 @@ export declare enum ClosureSignalProp {
65
66
  SignalIndexAccessor = "b",
66
67
  Index = "c"
67
68
  }
69
+ export declare enum KeyedScopesProp {
70
+ PreviousKey = "_"
71
+ }
68
72
  export declare enum LoadSignalValue {
69
73
  Value = "a",
70
74
  Signal = "b"
@@ -9,6 +9,7 @@ export declare enum AccessorPrefix {
9
9
  DynamicHTMLLastChild = "DynamicHTMLLastChild:",
10
10
  EventAttributes = "EventAttributes:",
11
11
  Getter = "Getter:",
12
+ KeyedScopes = "KeyedScopes:",
12
13
  Lifecycle = "Lifecycle:",
13
14
  Promise = "Promise:",
14
15
  TagVariableChange = "TagVariableChange:"
@@ -65,6 +66,9 @@ export declare enum ClosureSignalProp {
65
66
  SignalIndexAccessor = "signalIndexAccessor",
66
67
  Index = "index"
67
68
  }
69
+ export declare enum KeyedScopesProp {
70
+ PreviousKey = "PreviousKey:"
71
+ }
68
72
  export declare enum LoadSignalValue {
69
73
  Value = "value",
70
74
  Signal = "signal"
@@ -41,7 +41,7 @@ export interface AwaitCounter {
41
41
  i: number;
42
42
  c: () => void | 1;
43
43
  }
44
- export { AccessorPrefix, AccessorProp, ClosureSignalProp, PendingRenderProp, RendererProp, } from "./accessor.debug";
44
+ export { AccessorPrefix, AccessorProp, ClosureSignalProp, KeyedScopesProp, PendingRenderProp, RendererProp, } from "./accessor.debug";
45
45
  export declare enum NodeType {
46
46
  Element = 1,
47
47
  Text = 3,
package/dist/debug/dom.js CHANGED
@@ -436,6 +436,44 @@ function _for_closure(ownerLoopNodeAccessor, fn) {
436
436
  ownerSignal._ = fn;
437
437
  return ownerSignal;
438
438
  }
439
+ function _for_selector(ownerLoopNodeAccessor, ownerValueAccessor, keyValueAccessor, fn) {
440
+ const scopeAccessor = "BranchScopes:" + ownerLoopNodeAccessor;
441
+ const mapAccessor = "KeyedScopes:" + ownerLoopNodeAccessor;
442
+ const prevKeyProp = `PreviousKey:${ownerValueAccessor}`;
443
+ const ownerSignal = (ownerScope) => {
444
+ const scopes = toArray(ownerScope[scopeAccessor]);
445
+ if (ownerScope["#Gen"] < runId && scopes.length) {
446
+ const nextKey = ownerScope[ownerValueAccessor];
447
+ queueRender(ownerScope, () => {
448
+ const map = keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor);
449
+ if (map && prevKeyProp in map) {
450
+ const prevScope = map.get(map[prevKeyProp]);
451
+ const nextScope = map.get(nextKey);
452
+ if (prevScope !== nextScope) {
453
+ runLiveBranch(prevScope, fn);
454
+ runLiveBranch(nextScope, fn);
455
+ }
456
+ } else for (const scope of toArray(ownerScope[scopeAccessor])) runLiveBranch(scope, fn);
457
+ if (map) map[prevKeyProp] = nextKey;
458
+ }, -1, 0, scopes[0]["#Id"]);
459
+ }
460
+ };
461
+ ownerSignal._ = fn;
462
+ return ownerSignal;
463
+ }
464
+ function keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor) {
465
+ const map = ownerScope[mapAccessor] ||= /* @__PURE__ */ new Map();
466
+ if (!map.size) for (const scope of toArray(ownerScope[scopeAccessor])) {
467
+ const key = scope["#LoopKey"] ?? scope[keyValueAccessor];
468
+ if (key === void 0) return ownerScope[mapAccessor] = null;
469
+ scope["#LoopKey"] = key;
470
+ map.set(key, scope);
471
+ }
472
+ return map;
473
+ }
474
+ function runLiveBranch(scope, fn) {
475
+ if (scope && scope["#Gen"] > 0 && scope["#Gen"] < runId) fn(scope);
476
+ }
439
477
  function _if_closure(ownerConditionalNodeAccessor, branch, fn) {
440
478
  const scopeAccessor = "BranchScopes:" + ownerConditionalNodeAccessor;
441
479
  const branchAccessor = "ConditionalRenderer:" + ownerConditionalNodeAccessor;
@@ -1597,12 +1635,14 @@ const _for_until = /* @__PURE__ */ loop(([until, from, step, by = byFirstArg], c
1597
1635
  function loop(forEach) {
1598
1636
  return (nodeAccessor, template, walks, setup, params) => {
1599
1637
  const scopesAccessor = "BranchScopes:" + nodeAccessor;
1638
+ const keyedScopesAccessor = "KeyedScopes:" + nodeAccessor;
1600
1639
  const renderer = _content("", template, walks, setup)();
1601
1640
  enableBranches();
1602
1641
  return (scope, value) => {
1603
1642
  const referenceNode = scope[nodeAccessor];
1604
1643
  const oldScopes = toArray(scope[scopesAccessor]);
1605
1644
  const newScopes = scope[scopesAccessor] = [];
1645
+ scope[keyedScopesAccessor] = null;
1606
1646
  const oldLen = oldScopes.length;
1607
1647
  const parentNode = referenceNode.nodeType > 1 ? referenceNode.parentNode || oldScopes[0]?.["#StartNode"].parentNode : referenceNode;
1608
1648
  let oldScopesByKey;
@@ -2186,6 +2226,7 @@ exports._enable_catch = _enable_catch;
2186
2226
  exports._for_closure = _for_closure;
2187
2227
  exports._for_in = _for_in;
2188
2228
  exports._for_of = _for_of;
2229
+ exports._for_selector = _for_selector;
2189
2230
  exports._for_to = _for_to;
2190
2231
  exports._for_until = _for_until;
2191
2232
  exports._hoist = _hoist;
@@ -434,6 +434,44 @@ function _for_closure(ownerLoopNodeAccessor, fn) {
434
434
  ownerSignal._ = fn;
435
435
  return ownerSignal;
436
436
  }
437
+ function _for_selector(ownerLoopNodeAccessor, ownerValueAccessor, keyValueAccessor, fn) {
438
+ const scopeAccessor = "BranchScopes:" + ownerLoopNodeAccessor;
439
+ const mapAccessor = "KeyedScopes:" + ownerLoopNodeAccessor;
440
+ const prevKeyProp = `PreviousKey:${ownerValueAccessor}`;
441
+ const ownerSignal = (ownerScope) => {
442
+ const scopes = toArray(ownerScope[scopeAccessor]);
443
+ if (ownerScope["#Gen"] < runId && scopes.length) {
444
+ const nextKey = ownerScope[ownerValueAccessor];
445
+ queueRender(ownerScope, () => {
446
+ const map = keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor);
447
+ if (map && prevKeyProp in map) {
448
+ const prevScope = map.get(map[prevKeyProp]);
449
+ const nextScope = map.get(nextKey);
450
+ if (prevScope !== nextScope) {
451
+ runLiveBranch(prevScope, fn);
452
+ runLiveBranch(nextScope, fn);
453
+ }
454
+ } else for (const scope of toArray(ownerScope[scopeAccessor])) runLiveBranch(scope, fn);
455
+ if (map) map[prevKeyProp] = nextKey;
456
+ }, -1, 0, scopes[0]["#Id"]);
457
+ }
458
+ };
459
+ ownerSignal._ = fn;
460
+ return ownerSignal;
461
+ }
462
+ function keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor) {
463
+ const map = ownerScope[mapAccessor] ||= /* @__PURE__ */ new Map();
464
+ if (!map.size) for (const scope of toArray(ownerScope[scopeAccessor])) {
465
+ const key = scope["#LoopKey"] ?? scope[keyValueAccessor];
466
+ if (key === void 0) return ownerScope[mapAccessor] = null;
467
+ scope["#LoopKey"] = key;
468
+ map.set(key, scope);
469
+ }
470
+ return map;
471
+ }
472
+ function runLiveBranch(scope, fn) {
473
+ if (scope && scope["#Gen"] > 0 && scope["#Gen"] < runId) fn(scope);
474
+ }
437
475
  function _if_closure(ownerConditionalNodeAccessor, branch, fn) {
438
476
  const scopeAccessor = "BranchScopes:" + ownerConditionalNodeAccessor;
439
477
  const branchAccessor = "ConditionalRenderer:" + ownerConditionalNodeAccessor;
@@ -1595,12 +1633,14 @@ const _for_until = /* @__PURE__ */ loop(([until, from, step, by = byFirstArg], c
1595
1633
  function loop(forEach) {
1596
1634
  return (nodeAccessor, template, walks, setup, params) => {
1597
1635
  const scopesAccessor = "BranchScopes:" + nodeAccessor;
1636
+ const keyedScopesAccessor = "KeyedScopes:" + nodeAccessor;
1598
1637
  const renderer = _content("", template, walks, setup)();
1599
1638
  enableBranches();
1600
1639
  return (scope, value) => {
1601
1640
  const referenceNode = scope[nodeAccessor];
1602
1641
  const oldScopes = toArray(scope[scopesAccessor]);
1603
1642
  const newScopes = scope[scopesAccessor] = [];
1643
+ scope[keyedScopesAccessor] = null;
1604
1644
  const oldLen = oldScopes.length;
1605
1645
  const parentNode = referenceNode.nodeType > 1 ? referenceNode.parentNode || oldScopes[0]?.["#StartNode"].parentNode : referenceNode;
1606
1646
  let oldScopesByKey;
@@ -2122,4 +2162,4 @@ function getSelectorOrResolve(selector, resolve) {
2122
2162
  return document.querySelector(selector) || (console.warn(`A lazy load trigger could not find an element matching "${selector}". The module was loaded immediately.`), resolve());
2123
2163
  }
2124
2164
  //#endregion
2125
- export { $signal, $signalReset, _assert_hoist, _assert_init, _attr, _attr_class, _attr_class_item, _attr_class_items, _attr_content, _attr_details_or_dialog_open as _attr_details_open, _attr_details_or_dialog_open as _attr_dialog_open, _attr_details_or_dialog_open_default as _attr_details_open_default, _attr_details_or_dialog_open_default as _attr_dialog_open_default, _attr_details_or_dialog_open_script as _attr_details_open_script, _attr_details_or_dialog_open_script as _attr_dialog_open_script, _attr_input_checked, _attr_input_checkedValue, _attr_input_checkedValue_default, _attr_input_checkedValue_script, _attr_input_checked_default, _attr_input_checked_script, _attr_input_value, _attr_input_value as _attr_textarea_value, _attr_input_value_default, _attr_input_value_default as _attr_textarea_value_default, _attr_input_value_script, _attr_input_value_script as _attr_textarea_value_script, _attr_nonce, _attr_select_value, _attr_select_value_default, _attr_select_value_script, _attr_style, _attr_style_item, _attr_style_items, _attrs, _attrs_content, _attrs_partial, _attrs_partial_content, _attrs_script, _await_content, _await_promise, _call, _child_setup, _closure, _closure_get, _const, _content, _content_closures, _content_resume, _dynamic_tag, _dynamic_tag_content, _el, _el_read, _enable_catch, _for_closure, _for_in, _for_of, _for_to, _for_until, _hoist, _hoist_resume, _html, _id, _if, _if_closure, _let, _let_change, _lifecycle, _load_event_trigger, _load_idle_trigger, _load_media_trigger, _load_race_trigger, _load_setup, _load_signal, _load_template, _load_visible_trigger, _on, _or, _resume, _resume_dynamic_tag, _return, _return_change, _script, _template, _text, _text_content, _to_text, _try, _var, _var_change, _var_resume, attrTag, attrTags, compat, forIn, forOf, forTo, forUntil, init, initEmbedded, ready, run };
2165
+ export { $signal, $signalReset, _assert_hoist, _assert_init, _attr, _attr_class, _attr_class_item, _attr_class_items, _attr_content, _attr_details_or_dialog_open as _attr_details_open, _attr_details_or_dialog_open as _attr_dialog_open, _attr_details_or_dialog_open_default as _attr_details_open_default, _attr_details_or_dialog_open_default as _attr_dialog_open_default, _attr_details_or_dialog_open_script as _attr_details_open_script, _attr_details_or_dialog_open_script as _attr_dialog_open_script, _attr_input_checked, _attr_input_checkedValue, _attr_input_checkedValue_default, _attr_input_checkedValue_script, _attr_input_checked_default, _attr_input_checked_script, _attr_input_value, _attr_input_value as _attr_textarea_value, _attr_input_value_default, _attr_input_value_default as _attr_textarea_value_default, _attr_input_value_script, _attr_input_value_script as _attr_textarea_value_script, _attr_nonce, _attr_select_value, _attr_select_value_default, _attr_select_value_script, _attr_style, _attr_style_item, _attr_style_items, _attrs, _attrs_content, _attrs_partial, _attrs_partial_content, _attrs_script, _await_content, _await_promise, _call, _child_setup, _closure, _closure_get, _const, _content, _content_closures, _content_resume, _dynamic_tag, _dynamic_tag_content, _el, _el_read, _enable_catch, _for_closure, _for_in, _for_of, _for_selector, _for_to, _for_until, _hoist, _hoist_resume, _html, _id, _if, _if_closure, _let, _let_change, _lifecycle, _load_event_trigger, _load_idle_trigger, _load_media_trigger, _load_race_trigger, _load_setup, _load_signal, _load_template, _load_visible_trigger, _on, _or, _resume, _resume_dynamic_tag, _return, _return_change, _script, _template, _text, _text_content, _to_text, _try, _var, _var_change, _var_resume, attrTag, attrTags, compat, forIn, forOf, forTo, forUntil, init, initEmbedded, ready, run };
@@ -6,6 +6,7 @@ export declare function _let_change<T>(id: EncodedAccessor, fn?: SignalFn): (sco
6
6
  export declare function _const<T>(valueAccessor: EncodedAccessor, fn?: SignalFn): Signal<T>;
7
7
  export declare function _or(id: number, fn: SignalFn, defaultPending?: number, scopeIdAccessor?: EncodedAccessor): Signal<never>;
8
8
  export declare function _for_closure(ownerLoopNodeAccessor: EncodedAccessor, fn: SignalFn): SignalFn;
9
+ export declare function _for_selector(ownerLoopNodeAccessor: EncodedAccessor, ownerValueAccessor: EncodedAccessor, keyValueAccessor: EncodedAccessor, fn: SignalFn): SignalFn;
9
10
  export declare function _if_closure(ownerConditionalNodeAccessor: EncodedAccessor, branch: number, fn: SignalFn): SignalFn;
10
11
  export declare function subscribeToScopeSet(ownerScope: Scope, accessor: Accessor, scope: Scope): void;
11
12
  export declare function _closure(...closureSignals: ReturnType<typeof _closure_get>[]): (scope: Scope) => void;
package/dist/dom.d.ts CHANGED
@@ -13,5 +13,5 @@ export { _enable_catch, run } from "./dom/queue";
13
13
  export { _content, _content_closures, _content_resume } from "./dom/renderer";
14
14
  export { _el, _resume, _var_resume, init, initEmbedded, ready, } from "./dom/resume";
15
15
  export { _assert_init } from "./dom/scope";
16
- export { _child_setup, _closure, _closure_get, _const, _el_read, _for_closure, _hoist, _hoist_resume, _id, _if_closure, _let, _let_change, _or, _return, _return_change, _script, _var, _var_change, } from "./dom/signals";
16
+ export { _child_setup, _closure, _closure_get, _const, _el_read, _for_closure, _for_selector, _hoist, _hoist_resume, _id, _if_closure, _let, _let_change, _or, _return, _return_change, _script, _var, _var_change, } from "./dom/signals";
17
17
  export { _template } from "./dom/template";
package/dist/dom.js CHANGED
@@ -303,6 +303,36 @@ function _for_closure(ownerLoopNodeAccessor, fn) {
303
303
  };
304
304
  return ownerSignal._ = fn, ownerSignal;
305
305
  }
306
+ function _for_selector(ownerLoopNodeAccessor, ownerValueAccessor, keyValueAccessor, fn) {
307
+ ownerLoopNodeAccessor = decodeAccessor(ownerLoopNodeAccessor), ownerValueAccessor = decodeAccessor(ownerValueAccessor), keyValueAccessor !== "M" && (keyValueAccessor = decodeAccessor(keyValueAccessor));
308
+ let scopeAccessor = "A" + ownerLoopNodeAccessor, mapAccessor = "O" + ownerLoopNodeAccessor, prevKeyProp = `_${ownerValueAccessor}`, ownerSignal = (ownerScope) => {
309
+ let scopes = toArray(ownerScope[scopeAccessor]);
310
+ if (ownerScope.H < runId && scopes.length) {
311
+ let nextKey = ownerScope[ownerValueAccessor];
312
+ queueRender(ownerScope, () => {
313
+ let map = keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor);
314
+ if (map && prevKeyProp in map) {
315
+ let prevScope = map.get(map[prevKeyProp]), nextScope = map.get(nextKey);
316
+ prevScope !== nextScope && (runLiveBranch(prevScope, fn), runLiveBranch(nextScope, fn));
317
+ } else for (let scope of toArray(ownerScope[scopeAccessor])) runLiveBranch(scope, fn);
318
+ map && (map[prevKeyProp] = nextKey);
319
+ }, -1, 0, scopes[0].L);
320
+ }
321
+ };
322
+ return ownerSignal._ = fn, ownerSignal;
323
+ }
324
+ function keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor) {
325
+ let map = ownerScope[mapAccessor] ||= /* @__PURE__ */ new Map();
326
+ if (!map.size) for (let scope of toArray(ownerScope[scopeAccessor])) {
327
+ let key = scope.M ?? scope[keyValueAccessor];
328
+ if (key === void 0) return ownerScope[mapAccessor] = null;
329
+ scope.M = key, map.set(key, scope);
330
+ }
331
+ return map;
332
+ }
333
+ function runLiveBranch(scope, fn) {
334
+ scope && scope.H > 0 && scope.H < runId && fn(scope);
335
+ }
306
336
  function _if_closure(ownerConditionalNodeAccessor, branch, fn) {
307
337
  ownerConditionalNodeAccessor = decodeAccessor(ownerConditionalNodeAccessor);
308
338
  let scopeAccessor = "A" + ownerConditionalNodeAccessor, branchAccessor = "D" + ownerConditionalNodeAccessor, ownerSignal = (scope) => {
@@ -1006,9 +1036,11 @@ function setConditionalRenderer(scope, nodeAccessor, newRenderer, createBranch)
1006
1036
  function loop(forEach) {
1007
1037
  return (nodeAccessor, template, walks, setup, params) => {
1008
1038
  nodeAccessor = decodeAccessor(nodeAccessor);
1009
- let scopesAccessor = "A" + nodeAccessor, renderer = _content("", template, walks, setup)();
1039
+ let scopesAccessor = "A" + nodeAccessor, keyedScopesAccessor = "O" + nodeAccessor, renderer = _content("", template, walks, setup)();
1010
1040
  return enableBranches(), (scope, value) => {
1011
- let referenceNode = scope[nodeAccessor], oldScopes = toArray(scope[scopesAccessor]), newScopes = scope[scopesAccessor] = [], oldLen = oldScopes.length, parentNode = referenceNode.nodeType > 1 ? referenceNode.parentNode || oldScopes[0]?.S.parentNode : referenceNode, oldScopesByKey, hasPotentialMoves;
1041
+ let referenceNode = scope[nodeAccessor], oldScopes = toArray(scope[scopesAccessor]), newScopes = scope[scopesAccessor] = [];
1042
+ scope[keyedScopesAccessor] = null;
1043
+ let oldLen = oldScopes.length, parentNode = referenceNode.nodeType > 1 ? referenceNode.parentNode || oldScopes[0]?.S.parentNode : referenceNode, oldScopesByKey, hasPotentialMoves;
1012
1044
  forEach(value, (key, args) => {
1013
1045
  let branch = oldLen && (oldScopesByKey ||= oldScopes.reduce((map, scope, i) => map.set(scope.M ?? i, scope), /* @__PURE__ */ new Map())).get(key);
1014
1046
  branch ? hasPotentialMoves = oldScopesByKey.delete(key) : branch = createAndSetupBranch(scope.$, renderer, scope, parentNode), branch.M = key, newScopes.push(branch), params?.(branch, args);
@@ -1283,4 +1315,4 @@ exports.$signal = $signal, exports.$signalReset = $signalReset, exports._assert_
1283
1315
  get: function() {
1284
1316
  return _dynamic_tag;
1285
1317
  }
1286
- }), exports._dynamic_tag_content = _dynamic_tag_content, exports._el = _el, exports._el_read = _el_read, exports._enable_catch = _enable_catch, exports._for_closure = _for_closure, exports._for_in = _for_in, exports._for_of = _for_of, exports._for_to = _for_to, exports._for_until = _for_until, exports._hoist = _hoist, exports._hoist_resume = _hoist_resume, exports._html = _html, exports._id = _id, exports._if = _if, exports._if_closure = _if_closure, exports._let = _let, exports._let_change = _let_change, exports._lifecycle = _lifecycle, exports._load_event_trigger = _load_event_trigger, exports._load_idle_trigger = _load_idle_trigger, exports._load_media_trigger = _load_media_trigger, exports._load_race_trigger = _load_race_trigger, exports._load_setup = _load_setup, exports._load_signal = _load_signal, exports._load_template = _load_template, exports._load_visible_trigger = _load_visible_trigger, exports._on = _on, exports._or = _or, exports._resume = _resume, exports._resume_dynamic_tag = _resume_dynamic_tag, exports._return = _return, exports._return_change = _return_change, exports._script = _script, exports._template = _template, exports._text = _text, exports._text_content = _text_content, exports._to_text = _to_text, exports._try = _try, exports._var = _var, exports._var_change = _var_change, exports._var_resume = _var_resume, exports.attrTag = attrTag, exports.attrTags = attrTags, exports.compat = compat, exports.forIn = forIn, exports.forOf = forOf, exports.forTo = forTo, exports.forUntil = forUntil, exports.init = init, exports.initEmbedded = initEmbedded, exports.ready = ready, exports.run = run;
1318
+ }), exports._dynamic_tag_content = _dynamic_tag_content, exports._el = _el, exports._el_read = _el_read, exports._enable_catch = _enable_catch, exports._for_closure = _for_closure, exports._for_in = _for_in, exports._for_of = _for_of, exports._for_selector = _for_selector, exports._for_to = _for_to, exports._for_until = _for_until, exports._hoist = _hoist, exports._hoist_resume = _hoist_resume, exports._html = _html, exports._id = _id, exports._if = _if, exports._if_closure = _if_closure, exports._let = _let, exports._let_change = _let_change, exports._lifecycle = _lifecycle, exports._load_event_trigger = _load_event_trigger, exports._load_idle_trigger = _load_idle_trigger, exports._load_media_trigger = _load_media_trigger, exports._load_race_trigger = _load_race_trigger, exports._load_setup = _load_setup, exports._load_signal = _load_signal, exports._load_template = _load_template, exports._load_visible_trigger = _load_visible_trigger, exports._on = _on, exports._or = _or, exports._resume = _resume, exports._resume_dynamic_tag = _resume_dynamic_tag, exports._return = _return, exports._return_change = _return_change, exports._script = _script, exports._template = _template, exports._text = _text, exports._text_content = _text_content, exports._to_text = _to_text, exports._try = _try, exports._var = _var, exports._var_change = _var_change, exports._var_resume = _var_resume, exports.attrTag = attrTag, exports.attrTags = attrTags, exports.compat = compat, exports.forIn = forIn, exports.forOf = forOf, exports.forTo = forTo, exports.forUntil = forUntil, exports.init = init, exports.initEmbedded = initEmbedded, exports.ready = ready, exports.run = run;
package/dist/dom.mjs CHANGED
@@ -302,6 +302,36 @@ function _for_closure(ownerLoopNodeAccessor, fn) {
302
302
  };
303
303
  return ownerSignal._ = fn, ownerSignal;
304
304
  }
305
+ function _for_selector(ownerLoopNodeAccessor, ownerValueAccessor, keyValueAccessor, fn) {
306
+ ownerLoopNodeAccessor = decodeAccessor(ownerLoopNodeAccessor), ownerValueAccessor = decodeAccessor(ownerValueAccessor), keyValueAccessor !== "M" && (keyValueAccessor = decodeAccessor(keyValueAccessor));
307
+ let scopeAccessor = "A" + ownerLoopNodeAccessor, mapAccessor = "O" + ownerLoopNodeAccessor, prevKeyProp = `_${ownerValueAccessor}`, ownerSignal = (ownerScope) => {
308
+ let scopes = toArray(ownerScope[scopeAccessor]);
309
+ if (ownerScope.H < runId && scopes.length) {
310
+ let nextKey = ownerScope[ownerValueAccessor];
311
+ queueRender(ownerScope, () => {
312
+ let map = keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor);
313
+ if (map && prevKeyProp in map) {
314
+ let prevScope = map.get(map[prevKeyProp]), nextScope = map.get(nextKey);
315
+ prevScope !== nextScope && (runLiveBranch(prevScope, fn), runLiveBranch(nextScope, fn));
316
+ } else for (let scope of toArray(ownerScope[scopeAccessor])) runLiveBranch(scope, fn);
317
+ map && (map[prevKeyProp] = nextKey);
318
+ }, -1, 0, scopes[0].L);
319
+ }
320
+ };
321
+ return ownerSignal._ = fn, ownerSignal;
322
+ }
323
+ function keyedScopes(ownerScope, scopeAccessor, mapAccessor, keyValueAccessor) {
324
+ let map = ownerScope[mapAccessor] ||= /* @__PURE__ */ new Map();
325
+ if (!map.size) for (let scope of toArray(ownerScope[scopeAccessor])) {
326
+ let key = scope.M ?? scope[keyValueAccessor];
327
+ if (key === void 0) return ownerScope[mapAccessor] = null;
328
+ scope.M = key, map.set(key, scope);
329
+ }
330
+ return map;
331
+ }
332
+ function runLiveBranch(scope, fn) {
333
+ scope && scope.H > 0 && scope.H < runId && fn(scope);
334
+ }
305
335
  function _if_closure(ownerConditionalNodeAccessor, branch, fn) {
306
336
  ownerConditionalNodeAccessor = decodeAccessor(ownerConditionalNodeAccessor);
307
337
  let scopeAccessor = "A" + ownerConditionalNodeAccessor, branchAccessor = "D" + ownerConditionalNodeAccessor, ownerSignal = (scope) => {
@@ -1005,9 +1035,11 @@ function setConditionalRenderer(scope, nodeAccessor, newRenderer, createBranch)
1005
1035
  function loop(forEach) {
1006
1036
  return (nodeAccessor, template, walks, setup, params) => {
1007
1037
  nodeAccessor = decodeAccessor(nodeAccessor);
1008
- let scopesAccessor = "A" + nodeAccessor, renderer = _content("", template, walks, setup)();
1038
+ let scopesAccessor = "A" + nodeAccessor, keyedScopesAccessor = "O" + nodeAccessor, renderer = _content("", template, walks, setup)();
1009
1039
  return enableBranches(), (scope, value) => {
1010
- let referenceNode = scope[nodeAccessor], oldScopes = toArray(scope[scopesAccessor]), newScopes = scope[scopesAccessor] = [], oldLen = oldScopes.length, parentNode = referenceNode.nodeType > 1 ? referenceNode.parentNode || oldScopes[0]?.S.parentNode : referenceNode, oldScopesByKey, hasPotentialMoves;
1040
+ let referenceNode = scope[nodeAccessor], oldScopes = toArray(scope[scopesAccessor]), newScopes = scope[scopesAccessor] = [];
1041
+ scope[keyedScopesAccessor] = null;
1042
+ let oldLen = oldScopes.length, parentNode = referenceNode.nodeType > 1 ? referenceNode.parentNode || oldScopes[0]?.S.parentNode : referenceNode, oldScopesByKey, hasPotentialMoves;
1011
1043
  forEach(value, (key, args) => {
1012
1044
  let branch = oldLen && (oldScopesByKey ||= oldScopes.reduce((map, scope, i) => map.set(scope.M ?? i, scope), /* @__PURE__ */ new Map())).get(key);
1013
1045
  branch ? hasPotentialMoves = oldScopesByKey.delete(key) : branch = createAndSetupBranch(scope.$, renderer, scope, parentNode), branch.M = key, newScopes.push(branch), params?.(branch, args);
@@ -1278,4 +1310,4 @@ function getSelectorOrResolve(selector, resolve) {
1278
1310
  return document.querySelector(selector) || resolve();
1279
1311
  }
1280
1312
  //#endregion
1281
- export { $signal, $signalReset, _assert_hoist, _assert_init, _attr, _attr_class, _attr_class_item, _attr_class_items, _attr_content, _attr_details_or_dialog_open as _attr_details_open, _attr_details_or_dialog_open as _attr_dialog_open, _attr_details_or_dialog_open_default as _attr_details_open_default, _attr_details_or_dialog_open_default as _attr_dialog_open_default, _attr_details_or_dialog_open_script as _attr_details_open_script, _attr_details_or_dialog_open_script as _attr_dialog_open_script, _attr_input_checked, _attr_input_checkedValue, _attr_input_checkedValue_default, _attr_input_checkedValue_script, _attr_input_checked_default, _attr_input_checked_script, _attr_input_value, _attr_input_value as _attr_textarea_value, _attr_input_value_default, _attr_input_value_default as _attr_textarea_value_default, _attr_input_value_script, _attr_input_value_script as _attr_textarea_value_script, _attr_nonce, _attr_select_value, _attr_select_value_default, _attr_select_value_script, _attr_style, _attr_style_item, _attr_style_items, _attrs, _attrs_content, _attrs_partial, _attrs_partial_content, _attrs_script, _await_content, _await_promise, _call, _child_setup, _closure, _closure_get, _const, _content, _content_closures, _content_resume, _dynamic_tag, _dynamic_tag_content, _el, _el_read, _enable_catch, _for_closure, _for_in, _for_of, _for_to, _for_until, _hoist, _hoist_resume, _html, _id, _if, _if_closure, _let, _let_change, _lifecycle, _load_event_trigger, _load_idle_trigger, _load_media_trigger, _load_race_trigger, _load_setup, _load_signal, _load_template, _load_visible_trigger, _on, _or, _resume, _resume_dynamic_tag, _return, _return_change, _script, _template, _text, _text_content, _to_text, _try, _var, _var_change, _var_resume, attrTag, attrTags, compat, forIn, forOf, forTo, forUntil, init, initEmbedded, ready, run };
1313
+ export { $signal, $signalReset, _assert_hoist, _assert_init, _attr, _attr_class, _attr_class_item, _attr_class_items, _attr_content, _attr_details_or_dialog_open as _attr_details_open, _attr_details_or_dialog_open as _attr_dialog_open, _attr_details_or_dialog_open_default as _attr_details_open_default, _attr_details_or_dialog_open_default as _attr_dialog_open_default, _attr_details_or_dialog_open_script as _attr_details_open_script, _attr_details_or_dialog_open_script as _attr_dialog_open_script, _attr_input_checked, _attr_input_checkedValue, _attr_input_checkedValue_default, _attr_input_checkedValue_script, _attr_input_checked_default, _attr_input_checked_script, _attr_input_value, _attr_input_value as _attr_textarea_value, _attr_input_value_default, _attr_input_value_default as _attr_textarea_value_default, _attr_input_value_script, _attr_input_value_script as _attr_textarea_value_script, _attr_nonce, _attr_select_value, _attr_select_value_default, _attr_select_value_script, _attr_style, _attr_style_item, _attr_style_items, _attrs, _attrs_content, _attrs_partial, _attrs_partial_content, _attrs_script, _await_content, _await_promise, _call, _child_setup, _closure, _closure_get, _const, _content, _content_closures, _content_resume, _dynamic_tag, _dynamic_tag_content, _el, _el_read, _enable_catch, _for_closure, _for_in, _for_of, _for_selector, _for_to, _for_until, _hoist, _hoist_resume, _html, _id, _if, _if_closure, _let, _let_change, _lifecycle, _load_event_trigger, _load_idle_trigger, _load_media_trigger, _load_race_trigger, _load_setup, _load_signal, _load_template, _load_visible_trigger, _on, _or, _resume, _resume_dynamic_tag, _return, _return_change, _script, _template, _text, _text_content, _to_text, _try, _var, _var_change, _var_resume, attrTag, attrTags, compat, forIn, forOf, forTo, forUntil, init, initEmbedded, ready, run };
@@ -96,6 +96,7 @@ let AccessorPrefix$1 = /* @__PURE__ */ function(AccessorPrefix) {
96
96
  AccessorPrefix["DynamicHTMLLastChild"] = "DynamicHTMLLastChild:";
97
97
  AccessorPrefix["EventAttributes"] = "EventAttributes:";
98
98
  AccessorPrefix["Getter"] = "Getter:";
99
+ AccessorPrefix["KeyedScopes"] = "KeyedScopes:";
99
100
  AccessorPrefix["Lifecycle"] = "Lifecycle:";
100
101
  AccessorPrefix["Promise"] = "Promise:";
101
102
  AccessorPrefix["TagVariableChange"] = "TagVariableChange:";
@@ -1073,6 +1074,7 @@ let AccessorPrefix = /* @__PURE__ */ function(AccessorPrefix) {
1073
1074
  AccessorPrefix["DynamicHTMLLastChild"] = "H";
1074
1075
  AccessorPrefix["EventAttributes"] = "I";
1075
1076
  AccessorPrefix["Getter"] = "J";
1077
+ AccessorPrefix["KeyedScopes"] = "O";
1076
1078
  AccessorPrefix["Lifecycle"] = "K";
1077
1079
  AccessorPrefix["Promise"] = "L";
1078
1080
  AccessorPrefix["TagVariableChange"] = "M";
@@ -2250,6 +2252,7 @@ const pureDOMFunctions = new Set([
2250
2252
  "_closure_get",
2251
2253
  "_or",
2252
2254
  "_for_closure",
2255
+ "_for_selector",
2253
2256
  "_for_in",
2254
2257
  "_for_of",
2255
2258
  "_for_to",
@@ -2824,7 +2827,79 @@ function forEachIdentifierPath(nodePath, cb) {
2824
2827
  }
2825
2828
  }
2826
2829
  //#endregion
2830
+ //#region src/translator/util/for-selector.ts
2831
+ const forSelectorsBySection = /* @__PURE__ */ new WeakMap();
2832
+ const forSelectorValues = /* @__PURE__ */ new WeakSet();
2833
+ function getForSelectorKey(bodySection, closure) {
2834
+ const selectors = forSelectorsBySection.get(bodySection);
2835
+ if (selectors?.closures.has(getCanonicalBinding(closure))) return selectors.keyBinding;
2836
+ }
2837
+ function isForSelectorValue(binding) {
2838
+ return forSelectorValues.has(binding);
2839
+ }
2840
+ function detectForSelector(bodySection, keyBinding) {
2841
+ let closures;
2842
+ for (const expr of keyBinding.reads) {
2843
+ if (expr.section !== bodySection) continue;
2844
+ forEach(expr.referencedBindings, (closure) => {
2845
+ const canonical = getCanonicalBinding(closure);
2846
+ if (closure.type !== 6 && isDirectClosure(bodySection, closure) && !closures?.has(canonical) && onlyComparesKey(closure, canonical, bodySection, keyBinding)) {
2847
+ (closures ||= /* @__PURE__ */ new Set()).add(canonical);
2848
+ forSelectorValues.add(closure);
2849
+ }
2850
+ });
2851
+ }
2852
+ if (closures) forSelectorsBySection.set(bodySection, {
2853
+ keyBinding,
2854
+ closures
2855
+ });
2856
+ }
2857
+ function onlyComparesKey(closure, canonical, bodySection, keyBinding) {
2858
+ let found = false;
2859
+ for (let chain = closure; chain; chain = chain.upstreamAlias) for (const expr of chain.reads) {
2860
+ if (expr.section !== bodySection) continue;
2861
+ let other = false;
2862
+ forEach(getExpressionReads(expr), (read) => {
2863
+ const resolved = read.extra.read;
2864
+ const at = resolved && resolvesTo(resolved, canonical);
2865
+ if (!at) return;
2866
+ if (at === 2 || resolved.getter || !readsKey(read.comparedTo?.extra?.read, keyBinding)) other = true;
2867
+ else found = true;
2868
+ });
2869
+ if (other) return false;
2870
+ }
2871
+ return found;
2872
+ }
2873
+ function resolvesTo(read, canonical) {
2874
+ let binding = read.binding;
2875
+ let through = 0;
2876
+ forEach(read.props, (prop) => {
2877
+ if (binding) {
2878
+ if (getCanonicalBinding(binding) === canonical) through = 2;
2879
+ binding = binding.propertyAliases.get(prop);
2880
+ }
2881
+ });
2882
+ return binding && getCanonicalBinding(binding) === canonical ? 1 : through;
2883
+ }
2884
+ function readsKey(read, keyBinding) {
2885
+ if (!read || read.getter) return false;
2886
+ let binding = read.binding;
2887
+ forEach(read.props, (prop) => {
2888
+ binding = binding?.propertyAliases.get(prop);
2889
+ });
2890
+ return !!binding && getCanonicalBinding(binding) === getCanonicalBinding(keyBinding);
2891
+ }
2892
+ //#endregion
2827
2893
  //#region src/translator/util/to-property-name.ts
2894
+ function getMemberExpressionPropString(expr) {
2895
+ switch (expr.property.type) {
2896
+ case "StringLiteral": return expr.property.value;
2897
+ case "NumericLiteral": return "" + expr.property.value;
2898
+ case "Identifier":
2899
+ if (expr.computed) return;
2900
+ return expr.property.name;
2901
+ }
2902
+ }
2828
2903
  function isValidPropertyIdentifier(name) {
2829
2904
  return /^[a-z_$][a-z0-9_$]*$/i.test(name);
2830
2905
  }
@@ -2974,6 +3049,8 @@ function getSignal(section, referencedBindings, name) {
2974
3049
  export: !!exportName,
2975
3050
  hasSideEffect: !!(referencedBindings && (Array.isArray(referencedBindings) || referencedBindings.type === 0 || referencedBindings.type === 1 || referencedBindings.section !== section || referencedBindings.closureSections || referencedBindings.hoists)),
2976
3051
  hasDynamicSubscribers: false,
3052
+ forcePersist: false,
3053
+ inline: void 0,
2977
3054
  extraArgs: void 0,
2978
3055
  prependStatements: void 0,
2979
3056
  buildAssignment: void 0
@@ -2981,8 +3058,18 @@ function getSignal(section, referencedBindings, name) {
2981
3058
  if (isOutputHTML()) return signal;
2982
3059
  else if (!referencedBindings) signal.build = () => getSignalFn(signal);
2983
3060
  else if (Array.isArray(referencedBindings)) {
2984
- subscribe(referencedBindings, signal);
2985
- signal.build = () => {
3061
+ const collapseSource = collapsedIntersectionSource.get(referencedBindings);
3062
+ subscribe(collapseSource || referencedBindings, signal);
3063
+ if (collapseSource) {
3064
+ const sourceSignal = getSignal(section, collapseSource);
3065
+ forEach(referencedBindings, (member) => {
3066
+ const memberSignal = getSignal(section, member);
3067
+ const inline = member.type === 5 && !member.upstreamAlias && member.reads.size === 1 && sourceSignal.values.find((v) => v.signal === memberSignal);
3068
+ if (inline) memberSignal.inline = inline;
3069
+ else memberSignal.hasSideEffect = memberSignal.forcePersist = true;
3070
+ });
3071
+ signal.build = () => getSignalFn(signal);
3072
+ } else signal.build = () => {
2986
3073
  const { id, scopeOffset } = intersectionMeta.get(referencedBindings);
2987
3074
  return callRuntime("_or", _marko_compiler.types.numericLiteral(id), getSignalFn(signal), scopeOffset || referencedBindings.length > 2 ? _marko_compiler.types.numericLiteral(referencedBindings.length - 1) : void 0, scopeOffset && getScopeAccessorLiteral(scopeOffset, true));
2988
3075
  };
@@ -3010,7 +3097,8 @@ function initValue(binding, isLet = false) {
3010
3097
  signal.build = () => {
3011
3098
  if (isPureMemberForwarder(binding)) return;
3012
3099
  const fn = getSignalFn(signal);
3013
- if (binding.upstreamAlias && binding.property === void 0 && binding.excludeProperties === void 0 || !signal.hasSideEffect || !signalHasStatements(signal)) return fn;
3100
+ const isDirectAlias = binding.upstreamAlias && binding.property === void 0 && binding.excludeProperties === void 0;
3101
+ if (!signal.forcePersist && (isDirectAlias || !signal.hasSideEffect || !signalHasStatements(signal))) return fn;
3014
3102
  return callRuntime(isLet ? signal.extraArgs ? "_let_change" : "_let" : "_const", getScopeAccessorLiteral(binding, true, isLet), fn);
3015
3103
  };
3016
3104
  for (const alias of binding.aliases) if (alias.type !== 6) initValue(alias);
@@ -3018,7 +3106,7 @@ function initValue(binding, isLet = false) {
3018
3106
  return signal;
3019
3107
  }
3020
3108
  function signalHasStatements(signal) {
3021
- if (signal.extraArgs || signal.render.length || signal.effect.length || signal.values.length || signal.intersection) return true;
3109
+ if (signal.extraArgs || signal.forcePersist || signal.render.length || signal.effect.length || signal.values.length || signal.intersection) return true;
3022
3110
  const binding = signal.referencedBindings;
3023
3111
  if (binding) {
3024
3112
  if (!Array.isArray(binding) && (binding.closureSections || binding.type === 0 || binding.section === signal.section && (binding.hoists || binding.aliases.size || hasNonConstantPropertyAlias(binding)))) return true;
@@ -3026,7 +3114,7 @@ function signalHasStatements(signal) {
3026
3114
  return false;
3027
3115
  }
3028
3116
  function isPureMemberForwarder(binding) {
3029
- if (binding.property === void 0 || binding.reads.size || binding.exposed || binding.aliases.size || binding.assignmentSections || getSerializeReason(binding.section, binding) || getSignal(binding.section, binding).hasSideEffect) return false;
3117
+ if (binding.property === void 0 || binding.reads.size || binding.exposed || binding.aliases.size || binding.assignmentSections || isForSelectorValue(binding) || getSerializeReason(binding.section, binding) || getSignal(binding.section, binding).hasSideEffect) return false;
3030
3118
  for (const alias of binding.propertyAliases.values()) if (alias.type !== 6) return true;
3031
3119
  return false;
3032
3120
  }
@@ -3078,12 +3166,15 @@ function getSignalFn(signal) {
3078
3166
  for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) pushMemberForwards(signal.render, toMemberExpression(createScopeReadExpression(binding), key, binding.nullable), alias);
3079
3167
  if (assertsHoists) signal.render.push(_marko_compiler.types.expressionStatement(callRuntime("_assert_hoist", createScopeReadExpression(binding))));
3080
3168
  }
3081
- for (const value of signal.values) if (signalHasStatements(value.signal)) signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(value.signal.identifier, [
3082
- scopeIdentifier,
3083
- value.value,
3084
- ...getTranslatedExtraArgs(value.signal)
3085
- ])));
3086
- else signal.render.push(_marko_compiler.types.expressionStatement(withLeadingComment(value.value, getDebugNames(value.signal.referencedBindings))));
3169
+ for (const value of signal.values) {
3170
+ if (value.signal.inline) continue;
3171
+ if (signalHasStatements(value.signal)) signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(value.signal.identifier, [
3172
+ scopeIdentifier,
3173
+ value.value,
3174
+ ...getTranslatedExtraArgs(value.signal)
3175
+ ])));
3176
+ else signal.render.push(_marko_compiler.types.expressionStatement(withLeadingComment(value.value, getDebugNames(value.signal.referencedBindings))));
3177
+ }
3087
3178
  forEach(signal.intersection, (intersection) => {
3088
3179
  signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(intersection.identifier, [scopeIdentifier])));
3089
3180
  });
@@ -3845,10 +3936,14 @@ var for_default = {
3845
3936
  addSerializeExpr(tagSection, tagExtra, kStatefulReason$1);
3846
3937
  if (paramsBinding) {
3847
3938
  setBindingDownstream(paramsBinding, tagExtra);
3848
- const keyBinding = paramsBinding.propertyAliases.get(forType === "of" ? "1" : "0");
3849
- if (keyBinding && !getKnownAttrValues(tag.node).by) {
3850
- keyBinding.type = 6;
3851
- keyBinding.scopeAccessor = getAccessorProp().LoopKey;
3939
+ const byAttr = getKnownAttrValues(tag.node).by;
3940
+ const keyBinding = getLoopKeyBinding(byAttr, paramsBinding, forType);
3941
+ if (keyBinding) {
3942
+ if (!byAttr) {
3943
+ keyBinding.type = 6;
3944
+ keyBinding.scopeAccessor = getAccessorProp().LoopKey;
3945
+ }
3946
+ onFinalizeReferences(() => detectForSelector(bodySection, keyBinding));
3852
3947
  }
3853
3948
  }
3854
3949
  bodySection.sectionAccessor = {
@@ -3935,7 +4030,9 @@ var for_default = {
3935
4030
  const { node } = tag;
3936
4031
  const { referencedBindings } = node.extra;
3937
4032
  const nodeRef = getOptimizedOnlyChildNodeBinding(tag, tagSection);
3938
- setClosureSignalBuilder(tag, (_closure, render) => {
4033
+ setClosureSignalBuilder(tag, (closure, render) => {
4034
+ const selectorKeyBinding = getForSelectorKey(bodySection, closure);
4035
+ if (selectorKeyBinding) return callRuntime("_for_selector", getScopeAccessorLiteral(nodeRef, true), getScopeAccessorLiteral(closure, true), getScopeAccessorLiteral(selectorKeyBinding, true), render);
3939
4036
  return callRuntime("_for_closure", getScopeAccessorLiteral(nodeRef, true), render);
3940
4037
  });
3941
4038
  const forType = getForType(node);
@@ -4009,6 +4106,40 @@ function getForType(tag) {
4009
4106
  case "until": return attr.name;
4010
4107
  }
4011
4108
  }
4109
+ function getLoopKeyBinding(byAttr, paramsBinding, forType) {
4110
+ if (!paramsBinding) return;
4111
+ if (byAttr) {
4112
+ const keyChain = getByKeyChain(byAttr);
4113
+ if (!keyChain) return;
4114
+ let keyBinding = paramsBinding.propertyAliases.get("0");
4115
+ for (const property of keyChain) keyBinding = keyBinding?.propertyAliases.get(property);
4116
+ return keyBinding;
4117
+ }
4118
+ return paramsBinding.propertyAliases.get(forType === "of" ? "1" : "0");
4119
+ }
4120
+ function getByKeyChain(byAttr) {
4121
+ if (byAttr.type === "StringLiteral") return [byAttr.value];
4122
+ if (byAttr.type === "ArrowFunctionExpression" || byAttr.type === "FunctionExpression") {
4123
+ const itemParam = byAttr.params[0];
4124
+ let body = byAttr.body;
4125
+ if (body.type === "BlockStatement") {
4126
+ const [statement] = body.body;
4127
+ body = body.body.length === 1 && statement.type === "ReturnStatement" ? statement.argument : void 0;
4128
+ }
4129
+ if (itemParam?.type === "Identifier" && body) return getStaticMemberChain(body, itemParam.name);
4130
+ }
4131
+ }
4132
+ function getStaticMemberChain(node, rootName) {
4133
+ const chain = [];
4134
+ let cur = node;
4135
+ while (cur.type === "MemberExpression" || cur.type === "OptionalMemberExpression") {
4136
+ const property = getMemberExpressionPropString(cur);
4137
+ if (property === void 0) return;
4138
+ chain.push(property);
4139
+ cur = cur.object;
4140
+ }
4141
+ if (cur.type === "Identifier" && cur.name === rootName) return chain.reverse();
4142
+ }
4012
4143
  function forTypeToRuntime(type) {
4013
4144
  switch (type) {
4014
4145
  case "of": return "forOf";
@@ -6721,7 +6852,11 @@ function finalizeReferences() {
6721
6852
  forEachSection((section) => {
6722
6853
  const { id, bindings } = section;
6723
6854
  const isOwnedBinding = ({ section }) => section.id === id;
6724
- let intersections = intersectionsBySection.get(section) || [];
6855
+ let intersections = (intersectionsBySection.get(section) || []).filter((intersection) => {
6856
+ const collapseSource = getCollapsibleIntersectionSource(intersection, section);
6857
+ if (collapseSource) collapsedIntersectionSource.set(intersection, collapseSource);
6858
+ return !collapseSource;
6859
+ });
6725
6860
  if (intersections.length) {
6726
6861
  const anchors = /* @__PURE__ */ new Map();
6727
6862
  for (const intersection of intersections) for (let i = intersection.length; i--;) if (isOwnedBinding(intersection[i])) {
@@ -6754,6 +6889,7 @@ function finalizeReferences() {
6754
6889
  });
6755
6890
  const programSection = (0, _marko_compiler_babel_utils.getProgram)().node.extra.section;
6756
6891
  if (programSection.returnValueExpr) programSection.returnSerializeReason = getSerializeSourcesForExpr(programSection.returnValueExpr);
6892
+ for (const finalize of getReferenceFinalizers()) finalize();
6757
6893
  readsByExpression.clear();
6758
6894
  fnReadsByExpression.clear();
6759
6895
  }
@@ -6769,6 +6905,19 @@ function getMaxOwnSourceOffset(intersection, section) {
6769
6905
  return scopeOffset;
6770
6906
  }
6771
6907
  const intersectionMeta = /* @__PURE__ */ new WeakMap();
6908
+ const collapsedIntersectionSource = /* @__PURE__ */ new WeakMap();
6909
+ function getCollapsibleIntersectionSource(intersection, section) {
6910
+ let sources;
6911
+ for (const member of intersection) {
6912
+ if (!member.sources) return void 0;
6913
+ const isDirectAlias = member.upstreamAlias && member.property === void 0 && member.excludeProperties === void 0;
6914
+ if (member.section !== section || isDirectAlias) return void 0;
6915
+ sources = mergeSources(sources, member.sources);
6916
+ }
6917
+ if (!sources || sources.state && sources.param) return;
6918
+ const source = sources.state || sources.param;
6919
+ return source && !Array.isArray(source) && source.section === section && !source.scopeOffset ? source : void 0;
6920
+ }
6772
6921
  function setBindingDownstream(binding, expr) {
6773
6922
  getBindingValueExprs().set(binding, expr || false);
6774
6923
  if (expr && expr !== true) forEach(expr, (expr) => {
@@ -6878,13 +7027,21 @@ const propsUtil = new Sorted(function compareProps(a, b) {
6878
7027
  });
6879
7028
  const [getReadsByExpression] = createProgramState(() => /* @__PURE__ */ new Map());
6880
7029
  const [getFunctionReadsByExpression] = createProgramState(() => /* @__PURE__ */ new Map());
7030
+ const [getReferenceFinalizers] = createProgramState(() => []);
7031
+ function onFinalizeReferences(finalize) {
7032
+ getReferenceFinalizers().push(finalize);
7033
+ }
7034
+ function getExpressionReads(exprExtra) {
7035
+ return getReadsByExpression().get(exprExtra);
7036
+ }
6881
7037
  function addRead(exprExtra, extra, binding, section, getter) {
6882
7038
  const readsByExpression = getReadsByExpression();
6883
7039
  const read = {
6884
7040
  binding,
6885
7041
  extra,
6886
7042
  getter,
6887
- ownVar: false
7043
+ ownVar: false,
7044
+ comparedTo: void 0
6888
7045
  };
6889
7046
  binding.reads.add(exprExtra);
6890
7047
  exprExtra.section = section;
@@ -6914,6 +7071,8 @@ function addReadToExpression(root, binding, getter) {
6914
7071
  const section = getOrCreateSection(exprRoot);
6915
7072
  const exprExtra = exprRoot.node.extra ??= { section };
6916
7073
  const read = addRead(exprExtra, node.extra ??= {}, binding, section, getter);
7074
+ const { parent } = root;
7075
+ if (parent.type === "BinaryExpression" && (parent.operator === "===" || parent.operator === "!==")) read.comparedTo = parent.left === node ? parent.right : parent.left;
6917
7076
  if (!getter && binding.type === 5) {
6918
7077
  const babelBinding = root.scope.getBinding(binding.name);
6919
7078
  read.ownVar = !!babelBinding && babelBinding.kind !== "param" && isReferenceInOwnBody(babelBinding.path, root);
@@ -7020,13 +7179,16 @@ function getReadReplacement(node, signal) {
7020
7179
  let replacement;
7021
7180
  if (read.props === void 0) {
7022
7181
  if (read.getter?.invoked) return;
7023
- if (isOutputDOM()) if (signal?.referencedBindings === readBinding && !signal.hasSideEffect) replacement = getSignalValueIdentifier(signal);
7024
- else if (read.getter?.hoisted) replacement = _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, read.getter.hoisted), [getScopeExpression(extra.section, read.getter.hoisted)]);
7025
- else if (readBinding.type === 0) {
7026
- if (read.getter) replacement = _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, readBinding.section), [getScopeExpression(extra.section, readBinding.section)]);
7027
- } else if (!isOptimize() && read.ownVar) replacement = callRuntime("_assert_init", extra.section ? getScopeExpression(extra.section, readBinding.section) : scopeIdentifier, getScopeAccessorLiteral(readBinding));
7028
- else replacement = createScopeReadExpression(readBinding, extra.section);
7029
- else if (node.type !== "Identifier") replacement = _marko_compiler.types.identifier(readBinding.name);
7182
+ if (isOutputDOM()) {
7183
+ const inlined = getSignals(extra.section).get(readBinding)?.inline?.value;
7184
+ if (inlined) replacement = _marko_compiler.types.cloneNode(inlined, true);
7185
+ else if (signal?.referencedBindings === readBinding && !signal.hasSideEffect) replacement = getSignalValueIdentifier(signal);
7186
+ else if (read.getter?.hoisted) replacement = _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, read.getter.hoisted), [getScopeExpression(extra.section, read.getter.hoisted)]);
7187
+ else if (readBinding.type === 0) {
7188
+ if (read.getter) replacement = _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, readBinding.section), [getScopeExpression(extra.section, readBinding.section)]);
7189
+ } else if (!isOptimize() && read.ownVar) replacement = callRuntime("_assert_init", extra.section ? getScopeExpression(extra.section, readBinding.section) : scopeIdentifier, getScopeAccessorLiteral(readBinding));
7190
+ else replacement = createScopeReadExpression(readBinding, extra.section);
7191
+ } else if (node.type !== "Identifier") replacement = _marko_compiler.types.identifier(readBinding.name);
7030
7192
  else if (read.getter?.hoisted) replacement = getBindingGetterIdentifier(readBinding, read.getter.hoisted);
7031
7193
  else if (readBinding.type === 0) {
7032
7194
  if (readBinding.getters.has(readBinding.section)) replacement = getBindingGetterIdentifier(readBinding, readBinding.section);
@@ -7237,15 +7399,6 @@ function createGetterRead(binding, props, getter) {
7237
7399
  getter
7238
7400
  };
7239
7401
  }
7240
- function getMemberExpressionPropString(expr) {
7241
- switch (expr.property.type) {
7242
- case "StringLiteral": return expr.property.value;
7243
- case "NumericLiteral": return "" + expr.property.value;
7244
- case "Identifier":
7245
- if (expr.computed) return;
7246
- return expr.property.name;
7247
- }
7248
- }
7249
7402
  function isReferencedExtra(extra) {
7250
7403
  return !!(extra && !extra.pruned && extra.section);
7251
7404
  }
@@ -0,0 +1,5 @@
1
+ import { type Binding } from "./references";
2
+ import { type Section } from "./sections";
3
+ export declare function getForSelectorKey(bodySection: Section, closure: Binding): Binding | undefined;
4
+ export declare function isForSelectorValue(binding: Binding): boolean;
5
+ export declare function detectForSelector(bodySection: Section, keyBinding: Binding): void;
@@ -69,6 +69,7 @@ interface Read {
69
69
  extra: t.NodeExtra;
70
70
  ownVar: boolean;
71
71
  getter: Getter | undefined;
72
+ comparedTo: t.Node | undefined;
72
73
  }
73
74
  interface ExtraRead {
74
75
  binding: Binding;
@@ -122,12 +123,15 @@ export declare const intersectionMeta: WeakMap<Intersection, {
122
123
  id: number;
123
124
  scopeOffset: Binding | undefined;
124
125
  }>;
126
+ export declare const collapsedIntersectionSource: WeakMap<Intersection, Binding>;
125
127
  export declare function setBindingDownstream(binding: Binding, expr: boolean | Opt<t.NodeExtra>): void;
126
128
  export declare function createSources(state: Sources["state"], param: Sources["param"]): Sources;
127
129
  export declare function compareSources(a: Sources, b: Sources): number;
128
130
  export declare function mergeSources(a: undefined | Sources, b: undefined | Sources): Sources | undefined;
129
131
  export declare const bindingUtil: Sorted<Binding>;
130
132
  export declare const propsUtil: Sorted<string>;
133
+ export declare function onFinalizeReferences(finalize: () => void): void;
134
+ export declare function getExpressionReads(exprExtra: ReferencedExtra): Opt<Read>;
131
135
  export declare function addRead(exprExtra: ReferencedExtra, extra: t.NodeExtra, binding: Binding, section: Section, getter: Getter | undefined): Read;
132
136
  export declare function dropNodes(node: t.Node | t.Node[]): void;
133
137
  export declare function getCanonicalBinding(binding: Binding): Binding;
@@ -20,12 +20,17 @@ export interface Signal {
20
20
  effectReferencedBindings: ReferencedBindings;
21
21
  hasDynamicSubscribers: boolean;
22
22
  hasSideEffect: boolean;
23
+ forcePersist: boolean;
24
+ inline: {
25
+ value: t.Expression;
26
+ } | undefined;
23
27
  export: boolean;
24
28
  extraArgs: t.Expression[] | undefined;
25
29
  prependStatements: t.Statement[] | undefined;
26
30
  buildAssignment: ((valueSection: Section, value: t.Expression) => t.Expression | undefined) | undefined;
27
31
  }
28
32
  type closureSignalBuilder = (closure: Binding, render: t.Expression) => t.Expression;
33
+ export declare const getSignals: (section: Section) => Map<unknown, Signal>;
29
34
  export declare function setClosureSignalBuilder(tag: t.NodePath<t.MarkoTag>, builder: closureSignalBuilder): void;
30
35
  export declare const getTryHasPlaceholder: (section: Section) => true | undefined, setTryHasPlaceholder: (section: Section, value: true | undefined) => void;
31
36
  export declare function setSectionSerializedValue(section: Section, prop: AccessorProp, expression: t.Expression): void;
@@ -1,4 +1,5 @@
1
1
  import { types as t } from "@marko/compiler";
2
+ export declare function getMemberExpressionPropString(expr: t.MemberExpression | t.OptionalMemberExpression): string | undefined;
2
3
  export declare function isValidPropertyIdentifier(name: string): boolean;
3
4
  export declare function toPropertyName(name: string): t.Identifier | t.NumericLiteral | t.StringLiteral;
4
5
  export declare function toObjectProperty(name: string, value: t.Expression): t.ObjectProperty;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "6.1.23",
3
+ "version": "6.1.24",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",