marko 6.1.22 → 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";
@@ -1757,6 +1759,7 @@ function isClientAssetImport(file, request) {
1757
1759
  const kDirectContent = Symbol("direct content");
1758
1760
  function getBindingPropTree(binding) {
1759
1761
  if (pruneBinding(binding)) return;
1762
+ binding.exposed = true;
1760
1763
  const props = {
1761
1764
  binding,
1762
1765
  props: void 0,
@@ -2249,6 +2252,7 @@ const pureDOMFunctions = new Set([
2249
2252
  "_closure_get",
2250
2253
  "_or",
2251
2254
  "_for_closure",
2255
+ "_for_selector",
2252
2256
  "_for_in",
2253
2257
  "_for_of",
2254
2258
  "_for_to",
@@ -2823,7 +2827,79 @@ function forEachIdentifierPath(nodePath, cb) {
2823
2827
  }
2824
2828
  }
2825
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
2826
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
+ }
2827
2903
  function isValidPropertyIdentifier(name) {
2828
2904
  return /^[a-z_$][a-z0-9_$]*$/i.test(name);
2829
2905
  }
@@ -2973,6 +3049,8 @@ function getSignal(section, referencedBindings, name) {
2973
3049
  export: !!exportName,
2974
3050
  hasSideEffect: !!(referencedBindings && (Array.isArray(referencedBindings) || referencedBindings.type === 0 || referencedBindings.type === 1 || referencedBindings.section !== section || referencedBindings.closureSections || referencedBindings.hoists)),
2975
3051
  hasDynamicSubscribers: false,
3052
+ forcePersist: false,
3053
+ inline: void 0,
2976
3054
  extraArgs: void 0,
2977
3055
  prependStatements: void 0,
2978
3056
  buildAssignment: void 0
@@ -2980,8 +3058,18 @@ function getSignal(section, referencedBindings, name) {
2980
3058
  if (isOutputHTML()) return signal;
2981
3059
  else if (!referencedBindings) signal.build = () => getSignalFn(signal);
2982
3060
  else if (Array.isArray(referencedBindings)) {
2983
- subscribe(referencedBindings, signal);
2984
- 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 = () => {
2985
3073
  const { id, scopeOffset } = intersectionMeta.get(referencedBindings);
2986
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));
2987
3075
  };
@@ -3007,8 +3095,10 @@ function initValue(binding, isLet = false) {
3007
3095
  const section = binding.section;
3008
3096
  const signal = getSignal(section, binding);
3009
3097
  signal.build = () => {
3098
+ if (isPureMemberForwarder(binding)) return;
3010
3099
  const fn = getSignalFn(signal);
3011
- 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;
3012
3102
  return callRuntime(isLet ? signal.extraArgs ? "_let_change" : "_let" : "_const", getScopeAccessorLiteral(binding, true, isLet), fn);
3013
3103
  };
3014
3104
  for (const alias of binding.aliases) if (alias.type !== 6) initValue(alias);
@@ -3016,13 +3106,30 @@ function initValue(binding, isLet = false) {
3016
3106
  return signal;
3017
3107
  }
3018
3108
  function signalHasStatements(signal) {
3019
- 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;
3020
3110
  const binding = signal.referencedBindings;
3021
3111
  if (binding) {
3022
3112
  if (!Array.isArray(binding) && (binding.closureSections || binding.type === 0 || binding.section === signal.section && (binding.hoists || binding.aliases.size || hasNonConstantPropertyAlias(binding)))) return true;
3023
3113
  } else if (signal.section.referencedClosures) return true;
3024
3114
  return false;
3025
3115
  }
3116
+ function isPureMemberForwarder(binding) {
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;
3118
+ for (const alias of binding.propertyAliases.values()) if (alias.type !== 6) return true;
3119
+ return false;
3120
+ }
3121
+ function pushMemberForwards(renderStatements, value, alias) {
3122
+ if (isPureMemberForwarder(alias)) {
3123
+ for (const [key, child] of alias.propertyAliases) if (child.type !== 6) pushMemberForwards(renderStatements, toMemberExpression(_marko_compiler.types.cloneNode(value, true), key, alias.nullable), child);
3124
+ } else {
3125
+ const aliasSignal = getSignal(alias.section, alias);
3126
+ renderStatements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3127
+ scopeIdentifier,
3128
+ value,
3129
+ ...getTranslatedExtraArgs(aliasSignal)
3130
+ ])));
3131
+ }
3132
+ }
3026
3133
  function getSignalFn(signal) {
3027
3134
  const section = signal.section;
3028
3135
  const binding = signal.referencedBindings;
@@ -3056,22 +3163,18 @@ function getSignalFn(signal) {
3056
3163
  ...getTranslatedExtraArgs(aliasSignal)
3057
3164
  ])));
3058
3165
  }
