tutuca 0.9.96 → 0.9.98

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.
@@ -1,5 +1,5 @@
1
1
  // src/storybook.js
2
- import { component, dispatchPhase, html, injectCss, tutuca } from "tutuca";
2
+ import { component, dispatchPhase, html, injectCss, phaseHasBubble, tutuca } from "tutuca";
3
3
  var Storybook = component({
4
4
  name: "Storybook",
5
5
  fields: {
@@ -274,18 +274,25 @@ var Example = component({
274
274
  },
275
275
  receive: {
276
276
  init(ctx) {
277
- dispatchPhase(ctx, ctx.at.field("value").buildPath(), this.on?.init, this.value);
277
+ this.runPhase(ctx, "init", this.on?.init);
278
278
  return this;
279
279
  },
280
280
  resume(ctx) {
281
- dispatchPhase(ctx, ctx.at.field("value").buildPath(), this.on?.resume, this.value);
281
+ this.runPhase(ctx, "resume", this.on?.resume);
282
282
  return this;
283
283
  },
284
284
  suspend(ctx) {
285
- dispatchPhase(ctx, ctx.at.field("value").buildPath(), this.on?.suspend, this.value);
285
+ this.runPhase(ctx, "suspend", this.on?.suspend);
286
286
  return this;
287
287
  }
288
288
  },
289
+ methods: {
290
+ runPhase(ctx, name, phase) {
291
+ if (phaseHasBubble(phase))
292
+ console.warn(`storybook on.${name}: a \`bubble\` action leaves this example and is received by the storybook engine, so your component's bubble handler won't run. Use send/request/input to drive a preset state.`);
293
+ dispatchPhase(ctx, ctx.at.field("value").buildPath(), phase, this.value);
294
+ }
295
+ },
289
296
  input: {
290
297
  onLogSelected() {
291
298
  console.log(this.value);
@@ -1224,6 +1224,8 @@ class RequestHandler {
1224
1224
  import { isIndexed, isKeyed } from "immutable";
1225
1225
 
1226
1226
  // src/cache.js
1227
+ var isWeakKey = (k) => k !== null && (typeof k === "object" || typeof k === "function");
1228
+
1227
1229
  class NullDomCache {
1228
1230
  get(_keys, _cacheKey) {}
1229
1231
  set(_keys, _cacheKey, _v) {}
@@ -1267,7 +1269,7 @@ class WeakMapDomCache {
1267
1269
  const key = keys[i];
1268
1270
  let next = cur.get(key);
1269
1271
  if (!next) {
1270
- if (typeof key !== "object") {
1272
+ if (!isWeakKey(key)) {
1271
1273
  this.badKey += 1;
1272
1274
  return;
1273
1275
  }
@@ -1280,7 +1282,7 @@ class WeakMapDomCache {
1280
1282
  const leaf = cur.get(lastKey);
1281
1283
  if (leaf)
1282
1284
  leaf[cacheKey] = v;
1283
- else if (typeof lastKey === "object")
1285
+ else if (isWeakKey(lastKey))
1284
1286
  cur.set(lastKey, { [cacheKey]: v });
1285
1287
  else
1286
1288
  this.badKey += 1;
@@ -1742,37 +1744,47 @@ class Renderer {
1742
1744
  renderEach(stack, iterInfo, node, viewName) {
1743
1745
  const { seq, filter, loopWith } = iterInfo.eval(stack);
1744
1746
  const r = [];
1745
- const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
1746
- getSeqInfo(seq)(seq, (key, value, attrName) => {
1747
- if (filter.call(stack.it, key, value, iterData)) {
1748
- const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
1749
- this.pushEachEntry(r, node.nodeId, attrName, key, dom);
1750
- }
1751
- }, start, end);
1747
+ const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
1748
+ const renderOne = (key, value, attrName) => {
1749
+ const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
1750
+ this.pushEachEntry(r, node.nodeId, attrName, key, dom);
1751
+ };
1752
+ if (keys)
1753
+ imKeysIter(seq, renderOne, keys);
1754
+ else
1755
+ getSeqInfo(seq)(seq, (key, value, attrName) => {
1756
+ if (filter.call(stack.it, key, value, iterData))
1757
+ renderOne(key, value, attrName);
1758
+ }, start, end);
1752
1759
  return r;
1753
1760
  }
1754
1761
  renderEachWhen(stack, iterInfo, view, nid) {
1755
1762
  const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
1756
1763
  const r = [];
1757
1764
  const it = stack.it;
1758
- const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
1759
- getSeqInfo(seq)(seq, (key, value, attrName) => {
1760
- if (filter.call(it, key, value, iterData)) {
1761
- const cachePath = enricher ? [view, it, value] : [view, value];
1762
- const binds = { key, value };
1763
- const cacheKey = `${nid}-${key}`;
1764
- if (enricher)
1765
- enricher.call(it, binds, key, value, iterData);
1766
- const cachedNode = this.cache.get(cachePath, cacheKey);
1767
- if (cachedNode)
1768
- this.pushEachEntry(r, nid, attrName, key, cachedNode);
1769
- else {
1770
- const dom = this.renderView(view, stack.enter(value, binds, false));
1771
- this.pushEachEntry(r, nid, attrName, key, dom);
1772
- this.cache.set(cachePath, cacheKey, dom);
1773
- }
1765
+ const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, makeLoopCtx(stack, filter)), seq);
1766
+ const renderOne = (key, value, attrName) => {
1767
+ const cachePath = enricher ? [view, it, value] : [view, value];
1768
+ const binds = { key, value };
1769
+ const cacheKey = `${nid}-${key}`;
1770
+ if (enricher)
1771
+ enricher.call(it, binds, key, value, iterData);
1772
+ const cachedNode = this.cache.get(cachePath, cacheKey);
1773
+ if (cachedNode)
1774
+ this.pushEachEntry(r, nid, attrName, key, cachedNode);
1775
+ else {
1776
+ const dom = this.renderView(view, stack.enter(value, binds, false));
1777
+ this.pushEachEntry(r, nid, attrName, key, dom);
1778
+ this.cache.set(cachePath, cacheKey, dom);
1774
1779
  }
1775
- }, start, end);
1780
+ };
1781
+ if (keys)
1782
+ imKeysIter(seq, renderOne, keys);
1783
+ else
1784
+ getSeqInfo(seq)(seq, (key, value, attrName) => {
1785
+ if (filter.call(it, key, value, iterData))
1786
+ renderOne(key, value, attrName);
1787
+ }, start, end);
1776
1788
  return r;
1777
1789
  }
1778
1790
  renderView(view, stack) {
@@ -1808,8 +1820,17 @@ var filterAlwaysTrue = (_v, _k, _seq) => true;
1808
1820
  var nullLoopWith = (seq) => ({ iterData: { seq } });
1809
1821
  var unpackLoopResult = (result, seq) => {
1810
1822
  const r = result ?? {};
1811
- return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
1823
+ return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
1824
+ };
1825
+ var imKeysIter = (seq, visit, keys) => {
1826
+ const attrName = isIndexed(seq) ? "si" : "sk";
1827
+ for (const key of keys)
1828
+ visit(key, seq.get(key), attrName);
1812
1829
  };
1830
+ var makeLoopCtx = (stack, filter) => ({
1831
+ lookup: (name) => stack.lookupBind(name),
1832
+ filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
1833
+ });
1813
1834
  var imIndexedIter = (seq, visit, start, end) => {
1814
1835
  const [s, e] = normalizeRange(start, end, seq.size);
1815
1836
  for (let i = s;i < e; i++)
@@ -2357,11 +2378,11 @@ class IterInfo {
2357
2378
  return { seq, filter, loopWith, enricher };
2358
2379
  }
2359
2380
  enrichBinds(stack, key) {
2360
- const { seq, loopWith, enricher } = this.eval(stack);
2381
+ const { seq, filter, loopWith, enricher } = this.eval(stack);
2361
2382
  const value = seq?.get ? seq.get(key, null) : null;
2362
2383
  const binds = { key, value };
2363
2384
  if (enricher) {
2364
- const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
2385
+ const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
2365
2386
  enricher.call(stack.it, binds, key, value, iterData);
2366
2387
  }
2367
2388
  return binds;
@@ -3712,6 +3733,13 @@ function phaseOps(phase) {
3712
3733
  function resolveArgs(args, self) {
3713
3734
  return typeof args === "function" ? args(self) ?? [] : args ?? [];
3714
3735
  }
3736
+ function phaseHasBubble(phase) {
3737
+ if (!phase)
3738
+ return false;
3739
+ if (phase.bubble?.length)
3740
+ return true;
3741
+ return (phase.do ?? []).some((op) => op.type === "bubble");
3742
+ }
3715
3743
  function dispatchPhase(dispatcher, targetPath, phase, self) {
3716
3744
  if (!phase)
3717
3745
  return;
@@ -4005,7 +4033,8 @@ class FieldSet extends Field {
4005
4033
  }
4006
4034
  function mkCompField(field, scope, args) {
4007
4035
  const Comp = scope?.lookupComponent(field.type) ?? null;
4008
- console.assert(!scope || Comp !== null, "component not found", { field });
4036
+ if (Comp === null)
4037
+ console.warn(scope ? `component field "${field.name}": component "${field.type}" not found in scope` : `component field "${field.name}": cannot resolve component "${field.type}" — built without a registered scope (use ${field.type}.make({}) as the default, or build via a registered component)`);
4009
4038
  return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
4010
4039
  }
4011
4040
 
@@ -4154,6 +4183,7 @@ export {
4154
4183
  removeIn,
4155
4184
  remove,
4156
4185
  phaseOps,
4186
+ phaseHasBubble,
4157
4187
  mergeWith,
4158
4188
  mergeDeepWith,
4159
4189
  mergeDeep,
package/dist/tutuca.js CHANGED
@@ -5594,6 +5594,8 @@ class RequestHandler {
5594
5594
  }
5595
5595
 
5596
5596
  // src/cache.js
5597
+ var isWeakKey = (k) => k !== null && (typeof k === "object" || typeof k === "function");
5598
+
5597
5599
  class NullDomCache {
5598
5600
  get(_keys, _cacheKey) {}
5599
5601
  set(_keys, _cacheKey, _v) {}
@@ -5637,7 +5639,7 @@ class WeakMapDomCache {
5637
5639
  const key = keys[i];
5638
5640
  let next = cur.get(key);
5639
5641
  if (!next) {
5640
- if (typeof key !== "object") {
5642
+ if (!isWeakKey(key)) {
5641
5643
  this.badKey += 1;
5642
5644
  return;
5643
5645
  }
@@ -5650,7 +5652,7 @@ class WeakMapDomCache {
5650
5652
  const leaf = cur.get(lastKey);
5651
5653
  if (leaf)
5652
5654
  leaf[cacheKey] = v;
5653
- else if (typeof lastKey === "object")
5655
+ else if (isWeakKey(lastKey))
5654
5656
  cur.set(lastKey, { [cacheKey]: v });
5655
5657
  else
5656
5658
  this.badKey += 1;
@@ -6112,37 +6114,47 @@ class Renderer {
6112
6114
  renderEach(stack, iterInfo, node, viewName) {
6113
6115
  const { seq, filter, loopWith } = iterInfo.eval(stack);
6114
6116
  const r = [];
6115
- const { iterData, start, end } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
6116
- getSeqInfo(seq)(seq, (key, value, attrName) => {
6117
- if (filter.call(stack.it, key, value, iterData)) {
6118
- const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
6119
- this.pushEachEntry(r, node.nodeId, attrName, key, dom);
6120
- }
6121
- }, start, end);
6117
+ const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
6118
+ const renderOne = (key, value, attrName) => {
6119
+ const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
6120
+ this.pushEachEntry(r, node.nodeId, attrName, key, dom);
6121
+ };
6122
+ if (keys)
6123
+ imKeysIter(seq, renderOne, keys);
6124
+ else
6125
+ getSeqInfo(seq)(seq, (key, value, attrName) => {
6126
+ if (filter.call(stack.it, key, value, iterData))
6127
+ renderOne(key, value, attrName);
6128
+ }, start, end);
6122
6129
  return r;
6123
6130
  }
6124
6131
  renderEachWhen(stack, iterInfo, view, nid) {
6125
6132
  const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
6126
6133
  const r = [];
6127
6134
  const it = stack.it;
6128
- const { iterData, start, end } = unpackLoopResult(loopWith.call(it, seq), seq);
6129
- getSeqInfo(seq)(seq, (key, value, attrName) => {
6130
- if (filter.call(it, key, value, iterData)) {
6131
- const cachePath = enricher ? [view, it, value] : [view, value];
6132
- const binds = { key, value };
6133
- const cacheKey = `${nid}-${key}`;
6134
- if (enricher)
6135
- enricher.call(it, binds, key, value, iterData);
6136
- const cachedNode = this.cache.get(cachePath, cacheKey);
6137
- if (cachedNode)
6138
- this.pushEachEntry(r, nid, attrName, key, cachedNode);
6139
- else {
6140
- const dom = this.renderView(view, stack.enter(value, binds, false));
6141
- this.pushEachEntry(r, nid, attrName, key, dom);
6142
- this.cache.set(cachePath, cacheKey, dom);
6143
- }
6135
+ const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, makeLoopCtx(stack, filter)), seq);
6136
+ const renderOne = (key, value, attrName) => {
6137
+ const cachePath = enricher ? [view, it, value] : [view, value];
6138
+ const binds = { key, value };
6139
+ const cacheKey = `${nid}-${key}`;
6140
+ if (enricher)
6141
+ enricher.call(it, binds, key, value, iterData);
6142
+ const cachedNode = this.cache.get(cachePath, cacheKey);
6143
+ if (cachedNode)
6144
+ this.pushEachEntry(r, nid, attrName, key, cachedNode);
6145
+ else {
6146
+ const dom = this.renderView(view, stack.enter(value, binds, false));
6147
+ this.pushEachEntry(r, nid, attrName, key, dom);
6148
+ this.cache.set(cachePath, cacheKey, dom);
6144
6149
  }
6145
- }, start, end);
6150
+ };
6151
+ if (keys)
6152
+ imKeysIter(seq, renderOne, keys);
6153
+ else
6154
+ getSeqInfo(seq)(seq, (key, value, attrName) => {
6155
+ if (filter.call(it, key, value, iterData))
6156
+ renderOne(key, value, attrName);
6157
+ }, start, end);
6146
6158
  return r;
6147
6159
  }
6148
6160
  renderView(view, stack) {
@@ -6178,8 +6190,17 @@ var filterAlwaysTrue = (_v, _k, _seq) => true;
6178
6190
  var nullLoopWith = (seq) => ({ iterData: { seq } });
6179
6191
  var unpackLoopResult = (result, seq) => {
6180
6192
  const r = result ?? {};
6181
- return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end };
6193
+ return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
6194
+ };
6195
+ var imKeysIter = (seq, visit, keys) => {
6196
+ const attrName = isIndexed(seq) ? "si" : "sk";
6197
+ for (const key of keys)
6198
+ visit(key, seq.get(key), attrName);
6182
6199
  };
6200
+ var makeLoopCtx = (stack, filter) => ({
6201
+ lookup: (name) => stack.lookupBind(name),
6202
+ filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
6203
+ });
6183
6204
  var imIndexedIter = (seq, visit, start, end) => {
6184
6205
  const [s, e] = normalizeRange(start, end, seq.size);
6185
6206
  for (let i = s;i < e; i++)
@@ -6727,11 +6748,11 @@ class IterInfo {
6727
6748
  return { seq, filter, loopWith, enricher };
6728
6749
  }
6729
6750
  enrichBinds(stack, key) {
6730
- const { seq, loopWith, enricher } = this.eval(stack);
6751
+ const { seq, filter, loopWith, enricher } = this.eval(stack);
6731
6752
  const value = seq?.get ? seq.get(key, null) : null;
6732
6753
  const binds = { key, value };
6733
6754
  if (enricher) {
6734
- const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq), seq);
6755
+ const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
6735
6756
  enricher.call(stack.it, binds, key, value, iterData);
6736
6757
  }
6737
6758
  return binds;
@@ -8026,6 +8047,13 @@ function phaseOps(phase) {
8026
8047
  function resolveArgs(args, self) {
8027
8048
  return typeof args === "function" ? args(self) ?? [] : args ?? [];
8028
8049
  }
8050
+ function phaseHasBubble(phase) {
8051
+ if (!phase)
8052
+ return false;
8053
+ if (phase.bubble?.length)
8054
+ return true;
8055
+ return (phase.do ?? []).some((op) => op.type === "bubble");
8056
+ }
8029
8057
  function dispatchPhase(dispatcher, targetPath, phase, self) {
8030
8058
  if (!phase)
8031
8059
  return;
@@ -8318,7 +8346,8 @@ class FieldSet extends Field {
8318
8346
  }
8319
8347
  function mkCompField(field, scope, args) {
8320
8348
  const Comp = scope?.lookupComponent(field.type) ?? null;
8321
- console.assert(!scope || Comp !== null, "component not found", { field });
8349
+ if (Comp === null)
8350
+ console.warn(scope ? `component field "${field.name}": component "${field.type}" not found in scope` : `component field "${field.name}": cannot resolve component "${field.type}" — built without a registered scope (use ${field.type}.make({}) as the default, or build via a registered component)`);
8322
8351
  return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
8323
8352
  }
8324
8353
 
@@ -8467,6 +8496,7 @@ export {
8467
8496
  removeIn,
8468
8497
  remove,
8469
8498
  phaseOps,
8499
+ phaseHasBubble,
8470
8500
  mergeWith$1 as mergeWith,
8471
8501
  mergeDeepWith$1 as mergeDeepWith,
8472
8502
  mergeDeep$1 as mergeDeep,