marko 6.3.34 → 6.3.36

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.
Files changed (62) hide show
  1. package/cheatsheet.md +2 -2
  2. package/dist/common/constants/accessor-prefix.d.ts +1 -0
  3. package/dist/common/constants/accessor-prefix.debug.d.ts +1 -0
  4. package/dist/common/errors.d.ts +1 -0
  5. package/dist/common/meta.d.ts +1 -0
  6. package/dist/common/types.d.ts +10 -0
  7. package/dist/debug/dom/catch.feat.js +1 -1
  8. package/dist/debug/dom/catch.feat.mjs +1 -1
  9. package/dist/debug/dom/controllable-input.feat.js +1 -1
  10. package/dist/debug/dom/controllable-input.feat.mjs +1 -1
  11. package/dist/debug/dom/controllable-open.feat.js +1 -1
  12. package/dist/debug/dom/controllable-open.feat.mjs +1 -1
  13. package/dist/debug/dom/controllable-select.feat.js +1 -1
  14. package/dist/debug/dom/controllable-select.feat.mjs +1 -1
  15. package/dist/debug/dom/controllable-textarea.feat.js +1 -1
  16. package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
  17. package/dist/debug/dom/controllable.feat.js +1 -1
  18. package/dist/debug/dom/controllable.feat.mjs +1 -1
  19. package/dist/debug/dom/dynamic-tag-var.feat.js +7 -0
  20. package/dist/debug/dom/dynamic-tag-var.feat.mjs +6 -0
  21. package/dist/debug/{dom-Bj58jt8y.js → dom-BbFAdZEB.js} +54 -17
  22. package/dist/debug/{dom-klf8Ec_o.mjs → dom-ClMc0GK9.mjs} +43 -18
  23. package/dist/debug/dom.js +1 -1
  24. package/dist/debug/dom.mjs +1 -1
  25. package/dist/debug/html.js +94 -25
  26. package/dist/debug/html.mjs +94 -25
  27. package/dist/dom/catch.feat.js +4 -4
  28. package/dist/dom/catch.feat.mjs +1 -1
  29. package/dist/dom/control-flow.d.ts +3 -0
  30. package/dist/dom/controllable-input.feat.js +2 -2
  31. package/dist/dom/controllable-input.feat.mjs +1 -1
  32. package/dist/dom/controllable-open.feat.js +2 -2
  33. package/dist/dom/controllable-open.feat.mjs +1 -1
  34. package/dist/dom/controllable-select.feat.js +2 -2
  35. package/dist/dom/controllable-select.feat.mjs +1 -1
  36. package/dist/dom/controllable-textarea.feat.js +2 -2
  37. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  38. package/dist/dom/controllable.feat.js +2 -2
  39. package/dist/dom/controllable.feat.mjs +1 -1
  40. package/dist/dom/dynamic-tag-var.feat.d.ts +1 -0
  41. package/dist/dom/dynamic-tag-var.feat.js +3 -0
  42. package/dist/dom/dynamic-tag-var.feat.mjs +4 -0
  43. package/dist/dom/signals.d.ts +3 -3
  44. package/dist/{dom-B-XpL2_H.js → dom-59H9kVUF.js} +133 -118
  45. package/dist/{dom-6hBvZW7X.mjs → dom-BKDjlXIl.mjs} +25 -15
  46. package/dist/dom.js +34 -34
  47. package/dist/dom.mjs +1 -1
  48. package/dist/html/dynamic-tag.d.ts +1 -1
  49. package/dist/html/serializer.d.ts +9 -1
  50. package/dist/html/template.d.ts +1 -0
  51. package/dist/html/writer.d.ts +1 -0
  52. package/dist/html.js +19 -13
  53. package/dist/html.mjs +19 -13
  54. package/dist/translator/index.js +287 -101
  55. package/dist/translator/util/references.d.ts +1 -0
  56. package/dist/translator/util/runtime.d.ts +1 -1
  57. package/dist/translator/util/signals.d.ts +2 -0
  58. package/dist/translator/util/translate-var.d.ts +1 -1
  59. package/dist/translator/util/traverse.d.ts +2 -0
  60. package/dist/translator/visitors/export-declaration.d.ts +8 -0
  61. package/package.json +4 -4
  62. package/tags/let.d.marko +3 -4
@@ -35,6 +35,7 @@ const LoopKey = "#LoopKey";
35
35
  const PlaceholderContent = "#PlaceholderContent";
36
36
  const Renderer = "#Renderer";
37
37
  const TagVariable = "#TagVariable";
38
+ const Owner = "owner";
38
39
  const Embed = "embed";
39
40
  //#endregion
40
41
  //#region src/common/helpers.ts
@@ -224,10 +225,16 @@ function assertExclusiveAttrs(attrs, onError = throwErr) {
224
225
  (exclusiveAttrs ||= []).push("checkedValueChange");
225
226
  if ("checked" in attrs) exclusiveAttrs.push("checked");
226
227
  }
227
- if (attrs.valueChange) (exclusiveAttrs ||= []).push("valueChange");
228
+ if (attrs.valueChange) {
229
+ (exclusiveAttrs ||= []).push("valueChange");
230
+ if ("checked" in attrs && !exclusiveAttrs.includes("checked")) exclusiveAttrs.push("checked");
231
+ }
228
232
  if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
229
233
  }
230
234
  }
235
+ function assertNoValueBindingOnCheckable(type, valueChange) {
236
+ if (valueChange && /^(?:button|checkbox|hidden|image|radio|reset|submit)$/i.test(type)) console.error(`\`valueChange\` cannot be used on a \`type="${type}"\` \`<input>\` — user interaction can never change its \`value\`.` + (/^[cr]/i.test(type) ? " Bind `checked` or `checkedValue` instead." : ""));
237
+ }
231
238
  function assertHandlerIsFunction(name, value) {
232
239
  if (value && typeof value !== "function") throw new Error(`The \`${name}\` handler must be a function or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …), but received type "${typeof value}".`);
233
240
  }
