tutuca 0.13.3 → 0.15.0
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/dist/tutuca-cli.js +1079 -1254
- package/dist/tutuca-dev.ext.js +1086 -1216
- package/dist/tutuca-dev.js +1095 -1225
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +1055 -1133
- package/dist/tutuca-extra.js +1061 -1139
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.ext.js +1054 -1116
- package/dist/tutuca.js +1060 -1122
- package/dist/tutuca.min.js +3 -3
- package/package.json +1 -1
- package/skill/tutuca/SKILL.md +2 -2
- package/skill/tutuca/advanced.md +48 -17
- package/skill/tutuca/component-design.md +2 -2
- package/skill/tutuca/core.md +5 -4
- package/skill/tutuca/messages-and-intents.md +9 -11
- package/skill/tutuca/patterns/README.md +1 -1
- package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +11 -6
- package/skill/tutuca/patterns/share-state-across-the-tree.md +18 -3
- package/skill/tutuca/semantics.md +63 -39
- package/skill/tutuca-source/tutuca.ext.js +1054 -1116
package/dist/tutuca-dev.ext.js
CHANGED
|
@@ -128,8 +128,8 @@ function jestMatchers(chai2, utils) {
|
|
|
128
128
|
expected
|
|
129
129
|
);
|
|
130
130
|
});
|
|
131
|
-
m("toHaveProperty", function(
|
|
132
|
-
const keys = Array.isArray(
|
|
131
|
+
m("toHaveProperty", function(path2, ...rest) {
|
|
132
|
+
const keys = Array.isArray(path2) ? path2 : String(path2).split(".");
|
|
133
133
|
let cur = this._obj;
|
|
134
134
|
let found = true;
|
|
135
135
|
for (const k of keys) {
|
|
@@ -144,7 +144,7 @@ function jestMatchers(chai2, utils) {
|
|
|
144
144
|
pass,
|
|
145
145
|
"expected #{this} to have property #{exp}",
|
|
146
146
|
"expected #{this} not to have property #{exp}",
|
|
147
|
-
|
|
147
|
+
path2
|
|
148
148
|
);
|
|
149
149
|
});
|
|
150
150
|
m("toBeInstanceOf", function(ctor) {
|
|
@@ -209,12 +209,6 @@ enableMapSet();
|
|
|
209
209
|
|
|
210
210
|
// src/path.js
|
|
211
211
|
var NONE = /* @__PURE__ */ Symbol("NONE");
|
|
212
|
-
var readKey = (value, key, dval = null) => {
|
|
213
|
-
if (value == null) return dval;
|
|
214
|
-
if (value instanceof Map) return value.has(key) ? value.get(key) : dval;
|
|
215
|
-
if (value instanceof Set) return value.has(key) ? key : dval;
|
|
216
|
-
return Object.hasOwn(value, key) ? value[key] : dval;
|
|
217
|
-
};
|
|
218
212
|
var writeKey = (value, key, next) => {
|
|
219
213
|
if (value instanceof Map) value.set(key, next);
|
|
220
214
|
else if (value instanceof Set) {
|
|
@@ -222,20 +216,15 @@ var writeKey = (value, key, next) => {
|
|
|
222
216
|
value.add(next);
|
|
223
217
|
} else value[key] = next;
|
|
224
218
|
};
|
|
225
|
-
var writeSeqKey = (value, key, next) =>
|
|
226
|
-
if (value instanceof Map || value instanceof Set || Array.isArray(value) || Object.hasOwn(value, key))
|
|
227
|
-
writeKey(value, key, next);
|
|
228
|
-
else if (typeof value?.set === "function") value.set(key, next);
|
|
229
|
-
else writeKey(value, key, next);
|
|
230
|
-
};
|
|
219
|
+
var writeSeqKey = (value, key, next) => !(value instanceof Map || value instanceof Set || Array.isArray(value)) && !Object.hasOwn(value, key) && typeof value?.set === "function" ? value.set(key, next) : writeKey(value, key, next);
|
|
231
220
|
var Step = class {
|
|
232
|
-
lookup(_v, dval = null) {
|
|
233
|
-
return dval;
|
|
234
|
-
}
|
|
235
221
|
setDraftValue(_root, _v) {
|
|
236
222
|
}
|
|
237
|
-
|
|
238
|
-
|
|
223
|
+
// Re-enter this step while rebuilding a stack. `renderPath` is the dispatch
|
|
224
|
+
// position AFTER this step: a rebuilt frame must carry the same render path
|
|
225
|
+
// the renderer had there, or the provides it publishes would be located wrong.
|
|
226
|
+
enterFrame(stack, next, renderPath) {
|
|
227
|
+
return stack.enter(next, {}, true, renderPath);
|
|
239
228
|
}
|
|
240
229
|
toAbstractPathStep() {
|
|
241
230
|
return this;
|
|
@@ -252,41 +241,29 @@ var Step = class {
|
|
|
252
241
|
return null;
|
|
253
242
|
}
|
|
254
243
|
};
|
|
255
|
-
var BindStep = class
|
|
244
|
+
var BindStep = class extends Step {
|
|
256
245
|
constructor(binds) {
|
|
257
246
|
super();
|
|
258
247
|
this.binds = binds;
|
|
259
248
|
}
|
|
260
|
-
lookup(v
|
|
249
|
+
lookup(v) {
|
|
261
250
|
return v;
|
|
262
251
|
}
|
|
263
|
-
enterFrame(stack, next) {
|
|
264
|
-
return stack.enter(next, { ...this.binds }, false);
|
|
265
|
-
}
|
|
266
|
-
withIndex(i) {
|
|
267
|
-
return new _BindStep({ ...this.binds, key: i });
|
|
268
|
-
}
|
|
269
|
-
withKey(key) {
|
|
270
|
-
return new _BindStep({ ...this.binds, key });
|
|
252
|
+
enterFrame(stack, next, renderPath) {
|
|
253
|
+
return stack.enter(next, { ...this.binds }, false, renderPath);
|
|
271
254
|
}
|
|
272
255
|
toAbstractPathStep() {
|
|
273
256
|
return null;
|
|
274
257
|
}
|
|
275
258
|
};
|
|
276
|
-
var ScopeBindStep = class
|
|
259
|
+
var ScopeBindStep = class extends BindStep {
|
|
277
260
|
constructor(val, binds = {}) {
|
|
278
261
|
super(binds);
|
|
279
262
|
this.val = val;
|
|
280
263
|
}
|
|
281
|
-
enterFrame(stack, next) {
|
|
264
|
+
enterFrame(stack, next, renderPath) {
|
|
282
265
|
const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
|
|
283
|
-
return stack.enter(next, { ...this.binds, ...dyn }, false);
|
|
284
|
-
}
|
|
285
|
-
withIndex(i) {
|
|
286
|
-
return new _ScopeBindStep(this.val, { ...this.binds, key: i });
|
|
287
|
-
}
|
|
288
|
-
withKey(key) {
|
|
289
|
-
return new _ScopeBindStep(this.val, { ...this.binds, key });
|
|
266
|
+
return stack.enter(next, { ...this.binds, ...dyn }, false, renderPath);
|
|
290
267
|
}
|
|
291
268
|
};
|
|
292
269
|
var FieldStep = class extends Step {
|
|
@@ -294,18 +271,12 @@ var FieldStep = class extends Step {
|
|
|
294
271
|
super();
|
|
295
272
|
this.field = field;
|
|
296
273
|
}
|
|
297
|
-
lookup(v
|
|
298
|
-
return
|
|
274
|
+
lookup(v) {
|
|
275
|
+
return seqGet(v, this.field, NONE);
|
|
299
276
|
}
|
|
300
277
|
setDraftValue(root, v) {
|
|
301
278
|
writeKey(root, this.field, v);
|
|
302
279
|
}
|
|
303
|
-
withIndex(i) {
|
|
304
|
-
return new SeqStep(this.field, i);
|
|
305
|
-
}
|
|
306
|
-
withKey(k) {
|
|
307
|
-
return new SeqStep(this.field, k);
|
|
308
|
-
}
|
|
309
280
|
toKey() {
|
|
310
281
|
return { field: this.field };
|
|
311
282
|
}
|
|
@@ -316,15 +287,15 @@ var SeqStep = class extends Step {
|
|
|
316
287
|
this.field = field;
|
|
317
288
|
this.key = key;
|
|
318
289
|
}
|
|
319
|
-
lookup(v
|
|
320
|
-
return seqGet(
|
|
290
|
+
lookup(v) {
|
|
291
|
+
return seqGet(seqGet(v, this.field, null), this.key, NONE);
|
|
321
292
|
}
|
|
322
293
|
setDraftValue(root, v) {
|
|
323
|
-
const seq =
|
|
294
|
+
const seq = seqGet(root, this.field, null);
|
|
324
295
|
if (seq != null) writeSeqKey(seq, this.key, v);
|
|
325
296
|
}
|
|
326
|
-
enterFrame(stack, next) {
|
|
327
|
-
return stack.enter(next, { key: this.key }, true);
|
|
297
|
+
enterFrame(stack, next, renderPath) {
|
|
298
|
+
return stack.enter(next, { key: this.key }, true, renderPath);
|
|
328
299
|
}
|
|
329
300
|
toKey() {
|
|
330
301
|
return { field: this.field, key: this.key };
|
|
@@ -336,20 +307,20 @@ var SeqAccessStep = class extends Step {
|
|
|
336
307
|
this.seqField = seqField;
|
|
337
308
|
this.keyField = keyField;
|
|
338
309
|
}
|
|
339
|
-
lookup(v
|
|
340
|
-
const seq =
|
|
341
|
-
const key =
|
|
342
|
-
return key !== NONE && seq !== NONE ? seqGet(seq, key,
|
|
310
|
+
lookup(v) {
|
|
311
|
+
const seq = seqGet(v, this.seqField, NONE);
|
|
312
|
+
const key = seqGet(v, this.keyField, NONE);
|
|
313
|
+
return key !== NONE && seq !== NONE ? seqGet(seq, key, NONE) : NONE;
|
|
343
314
|
}
|
|
344
315
|
setDraftValue(root, v) {
|
|
345
|
-
const seq =
|
|
346
|
-
const key =
|
|
316
|
+
const seq = seqGet(root, this.seqField, NONE);
|
|
317
|
+
const key = seqGet(root, this.keyField, NONE);
|
|
347
318
|
if (seq !== NONE && key !== NONE) writeSeqKey(seq, key, v);
|
|
348
319
|
}
|
|
349
320
|
// Resolve `keyField` against `v` now and freeze it as a literal-key `SeqStep`, so a
|
|
350
321
|
// later lookup/setValue lands on this same item even if `keyField` changes meanwhile.
|
|
351
322
|
pinKey(v) {
|
|
352
|
-
const key =
|
|
323
|
+
const key = seqGet(v, this.keyField, NONE);
|
|
353
324
|
return key === NONE ? this : new SeqStep(this.seqField, key);
|
|
354
325
|
}
|
|
355
326
|
// The key is a *field reference* resolved live, so it is unknown without a value;
|
|
@@ -360,70 +331,62 @@ var SeqAccessStep = class extends Step {
|
|
|
360
331
|
}
|
|
361
332
|
};
|
|
362
333
|
var EachBindStep = class extends Step {
|
|
363
|
-
constructor(
|
|
334
|
+
constructor(eachNode, key) {
|
|
364
335
|
super();
|
|
365
|
-
this.
|
|
336
|
+
this.eachNode = eachNode;
|
|
366
337
|
this.key = key;
|
|
367
338
|
}
|
|
368
|
-
lookup(v
|
|
339
|
+
lookup(v) {
|
|
369
340
|
return v;
|
|
370
341
|
}
|
|
371
342
|
// Replay the renderer's per-item binds (key, value + any @enrich-with binds)
|
|
372
343
|
// so a rebuilt stack matches the one @each rendered with.
|
|
373
|
-
enterFrame(stack, next) {
|
|
374
|
-
return stack.enter(next, this.
|
|
344
|
+
enterFrame(stack, next, renderPath) {
|
|
345
|
+
return stack.enter(next, this.eachNode.enrichBinds(stack, this.key), false, renderPath);
|
|
375
346
|
}
|
|
376
347
|
toAbstractPathStep() {
|
|
377
348
|
return null;
|
|
378
349
|
}
|
|
379
350
|
};
|
|
380
351
|
var EachRenderItStep = class extends SeqStep {
|
|
381
|
-
enterFrame(stack, next) {
|
|
382
|
-
return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
|
|
352
|
+
enterFrame(stack, next, renderPath) {
|
|
353
|
+
return stack.enter(next, { key: this.key, value: next }, false, renderPath).enter(next, {}, true, renderPath);
|
|
383
354
|
}
|
|
384
355
|
toAbstractPathStep() {
|
|
385
356
|
return new SeqStep(this.field, this.key);
|
|
386
357
|
}
|
|
387
358
|
};
|
|
388
|
-
function
|
|
389
|
-
|
|
359
|
+
function stepToJson(step) {
|
|
360
|
+
if (step instanceof SeqStep) return { f: step.field, k: step.key };
|
|
361
|
+
if (step instanceof FieldStep) return { f: step.field };
|
|
362
|
+
if (step instanceof SeqAccessStep) return { f: step.seqField, a: step.keyField };
|
|
363
|
+
return null;
|
|
390
364
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
warnRawDynStep("lookup", this);
|
|
404
|
-
return dval;
|
|
405
|
-
}
|
|
406
|
-
enterFrame(stack, _next) {
|
|
407
|
-
warnRawDynStep("enterFrame", this);
|
|
408
|
-
return stack;
|
|
409
|
-
}
|
|
410
|
-
};
|
|
411
|
-
var DynEachStep = class extends DynStep {
|
|
412
|
-
constructor(producerCompId, producerSteps, key) {
|
|
413
|
-
super(producerCompId, producerSteps);
|
|
414
|
-
this.key = key;
|
|
365
|
+
function stepFromJson(j) {
|
|
366
|
+
if (j == null || typeof j.f !== "string") return null;
|
|
367
|
+
if (j.k !== void 0) return new SeqStep(j.f, j.k);
|
|
368
|
+
if (j.a !== void 0) return new SeqAccessStep(j.f, j.a);
|
|
369
|
+
return new FieldStep(j.f);
|
|
370
|
+
}
|
|
371
|
+
function pathToJson(path2) {
|
|
372
|
+
const out = [];
|
|
373
|
+
for (const step of path2.steps) {
|
|
374
|
+
const j = stepToJson(step);
|
|
375
|
+
if (j === null) return null;
|
|
376
|
+
out.push(j);
|
|
415
377
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
378
|
+
return out;
|
|
379
|
+
}
|
|
380
|
+
function pathFromJson(j) {
|
|
381
|
+
if (!Array.isArray(j)) return null;
|
|
382
|
+
const steps = [];
|
|
383
|
+
for (const item of j) {
|
|
384
|
+
const step = stepFromJson(item);
|
|
385
|
+
if (step === null) return null;
|
|
386
|
+
steps.push(step);
|
|
425
387
|
}
|
|
426
|
-
|
|
388
|
+
return new Path(steps);
|
|
389
|
+
}
|
|
427
390
|
var Path = class _Path {
|
|
428
391
|
constructor(steps = []) {
|
|
429
392
|
this.steps = steps;
|
|
@@ -431,43 +394,13 @@ var Path = class _Path {
|
|
|
431
394
|
concat(steps) {
|
|
432
395
|
return new _Path(this.steps.concat(steps));
|
|
433
396
|
}
|
|
434
|
-
popStep
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
// The dispatch path: frame-only steps removed, one step per crossed component
|
|
438
|
-
// (DynStep included). `popStep` over it bubbles through every component.
|
|
397
|
+
// Frame-only steps removed, one step per crossed component: `popStep` over the
|
|
398
|
+
// result bubbles through every component.
|
|
439
399
|
compact() {
|
|
440
400
|
const out = [];
|
|
441
401
|
for (const step of this.steps) {
|
|
442
402
|
const s = step.toAbstractPathStep();
|
|
443
|
-
if (s !== null)
|
|
444
|
-
if (s !== step) s._originCid = step._originCid;
|
|
445
|
-
out.push(s);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
return new _Path(out);
|
|
449
|
-
}
|
|
450
|
-
// The abstract path used to apply a transaction: every DynStep is teleported —
|
|
451
|
-
// the steps interior to its producer..consumer span are dropped and the
|
|
452
|
-
// producer's own path spliced in — so a mutation lands on the data's real
|
|
453
|
-
// location. A path with no DynStep is returned unchanged.
|
|
454
|
-
toTransactionPath() {
|
|
455
|
-
let hasDyn = false;
|
|
456
|
-
for (const step of this.steps)
|
|
457
|
-
if (step instanceof DynStep) {
|
|
458
|
-
hasDyn = true;
|
|
459
|
-
break;
|
|
460
|
-
}
|
|
461
|
-
if (!hasDyn) return this;
|
|
462
|
-
const out = [];
|
|
463
|
-
for (const step of this.steps) {
|
|
464
|
-
if (step instanceof DynStep) {
|
|
465
|
-
while (out.length > 0 && step.interiorCids.has(out[out.length - 1]._originCid)) out.pop();
|
|
466
|
-
for (const ts of step.teleportSteps()) {
|
|
467
|
-
ts._originCid = step.producerCompId;
|
|
468
|
-
out.push(ts);
|
|
469
|
-
}
|
|
470
|
-
} else out.push(step);
|
|
403
|
+
if (s !== null) out.push(s);
|
|
471
404
|
}
|
|
472
405
|
return new _Path(out);
|
|
473
406
|
}
|
|
@@ -475,7 +408,6 @@ var Path = class _Path {
|
|
|
475
408
|
// key as it is *now* so a later lookup/setValue lands on the same item even if the
|
|
476
409
|
// keyField changed meanwhile (e.g. the selected tab moved while an intent was in
|
|
477
410
|
// flight). Returns a new Path with those steps replaced; `this` if nothing pinned.
|
|
478
|
-
// Must be called on a transaction path (no DynSteps — call toTransactionPath first).
|
|
479
411
|
pinKeys(root) {
|
|
480
412
|
let curVal = root;
|
|
481
413
|
let out = null;
|
|
@@ -483,7 +415,7 @@ var Path = class _Path {
|
|
|
483
415
|
const step = this.steps[i];
|
|
484
416
|
const pinned = step.pinKey(curVal);
|
|
485
417
|
if (pinned !== step) (out ??= this.steps.slice())[i] = pinned;
|
|
486
|
-
curVal = step.lookup(curVal
|
|
418
|
+
curVal = step.lookup(curVal);
|
|
487
419
|
if (curVal === NONE) break;
|
|
488
420
|
}
|
|
489
421
|
return out ? new _Path(out) : this;
|
|
@@ -491,20 +423,20 @@ var Path = class _Path {
|
|
|
491
423
|
lookup(v, dval = null) {
|
|
492
424
|
let curVal = v;
|
|
493
425
|
for (const step of this.steps) {
|
|
494
|
-
curVal = step.lookup(curVal
|
|
426
|
+
curVal = step.lookup(curVal);
|
|
495
427
|
if (curVal === NONE) return dval;
|
|
496
428
|
}
|
|
497
429
|
return curVal;
|
|
498
430
|
}
|
|
499
431
|
// The values entered along the path, root→leaf (root included): index 0 is `root`,
|
|
500
432
|
// the last entry is the leaf this path resolves to. Stops early at the first
|
|
501
|
-
// unresolvable step.
|
|
502
|
-
//
|
|
433
|
+
// unresolvable step. Used to walk the component instances on a dispatch path
|
|
434
|
+
// (filter via Components.getCompFor).
|
|
503
435
|
resolveChain(root) {
|
|
504
436
|
const out = [root];
|
|
505
437
|
let curVal = root;
|
|
506
438
|
for (const step of this.steps) {
|
|
507
|
-
curVal = step.lookup(curVal
|
|
439
|
+
curVal = step.lookup(curVal);
|
|
508
440
|
if (curVal === NONE) break;
|
|
509
441
|
out.push(curVal);
|
|
510
442
|
}
|
|
@@ -513,7 +445,7 @@ var Path = class _Path {
|
|
|
513
445
|
// A flat `[{ field, key? }]` list of the addressing steps, skipping frame-only
|
|
514
446
|
// steps (binds). Generic path introspection so tooling (e.g. the storybook
|
|
515
447
|
// activity log) can identify which subtree a transaction touched without
|
|
516
|
-
// depending on Step internals.
|
|
448
|
+
// depending on Step internals.
|
|
517
449
|
toKeys() {
|
|
518
450
|
const out = [];
|
|
519
451
|
for (const step of this.steps) {
|
|
@@ -527,69 +459,146 @@ var Path = class _Path {
|
|
|
527
459
|
return (0, immer_exports.produce)(root, (draft) => {
|
|
528
460
|
let parent = draft;
|
|
529
461
|
for (let i = 0; i < this.steps.length - 1; i++) {
|
|
530
|
-
parent = this.steps[i].lookup(parent
|
|
462
|
+
parent = this.steps[i].lookup(parent);
|
|
531
463
|
if (parent === NONE) return;
|
|
532
464
|
}
|
|
533
465
|
this.steps.at(-1).setDraftValue(parent, v);
|
|
534
466
|
});
|
|
535
467
|
}
|
|
468
|
+
};
|
|
469
|
+
function walkItems(stack, items, renderPath, path2) {
|
|
470
|
+
let prev = stack.it;
|
|
471
|
+
for (const step of items) {
|
|
472
|
+
const next = step.lookup(prev);
|
|
473
|
+
if (next === NONE) {
|
|
474
|
+
console.warn("bad PathItem", { root: stack.it, step, path: path2 });
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
renderPath = renderPath.pushItem(step);
|
|
478
|
+
stack = step.enterFrame(stack, next, renderPath);
|
|
479
|
+
prev = next;
|
|
480
|
+
}
|
|
481
|
+
return [stack, renderPath];
|
|
482
|
+
}
|
|
483
|
+
var EMPTY_PATH = new Path([]);
|
|
484
|
+
var DispatchPath = class _DispatchPath {
|
|
485
|
+
constructor(frames = [{ base: EMPTY_PATH, items: [] }]) {
|
|
486
|
+
this.frames = frames;
|
|
487
|
+
}
|
|
488
|
+
// Plain addressing steps in one frame based at the root: what a caller means
|
|
489
|
+
// by "this position" when it has no continuation of its own.
|
|
490
|
+
static ofSteps(steps) {
|
|
491
|
+
return new _DispatchPath([{ base: EMPTY_PATH, items: steps.slice() }]);
|
|
492
|
+
}
|
|
493
|
+
get top() {
|
|
494
|
+
return this.frames[this.frames.length - 1];
|
|
495
|
+
}
|
|
496
|
+
_withTopItems(items) {
|
|
497
|
+
const frames = this.frames.slice();
|
|
498
|
+
frames[frames.length - 1] = { base: this.top.base, items };
|
|
499
|
+
return new _DispatchPath(frames);
|
|
500
|
+
}
|
|
501
|
+
concat(steps) {
|
|
502
|
+
return this._withTopItems(this.top.items.concat(steps));
|
|
503
|
+
}
|
|
504
|
+
pushItem(step) {
|
|
505
|
+
return this.concat([step]);
|
|
506
|
+
}
|
|
507
|
+
pushFrame(base) {
|
|
508
|
+
return new _DispatchPath(this.frames.concat({ base, items: [] }));
|
|
509
|
+
}
|
|
510
|
+
// Whether bubbling has anywhere left to go: another step in this frame, or a
|
|
511
|
+
// visual caller underneath it. (A path always has at least one frame.)
|
|
512
|
+
canPop() {
|
|
513
|
+
return this.frames.length > 1 || this.frames[0].items.length > 0;
|
|
514
|
+
}
|
|
515
|
+
// One component closer to the root. At the top of a frame that is popping back
|
|
516
|
+
// to the visual caller, not to the producer's own parent — the caller is where
|
|
517
|
+
// the `*name` was written, and where an unhandled message should keep going.
|
|
518
|
+
popStep() {
|
|
519
|
+
const { top } = this;
|
|
520
|
+
if (top.items.length > 0) return this._withTopItems(top.items.slice(0, -1));
|
|
521
|
+
if (this.frames.length > 1) return new _DispatchPath(this.frames.slice(0, -1));
|
|
522
|
+
return this;
|
|
523
|
+
}
|
|
524
|
+
// Drop frame-only steps inside every frame independently; a frame's base is
|
|
525
|
+
// already addressing-only.
|
|
526
|
+
compact() {
|
|
527
|
+
return new _DispatchPath(
|
|
528
|
+
this.frames.map(({ base, items }) => ({ base, items: new Path(items).compact().steps }))
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
// A stable string for the ADDRESS this path denotes, for the render cache. The
|
|
532
|
+
// same immutable value can sit at two places in the tree, and a subtree rendered
|
|
533
|
+
// at one of them bakes that address in — the provides it publishes are located
|
|
534
|
+
// there. Frame-only steps address nothing, so they are compacted out: two sites
|
|
535
|
+
// that differ only in binds do render the same subtree.
|
|
536
|
+
get addressKey() {
|
|
537
|
+
this._addressKey ??= renderPathText(this.toTransactionPath().compact());
|
|
538
|
+
return this._addressKey;
|
|
539
|
+
}
|
|
540
|
+
// The active transaction address: the top frame's absolute base followed by
|
|
541
|
+
// its ordinary descendant steps. This is where a mutation lands.
|
|
542
|
+
toTransactionPath() {
|
|
543
|
+
const { base, items } = this.top;
|
|
544
|
+
return base.concat(items);
|
|
545
|
+
}
|
|
546
|
+
// Rebuild the render stack this path was dispatched from. A frame with a base
|
|
547
|
+
// re-enters at that absolute value first — replaying the resume a `*name`
|
|
548
|
+
// render performed — and then walks its ordinary items.
|
|
536
549
|
buildStack(stack) {
|
|
537
|
-
let
|
|
538
|
-
for (
|
|
539
|
-
const
|
|
540
|
-
if (
|
|
541
|
-
|
|
542
|
-
|
|
550
|
+
let renderPath = new _DispatchPath();
|
|
551
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
552
|
+
const { base, items } = this.frames[i];
|
|
553
|
+
if (i > 0 || base.steps.length > 0) {
|
|
554
|
+
const baseValue = base.lookup(stack.root, NONE);
|
|
555
|
+
if (baseValue === NONE) {
|
|
556
|
+
console.warn("bad frame base", { base, path: this });
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
renderPath = renderPath.pushFrame(base);
|
|
560
|
+
stack = stack.enter(baseValue, {}, true, renderPath);
|
|
543
561
|
}
|
|
544
|
-
|
|
545
|
-
|
|
562
|
+
const walked = walkItems(stack, items, renderPath, this);
|
|
563
|
+
if (walked === null) return null;
|
|
564
|
+
[stack, renderPath] = walked;
|
|
546
565
|
}
|
|
547
566
|
return stack;
|
|
548
567
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
568
|
+
// Reconstruct the dispatch position of a DOM event from the `data-*` stamps and
|
|
569
|
+
// `§…§` meta comments the renderer left on the way down. `stopOnNoEvent` is off for
|
|
570
|
+
// drag events, whose path is needed even where no handler is registered.
|
|
571
|
+
static fromNodeAndEventName(node, eventName, rootNode, comps, stopOnNoEvent = true) {
|
|
572
|
+
const parts = [];
|
|
552
573
|
const bubbles = BUBBLING_EVENTS.has(eventName);
|
|
553
|
-
let depth = 0;
|
|
554
574
|
let eventIds = [];
|
|
555
575
|
let handlers = null;
|
|
556
|
-
let
|
|
576
|
+
let nodeRefs = [];
|
|
557
577
|
let isLeafComponent = true;
|
|
558
578
|
const crossComponent = (cidNum, vid) => {
|
|
559
579
|
const comp = comps.getComponentForId(cidNum);
|
|
560
|
-
let
|
|
580
|
+
let pushPart = true;
|
|
561
581
|
if (handlers === null && (isLeafComponent || bubbles)) {
|
|
562
582
|
handlers = findHandlers(comp, eventIds, vid, eventName);
|
|
563
583
|
if (handlers === null) {
|
|
564
584
|
if (isLeafComponent && stopOnNoEvent && !bubbles) return false;
|
|
565
585
|
} else if (!isLeafComponent) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
pushStep = false;
|
|
586
|
+
parts.length = 0;
|
|
587
|
+
pushPart = false;
|
|
569
588
|
}
|
|
570
589
|
}
|
|
571
590
|
isLeafComponent = false;
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
if (step) {
|
|
576
|
-
step._originCid = cidNum;
|
|
577
|
-
pathSteps.push(step);
|
|
578
|
-
if (step instanceof DynStep) {
|
|
579
|
-
step.interiorCids.add(cidNum);
|
|
580
|
-
pendingDyns.push(step);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
591
|
+
if (pushPart) {
|
|
592
|
+
const part = resolvePathPart(comp, nodeRefs, vid);
|
|
593
|
+
if (part) parts.push(part);
|
|
583
594
|
}
|
|
584
|
-
for (let i = pendingDyns.length - 1; i >= 0; i--)
|
|
585
|
-
if (pendingDyns[i].producerCompId === cidNum) pendingDyns.splice(i, 1);
|
|
586
595
|
eventIds = [];
|
|
587
|
-
|
|
596
|
+
nodeRefs = [];
|
|
588
597
|
return true;
|
|
589
598
|
};
|
|
590
|
-
while (node && node !== rootNode
|
|
599
|
+
while (node && node !== rootNode) {
|
|
591
600
|
if (node?.dataset) {
|
|
592
|
-
const { eid, cid, vid } = node.dataset;
|
|
601
|
+
const { eid, cid, vid, rp } = node.dataset;
|
|
593
602
|
if (eid !== void 0) eventIds.push(eid);
|
|
594
603
|
const metas = metaChain(node.previousSibling);
|
|
595
604
|
let sawComp = false;
|
|
@@ -597,21 +606,46 @@ var Path = class _Path {
|
|
|
597
606
|
if (m.$ === "Comp") {
|
|
598
607
|
sawComp = true;
|
|
599
608
|
if (!crossComponent(m.cid, m.vid)) return NO_EVENT_INFO;
|
|
600
|
-
|
|
609
|
+
nodeRefs.push({ nid: m.nid, base: pathFromJson(m.base) });
|
|
601
610
|
} else {
|
|
602
|
-
|
|
611
|
+
nodeRefs.push({ nid: m.nid, si: m.si, sk: m.sk });
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
if (!sawComp && cid !== void 0) {
|
|
615
|
+
if (!crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
616
|
+
if (rp !== void 0) {
|
|
617
|
+
const base = parseRenderPath(rp);
|
|
618
|
+
if (base !== null) nodeRefs.push({ base });
|
|
603
619
|
}
|
|
604
620
|
}
|
|
605
|
-
if (!sawComp && cid !== void 0 && !crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
606
621
|
}
|
|
607
|
-
depth += 1;
|
|
608
622
|
node = node.parentNode;
|
|
609
623
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
624
|
+
parts.reverse();
|
|
625
|
+
let path2 = new _DispatchPath();
|
|
626
|
+
for (const part of parts)
|
|
627
|
+
path2 = part.base !== void 0 ? path2.pushFrame(part.base) : path2.pushItem(part.step);
|
|
628
|
+
return [path2, handlers];
|
|
613
629
|
}
|
|
614
630
|
};
|
|
631
|
+
function keyedPath(path2, key) {
|
|
632
|
+
const steps = path2.steps;
|
|
633
|
+
const last = steps[steps.length - 1];
|
|
634
|
+
if (last instanceof SeqStep || last instanceof FieldStep)
|
|
635
|
+
return new Path(steps.slice(0, -1).concat(new SeqStep(last.field, key)));
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
function renderPathText(path2) {
|
|
639
|
+
return JSON.stringify(pathToJson(path2));
|
|
640
|
+
}
|
|
641
|
+
function parseRenderPath(text) {
|
|
642
|
+
try {
|
|
643
|
+
return pathFromJson(JSON.parse(text));
|
|
644
|
+
} catch (err) {
|
|
645
|
+
console.warn("bad render path", err, text);
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
615
649
|
function metaChain(n) {
|
|
616
650
|
const out = [];
|
|
617
651
|
while (n?.nodeType === 8 && n.textContent[0] === "§") {
|
|
@@ -656,28 +690,28 @@ var StepCtx = class _StepCtx {
|
|
|
656
690
|
resolveNode() {
|
|
657
691
|
return this.comp.getNodeForId(+this.meta.nid, this.vid);
|
|
658
692
|
}
|
|
659
|
-
applyKey(pi) {
|
|
660
|
-
if (pi === null) return null;
|
|
661
|
-
const m = this.meta;
|
|
662
|
-
if (m.si !== void 0) return pi.withIndex(+m.si);
|
|
663
|
-
if (m.sk !== void 0) return pi.withKey(m.sk);
|
|
664
|
-
return pi;
|
|
665
|
-
}
|
|
666
693
|
};
|
|
667
|
-
function
|
|
668
|
-
for (let i = 0; i <
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
if (
|
|
694
|
+
function resolvePathPart(comp, nodeRefs, vid) {
|
|
695
|
+
for (let i = 0; i < nodeRefs.length; i++) {
|
|
696
|
+
const ref = nodeRefs[i];
|
|
697
|
+
if (ref.base != null) return { base: ref.base };
|
|
698
|
+
if (ref.nid === void 0 || ref.nid === null) continue;
|
|
699
|
+
const ctx = new StepCtx(comp, nodeRefs, i, vid);
|
|
700
|
+
const step = ctx.resolveNode()?.toPathStep(ctx) ?? null;
|
|
701
|
+
if (step !== null) return { step };
|
|
672
702
|
}
|
|
673
703
|
return null;
|
|
674
704
|
}
|
|
675
705
|
var NO_EVENT_INFO = [null, null];
|
|
676
706
|
var BUBBLING_EVENTS = /* @__PURE__ */ new Set(["drop"]);
|
|
707
|
+
var path = () => new PathBuilder();
|
|
677
708
|
var PathBuilder = class {
|
|
678
709
|
constructor() {
|
|
679
710
|
this.pathChanges = [];
|
|
680
711
|
}
|
|
712
|
+
toPath() {
|
|
713
|
+
return new Path(this.pathChanges);
|
|
714
|
+
}
|
|
681
715
|
add(pathChange) {
|
|
682
716
|
this.pathChanges.push(pathChange);
|
|
683
717
|
return this;
|
|
@@ -693,10 +727,8 @@ var PathBuilder = class {
|
|
|
693
727
|
}
|
|
694
728
|
};
|
|
695
729
|
|
|
696
|
-
// src/util/env.js
|
|
697
|
-
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
698
|
-
|
|
699
730
|
// src/value.js
|
|
731
|
+
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
700
732
|
var VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*\??$/;
|
|
701
733
|
var isValidValId = (name) => VALID_VAL_ID_RE.test(name);
|
|
702
734
|
var VALID_FLOAT_RE = /^-?[0-9]+(\.[0-9]+)?$/;
|
|
@@ -878,22 +910,10 @@ function _parsePredicate(s, tokens, px) {
|
|
|
878
910
|
}
|
|
879
911
|
return new PredicateVal(pred, args);
|
|
880
912
|
}
|
|
881
|
-
|
|
882
|
-
if (val === null) return 0;
|
|
883
|
-
if (val instanceof ConstVal) return val.kind;
|
|
884
|
-
if (val instanceof StrTplVal) return val.kind;
|
|
885
|
-
if (val instanceof SeqAccessVal) return K_SEQ;
|
|
886
|
-
if (val instanceof FieldVal) return K_FIELD;
|
|
887
|
-
if (val instanceof MethodVal) return K_METHOD;
|
|
888
|
-
if (val instanceof BindVal) return K_BIND;
|
|
889
|
-
if (val instanceof DynVal) return K_DYN;
|
|
890
|
-
if (val instanceof NameVal) return K_NAME;
|
|
891
|
-
if (val instanceof EventMemberVal) return K_EVENT;
|
|
892
|
-
return 0;
|
|
893
|
-
}
|
|
913
|
+
var kindOf = (val) => val?.kind ?? 0;
|
|
894
914
|
var BaseVal = class {
|
|
895
|
-
|
|
896
|
-
|
|
915
|
+
// No kind: never accepted by a group (PredicateVal, which only parseBool builds).
|
|
916
|
+
kind = 0;
|
|
897
917
|
eval(_stack) {
|
|
898
918
|
}
|
|
899
919
|
toPathItem() {
|
|
@@ -913,9 +933,6 @@ var ConstVal = class extends BaseVal {
|
|
|
913
933
|
this.val = val;
|
|
914
934
|
this.kind = kind;
|
|
915
935
|
}
|
|
916
|
-
render(_stack, _rx) {
|
|
917
|
-
return this.val;
|
|
918
|
-
}
|
|
919
936
|
eval(_stack) {
|
|
920
937
|
return this.val;
|
|
921
938
|
}
|
|
@@ -941,9 +958,7 @@ var PredicateVal = class extends BaseVal {
|
|
|
941
958
|
return `${this.pred.name} ${this.args.map(String).join(" ")}`;
|
|
942
959
|
}
|
|
943
960
|
};
|
|
944
|
-
var
|
|
945
|
-
};
|
|
946
|
-
var StrTplVal = class _StrTplVal extends VarVal {
|
|
961
|
+
var StrTplVal = class _StrTplVal extends BaseVal {
|
|
947
962
|
constructor(vals) {
|
|
948
963
|
super();
|
|
949
964
|
this.vals = vals;
|
|
@@ -956,9 +971,6 @@ var StrTplVal = class _StrTplVal extends VarVal {
|
|
|
956
971
|
for (const v of this.vals) if (!(v instanceof ConstVal) || v.fromMacroVar) return false;
|
|
957
972
|
return true;
|
|
958
973
|
}
|
|
959
|
-
render(stack, _rx) {
|
|
960
|
-
return this.eval(stack);
|
|
961
|
-
}
|
|
962
974
|
eval(stack) {
|
|
963
975
|
const strs = new Array(this.vals.length);
|
|
964
976
|
for (let i = 0; i < this.vals.length; i++) strs[i] = this.vals[i]?.eval(stack, "");
|
|
@@ -995,7 +1007,8 @@ var StrTplVal = class _StrTplVal extends VarVal {
|
|
|
995
1007
|
return new _StrTplVal(lo === 0 && hi === vals.length ? vals : vals.slice(lo, hi));
|
|
996
1008
|
}
|
|
997
1009
|
};
|
|
998
|
-
var NameVal = class extends
|
|
1010
|
+
var NameVal = class extends BaseVal {
|
|
1011
|
+
kind = K_NAME;
|
|
999
1012
|
constructor(name) {
|
|
1000
1013
|
super();
|
|
1001
1014
|
this.name = name;
|
|
@@ -1045,6 +1058,7 @@ var EVENT_CONVENIENCES = {
|
|
|
1045
1058
|
dragKey: nullSafe((info) => info.lookupBind("key"))
|
|
1046
1059
|
};
|
|
1047
1060
|
var EventMemberVal = class extends BaseVal {
|
|
1061
|
+
kind = K_EVENT;
|
|
1048
1062
|
constructor(members) {
|
|
1049
1063
|
super();
|
|
1050
1064
|
this.members = members;
|
|
@@ -1067,24 +1081,21 @@ var EventMemberVal = class extends BaseVal {
|
|
|
1067
1081
|
return `e.${this.members.join(".")}`;
|
|
1068
1082
|
}
|
|
1069
1083
|
};
|
|
1070
|
-
var
|
|
1071
|
-
render(stack, _rx) {
|
|
1072
|
-
return this.eval(stack);
|
|
1073
|
-
}
|
|
1074
|
-
};
|
|
1075
|
-
var RenderNameVal = class extends RenderVal {
|
|
1084
|
+
var SigilNameVal = class extends BaseVal {
|
|
1076
1085
|
constructor(name) {
|
|
1077
1086
|
super();
|
|
1078
1087
|
this.name = name;
|
|
1079
1088
|
}
|
|
1089
|
+
toString() {
|
|
1090
|
+
return this.sigil + this.name;
|
|
1091
|
+
}
|
|
1080
1092
|
};
|
|
1081
|
-
var BindVal = class extends
|
|
1093
|
+
var BindVal = class extends SigilNameVal {
|
|
1094
|
+
kind = K_BIND;
|
|
1095
|
+
sigil = "@";
|
|
1082
1096
|
eval(stack) {
|
|
1083
1097
|
return stack.lookupBind(this.name);
|
|
1084
1098
|
}
|
|
1085
|
-
toString() {
|
|
1086
|
-
return `@${this.name}`;
|
|
1087
|
-
}
|
|
1088
1099
|
};
|
|
1089
1100
|
var BindMemberVal = class extends BindVal {
|
|
1090
1101
|
constructor(name, member) {
|
|
@@ -1099,37 +1110,35 @@ var BindMemberVal = class extends BindVal {
|
|
|
1099
1110
|
return `@${this.name}.${this.member}`;
|
|
1100
1111
|
}
|
|
1101
1112
|
};
|
|
1102
|
-
var DynVal = class extends
|
|
1113
|
+
var DynVal = class extends SigilNameVal {
|
|
1114
|
+
kind = K_DYN;
|
|
1115
|
+
sigil = "*";
|
|
1103
1116
|
eval(stack) {
|
|
1104
1117
|
return stack.lookupDynamic(this.name);
|
|
1105
1118
|
}
|
|
1106
|
-
toString() {
|
|
1107
|
-
return `*${this.name}`;
|
|
1108
|
-
}
|
|
1109
1119
|
};
|
|
1110
|
-
var FieldVal = class extends
|
|
1120
|
+
var FieldVal = class extends SigilNameVal {
|
|
1121
|
+
kind = K_FIELD;
|
|
1122
|
+
sigil = ".";
|
|
1111
1123
|
eval(stack) {
|
|
1112
1124
|
return stack.lookupFieldRaw(this.name);
|
|
1113
1125
|
}
|
|
1114
1126
|
toPathItem() {
|
|
1115
1127
|
return new FieldStep(this.name);
|
|
1116
1128
|
}
|
|
1117
|
-
toString() {
|
|
1118
|
-
return `.${this.name}`;
|
|
1119
|
-
}
|
|
1120
1129
|
};
|
|
1121
|
-
var MethodVal = class extends
|
|
1130
|
+
var MethodVal = class extends SigilNameVal {
|
|
1131
|
+
kind = K_METHOD;
|
|
1132
|
+
sigil = "$";
|
|
1122
1133
|
eval(stack) {
|
|
1123
1134
|
return stack.lookupMethod(this.name);
|
|
1124
1135
|
}
|
|
1125
1136
|
evalAsHandler(stack) {
|
|
1126
1137
|
return stack.lookupFieldRaw(this.name);
|
|
1127
1138
|
}
|
|
1128
|
-
toString() {
|
|
1129
|
-
return `$${this.name}`;
|
|
1130
|
-
}
|
|
1131
1139
|
};
|
|
1132
|
-
var SeqAccessVal = class extends
|
|
1140
|
+
var SeqAccessVal = class extends BaseVal {
|
|
1141
|
+
kind = K_SEQ;
|
|
1133
1142
|
constructor(seqVal, keyVal) {
|
|
1134
1143
|
super();
|
|
1135
1144
|
this.seqVal = seqVal;
|
|
@@ -1152,9 +1161,6 @@ var Attributes = class {
|
|
|
1152
1161
|
constructor(items) {
|
|
1153
1162
|
this.items = items;
|
|
1154
1163
|
}
|
|
1155
|
-
static parse(attributes, px, parseAll = false) {
|
|
1156
|
-
return new AttrParser(px).parse(attributes, parseAll);
|
|
1157
|
-
}
|
|
1158
1164
|
isConstant() {
|
|
1159
1165
|
return false;
|
|
1160
1166
|
}
|
|
@@ -1172,10 +1178,16 @@ function parseDirectiveValue(px, directiveName, source, parser) {
|
|
|
1172
1178
|
}
|
|
1173
1179
|
return val;
|
|
1174
1180
|
}
|
|
1181
|
+
var ITER_DIRECTIVES = {
|
|
1182
|
+
when: "whenVal",
|
|
1183
|
+
"loop-with": "loopWithVal",
|
|
1184
|
+
"enrich-with": "enrichWithVal"
|
|
1185
|
+
};
|
|
1186
|
+
var parseIterDirective = (px, name, s) => parseDirectiveValue(px, name, s, parseAlterHandler);
|
|
1175
1187
|
function parseIterationDirectives(attributes, px) {
|
|
1176
1188
|
const parseNamed = (name) => {
|
|
1177
1189
|
const attr = attributes.getNamedItem(`@${name}`);
|
|
1178
|
-
return attr ?
|
|
1190
|
+
return attr ? parseIterDirective(px, name, attr.value) : null;
|
|
1179
1191
|
};
|
|
1180
1192
|
return { whenVal: parseNamed("when"), loopWithVal: parseNamed("loop-with") };
|
|
1181
1193
|
}
|
|
@@ -1216,11 +1228,22 @@ var AttrParser = class {
|
|
|
1216
1228
|
this.px.onParseIssue("bad-value", info);
|
|
1217
1229
|
}
|
|
1218
1230
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1231
|
+
// `@then` / `@else` fill the branches of the `@if.<attr>` on the same element.
|
|
1232
|
+
parseBranch(slot, name, s) {
|
|
1233
|
+
if (this.ifAttr === null) return this._orphan(name, s, "if");
|
|
1234
|
+
this.ifAttr[slot] = parseText(s, this.px) ?? NOT_SET_VAL;
|
|
1221
1235
|
}
|
|
1222
|
-
|
|
1223
|
-
|
|
1236
|
+
// `@when` / `@loop-with` / `@enrich-with` amend the `@each` on the same element. A
|
|
1237
|
+
// loop-less `@enrich-with` is a scope of its own; the other two need the loop.
|
|
1238
|
+
parseIter(name, s) {
|
|
1239
|
+
const val = parseIterDirective(this.px, name, s);
|
|
1240
|
+
if (this.eachAttr !== null) this.eachAttr[ITER_DIRECTIVES[name]] = val;
|
|
1241
|
+
else if (name === "enrich-with") this.pushWrapper("scope", s, val);
|
|
1242
|
+
else this._orphan(name, s, "each");
|
|
1243
|
+
}
|
|
1244
|
+
// A directive that only means something next to another one, written alone.
|
|
1245
|
+
_orphan(name, value, needs) {
|
|
1246
|
+
this.px.onParseIssue("orphan-directive", { name, value, needs });
|
|
1224
1247
|
}
|
|
1225
1248
|
parseEvent(directiveName, value) {
|
|
1226
1249
|
const [eventName, ...modifiers] = directiveName.slice(3).split("+");
|
|
@@ -1234,77 +1257,51 @@ var AttrParser = class {
|
|
|
1234
1257
|
this.events.add(eventName, handler, modifiers);
|
|
1235
1258
|
}
|
|
1236
1259
|
}
|
|
1237
|
-
_parseDirectiveValue(directiveName, s, parserFn) {
|
|
1238
|
-
return parseDirectiveValue(this.px, directiveName, s, parserFn);
|
|
1239
|
-
}
|
|
1240
1260
|
parseDirective(s, directiveName) {
|
|
1241
1261
|
switch (directiveName) {
|
|
1242
1262
|
case "dangerouslysetinnerhtml":
|
|
1243
1263
|
this.attrs ??= [];
|
|
1244
|
-
this.attrs.push(new RawHtmlAttr(this.
|
|
1264
|
+
this.attrs.push(new RawHtmlAttr(parseDirectiveValue(this.px, directiveName, s, parseText)));
|
|
1245
1265
|
this.hasDynamic = true;
|
|
1246
1266
|
return;
|
|
1247
1267
|
case "push-view":
|
|
1248
|
-
this.pushWrapper("push-view", s, this.
|
|
1268
|
+
this.pushWrapper("push-view", s, parseDirectiveValue(this.px, directiveName, s, parseText));
|
|
1249
1269
|
return;
|
|
1250
1270
|
case "text":
|
|
1251
|
-
this.textChild = this.
|
|
1271
|
+
this.textChild = parseDirectiveValue(this.px, directiveName, s, parseText);
|
|
1252
1272
|
return;
|
|
1253
1273
|
case "show":
|
|
1254
|
-
this.pushWrapper("show", s, this.
|
|
1274
|
+
this.pushWrapper("show", s, parseDirectiveValue(this.px, directiveName, s, parseBool));
|
|
1255
1275
|
return;
|
|
1256
1276
|
case "hide":
|
|
1257
|
-
this.pushWrapper("hide", s, this.
|
|
1277
|
+
this.pushWrapper("hide", s, parseDirectiveValue(this.px, directiveName, s, parseBool));
|
|
1258
1278
|
return;
|
|
1259
1279
|
case "each": {
|
|
1260
|
-
const val = this.
|
|
1280
|
+
const val = parseDirectiveValue(this.px, directiveName, s, parseSequence);
|
|
1261
1281
|
this.eachAttr = this.pushWrapper("each", s, val);
|
|
1262
1282
|
return;
|
|
1263
1283
|
}
|
|
1264
|
-
case "enrich-with":
|
|
1265
|
-
if (this.eachAttr !== null)
|
|
1266
|
-
this.eachAttr.enrichWithVal = this._parseDirectiveValue(
|
|
1267
|
-
directiveName,
|
|
1268
|
-
s,
|
|
1269
|
-
parseAlterHandler
|
|
1270
|
-
);
|
|
1271
|
-
else
|
|
1272
|
-
this.pushWrapper(
|
|
1273
|
-
"scope",
|
|
1274
|
-
s,
|
|
1275
|
-
this._parseDirectiveValue(directiveName, s, parseAlterHandler)
|
|
1276
|
-
);
|
|
1277
|
-
return;
|
|
1278
1284
|
case "when":
|
|
1279
|
-
this._parseWhen(s);
|
|
1280
|
-
return;
|
|
1281
1285
|
case "loop-with":
|
|
1282
|
-
|
|
1286
|
+
case "enrich-with":
|
|
1287
|
+
this.parseIter(directiveName, s);
|
|
1283
1288
|
return;
|
|
1284
1289
|
case "then":
|
|
1285
|
-
this.
|
|
1290
|
+
this.parseBranch("thenVal", directiveName, s);
|
|
1286
1291
|
return;
|
|
1287
1292
|
case "else":
|
|
1288
|
-
this.
|
|
1293
|
+
this.parseBranch("elseVal", directiveName, s);
|
|
1289
1294
|
return;
|
|
1290
1295
|
}
|
|
1291
1296
|
if (directiveName.startsWith("on.")) this.parseEvent(directiveName, s);
|
|
1292
1297
|
else if (directiveName.startsWith("if.")) this.parseIf(directiveName, s);
|
|
1293
|
-
else if (directiveName.startsWith("then.")) this.
|
|
1294
|
-
else if (directiveName.startsWith("else.")) this.
|
|
1298
|
+
else if (directiveName.startsWith("then.")) this.parseBranch("thenVal", directiveName, s);
|
|
1299
|
+
else if (directiveName.startsWith("else.")) this.parseBranch("elseVal", directiveName, s);
|
|
1295
1300
|
else {
|
|
1296
1301
|
const info = { name: directiveName, value: s };
|
|
1297
1302
|
this.px.onParseIssue("unknown-directive", info);
|
|
1298
1303
|
}
|
|
1299
1304
|
}
|
|
1300
|
-
_parseWhen(s) {
|
|
1301
|
-
if (this.eachAttr !== null)
|
|
1302
|
-
this.eachAttr.whenVal = this._parseDirectiveValue("when", s, parseAlterHandler);
|
|
1303
|
-
}
|
|
1304
|
-
_parseLoopWith(s) {
|
|
1305
|
-
if (this.eachAttr !== null)
|
|
1306
|
-
this.eachAttr.loopWithVal = this._parseDirectiveValue("loop-with", s, parseAlterHandler);
|
|
1307
|
-
}
|
|
1308
1305
|
parse(attributes, parseAll = false) {
|
|
1309
1306
|
for (const { name, value } of attributes) {
|
|
1310
1307
|
const charCode = name.charCodeAt(0);
|
|
@@ -1657,19 +1654,21 @@ var VNode = class _VNode extends VBase {
|
|
|
1657
1654
|
const createOpts = attrs.is != null ? { is: attrs.is } : void 0;
|
|
1658
1655
|
const node = ns === null ? doc.createElement(tag, createOpts) : doc.createElementNS(ns, tag, createOpts);
|
|
1659
1656
|
const cOpts = childOpts(this, ns, opts);
|
|
1660
|
-
|
|
1661
|
-
const { value, checked, ...rest } = attrs;
|
|
1662
|
-
applyProperties(node, rest);
|
|
1663
|
-
appendChildNodes(node, this.childs, cOpts);
|
|
1664
|
-
if (value !== void 0) applyValueLast(node, value);
|
|
1665
|
-
if (checked !== void 0) setProp(node, "checked", checked, false);
|
|
1666
|
-
} else {
|
|
1667
|
-
applyProperties(node, attrs);
|
|
1668
|
-
appendChildNodes(node, this.childs, cOpts);
|
|
1669
|
-
}
|
|
1657
|
+
applyAttrs(node, attrs, () => appendChildNodes(node, this.childs, cOpts));
|
|
1670
1658
|
return node;
|
|
1671
1659
|
}
|
|
1672
1660
|
};
|
|
1661
|
+
function applyAttrs(node, attrs, placeChildren) {
|
|
1662
|
+
const hasValue = "value" in attrs;
|
|
1663
|
+
const hasChecked = "checked" in attrs;
|
|
1664
|
+
if (hasValue || hasChecked) {
|
|
1665
|
+
const { value: _v, checked: _c, ...rest } = attrs;
|
|
1666
|
+
applyProperties(node, rest);
|
|
1667
|
+
} else applyProperties(node, attrs);
|
|
1668
|
+
placeChildren();
|
|
1669
|
+
if (hasValue) applyValueLast(node, attrs.value);
|
|
1670
|
+
if (hasChecked) setProp(node, "checked", attrs.checked, isNamespaced(node));
|
|
1671
|
+
}
|
|
1673
1672
|
function diffProps(a, b) {
|
|
1674
1673
|
if (a === b) return null;
|
|
1675
1674
|
let diff = null;
|
|
@@ -1700,22 +1699,16 @@ function morphNode(domNode, source, target, opts) {
|
|
|
1700
1699
|
}
|
|
1701
1700
|
if (type === 1 && source.isSameKind(target)) {
|
|
1702
1701
|
const propsDiff = diffProps(source.attrs, target.attrs);
|
|
1703
|
-
const
|
|
1704
|
-
|
|
1705
|
-
if (propsDiff) {
|
|
1706
|
-
if (hasValue || hasChecked) {
|
|
1707
|
-
const { value: _v, checked: _c, ...rest } = propsDiff;
|
|
1708
|
-
applyProperties(domNode, rest);
|
|
1709
|
-
} else applyProperties(domNode, propsDiff);
|
|
1710
|
-
}
|
|
1711
|
-
if (!target.attrs.dangerouslySetInnerHTML) {
|
|
1702
|
+
const placeChildren = () => {
|
|
1703
|
+
if (target.attrs.dangerouslySetInnerHTML) return;
|
|
1712
1704
|
const ns = effectiveNs(target, opts);
|
|
1713
1705
|
morphChildren(domNode, source.childs, target.childs, childOpts(target, ns, opts));
|
|
1706
|
+
};
|
|
1707
|
+
if (propsDiff) applyAttrs(domNode, propsDiff, placeChildren);
|
|
1708
|
+
else placeChildren();
|
|
1709
|
+
if (!(propsDiff && "value" in propsDiff) && source.tag === "SELECT") {
|
|
1710
|
+
if (target.attrs.value !== void 0) applyValueLast(domNode, target.attrs.value);
|
|
1714
1711
|
}
|
|
1715
|
-
if (hasValue) applyValueLast(domNode, propsDiff.value);
|
|
1716
|
-
else if (source.tag === "SELECT" && target.attrs.value !== void 0)
|
|
1717
|
-
applyValueLast(domNode, target.attrs.value);
|
|
1718
|
-
if (hasChecked) setProp(domNode, "checked", propsDiff.checked, false);
|
|
1719
1712
|
return domNode;
|
|
1720
1713
|
}
|
|
1721
1714
|
if (type === 11) {
|
|
@@ -1834,20 +1827,26 @@ function h(tagName, properties, children, namespace) {
|
|
|
1834
1827
|
}
|
|
1835
1828
|
|
|
1836
1829
|
// src/anode.js
|
|
1837
|
-
function
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1830
|
+
function renderTarget(val, stack) {
|
|
1831
|
+
if (val instanceof DynVal) {
|
|
1832
|
+
const loc = stack.lookupDynamicLocated(val.name);
|
|
1833
|
+
if (loc?.path == null) return [loc?.value ?? null, stack.renderPath, null];
|
|
1834
|
+
return [loc.value, stack.renderPath.pushFrame(loc.path), loc.path];
|
|
1835
|
+
}
|
|
1836
|
+
const step = val.toPathItem?.() ?? null;
|
|
1837
|
+
if (step === null) return [val.eval(stack), stack.renderPath, null];
|
|
1838
|
+
const path2 = stack.renderPath.pushItem(step);
|
|
1839
|
+
return [val.eval(stack), path2, stack.pendingFrame ? path2.toTransactionPath() : null];
|
|
1844
1840
|
}
|
|
1845
1841
|
var BaseNode = class {
|
|
1846
1842
|
render(_stack, _rx) {
|
|
1847
1843
|
return null;
|
|
1848
1844
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1845
|
+
// Stamp a `data-*` attribute on the element(s) this node renders. A no-op for
|
|
1846
|
+
// nodes that produce no element of their own (text, `<x render*>`): a view whose
|
|
1847
|
+
// root is one of those records its component boundary in the `§Comp§` meta
|
|
1848
|
+
// comment instead (see Renderer._rValComp).
|
|
1849
|
+
setDataAttr(_key, _val) {
|
|
1851
1850
|
}
|
|
1852
1851
|
isConstant() {
|
|
1853
1852
|
return false;
|
|
@@ -1886,21 +1885,12 @@ var TextNode = class extends BaseNode {
|
|
|
1886
1885
|
isConstant() {
|
|
1887
1886
|
return true;
|
|
1888
1887
|
}
|
|
1889
|
-
setDataAttr(_key, _val) {
|
|
1890
|
-
}
|
|
1891
1888
|
};
|
|
1892
1889
|
var CommentNode = class extends TextNode {
|
|
1893
1890
|
render(_stack, rx) {
|
|
1894
1891
|
return rx.renderComment(this.val);
|
|
1895
1892
|
}
|
|
1896
1893
|
};
|
|
1897
|
-
function optimizeChilds(childs) {
|
|
1898
|
-
for (let i = 0; i < childs.length; i++) {
|
|
1899
|
-
const child = childs[i];
|
|
1900
|
-
if (child.isConstant()) childs[i] = new RenderOnceNode(child);
|
|
1901
|
-
else child.optimize();
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
1894
|
function optimizeNode(node) {
|
|
1905
1895
|
if (node.isConstant()) return new RenderOnceNode(node);
|
|
1906
1896
|
node.optimize();
|
|
@@ -1915,7 +1905,8 @@ var ChildsNode = class extends BaseNode {
|
|
|
1915
1905
|
return this.childs.every((v) => v.isConstant());
|
|
1916
1906
|
}
|
|
1917
1907
|
optimize() {
|
|
1918
|
-
|
|
1908
|
+
const { childs } = this;
|
|
1909
|
+
for (let i = 0; i < childs.length; i++) childs[i] = optimizeNode(childs[i]);
|
|
1919
1910
|
}
|
|
1920
1911
|
};
|
|
1921
1912
|
var DomNode = class extends ChildsNode {
|
|
@@ -1927,8 +1918,7 @@ var DomNode = class extends ChildsNode {
|
|
|
1927
1918
|
}
|
|
1928
1919
|
render(stack, rx) {
|
|
1929
1920
|
const childNodes = new Array(this.childs.length);
|
|
1930
|
-
for (let i = 0; i < childNodes.length; i++)
|
|
1931
|
-
childNodes[i] = this.childs[i]?.render?.(stack, rx) ?? null;
|
|
1921
|
+
for (let i = 0; i < childNodes.length; i++) childNodes[i] = this.childs[i].render(stack, rx);
|
|
1932
1922
|
return rx.renderTag(this.tagName, this.attrs.eval(stack), childNodes, this.namespace);
|
|
1933
1923
|
}
|
|
1934
1924
|
setDataAttr(key, val) {
|
|
@@ -1940,7 +1930,7 @@ var DomNode = class extends ChildsNode {
|
|
|
1940
1930
|
};
|
|
1941
1931
|
var FragmentNode = class extends ChildsNode {
|
|
1942
1932
|
render(stack, rx) {
|
|
1943
|
-
return rx.renderFragment(this.childs.map((c) => c
|
|
1933
|
+
return rx.renderFragment(this.childs.map((c) => c.render(stack, rx)));
|
|
1944
1934
|
}
|
|
1945
1935
|
setDataAttr(key, val) {
|
|
1946
1936
|
for (const child of this.childs) child.setDataAttr(key, val);
|
|
@@ -1954,8 +1944,10 @@ var ANode = class _ANode extends BaseNode {
|
|
|
1954
1944
|
this.nodeId = nodeId;
|
|
1955
1945
|
this.val = val;
|
|
1956
1946
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1947
|
+
// The addressing step this node contributes to an event's dispatch path, given
|
|
1948
|
+
// the `StepCtx` of the meta that named it; null when it addresses nothing.
|
|
1949
|
+
toPathStep(_ctx) {
|
|
1950
|
+
return this.val?.toPathItem?.() ?? null;
|
|
1959
1951
|
}
|
|
1960
1952
|
static parse(html2, px) {
|
|
1961
1953
|
const nodes = px.parseHTML(html2);
|
|
@@ -1971,8 +1963,8 @@ var ANode = class _ANode extends BaseNode {
|
|
|
1971
1963
|
return maybeFragment(trimmed);
|
|
1972
1964
|
}
|
|
1973
1965
|
static fromDOM(node, px) {
|
|
1974
|
-
if (node
|
|
1975
|
-
|
|
1966
|
+
if (node.nodeType === 3) return new TextNode(node.textContent);
|
|
1967
|
+
if (node.nodeType === 8) return new CommentNode(node.textContent);
|
|
1976
1968
|
const { childNodes, attributes: attrs, tagName: tag } = node;
|
|
1977
1969
|
const childs = [];
|
|
1978
1970
|
for (let i = 0; i < childNodes.length; i++) {
|
|
@@ -1990,11 +1982,11 @@ var ANode = class _ANode extends BaseNode {
|
|
|
1990
1982
|
const slotName = attrs.getNamedItem("name")?.value ?? "_";
|
|
1991
1983
|
return px.frame.macroSlots[slotName] ?? maybeFragment(childs);
|
|
1992
1984
|
}
|
|
1993
|
-
const [nAttrs, wrappers] =
|
|
1985
|
+
const [nAttrs, wrappers] = new AttrParser(px).parse(attrs, true);
|
|
1994
1986
|
px.onAttributes(nAttrs, wrappers, null, true, tag);
|
|
1995
1987
|
return wrap(px.newMacroNode(macroName, nAttrs.toMacroVars(), childs), px, wrappers);
|
|
1996
1988
|
} else if (VALID_NODE_RE.test(tag)) {
|
|
1997
|
-
const [nAttrs, wrappers, textChild] =
|
|
1989
|
+
const [nAttrs, wrappers, textChild] = new AttrParser(px).parse(attrs);
|
|
1998
1990
|
px.onAttributes(nAttrs, wrappers, textChild, false, tag);
|
|
1999
1991
|
if (textChild) childs.unshift(new RenderTextNode(null, textChild));
|
|
2000
1992
|
const domChilds = tag !== "PRE" ? condenseChildsWhites(childs) : childs;
|
|
@@ -2156,39 +2148,32 @@ var RenderViewId = class extends ANode {
|
|
|
2156
2148
|
evalViewName(stack) {
|
|
2157
2149
|
return this.viewVal ? this.viewVal.eval(stack) : null;
|
|
2158
2150
|
}
|
|
2159
|
-
// A `<x render*>` produces no DOM element of its own to carry `data-cid`;
|
|
2160
|
-
// when it is a view's root the component boundary is recorded in the `Comp`
|
|
2161
|
-
// meta comment instead (see Renderer._rValComp), so this is a no-op.
|
|
2162
|
-
setDataAttr(_key, _val) {
|
|
2163
|
-
}
|
|
2164
2151
|
};
|
|
2165
|
-
function dynRenderStep(comp, name, key) {
|
|
2166
|
-
const p = resolveDynProducer(comp, name);
|
|
2167
|
-
if (!p) return null;
|
|
2168
|
-
return key === void 0 ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
2169
|
-
}
|
|
2170
2152
|
var RenderNode = class extends RenderViewId {
|
|
2171
2153
|
render(stack, rx) {
|
|
2172
|
-
const
|
|
2173
|
-
|
|
2154
|
+
const [value, renderPath, base] = renderTarget(this.val, stack);
|
|
2155
|
+
const newStack = stack.enter(value, {}, true, renderPath, false);
|
|
2156
|
+
return rx.renderIt(newStack, this, this.evalViewName(stack), base);
|
|
2174
2157
|
}
|
|
2158
|
+
// A `*name` target contributes no step: the site recorded the absolute base it
|
|
2159
|
+
// resumed at, and event reconstruction turns that into a continuation frame.
|
|
2175
2160
|
toPathStep(ctx) {
|
|
2176
|
-
if (this.val instanceof DynVal) return
|
|
2161
|
+
if (this.val instanceof DynVal) return null;
|
|
2177
2162
|
return super.toPathStep(ctx);
|
|
2178
2163
|
}
|
|
2179
2164
|
};
|
|
2180
2165
|
var RenderItNode = class extends RenderViewId {
|
|
2181
2166
|
render(stack, rx) {
|
|
2182
|
-
const
|
|
2183
|
-
|
|
2167
|
+
const base = stack.pendingFrame ? stack.renderPath.toTransactionPath() : null;
|
|
2168
|
+
const newStack = stack.enter(stack.it, {}, true, stack.renderPath, false);
|
|
2169
|
+
return rx.renderIt(newStack, this, this.evalViewName(stack), base);
|
|
2184
2170
|
}
|
|
2185
2171
|
toPathStep(ctx) {
|
|
2186
2172
|
const next = ctx.next();
|
|
2187
2173
|
if (next === null) return null;
|
|
2188
2174
|
const nextNode = next.resolveNode();
|
|
2189
2175
|
if (nextNode instanceof EachNode && next.hasKey) {
|
|
2190
|
-
if (nextNode.val instanceof DynVal)
|
|
2191
|
-
return dynRenderStep(ctx.comp, nextNode.val.name, next.key);
|
|
2176
|
+
if (nextNode.val instanceof DynVal) return null;
|
|
2192
2177
|
return new EachRenderItStep(nextNode.val.name, next.key);
|
|
2193
2178
|
}
|
|
2194
2179
|
return null;
|
|
@@ -2210,9 +2195,6 @@ var RenderTextNode = class extends ANode {
|
|
|
2210
2195
|
render(stack, _rx) {
|
|
2211
2196
|
return this.val.eval(stack);
|
|
2212
2197
|
}
|
|
2213
|
-
// Renders to a text node, which can't carry `data-cid`.
|
|
2214
|
-
setDataAttr(_key, _val) {
|
|
2215
|
-
}
|
|
2216
2198
|
};
|
|
2217
2199
|
var RenderOnceNode = class extends BaseNode {
|
|
2218
2200
|
constructor(node) {
|
|
@@ -2287,35 +2269,45 @@ var ScopeNode = class extends WrapperNode {
|
|
|
2287
2269
|
var EachNode = class extends WrapperNode {
|
|
2288
2270
|
constructor(nodeId, val) {
|
|
2289
2271
|
super(nodeId, val);
|
|
2290
|
-
this.iterInfo = new IterInfo(
|
|
2272
|
+
this.iterInfo = new IterInfo();
|
|
2291
2273
|
}
|
|
2292
2274
|
render(stack, rx) {
|
|
2293
|
-
return rx.renderEachWhen(stack, this
|
|
2275
|
+
return rx.renderEachWhen(stack, this);
|
|
2276
|
+
}
|
|
2277
|
+
// The sequence and the three loop handlers, resolved against `stack`.
|
|
2278
|
+
evalIter(stack) {
|
|
2279
|
+
const { whenVal, loopWithVal, enrichWithVal } = this.iterInfo;
|
|
2280
|
+
return {
|
|
2281
|
+
seq: this.val.eval(stack) ?? [],
|
|
2282
|
+
filter: whenVal?.evalAsHandler(stack) ?? filterAlwaysTrue,
|
|
2283
|
+
loopWith: loopWithVal?.evalAsHandler(stack) ?? nullLoopWith,
|
|
2284
|
+
enricher: enrichWithVal?.evalAsHandler(stack) ?? null
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
// Rebuild the per-item binds for `key` (see iteration.js bindsForKey).
|
|
2288
|
+
enrichBinds(stack, key) {
|
|
2289
|
+
const { seq, filter, loopWith, enricher } = this.evalIter(stack);
|
|
2290
|
+
const ctx = makeLoopCtx(stack, filter);
|
|
2291
|
+
return bindsForKey({ seq, it: stack.it, loopWith, enricher, ctx }, key);
|
|
2294
2292
|
}
|
|
2295
2293
|
toPathStep(ctx) {
|
|
2296
|
-
return ctx.hasKey ? new EachBindStep(this
|
|
2294
|
+
return ctx.hasKey ? new EachBindStep(this, ctx.key) : null;
|
|
2295
|
+
}
|
|
2296
|
+
// Where one item lives, for the render path. `@each` re-binds `it` to the item
|
|
2297
|
+
// whether or not the body is a component, so the position moves either way and
|
|
2298
|
+
// the step has to address it — `.rows` iterated at `key` IS `rows[key]`.
|
|
2299
|
+
// Null for a dynamic sequence: `*rows` carries its own absolute path and enters
|
|
2300
|
+
// a continuation frame instead (see Renderer.renderEachWhen).
|
|
2301
|
+
itemStep(key) {
|
|
2302
|
+
return this.val instanceof FieldVal ? new SeqStep(this.val.name, key) : null;
|
|
2297
2303
|
}
|
|
2298
2304
|
static register = true;
|
|
2299
2305
|
};
|
|
2300
2306
|
var IterInfo = class {
|
|
2301
|
-
constructor(
|
|
2302
|
-
this.
|
|
2303
|
-
this.
|
|
2304
|
-
this.
|
|
2305
|
-
this.enrichWithVal = enrichWithVal;
|
|
2306
|
-
}
|
|
2307
|
-
eval(stack) {
|
|
2308
|
-
const seq = this.val.eval(stack) ?? [];
|
|
2309
|
-
const filter = this.whenVal?.evalAsHandler(stack) ?? filterAlwaysTrue;
|
|
2310
|
-
const loopWith = this.loopWithVal?.evalAsHandler(stack) ?? nullLoopWith;
|
|
2311
|
-
const enricher = this.enrichWithVal?.evalAsHandler(stack) ?? null;
|
|
2312
|
-
return { seq, filter, loopWith, enricher };
|
|
2313
|
-
}
|
|
2314
|
-
// Rebuild the per-item binds for `key` (see iteration.js bindsForKey).
|
|
2315
|
-
enrichBinds(stack, key) {
|
|
2316
|
-
const { seq, filter, loopWith, enricher } = this.eval(stack);
|
|
2317
|
-
const ctx = makeLoopCtx(stack, filter);
|
|
2318
|
-
return bindsForKey({ seq, it: stack.it, loopWith, enricher, ctx }, key);
|
|
2307
|
+
constructor() {
|
|
2308
|
+
this.whenVal = null;
|
|
2309
|
+
this.loopWithVal = null;
|
|
2310
|
+
this.enrichWithVal = null;
|
|
2319
2311
|
}
|
|
2320
2312
|
};
|
|
2321
2313
|
function xOp(consumed = [], { wrappable = false, wrapper = null, ignoresChildren = false } = {}) {
|
|
@@ -2343,26 +2335,31 @@ var WRAPPER_NODES = {
|
|
|
2343
2335
|
scope: ScopeNode,
|
|
2344
2336
|
"push-view": PushViewNameNode
|
|
2345
2337
|
};
|
|
2346
|
-
var ParseContext = class
|
|
2347
|
-
constructor(document2
|
|
2348
|
-
this.
|
|
2349
|
-
this.
|
|
2350
|
-
this.
|
|
2351
|
-
this.
|
|
2352
|
-
this.
|
|
2353
|
-
this.
|
|
2354
|
-
this.Text = Text ?? globalThis.Text;
|
|
2355
|
-
this.Comment = Comment ?? globalThis.Comment;
|
|
2356
|
-
this.cacheConstNodes = true;
|
|
2338
|
+
var ParseContext = class {
|
|
2339
|
+
constructor(document2 = globalThis.document) {
|
|
2340
|
+
this.document = document2;
|
|
2341
|
+
this.nodes = [];
|
|
2342
|
+
this.events = [];
|
|
2343
|
+
this.macroNodes = [];
|
|
2344
|
+
this.parent = null;
|
|
2345
|
+
this.frame = {};
|
|
2357
2346
|
this.currentTag = null;
|
|
2358
2347
|
}
|
|
2359
2348
|
isInsideMacro(name) {
|
|
2360
2349
|
return this.frame.macroName === name || this.parent?.isInsideMacro(name);
|
|
2361
2350
|
}
|
|
2351
|
+
// A macro body parses in a child context that shares every accumulator with
|
|
2352
|
+
// its parent (nodes, events, macroNodes, and whatever a subclass collects) and
|
|
2353
|
+
// differs only in its frame. Cloned rather than constructed so a subclass
|
|
2354
|
+
// keeps collecting inside macro bodies without re-implementing this — the
|
|
2355
|
+
// lint and class-set contexts used to lose (or had to copy) exactly that.
|
|
2362
2356
|
enterMacro(macroName, macroVars, macroSlots) {
|
|
2363
|
-
const
|
|
2364
|
-
|
|
2365
|
-
|
|
2357
|
+
const child = Object.create(Object.getPrototypeOf(this));
|
|
2358
|
+
return Object.assign(child, this, {
|
|
2359
|
+
frame: { macroName, macroVars, macroSlots },
|
|
2360
|
+
parent: this,
|
|
2361
|
+
currentTag: null
|
|
2362
|
+
});
|
|
2366
2363
|
}
|
|
2367
2364
|
parseHTML(html2) {
|
|
2368
2365
|
const t = this.document.createElement("template");
|
|
@@ -2427,10 +2424,10 @@ var isBlockDomNode = (n) => {
|
|
|
2427
2424
|
return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
|
|
2428
2425
|
};
|
|
2429
2426
|
var isEmptyText = (c) => c instanceof TextNode && c.val === "";
|
|
2430
|
-
var isIgnorableXChild = (c) => c instanceof CommentNode ||
|
|
2427
|
+
var isIgnorableXChild = (c) => c instanceof CommentNode || c.isWhiteSpace();
|
|
2431
2428
|
var hasMeaningfulChilds = (childs) => childs.some((c) => !isIgnorableXChild(c));
|
|
2432
2429
|
function trimEdgeWhite(node) {
|
|
2433
|
-
if (!node.isWhiteSpace
|
|
2430
|
+
if (!node.isWhiteSpace()) return false;
|
|
2434
2431
|
node.condenseWhiteSpace();
|
|
2435
2432
|
return true;
|
|
2436
2433
|
}
|
|
@@ -2441,7 +2438,7 @@ function condenseChildsWhites(childs) {
|
|
|
2441
2438
|
if (last > 0 && trimEdgeWhite(childs[last])) emptied = true;
|
|
2442
2439
|
for (let i = 1; i < last; i++) {
|
|
2443
2440
|
const cur = childs[i];
|
|
2444
|
-
if (!(cur.isWhiteSpace
|
|
2441
|
+
if (!(cur.isWhiteSpace() && cur.hasNewLine())) continue;
|
|
2445
2442
|
const bothBlock = isBlockDomNode(childs[i - 1]) && isBlockDomNode(childs[i + 1]);
|
|
2446
2443
|
cur.condenseWhiteSpace(bothBlock ? "" : " ");
|
|
2447
2444
|
if (bothBlock) emptied = true;
|
|
@@ -2449,12 +2446,12 @@ function condenseChildsWhites(childs) {
|
|
|
2449
2446
|
return emptied ? childs.filter((c) => !isEmptyText(c)) : childs;
|
|
2450
2447
|
}
|
|
2451
2448
|
var View = class {
|
|
2452
|
-
constructor(name, rawView = "No View Defined", style = ""
|
|
2449
|
+
constructor(name, rawView = "No View Defined", style = "") {
|
|
2453
2450
|
this.name = name;
|
|
2454
|
-
this.anode = anode;
|
|
2455
|
-
this.style = style;
|
|
2456
|
-
this.ctx = ctx;
|
|
2457
2451
|
this.rawView = rawView;
|
|
2452
|
+
this.style = style;
|
|
2453
|
+
this.anode = null;
|
|
2454
|
+
this.ctx = null;
|
|
2458
2455
|
}
|
|
2459
2456
|
compile(ctx, scope, cid) {
|
|
2460
2457
|
this.ctx = ctx;
|
|
@@ -2462,7 +2459,7 @@ var View = class {
|
|
|
2462
2459
|
this.anode.setDataAttr("data-cid", cid);
|
|
2463
2460
|
this.anode.setDataAttr("data-vid", this.name);
|
|
2464
2461
|
this.ctx.compile(scope);
|
|
2465
|
-
|
|
2462
|
+
this.anode = optimizeNode(this.anode);
|
|
2466
2463
|
}
|
|
2467
2464
|
render(stack, rx) {
|
|
2468
2465
|
if (this.anode === null) {
|
|
@@ -2487,7 +2484,7 @@ var NodeEvents = class {
|
|
|
2487
2484
|
getHandlersFor(eventName) {
|
|
2488
2485
|
let r = null;
|
|
2489
2486
|
for (const handler of this.handlers)
|
|
2490
|
-
if (handler.
|
|
2487
|
+
if (handler.name === eventName) {
|
|
2491
2488
|
r ??= [];
|
|
2492
2489
|
r.push(handler);
|
|
2493
2490
|
}
|
|
@@ -2501,9 +2498,6 @@ var NodeEvent = class {
|
|
|
2501
2498
|
this.modifierWrapper = compileModifiers(name, modifiers);
|
|
2502
2499
|
this.modifiers = modifiers;
|
|
2503
2500
|
}
|
|
2504
|
-
handlesEventName(name) {
|
|
2505
|
-
return this.name === name;
|
|
2506
|
-
}
|
|
2507
2501
|
getHandlerAndArgs(stack, event) {
|
|
2508
2502
|
const r = this.handlerCall.getHandlerAndArgs(stack, event);
|
|
2509
2503
|
r[0] = this.modifierWrapper(r[0], event);
|
|
@@ -2555,92 +2549,209 @@ function compileModifiers(eventName, names) {
|
|
|
2555
2549
|
};
|
|
2556
2550
|
}
|
|
2557
2551
|
|
|
2558
|
-
// src/
|
|
2559
|
-
var
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2552
|
+
// src/stack.js
|
|
2553
|
+
var STOP = /* @__PURE__ */ Symbol("STOP");
|
|
2554
|
+
var NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
2555
|
+
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
2556
|
+
var isTypeName = (s) => {
|
|
2557
|
+
const c = s.charCodeAt(0);
|
|
2558
|
+
return c >= 65 && c <= 90;
|
|
2559
|
+
};
|
|
2560
|
+
function lookup(chain, name, dv = null) {
|
|
2561
|
+
let n = chain;
|
|
2562
|
+
while (n !== null) {
|
|
2563
|
+
const r = n[0].lookup(name);
|
|
2564
|
+
if (r === STOP) return dv;
|
|
2565
|
+
if (r !== NEXT) return r;
|
|
2566
|
+
n = n[1];
|
|
2568
2567
|
}
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
nodes,
|
|
2577
|
-
events,
|
|
2578
|
-
macroNodes,
|
|
2579
|
-
frame,
|
|
2580
|
-
this
|
|
2581
|
-
);
|
|
2582
|
-
v.classes = this.classes;
|
|
2583
|
-
return v;
|
|
2568
|
+
return dv;
|
|
2569
|
+
}
|
|
2570
|
+
var BindFrame = class {
|
|
2571
|
+
constructor(it, binds, isFrame) {
|
|
2572
|
+
this.it = it;
|
|
2573
|
+
this.binds = binds;
|
|
2574
|
+
this.isFrame = isFrame;
|
|
2584
2575
|
}
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
if (attr.name !== "class") {
|
|
2589
|
-
continue;
|
|
2590
|
-
}
|
|
2591
|
-
const { val, thenVal, elseVal } = attr;
|
|
2592
|
-
if (thenVal !== void 0) {
|
|
2593
|
-
this._maybeAddVal(thenVal);
|
|
2594
|
-
this._maybeAddVal(elseVal);
|
|
2595
|
-
} else {
|
|
2596
|
-
this._maybeAddVal(val);
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
} else {
|
|
2600
|
-
const attr = attrs.items.class;
|
|
2601
|
-
if (attr) {
|
|
2602
|
-
this._addClasses(attr);
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2576
|
+
lookup(name) {
|
|
2577
|
+
const v = this.binds[name];
|
|
2578
|
+
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
2605
2579
|
}
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2580
|
+
};
|
|
2581
|
+
var DynFrame = class {
|
|
2582
|
+
constructor(binds, types) {
|
|
2583
|
+
this.binds = binds;
|
|
2584
|
+
this.types = types;
|
|
2610
2585
|
}
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
if (val instanceof ConstVal && val.val !== "") {
|
|
2615
|
-
this._addClasses(val.val);
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
return true;
|
|
2619
|
-
}
|
|
2620
|
-
return false;
|
|
2586
|
+
lookup(name) {
|
|
2587
|
+
const v = (isTypeName(name) ? this.types : this.binds)[name];
|
|
2588
|
+
return v === void 0 ? NEXT : v;
|
|
2621
2589
|
}
|
|
2622
2590
|
};
|
|
2623
|
-
function
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
classes.add(name);
|
|
2630
|
-
}
|
|
2631
|
-
}
|
|
2591
|
+
function computeViewsId(views) {
|
|
2592
|
+
let s = "";
|
|
2593
|
+
let n = views;
|
|
2594
|
+
while (n !== null) {
|
|
2595
|
+
s += n[0];
|
|
2596
|
+
n = n[1];
|
|
2632
2597
|
}
|
|
2633
|
-
return
|
|
2598
|
+
return s === "main" ? "" : s;
|
|
2634
2599
|
}
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2600
|
+
var Stack = class _Stack {
|
|
2601
|
+
constructor(fields) {
|
|
2602
|
+
Object.assign(this, fields);
|
|
2603
|
+
}
|
|
2604
|
+
_with(patch) {
|
|
2605
|
+
return new _Stack({ ...this, ...patch });
|
|
2606
|
+
}
|
|
2607
|
+
// Evaluate every provide the entered component publishes and push them as one
|
|
2608
|
+
// dynBinds frame, keyed by NAME. A value is published together with the absolute
|
|
2609
|
+
// path it lives at: the same declaration is read as `*name` AND resumed at by
|
|
2610
|
+
// `<x render="*name">`, so a consumer needs both halves. Types go in the same
|
|
2611
|
+
// frame's other map. No-op with no provides.
|
|
2612
|
+
_pushProvides() {
|
|
2613
|
+
const comp = this.comps.getCompFor(this.it);
|
|
2614
|
+
if (comp == null) return this;
|
|
2615
|
+
const { provide, provideType } = comp;
|
|
2616
|
+
const binds = {};
|
|
2617
|
+
const types = {};
|
|
2618
|
+
let has = false;
|
|
2619
|
+
const base = this._publishBase();
|
|
2620
|
+
for (const k in provide) {
|
|
2621
|
+
const step = provide[k].toPathItem?.() ?? null;
|
|
2622
|
+
if (step === null) continue;
|
|
2623
|
+
const value = provide[k].eval(this);
|
|
2624
|
+
binds[k] = { value, path: base === null ? null : base.concat([step]) };
|
|
2625
|
+
has = true;
|
|
2626
|
+
}
|
|
2627
|
+
for (const k in provideType) {
|
|
2628
|
+
types[k] = provideType[k];
|
|
2629
|
+
has = true;
|
|
2630
|
+
}
|
|
2631
|
+
if (!has) return this;
|
|
2632
|
+
return this._with({ dynBinds: [new DynFrame(binds, types), this.dynBinds] });
|
|
2633
|
+
}
|
|
2634
|
+
// The absolute address of the component being entered, or null when this
|
|
2635
|
+
// position cannot be written down as one. Frame-only steps carry bindings and
|
|
2636
|
+
// address nothing, so they are compacted away first; what is left is checked
|
|
2637
|
+
// against the value actually being rendered, because a scope CAN move the
|
|
2638
|
+
// render position without contributing an addressing step (a plain `@each`
|
|
2639
|
+
// body re-binds `it` to the item while its rebuild step is an identity).
|
|
2640
|
+
//
|
|
2641
|
+
// A null base still publishes the VALUE — `*name` reads it fine — but there is
|
|
2642
|
+
// nowhere to resume, so `<x render="*name">` renders nothing rather than
|
|
2643
|
+
// editing whatever happens to live at the address we guessed.
|
|
2644
|
+
_publishBase() {
|
|
2645
|
+
const base = this.renderPath.toTransactionPath().compact();
|
|
2646
|
+
return base.lookup(this.root, NOT_FOUND) === this.it ? base : null;
|
|
2647
|
+
}
|
|
2648
|
+
static root(comps, it, ctx = null) {
|
|
2649
|
+
return new _Stack({
|
|
2650
|
+
comps,
|
|
2651
|
+
root: it,
|
|
2652
|
+
it,
|
|
2653
|
+
binds: [new BindFrame(it, {}, true), null],
|
|
2654
|
+
dynBinds: [new DynFrame({}, {}), null],
|
|
2655
|
+
views: ["main", null],
|
|
2656
|
+
viewsId: "",
|
|
2657
|
+
renderPath: new DispatchPath(),
|
|
2658
|
+
pendingFrame: false,
|
|
2659
|
+
ctx
|
|
2660
|
+
})._pushProvides();
|
|
2661
|
+
}
|
|
2662
|
+
// `renderPath` defaults to this stack's own: an ordinary scope does not move.
|
|
2663
|
+
// `pendingFrame` clears on a component frame (which emits the base) and is
|
|
2664
|
+
// inherited by transparent scopes, which have to carry it to the next boundary.
|
|
2665
|
+
enter(it, bindings = {}, isFrame = true, renderPath = this.renderPath, pendingFrame = null) {
|
|
2666
|
+
const stack = this._with({
|
|
2667
|
+
it,
|
|
2668
|
+
binds: [new BindFrame(it, bindings, isFrame), this.binds],
|
|
2669
|
+
renderPath,
|
|
2670
|
+
pendingFrame: pendingFrame ?? (isFrame ? false : this.pendingFrame)
|
|
2671
|
+
});
|
|
2672
|
+
return isFrame ? stack._pushProvides() : stack;
|
|
2673
|
+
}
|
|
2674
|
+
pushViewName(name) {
|
|
2675
|
+
const views = [name, this.views];
|
|
2676
|
+
return this._with({ views, viewsId: computeViewsId(views) });
|
|
2677
|
+
}
|
|
2678
|
+
// Published types are stable per scope and would only churn the render cache, so
|
|
2679
|
+
// the cache key covers values alone.
|
|
2680
|
+
_pushDynBindValuesToArray(arr, comp) {
|
|
2681
|
+
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
2682
|
+
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
2683
|
+
}
|
|
2684
|
+
// `*name`: the nearest binding above (including this component's own provides,
|
|
2685
|
+
// pushed on entering it), else a path registered in the component's lexical
|
|
2686
|
+
// scope, else this component's declared default, else null.
|
|
2687
|
+
//
|
|
2688
|
+
// One chain walk and no producer resolution: a lookup names what it WANTS, so the
|
|
2689
|
+
// frame it wants is keyed by that name. The default belongs to the CONSUMER's
|
|
2690
|
+
// declaration and is evaluated against the consumer's stack, which is why it is
|
|
2691
|
+
// consulted only after the whole chain has missed.
|
|
2692
|
+
lookupDynamicLocated(name) {
|
|
2693
|
+
if (isTypeName(name)) return null;
|
|
2694
|
+
const v = lookup(this.dynBinds, name);
|
|
2695
|
+
if (v != null) return v;
|
|
2696
|
+
const comp = this.comps.getCompFor(this.it);
|
|
2697
|
+
if (comp == null) return null;
|
|
2698
|
+
const path2 = comp.scope?.lookupPath?.(name) ?? null;
|
|
2699
|
+
if (path2 !== null) {
|
|
2700
|
+
const value2 = path2.lookup(this.root, NOT_FOUND);
|
|
2701
|
+
if (value2 !== NOT_FOUND) return { value: value2, path: path2 };
|
|
2702
|
+
}
|
|
2703
|
+
const dval = comp.lookup[name] ?? null;
|
|
2704
|
+
if (dval === null) return null;
|
|
2705
|
+
const step = dval.toPathItem?.() ?? null;
|
|
2706
|
+
const value = dval.eval(this);
|
|
2707
|
+
return step === null ? { value, path: null } : { value, path: this.renderPath.toTransactionPath().concat([step]) };
|
|
2708
|
+
}
|
|
2709
|
+
lookupDynamic(name) {
|
|
2710
|
+
if (isTypeName(name)) return lookup(this.dynBinds, name);
|
|
2711
|
+
return this.lookupDynamicLocated(name)?.value ?? null;
|
|
2712
|
+
}
|
|
2713
|
+
lookupBind(name) {
|
|
2714
|
+
return lookup(this.binds, name);
|
|
2715
|
+
}
|
|
2716
|
+
lookupFieldRaw(name) {
|
|
2717
|
+
return this.it[name] ?? null;
|
|
2718
|
+
}
|
|
2719
|
+
lookupMethod(name) {
|
|
2720
|
+
const fn = this.it[name];
|
|
2721
|
+
return fn instanceof Function ? fn.call(this.it) : null;
|
|
2722
|
+
}
|
|
2723
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
2724
|
+
// `e.<member>` handler args. Null outside a live event transaction (`ctx` is
|
|
2725
|
+
// then a send/intent transaction, which carries no `e`).
|
|
2726
|
+
lookupEvent() {
|
|
2727
|
+
return this.ctx?.e ?? null;
|
|
2728
|
+
}
|
|
2729
|
+
lookupDragInfo() {
|
|
2730
|
+
return this.ctx?.dragInfo ?? null;
|
|
2731
|
+
}
|
|
2732
|
+
getHandlerFor(name, key) {
|
|
2733
|
+
return this.comps.getHandlerFor(this.it, name, key);
|
|
2734
|
+
}
|
|
2735
|
+
lookupBestView(views, defaultViewName) {
|
|
2736
|
+
let n = this.views;
|
|
2737
|
+
while (n !== null) {
|
|
2738
|
+
const view = views[n[0]];
|
|
2739
|
+
if (view !== void 0) return view;
|
|
2740
|
+
n = n[1];
|
|
2741
|
+
}
|
|
2742
|
+
return views[defaultViewName];
|
|
2743
|
+
}
|
|
2744
|
+
};
|
|
2745
|
+
var NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
2746
|
+
|
|
2747
|
+
// src/components.js
|
|
2748
|
+
var COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
2749
|
+
var Components = class {
|
|
2750
|
+
constructor() {
|
|
2751
|
+
this.byId = /* @__PURE__ */ new Map();
|
|
2641
2752
|
}
|
|
2642
2753
|
registerComponent(Comp) {
|
|
2643
|
-
this.byId.set(Comp
|
|
2754
|
+
this.byId.set(Comp.id, Comp);
|
|
2644
2755
|
}
|
|
2645
2756
|
getComponentForId(id) {
|
|
2646
2757
|
return this.byId.get(id) ?? null;
|
|
@@ -2660,7 +2771,7 @@ var Components = class {
|
|
|
2660
2771
|
}
|
|
2661
2772
|
compileStyles() {
|
|
2662
2773
|
const styles = [];
|
|
2663
|
-
for (const Comp of this.byId.values()) styles.push(Comp
|
|
2774
|
+
for (const Comp of this.byId.values()) styles.push(Comp.compileStyle());
|
|
2664
2775
|
return styles.join("\n");
|
|
2665
2776
|
}
|
|
2666
2777
|
};
|
|
@@ -2671,15 +2782,17 @@ var ComponentStack = class _ComponentStack {
|
|
|
2671
2782
|
this.byName = {};
|
|
2672
2783
|
this.intentsByName = {};
|
|
2673
2784
|
this.macros = {};
|
|
2785
|
+
this.paths = {};
|
|
2674
2786
|
}
|
|
2675
2787
|
enter() {
|
|
2676
2788
|
return new _ComponentStack(this.comps, this);
|
|
2677
2789
|
}
|
|
2678
2790
|
registerComponents(comps, opts) {
|
|
2679
|
-
const { aliases = {} } = opts ?? {};
|
|
2791
|
+
const { aliases = {}, paths } = opts ?? {};
|
|
2792
|
+
if (paths) this.registerPaths(paths);
|
|
2680
2793
|
for (let i = 0; i < comps.length; i++) {
|
|
2681
2794
|
const Comp = comps[i];
|
|
2682
|
-
Comp
|
|
2795
|
+
Comp.scope = this.enter();
|
|
2683
2796
|
this.comps.registerComponent(Comp);
|
|
2684
2797
|
this.byName[Comp.name] = Comp;
|
|
2685
2798
|
}
|
|
@@ -2690,6 +2803,27 @@ var ComponentStack = class _ComponentStack {
|
|
|
2690
2803
|
else console.warn("alias", alias, "to inexistent component", aliases[alias]);
|
|
2691
2804
|
}
|
|
2692
2805
|
}
|
|
2806
|
+
// Register lowercase names as absolute paths from the app state root. A
|
|
2807
|
+
// descendant that declares one in its `lookup` reads and renders `*name` without
|
|
2808
|
+
// anything above it publishing one — which is what makes a session, a theme or a
|
|
2809
|
+
// host-owned value available in its natural registration scope, instead of forcing
|
|
2810
|
+
// an application root whose only job is to `provide` it. Register on a nested
|
|
2811
|
+
// scope to narrow a name; nearest registration wins.
|
|
2812
|
+
//
|
|
2813
|
+
// Uppercase names are ignored: a component TYPE is what `lookupComponent` already
|
|
2814
|
+
// answers, and a type has no path.
|
|
2815
|
+
registerPaths(paths) {
|
|
2816
|
+
for (const name in paths) {
|
|
2817
|
+
if (isTypeName(name)) {
|
|
2818
|
+
console.warn("registerPaths: a type name has no path", name);
|
|
2819
|
+
continue;
|
|
2820
|
+
}
|
|
2821
|
+
this.paths[name] = paths[name].toPath();
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
lookupPath(name) {
|
|
2825
|
+
return this.paths[name] ?? this.parent?.lookupPath(name) ?? null;
|
|
2826
|
+
}
|
|
2693
2827
|
registerMacros(macros) {
|
|
2694
2828
|
for (const key in macros) {
|
|
2695
2829
|
const lower = key.toLowerCase();
|
|
@@ -2721,97 +2855,82 @@ var ComponentStack = class _ComponentStack {
|
|
|
2721
2855
|
lookupComponent(name) {
|
|
2722
2856
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
2723
2857
|
}
|
|
2724
|
-
//
|
|
2725
|
-
// names
|
|
2726
|
-
//
|
|
2727
|
-
//
|
|
2728
|
-
//
|
|
2729
|
-
|
|
2858
|
+
// Whether anything in this scope chain provides `name`. Existence only: a lookup
|
|
2859
|
+
// names what it WANTS and takes whoever is nearest above it at render time, so
|
|
2860
|
+
// there is no producer to identify — several components may publish one name and
|
|
2861
|
+
// the live render ancestry decides. Used by the linter to tell a lookup that can
|
|
2862
|
+
// be satisfied from one that never will be.
|
|
2863
|
+
hasProvider(name) {
|
|
2730
2864
|
for (const compName in this.byName) {
|
|
2731
|
-
|
|
2732
|
-
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
2865
|
+
if (this.byName[compName].provide?.[name] !== void 0) return true;
|
|
2733
2866
|
}
|
|
2734
|
-
return this.parent?.
|
|
2867
|
+
return this.parent?.hasProvider(name) ?? false;
|
|
2735
2868
|
}
|
|
2736
2869
|
lookupMacro(name) {
|
|
2737
2870
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
2738
2871
|
}
|
|
2739
2872
|
};
|
|
2740
|
-
var ProvideInfo = class {
|
|
2741
|
-
constructor(val) {
|
|
2742
|
-
this.val = val;
|
|
2743
|
-
}
|
|
2744
|
-
};
|
|
2745
|
-
var LookupInfo = class {
|
|
2746
|
-
constructor(val) {
|
|
2747
|
-
this.val = val;
|
|
2748
|
-
}
|
|
2749
|
-
};
|
|
2750
2873
|
var isString = (v) => typeof v === "string";
|
|
2751
|
-
var isTypeName = (s) => {
|
|
2752
|
-
const c = s.charCodeAt(0);
|
|
2753
|
-
return c >= 65 && c <= 90;
|
|
2754
|
-
};
|
|
2755
2874
|
var _rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
2756
2875
|
var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
2757
2876
|
var _compId = 0;
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2877
|
+
function initComponent(Class, o) {
|
|
2878
|
+
Class[COMPONENT] = Class;
|
|
2879
|
+
Class.id = _compId++;
|
|
2880
|
+
Class.views = { main: new View("main", o.view, o.style) };
|
|
2881
|
+
Class.commonStyle = o.commonStyle ?? "";
|
|
2882
|
+
Class.globalStyle = o.globalStyle ?? "";
|
|
2883
|
+
Class.receive = o.receive ?? {};
|
|
2884
|
+
Class.intent = o.intent ?? {};
|
|
2885
|
+
Class.alter = o.alter ?? {};
|
|
2886
|
+
for (const name in o.views ?? {}) {
|
|
2887
|
+
const v = o.views[name];
|
|
2888
|
+
const { view, style } = isString(v) ? { view: v } : v;
|
|
2889
|
+
Class.views[name] = new View(name, view, style);
|
|
2890
|
+
}
|
|
2891
|
+
Class._rawProvide = o.provide ?? {};
|
|
2892
|
+
Class._rawLookup = o.lookup ?? [];
|
|
2893
|
+
Class.provide = {};
|
|
2894
|
+
Class.provideType = {};
|
|
2895
|
+
Class.lookup = {};
|
|
2896
|
+
Class.scope = null;
|
|
2897
|
+
Class.spec = o;
|
|
2898
|
+
Class.extra = {};
|
|
2899
|
+
for (const key of Object.keys(o)) if (!KNOWN_SPEC_KEYS.has(key)) Class.extra[key] = o[key];
|
|
2900
|
+
return Object.assign(Class, COMPONENT_METHODS);
|
|
2901
|
+
}
|
|
2902
|
+
var COMPONENT_METHODS = {
|
|
2784
2903
|
compile(ParseContext2) {
|
|
2785
2904
|
for (const name in this.views)
|
|
2786
2905
|
this.views[name].compile(new ParseContext2(), this.scope, this.id);
|
|
2787
2906
|
const ctx = this.views.main.ctx;
|
|
2788
2907
|
for (const key in this._rawProvide) {
|
|
2789
2908
|
if (isTypeName(key)) {
|
|
2790
|
-
if (this._rawProvide[key] === "self") this.provideType[key] = this
|
|
2909
|
+
if (this._rawProvide[key] === "self") this.provideType[key] = this;
|
|
2791
2910
|
continue;
|
|
2792
2911
|
}
|
|
2793
2912
|
const val = parseProvide(this._rawProvide[key], ctx);
|
|
2794
|
-
if (val) this.provide[key] =
|
|
2913
|
+
if (val) this.provide[key] = val;
|
|
2795
2914
|
}
|
|
2796
2915
|
for (const entry of this._rawLookup) {
|
|
2797
2916
|
const name = isString(entry) ? entry : isString(entry?.name) ? entry.name : null;
|
|
2798
2917
|
if (name === null) continue;
|
|
2799
2918
|
const defStr = isString(entry?.default) ? entry.default : null;
|
|
2800
|
-
this.lookup[name] =
|
|
2919
|
+
this.lookup[name] = defStr === null ? null : parseField(defStr, ctx);
|
|
2801
2920
|
}
|
|
2802
2921
|
for (const key in this.lookup)
|
|
2803
2922
|
if (this.provide[key] !== void 0)
|
|
2804
2923
|
console.warn("name declared in both provide and lookup", this.name, key);
|
|
2805
|
-
}
|
|
2924
|
+
},
|
|
2806
2925
|
getView(name) {
|
|
2807
2926
|
return this.views[name] ?? this.views.main;
|
|
2808
|
-
}
|
|
2809
|
-
getEventForId(id,
|
|
2810
|
-
return this.getView(
|
|
2811
|
-
}
|
|
2812
|
-
getNodeForId(id,
|
|
2813
|
-
return this.getView(
|
|
2814
|
-
}
|
|
2927
|
+
},
|
|
2928
|
+
getEventForId(id, viewName) {
|
|
2929
|
+
return this.getView(viewName).ctx.getEventForId(id);
|
|
2930
|
+
},
|
|
2931
|
+
getNodeForId(id, viewName) {
|
|
2932
|
+
return this.getView(viewName).ctx.getNodeForId(id);
|
|
2933
|
+
},
|
|
2815
2934
|
compileStyle() {
|
|
2816
2935
|
const { id, commonStyle, globalStyle, views } = this;
|
|
2817
2936
|
const styles = commonStyle ? [`[data-cid="${id}"]{${commonStyle}}`] : [];
|
|
@@ -2824,6 +2943,68 @@ var Component = class {
|
|
|
2824
2943
|
}
|
|
2825
2944
|
};
|
|
2826
2945
|
|
|
2946
|
+
// src/util/parsectx.js
|
|
2947
|
+
var ParseCtxClassSetCollector = class extends ParseContext {
|
|
2948
|
+
constructor(...args) {
|
|
2949
|
+
super(...args);
|
|
2950
|
+
this.classes = /* @__PURE__ */ new Set();
|
|
2951
|
+
}
|
|
2952
|
+
_addClasses(s) {
|
|
2953
|
+
for (const v of s.split(/\s+/)) {
|
|
2954
|
+
this.classes.add(v);
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
onAttributes(attrs, _wrapperAttrs, _textChild, _isMacroCall, _tag) {
|
|
2958
|
+
if (Array.isArray(attrs.items)) {
|
|
2959
|
+
for (const attr of attrs.items) {
|
|
2960
|
+
if (attr.name !== "class") {
|
|
2961
|
+
continue;
|
|
2962
|
+
}
|
|
2963
|
+
const { val, thenVal, elseVal } = attr;
|
|
2964
|
+
if (thenVal !== void 0) {
|
|
2965
|
+
this._maybeAddVal(thenVal);
|
|
2966
|
+
this._maybeAddVal(elseVal);
|
|
2967
|
+
} else {
|
|
2968
|
+
this._maybeAddVal(val);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
} else {
|
|
2972
|
+
const attr = attrs.items.class;
|
|
2973
|
+
if (attr) {
|
|
2974
|
+
this._addClasses(attr);
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
_maybeAddVal(value) {
|
|
2979
|
+
if (!this._maybeAddStrTpl(value) && typeof value?.val === "string") {
|
|
2980
|
+
this._addClasses(value.val);
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
_maybeAddStrTpl(value) {
|
|
2984
|
+
if (value?.vals !== void 0) {
|
|
2985
|
+
for (const val of value.vals) {
|
|
2986
|
+
if (val instanceof ConstVal && val.val !== "") {
|
|
2987
|
+
this._addClasses(val.val);
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
return true;
|
|
2991
|
+
}
|
|
2992
|
+
return false;
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
function collectAppClassesInSet(app) {
|
|
2996
|
+
const classes = /* @__PURE__ */ new Set();
|
|
2997
|
+
for (const Comp of app.comps.byId.values()) {
|
|
2998
|
+
for (const key in Comp.views) {
|
|
2999
|
+
const view = Comp.views[key];
|
|
3000
|
+
for (const name of view.ctx.classes) {
|
|
3001
|
+
classes.add(name);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
return classes;
|
|
3006
|
+
}
|
|
3007
|
+
|
|
2827
3008
|
// tools/core/html-tokenizer.js
|
|
2828
3009
|
var CharCodes = {
|
|
2829
3010
|
Tab: 9,
|
|
@@ -5115,7 +5296,6 @@ var DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED";
|
|
|
5115
5296
|
var DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED";
|
|
5116
5297
|
var PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE";
|
|
5117
5298
|
var PROVIDE_TYPE_BAD_SHAPE = "PROVIDE_TYPE_BAD_SHAPE";
|
|
5118
|
-
var PROVIDE_NAME_COLLISION = "PROVIDE_NAME_COLLISION";
|
|
5119
5299
|
var LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE";
|
|
5120
5300
|
var LOOKUP_NO_PROVIDER = "LOOKUP_NO_PROVIDER";
|
|
5121
5301
|
var RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP";
|
|
@@ -5132,6 +5312,7 @@ var IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET";
|
|
|
5132
5312
|
var UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME";
|
|
5133
5313
|
var UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG";
|
|
5134
5314
|
var UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE";
|
|
5315
|
+
var ORPHAN_DIRECTIVE = "ORPHAN_DIRECTIVE";
|
|
5135
5316
|
var UNKNOWN_X_OP = "UNKNOWN_X_OP";
|
|
5136
5317
|
var UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR";
|
|
5137
5318
|
var X_OP_IGNORES_CHILDREN = "X_OP_IGNORES_CHILDREN";
|
|
@@ -5166,6 +5347,7 @@ var LEVEL_ERROR2 = "error";
|
|
|
5166
5347
|
var LEVEL_HINT = "hint";
|
|
5167
5348
|
var PARSE_ISSUES = {
|
|
5168
5349
|
"unknown-directive": { id: UNKNOWN_DIRECTIVE, candidates: KNOWN_DIRECTIVE_NAMES },
|
|
5350
|
+
"orphan-directive": { id: ORPHAN_DIRECTIVE },
|
|
5169
5351
|
"unknown-x-op": { id: UNKNOWN_X_OP, candidates: X_KNOWN_OP_NAMES, atPrefix: X_KNOWN_OP_NAMES },
|
|
5170
5352
|
"unknown-x-attr": {
|
|
5171
5353
|
id: UNKNOWN_X_ATTR,
|
|
@@ -5238,7 +5420,6 @@ function checkComponent(Comp, lx = new LintContext(), { wellKnownExtras = EMPTY_
|
|
|
5238
5420
|
checkFieldMethodNameCollisions(lx, Comp);
|
|
5239
5421
|
checkProvidesAreAddressable(lx, Comp);
|
|
5240
5422
|
checkProvidedTypes(lx, Comp);
|
|
5241
|
-
checkProvideNameCollisions(lx, Comp);
|
|
5242
5423
|
checkLookupShapes(lx, Comp);
|
|
5243
5424
|
checkLookupTypesResolve(lx, Comp);
|
|
5244
5425
|
checkLookupsHaveProviders(lx, Comp);
|
|
@@ -5922,19 +6103,6 @@ function checkProvidedTypes(lx, Comp) {
|
|
|
5922
6103
|
if (raw !== "self") lx.error(PROVIDE_TYPE_BAD_SHAPE, { name, value: raw });
|
|
5923
6104
|
}
|
|
5924
6105
|
}
|
|
5925
|
-
function checkProvideNameCollisions(lx, Comp) {
|
|
5926
|
-
const scope = Comp.scope;
|
|
5927
|
-
if (!scope) return;
|
|
5928
|
-
for (const name in Comp.provide) {
|
|
5929
|
-
for (let s = scope; s; s = s.parent) {
|
|
5930
|
-
for (const otherName in s.byName) {
|
|
5931
|
-
const Other = s.byName[otherName];
|
|
5932
|
-
if (Other !== Comp && Other.provide?.[name] !== void 0)
|
|
5933
|
-
lx.error(PROVIDE_NAME_COLLISION, { name, other: Other.name });
|
|
5934
|
-
}
|
|
5935
|
-
}
|
|
5936
|
-
}
|
|
5937
|
-
}
|
|
5938
6106
|
var KNOWN_LOOKUP_KEYS = /* @__PURE__ */ new Set(["name", "default"]);
|
|
5939
6107
|
function checkLookupShapes(lx, Comp) {
|
|
5940
6108
|
const raw = Comp._rawLookup;
|
|
@@ -5976,8 +6144,8 @@ function checkLookupsHaveProviders(lx, Comp) {
|
|
|
5976
6144
|
if (!scope) return;
|
|
5977
6145
|
for (const name in Comp.lookup) {
|
|
5978
6146
|
if (isTypeName2(name)) continue;
|
|
5979
|
-
if (scope.
|
|
5980
|
-
const info = { name, hasDefault: Comp.lookup[name]
|
|
6147
|
+
if (scope.hasProvider?.(name) || scope.lookupPath?.(name)) continue;
|
|
6148
|
+
const info = { name, hasDefault: Comp.lookup[name] != null };
|
|
5981
6149
|
if (info.hasDefault) lx.hint(LOOKUP_NO_PROVIDER, info);
|
|
5982
6150
|
else lx.error(LOOKUP_NO_PROVIDER, info);
|
|
5983
6151
|
}
|
|
@@ -6025,13 +6193,14 @@ var LintContext = class {
|
|
|
6025
6193
|
this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
|
|
6026
6194
|
}
|
|
6027
6195
|
};
|
|
6028
|
-
var LintParseContext = class extends
|
|
6029
|
-
constructor(document2
|
|
6030
|
-
super(document2
|
|
6196
|
+
var LintParseContext = class extends ParseCtxClassSetCollector {
|
|
6197
|
+
constructor(document2) {
|
|
6198
|
+
super(document2);
|
|
6031
6199
|
this.attrs = [];
|
|
6032
6200
|
this.parseIssues = [];
|
|
6033
6201
|
}
|
|
6034
6202
|
onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false, tag = null) {
|
|
6203
|
+
super.onAttributes(attrs, wrapperAttrs, textChild, isMacroCall, tag);
|
|
6035
6204
|
this.attrs.push({ attrs, wrapperAttrs, textChild, isMacroCall, tag });
|
|
6036
6205
|
}
|
|
6037
6206
|
onParseIssue(kind, info) {
|
|
@@ -6068,14 +6237,36 @@ function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
|
6068
6237
|
|
|
6069
6238
|
// src/oo.js
|
|
6070
6239
|
var BAD_VALUE2 = /* @__PURE__ */ Symbol("BadValue");
|
|
6071
|
-
var
|
|
6240
|
+
var COERCE_NONE = (_v) => null;
|
|
6241
|
+
var COERCE_MAP = (v) => {
|
|
6242
|
+
if (v instanceof Map) return new Map(v);
|
|
6243
|
+
if (Array.isArray(v) || isPlainObject(v))
|
|
6244
|
+
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
6245
|
+
return null;
|
|
6246
|
+
};
|
|
6247
|
+
var FIELD_TYPES = {
|
|
6248
|
+
any: [(_v) => true, COERCE_NONE, () => null],
|
|
6249
|
+
text: [(v) => typeof v === "string", (v) => v?.toString?.() ?? "", () => ""],
|
|
6250
|
+
int: [Number.isInteger, (v) => Number.isFinite(v) ? Math.trunc(v) : null, () => 0],
|
|
6251
|
+
float: [Number.isFinite, COERCE_NONE, () => 0],
|
|
6252
|
+
bool: [(v) => typeof v === "boolean", (v) => !!v, () => false],
|
|
6253
|
+
list: [Array.isArray, (v) => Array.isArray(v) ? [...v] : null, () => []],
|
|
6254
|
+
object: [isPlainObject, (v) => isPlainObject(v) ? { ...v } : null, () => ({})],
|
|
6255
|
+
map: [(v) => v instanceof Map, COERCE_MAP, () => /* @__PURE__ */ new Map()],
|
|
6256
|
+
set: [
|
|
6257
|
+
(v) => v instanceof Set,
|
|
6258
|
+
(v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null,
|
|
6259
|
+
() => /* @__PURE__ */ new Set()
|
|
6260
|
+
]
|
|
6261
|
+
};
|
|
6072
6262
|
var Field = class {
|
|
6073
|
-
|
|
6263
|
+
// `type` names an entry of FIELD_TYPES; `defaultValue` falls back to the type's own.
|
|
6264
|
+
constructor(type, name, defaultValue, [typeCheck, coercer, makeDefault] = FIELD_TYPES[type]) {
|
|
6074
6265
|
this.type = type;
|
|
6075
6266
|
this.name = name;
|
|
6076
6267
|
this.typeCheck = typeCheck;
|
|
6077
6268
|
this.coercer = coercer;
|
|
6078
|
-
this.defaultValue = defaultValue;
|
|
6269
|
+
this.defaultValue = defaultValue === void 0 ? makeDefault() : defaultValue;
|
|
6079
6270
|
}
|
|
6080
6271
|
isValid(v) {
|
|
6081
6272
|
return this.typeCheck(v);
|
|
@@ -6089,81 +6280,14 @@ var Field = class {
|
|
|
6089
6280
|
return this.coerceOr(v, this.defaultValue);
|
|
6090
6281
|
}
|
|
6091
6282
|
};
|
|
6092
|
-
var
|
|
6093
|
-
var CHECK_TYPE_INT = Number.isInteger;
|
|
6094
|
-
var CHECK_TYPE_FLOAT = Number.isFinite;
|
|
6095
|
-
var CHECK_TYPE_BOOL = (v) => typeof v === "boolean";
|
|
6096
|
-
var CHECK_TYPE_STRING = (v) => typeof v === "string";
|
|
6097
|
-
var CHECK_TYPE_LIST = Array.isArray;
|
|
6098
|
-
var CHECK_TYPE_OBJECT = isPlainObject;
|
|
6099
|
-
var CHECK_TYPE_MAP = (v) => v instanceof Map;
|
|
6100
|
-
var CHECK_TYPE_SET = (v) => v instanceof Set;
|
|
6101
|
-
var COERCE_NONE = (_v) => null;
|
|
6102
|
-
var COERCE_BOOL = (v) => !!v;
|
|
6103
|
-
var COERCE_STRING = (v) => v?.toString?.() ?? "";
|
|
6104
|
-
var COERCE_INT = (v) => Number.isFinite(v) ? Math.trunc(v) : null;
|
|
6105
|
-
var COERCE_LIST = (v) => Array.isArray(v) ? [...v] : null;
|
|
6106
|
-
var COERCE_OBJECT = (v) => isPlainObject(v) ? { ...v } : null;
|
|
6107
|
-
var COERCE_MAP = (v) => {
|
|
6108
|
-
if (v instanceof Map) return new Map(v);
|
|
6109
|
-
if (Array.isArray(v) || isPlainObject(v))
|
|
6110
|
-
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
6111
|
-
return null;
|
|
6112
|
-
};
|
|
6113
|
-
var COERCE_SET = (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null;
|
|
6114
|
-
var FieldBool = class extends Field {
|
|
6115
|
-
constructor(name, defaultValue = false) {
|
|
6116
|
-
super("bool", name, CHECK_TYPE_BOOL, COERCE_BOOL, defaultValue);
|
|
6117
|
-
}
|
|
6118
|
-
};
|
|
6119
|
-
var FieldAny = class extends Field {
|
|
6120
|
-
constructor(name, defaultValue = null) {
|
|
6121
|
-
super("any", name, CHECK_TYPE_ANY, nullCoercer, defaultValue);
|
|
6122
|
-
}
|
|
6123
|
-
};
|
|
6124
|
-
var FieldString = class extends Field {
|
|
6125
|
-
constructor(name, defaultValue = "") {
|
|
6126
|
-
super("text", name, CHECK_TYPE_STRING, COERCE_STRING, defaultValue);
|
|
6127
|
-
}
|
|
6128
|
-
};
|
|
6129
|
-
var FieldInt = class extends Field {
|
|
6130
|
-
constructor(name, defaultValue = 0) {
|
|
6131
|
-
super("int", name, CHECK_TYPE_INT, COERCE_INT, defaultValue);
|
|
6132
|
-
}
|
|
6133
|
-
};
|
|
6134
|
-
var FieldFloat = class extends Field {
|
|
6135
|
-
constructor(name, defaultValue = 0) {
|
|
6136
|
-
super("float", name, CHECK_TYPE_FLOAT, COERCE_NONE, defaultValue);
|
|
6137
|
-
}
|
|
6138
|
-
};
|
|
6139
|
-
var metaOf = (v) => v?.constructor?.[COMPONENT] ?? v?.constructor?.getMetaClass?.();
|
|
6283
|
+
var metaOf = (v) => v?.constructor?.getMetaClass?.();
|
|
6140
6284
|
var getTypeName = (v) => metaOf(v)?.name ?? null;
|
|
6141
6285
|
var FieldComp = class extends Field {
|
|
6142
6286
|
constructor(type, name, args) {
|
|
6143
|
-
super(type, name, (v) => getTypeName(v) === type,
|
|
6287
|
+
super(type, name, null, [(v) => getTypeName(v) === type, COERCE_NONE, () => null]);
|
|
6144
6288
|
this.args = args;
|
|
6145
6289
|
}
|
|
6146
6290
|
};
|
|
6147
|
-
var FieldList = class extends Field {
|
|
6148
|
-
constructor(name, defaultValue = []) {
|
|
6149
|
-
super("list", name, CHECK_TYPE_LIST, COERCE_LIST, defaultValue);
|
|
6150
|
-
}
|
|
6151
|
-
};
|
|
6152
|
-
var FieldObject = class extends Field {
|
|
6153
|
-
constructor(name, defaultValue = {}) {
|
|
6154
|
-
super("object", name, CHECK_TYPE_OBJECT, COERCE_OBJECT, defaultValue);
|
|
6155
|
-
}
|
|
6156
|
-
};
|
|
6157
|
-
var FieldMap = class extends Field {
|
|
6158
|
-
constructor(name, defaultValue = /* @__PURE__ */ new Map()) {
|
|
6159
|
-
super("map", name, CHECK_TYPE_MAP, COERCE_MAP, defaultValue);
|
|
6160
|
-
}
|
|
6161
|
-
};
|
|
6162
|
-
var FieldSet = class extends Field {
|
|
6163
|
-
constructor(name, defaultValue = /* @__PURE__ */ new Set()) {
|
|
6164
|
-
super("set", name, CHECK_TYPE_SET, COERCE_SET, defaultValue);
|
|
6165
|
-
}
|
|
6166
|
-
};
|
|
6167
6291
|
function mkCompField(field, scope, args) {
|
|
6168
6292
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
6169
6293
|
if (Comp === null)
|
|
@@ -6172,112 +6296,66 @@ function mkCompField(field, scope, args) {
|
|
|
6172
6296
|
);
|
|
6173
6297
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
6174
6298
|
}
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
const
|
|
6185
|
-
const
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6299
|
+
function fieldFromSpec(name, value) {
|
|
6300
|
+
const type = typeof value;
|
|
6301
|
+
if (type === "string") return new Field("text", name, value);
|
|
6302
|
+
if (type === "number") return new Field("float", name, value);
|
|
6303
|
+
if (type === "boolean") return new Field("bool", name, value);
|
|
6304
|
+
if (Array.isArray(value)) return new Field("list", name, [...value]);
|
|
6305
|
+
if (value instanceof Set) return new Field("set", name, new Set(value));
|
|
6306
|
+
if (value instanceof Map) return new Field("map", name, new Map(value));
|
|
6307
|
+
if (value?.type && Object.hasOwn(value, "defaultValue")) {
|
|
6308
|
+
const t = value.type in FIELD_TYPES ? value.type : "any";
|
|
6309
|
+
const probe = new Field(t, name);
|
|
6310
|
+
return new Field(t, name, probe.coerceOr(value.defaultValue, probe.defaultValue));
|
|
6311
|
+
}
|
|
6312
|
+
if (value?.component && value?.args !== void 0)
|
|
6313
|
+
return new FieldComp(value.component, name, value.args);
|
|
6314
|
+
if (isPlainObject(value)) return new Field("object", name, { ...value });
|
|
6315
|
+
return new Field("any", name, value);
|
|
6316
|
+
}
|
|
6317
|
+
function classFromData(name, { fields: spec = {}, methods = {}, statics = {} }) {
|
|
6318
|
+
const fields = {};
|
|
6319
|
+
for (const key in spec) fields[key] = fieldFromSpec(key, spec[key]);
|
|
6320
|
+
const defaults = Object.fromEntries(
|
|
6321
|
+
Object.entries(fields).map(([key, field]) => [key, field.defaultValue])
|
|
6322
|
+
);
|
|
6323
|
+
const Class = {
|
|
6324
|
+
[name]: class {
|
|
6325
|
+
constructor(values = {}) {
|
|
6326
|
+
Object.assign(this, defaults, values);
|
|
6193
6327
|
}
|
|
6194
|
-
}[name];
|
|
6195
|
-
Class[immer_exports.immerable] = true;
|
|
6196
|
-
Object.assign(Class.prototype, _methods);
|
|
6197
|
-
const metaClass = { fields, name, methods: _methods };
|
|
6198
|
-
Object.assign(
|
|
6199
|
-
Class,
|
|
6200
|
-
{
|
|
6201
|
-
getMetaClass: () => metaClass,
|
|
6202
|
-
make(inArgs = {}, opts = {}) {
|
|
6203
|
-
const args = {};
|
|
6204
|
-
const scope = opts.scope ?? this[COMPONENT]?.scope ?? this.scope;
|
|
6205
|
-
for (const key in inArgs) {
|
|
6206
|
-
const field = fields[key];
|
|
6207
|
-
if (compFields.has(key)) args[key] = mkCompField(field, scope, inArgs[key]);
|
|
6208
|
-
else if (field === void 0)
|
|
6209
|
-
console.warn("extra argument to constructor:", name, key, inArgs);
|
|
6210
|
-
else args[key] = field.coerceOrDefault(inArgs[key]);
|
|
6211
|
-
}
|
|
6212
|
-
for (const key of compFields)
|
|
6213
|
-
if (args[key] === void 0) args[key] = mkCompField(fields[key], scope, inArgs[key]);
|
|
6214
|
-
return (0, immer_exports.freeze)(new this(args), true);
|
|
6215
|
-
}
|
|
6216
|
-
},
|
|
6217
|
-
this._statics
|
|
6218
|
-
);
|
|
6219
|
-
return Class;
|
|
6220
|
-
}
|
|
6221
|
-
methods(proto) {
|
|
6222
|
-
for (const k in proto) this._methods[k] = proto[k];
|
|
6223
|
-
}
|
|
6224
|
-
statics(proto) {
|
|
6225
|
-
for (const k in proto) this._statics[k] = proto[k];
|
|
6226
|
-
}
|
|
6227
|
-
addField(name, dval, FieldCls) {
|
|
6228
|
-
const field = new FieldCls(name, dval);
|
|
6229
|
-
this.fields[name] = field;
|
|
6230
|
-
return field;
|
|
6231
|
-
}
|
|
6232
|
-
addCompField(name, type, args) {
|
|
6233
|
-
const field = new FieldComp(type, name, args);
|
|
6234
|
-
this.compFields.add(name);
|
|
6235
|
-
this.fields[name] = field;
|
|
6236
|
-
return field;
|
|
6237
|
-
}
|
|
6238
|
-
};
|
|
6239
|
-
var FIELD_CLASS = /* @__PURE__ */ Symbol.for("tutuca.fieldClass");
|
|
6240
|
-
var fieldsByTypeName = {
|
|
6241
|
-
text: FieldString,
|
|
6242
|
-
int: FieldInt,
|
|
6243
|
-
float: FieldFloat,
|
|
6244
|
-
bool: FieldBool,
|
|
6245
|
-
list: FieldList,
|
|
6246
|
-
object: FieldObject,
|
|
6247
|
-
map: FieldMap,
|
|
6248
|
-
set: FieldSet,
|
|
6249
|
-
any: FieldAny
|
|
6250
|
-
};
|
|
6251
|
-
function fieldFromDescriptor(name, value) {
|
|
6252
|
-
const FieldCls = fieldsByTypeName[value.type] ?? FieldAny;
|
|
6253
|
-
const probe = new FieldCls(name);
|
|
6254
|
-
return [FieldCls, probe.coerceOr(value.defaultValue, probe.defaultValue)];
|
|
6255
|
-
}
|
|
6256
|
-
function classFromData(name, { fields = {}, methods, statics }) {
|
|
6257
|
-
const b = new ClassBuilder(name);
|
|
6258
|
-
for (const field in fields) {
|
|
6259
|
-
const value = fields[field];
|
|
6260
|
-
const type = typeof value;
|
|
6261
|
-
if (type === "string") b.addField(field, value, FieldString);
|
|
6262
|
-
else if (type === "number") b.addField(field, value, FieldFloat);
|
|
6263
|
-
else if (type === "boolean") b.addField(field, value, FieldBool);
|
|
6264
|
-
else if (Array.isArray(value)) b.addField(field, [...value], FieldList);
|
|
6265
|
-
else if (value instanceof Set) b.addField(field, new Set(value), FieldSet);
|
|
6266
|
-
else if (value instanceof Map) b.addField(field, new Map(value), FieldMap);
|
|
6267
|
-
else if (value?.type && Object.hasOwn(value, "defaultValue")) {
|
|
6268
|
-
const [FieldCls, dval] = fieldFromDescriptor(field, value);
|
|
6269
|
-
b.addField(field, dval, FieldCls);
|
|
6270
|
-
} else if (value?.component && value?.args !== void 0)
|
|
6271
|
-
b.addCompField(field, value.component, value.args);
|
|
6272
|
-
else if (isPlainObject(value)) b.addField(field, { ...value }, FieldObject);
|
|
6273
|
-
else {
|
|
6274
|
-
const FieldCls = value?.[FIELD_CLASS] ?? FieldAny;
|
|
6275
|
-
b.addField(field, value, FieldCls);
|
|
6276
6328
|
}
|
|
6277
|
-
}
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6329
|
+
}[name];
|
|
6330
|
+
Class[immer_exports.immerable] = true;
|
|
6331
|
+
Object.assign(Class.prototype, methods);
|
|
6332
|
+
Object.assign(
|
|
6333
|
+
Class,
|
|
6334
|
+
{
|
|
6335
|
+
fields,
|
|
6336
|
+
methods,
|
|
6337
|
+
// The documented way for instance code to reach its class's fields
|
|
6338
|
+
// (`this.constructor.getMetaClass().fields.x.defaultValue`).
|
|
6339
|
+
getMetaClass: () => Class,
|
|
6340
|
+
make(inArgs = {}, opts = {}) {
|
|
6341
|
+
const args = {};
|
|
6342
|
+
const scope = opts.scope ?? this.scope;
|
|
6343
|
+
for (const key in inArgs) {
|
|
6344
|
+
const field = fields[key];
|
|
6345
|
+
if (field === void 0)
|
|
6346
|
+
console.warn("extra argument to constructor:", name, key, inArgs);
|
|
6347
|
+
else if (field instanceof FieldComp) args[key] = mkCompField(field, scope, inArgs[key]);
|
|
6348
|
+
else args[key] = field.coerceOrDefault(inArgs[key]);
|
|
6349
|
+
}
|
|
6350
|
+
for (const key in fields)
|
|
6351
|
+
if (fields[key] instanceof FieldComp && args[key] === void 0)
|
|
6352
|
+
args[key] = mkCompField(fields[key], scope, void 0);
|
|
6353
|
+
return (0, immer_exports.freeze)(new this(args), true);
|
|
6354
|
+
}
|
|
6355
|
+
},
|
|
6356
|
+
statics
|
|
6357
|
+
);
|
|
6358
|
+
return Class;
|
|
6281
6359
|
}
|
|
6282
6360
|
function validateDraftFields(current, draft) {
|
|
6283
6361
|
const meta = metaOf(current);
|
|
@@ -6293,14 +6371,11 @@ function validateDraftFields(current, draft) {
|
|
|
6293
6371
|
}
|
|
6294
6372
|
}
|
|
6295
6373
|
}
|
|
6296
|
-
var META_KEYS = "name id fields methods views receive intent alter provide provideType lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
|
|
6297
|
-
" "
|
|
6298
|
-
);
|
|
6299
6374
|
var RESERVED_COMPONENT_STATICS = /* @__PURE__ */ new Set([
|
|
6300
|
-
...
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
...Object.
|
|
6375
|
+
..."name id fields methods views receive intent alter provide provideType lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup make getMetaClass".split(
|
|
6376
|
+
" "
|
|
6377
|
+
),
|
|
6378
|
+
...Object.keys(COMPONENT_METHODS)
|
|
6304
6379
|
]);
|
|
6305
6380
|
function assertNoReservedComponentStatics(statics = {}) {
|
|
6306
6381
|
for (const name in statics) {
|
|
@@ -6309,186 +6384,10 @@ function assertNoReservedComponentStatics(statics = {}) {
|
|
|
6309
6384
|
}
|
|
6310
6385
|
}
|
|
6311
6386
|
}
|
|
6312
|
-
|
|
6387
|
+
function component(opts) {
|
|
6313
6388
|
assertNoReservedComponentStatics(opts.statics);
|
|
6314
|
-
|
|
6315
|
-
const comp = new Component(Class, opts);
|
|
6316
|
-
const metaClass = Class.getMetaClass();
|
|
6317
|
-
comp.fields = metaClass.fields;
|
|
6318
|
-
comp.methods = metaClass.methods;
|
|
6319
|
-
Class.getMetaClass = () => comp;
|
|
6320
|
-
Class[COMPONENT] = comp;
|
|
6321
|
-
for (const key of META_KEYS)
|
|
6322
|
-
if (!Object.hasOwn(Class, key))
|
|
6323
|
-
Object.defineProperty(Class, key, {
|
|
6324
|
-
get() {
|
|
6325
|
-
return comp[key];
|
|
6326
|
-
},
|
|
6327
|
-
set(v) {
|
|
6328
|
-
comp[key] = v;
|
|
6329
|
-
},
|
|
6330
|
-
configurable: true
|
|
6331
|
-
});
|
|
6332
|
-
for (const key of Object.getOwnPropertyNames(Component.prototype))
|
|
6333
|
-
if (key !== "constructor" && !Object.hasOwn(Class, key))
|
|
6334
|
-
Class[key] = (...args) => comp[key](...args);
|
|
6335
|
-
return Class;
|
|
6336
|
-
};
|
|
6337
|
-
var component = (opts) => Component.fromSpec(opts);
|
|
6338
|
-
|
|
6339
|
-
// src/stack.js
|
|
6340
|
-
var STOP = /* @__PURE__ */ Symbol("STOP");
|
|
6341
|
-
var NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
6342
|
-
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
6343
|
-
function routeLookup(route, lex, dyn) {
|
|
6344
|
-
for (let i = 0; i < route.length; i++) {
|
|
6345
|
-
const leg = route[i];
|
|
6346
|
-
if (leg === "dyn") {
|
|
6347
|
-
const v = dyn();
|
|
6348
|
-
if (v != null) return v;
|
|
6349
|
-
} else if (leg === "lex") {
|
|
6350
|
-
const v = lex();
|
|
6351
|
-
if (v != null) return v;
|
|
6352
|
-
} else {
|
|
6353
|
-
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
6354
|
-
}
|
|
6355
|
-
}
|
|
6356
|
-
return null;
|
|
6357
|
-
}
|
|
6358
|
-
function lookup(chain, name, dv = null) {
|
|
6359
|
-
let n = chain;
|
|
6360
|
-
while (n !== null) {
|
|
6361
|
-
const r = n[0].lookup(name);
|
|
6362
|
-
if (r === STOP) return dv;
|
|
6363
|
-
if (r !== NEXT) return r;
|
|
6364
|
-
n = n[1];
|
|
6365
|
-
}
|
|
6366
|
-
return dv;
|
|
6367
|
-
}
|
|
6368
|
-
var BindFrame = class {
|
|
6369
|
-
constructor(it, binds, isFrame) {
|
|
6370
|
-
this.it = it;
|
|
6371
|
-
this.binds = binds;
|
|
6372
|
-
this.isFrame = isFrame;
|
|
6373
|
-
}
|
|
6374
|
-
lookup(name) {
|
|
6375
|
-
const v = this.binds[name];
|
|
6376
|
-
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
6377
|
-
}
|
|
6378
|
-
};
|
|
6379
|
-
var ObjectFrame = class {
|
|
6380
|
-
constructor(binds) {
|
|
6381
|
-
this.binds = binds;
|
|
6382
|
-
}
|
|
6383
|
-
lookup(key) {
|
|
6384
|
-
const v = this.binds[key];
|
|
6385
|
-
return v === void 0 ? NEXT : v;
|
|
6386
|
-
}
|
|
6387
|
-
};
|
|
6388
|
-
function computeViewsId(views) {
|
|
6389
|
-
let s = "";
|
|
6390
|
-
let n = views;
|
|
6391
|
-
while (n !== null) {
|
|
6392
|
-
s += n[0];
|
|
6393
|
-
n = n[1];
|
|
6394
|
-
}
|
|
6395
|
-
return s === "main" ? "" : s;
|
|
6389
|
+
return initComponent(classFromData(opts.name ?? "UnkComp", opts), opts);
|
|
6396
6390
|
}
|
|
6397
|
-
var Stack = class _Stack {
|
|
6398
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
6399
|
-
this.comps = comps;
|
|
6400
|
-
this.it = it;
|
|
6401
|
-
this.binds = binds;
|
|
6402
|
-
this.dynBinds = dynBinds;
|
|
6403
|
-
this.views = views;
|
|
6404
|
-
this.viewsId = viewsId;
|
|
6405
|
-
this.ctx = ctx;
|
|
6406
|
-
}
|
|
6407
|
-
// Evaluate every provide the entered component publishes and push them as one
|
|
6408
|
-
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
6409
|
-
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
6410
|
-
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
6411
|
-
_pushProvides() {
|
|
6412
|
-
const comp = this.comps.getCompFor(this.it);
|
|
6413
|
-
if (comp == null) return this;
|
|
6414
|
-
const { provide, provideType } = comp;
|
|
6415
|
-
const dynObj = {};
|
|
6416
|
-
let has = false;
|
|
6417
|
-
for (const k in provide) {
|
|
6418
|
-
dynObj[k] = provide[k].val.eval(this);
|
|
6419
|
-
has = true;
|
|
6420
|
-
}
|
|
6421
|
-
for (const k in provideType) {
|
|
6422
|
-
dynObj[k] = provideType[k];
|
|
6423
|
-
has = true;
|
|
6424
|
-
}
|
|
6425
|
-
if (!has) return this;
|
|
6426
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
6427
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
6428
|
-
return new _Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
6429
|
-
}
|
|
6430
|
-
static root(comps, it, ctx) {
|
|
6431
|
-
const binds = [new BindFrame(it, {}, true), null];
|
|
6432
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
6433
|
-
const views = ["main", null];
|
|
6434
|
-
return new _Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
6435
|
-
}
|
|
6436
|
-
enter(it, bindings = {}, isFrame = true) {
|
|
6437
|
-
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
6438
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
6439
|
-
const stack = new _Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
6440
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
6441
|
-
}
|
|
6442
|
-
pushViewName(name) {
|
|
6443
|
-
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
6444
|
-
const newViews = [name, views];
|
|
6445
|
-
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
6446
|
-
}
|
|
6447
|
-
// Published types are stable per scope and would only churn the render cache, so
|
|
6448
|
-
// the cache key covers values alone.
|
|
6449
|
-
_pushDynBindValuesToArray(arr, comp) {
|
|
6450
|
-
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
6451
|
-
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
6452
|
-
}
|
|
6453
|
-
// `*name`: the nearest binding above (including this component's own provides,
|
|
6454
|
-
// pushed on entering it), else this component's declared default, else null.
|
|
6455
|
-
lookupDynamic(name) {
|
|
6456
|
-
const v = lookup(this.dynBinds, name);
|
|
6457
|
-
if (v != null) return v;
|
|
6458
|
-
const comp = this.comps.getCompFor(this.it);
|
|
6459
|
-
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
6460
|
-
}
|
|
6461
|
-
lookupBind(name) {
|
|
6462
|
-
return lookup(this.binds, name);
|
|
6463
|
-
}
|
|
6464
|
-
lookupFieldRaw(name) {
|
|
6465
|
-
return this.it[name] ?? null;
|
|
6466
|
-
}
|
|
6467
|
-
lookupMethod(name) {
|
|
6468
|
-
const fn = this.it[name];
|
|
6469
|
-
return fn instanceof Function ? fn.call(this.it) : null;
|
|
6470
|
-
}
|
|
6471
|
-
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
6472
|
-
// `e.<member>` handler args. Null outside a live event transaction.
|
|
6473
|
-
lookupEvent() {
|
|
6474
|
-
return this.ctx?.event ?? null;
|
|
6475
|
-
}
|
|
6476
|
-
lookupDragInfo() {
|
|
6477
|
-
return this.ctx?.dragInfo ?? null;
|
|
6478
|
-
}
|
|
6479
|
-
getHandlerFor(name, key) {
|
|
6480
|
-
return this.comps.getHandlerFor(this.it, name, key);
|
|
6481
|
-
}
|
|
6482
|
-
lookupBestView(views, defaultViewName) {
|
|
6483
|
-
let n = this.views;
|
|
6484
|
-
while (n !== null) {
|
|
6485
|
-
const view = views[n[0]];
|
|
6486
|
-
if (view !== void 0) return view;
|
|
6487
|
-
n = n[1];
|
|
6488
|
-
}
|
|
6489
|
-
return views[defaultViewName];
|
|
6490
|
-
}
|
|
6491
|
-
};
|
|
6492
6391
|
|
|
6493
6392
|
// src/transactor.js
|
|
6494
6393
|
var State2 = class {
|
|
@@ -6529,14 +6428,7 @@ var Transactor = class {
|
|
|
6529
6428
|
// carry: kind, name, args, path, pathKeys, targetPath, handler, handlerName,
|
|
6530
6429
|
// matched, before, after, parent, timestamp. Purely observational.
|
|
6531
6430
|
observe(cb) {
|
|
6532
|
-
this._observers
|
|
6533
|
-
return () => {
|
|
6534
|
-
const i = this._observers.indexOf(cb);
|
|
6535
|
-
if (i !== -1) this._observers.splice(i, 1);
|
|
6536
|
-
};
|
|
6537
|
-
}
|
|
6538
|
-
_emit(record) {
|
|
6539
|
-
for (const cb of this._observers) cb(record);
|
|
6431
|
+
return subscribe(this._observers, cb);
|
|
6540
6432
|
}
|
|
6541
6433
|
// Record a refusal: a dispatch the runtime could not carry out. Kinds are
|
|
6542
6434
|
// open strings; today the runtime raises NO_HANDLER (a receive name with no
|
|
@@ -6555,20 +6447,16 @@ var Transactor = class {
|
|
|
6555
6447
|
// Subscribe to refusal records as they happen. Returns an unsubscribe fn,
|
|
6556
6448
|
// like observe().
|
|
6557
6449
|
observeRefusals(cb) {
|
|
6558
|
-
this._refusalObservers
|
|
6559
|
-
return () => {
|
|
6560
|
-
const i = this._refusalObservers.indexOf(cb);
|
|
6561
|
-
if (i !== -1) this._refusalObservers.splice(i, 1);
|
|
6562
|
-
};
|
|
6450
|
+
return subscribe(this._refusalObservers, cb);
|
|
6563
6451
|
}
|
|
6564
6452
|
// Build and dispatch one observer record. Pins field-resolved keys (e.g. a
|
|
6565
6453
|
// `.a[.selId]` render target reconstructed from a DOM event) against the root the
|
|
6566
6454
|
// handler read, so pathKeys carries concrete keys instead of dropping the dynamic
|
|
6567
6455
|
// step. No-op when nobody is observing.
|
|
6568
|
-
_emitRecord(root, { kind, name, args, path, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
6456
|
+
_emitRecord(root, { kind, name, args, path: path2, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
6569
6457
|
if (this._observers.length === 0) return;
|
|
6570
|
-
const pinned =
|
|
6571
|
-
|
|
6458
|
+
const pinned = path2.pinKeys(root);
|
|
6459
|
+
const record = {
|
|
6572
6460
|
kind,
|
|
6573
6461
|
name,
|
|
6574
6462
|
args: args ?? null,
|
|
@@ -6582,14 +6470,14 @@ var Transactor = class {
|
|
|
6582
6470
|
after,
|
|
6583
6471
|
parent,
|
|
6584
6472
|
timestamp: Date.now()
|
|
6585
|
-
}
|
|
6473
|
+
};
|
|
6474
|
+
for (const cb of this._observers) cb(record);
|
|
6586
6475
|
}
|
|
6587
6476
|
// The observer record for a settled transaction. The resolved handler
|
|
6588
6477
|
// (`_resolvedHandler`/`_matched`) and per-leaf before/after (`_before`/`_after`)
|
|
6589
6478
|
// were captured while the handler ran (see callHandler / Transaction.run).
|
|
6590
6479
|
_emitTransaction(transaction, root) {
|
|
6591
6480
|
if (this._observers.length === 0) return;
|
|
6592
|
-
if (transaction._resolvedHandler === void 0) return;
|
|
6593
6481
|
this._emitRecord(root, {
|
|
6594
6482
|
kind: transaction.observeKind,
|
|
6595
6483
|
name: transaction.observeName,
|
|
@@ -6603,33 +6491,29 @@ var Transactor = class {
|
|
|
6603
6491
|
parent: transaction.parentTransaction
|
|
6604
6492
|
});
|
|
6605
6493
|
}
|
|
6606
|
-
// Make `child` a tracked unit of `parent`'s subtree: the parent's completion stays open
|
|
6607
|
-
// until the child's *whole* subtree settles. Tracking happens at dispatch time — during
|
|
6608
|
-
// the parent's handler or afterTransaction — while the parent's self-unit is still held,
|
|
6609
|
-
// so the parent counter can't reach zero before the child is registered. Returns `child`.
|
|
6610
|
-
_link(child, parent) {
|
|
6611
|
-
if (parent) {
|
|
6612
|
-
const release = parent.completion.track();
|
|
6613
|
-
child.completion.whenSubtreeSettled().then(release);
|
|
6614
|
-
}
|
|
6615
|
-
return child;
|
|
6616
|
-
}
|
|
6617
6494
|
// `origin` is where the message came FROM, pinned now for the same reason an
|
|
6618
6495
|
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
6619
6496
|
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
6620
6497
|
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6498
|
+
//
|
|
6499
|
+
// The parent's subtree stays open until this message's whole subtree settles. The
|
|
6500
|
+
// unit is taken now, at dispatch — during the parent's handler or afterTransaction,
|
|
6501
|
+
// while the parent's self-unit is still held — so its counter can't reach zero first.
|
|
6502
|
+
pushSend(path2, name, args = [], parent = null, origin = null, txnPath = null) {
|
|
6503
|
+
const t = new SendEvent(path2, this, name, args, parent);
|
|
6504
|
+
t.txnPath = txnPath;
|
|
6505
|
+
t.origin = origin;
|
|
6506
|
+
t.originPinned = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
6624
6507
|
this.pushTransaction(t);
|
|
6625
|
-
|
|
6508
|
+
if (parent) t.completion.carry(parent.completion.track());
|
|
6509
|
+
return t;
|
|
6626
6510
|
}
|
|
6627
6511
|
// Raise an intent: a job the sender did not address, walked along a route until
|
|
6628
6512
|
// something answers. `opts.route` is a list of legs (see DEFAULT_ROUTE) and
|
|
6629
6513
|
// `opts.livePath` opts out of pinning the answer's destination keys.
|
|
6630
|
-
pushIntent(
|
|
6514
|
+
pushIntent(path2, name, args = [], opts = {}, parent = null) {
|
|
6631
6515
|
const release = parent ? parent.completion.track() : null;
|
|
6632
|
-
const walk = new IntentWalk(this,
|
|
6516
|
+
const walk = new IntentWalk(this, path2, name, args, opts, parent, release);
|
|
6633
6517
|
walk.advance();
|
|
6634
6518
|
return walk;
|
|
6635
6519
|
}
|
|
@@ -6646,7 +6530,7 @@ var Transactor = class {
|
|
|
6646
6530
|
return this.transactions.length > 0;
|
|
6647
6531
|
}
|
|
6648
6532
|
transactNext() {
|
|
6649
|
-
|
|
6533
|
+
this.transact(this.transactions.shift());
|
|
6650
6534
|
}
|
|
6651
6535
|
transact(transaction) {
|
|
6652
6536
|
try {
|
|
@@ -6659,20 +6543,31 @@ var Transactor = class {
|
|
|
6659
6543
|
} else console.warn("undefined new state", { curState, transaction });
|
|
6660
6544
|
} finally {
|
|
6661
6545
|
transaction.ensureWalkAdvanced?.();
|
|
6662
|
-
transaction._completion?.
|
|
6663
|
-
transaction._completion?.releaseSelf();
|
|
6546
|
+
transaction._completion?.finish();
|
|
6664
6547
|
}
|
|
6665
6548
|
}
|
|
6666
|
-
transactInputNow(
|
|
6667
|
-
this.transact(new InputEvent(
|
|
6549
|
+
transactInputNow(path2, event, eventHandler, dragInfo) {
|
|
6550
|
+
this.transact(new InputEvent(path2, event, eventHandler, this, dragInfo));
|
|
6668
6551
|
}
|
|
6669
6552
|
};
|
|
6670
6553
|
function nullHandler() {
|
|
6671
6554
|
return this;
|
|
6672
6555
|
}
|
|
6556
|
+
function subscribe(list, cb) {
|
|
6557
|
+
list.push(cb);
|
|
6558
|
+
return () => {
|
|
6559
|
+
const i = list.indexOf(cb);
|
|
6560
|
+
if (i !== -1) list.splice(i, 1);
|
|
6561
|
+
};
|
|
6562
|
+
}
|
|
6563
|
+
function warnUnknownLeg(what, leg) {
|
|
6564
|
+
console.warn(`unknown ${what} route leg`, leg, '- expected "dyn" or "lex"');
|
|
6565
|
+
return null;
|
|
6566
|
+
}
|
|
6673
6567
|
var Transaction = class {
|
|
6674
|
-
constructor(
|
|
6675
|
-
this.path =
|
|
6568
|
+
constructor(path2, transactor, parentTransaction = null) {
|
|
6569
|
+
this.path = path2;
|
|
6570
|
+
this.txnPath = null;
|
|
6676
6571
|
this.transactor = transactor;
|
|
6677
6572
|
this.parentTransaction = parentTransaction;
|
|
6678
6573
|
this._completion = null;
|
|
@@ -6692,39 +6587,41 @@ var Transaction = class {
|
|
|
6692
6587
|
whenSubtreeSettled() {
|
|
6693
6588
|
return this.completion.whenSubtreeSettled();
|
|
6694
6589
|
}
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
//
|
|
6698
|
-
// rather than throwing, so a stray call from the wrong place is a message and not a
|
|
6699
|
-
// crash. `walk` is undefined here, which is how ctx.reply/ctx.fail tell the two apart.
|
|
6700
|
-
stop() {
|
|
6701
|
-
warnNotIntent("stop");
|
|
6702
|
-
}
|
|
6703
|
-
forward(_opts) {
|
|
6704
|
-
console.warn('ctx.forward() needs a "receive" or "intent" handler - ignored');
|
|
6705
|
-
}
|
|
6706
|
-
// The kind reported to observers (see Transactor.observe); null on the base.
|
|
6707
|
-
get observeKind() {
|
|
6708
|
-
return null;
|
|
6709
|
-
}
|
|
6710
|
-
// The name reported to observers; null on the base. Overridden by NameArgs (the
|
|
6711
|
-
// dispatched message name) and InputEvent (the DOM event type). Kept separate from
|
|
6712
|
-
// `name`/`ctx.name` so it can't change handler-visible behavior.
|
|
6713
|
-
get observeName() {
|
|
6714
|
-
return null;
|
|
6715
|
-
}
|
|
6590
|
+
// Every transaction kind defines `observeKind` / `observeName` (what observers see;
|
|
6591
|
+
// kept apart from `name`/`ctx.name` so they can't change handler-visible behavior),
|
|
6592
|
+
// `getHandlerAndArgs(root, instance, comps)`, and the three `_forward*` hooks below.
|
|
6716
6593
|
callHandler(root, instance, draft, comps) {
|
|
6717
6594
|
const [handler, args] = this.getHandlerAndArgs(root, instance, comps);
|
|
6718
6595
|
this._resolvedHandler = handler;
|
|
6719
6596
|
return handler.apply(instance, [draft, ...args]);
|
|
6720
6597
|
}
|
|
6721
|
-
|
|
6722
|
-
|
|
6598
|
+
// `forward` is where a name can LEAVE the component: the message being handled is
|
|
6599
|
+
// raised again as an INTENT under the same name (`_forwardName()`) with the same
|
|
6600
|
+
// arguments unless `opts.args` says otherwise, from the position `_forwardPath()`
|
|
6601
|
+
// names. Deferred to afterTransaction so the state the handler produced is in place
|
|
6602
|
+
// before the walk starts. (`IntentEvent` overrides both: in an intent body, forward
|
|
6603
|
+
// amends the walk that is already running.)
|
|
6604
|
+
forward(opts) {
|
|
6605
|
+
this._forward = opts ?? {};
|
|
6606
|
+
}
|
|
6607
|
+
afterTransaction() {
|
|
6608
|
+
const f = this._forward;
|
|
6609
|
+
if (f === void 0) return;
|
|
6610
|
+
this._forward = void 0;
|
|
6611
|
+
const name = this._forwardName();
|
|
6612
|
+
if (name === void 0) {
|
|
6613
|
+
this.transactor.refuse("FORWARD_NO_NAME", {});
|
|
6614
|
+
return;
|
|
6615
|
+
}
|
|
6616
|
+
const { args = this._forwardArgs(), ...rest } = f;
|
|
6617
|
+
this.transactor.pushIntent(this._forwardPath(), name, args, rest, this);
|
|
6723
6618
|
}
|
|
6724
|
-
// The path used to apply the mutation
|
|
6725
|
-
//
|
|
6619
|
+
// The path used to apply the mutation: the ACTIVE frame of the dispatch path, so
|
|
6620
|
+
// an event inside a `<x render="*name">` subtree updates the value where it
|
|
6621
|
+
// really lives (the dispatch `this.path` keeps the visual callers, for bubbling).
|
|
6622
|
+
// `txnPath`, when pinned by the sender, wins.
|
|
6726
6623
|
getTransactionPath() {
|
|
6727
|
-
return this.path.toTransactionPath()
|
|
6624
|
+
return this.txnPath ?? this.path.toTransactionPath();
|
|
6728
6625
|
}
|
|
6729
6626
|
run(curRoot, comps) {
|
|
6730
6627
|
const txnPath = this.getTransactionPath();
|
|
@@ -6741,19 +6638,27 @@ var Transaction = class {
|
|
|
6741
6638
|
}
|
|
6742
6639
|
};
|
|
6743
6640
|
var InputEvent = class extends Transaction {
|
|
6744
|
-
constructor(
|
|
6745
|
-
super(
|
|
6641
|
+
constructor(path2, e, handler, transactor, dragInfo) {
|
|
6642
|
+
super(path2, transactor);
|
|
6746
6643
|
this.e = e;
|
|
6747
6644
|
this.handler = handler;
|
|
6748
6645
|
this.dragInfo = dragInfo;
|
|
6749
6646
|
this._dispatchPath = null;
|
|
6750
6647
|
}
|
|
6751
|
-
// Frame steps removed,
|
|
6752
|
-
//
|
|
6648
|
+
// Frame-only steps removed, one step per crossed component kept — inside every
|
|
6649
|
+
// continuation frame independently, so bubbling it visits every component and
|
|
6650
|
+
// then returns to the caller that wrote the `*name`.
|
|
6753
6651
|
get dispatchPath() {
|
|
6754
6652
|
this._dispatchPath ??= this.path.compact();
|
|
6755
6653
|
return this._dispatchPath;
|
|
6756
6654
|
}
|
|
6655
|
+
// Only a DOM event's path carries frame-only bind steps (they replay the handler's
|
|
6656
|
+
// arguments, but address no state); the compacted path is where the mutation lands,
|
|
6657
|
+
// so a handler inside @each still updates the component that owns the view. Every
|
|
6658
|
+
// other transaction is dispatched at an already-compacted position.
|
|
6659
|
+
getTransactionPath() {
|
|
6660
|
+
return this.dispatchPath.toTransactionPath();
|
|
6661
|
+
}
|
|
6757
6662
|
// A DOM event is an ADDRESSED message like any other — it reaches the component that
|
|
6758
6663
|
// owns the view and stops. It keeps its own class only because it resolves its handler
|
|
6759
6664
|
// from the compiled view and runs synchronously, not because it is a different channel.
|
|
@@ -6763,47 +6668,36 @@ var InputEvent = class extends Transaction {
|
|
|
6763
6668
|
get observeName() {
|
|
6764
6669
|
return this.e?.type ?? null;
|
|
6765
6670
|
}
|
|
6766
|
-
// A view's name is a message
|
|
6767
|
-
//
|
|
6768
|
-
//
|
|
6769
|
-
//
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
}
|
|
6773
|
-
afterTransaction() {
|
|
6774
|
-
const f = this._forward;
|
|
6775
|
-
if (f === void 0) return;
|
|
6776
|
-
this._forward = void 0;
|
|
6777
|
-
const { args = this._handlerArgs ?? [], ...rest } = f;
|
|
6671
|
+
// A view's name is a message, and forwarding it means a view that says
|
|
6672
|
+
// `@on.click="saveDraft .text"` never has to change when an ancestor takes the job
|
|
6673
|
+
// over. (A `$method` handler has a name too, so forwarding one raises an intent under
|
|
6674
|
+
// it.) `handler` is a NodeEvent, whose own `name` is the DOM event type; the MESSAGE
|
|
6675
|
+
// name is the one the view wrote, on the handler call it wraps.
|
|
6676
|
+
_forwardName() {
|
|
6778
6677
|
const hv = this.handler?.handlerCall?.handlerVal ?? this.handler?.handlerVal;
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6678
|
+
return hv?.name;
|
|
6679
|
+
}
|
|
6680
|
+
_forwardArgs() {
|
|
6681
|
+
return this._handlerArgs ?? [];
|
|
6682
|
+
}
|
|
6683
|
+
_forwardPath() {
|
|
6684
|
+
return this.dispatchPath;
|
|
6785
6685
|
}
|
|
6786
6686
|
getHandlerAndArgs(root, _instance, comps) {
|
|
6787
|
-
const stack = this.path.
|
|
6687
|
+
const stack = this.path.buildStack(Stack.root(comps, root, this));
|
|
6788
6688
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
6789
6689
|
this._handlerArgs = [...args];
|
|
6790
|
-
const
|
|
6791
|
-
args.push(new EventContext(
|
|
6690
|
+
const path2 = this.dispatchPath;
|
|
6691
|
+
args.push(new EventContext(path2, this.transactor, this));
|
|
6792
6692
|
return [handler, args];
|
|
6793
6693
|
}
|
|
6794
|
-
// The dispatched DOM event, read only through `e.<member>` handler args
|
|
6795
|
-
// (src/value.js EventMemberVal via Stack.lookupEvent). There is no bare
|
|
6796
|
-
// implicit-name vocabulary anymore: every arg carries a sigil.
|
|
6797
|
-
get event() {
|
|
6798
|
-
return this.e;
|
|
6799
|
-
}
|
|
6800
6694
|
};
|
|
6801
6695
|
var NameArgsTransaction = class extends Transaction {
|
|
6802
|
-
constructor(
|
|
6803
|
-
super(
|
|
6696
|
+
constructor(path2, transactor, name, args, parentTransaction) {
|
|
6697
|
+
super(path2, transactor, parentTransaction);
|
|
6804
6698
|
this.name = name;
|
|
6805
6699
|
this.args = args;
|
|
6806
|
-
this.targetPath =
|
|
6700
|
+
this.targetPath = path2;
|
|
6807
6701
|
}
|
|
6808
6702
|
handlerProp = null;
|
|
6809
6703
|
// NameArgs verbs map their handler bucket straight to the observed kind:
|
|
@@ -6814,6 +6708,17 @@ var NameArgsTransaction = class extends Transaction {
|
|
|
6814
6708
|
get observeName() {
|
|
6815
6709
|
return this.name;
|
|
6816
6710
|
}
|
|
6711
|
+
// `forward` in a RECEIVE body starts a walk: the message that arrived becomes an
|
|
6712
|
+
// intent, keeping its name and payload.
|
|
6713
|
+
_forwardName() {
|
|
6714
|
+
return this.name;
|
|
6715
|
+
}
|
|
6716
|
+
_forwardArgs() {
|
|
6717
|
+
return this.args;
|
|
6718
|
+
}
|
|
6719
|
+
_forwardPath() {
|
|
6720
|
+
return this.path;
|
|
6721
|
+
}
|
|
6817
6722
|
getHandlerForName(comp) {
|
|
6818
6723
|
const handlers = comp?.[this.handlerProp];
|
|
6819
6724
|
const exact = handlers?.[this.name];
|
|
@@ -6844,24 +6749,11 @@ var SendEvent = class extends NameArgsTransaction {
|
|
|
6844
6749
|
get observeKind() {
|
|
6845
6750
|
return this._isAnswer ? "answer" : "receive";
|
|
6846
6751
|
}
|
|
6847
|
-
// `forward` in a RECEIVE body starts a walk: the message that arrived becomes an
|
|
6848
|
-
// intent, keeping its name and payload. This is what lets a view's name leave the
|
|
6849
|
-
// component without the view changing.
|
|
6850
|
-
forward(opts) {
|
|
6851
|
-
this._forward = opts ?? {};
|
|
6852
|
-
}
|
|
6853
|
-
afterTransaction() {
|
|
6854
|
-
const f = this._forward;
|
|
6855
|
-
if (f === void 0) return;
|
|
6856
|
-
this._forward = void 0;
|
|
6857
|
-
const { args = this.args, ...rest } = f;
|
|
6858
|
-
this.transactor.pushIntent(this.path, this.name, args, rest, this);
|
|
6859
|
-
}
|
|
6860
6752
|
};
|
|
6861
6753
|
var IntentEvent = class extends NameArgsTransaction {
|
|
6862
6754
|
handlerProp = "intent";
|
|
6863
|
-
constructor(
|
|
6864
|
-
super(
|
|
6755
|
+
constructor(path2, transactor, walk) {
|
|
6756
|
+
super(path2, transactor, walk.name, walk.args, walk.parent);
|
|
6865
6757
|
this.walk = walk;
|
|
6866
6758
|
this.targetPath = walk.origin;
|
|
6867
6759
|
}
|
|
@@ -6870,9 +6762,6 @@ var IntentEvent = class extends NameArgsTransaction {
|
|
|
6870
6762
|
forward(opts) {
|
|
6871
6763
|
this.walk.amend(opts, this.path);
|
|
6872
6764
|
}
|
|
6873
|
-
stop() {
|
|
6874
|
-
this.walk.finish(null, null);
|
|
6875
|
-
}
|
|
6876
6765
|
afterTransaction() {
|
|
6877
6766
|
this.ensureWalkAdvanced();
|
|
6878
6767
|
}
|
|
@@ -6888,17 +6777,17 @@ var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
|
|
|
6888
6777
|
var REFUSAL_RING_CAP = 200;
|
|
6889
6778
|
var INTENT_DEPTH = 64;
|
|
6890
6779
|
var IntentWalk = class {
|
|
6891
|
-
constructor(transactor,
|
|
6780
|
+
constructor(transactor, path2, name, args, opts, parent, release) {
|
|
6892
6781
|
this.transactor = transactor;
|
|
6893
6782
|
this.name = name;
|
|
6894
6783
|
this.args = args;
|
|
6895
6784
|
this.route = opts?.route ?? DEFAULT_ROUTE;
|
|
6896
6785
|
this.parent = parent;
|
|
6897
6786
|
this.release = release;
|
|
6898
|
-
this.origin =
|
|
6899
|
-
this.answerPath = opts?.livePath ? null :
|
|
6787
|
+
this.origin = path2;
|
|
6788
|
+
this.answerPath = opts?.livePath ? null : path2.toTransactionPath().pinKeys(transactor.state.val);
|
|
6900
6789
|
this.legIndex = 0;
|
|
6901
|
-
this.dynAt =
|
|
6790
|
+
this.dynAt = path2;
|
|
6902
6791
|
this.hops = 0;
|
|
6903
6792
|
this.ended = false;
|
|
6904
6793
|
}
|
|
@@ -6910,7 +6799,7 @@ var IntentWalk = class {
|
|
|
6910
6799
|
while (this.legIndex < this.route.length) {
|
|
6911
6800
|
const leg = this.route[this.legIndex];
|
|
6912
6801
|
if (leg === "dyn") {
|
|
6913
|
-
if (this.dynAt.
|
|
6802
|
+
if (!this.dynAt.canPop()) {
|
|
6914
6803
|
this.legIndex++;
|
|
6915
6804
|
continue;
|
|
6916
6805
|
}
|
|
@@ -6922,7 +6811,7 @@ var IntentWalk = class {
|
|
|
6922
6811
|
this.legIndex++;
|
|
6923
6812
|
return this._tryLex();
|
|
6924
6813
|
}
|
|
6925
|
-
|
|
6814
|
+
warnUnknownLeg("intent", leg);
|
|
6926
6815
|
this.legIndex++;
|
|
6927
6816
|
}
|
|
6928
6817
|
this.exhaust("noHandler");
|
|
@@ -7007,11 +6896,11 @@ var IntentWalk = class {
|
|
|
7007
6896
|
if (this.ended) return;
|
|
7008
6897
|
this.ended = true;
|
|
7009
6898
|
if (name === null) return this.release?.();
|
|
7010
|
-
const
|
|
7011
|
-
|
|
6899
|
+
const t = new SendEvent(this.origin, this.transactor, name, args, this.parent);
|
|
6900
|
+
t.txnPath = this.answerPath;
|
|
7012
6901
|
t._isAnswer = true;
|
|
7013
6902
|
this.transactor.pushTransaction(t);
|
|
7014
|
-
if (this.release) t.completion.
|
|
6903
|
+
if (this.release) t.completion.carry(this.release);
|
|
7015
6904
|
}
|
|
7016
6905
|
};
|
|
7017
6906
|
var Completion = class {
|
|
@@ -7019,12 +6908,12 @@ var Completion = class {
|
|
|
7019
6908
|
this.val = void 0;
|
|
7020
6909
|
this.selfSettled = false;
|
|
7021
6910
|
this.subtreeSettled = false;
|
|
7022
|
-
this.pending =
|
|
6911
|
+
this.pending = 0;
|
|
7023
6912
|
this._selfResolve = null;
|
|
7024
6913
|
this._selfPromise = null;
|
|
7025
6914
|
this._subtreeResolve = null;
|
|
7026
6915
|
this._subtreePromise = null;
|
|
7027
|
-
this.
|
|
6916
|
+
this._releaseSelf = this.track();
|
|
7028
6917
|
}
|
|
7029
6918
|
whenSettled() {
|
|
7030
6919
|
if (this.selfSettled) return Promise.resolve(this.val);
|
|
@@ -7047,38 +6936,38 @@ var Completion = class {
|
|
|
7047
6936
|
this.val = val;
|
|
7048
6937
|
this._selfResolve?.(val);
|
|
7049
6938
|
}
|
|
7050
|
-
//
|
|
7051
|
-
|
|
7052
|
-
|
|
6939
|
+
// The transaction is done processing: self is settled (with the value the handler
|
|
6940
|
+
// produced, or none on the undefined-state / throw paths) and the self-unit goes.
|
|
6941
|
+
finish() {
|
|
6942
|
+
this.markSelfSettled(this.val);
|
|
6943
|
+
this._releaseSelf();
|
|
7053
6944
|
}
|
|
7054
|
-
// Register an outstanding unit; returns
|
|
6945
|
+
// Register an outstanding unit; returns its one-shot release. The subtree settles
|
|
6946
|
+
// when the last unit is released.
|
|
7055
6947
|
track() {
|
|
7056
6948
|
this.pending++;
|
|
7057
6949
|
let done = false;
|
|
7058
6950
|
return () => {
|
|
7059
6951
|
if (done) return;
|
|
7060
6952
|
done = true;
|
|
7061
|
-
this.
|
|
6953
|
+
if (--this.pending === 0) {
|
|
6954
|
+
this.subtreeSettled = true;
|
|
6955
|
+
this._subtreeResolve?.(this.val);
|
|
6956
|
+
}
|
|
7062
6957
|
};
|
|
7063
6958
|
}
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
this.
|
|
7068
|
-
}
|
|
7069
|
-
_release() {
|
|
7070
|
-
if (--this.pending === 0) {
|
|
7071
|
-
this.subtreeSettled = true;
|
|
7072
|
-
this._subtreeResolve?.(this.val);
|
|
7073
|
-
}
|
|
6959
|
+
// Hand a unit held elsewhere to this subtree: `release` runs once this transaction
|
|
6960
|
+
// and everything it spawned have settled.
|
|
6961
|
+
carry(release) {
|
|
6962
|
+
this.whenSubtreeSettled().then(release);
|
|
7074
6963
|
}
|
|
7075
6964
|
};
|
|
7076
6965
|
var Dispatcher = class {
|
|
7077
|
-
constructor(
|
|
7078
|
-
this.path =
|
|
6966
|
+
constructor(path2, transactor, parentTransaction) {
|
|
6967
|
+
this.path = path2;
|
|
7079
6968
|
this.transactor = transactor;
|
|
7080
6969
|
this.parent = parentTransaction;
|
|
7081
|
-
this.root =
|
|
6970
|
+
this.root = transactor.state.val;
|
|
7082
6971
|
}
|
|
7083
6972
|
// Walk the component instances on this ctx's path, leaf→root, calling
|
|
7084
6973
|
// callback(Component, instance). Return false from the callback to stop early.
|
|
@@ -7103,28 +6992,37 @@ var Dispatcher = class {
|
|
|
7103
6992
|
// replayed; provides are pushed on every component frame either way, so a provide
|
|
7104
6993
|
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
7105
6994
|
_stack() {
|
|
7106
|
-
this._stackMemo ??= this.path.
|
|
6995
|
+
this._stackMemo ??= this.path.buildStack(
|
|
6996
|
+
Stack.root(this.transactor.comps, this.root, this.parent)
|
|
6997
|
+
);
|
|
7107
6998
|
return this._stackMemo;
|
|
7108
6999
|
}
|
|
7109
7000
|
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
7110
7001
|
// the same spelling as `ctx.intent` — `["dyn"]` the render ancestry, `["lex"]` the
|
|
7111
7002
|
// registration scope, default both.
|
|
7003
|
+
// Legs are tried in route order, like the intent walker's; an unknown leg warns and
|
|
7004
|
+
// is skipped, and an empty route resolves to null.
|
|
7112
7005
|
lookup(name, opts) {
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
()
|
|
7116
|
-
|
|
7117
|
-
|
|
7006
|
+
for (const leg of opts?.route ?? DEFAULT_ROUTE) {
|
|
7007
|
+
const v = leg === "dyn" ? this._stack()?.lookupDynamic(name) ?? null : leg === "lex" ? this._lookupLex(name) : warnUnknownLeg("lookup", leg);
|
|
7008
|
+
if (v != null) return v;
|
|
7009
|
+
}
|
|
7010
|
+
return null;
|
|
7118
7011
|
}
|
|
7119
7012
|
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
7120
|
-
// running, which is the leaf of this ctx's path.
|
|
7013
|
+
// running, which is the leaf of this ctx's path. A type name resolves to the
|
|
7014
|
+
// component registered under it; a value name to a path registered under it
|
|
7015
|
+
// (see ComponentStack.registerPaths), read against the current root.
|
|
7121
7016
|
_lookupLex(name) {
|
|
7122
7017
|
let Comp = null;
|
|
7123
7018
|
this.walkPath((c) => {
|
|
7124
7019
|
Comp = c;
|
|
7125
7020
|
return false;
|
|
7126
7021
|
});
|
|
7127
|
-
|
|
7022
|
+
const scope = Comp?.scope;
|
|
7023
|
+
if (scope == null) return null;
|
|
7024
|
+
if (isTypeName(name)) return scope.lookupComponent(name) ?? null;
|
|
7025
|
+
return scope.lookupPath(name)?.lookup(this.root) ?? null;
|
|
7128
7026
|
}
|
|
7129
7027
|
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
7130
7028
|
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
@@ -7146,8 +7044,8 @@ var Dispatcher = class {
|
|
|
7146
7044
|
send(name, args) {
|
|
7147
7045
|
return this.sendAtPath(this.path, name, args);
|
|
7148
7046
|
}
|
|
7149
|
-
sendAtPath(
|
|
7150
|
-
return this.transactor.pushSend(
|
|
7047
|
+
sendAtPath(path2, name, args) {
|
|
7048
|
+
return this.transactor.pushSend(path2, name, args, this.parent, this.path);
|
|
7151
7049
|
}
|
|
7152
7050
|
// An intent is ROUTED: it names a job and walks until something answers. The verb
|
|
7153
7051
|
// does not decide which scope answers — `opts.route` does, written here at the call
|
|
@@ -7155,8 +7053,8 @@ var Dispatcher = class {
|
|
|
7155
7053
|
intent(name, args, opts) {
|
|
7156
7054
|
return this.intentAtPath(this.path, name, args, opts);
|
|
7157
7055
|
}
|
|
7158
|
-
intentAtPath(
|
|
7159
|
-
return this.transactor.pushIntent(
|
|
7056
|
+
intentAtPath(path2, name, args, opts) {
|
|
7057
|
+
return this.transactor.pushIntent(path2, name, args, opts, this.parent);
|
|
7160
7058
|
}
|
|
7161
7059
|
};
|
|
7162
7060
|
var EventContext = class extends Dispatcher {
|
|
@@ -7185,11 +7083,19 @@ var EventContext = class extends Dispatcher {
|
|
|
7185
7083
|
this.transactor.refuse("NO_SENDER", { name });
|
|
7186
7084
|
return null;
|
|
7187
7085
|
}
|
|
7188
|
-
return this.
|
|
7086
|
+
return this.transactor.pushSend(
|
|
7087
|
+
origin,
|
|
7088
|
+
name,
|
|
7089
|
+
args,
|
|
7090
|
+
this.parent,
|
|
7091
|
+
this.path,
|
|
7092
|
+
this.parent.originPinned
|
|
7093
|
+
);
|
|
7189
7094
|
}
|
|
7190
|
-
// End the walk answering nothing — "served, and no answer".
|
|
7095
|
+
// End the walk answering nothing — "served, and no answer". Like reply/fail,
|
|
7096
|
+
// legal only in an `intent` handler.
|
|
7191
7097
|
stop() {
|
|
7192
|
-
return this.parent.stop();
|
|
7098
|
+
return this.parent.walk === void 0 ? warnNotIntent("stop") : this.parent.walk.finish(null, null);
|
|
7193
7099
|
}
|
|
7194
7100
|
// From an `intent` body: hand the intent to the next hop, optionally amending it.
|
|
7195
7101
|
// From a `receive` body: turn the message that arrived into an intent. One word from
|
|
@@ -7217,13 +7123,13 @@ var PathChanges = class extends PathBuilder {
|
|
|
7217
7123
|
}
|
|
7218
7124
|
};
|
|
7219
7125
|
function rootDispatcher(transactor) {
|
|
7220
|
-
return new Dispatcher(new
|
|
7126
|
+
return new Dispatcher(new DispatchPath(), transactor, null);
|
|
7221
7127
|
}
|
|
7222
7128
|
|
|
7223
7129
|
// tools/core/results.js
|
|
7224
7130
|
var ModuleInfo = class {
|
|
7225
|
-
constructor({ path = null, present = /* @__PURE__ */ new Set(), counts = {}, warnings = [] }) {
|
|
7226
|
-
this.path =
|
|
7131
|
+
constructor({ path: path2 = null, present = /* @__PURE__ */ new Set(), counts = {}, warnings = [] }) {
|
|
7132
|
+
this.path = path2;
|
|
7227
7133
|
this.present = present;
|
|
7228
7134
|
this.counts = counts;
|
|
7229
7135
|
this.warnings = warnings;
|
|
@@ -7333,8 +7239,8 @@ var DescribeResult = class {
|
|
|
7333
7239
|
}
|
|
7334
7240
|
};
|
|
7335
7241
|
var ModuleTestReport = class {
|
|
7336
|
-
constructor({ path = null, suites = [], counts = { pass: 0, fail: 0, skip: 0, total: 0 } }) {
|
|
7337
|
-
this.path =
|
|
7242
|
+
constructor({ path: path2 = null, suites = [], counts = { pass: 0, fail: 0, skip: 0, total: 0 } }) {
|
|
7243
|
+
this.path = path2;
|
|
7338
7244
|
this.suites = suites;
|
|
7339
7245
|
this.counts = counts;
|
|
7340
7246
|
}
|
|
@@ -7377,8 +7283,8 @@ var Test = class {
|
|
|
7377
7283
|
}
|
|
7378
7284
|
};
|
|
7379
7285
|
var ModuleTests = class {
|
|
7380
|
-
constructor({ path = null, suites = [] } = {}) {
|
|
7381
|
-
this.path =
|
|
7286
|
+
constructor({ path: path2 = null, suites = [] } = {}) {
|
|
7287
|
+
this.path = path2;
|
|
7382
7288
|
this.suites = suites;
|
|
7383
7289
|
}
|
|
7384
7290
|
};
|
|
@@ -7400,8 +7306,8 @@ function titleFromArg(arg) {
|
|
|
7400
7306
|
if (typeof arg === "function") return arg.name || "(anonymous)";
|
|
7401
7307
|
return String(arg);
|
|
7402
7308
|
}
|
|
7403
|
-
function makeCollector({ path = null, components = [] } = {}) {
|
|
7404
|
-
const moduleTests = new ModuleTests({ path, suites: [] });
|
|
7309
|
+
function makeCollector({ path: path2 = null, components = [] } = {}) {
|
|
7310
|
+
const moduleTests = new ModuleTests({ path: path2, suites: [] });
|
|
7405
7311
|
const stack = [];
|
|
7406
7312
|
function describe(...args) {
|
|
7407
7313
|
let head;
|
|
@@ -7502,7 +7408,7 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
7502
7408
|
val
|
|
7503
7409
|
);
|
|
7504
7410
|
});
|
|
7505
|
-
dispatchPhase(rootDispatcher(transactor), new
|
|
7411
|
+
dispatchPhase(rootDispatcher(transactor), new DispatchPath(), phase, value);
|
|
7506
7412
|
await transactor.settle();
|
|
7507
7413
|
return transactor.state.val;
|
|
7508
7414
|
}
|
|
@@ -7512,7 +7418,7 @@ async function drive(cfg, value, phase, opts = {}) {
|
|
|
7512
7418
|
async function runTests({
|
|
7513
7419
|
getTests,
|
|
7514
7420
|
components = [],
|
|
7515
|
-
path = null,
|
|
7421
|
+
path: path2 = null,
|
|
7516
7422
|
expect: expect3,
|
|
7517
7423
|
name = null,
|
|
7518
7424
|
grep = null,
|
|
@@ -7523,13 +7429,13 @@ async function runTests({
|
|
|
7523
7429
|
const counts = { pass: 0, fail: 0, skip: 0, total: 0 };
|
|
7524
7430
|
if (typeof getTests !== "function") {
|
|
7525
7431
|
return new TestReport({
|
|
7526
|
-
modules: [new ModuleTestReport({ path, suites: [], counts })]
|
|
7432
|
+
modules: [new ModuleTestReport({ path: path2, suites: [], counts })]
|
|
7527
7433
|
});
|
|
7528
7434
|
}
|
|
7529
7435
|
if (typeof expect3 !== "function") {
|
|
7530
7436
|
throw new Error("runTests: expect must be provided (e.g. chai's expect)");
|
|
7531
7437
|
}
|
|
7532
|
-
const { describe, test: test2, moduleTests } = makeCollector({ path, components });
|
|
7438
|
+
const { describe, test: test2, moduleTests } = makeCollector({ path: path2, components });
|
|
7533
7439
|
let _stack = null;
|
|
7534
7440
|
const getStack = () => _stack ??= buildStack({ components, macros, intentHandlers });
|
|
7535
7441
|
const driveLocal = (value, phase, opts = {}) => driveStack(getStack(), value, phase, opts);
|
|
@@ -7592,7 +7498,7 @@ async function runTests({
|
|
|
7592
7498
|
if (r !== null) suiteResults.push(r);
|
|
7593
7499
|
}
|
|
7594
7500
|
return new TestReport({
|
|
7595
|
-
modules: [new ModuleTestReport({ path, suites: suiteResults, counts })]
|
|
7501
|
+
modules: [new ModuleTestReport({ path: path2, suites: suiteResults, counts })]
|
|
7596
7502
|
});
|
|
7597
7503
|
}
|
|
7598
7504
|
|
|
@@ -7761,19 +7667,19 @@ function lintIdToMessage(id, info) {
|
|
|
7761
7667
|
case "DYN_ALIAS_NOT_REFERENCED":
|
|
7762
7668
|
return `Lookup '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
|
|
7763
7669
|
case "PROVIDE_NOT_ADDRESSABLE":
|
|
7764
|
-
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a
|
|
7670
|
+
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a provide doubles as the path '<x render="*${info.name}">' resumes at, so this one is dropped and '*${info.name}' resolves to nothing`;
|
|
7765
7671
|
case "LOOKUP_BAD_SHAPE":
|
|
7766
7672
|
return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
|
|
7767
7673
|
case "LOOKUP_NO_PROVIDER":
|
|
7768
|
-
return info.hasDefault ? `Lookup '${info.name}' is provided by no component in scope, so it always resolves to its default` : `Lookup '${info.name}' is provided by no component in scope — add a 'provide' for it, or give this lookup a default`;
|
|
7674
|
+
return info.hasDefault ? `Lookup '${info.name}' is provided by no component in scope and matches no registered path, so it always resolves to its default` : `Lookup '${info.name}' is provided by no component in scope and matches no registered path — add a 'provide' for it, register a path under that name, or give this lookup a default`;
|
|
7769
7675
|
case "PROVIDE_TYPE_BAD_SHAPE":
|
|
7770
7676
|
return `Provide '${info.name}' starts uppercase, so it publishes a component type — its value must be 'self', not '${info.value}'`;
|
|
7771
|
-
case "PROVIDE_NAME_COLLISION":
|
|
7772
|
-
return `Provide '${info.name}' is also provided by '${info.other}' in the same scope — one name, one provider, so a lookup can find it`;
|
|
7773
7677
|
case "UNKNOWN_MACRO_ARG":
|
|
7774
7678
|
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
7775
7679
|
case "UNKNOWN_DIRECTIVE":
|
|
7776
7680
|
return `Unknown directive '@${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
|
|
7681
|
+
case "ORPHAN_DIRECTIVE":
|
|
7682
|
+
return `'@${info.name}=${JSON.stringify(info.value)}' needs an '@${info.needs}' on the same element — it was ignored${fmtTagSuffix(info)}`;
|
|
7777
7683
|
case "UNKNOWN_X_OP":
|
|
7778
7684
|
return `Unknown <x> op '${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
|
|
7779
7685
|
case "UNKNOWN_X_ATTR":
|
|
@@ -7907,7 +7813,6 @@ var App = class {
|
|
|
7907
7813
|
this.transactor = new Transactor(comps, null);
|
|
7908
7814
|
this.ParseContext = ParseContext2;
|
|
7909
7815
|
this.renderer = renderer;
|
|
7910
|
-
this.maxEventNodeDepth = Infinity;
|
|
7911
7816
|
this._transactNextBatchId = this._evictCacheId = null;
|
|
7912
7817
|
this._eventNames = new Set(_evs);
|
|
7913
7818
|
this.dragInfo = this.curDragOver = null;
|
|
@@ -7934,18 +7839,17 @@ var App = class {
|
|
|
7934
7839
|
_dispatchEvent(e) {
|
|
7935
7840
|
const { type } = e;
|
|
7936
7841
|
const isDrag = type === "dragover" || type === "dragstart" || type === "dragend" || type === "drop";
|
|
7937
|
-
const { rootNode
|
|
7938
|
-
const [
|
|
7842
|
+
const { rootNode, comps, transactor } = this;
|
|
7843
|
+
const [path2, handlers] = DispatchPath.fromNodeAndEventName(
|
|
7939
7844
|
e.target,
|
|
7940
7845
|
type,
|
|
7941
|
-
|
|
7942
|
-
maxDepth,
|
|
7846
|
+
rootNode,
|
|
7943
7847
|
comps,
|
|
7944
7848
|
!isDrag
|
|
7945
7849
|
);
|
|
7946
|
-
if (isDrag) this._handleDragEvent(e, type,
|
|
7947
|
-
if (
|
|
7948
|
-
for (const handler of handlers) transactor.transactInputNow(
|
|
7850
|
+
if (isDrag) this._handleDragEvent(e, type, path2);
|
|
7851
|
+
if (path2 !== null && handlers !== null)
|
|
7852
|
+
for (const handler of handlers) transactor.transactInputNow(path2, e, handler, this.dragInfo);
|
|
7949
7853
|
}
|
|
7950
7854
|
_handleTouchEvent(e) {
|
|
7951
7855
|
const { type } = e;
|
|
@@ -7988,7 +7892,7 @@ var App = class {
|
|
|
7988
7892
|
this._touch = null;
|
|
7989
7893
|
}
|
|
7990
7894
|
}
|
|
7991
|
-
_handleDragEvent(e, type,
|
|
7895
|
+
_handleDragEvent(e, type, path2) {
|
|
7992
7896
|
if (type === "dragover") {
|
|
7993
7897
|
const dropTarget = getClosestDropTarget(e.target, this.rootNode, Infinity);
|
|
7994
7898
|
if (dropTarget !== null) {
|
|
@@ -8000,10 +7904,10 @@ var App = class {
|
|
|
8000
7904
|
} else if (type === "dragstart") {
|
|
8001
7905
|
e.target.dataset.dragging = 1;
|
|
8002
7906
|
const rootValue = this.state.val;
|
|
8003
|
-
const txnPath =
|
|
7907
|
+
const txnPath = path2.compact().toTransactionPath();
|
|
8004
7908
|
const value = txnPath.lookup(rootValue);
|
|
8005
7909
|
const dragType = e.target.dataset.dragtype ?? "?";
|
|
8006
|
-
const stack =
|
|
7910
|
+
const stack = path2.buildStack(this.makeStack(rootValue));
|
|
8007
7911
|
this.dragInfo = new DragInfo(stack, value, dragType, e.target);
|
|
8008
7912
|
} else if (type === "drop") {
|
|
8009
7913
|
e.preventDefault();
|
|
@@ -8048,10 +7952,9 @@ var App = class {
|
|
|
8048
7952
|
}
|
|
8049
7953
|
compile() {
|
|
8050
7954
|
for (const Comp of this.comps.byId.values()) {
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
for (const name of meta.views[key].ctx.genEventNames()) this._eventNames.add(name);
|
|
7955
|
+
Comp.compile(this.ParseContext);
|
|
7956
|
+
for (const key in Comp.views)
|
|
7957
|
+
for (const name of Comp.views[key].ctx.genEventNames()) this._eventNames.add(name);
|
|
8055
7958
|
}
|
|
8056
7959
|
this._compiled = true;
|
|
8057
7960
|
}
|
|
@@ -8074,11 +7977,13 @@ var App = class {
|
|
|
8074
7977
|
}
|
|
8075
7978
|
stop() {
|
|
8076
7979
|
this.stopCacheEvictionInterval();
|
|
7980
|
+
clearTimeout(this._transactNextBatchId);
|
|
7981
|
+
this._transactNextBatchId = null;
|
|
8077
7982
|
for (const name of this._eventNames)
|
|
8078
7983
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
8079
7984
|
}
|
|
8080
7985
|
sendAtRoot(name, args) {
|
|
8081
|
-
this.transactor.pushSend(new
|
|
7986
|
+
this.transactor.pushSend(new DispatchPath(), name, args);
|
|
8082
7987
|
}
|
|
8083
7988
|
registerComponents(comps, opts) {
|
|
8084
7989
|
const scope = this.compStack.enter();
|
|
@@ -8160,28 +8065,21 @@ var NullDomCache = class {
|
|
|
8160
8065
|
set(_keys, _cacheKey, _v) {
|
|
8161
8066
|
}
|
|
8162
8067
|
evict() {
|
|
8163
|
-
return { hit: 0, miss: 0, badKey: 0 };
|
|
8164
8068
|
}
|
|
8165
8069
|
};
|
|
8166
8070
|
var WeakMapDomCache = class {
|
|
8167
8071
|
constructor() {
|
|
8168
|
-
this.hit = this.miss = this.badKey = 0;
|
|
8169
8072
|
this.keysByLen = /* @__PURE__ */ new Map();
|
|
8170
8073
|
}
|
|
8171
|
-
_returnValue(r) {
|
|
8172
|
-
if (r === void 0) this.miss += 1;
|
|
8173
|
-
else this.hit += 1;
|
|
8174
|
-
return r;
|
|
8175
|
-
}
|
|
8176
8074
|
get(keys, cacheKey) {
|
|
8177
8075
|
const len = keys.length;
|
|
8178
8076
|
let cur = this.keysByLen.get(len);
|
|
8179
|
-
if (!cur) return
|
|
8077
|
+
if (!cur) return void 0;
|
|
8180
8078
|
for (let i = 0; i < len - 1; i++) {
|
|
8181
8079
|
cur = cur.get(keys[i]);
|
|
8182
|
-
if (!cur) return
|
|
8080
|
+
if (!cur) return void 0;
|
|
8183
8081
|
}
|
|
8184
|
-
return
|
|
8082
|
+
return cur.get(keys[len - 1])?.[cacheKey];
|
|
8185
8083
|
}
|
|
8186
8084
|
set(keys, cacheKey, v) {
|
|
8187
8085
|
const len = keys.length;
|
|
@@ -8194,10 +8092,7 @@ var WeakMapDomCache = class {
|
|
|
8194
8092
|
const key = keys[i];
|
|
8195
8093
|
let next = cur.get(key);
|
|
8196
8094
|
if (!next) {
|
|
8197
|
-
if (!isWeakKey(key))
|
|
8198
|
-
this.badKey += 1;
|
|
8199
|
-
return;
|
|
8200
|
-
}
|
|
8095
|
+
if (!isWeakKey(key)) return;
|
|
8201
8096
|
next = /* @__PURE__ */ new WeakMap();
|
|
8202
8097
|
cur.set(key, next);
|
|
8203
8098
|
}
|
|
@@ -8207,23 +8102,38 @@ var WeakMapDomCache = class {
|
|
|
8207
8102
|
const leaf = cur.get(lastKey);
|
|
8208
8103
|
if (leaf) leaf[cacheKey] = v;
|
|
8209
8104
|
else if (isWeakKey(lastKey)) cur.set(lastKey, { [cacheKey]: v });
|
|
8210
|
-
else this.badKey += 1;
|
|
8211
8105
|
}
|
|
8212
8106
|
evict() {
|
|
8213
|
-
const { hit, miss, badKey } = this;
|
|
8214
|
-
this.hit = this.miss = this.badKey = 0;
|
|
8215
8107
|
this.keysByLen = /* @__PURE__ */ new Map();
|
|
8216
|
-
return { hit, miss, badKey };
|
|
8217
8108
|
}
|
|
8218
8109
|
};
|
|
8219
8110
|
|
|
8220
8111
|
// src/renderer.js
|
|
8221
|
-
|
|
8112
|
+
function stampRenderBase(vdom, text) {
|
|
8113
|
+
if (vdom instanceof VNode)
|
|
8114
|
+
return new VNode(
|
|
8115
|
+
vdom.tag,
|
|
8116
|
+
{ ...vdom.attrs, "data-rp": text },
|
|
8117
|
+
vdom.childs,
|
|
8118
|
+
vdom.key,
|
|
8119
|
+
vdom.namespace
|
|
8120
|
+
);
|
|
8121
|
+
if (vdom instanceof VFragment)
|
|
8122
|
+
return new VFragment(vdom.childs.map((c) => stampRenderBase(c, text)));
|
|
8123
|
+
return vdom;
|
|
8124
|
+
}
|
|
8222
8125
|
var Renderer = class {
|
|
8223
8126
|
constructor(comps) {
|
|
8224
8127
|
this.comps = comps;
|
|
8225
8128
|
this.cache = new WeakMapDomCache();
|
|
8226
|
-
|
|
8129
|
+
}
|
|
8130
|
+
// Parse nodes build their VDOM through the renderer, never by importing vdom.js
|
|
8131
|
+
// themselves: a component may have been compiled by ANOTHER copy of the library
|
|
8132
|
+
// (a docs example imports the dist bundle while the host app runs from src), and
|
|
8133
|
+
// `render()` recognizes VNodes by `instanceof` against ITS copy's classes. Going
|
|
8134
|
+
// through `rx` guarantees the rendering copy makes them.
|
|
8135
|
+
renderTag(tag, attrs, childs, namespace) {
|
|
8136
|
+
return h(tag, attrs, childs, namespace);
|
|
8227
8137
|
}
|
|
8228
8138
|
renderFragment(childs) {
|
|
8229
8139
|
return new VFragment(childs);
|
|
@@ -8234,38 +8144,24 @@ var Renderer = class {
|
|
|
8234
8144
|
setNullCache() {
|
|
8235
8145
|
this.cache = new NullDomCache();
|
|
8236
8146
|
}
|
|
8237
|
-
// Library utilities for consumers embedding tutuca: render a value to a detached
|
|
8238
|
-
// DOM node / an HTML string. Not called by the framework itself.
|
|
8239
|
-
renderToDOM(stack, val) {
|
|
8240
|
-
const rootNode = document.createElement("div");
|
|
8241
|
-
const rOpts = { document };
|
|
8242
|
-
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
8243
|
-
return rootNode.childNodes[0];
|
|
8244
|
-
}
|
|
8245
|
-
renderToString(stack, val, cleanAttrs = true) {
|
|
8246
|
-
const dom = this.renderToDOM(stack, val);
|
|
8247
|
-
if (cleanAttrs) {
|
|
8248
|
-
const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
|
|
8249
|
-
for (const { dataset } of nodes) for (const name of DATASET_ATTRS) delete dataset[name];
|
|
8250
|
-
}
|
|
8251
|
-
return dom.innerHTML;
|
|
8252
|
-
}
|
|
8253
8147
|
renderRoot(stack, val, viewName = null) {
|
|
8254
8148
|
const comp = this.comps.getCompFor(val);
|
|
8255
8149
|
if (comp === null) return null;
|
|
8256
8150
|
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
8257
8151
|
}
|
|
8258
|
-
|
|
8152
|
+
// Render `stack.it` at a `<x render*>` site (`node`). `base` is the absolute
|
|
8153
|
+
// path the site resumed at, when it rendered a `*name` (see _rValComp).
|
|
8154
|
+
renderIt(stack, node, viewName, base = null) {
|
|
8259
8155
|
const comp = this.comps.getCompFor(stack.it);
|
|
8260
|
-
return comp ? this._rValComp(stack, stack.it, comp, node,
|
|
8156
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, "", viewName, base) : null;
|
|
8261
8157
|
}
|
|
8262
8158
|
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
8263
8159
|
// `render-each`, or the view's root anode for the app root). It keys the
|
|
8264
8160
|
// cache as a globally-unique object: node ids alone are unique only within a
|
|
8265
8161
|
// single view, so the same value rendered by two components (e.g. through a
|
|
8266
8162
|
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
8267
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
8268
|
-
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
8163
|
+
_rValComp(stack, val, comp, node, key, viewName, base = null) {
|
|
8164
|
+
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}${stack.renderPath.addressKey}`;
|
|
8269
8165
|
const cachePath = [node, val];
|
|
8270
8166
|
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
8271
8167
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
@@ -8273,30 +8169,43 @@ var Renderer = class {
|
|
|
8273
8169
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
8274
8170
|
const body = this.renderView(view, stack);
|
|
8275
8171
|
if (body == null) return null;
|
|
8172
|
+
const baseJson = base === null ? null : pathToJson(base);
|
|
8276
8173
|
const meta = this._renderMetadata({
|
|
8277
8174
|
$: "Comp",
|
|
8278
8175
|
nid: node?.nodeId ?? null,
|
|
8279
8176
|
cid: comp.id,
|
|
8280
|
-
vid: view.name
|
|
8177
|
+
vid: view.name,
|
|
8178
|
+
...baseJson === null ? null : { base: baseJson }
|
|
8281
8179
|
});
|
|
8282
|
-
const dom = new VFragment([
|
|
8180
|
+
const dom = new VFragment([
|
|
8181
|
+
meta,
|
|
8182
|
+
baseJson === null ? body : stampRenderBase(body, JSON.stringify(baseJson))
|
|
8183
|
+
]);
|
|
8283
8184
|
this.cache.set(cachePath, cacheKey, dom);
|
|
8284
8185
|
return dom;
|
|
8285
8186
|
}
|
|
8286
8187
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
8287
8188
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
8288
8189
|
}
|
|
8289
|
-
renderEachWhen(stack,
|
|
8290
|
-
const {
|
|
8190
|
+
renderEachWhen(stack, each) {
|
|
8191
|
+
const { val: seqVal, node: view, nodeId: nid } = each;
|
|
8192
|
+
const { seq, filter, loopWith, enricher } = each.evalIter(stack);
|
|
8193
|
+
const seqPath = seqVal instanceof DynVal ? stack.lookupDynamicLocated(seqVal.name)?.path ?? null : null;
|
|
8291
8194
|
const r = [];
|
|
8292
8195
|
const it = stack.it;
|
|
8293
8196
|
const renderOne = (key, value, attrName, binds) => {
|
|
8197
|
+
const itemBase = seqPath === null ? null : keyedPath(seqPath, key);
|
|
8198
|
+
const itemStep = itemBase === null ? each.itemStep(key) : null;
|
|
8199
|
+
const itemPath = itemBase !== null ? stack.renderPath.pushFrame(itemBase) : itemStep !== null ? stack.renderPath.pushItem(itemStep) : stack.renderPath;
|
|
8294
8200
|
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
8295
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
8201
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}${itemPath.addressKey}`;
|
|
8296
8202
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
8297
8203
|
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
8298
8204
|
else {
|
|
8299
|
-
const dom = this.renderView(
|
|
8205
|
+
const dom = this.renderView(
|
|
8206
|
+
view,
|
|
8207
|
+
stack.enter(value, binds, false, itemPath, itemBase !== null)
|
|
8208
|
+
);
|
|
8300
8209
|
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
8301
8210
|
this.cache.set(cachePath, cacheKey, dom);
|
|
8302
8211
|
}
|
|
@@ -8445,12 +8354,7 @@ function shadowCheckComponent(Comp) {
|
|
|
8445
8354
|
shadowViews[name] = { name, ctx, rawView };
|
|
8446
8355
|
}
|
|
8447
8356
|
const shadowComp = Object.create(Comp);
|
|
8448
|
-
|
|
8449
|
-
value: shadowViews,
|
|
8450
|
-
writable: true,
|
|
8451
|
-
enumerable: true,
|
|
8452
|
-
configurable: true
|
|
8453
|
-
});
|
|
8357
|
+
shadowComp.views = shadowViews;
|
|
8454
8358
|
return checkComponent(shadowComp).reports;
|
|
8455
8359
|
}
|
|
8456
8360
|
function check(app) {
|
|
@@ -8476,39 +8380,6 @@ function check(app) {
|
|
|
8476
8380
|
);
|
|
8477
8381
|
return counts;
|
|
8478
8382
|
}
|
|
8479
|
-
var LintClassCollectorCtx = class _LintClassCollectorCtx extends ParseCtxClassSetCollector {
|
|
8480
|
-
constructor(...args) {
|
|
8481
|
-
super(...args);
|
|
8482
|
-
this.attrs = [];
|
|
8483
|
-
this.parseIssues = [];
|
|
8484
|
-
}
|
|
8485
|
-
enterMacro(macroName, macroVars, macroSlots) {
|
|
8486
|
-
const { document: document2, Text, Comment, nodes, events, macroNodes } = this;
|
|
8487
|
-
const frame = { macroName, macroVars, macroSlots };
|
|
8488
|
-
const v = new _LintClassCollectorCtx(
|
|
8489
|
-
document2,
|
|
8490
|
-
Text,
|
|
8491
|
-
Comment,
|
|
8492
|
-
nodes,
|
|
8493
|
-
events,
|
|
8494
|
-
macroNodes,
|
|
8495
|
-
frame,
|
|
8496
|
-
this
|
|
8497
|
-
);
|
|
8498
|
-
v.classes = this.classes;
|
|
8499
|
-
v.attrs = this.attrs;
|
|
8500
|
-
v.parseIssues = this.parseIssues;
|
|
8501
|
-
return v;
|
|
8502
|
-
}
|
|
8503
|
-
onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false, tag = null) {
|
|
8504
|
-
super.onAttributes(attrs, wrapperAttrs, textChild, isMacroCall, tag);
|
|
8505
|
-
this.attrs.push({ attrs, wrapperAttrs, textChild, isMacroCall, tag });
|
|
8506
|
-
}
|
|
8507
|
-
onParseIssue(kind, info) {
|
|
8508
|
-
const tag = this.currentTag;
|
|
8509
|
-
this.parseIssues.push({ kind, info: tag && info.tag === void 0 ? { ...info, tag } : info });
|
|
8510
|
-
}
|
|
8511
|
-
};
|
|
8512
8383
|
var export_expect = chai_exports.expect;
|
|
8513
8384
|
export {
|
|
8514
8385
|
ALT_HANDLER_NOT_DEFINED,
|
|
@@ -8529,7 +8400,6 @@ export {
|
|
|
8529
8400
|
DescribeResult,
|
|
8530
8401
|
EVENT_HANDLER_METHOD_NOT_ALLOWED,
|
|
8531
8402
|
ExampleIndex,
|
|
8532
|
-
FIELD_CLASS,
|
|
8533
8403
|
FIELD_METHOD_NAME_COLLISION,
|
|
8534
8404
|
FIELD_VAL_IS_METHOD,
|
|
8535
8405
|
FIELD_VAL_NOT_DEFINED,
|
|
@@ -8538,7 +8408,6 @@ export {
|
|
|
8538
8408
|
IF_NO_BRANCH_SET,
|
|
8539
8409
|
LOOKUP_BAD_SHAPE,
|
|
8540
8410
|
LOOKUP_NO_PROVIDER,
|
|
8541
|
-
LintClassCollectorCtx,
|
|
8542
8411
|
LintComponentResult,
|
|
8543
8412
|
LintContext,
|
|
8544
8413
|
LintFinding,
|
|
@@ -8551,9 +8420,9 @@ export {
|
|
|
8551
8420
|
ModuleInfo,
|
|
8552
8421
|
ModuleTestReport,
|
|
8553
8422
|
ModuleTests,
|
|
8423
|
+
ORPHAN_DIRECTIVE,
|
|
8554
8424
|
PASS,
|
|
8555
8425
|
PLACEHOLDERLESS_TEMPLATE_STRING,
|
|
8556
|
-
PROVIDE_NAME_COLLISION,
|
|
8557
8426
|
PROVIDE_NOT_ADDRESSABLE,
|
|
8558
8427
|
PROVIDE_TYPE_BAD_SHAPE,
|
|
8559
8428
|
ParseContext,
|
|
@@ -8594,6 +8463,7 @@ export {
|
|
|
8594
8463
|
lintIdToMessage,
|
|
8595
8464
|
macro,
|
|
8596
8465
|
makeCollector,
|
|
8466
|
+
path,
|
|
8597
8467
|
phaseOps,
|
|
8598
8468
|
reportTestReportToConsole,
|
|
8599
8469
|
resolveArgs,
|