3059
- for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) {
3060
- const aliasSignal = getSignal(alias.section, alias);
3061
- signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3062
- scopeIdentifier,
3063
- toMemberExpression(createScopeReadExpression(binding), key, binding.nullable),
3064
- ...getTranslatedExtraArgs(aliasSignal)
3065
- ])));
3066
- }
3166
+ for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) pushMemberForwards(signal.render, toMemberExpression(createScopeReadExpression(binding), key, binding.nullable), alias);
3067
3167
  if (assertsHoists) signal.render.push(_marko_compiler.types.expressionStatement(callRuntime("_assert_hoist", createScopeReadExpression(binding))));
3068
3168
  }
3069
- for (const value of signal.values) if (signalHasStatements(value.signal)) signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(value.signal.identifier, [
3070
- scopeIdentifier,
3071
- value.value,
3072
- ...getTranslatedExtraArgs(value.signal)
3073
- ])));
3074
- 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
+ }
3075
3178
  forEach(signal.intersection, (intersection) => {
3076
3179
  signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(intersection.identifier, [scopeIdentifier])));
3077
3180
  });
@@ -3833,10 +3936,14 @@ var for_default = {
3833
3936
  addSerializeExpr(tagSection, tagExtra, kStatefulReason$1);
3834
3937
  if (paramsBinding) {
3835
3938
  setBindingDownstream(paramsBinding, tagExtra);
3836
- const keyBinding = paramsBinding.propertyAliases.get(forType === "of" ? "1" : "0");
3837
- if (keyBinding && !getKnownAttrValues(tag.node).by) {
3838
- keyBinding.type = 6;
3839
- 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));
3840
3947
  }
3841
3948
  }
3842
3949
  bodySection.sectionAccessor = {
@@ -3923,7 +4030,9 @@ var for_default = {
3923
4030
  const { node } = tag;
3924
4031
  const { referencedBindings } = node.extra;
3925
4032
  const nodeRef = getOptimizedOnlyChildNodeBinding(tag, tagSection);
3926
- 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);
3927
4036
  return callRuntime("_for_closure", getScopeAccessorLiteral(nodeRef, true), render);
3928
4037
  });
3929
4038
  const forType = getForType(node);
@@ -3997,6 +4106,40 @@ function getForType(tag) {
3997
4106
  case "until": return attr.name;
3998
4107
  }