@@ -248,6 +255,7 @@ function joinWithAnd(a) {
248
255
  //#endregion
249
256
  //#region src/common/meta.ts
250
257
  const DYNAMIC_TAG_SCRIPT_REGISTER_ID = "_dynamicTagScript";
258
+ const DYNAMIC_TAG_VAR_REGISTER_ID = "_dynamicTagVar";
251
259
  //#endregion
252
260
  //#region src/html/content.ts
253
261
  function _to_text(val) {
@@ -258,8 +266,8 @@ function _unescaped(val) {
258
266
  assertValidTextValue(val);
259
267
  return val ? val + "" : val === 0 ? "0" : "";
260
268
  }
261
- const unsafeXMLReg = /[<&]/g;
262
- const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;";
269
+ const unsafeXMLReg = /[<&\r]/g;
270
+ const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : c === "<" ? "&lt;" : "&#13;";
263
271
  const escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str;
264
272
  function _escape(val) {
265
273
  assertValidTextValue(val);
@@ -572,7 +580,18 @@ function setDebugInfo(obj, file, loc, vars) {
572
580
  DEBUG.set(obj, {
573
581
  file,
574
582
  loc,
575
- vars
583
+ vars,
584
+ slots: DEBUG.get(obj)?.slots
585
+ });
586
+ }
587
+ function setDebugSlotName(obj, accessor, name) {
588
+ const debug = DEBUG.get(obj);
589
+ if (debug) (debug.slots ??= {})[accessor] = name;
590
+ else DEBUG.set(obj, {
591
+ file: "",
592
+ loc: 0,
593
+ vars: void 0,
594
+ slots: { [accessor]: name }
576
595
  });
577
596
  }
578
597
  var Serializer = class {
@@ -1471,21 +1490,27 @@ function throwUnserializable(state, cause, ref = null, accessor = "") {
1471
1490
  if (cause !== void 0 && state.boundary?.abort) {
1472
1491
  let message = "Unable to serialize";
1473
1492
  let access = "";
1474
- while (ref?.accessor) {
1493
+ while (ref) {
1494
+ const { accessor } = ref;
1475
1495
  const debug = ref.parent?.debug;
1476
- if (debug) {
1477
- const varLoc = debug.vars?.[ref.accessor];
1478
- let debugAccess = ref.accessor;
1496
+ if (accessor && debug) {
1497
+ const rawAccessor = fromObjectKey(accessor);
1498
+ const varLoc = debug.vars?.[rawAccessor];
1499
+ const slotName = debug.slots?.[rawAccessor];
1500
+ let debugAccess = varLoc ? rawAccessor : void 0;
1479
1501
  let debugLoc = debug.loc;
1480
1502
  if (varLoc) if (Array.isArray(varLoc)) {
1481
1503
  debugAccess = varLoc[0];
1482
1504
  if (varLoc[1]) debugLoc = varLoc[1];
1483
1505
  } else debugLoc = varLoc;
1484
- message += ` ${JSON.stringify(debugAccess)} in ${debug.file}`;
1506
+ let display;
1507
+ if (debugAccess !== void 0) display = slotName && debugAccess.startsWith("...") ? `\`${slotName}\` from \`${debugAccess}\`` : JSON.stringify(debugAccess);
1508
+ else display = describeAccessor(rawAccessor, slotName) ?? JSON.stringify(rawAccessor);
1509
+ message += ` ${display} in ${debug.file}`;
1485
1510
  if (debugLoc) message += `:${debugLoc}`;
1486
1511
  break;
1487
1512
  }
1488
- access = toAccess(ref.accessor) + access;
1513
+ if (accessor) access = toAccess(accessor) + access;
1489
1514
  ref = ref.parent;
1490
1515
  }
1491
1516
  if (accessor) access = toAccess(accessor) + access;
@@ -1497,6 +1522,40 @@ function throwUnserializable(state, cause, ref = null, accessor = "") {
1497
1522
  state.boundary.abort(err);
1498
1523
  }
1499
1524
  }
1525
+ const accessorPrefixDescriptions = {
1526
+ BranchScopes: "the branch scopes",
1527
+ ClosureScopes: "the closure scopes",
1528
+ ClosureSignalIndex: "the closure signal index",
1529
+ ConditionalRenderer: "the conditional renderer",
1530
+ ControlledObserver: "the controlled observer",
1531
+ ControlledHandler: "the change handler",
1532
+ ControlledType: "the controlled type",
1533
+ ControlledValue: "the controlled value",
1534
+ DynamicHTMLLastChild: "the dynamic html",
1535
+ EventAttributes: "the event handlers",
1536
+ IdFallback: "the generated id",
1537
+ KeyedScopes: "the keyed scopes",
1538
+ Lifecycle: "the lifecycle handlers",
1539
+ Promise: "the pending promise",
1540
+ TagVariableChange: "the tag variable change handler"
1541
+ };
1542
+ function describeAccessor(accessor, slotName) {
1543
+ const sep = accessor.indexOf(":");
1544
+ if (~sep) {
1545
+ const description = slotName === void 0 ? accessorPrefixDescriptions[accessor.slice(0, sep)] : `the \`${slotName}\` handler`;
1546
+ if (description) {
1547
+ const node = /^#([a-z-]+)\//i.exec(accessor.slice(sep + 1));
1548
+ return node ? `${description} of \`<${node[1]}>\`` : description;
1549
+ }
1550
+ }
1551
+ }
1552
+ function fromObjectKey(key) {
1553
+ try {
1554
+ if (key[0] === "\"") return JSON.parse(key.replace(/\\x/g, "\\u00"));
1555
+ if (key[0] === "[") return JSON.parse(key.slice(1, -1));
1556
+ } catch {}
1557
+ return key;
1558
+ }
1500
1559
  function trackChannel(state, ref) {
1501
1560
  const refReadyId = ref.channel?.readyId;
1502
1561
  if (!refReadyId || refReadyId === state.channel?.readyId) return true;
@@ -1877,6 +1936,9 @@ function getContext(key) {
1877
1936
  function getState() {
1878
1937
  return $chunk.boundary.state;
1879
1938
  }
1939
+ function rendererKey(renderer) {
1940
+ return renderer?.["owner"] === void 0 ? renderer?.["id"] || renderer : renderer["id"] + " " + renderer[Owner];
1941
+ }
1880
1942
  function getScopeId(scope) {
1881
1943
  return scope[K_SCOPE_ID];
1882
1944
  }
@@ -1972,7 +2034,7 @@ function _attr_content(nodeAccessor, scopeId, content, serializeReason) {
1972
2034
  if (_peek_scope_id() !== branchId) {
1973
2035
  if (shouldResume) writeScope(scopeId, {
1974
2036
  [BranchScopes + nodeAccessor]: writeScope(branchId, {}),
1975
- [ConditionalRenderer + nodeAccessor]: render?.["id"]
2037
+ [ConditionalRenderer + nodeAccessor]: rendererKey(render)
1976
2038
  });
1977
2039
  } else _scope_id();
1978
2040
  }
@@ -2806,7 +2868,7 @@ function _attr_textarea_value(scopeId, nodeAccessor, value, valueChange, seriali
2806
2868
  }
2807
2869
  function _textarea_value(value) {
2808
2870
  const escaped = _escape(normalizeStrAttrValue(value));
2809
- return escaped[0] === "\n" || escaped[0] === "\r" ? "\n" + escaped : escaped;
2871
+ return escaped[0] === "\n" ? "\n" + escaped : escaped;
2810
2872
  }
2811
2873
  function _attr_input_value(scopeId, nodeAccessor, value, valueChange, serializeType) {
2812
2874
  if (valueChange) writeControlledScope(2, scopeId, nodeAccessor, void 0, valueChange, serializeType);
@@ -2870,6 +2932,7 @@ function _attrs(data, nodeAccessor, scopeId, tagName) {
2870
2932
  result += _attr_input_checkedValue(scopeId, nodeAccessor, data.checkedValue, data.checkedValueChange, data.value, 1);
2871
2933
  skip = /^(?:value|checked(?:Value)?)(?:Change)?$|[\s/>"'=]/;
2872
2934
  } else if (data.valueChange) {
2935
+ assertNoValueBindingOnCheckable(data.type, data.valueChange);
2873
2936
  result += _attr_input_value(scopeId, nodeAccessor, data.value, data.valueChange, 1);
2874
2937
  skip = /^value(?:Change)?$|[\s/>"'=]/;
2875
2938
  }
@@ -2936,21 +2999,22 @@ function _attrs_partial_content(data, skip, nodeAccessor, scopeId, tagName, seri
2936
2999
  _attr_content(nodeAccessor, scopeId, data?.content, serializeReason);
2937
3000
  }
2938
3001
  function writeControlledScope(type, scopeId, nodeAccessor, value, valueChange, serializeType) {
2939
- assertHandlerIsFunction([
3002
+ var handlerName = [
2940
3003
  "checkedChange",
2941
3004
  "checkedValueChange",
2942
3005
  "valueChange",
2943
3006
  "valueChange",
2944
3007
  "openChange"
2945
- ][type], valueChange);
2946
- writeScope(scopeId, serializeType ? {
3008
+ ][type];
3009
+ assertHandlerIsFunction(handlerName, valueChange);
3010
+ setDebugSlotName(writeScope(scopeId, serializeType ? {
2947
3011
  [ControlledType + nodeAccessor]: type,
2948
3012
  [ControlledValue + nodeAccessor]: value,
2949
3013
  [ControlledHandler + nodeAccessor]: valueChange
2950
3014
  } : {
2951
3015
  [ControlledValue + nodeAccessor]: value,
2952
3016
  [ControlledHandler + nodeAccessor]: valueChange
2953
- });
3017
+ }), ControlledHandler + nodeAccessor, handlerName);
2954
3018
  }
2955
3019
  function stringAttr(name, value) {
2956
3020
  return value && " " + name + attrAssignment(value);
@@ -3014,10 +3078,10 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
3014
3078
  if (renderer === "textarea") {
3015
3079
  if (renderContent) throw new Error("A dynamic tag rendering a `<textarea>` cannot have `content` and must use the `value` attribute instead.");
3016
3080
  _html(_attr_textarea_value(branchId, `#${renderer.toLowerCase()}/0`, input.value, input.valueChange, 1));
3017
- } else if (renderContent) {
3018
- if (typeof renderContent !== "function") throw new Error(`Body content is not supported for the \`<${renderer}>\` tag.`);
3019
- if (renderer === "select" && ("value" in input || "valueChange" in input)) _attr_select_value(branchId, `#${renderer.toLowerCase()}/0`, input.value, input.valueChange, renderContent, 1);
3020
- else _dynamic_tag(branchId, `#${renderer.toLowerCase()}/0`, renderContent, void 0, 0, void 0, serializeReason);
3081
+ } else {
3082
+ if (renderContent && typeof renderContent !== "function") throw new Error(`Body content is not supported for the \`<${renderer}>\` tag.`);
3083
+ if (renderer === "select" && ("value" in input || "valueChange" in input)) _attr_select_value(branchId, `#${renderer.toLowerCase()}/0`, input.value, input.valueChange, renderContent ? () => _dynamic_tag(branchId, `#${renderer.toLowerCase()}/0`, renderContent, void 0, 0, void 0, serializeReason) : void 0, 1);
3084
+ else if (renderContent) _dynamic_tag(branchId, `#${renderer.toLowerCase()}/0`, renderContent, void 0, 0, void 0, serializeReason);
3021
3085
  }
3022
3086
  _html(`</${renderer}>`);
3023
3087
  } else if (content) throw new Error(`Body content is not supported for the \`<${renderer}>\` tag.`);
@@ -3030,6 +3094,7 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
3030
3094
  if (shouldResume || needsScript) _html(state.mark("'", scopeId + " " + accessor + " " + branchId));
3031
3095
  };
3032
3096
  renderNative();
3097
+ result = _el(branchId, DYNAMIC_TAG_VAR_REGISTER_ID);
3033
3098
  } else {
3034
3099
  const chunk = getChunk();
3035
3100
  const beforeBranch = shouldResume ? deferBranchStart(chunk) : void 0;
@@ -3053,16 +3118,17 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
3053
3118
  }
3054
3119
  }
3055
3120
  if (rendered) {
3056
- if (shouldResume) writeScope(scopeId, { [ConditionalRenderer + accessor]: renderer?.["id"] || renderer });
3121
+ if (shouldResume) writeScope(scopeId, { [ConditionalRenderer + accessor]: rendererKey(renderer) });
3057
3122
  } else _scope_id();
3058
3123
  return result;
3059
3124
  };
3060
- function _content(id, fn) {
3125
+ function _content(id, fn, scopeId) {
3061
3126
  fn["id"] = id;
3127
+ fn[Owner] = scopeId;
3062
3128
  return fn;
3063
3129
  }
3064
3130
  function _content_resume(id, fn, scopeId) {
3065
- return _resume(_content(id, fn), id, scopeId);
3131
+ return _resume(_content(id, fn, scopeId), id, scopeId);
3066
3132
  }
3067
3133
  const patchDynamicTag = ((originalDynamicTag) => (patch) => {
3068
3134
  _dynamic_tag = (scopeId, accessor, tag, input, content, inputIsArgs, resume) => {
@@ -3383,14 +3449,17 @@ function writeTriggerScript(html, triggers) {
3383
3449
  const exprs = triggers.map((trigger) => {
3384
3450
  const options = trigger.options && toObjectExpression(trigger.options);
3385
3451
  switch (trigger.type) {
3386
- case "visible": return `(e=>e&&new IntersectionObserver((e,i)=>e.some(e=>e.isIntersecting)&&i.disconnect()+l()${options ? `,${options}` : ""}).observe(e))(document.querySelector(${JSON.stringify(trigger.selector)})||l())`;
3452
+ case "visible": return `(e=>e&&new IntersectionObserver((e,i)=>e.some(e=>e.isIntersecting)&&i.disconnect()+l()${options ? `,${options}` : ""}).observe(e))(${querySelectorOrLoad(trigger.selector)})`;
3387
3453
  case "idle": return `(self.requestIdleCallback||l)(l${options ? `,${options}` : ""})`;
3388
3454
  case "media": return `(m=>m.matches?l():m.addEventListener("change",l,{once:1}))(matchMedia(${JSON.stringify(trigger.selector)}))`;
3389
- default: return `(e=>e?.addEventListener("${trigger.type.slice(3)}",l,{once:1}))(document.querySelector(${JSON.stringify(trigger.selector)})||l())`;
3455
+ default: return `(e=>e?.addEventListener("${trigger.type.slice(3)}",l,{once:1}))(${querySelectorOrLoad(trigger.selector)})`;
3390
3456
  }
3391
3457
  });
3392
3458
  writeScript(`((p,h,d,l=$=>{d||p.after(new Range().createContextualFragment(d=h))})=>${exprs.length > 1 ? `{${exprs.join(";")}}` : exprs[0]})(document.currentScript,${htmlStr})`);
3393
3459
  }
3460
+ function querySelectorOrLoad(selector) {
3461
+ return `document.querySelector(${JSON.stringify(selector)})||${`(console.warn(${JSON.stringify(`A lazy load trigger could not find an element matching "${selector}". The module was loaded immediately.`)}),l())`}`;
3462
+ }
3394
3463
  function toObjectExpression(options) {
3395
3464
  let result = "{";
3396
3465
  let sep = "";
@@ -33,6 +33,7 @@ const LoopKey = "#LoopKey";
33
33
  const PlaceholderContent = "#PlaceholderContent";
34
34
  const Renderer = "#Renderer";
35
35
  const TagVariable = "#TagVariable";
36
+ const Owner = "owner";
36
37
  const Embed = "embed";
37
38
  //#endregion
38
39
  //#region src/common/helpers.ts
@@ -222,10 +223,16 @@ function assertExclusiveAttrs(attrs, onError = throwErr) {
222
223
  (exclusiveAttrs ||= []).push("checkedValueChange");
223
224
  if ("checked" in attrs) exclusiveAttrs.push("checked");
224
225
  }
225
- if (attrs.valueChange) (exclusiveAttrs ||= []).push("valueChange");
226
+ if (attrs.valueChange) {
227
+ (exclusiveAttrs ||= []).push("valueChange");
228
+ if ("checked" in attrs && !exclusiveAttrs.includes("checked")) exclusiveAttrs.push("checked");
229
+ }
226
230
  if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
227
231
  }
228
232
  }
233
+ function assertNoValueBindingOnCheckable(type, valueChange) {
234
+ if (valueChange && /^(?:button|checkbox|hidden|image|radio|reset|submit)$/i.test(type)) console.error(`\`valueChange\` cannot be used on a \`type="${type}"\` \`<input>\` — user interaction can never change its \`value\`.` + (/^[cr]/i.test(type) ? " Bind `checked` or `checkedValue` instead." : ""));
235
+ }
229
236
  function assertHandlerIsFunction(name, value) {
230
237
  if (value && typeof value !== "function") throw new Error(`The \`${name}\` handler must be a function or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …), but received type "${typeof value}".`);
231
238
  }
@@ -246,6 +253,7 @@ function joinWithAnd(a) {
246
253
  //#endregion
247
254
  //#region src/common/meta.ts
248
255
  const DYNAMIC_TAG_SCRIPT_REGISTER_ID = "_dynamicTagScript";
256
+ const DYNAMIC_TAG_VAR_REGISTER_ID = "_dynamicTagVar";
249
257
  //#endregion
250
258
  //#region src/html/content.ts
251
259
  function _to_text(val) {
@@ -256,8 +264,8 @@ function _unescaped(val) {
256
264
  assertValidTextValue(val);
257
265
  return val ? val + "" : val === 0 ? "0" : "";
258
266
  }
259
- const unsafeXMLReg = /[<&]/g;
260
- const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;";
267
+ const unsafeXMLReg = /[<&\r]/g;
268
+ const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : c === "<" ? "&lt;" : "&#13;";
261
269
  const escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str;
262
270
  function _escape(val) {
263
271
  assertValidTextValue(val);
@@ -570,7 +578,18 @@ function setDebugInfo(obj, file, loc, vars) {
570
578
  DEBUG.set(obj, {
571
579
  file,
572
580
  loc,
573
- vars
581
+ vars,
582
+ slots: DEBUG.get(obj)?.slots
583
+ });
584
+ }
585
+ function setDebugSlotName(obj, accessor, name) {
586
+ const debug = DEBUG.get(obj);
587
+ if (debug) (debug.slots ??= {})[accessor] = name;
588
+ else DEBUG.set(obj, {
589
+ file: "",
590
+ loc: 0,
591
+ vars: void 0,
592
+ slots: { [accessor]: name }
574
593
  });
575
594
  }
576
595
  var Serializer = class {
@@ -1469,21 +1488,27 @@ function throwUnserializable(state, cause, ref = null, accessor = "") {
1469
1488
  if (cause !== void 0 && state.boundary?.abort) {
1470
1489
  let message = "Unable to serialize";
1471
1490
  let access = "";
1472
- while (ref?.accessor) {
1491
+ while (ref) {
1492
+ const { accessor } = ref;
1473
1493
  const debug = ref.parent?.debug;
1474
- if (debug) {
1475
- const varLoc = debug.vars?.[ref.accessor];
1476
- let debugAccess = ref.accessor;
1494
+ if (accessor && debug) {
1495
+ const rawAccessor = fromObjectKey(accessor);
1496
+ const varLoc = debug.vars?.[rawAccessor];
1497
+ const slotName = debug.slots?.[rawAccessor];
1498
+ let debugAccess = varLoc ? rawAccessor : void 0;
1477
1499
  let debugLoc = debug.loc;
1478
1500
  if (varLoc) if (Array.isArray(varLoc)) {
1479
1501
  debugAccess = varLoc[0];
1480
1502
  if (varLoc[1]) debugLoc = varLoc[1];
1481
1503
  } else debugLoc = varLoc;
1482
- message += ` ${JSON.stringify(debugAccess)} in ${debug.file}`;
1504
+ let display;
1505
+ if (debugAccess !== void 0) display = slotName && debugAccess.startsWith("...") ? `\`${slotName}\` from \`${debugAccess}\`` : JSON.stringify(debugAccess);
1506
+ else display = describeAccessor(rawAccessor, slotName) ?? JSON.stringify(rawAccessor);
1507
+ message += ` ${display} in ${debug.file}`;
1483
1508
  if (debugLoc) message += `:${debugLoc}`;
1484
1509
  break;
1485
1510
  }
1486
- access = toAccess(ref.accessor) + access;
1511
+ if (accessor) access = toAccess(accessor) + access;
1487
1512
  ref = ref.parent;
1488
1513
  }
1489
1514
  if (accessor) access = toAccess(accessor) + access;
@@ -1495,6 +1520,40 @@ function throwUnserializable(state, cause, ref = null, accessor = "") {
1495
1520
  state.boundary.abort(err);
1496
1521
  }
1497
1522
  }
1523
+ const accessorPrefixDescriptions = {
1524
+ BranchScopes: "the branch scopes",
1525
+ ClosureScopes: "the closure scopes",
1526
+ ClosureSignalIndex: "the closure signal index",
1527
+ ConditionalRenderer: "the conditional renderer",
1528
+ ControlledObserver: "the controlled observer",
1529
+ ControlledHandler: "the change handler",
1530
+ ControlledType: "the controlled type",
1531
+ ControlledValue: "the controlled value",
1532
+ DynamicHTMLLastChild: "the dynamic html",
1533
+ EventAttributes: "the event handlers",
1534
+ IdFallback: "the generated id",
1535
+ KeyedScopes: "the keyed scopes",
1536
+ Lifecycle: "the lifecycle handlers",
1537
+ Promise: "the pending promise",
1538
+ TagVariableChange: "the tag variable change handler"
1539
+ };
1540
+ function describeAccessor(accessor, slotName) {
1541
+ const sep = accessor.indexOf(":");
1542
+ if (~sep) {
1543
+ const description = slotName === void 0 ? accessorPrefixDescriptions[accessor.slice(0, sep)] : `the \`${slotName}\` handler`;
1544
+ if (description) {
1545
+ const node = /^#([a-z-]+)\//i.exec(accessor.slice(sep + 1));
1546
+ return node ? `${description} of \`<${node[1]}>\`` : description;
1547
+ }
1548
+ }
1549
+ }
1550
+ function fromObjectKey(key) {
1551
+ try {
1552
+ if (key[0] === "\"") return JSON.parse(key.replace(/\\x/g, "\\u00"));
1553
+ if (key[0] === "[") return JSON.parse(key.slice(1, -1));
1554
+ } catch {}
1555
+ return key;
1556
+ }
1498
1557
  function trackChannel(state, ref) {
1499
1558
  const refReadyId = ref.channel?.readyId;
1500
1559
  if (!refReadyId || refReadyId === state.channel?.readyId) return true;
@@ -1875,6 +1934,9 @@ function getContext(key) {
1875
1934
  function getState() {
1876
1935
  return $chunk.boundary.state;
1877
1936
  }
1937
+ function rendererKey(renderer) {
1938
+ return renderer?.["owner"] === void 0 ? renderer?.["id"] || renderer : renderer["id"] + " " + renderer[Owner];
1939
+ }
1878
1940
  function getScopeId(scope) {
1879
1941
  return scope[K_SCOPE_ID];
1880
1942
  }
@@ -1970,7 +2032,7 @@ function _attr_content(nodeAccessor, scopeId, content, serializeReason) {
1970
2032
  if (_peek_scope_id() !== branchId) {
1971
2033
  if (shouldResume) writeScope(scopeId, {
1972
2034
  [BranchScopes + nodeAccessor]: writeScope(branchId, {}),
1973
- [ConditionalRenderer + nodeAccessor]: render?.["id"]
2035
+ [ConditionalRenderer + nodeAccessor]: rendererKey(render)
1974
2036
  });
1975
2037
  } else _scope_id();
1976
2038
  }
@@ -2804,7 +2866,7 @@ function _attr_textarea_value(scopeId, nodeAccessor, value, valueChange, seriali
2804
2866
  }
2805
2867
  function _textarea_value(value) {
2806
2868
  const escaped = _escape(normalizeStrAttrValue(value));
2807
- return escaped[0] === "\n" || escaped[0] === "\r" ? "\n" + escaped : escaped;
2869
+ return escaped[0] === "\n" ? "\n" + escaped : escaped;
2808
2870
  }
2809
2871
  function _attr_input_value(scopeId, nodeAccessor, value, valueChange, serializeType) {
2810
2872
  if (valueChange) writeControlledScope(2, scopeId, nodeAccessor, void 0, valueChange, serializeType);
@@ -2868,6 +2930,7 @@ function _attrs(data, nodeAccessor, scopeId, tagName) {
2868
2930
  result += _attr_input_checkedValue(scopeId, nodeAccessor, data.checkedValue, data.checkedValueChange, data.value, 1);
2869
2931
  skip = /^(?:value|checked(?:Value)?)(?:Change)?$|[\s/>"'=]/;
2870
2932
  } else if (data.valueChange) {
2933
+ assertNoValueBindingOnCheckable(data.type, data.valueChange);
2871
2934
  result += _attr_input_value(scopeId, nodeAccessor, data.value, data.valueChange, 1);
2872
2935
  skip = /^value(?:Change)?$|[\s/>"'=]/;
2873
2936
  }
@@ -2934,21 +2997,22 @@ function _attrs_partial_content(data, skip, nodeAccessor, scopeId, tagName, seri
2934
2997
  _attr_content(nodeAccessor, scopeId, data?.content, serializeReason);
2935
2998
  }
2936
2999
  function writeControlledScope(type, scopeId, nodeAccessor, value, valueChange, serializeType) {
2937
- assertHandlerIsFunction([
3000
+ var handlerName = [
2938
3001
  "checkedChange",
2939
3002
  "checkedValueChange",
2940
3003
  "valueChange",
2941
3004
  "valueChange",
2942
3005
  "openChange"
2943
- ][type], valueChange);
2944
- writeScope(scopeId, serializeType ? {
3006
+ ][type];
3007
+ assertHandlerIsFunction(handlerName, valueChange);
3008
+ setDebugSlotName(writeScope(scopeId, serializeType ? {
2945
3009
  [ControlledType + nodeAccessor]: type,
2946
3010
  [ControlledValue + nodeAccessor]: value,
2947
3011
  [ControlledHandler + nodeAccessor]: valueChange
2948
3012
  } : {
2949
3013
  [ControlledValue + nodeAccessor]: value,
2950
3014
  [ControlledHandler + nodeAccessor]: valueChange
2951
- });
3015
+ }), ControlledHandler + nodeAccessor, handlerName);
2952
3016
  }
2953
3017
  function stringAttr(name, value) {
2954
3018
  return value && " " + name + attrAssignment(value);
@@ -3012,10 +3076,10 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
3012
3076
  if (renderer === "textarea") {
3013
3077
  if (renderContent) throw new Error("A dynamic tag rendering a `<textarea>` cannot have `content` and must use the `value` attribute instead.");
3014
3078
  _html(_attr_textarea_value(branchId, `#${renderer.toLowerCase()}/0`, input.value, input.valueChange, 1));
3015
- } else if (renderContent) {
3016
- if (typeof renderContent !== "function") throw new Error(`Body content is not supported for the \`<${renderer}>\` tag.`);
3017
- if (renderer === "select" && ("value" in input || "valueChange" in input)) _attr_select_value(branchId, `#${renderer.toLowerCase()}/0`, input.value, input.valueChange, renderContent, 1);
3018
- else _dynamic_tag(branchId, `#${renderer.toLowerCase()}/0`, renderContent, void 0, 0, void 0, serializeReason);
3079
+ } else {
3080
+ if (renderContent && typeof renderContent !== "function") throw new Error(`Body content is not supported for the \`<${renderer}>\` tag.`);
3081
+ if (renderer === "select" && ("value" in input || "valueChange" in input)) _attr_select_value(branchId, `#${renderer.toLowerCase()}/0`, input.value, input.valueChange, renderContent ? () => _dynamic_tag(branchId, `#${renderer.toLowerCase()}/0`, renderContent, void 0, 0, void 0, serializeReason) : void 0, 1);
3082
+ else if (renderContent) _dynamic_tag(branchId, `#${renderer.toLowerCase()}/0`, renderContent, void 0, 0, void 0, serializeReason);
3019
3083
  }
3020
3084
  _html(`</${renderer}>`);
3021
3085
  } else if (content) throw new Error(`Body content is not supported for the \`<${renderer}>\` tag.`);
@@ -3028,6 +3092,7 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
3028
3092
  if (shouldResume || needsScript) _html(state.mark("'", scopeId + " " + accessor + " " + branchId));
3029
3093
  };
3030
3094
  renderNative();
3095
+ result = _el(branchId, DYNAMIC_TAG_VAR_REGISTER_ID);
3031
3096
  } else {
3032
3097
  const chunk = getChunk();
3033
3098
  const beforeBranch = shouldResume ? deferBranchStart(chunk) : void 0;
@@ -3051,16 +3116,17 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
3051
3116
  }
3052
3117
  }
3053
3118
  if (rendered) {
3054
- if (shouldResume) writeScope(scopeId, { [ConditionalRenderer + accessor]: renderer?.["id"] || renderer });
3119
+ if (shouldResume) writeScope(scopeId, { [ConditionalRenderer + accessor]: rendererKey(renderer) });
3055
3120
  } else _scope_id();
3056
3121
  return result;
3057
3122
  };
3058
- function _content(id, fn) {
3123
+ function _content(id, fn, scopeId) {
3059
3124
  fn["id"] = id;
3125
+ fn[Owner] = scopeId;
3060
3126
  return fn;
3061
3127
  }
3062
3128
  function _content_resume(id, fn, scopeId) {
3063
- return _resume(_content(id, fn), id, scopeId);
3129
+ return _resume(_content(id, fn, scopeId), id, scopeId);
3064
3130
  }
3065
3131
  const patchDynamicTag = ((originalDynamicTag) => (patch) => {
3066
3132
  _dynamic_tag = (scopeId, accessor, tag, input, content, inputIsArgs, resume) => {
@@ -3381,14 +3447,17 @@ function writeTriggerScript(html, triggers) {
3381
3447
  const exprs = triggers.map((trigger) => {
3382
3448
  const options = trigger.options && toObjectExpression(trigger.options);
3383
3449
  switch (trigger.type) {
3384
- case "visible": return `(e=>e&&new IntersectionObserver((e,i)=>e.some(e=>e.isIntersecting)&&i.disconnect()+l()${options ? `,${options}` : ""}).observe(e))(document.querySelector(${JSON.stringify(trigger.selector)})||l())`;
3450
+ case "visible": return `(e=>e&&new IntersectionObserver((e,i)=>e.some(e=>e.isIntersecting)&&i.disconnect()+l()${options ? `,${options}` : ""}).observe(e))(${querySelectorOrLoad(trigger.selector)})`;
3385
3451
  case "idle": return `(self.requestIdleCallback||l)(l${options ? `,${options}` : ""})`;
3386
3452
  case "media": return `(m=>m.matches?l():m.addEventListener("change",l,{once:1}))(matchMedia(${JSON.stringify(trigger.selector)}))`;
3387
- default: return `(e=>e?.addEventListener("${trigger.type.slice(3)}",l,{once:1}))(document.querySelector(${JSON.stringify(trigger.selector)})||l())`;
3453
+ default: return `(e=>e?.addEventListener("${trigger.type.slice(3)}",l,{once:1}))(${querySelectorOrLoad(trigger.selector)})`;
3388
3454
  }
3389
3455
  });
3390
3456
  writeScript(`((p,h,d,l=$=>{d||p.after(new Range().createContextualFragment(d=h))})=>${exprs.length > 1 ? `{${exprs.join(";")}}` : exprs[0]})(document.currentScript,${htmlStr})`);
3391
3457
  }
3458
+ function querySelectorOrLoad(selector) {
3459
+ return `document.querySelector(${JSON.stringify(selector)})||${`(console.warn(${JSON.stringify(`A lazy load trigger could not find an element matching "${selector}". The module was loaded immediately.`)}),l())`}`;
3460
+ }
3392
3461
  function toObjectExpression(options) {
3393
3462
  let result = "{";
3394
3463
  let sep = "";
@@ -1,12 +1,12 @@
1
- let require_control_flow = require("../dom-B-XpL2_H.js"), handlePendingTry = (fn, scope, branch) => {
1
+ let require_control_flow = require("../dom-59H9kVUF.js"), handlePendingTry = (fn, scope, branch) => {
2
2
  for (; branch;) {
3
3
  if (branch.O?.i) return (branch.J ||= []).push(fn, scope);
4
4
  branch = branch.N;
5
5
  }
6
6
  };
7
7
  //#region src/dom/catch.feat.ts
8
- require_control_flow.Yt((runEffects) => (effects, checkPending = require_control_flow.Xt.has(effects)) => {
9
- if (checkPending || require_control_flow.Jt.has(effects)) {
8
+ require_control_flow.Xt((runEffects) => (effects, checkPending = require_control_flow.Zt.has(effects)) => {
9
+ if (checkPending || require_control_flow.Yt.has(effects)) {
10
10
  let i = 0, fn, scope, branch;
11
11
  for (; i < effects.length;) fn = effects[i++], scope = effects[i++], (branch = scope.F)?.H !== 0 && !(checkPending && handlePendingTry(fn, scope, branch)) && fn(scope);
12
12
  } else runEffects(effects);
@@ -19,7 +19,7 @@ require_control_flow.Yt((runEffects) => (effects, checkPending = require_control
19
19
  }
20
20
  render.f = 0, runRender(render);
21
21
  } catch (error) {
22
- require_control_flow.h(render.b, error);
22
+ require_control_flow.g(render.b, error);
23
23
  }
24
24
  });
25
25
  //#endregion
@@ -4,7 +4,7 @@ let handlePendingTry = (fn, scope, branch) => {
4
4
  branch = branch.N;
5
5
  }
6
6
  };
7
- import { Jt as caughtError, Xt as placeholderShown, Yt as installCatch, h as renderCatch } from "../dom-6hBvZW7X.mjs";
7
+ import { Xt as installCatch, Yt as caughtError, Zt as placeholderShown, g as renderCatch } from "../dom-BKDjlXIl.mjs";
8
8
  //#region src/dom/catch.feat.ts
9
9
  installCatch((runEffects) => (effects, checkPending = placeholderShown.has(effects)) => {
10
10
  if (checkPending || caughtError.has(effects)) {
@@ -11,9 +11,12 @@ export declare function _try(nodeAccessor: EncodedAccessor, template?: string |
11
11
  export declare function renderCatch(scope: Scope, error: unknown): void;
12
12
  export declare const _if: (nodeAccessor: EncodedAccessor, ...branchesArgs: (string | SetupFn | 0)[]) => (scope: Scope, newBranch: number) => void;
13
13
  export declare const _show: (nodeAccessor: EncodedAccessor, startNodeAccessor?: EncodedAccessor, endNodeAccessor?: EncodedAccessor) => (scope: Scope, display: unknown) => void;
14
+ export declare function rendererKey(renderer: Renderer | string | undefined): string | Renderer | undefined;
14
15
  export declare function patchDynamicTag(fn: <T extends typeof _dynamic_tag>(cond: T) => T): void;
15
16
  export declare let _dynamic_tag: (nodeAccessor: EncodedAccessor, getContent?: ((scope: Scope) => Renderer) | 0, getTagVar?: (() => Signal<unknown>) | 0, inputIsArgs?: 1) => Signal<Renderer | string | undefined>;
16
17
  export declare const _dynamic_tag_content: (nodeAccessor: EncodedAccessor) => Signal<Renderer | undefined>;
18
+ export declare let bindNativeTagVar: undefined | ((branch: Scope) => void);
19
+ export declare function installDynamicTagVar(bind: typeof bindNativeTagVar): void;
17
20
  export declare const _resume_dynamic_tag: () => typeof dynamicTagScript;
18
21
  declare function dynamicTagScript(branch: Scope): void;
19
22
  export declare function setConditionalRenderer<T>(scope: Scope, nodeAccessor: Accessor, newRenderer: T, createBranch: ($global: Scope[typeof AccessorProp.Global], renderer: NonNullable<T>, parentScope: Scope, parentNode: ParentNode) => BranchScope): void;
@@ -1,3 +1,3 @@
1
- let require_control_flow = require("../dom-B-XpL2_H.js");
2
- require_control_flow.R[0] = require_control_flow.w, require_control_flow.R[1] = require_control_flow.S, require_control_flow.R[2] = require_control_flow.k;
1
+ let require_control_flow = require("../dom-59H9kVUF.js");
2
+ require_control_flow.z[0] = require_control_flow.T, require_control_flow.z[1] = require_control_flow.C, require_control_flow.z[2] = require_control_flow.A;
3
3
  //#endregion
@@ -1,3 +1,3 @@
1
- import { R as controllableScripts, S as _attr_input_checkedValue_script, k as _attr_input_value_script, w as _attr_input_checked_script } from "../dom-6hBvZW7X.mjs";
1
+ import { A as _attr_input_value_script, C as _attr_input_checkedValue_script, T as _attr_input_checked_script, z as controllableScripts } from "../dom-BKDjlXIl.mjs";
2
2
  controllableScripts[0] = _attr_input_checked_script, controllableScripts[1] = _attr_input_checkedValue_script, controllableScripts[2] = _attr_input_value_script;
3
3
  //#endregion
@@ -1,4 +1,4 @@
1
- let require_control_flow = require("../dom-B-XpL2_H.js");
1
+ let require_control_flow = require("../dom-59H9kVUF.js");
2
2
  //#region src/dom/controllable-open.feat.ts
3
- require_control_flow.R[4] = require_control_flow.v;
3
+ require_control_flow.z[4] = require_control_flow.y;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { R as controllableScripts, v as _attr_details_or_dialog_open_script } from "../dom-6hBvZW7X.mjs";
1
+ import { y as _attr_details_or_dialog_open_script, z as controllableScripts } from "../dom-BKDjlXIl.mjs";
2
2
  //#region src/dom/controllable-open.feat.ts
3
3
  controllableScripts[4] = _attr_details_or_dialog_open_script;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- let require_control_flow = require("../dom-B-XpL2_H.js");
1
+ let require_control_flow = require("../dom-59H9kVUF.js");
2
2
  //#region src/dom/controllable-select.feat.ts
3
- require_control_flow.R[3] = require_control_flow.M;
3
+ require_control_flow.z[3] = require_control_flow.N;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { M as _attr_select_value_script, R as controllableScripts } from "../dom-6hBvZW7X.mjs";
1
+ import { N as _attr_select_value_script, z as controllableScripts } from "../dom-BKDjlXIl.mjs";
2
2
  //#region src/dom/controllable-select.feat.ts
3
3
  controllableScripts[3] = _attr_select_value_script;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- let require_control_flow = require("../dom-B-XpL2_H.js");
1
+ let require_control_flow = require("../dom-59H9kVUF.js");
2
2
  //#region src/dom/controllable-textarea.feat.ts
3
- require_control_flow.R[2] = require_control_flow.k;
3
+ require_control_flow.z[2] = require_control_flow.A;
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { R as controllableScripts, k as _attr_input_value_script } from "../dom-6hBvZW7X.mjs";
1
+ import { A as _attr_input_value_script, z as controllableScripts } from "../dom-BKDjlXIl.mjs";
2
2
  //#region src/dom/controllable-textarea.feat.ts
3
3
  controllableScripts[2] = _attr_input_value_script;
4
4
  //#endregion
@@ -1,3 +1,3 @@
1
- let require_control_flow = require("../dom-B-XpL2_H.js");
2
- require("./controllable-input.feat.js"), require("./controllable-open.feat.js"), require("./controllable-select.feat.js"), require_control_flow.L.INPUT = require_control_flow.N, require_control_flow.L.TEXTAREA = require_control_flow.I, require_control_flow.L.SELECT = require_control_flow.F, require_control_flow.L.DETAILS = require_control_flow.L.DIALOG = require_control_flow.P;
1
+ let require_control_flow = require("../dom-59H9kVUF.js");
2
+ require("./controllable-input.feat.js"), require("./controllable-open.feat.js"), require("./controllable-select.feat.js"), require_control_flow.R.INPUT = require_control_flow.P, require_control_flow.R.TEXTAREA = require_control_flow.L, require_control_flow.R.SELECT = require_control_flow.I, require_control_flow.R.DETAILS = require_control_flow.R.DIALOG = require_control_flow.F;
3
3
  //#endregion