@source-crafter/xzor-runtime 0.1.16 → 0.1.18

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.
package/model.js CHANGED
@@ -8,8 +8,9 @@ import {
8
8
  disposeIsland,
9
9
  patchIsland,
10
10
  setFineHooks,
11
- setRenderObserver
12
- } from "./index-w2yxrgd1.js";
11
+ setRenderObserver,
12
+ setTracking
13
+ } from "./index-nxzr7r51.js";
13
14
 
14
15
  // runtime/entity-set.ts
15
16
  class EntitySet extends Array {
@@ -238,6 +239,10 @@ var LOOSE = 64;
238
239
  var ITEM = 128;
239
240
  var OWNED = 256;
240
241
  var FRESH = 512;
242
+ var SHOW = 1024;
243
+ var PAUSE = 2048;
244
+ var PAUSED = 4096;
245
+ var STALE = 8192;
241
246
  var bitOf = (index) => index === -1 ? 1 << 31 : index < 30 ? 1 << index : 1 << 30;
242
247
  var MEMOS = Symbol("xzor.fine.memos");
243
248
  var EMPTY = Symbol("xzor.fine.empty");
@@ -363,7 +368,7 @@ class Binding {
363
368
  }
364
369
  }
365
370
  #loose() {
366
- if ((this.flags & (LOOSE | DEAD)) !== 0 || (this.flags & KIND) >= EFFECT || holder === undefined)
371
+ if ((this.flags & (LOOSE | DEAD | PAUSE)) !== 0 || (this.flags & KIND) >= EFFECT || holder === undefined)
367
372
  return;
368
373
  this.flags |= LOOSE;
369
374
  holder.ctx.loose.push(this);
@@ -384,8 +389,13 @@ class Binding {
384
389
  }
