octane 0.2.13 → 0.2.15

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 (36) hide show
  1. package/dist/cjs/constants.cjs +7 -7
  2. package/dist/cjs/dom-binding-claims.cjs +28 -0
  3. package/dist/cjs/dom-binding-handoff.cjs +2 -2
  4. package/dist/cjs/dom-bindings.cjs +105 -13
  5. package/dist/cjs/runtime.cjs +311 -55
  6. package/dist/cjs/server/streamed-signals.cjs +3 -2
  7. package/dist/cjs/signals/control-binding.cjs +33 -9
  8. package/dist/cjs/signals/control-handoff.cjs +39 -0
  9. package/dist/cjs/stream-protocol.cjs +6 -0
  10. package/dist/cjs/version.cjs +1 -1
  11. package/dist/compiler/compile.js +86 -24
  12. package/dist/compiler/dom-binding-program.js +30 -3
  13. package/dist/compiler/dom-bindings.js +115 -34
  14. package/dist/compiler/volar.js +58 -17
  15. package/dist/constants.d.ts +2 -2
  16. package/dist/constants.js +2 -2
  17. package/dist/dom-binding-claims.d.ts +1 -0
  18. package/dist/dom-binding-claims.js +4 -0
  19. package/dist/dom-binding-handoff.d.ts +6 -4
  20. package/dist/dom-binding-handoff.js +1 -1
  21. package/dist/dom-binding-program.d.ts +2 -1
  22. package/dist/dom-binding-program.js +16 -1
  23. package/dist/dom-bindings.d.ts +5 -2
  24. package/dist/dom-bindings.js +105 -13
  25. package/dist/runtime.d.ts +34 -3
  26. package/dist/runtime.js +314 -55
  27. package/dist/server/streamed-signals.js +3 -2
  28. package/dist/signals/control-binding.d.ts +9 -5
  29. package/dist/signals/control-binding.js +38 -6
  30. package/dist/signals/control-handoff.d.ts +26 -0
  31. package/dist/signals/control-handoff.js +12 -0
  32. package/dist/signals/index.d.ts +1 -0
  33. package/dist/stream-protocol.d.ts +4 -0
  34. package/dist/stream-protocol.js +4 -0
  35. package/dist/version.js +1 -1
  36. package/package.json +1 -1