3999
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
+ }
4000
4143
  function forTypeToRuntime(type) {
4001
4144
  switch (type) {
4002
4145
  case "of": return "forOf";
@@ -6274,7 +6417,8 @@ function createBinding(name, type, refSection, upstreamAlias, property, excludeP
6274
6417
  export: void 0,
6275
6418
  directContentExport: void 0,
6276
6419
  nullable: !sameSection || excludeProperties === void 0,
6277
- pruned: void 0
6420
+ pruned: void 0,
6421
+ exposed: false
6278
6422
  };
6279
6423
  if (property) {
6280
6424
  if (declared) upstreamAlias.nullable = false;
@@ -6708,7 +6852,11 @@ function finalizeReferences() {
6708
6852
  forEachSection((section) => {
6709
6853
  const { id, bindings } = section;
6710
6854
  const isOwnedBinding = ({ section }) => section.id === id;
6711
- 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
+ });
6712
6860
  if (intersections.length) {
6713
6861
  const anchors = /* @__PURE__ */ new Map();
6714
6862
  for (const intersection of intersections) for (let i = intersection.length; i--;) if (isOwnedBinding(intersection[i])) {
@@ -6741,6 +6889,7 @@ function finalizeReferences() {
6741
6889
  });
6742
6890
  const programSection = (0, _marko_compiler_babel_utils.getProgram)().node.extra.section;
6743
6891
  if (programSection.returnValueExpr) programSection.returnSerializeReason = getSerializeSourcesForExpr(programSection.returnValueExpr);
6892
+ for (const finalize of getReferenceFinalizers()) finalize();
6744
6893
  readsByExpression.clear();
6745
6894
  fnReadsByExpression.clear();
6746
6895
  }
@@ -6756,6 +6905,19 @@ function getMaxOwnSourceOffset(intersection, section) {
6756
6905
  return scopeOffset;
6757
6906
  }
6758
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
+ }
6759
6921
  function setBindingDownstream(binding, expr) {
6760
6922
  getBindingValueExprs().set(binding, expr || false);
6761
6923
  if (expr && expr !== true) forEach(expr, (expr) => {
@@ -6865,13 +7027,21 @@ const propsUtil = new Sorted(function compareProps(a, b) {
6865
7027
  });
6866
7028
  const [getReadsByExpression] = createProgramState(() => /* @__PURE__ */ new Map());
6867
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
+ }
6868
7037
  function addRead(exprExtra, extra, binding, section, getter) {
6869
7038
  const readsByExpression = getReadsByExpression();
6870
7039
  const read = {
6871
7040
  binding,
6872
7041
  extra,
6873
7042
  getter,
6874
- ownVar: false
7043
+ ownVar: false,
7044
+ comparedTo: void 0
6875
7045
  };
6876
7046
  binding.reads.add(exprExtra);
6877
7047
  exprExtra.section = section;
@@ -6901,6 +7071,8 @@ function addReadToExpression(root, binding, getter) {
6901
7071
  const section = getOrCreateSection(exprRoot);
6902
7072
  const exprExtra = exprRoot.node.extra ??= { section };
6903
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;
6904
7076
  if (!getter && binding.type === 5) {
6905
7077
  const babelBinding = root.scope.getBinding(binding.name);
6906
7078
  read.ownVar = !!babelBinding && babelBinding.kind !== "param" && isReferenceInOwnBody(babelBinding.path, root);
@@ -7007,13 +7179,16 @@ function getReadReplacement(node, signal) {
7007
7179
  let replacement;
7008
7180
  if (read.props === void 0) {
7009
7181
  if (read.getter?.invoked) return;
7010
- if (isOutputDOM()) if (signal?.referencedBindings === readBinding && !signal.hasSideEffect) replacement = getSignalValueIdentifier(signal);
7011
- else if (read.getter?.hoisted) replacement = _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, read.getter.hoisted), [getScopeExpression(extra.section, read.getter.hoisted)]);
7012
- else if (readBinding.type === 0) {
7013
- if (read.getter) replacement = _marko_compiler.types.callExpression(getBindingGetterIdentifier(readBinding, readBinding.section), [getScopeExpression(extra.section, readBinding.section)]);
7014
- } else if (!isOptimize() && read.ownVar) replacement = callRuntime("_assert_init", extra.section ? getScopeExpression(extra.section, readBinding.section) : scopeIdentifier, getScopeAccessorLiteral(readBinding));
7015
- else replacement = createScopeReadExpression(readBinding, extra.section);
7016
- 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);
7017
7192
  else if (read.getter?.hoisted) replacement = getBindingGetterIdentifier(readBinding, read.getter.hoisted);
7018
7193
  else if (readBinding.type === 0) {
7019
7194
  if (readBinding.getters.has(readBinding.section)) replacement = getBindingGetterIdentifier(readBinding, readBinding.section);
@@ -7224,15 +7399,6 @@ function createGetterRead(binding, props, getter) {
7224
7399
  getter
7225
7400
  };
7226
7401
  }
7227
- function getMemberExpressionPropString(expr) {
7228
- switch (expr.property.type) {
7229
- case "StringLiteral": return expr.property.value;
7230
- case "NumericLiteral": return "" + expr.property.value;
7231
- case "Identifier":
7232
- if (expr.computed) return;
7233
- return expr.property.name;
7234
- }
7235
- }
7236
7402
  function isReferencedExtra(extra) {
7237
7403
  return !!(extra && !extra.pruned && extra.section);
7238
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;
@@ -48,6 +48,7 @@ export interface Binding {
48
48
  declared: boolean;
49
49
  nullable: boolean;
50
50
  pruned: boolean | undefined;
51
+ exposed: boolean;
51
52
  }
52
53
  export interface InputBinding extends Binding {
53
54
  type: BindingType.input;
@@ -68,6 +69,7 @@ interface Read {
68
69
  extra: t.NodeExtra;
69
70
  ownVar: boolean;
70
71
  getter: Getter | undefined;
72
+ comparedTo: t.Node | undefined;
71
73
  }
72
74
  interface ExtraRead {
73
75
  binding: Binding;
@@ -121,12 +123,15 @@ export declare const intersectionMeta: WeakMap<Intersection, {
121
123
  id: number;
122
124
  scopeOffset: Binding | undefined;
123
125
  }>;
126
+ export declare const collapsedIntersectionSource: WeakMap<Intersection, Binding>;
124
127
  export declare function setBindingDownstream(binding: Binding, expr: boolean | Opt<t.NodeExtra>): void;
125
128
  export declare function createSources(state: Sources["state"], param: Sources["param"]): Sources;
126
129
  export declare function compareSources(a: Sources, b: Sources): number;
127
130
  export declare function mergeSources(a: undefined | Sources, b: undefined | Sources): Sources | undefined;
128
131
  export declare const bindingUtil: Sorted<Binding>;
129
132
  export declare const propsUtil: Sorted<string>;
133
+ export declare function onFinalizeReferences(finalize: () => void): void;
134
+ export declare function getExpressionReads(exprExtra: ReferencedExtra): Opt<Read>;
130
135
  export declare function addRead(exprExtra: ReferencedExtra, extra: t.NodeExtra, binding: Binding, section: Section, getter: Getter | undefined): Read;
131
136
  export declare function dropNodes(node: t.Node | t.Node[]): void;
132
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.22",
3
+ "version": "6.1.24",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",