385
390
  stateHasChanged() {
386
391
  const flags = this.flags;
387
- if ((flags & DEAD) !== 0)
392
+ if ((flags & (DEAD | PAUSED)) !== 0) {
393
+ if ((flags & DEAD) === 0)
394
+ this.flags |= STALE;
388
395
  return;
396
+ }
397
+ if ((flags & SHOW) !== 0)
398
+ return this.#show();
389
399
  switch (flags & KIND) {
390
400
  case TEXT: {
391
401
  const value = this.#run();
@@ -403,6 +413,13 @@ class Binding {
403
413
  return setAttr(this.node, (flags & ITEM) !== 0 ? this.read.$n : this.data, this.#run());
404
414
  case REGION: {
405
415
  const region = this.data;
416
+ const branch = region.branch;
417
+ if (branch !== undefined) {
418
+ const index = this.#run();
419
+ if (index === region.index)
420
+ return;
421
+ region.index = index;
422
+ }
406
423
  disposeAll(region);
407
424
  const end = this.node;
408
425
  const parent = end.parentNode;
@@ -412,7 +429,7 @@ class Binding {
412
429
  node = next;
413
430
  }
414
431
  const frag = document.createDocumentFragment();
415
- within(region, () => this.#run(frag));
432
+ within(region, () => branch !== undefined ? untracked(() => branch(frag)) : this.#run(frag));
416
433
  parent.insertBefore(frag, end);
417
434
  return;
418
435
  }
@@ -431,6 +448,36 @@ class Binding {
431
448
  return;
432
449
  }
433
450
  }
451
+ #show() {
452
+ const show = this.data;
453
+ const index = this.#run();
454
+ if (index === show.index)
455
+ return;
456
+ const shown = show.branches[show.index];
457
+ if (shown !== undefined)
458
+ hideBranch(shown);
459
+ show.index = index;
460
+ let branch = show.branches[index];
461
+ if (branch !== undefined)
462
+ return showBranch(branch);
463
+ branch = { bindings: undefined, ctx: show.ctx, start: show.start, item: undefined, branch: undefined, index: -1, first: null, els: [], display: [] };
464
+ show.branches[index] = branch;
465
+ const frag = document.createDocumentFragment();
466
+ within(branch, () => untracked(() => show.build(frag)));
467
+ branch.first = frag.firstChild;
468
+ for (let node = frag.firstChild;node !== null; node = node.nextSibling)
469
+ if (node.nodeType === 1)
470
+ branch.els.push(node);
471
+ let before = this.node;
472
+ for (let i = index + 1;i < show.branches.length; i++) {
473
+ const next = show.branches[i]?.first;
474
+ if (next) {
475
+ before = next;
476
+ break;
477
+ }
478
+ }
479
+ before.parentNode.insertBefore(frag, before);
480
+ }
434
481
  #becomeIsland() {
435
482
  const read = this.read;
436
483
  const h = this.data;
@@ -453,7 +500,10 @@ class Binding {
453
500
  if ((this.flags & DEAD) !== 0)
454
501
  return;
455
502
  const kind = this.flags & KIND;
456
- if (kind === REGION)
503
+ if ((this.flags & SHOW) !== 0)
504
+ for (const branch of this.data.branches)
505
+ branch !== undefined && disposeAll(branch);
506
+ else if (kind === REGION)
457
507
  disposeAll(this.data);
458
508
  else if (kind === LIST || kind === KEYED)
459
509
  for (const row of this.data.order)
@@ -523,19 +573,92 @@ function track(b) {
523
573
  b.stateHasChanged();
524
574
  }
525
575
  function disposeAll(h) {
526
- for (let b = h.bindings;b !== undefined; b = b.next)
576
+ let loose = false;
577
+ for (let b = h.bindings;b !== undefined; b = b.next) {
578
+ if ((b.flags & LOOSE) !== 0)
579
+ loose = true;
527
580
  b.dispose();
581
+ }
528
582
  h.bindings = undefined;
583
+ if (loose)
584
+ sweepLoose(h.ctx);
585
+ }
586
+ function sweepLoose(ctx) {
587
+ if (ctx.sweep)
588
+ return;
589
+ ctx.sweep = true;
590
+ queueMicrotask(() => {
591
+ ctx.sweep = false;
592
+ const loose = ctx.loose;
593
+ let kept = 0;
594
+ for (const b of loose)
595
+ if ((b.flags & DEAD) === 0)
596
+ loose[kept++] = b;
597
+ loose.length = kept;
598
+ });
529
599
  }
530
600
  function refreshAll(h) {
531
601
  for (let b = h.bindings;b !== undefined; b = b.next) {
532
- b.stateHasChanged();
533
602
  const kind = b.flags & KIND;
534
- if (kind === LIST || kind === KEYED)
603
+ const kept = kind === REGION ? b.data.index : -1;
604
+ b.stateHasChanged();
605
+ if ((b.flags & SHOW) !== 0)
606
+ for (const branch of b.data.branches)
607
+ branch !== undefined && refreshAll(branch);
608
+ else if (kind === LIST || kind === KEYED)
535
609
  for (const row of b.data.order)
536
610
  refreshAll(row);
611
+ else if (kept !== -1 && kept === b.data.index)
612
+ refreshAll(b.data);
537
613
  }
538
614
  }
615
+ function under(b, f) {
616
+ const kind = b.flags & KIND;
617
+ if ((b.flags & SHOW) !== 0)
618
+ for (const branch of b.data.branches)
619
+ branch !== undefined && f(branch);
620
+ else if (kind === REGION)
621
+ f(b.data);
622
+ else if (kind === LIST || kind === KEYED)
623
+ for (const row of b.data.order)
624
+ f(row);
625
+ }
626
+ function pauseIn(h) {
627
+ for (let b = h.bindings;b !== undefined; b = b.next) {
628
+ if ((b.flags & PAUSE) !== 0)
629
+ under(b, freeze);
630
+ else
631
+ under(b, pauseIn);
632
+ }
633
+ }
634
+ function freeze(h) {
635
+ for (let b = h.bindings;b !== undefined; b = b.next) {
636
+ b.flags |= PAUSED;
637
+ under(b, freeze);
638
+ }
639
+ }
640
+ function thaw(h) {
641
+ for (let b = h.bindings;b !== undefined; b = b.next) {
642
+ const stale = (b.flags & STALE) !== 0;
643
+ b.flags &= ~(PAUSED | STALE);
644
+ if (stale)
645
+ b.stateHasChanged();
646
+ under(b, thaw);
647
+ }
648
+ }
649
+ function hideBranch(branch) {
650
+ for (let i = 0;i < branch.els.length; i++) {
651
+ const style = branch.els[i].style;
652
+ branch.display[i] = style.display;
653
+ style.display = "none";
654
+ }
655
+ pauseIn(branch);
656
+ }
657
+ function showBranch(branch) {
658
+ for (let i = 0;i < branch.els.length; i++)
659
+ branch.els[i].style.display = branch.display[i] ?? "";
660
+ thaw(branch);
661
+ }
539
662
  var textOf = (value) => value === null || value === undefined || value === false ? "" : String(value);
540
663
  function setAttr(el, name, value) {
541
664
  if (typeof value === "boolean" && name.startsWith("aria-"))
@@ -666,11 +789,21 @@ function reconcile(list, items) {
666
789
  throw duplicate(keys[i]);
667
790
  at.set(keys[i], next[i]);
668
791
  }
669
- for (const [key, row] of rows)
670
- if (!at.has(key) || at.get(key) !== row.item) {
792
+ for (const [key, row] of rows) {
793
+ if (!at.has(key)) {
671
794
  dropRow(row);
672
795
  rows.delete(key);
796
+ continue;
673
797
  }
798
+ const item = at.get(key);
799
+ if (item === row.item)
800
+ continue;
801
+ if (state.build.length > 1) {
802
+ dropRow(row);
803
+ rows.delete(key);
804
+ } else
805
+ retake(row, item);
806
+ }
674
807
  }
675
808
  const order = [];
676
809
  for (let i = 0;i < next.length; i++) {
@@ -685,6 +818,16 @@ function reconcile(list, items) {
685
818
  place(list.node, state.order, order);
686
819
  state.order = order;
687
820
  }
821
+ function retake(row, item) {
822
+ row.item = item;
823
+ for (let b = row.bindings;b !== undefined; b = b.next) {
824
+ if ((b.flags & ITEM) === 0)
825
+ continue;
826
+ if ((b.flags & KIND) === REGION)
827
+ b.data.item = item;
828
+ b.stateHasChanged();
829
+ }
830
+ }
688
831
  function sameValues(a, b) {
689
832
  if (a.length !== b.length)
690
833
  return false;
@@ -800,8 +943,8 @@ function on(el, event, handler, h) {
800
943
  } else
801
944
  el.addEventListener(event, (e) => afterHandler(h.ctx, handler(e)));
802
945
  }
803
- function region(start, end, build, item, flags) {
804
- const region2 = { bindings: undefined, ctx: holder.ctx, start, item };
946
+ function region(start, end, build, item, flags, branch) {
947
+ const region2 = { bindings: undefined, ctx: holder.ctx, start, item, branch, index: -1 };
805
948
  track(new Binding(REGION | flags, end, build, region2));
806
949
  }
807
950
  function list(end, items, reads, build, empty, key) {
@@ -809,6 +952,41 @@ function list(end, items, reads, build, empty, key) {
809
952
  track(new Binding(LIST, end, items, state));
810
953
  }
811
954
  var anchor = (parent) => parent.appendChild(document.createComment(""));
955
+ function awaiting(end, pending, then, fail) {
956
+ const state = { phase: 0, value: undefined, seq: 0 };
957
+ const view = new Binding(REGION, end, (p) => {
958
+ if (state.phase === 0)
959
+ pending?.(p);
960
+ else if (state.phase === 1)
961
+ then?.(p, state.value);
962
+ else
963
+ fail?.(p, state.value);
964
+ }, { bindings: undefined, ctx: holder.ctx, start: end.previousSibling, item: undefined, branch: undefined, index: -1 });
965
+ const show = (phase, value) => {
966
+ if ((view.flags & DEAD) !== 0)
967
+ return;
968
+ state.phase = phase;
969
+ state.value = value;
970
+ view.stateHasChanged();
971
+ };
972
+ track(view);
973
+ return (result) => {
974
+ const seq = ++state.seq;
975
+ if (typeof result?.then !== "function")
976
+ return show(1, result);
977
+ if (state.phase !== 0)
978
+ show(0, undefined);
979
+ result.then((value) => seq === state.seq && show(1, value), (error) => {
980
+ if (seq !== state.seq)
981
+ return;
982
+ show(2, error);
983
+ if (fail === undefined)
984
+ queueMicrotask(() => {
985
+ throw error;
986
+ });
987
+ });
988
+ };
989
+ }
812
990
  var fine = {
813
991
  template(specs) {
814
992
  let node;
@@ -879,6 +1057,16 @@ var fine = {
879
1057
  regionAt(end, build) {
880
1058
  region(end.previousSibling, end, build, undefined, 0);
881
1059
  },
1060
+ branchAt(end, run) {
1061
+ region(end.previousSibling, end, run, undefined, 0, run);
1062
+ },
1063
+ showAt(end, run) {
1064
+ const show = { ctx: holder.ctx, start: end.previousSibling, index: -1, build: run, branches: [] };
1065
+ track(new Binding(REGION | SHOW, end, run, show));
1066
+ },
1067
+ pauseAt(end, build) {
1068
+ region(end.previousSibling, end, () => 0, undefined, PAUSE, build);
1069
+ },
882
1070
  textOnce(node, read) {
883
1071
  node.data = textOf(untracked(read));
884
1072
  },
@@ -925,40 +1113,23 @@ var fine = {
925
1113
  });
926
1114
  },
927
1115
  awaitAt(end, read, pending, then, fail) {
928
- const state = { phase: 0, value: undefined, seq: 0 };
929
- const view = new Binding(REGION, end, (p) => {
930
- if (state.phase === 0)
931
- pending?.(p);
932
- else if (state.phase === 1)
933
- then?.(p, state.value);
934
- else
935
- fail?.(p, state.value);
936
- }, { bindings: undefined, ctx: holder.ctx, start: end.previousSibling, item: undefined });
937
- const show = (phase, value) => {
938
- if ((view.flags & DEAD) !== 0)
939
- return;
940
- state.phase = phase;
941
- state.value = value;
942
- view.stateHasChanged();
943
- };
944
- track(view);
1116
+ const show = awaiting(end, pending, then, fail);
1117
+ track(new Binding(EFFECT, end, () => show(read()), undefined));
1118
+ },
1119
+ awaitCallAt(end, args, call, pending, then, fail) {
1120
+ const show = awaiting(end, pending, then, fail);
1121
+ let last;
1122
+ const request = new Binding(EFFECT, end, () => show(call(...last)), undefined);
945
1123
  track(new Binding(EFFECT, end, () => {
946
- const result = read();
947
- const seq = ++state.seq;
948
- if (typeof result?.then !== "function")
949
- return show(1, result);
950
- if (state.phase !== 0)
951
- show(0, undefined);
952
- result.then((value) => seq === state.seq && show(1, value), (error) => {
953
- if (seq !== state.seq)
954
- return;
955
- show(2, error);
956
- if (fail === undefined)
957
- queueMicrotask(() => {
958
- throw error;
959
- });
960
- });
1124
+ const next = args();
1125
+ if (last !== undefined && next.every((v, i) => Object.is(v, last[i])))
1126
+ return;
1127
+ const first = last === undefined;
1128
+ last = next;
1129
+ if (!first)
1130
+ request.stateHasChanged();
961
1131
  }, undefined));
1132
+ track(request);
962
1133
  },
963
1134
  anchors(parent) {
964
1135
  anchor(parent);
@@ -968,6 +1139,13 @@ var fine = {
968
1139
  const row = holder;
969
1140
  region(end.previousSibling, end, row.reads[i], row.item, ITEM);
970
1141
  },
1142
+ branchItem(end, i) {
1143
+ const row = holder;
1144
+ const read = row.reads[i];
1145
+ const state = { bindings: undefined, ctx: row.ctx, start: end.previousSibling, item: row.item, branch: undefined, index: -1 };
1146
+ state.branch = (p) => read(state.item, p);
1147
+ track(new Binding(REGION | ITEM, end, read, state));
1148
+ },
971
1149
  list(parent, items, build) {
972
1150
  list(anchor(parent), items, undefined, build);
973
1151
  },
@@ -988,52 +1166,13 @@ var fine = {
988
1166
  }
989
1167
  };
990
1168
  var noop = () => {};
991
- var FIELDS = Symbol("xzor.fine.fields");
992
-
993
- class FineComponent extends ComponentBase {
994
- #subs;
995
- static get $reader() {
996
- return Model.$reader;
997
- }
998
- static same(a, b) {
999
- return Model.same(a, b);
1000
- }
1001
- static $define(cls, names) {
1002
- const counts = cls;
1003
- const at = counts[FIELDS] ?? 0;
1004
- counts[FIELDS] = at + names.length;
1005
- return at;
1006
- }
1007
- $watch(dep) {
1008
- const subs = this.#subs ??= [];
1009
- dep.slot = subs.length;
1010
- subs.push(dep);
1011
- }
1012
- $unwatch(dep) {
1013
- const subs = this.#subs;
1014
- if (subs === undefined || subs.length === 0)
1015
- return;
1016
- const last = subs.pop();
1017
- if (last !== dep) {
1018
- subs[dep.slot] = last;
1019
- last.slot = dep.slot;
1020
- }
1021
- }
1022
- $changed(index, _previous) {
1023
- const subs = this.#subs;
1024
- if (subs !== undefined)
1025
- for (let i = 0;i < subs.length; i++)
1026
- $notify(subs[i], index);
1027
- }
1028
- }
1029
- FineComponent.prototype[FINE] = true;
1030
- var CTX = Symbol("xzor.fine.ctx");
1169
+ var FineComponent = ComponentBase;
1031
1170
  setFineHooks({
1032
1171
  create(build, owner, app, scope) {
1033
1172
  const frag = document.createDocumentFragment();
1034
1173
  const start = frag.appendChild(document.createComment(""));
1035
- const ctx = { owner, app, scope, loose: [] };
1036
- owner[CTX] = ctx;
1174
+ const ctx = { owner, app, scope, loose: [], sweep: false };
1175
+ owner[FINE] = ctx;
1037
1176
  const root = { bindings: undefined, ctx, start, end: start };
1038
1177
  const reader = Model.$reader;
1039
1178
  Model.$reader = undefined;
@@ -1062,7 +1201,7 @@ setFineHooks({
1062
1201
  disposeAll(root);
1063
1202
  },
1064
1203
  handled(owner, result) {
1065
- const ctx = owner[CTX];
1204
+ const ctx = owner[FINE];
1066
1205
  if (ctx !== undefined)
1067
1206
  afterHandler(ctx, result);
1068
1207
  }
@@ -1155,7 +1294,9 @@ class Model extends EventTarget {
1155
1294
  pendingIgnored = undefined;
1156
1295
  }
1157
1296
  Object.defineProperty(cls, meta, { value: own });
1158
- return base ? base.names.length : 0;
1297
+ const at = base ? base.names.length : 0;
1298
+ Object.defineProperty(cls, "$at", { value: at });
1299
+ return at;
1159
1300
  }
1160
1301
  static same(a, b) {
1161
1302
  if (Object.is(a, b))
@@ -1676,6 +1817,7 @@ function flush() {
1676
1817
  }
1677
1818
  var $notify = changed;
1678
1819
  var $flush = flush;
1820
+ setTracking({ model: Model, notify: $notify });
1679
1821
  function sweep(own) {
1680
1822
  const more = own.more;
1681
1823
  if (more !== undefined) {
@@ -1770,5 +1912,5 @@ export {
1770
1912
  requiredIdValue
1771
1913
  };
1772
1914
 
1773
- //# debugId=55A54F7D726CA15364756E2164756E21
1915
+ //# debugId=68EBAF2C0CCC917064756E2164756E21
1774
1916
  //# sourceMappingURL=model.js.map