@@ -33,7 +33,7 @@ __export(constants_exports, {
33
33
  HYDRATE_SEED_ATTR: () => HYDRATE_SEED_ATTR,
34
34
  HYDRATE_STATIC_END: () => HYDRATE_STATIC_END,
35
35
  HYDRATE_STATIC_ID_COUNT_PREFIX: () => HYDRATE_STATIC_ID_COUNT_PREFIX,
36
- HYDRATE_STREAM_TOKEN_ATTR: () => import_stream_protocol.HYDRATE_STREAM_TOKEN_ATTR,
36
+ HYDRATE_STREAM_TOKEN_ATTR: () => import_stream_protocol2.HYDRATE_STREAM_TOKEN_ATTR,
37
37
  HYDRATE_WHEN_ATTR: () => HYDRATE_WHEN_ATTR,
38
38
  HYDRATION_END: () => HYDRATION_END,
39
39
  HYDRATION_FOR_EMPTY: () => HYDRATION_FOR_EMPTY,
@@ -46,16 +46,16 @@ __export(constants_exports, {
46
46
  POSITIVE_NUMERIC_ATTR_PROPS: () => POSITIVE_NUMERIC_ATTR_PROPS,
47
47
  REJECTION_SENTINEL_KEY: () => REJECTION_SENTINEL_KEY,
48
48
  SIGNAL_CONTROL_ATTR: () => import_hydration_markers.SIGNAL_CONTROL_ATTR,
49
- STREAM_BOUNDARY_ATTR: () => import_stream_protocol2.STREAM_BOUNDARY_ATTR,
49
+ STREAM_BOUNDARY_ATTR: () => import_stream_protocol3.STREAM_BOUNDARY_ATTR,
50
50
  STREAM_RESOURCE_ATTR: () => STREAM_RESOURCE_ATTR,
51
- STREAM_SCRIPT_ATTR: () => STREAM_SCRIPT_ATTR,
51
+ STREAM_SCRIPT_ATTR: () => import_stream_protocol4.STREAM_SCRIPT_ATTR,
52
52
  STREAM_SEED_ATTR: () => STREAM_SEED_ATTR,
53
53
  STREAM_SEED_COMMENT: () => STREAM_SEED_COMMENT,
54
54
  STREAM_SEGMENT_ATTR: () => STREAM_SEGMENT_ATTR,
55
55
  SUSPENSE_RESOLVED_COMMENT: () => SUSPENSE_RESOLVED_COMMENT,
56
56
  SUSPENSE_RESOLVED_NATIVE_ATTR: () => SUSPENSE_RESOLVED_NATIVE_ATTR,
57
57
  SUSPENSE_RESOLVED_SEED_ATTR: () => SUSPENSE_RESOLVED_SEED_ATTR,
58
- SUSPENSE_SCRIPT_ATTR: () => SUSPENSE_SCRIPT_ATTR,
58
+ SUSPENSE_SCRIPT_ATTR: () => import_stream_protocol.SUSPENSE_SCRIPT_ATTR,
59
59
  SUSPENSE_SEED_WIRE_PREFIX: () => SUSPENSE_SEED_WIRE_PREFIX,
60
60
  SVG_ONLY_TAGS: () => SVG_ONLY_TAGS,
61
61
  UNDEFINED_SENTINEL_KEY: () => UNDEFINED_SENTINEL_KEY,
@@ -67,8 +67,10 @@ __export(constants_exports, {
67
67
  });
68
68
  module.exports = __toCommonJS(constants_exports);
69
69
  var import_stream_protocol = require("./stream-protocol.cjs");
70
- var import_hydration_markers = require("./hydration-markers.cjs");
71
70
  var import_stream_protocol2 = require("./stream-protocol.cjs");
71
+ var import_hydration_markers = require("./hydration-markers.cjs");
72
+ var import_stream_protocol3 = require("./stream-protocol.cjs");
73
+ var import_stream_protocol4 = require("./stream-protocol.cjs");
72
74
  var import_dom_tables = require("./dom-tables.cjs");
73
75
  const HYDRATION_START = "[";
74
76
  const HYDRATION_END = "]";
@@ -80,7 +82,6 @@ const FOR_BLOCK_OPEN_EMPTY = `<!--${HYDRATION_FOR_EMPTY}-->`;
80
82
  const FOR_BLOCK_OPEN_ITEMS = `<!--${HYDRATION_FOR_ITEMS}-->`;
81
83
  const EMPTY_COMMENT = "<!---->";
82
84
  const HYDRATION_TEXT_SEP = " ";
83
- const SUSPENSE_SCRIPT_ATTR = "data-octane-suspense";
84
85
  const SUSPENSE_RESOLVED_COMMENT = "oct-suspense:";
85
86
  const SUSPENSE_RESOLVED_SEED_ATTR = "data-octane-suspense-seeds";
86
87
  const SUSPENSE_RESOLVED_NATIVE_ATTR = "data-octane-suspense-signals";
@@ -101,7 +102,6 @@ const HYDRATE_ID_COUNT_ATTR = "data-octane-hydrate-id-count";
101
102
  const HYDRATE_SEED_ATTR = "data-octane-hydrate-seed";
102
103
  const STREAM_SEGMENT_ATTR = "data-oct-s";
103
104
  const STREAM_SEED_ATTR = "data-oct-seed";
104
- const STREAM_SCRIPT_ATTR = "data-octane-stream";
105
105
  const STREAM_RESOURCE_ATTR = "data-oct-fr";
106
106
  const STREAM_SEED_COMMENT = "oct-seed:";
107
107
  const VOID_ELEMENTS = import_dom_tables.VOID_ELEMENTS;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var dom_binding_claims_exports = {};
20
+ __export(dom_binding_claims_exports, {
21
+ domBindingClaims: () => domBindingClaims
22
+ });
23
+ module.exports = __toCommonJS(dom_binding_claims_exports);
24
+ const domBindingClaims = /* @__PURE__ */ new WeakMap();
25
+ // Annotate the CommonJS export names for ESM import in node:
26
+ 0 && (module.exports = {
27
+ domBindingClaims
28
+ });
@@ -18,7 +18,7 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var dom_binding_handoff_exports = {};
20
20
  __export(dom_binding_handoff_exports, {
21
- BINDING_HANDOFF: () => BINDING_HANDOFF,
21
+ BINDING_HANDOFF: () => import_control_handoff.BINDING_HANDOFF,
22
22
  beginBindingEvent: () => beginBindingEvent,
23
23
  claimBindingHandoff: () => claimBindingHandoff,
24
24
  consumeBindingEvent: () => consumeBindingEvent,
@@ -28,7 +28,7 @@ __export(dom_binding_handoff_exports, {
28
28
  releaseBindingHandoff: () => releaseBindingHandoff
29
29
  });
30
30
  module.exports = __toCommonJS(dom_binding_handoff_exports);
31
- const BINDING_HANDOFF = /* @__PURE__ */ Symbol.for("octane.binding-handoff");
31
+ var import_control_handoff = require("./signals/control-handoff.cjs");
32
32
  const events = /* @__PURE__ */ new WeakMap();
33
33
  const delivered = /* @__PURE__ */ new WeakMap();
34
34
  function registerBindingEvent(node, type) {
@@ -31,7 +31,11 @@ __export(dom_bindings_exports, {
31
31
  });
32
32
  module.exports = __toCommonJS(dom_bindings_exports);
33
33
  var import_class_names = require("./class-names.cjs");
34
+ var import_dom_binding_claims = require("./dom-binding-claims.cjs");
34
35
  var import_sanitize_url = require("./sanitize-url.cjs");
36
+ var import_stream_protocol = require("./stream-protocol.cjs");
37
+ var import_native_read_seeds = require("./signals/native-read-seeds.cjs");
38
+ var import_control_handoff = require("./signals/control-handoff.cjs");
35
39
  var import_owner_context = require("./signals/owner-context.cjs");
36
40
  var import_read_protocol = require("./signals/read-protocol.cjs");
37
41
  function unbound(value) {
@@ -88,6 +92,11 @@ function __releaseBinding(node, name) {
88
92
  const channels = claims.get(node);
89
93
  channels.delete(name);
90
94
  if (channels.size === 0) claims.delete(node);
95
+ const published = import_dom_binding_claims.domBindingClaims.get(node);
96
+ if (published) {
97
+ published.delete(name);
98
+ if (published.size === 0) import_dom_binding_claims.domBindingClaims.delete(node);
99
+ }
91
100
  }
92
101
  function resolveNodes(root, descriptor) {
93
102
  if (root?.nodeType !== 1 || root.getAttribute("data-octane-bindings") !== descriptor.id || descriptor.nodes.length === 0) {
@@ -97,9 +106,9 @@ function resolveNodes(root, descriptor) {
97
106
  const nodes = [];
98
107
  const childIndices = [];
99
108
  for (let i = 0; i < descriptor.nodes.length; i++) {
100
- const [parent, tag, namespace, children] = descriptor.nodes[i];
109
+ const [parent, tag, namespace, children, , text] = descriptor.nodes[i];
101
110
  const node = i === 0 ? parent === -1 ? root : void 0 : parent >= 0 && parent < i && descriptor.nodes[parent][3] !== null ? nodes[parent]?.children[childIndices[parent]++] : void 0;
102
- if (node === void 0 || descriptor.nodes[i][4] === true || node.localName !== tag || node.namespaceURI !== namespaces[namespace] || children !== null && (node.childNodes.length !== children || node.children.length !== children)) {
111
+ if (node === void 0 || descriptor.nodes[i][4] === true || node.localName !== tag || node.namespaceURI !== namespaces[namespace] || (text ? node.childNodes.length > 1 || node.firstChild !== null && node.firstChild.nodeType !== 3 : children !== null && (node.childNodes.length !== children || node.children.length !== children))) {
103
112
  throw new Error("DOM bindings cannot adopt a mismatched static element topology.");
104
113
  }
105
114
  nodes.push(node);
@@ -140,9 +149,9 @@ function resolveAddressedNodes(root, descriptor) {
140
149
  }
141
150
  const childCounts = new Array(descriptor.nodes.length).fill(0);
142
151
  for (let i = 0; i < descriptor.nodes.length; i++) {
143
- const [parent, tag, namespace, children, openChildren] = descriptor.nodes[i];
152
+ const [parent, tag, namespace, children, openChildren, text] = descriptor.nodes[i];
144
153
  const node = nodes[i];
145
- if (node === void 0 || node.localName !== tag || node.namespaceURI !== namespaces[namespace] || (i === 0 ? parent !== -1 || node !== root : parent < 0 || parent >= i || descriptor.nodes[parent][3] === null || node.parentElement !== nodes[parent] || descriptor.nodes[parent][4] !== true && nodes[parent].children[childCounts[parent]] !== node) || openChildren && children === null || children !== null && !openChildren && (node.childNodes.length !== children || node.children.length !== children)) {
154
+ if (node === void 0 || node.localName !== tag || node.namespaceURI !== namespaces[namespace] || (i === 0 ? parent !== -1 || node !== root : parent < 0 || parent >= i || descriptor.nodes[parent][3] === null || node.parentElement !== nodes[parent] || descriptor.nodes[parent][4] !== true && nodes[parent].children[childCounts[parent]] !== node) || openChildren && children === null || (text ? node.childNodes.length > 1 || node.firstChild !== null && node.firstChild.nodeType !== 3 : children !== null && !openChildren && (node.childNodes.length !== children || node.children.length !== children))) {
146
155
  throw new Error("DOM bindings cannot adopt a mismatched addressed element topology.");
147
156
  }
148
157
  if (parent !== -1) childCounts[parent]++;
@@ -157,6 +166,11 @@ function resolveAddressedNodes(root, descriptor) {
157
166
  function normalize(binding, value) {
158
167
  const type = typeof value;
159
168
  switch (binding[1]) {
169
+ case "text":
170
+ if (value == null || value === false) return "";
171
+ if (type !== "string" && type !== "number" && type !== "bigint" && type !== "boolean")
172
+ throw new TypeError("DOM binding text must be a synchronous scalar.");
173
+ return String(value);
160
174
  case "styleObject":
161
175
  return value;
162
176
  case "class":
@@ -184,7 +198,11 @@ function normalize(binding, value) {
184
198
  }
185
199
  function write(node, binding, value) {
186
200
  const name = binding[2];
187
- if (binding[1] === "classToken") {
201
+ if (binding[1] === "text") {
202
+ const text = node.firstChild;
203
+ if (text === null) node.appendChild(node.ownerDocument.createTextNode(value));
204
+ else if (text.nodeValue !== value) text.nodeValue = value;
205
+ } else if (binding[1] === "classToken") {
188
206
  node.classList.toggle(name, value !== null);
189
207
  } else if (binding[1] === "url") {
190
208
  if (value === "" && !(name === "href" && node.localName === "a")) value = null;
@@ -283,16 +301,28 @@ function __adoptBindings(root, descriptor, source, options) {
283
301
  let dirty = false;
284
302
  let revision = 0;
285
303
  let unsubscribe;
304
+ let publicationRetries;
305
+ let published;
286
306
  const signal = options?.signal;
287
- const dispose = () => {
288
- if (disposed) return;
307
+ const dispose = (_disposal, publish, preservePresentation = false) => {
308
+ if (disposed) {
309
+ publish?.();
310
+ return;
311
+ }
289
312
  disposed = true;
313
+ publicationRetries?.clear();
290
314
  signal?.removeEventListener("abort", dispose);
291
315
  let failed = false;
292
316
  let failure;
317
+ try {
318
+ publish?.();
319
+ } catch (error) {
320
+ failed = true;
321
+ failure = error;
322
+ }
293
323
  for (const connection of signalConnections?.values() ?? []) {
294
324
  try {
295
- connection.dispose();
325
+ connection.dispose(preservePresentation);
296
326
  } catch (error) {
297
327
  if (!failed) {
298
328
  failed = true;
@@ -302,7 +332,7 @@ function __adoptBindings(root, descriptor, source, options) {
302
332
  }
303
333
  for (const connection of projections ? new Set(projections.values()) : []) {
304
334
  try {
305
- connection.dispose();
335
+ connection.dispose(preservePresentation);
306
336
  } catch (error) {
307
337
  if (!failed) {
308
338
  failed = true;
@@ -327,9 +357,9 @@ function __adoptBindings(root, descriptor, source, options) {
327
357
  for (let i = 0; i < owned.length; i++) {
328
358
  const [node, name] = owned[i];
329
359
  try {
330
- groups?.get(i)?.dispose();
331
- styles?.get(i)?.dispose();
332
- if (bindings[i][1] === "classToken" && previous[i] === "")
360
+ groups?.get(i)?.dispose(preservePresentation);
361
+ styles?.get(i)?.dispose(preservePresentation);
362
+ if (!preservePresentation && bindings[i][1] === "classToken" && previous[i] === "")
333
363
  node.classList.remove(bindings[i][2]);
334
364
  } catch (error) {
335
365
  if (!failed) {
@@ -385,7 +415,21 @@ function __adoptBindings(root, descriptor, source, options) {
385
415
  styles.set(i, style = __createBindingStyleRestoration(nodes[binding[0]], binding));
386
416
  style.write(next[i]);
387
417
  } else write(nodes[binding[0]], binding, next[i]);
388
- if (!disposed) previous[i] = next[i];
418
+ if (!disposed) {
419
+ previous[i] = next[i];
420
+ if (binding[1] === "attr" || binding[1] === "boolean" || binding[1] === "aria" || binding[1] === "class" || binding[1] === "styleProperty" || binding[1] === "text") {
421
+ const [node, name] = owned[i];
422
+ let published2 = next[i];
423
+ if (binding[1] === "styleProperty") {
424
+ const style = node.style;
425
+ const value = style.getPropertyValue(binding[2]);
426
+ published2 = value === "" ? null : value + (style.getPropertyPriority(binding[2]) ? " !important" : "");
427
+ }
428
+ let claims2 = import_dom_binding_claims.domBindingClaims.get(node);
429
+ if (claims2 === void 0) import_dom_binding_claims.domBindingClaims.set(node, claims2 = /* @__PURE__ */ new Map());
430
+ claims2.set(name, published2);
431
+ }
432
+ }
389
433
  }
390
434
  };
391
435
  const drain = (preview = false) => {
@@ -600,6 +644,7 @@ function __adoptBindings(root, descriptor, source, options) {
600
644
  writePrepared(next, indices, preparedControls, preparedGroups);
601
645
  } finally {
602
646
  busy = false;
647
+ published?.();
603
648
  }
604
649
  }
605
650
  };
@@ -622,6 +667,7 @@ function __adoptBindings(root, descriptor, source, options) {
622
667
  for (const index of previousUpdates ?? []) signalUpdates.add(index);
623
668
  }
624
669
  busy = false;
670
+ if (!preview) published?.();
625
671
  }
626
672
  };
627
673
  const refresh = () => {
@@ -637,6 +683,52 @@ function __adoptBindings(root, descriptor, source, options) {
637
683
  prepare: () => run(() => drain(true))
638
684
  };
639
685
  const handle = { refresh, dispose };
686
+ if (descriptor.handoff === "host") {
687
+ published = () => {
688
+ if (!publicationRetries?.size) return;
689
+ const pending = [...publicationRetries];
690
+ publicationRetries.clear();
691
+ for (const retry of pending)
692
+ queueMicrotask(() => {
693
+ if (!disposed) retry();
694
+ });
695
+ };
696
+ const host = root;
697
+ const document = host.ownerDocument;
698
+ const ancestry = [];
699
+ for (let node = host; node !== null; node = node.parentNode)
700
+ ancestry.push([node, node.parentNode]);
701
+ const sibling = (node, previous2) => {
702
+ let next = previous2 ? node.previousSibling : node.nextSibling;
703
+ while (next?.nodeType === 1 && next.localName === "script" && (next.hasAttribute(import_native_read_seeds.NATIVE_SIGNAL_SEED_ATTR) || next.hasAttribute(import_stream_protocol.SUSPENSE_SCRIPT_ATTR) || next.hasAttribute(import_stream_protocol.STREAM_SCRIPT_ATTR)))
704
+ next = previous2 ? next.previousSibling : next.nextSibling;
705
+ return next;
706
+ };
707
+ const previousSibling = sibling(host, true);
708
+ const nextSibling = sibling(host, false);
709
+ let handoff;
710
+ handle[import_control_handoff.BINDING_HANDOFF] = () => {
711
+ if (handoff !== void 0) return handoff;
712
+ return handoff = {
713
+ id: descriptor.id,
714
+ root: host,
715
+ anchor: host,
716
+ host: new Set(
717
+ bindings.map(
718
+ (binding) => binding[1] === "styleProperty" ? "style:" + binding[2] : binding[1].startsWith("style") ? "style" : binding[2]
719
+ )
720
+ ),
721
+ revision: () => busy ? -1 : revision,
722
+ afterPublication: (callback) => {
723
+ (publicationRetries ??= /* @__PURE__ */ new Set()).add(callback);
724
+ return () => publicationRetries.delete(callback);
725
+ },
726
+ valid: () => host.parentNode !== null && host.ownerDocument === document && ancestry.every(([node, parent]) => node.parentNode === parent) && sibling(host, true) === previousSibling && sibling(host, false) === nextSibling && host.getAttribute("data-octane-bindings") === descriptor.id,
727
+ active: () => !disposed,
728
+ retire: (publish) => dispose(void 0, publish, true)
729
+ };
730
+ };
731
+ }
640
732
  if (signal?.aborted) {
641
733
  dispose();
642
734
  return handle;