tutuca 0.13.3 → 0.14.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 +572 -379
- package/dist/tutuca-dev.ext.js +605 -409
- package/dist/tutuca-dev.js +616 -420
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +588 -374
- package/dist/tutuca-extra.js +595 -381
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.ext.js +588 -374
- package/dist/tutuca.js +595 -381
- 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 +1 -1
- package/skill/tutuca/messages-and-intents.md +1 -1
- 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 +43 -28
- package/skill/tutuca-source/tutuca.ext.js +588 -374
package/dist/tutuca-dev.js
CHANGED
|
@@ -1243,8 +1243,8 @@ function hasProperty(obj, name) {
|
|
|
1243
1243
|
return name in Object(obj);
|
|
1244
1244
|
}
|
|
1245
1245
|
__name(hasProperty, "hasProperty");
|
|
1246
|
-
function parsePath(
|
|
1247
|
-
const str =
|
|
1246
|
+
function parsePath(path2) {
|
|
1247
|
+
const str = path2.replace(/([^\\])\[/g, "$1.[");
|
|
1248
1248
|
const parts = str.match(/(\\\.|[^.]+?)+/g);
|
|
1249
1249
|
return parts.map((value) => {
|
|
1250
1250
|
if (value === "constructor" || value === "__proto__" || value === "prototype") {
|
|
@@ -1282,8 +1282,8 @@ function internalGetPathValue(obj, parsed, pathDepth) {
|
|
|
1282
1282
|
return res;
|
|
1283
1283
|
}
|
|
1284
1284
|
__name(internalGetPathValue, "internalGetPathValue");
|
|
1285
|
-
function getPathInfo(obj,
|
|
1286
|
-
const parsed = parsePath(
|
|
1285
|
+
function getPathInfo(obj, path2) {
|
|
1286
|
+
const parsed = parsePath(path2);
|
|
1287
1287
|
const last = parsed[parsed.length - 1];
|
|
1288
1288
|
const info = {
|
|
1289
1289
|
parent: parsed.length > 1 ? internalGetPathValue(obj, parsed, parsed.length - 1) : obj,
|
|
@@ -4158,8 +4158,8 @@ function jestMatchers(chai, utils) {
|
|
|
4158
4158
|
expected
|
|
4159
4159
|
);
|
|
4160
4160
|
});
|
|
4161
|
-
m("toHaveProperty", function(
|
|
4162
|
-
const keys = Array.isArray(
|
|
4161
|
+
m("toHaveProperty", function(path2, ...rest) {
|
|
4162
|
+
const keys = Array.isArray(path2) ? path2 : String(path2).split(".");
|
|
4163
4163
|
let cur = this._obj;
|
|
4164
4164
|
let found = true;
|
|
4165
4165
|
for (const k of keys) {
|
|
@@ -4174,7 +4174,7 @@ function jestMatchers(chai, utils) {
|
|
|
4174
4174
|
pass,
|
|
4175
4175
|
"expected #{this} to have property #{exp}",
|
|
4176
4176
|
"expected #{this} not to have property #{exp}",
|
|
4177
|
-
|
|
4177
|
+
path2
|
|
4178
4178
|
);
|
|
4179
4179
|
});
|
|
4180
4180
|
m("toBeInstanceOf", function(ctor) {
|
|
@@ -4493,7 +4493,7 @@ function processResult(result, scope) {
|
|
|
4493
4493
|
}
|
|
4494
4494
|
return result !== NOTHING ? result : void 0;
|
|
4495
4495
|
}
|
|
4496
|
-
function finalize(rootScope, value,
|
|
4496
|
+
function finalize(rootScope, value, path2) {
|
|
4497
4497
|
if (isFrozen(value))
|
|
4498
4498
|
return value;
|
|
4499
4499
|
const useStrictIteration = rootScope.immer_.shouldUseStrictIteration();
|
|
@@ -4501,7 +4501,7 @@ function finalize(rootScope, value, path) {
|
|
|
4501
4501
|
if (!state) {
|
|
4502
4502
|
each(
|
|
4503
4503
|
value,
|
|
4504
|
-
(key, childValue) => finalizeProperty(rootScope, state, value, key, childValue,
|
|
4504
|
+
(key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path2),
|
|
4505
4505
|
useStrictIteration
|
|
4506
4506
|
);
|
|
4507
4507
|
return value;
|
|
@@ -4531,16 +4531,16 @@ function finalize(rootScope, value, path) {
|
|
|
4531
4531
|
result,
|
|
4532
4532
|
key,
|
|
4533
4533
|
childValue,
|
|
4534
|
-
|
|
4534
|
+
path2,
|
|
4535
4535
|
isSet2
|
|
4536
4536
|
),
|
|
4537
4537
|
useStrictIteration
|
|
4538
4538
|
);
|
|
4539
4539
|
maybeFreeze(rootScope, result, false);
|
|
4540
|
-
if (
|
|
4540
|
+
if (path2 && rootScope.patches_) {
|
|
4541
4541
|
getPlugin("Patches").generatePatches_(
|
|
4542
4542
|
state,
|
|
4543
|
-
|
|
4543
|
+
path2,
|
|
4544
4544
|
rootScope.patches_,
|
|
4545
4545
|
rootScope.inversePatches_
|
|
4546
4546
|
);
|
|
@@ -4562,9 +4562,9 @@ function finalizeProperty(rootScope, parentState, targetObject, prop, childValue
|
|
|
4562
4562
|
if (childValue === targetObject)
|
|
4563
4563
|
die(5);
|
|
4564
4564
|
if (isDraft(childValue)) {
|
|
4565
|
-
const
|
|
4565
|
+
const path2 = rootPath && parentState && parentState.type_ !== 3 && // Set objects are atomic since they have no keys.
|
|
4566
4566
|
!has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0;
|
|
4567
|
-
const res = finalize(rootScope, childValue,
|
|
4567
|
+
const res = finalize(rootScope, childValue, path2);
|
|
4568
4568
|
set2(targetObject, prop, res);
|
|
4569
4569
|
if (isDraft(res)) {
|
|
4570
4570
|
rootScope.canAutoFreeze_ = false;
|
|
@@ -4979,8 +4979,11 @@ var Step = class {
|
|
|
4979
4979
|
}
|
|
4980
4980
|
setDraftValue(_root, _v) {
|
|
4981
4981
|
}
|
|
4982
|
-
|
|
4983
|
-
|
|
4982
|
+
// Re-enter this step while rebuilding a stack. `renderPath` is the dispatch
|
|
4983
|
+
// position AFTER this step: a rebuilt frame must carry the same render path
|
|
4984
|
+
// the renderer had there, or the provides it publishes would be located wrong.
|
|
4985
|
+
enterFrame(stack, next, renderPath) {
|
|
4986
|
+
return stack.enter(next, {}, true, renderPath);
|
|
4984
4987
|
}
|
|
4985
4988
|
toAbstractPathStep() {
|
|
4986
4989
|
return this;
|
|
@@ -5005,8 +5008,8 @@ var BindStep = class _BindStep extends Step {
|
|
|
5005
5008
|
lookup(v, _dval) {
|
|
5006
5009
|
return v;
|
|
5007
5010
|
}
|
|
5008
|
-
enterFrame(stack, next) {
|
|
5009
|
-
return stack.enter(next, { ...this.binds }, false);
|
|
5011
|
+
enterFrame(stack, next, renderPath) {
|
|
5012
|
+
return stack.enter(next, { ...this.binds }, false, renderPath);
|
|
5010
5013
|
}
|
|
5011
5014
|
withIndex(i) {
|
|
5012
5015
|
return new _BindStep({ ...this.binds, key: i });
|
|
@@ -5023,9 +5026,9 @@ var ScopeBindStep = class _ScopeBindStep extends BindStep {
|
|
|
5023
5026
|
super(binds);
|
|
5024
5027
|
this.val = val;
|
|
5025
5028
|
}
|
|
5026
|
-
enterFrame(stack, next) {
|
|
5029
|
+
enterFrame(stack, next, renderPath) {
|
|
5027
5030
|
const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
|
|
5028
|
-
return stack.enter(next, { ...this.binds, ...dyn }, false);
|
|
5031
|
+
return stack.enter(next, { ...this.binds, ...dyn }, false, renderPath);
|
|
5029
5032
|
}
|
|
5030
5033
|
withIndex(i) {
|
|
5031
5034
|
return new _ScopeBindStep(this.val, { ...this.binds, key: i });
|
|
@@ -5068,8 +5071,8 @@ var SeqStep = class extends Step {
|
|
|
5068
5071
|
const seq = readKey(root, this.field, null);
|
|
5069
5072
|
if (seq != null) writeSeqKey(seq, this.key, v);
|
|
5070
5073
|
}
|
|
5071
|
-
enterFrame(stack, next) {
|
|
5072
|
-
return stack.enter(next, { key: this.key }, true);
|
|
5074
|
+
enterFrame(stack, next, renderPath) {
|
|
5075
|
+
return stack.enter(next, { key: this.key }, true, renderPath);
|
|
5073
5076
|
}
|
|
5074
5077
|
toKey() {
|
|
5075
5078
|
return { field: this.field, key: this.key };
|
|
@@ -5115,60 +5118,52 @@ var EachBindStep = class extends Step {
|
|
|
5115
5118
|
}
|
|
5116
5119
|
// Replay the renderer's per-item binds (key, value + any @enrich-with binds)
|
|
5117
5120
|
// so a rebuilt stack matches the one @each rendered with.
|
|
5118
|
-
enterFrame(stack, next) {
|
|
5119
|
-
return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false);
|
|
5121
|
+
enterFrame(stack, next, renderPath) {
|
|
5122
|
+
return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false, renderPath);
|
|
5120
5123
|
}
|
|
5121
5124
|
toAbstractPathStep() {
|
|
5122
5125
|
return null;
|
|
5123
5126
|
}
|
|
5124
5127
|
};
|
|
5125
5128
|
var EachRenderItStep = class extends SeqStep {
|
|
5126
|
-
enterFrame(stack, next) {
|
|
5127
|
-
return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
|
|
5129
|
+
enterFrame(stack, next, renderPath) {
|
|
5130
|
+
return stack.enter(next, { key: this.key, value: next }, false, renderPath).enter(next, {}, true, renderPath);
|
|
5128
5131
|
}
|
|
5129
5132
|
toAbstractPathStep() {
|
|
5130
5133
|
return new SeqStep(this.field, this.key);
|
|
5131
5134
|
}
|
|
5132
5135
|
};
|
|
5133
|
-
function
|
|
5134
|
-
|
|
5136
|
+
function stepToJson(step) {
|
|
5137
|
+
if (step instanceof SeqStep) return { f: step.field, k: step.key };
|
|
5138
|
+
if (step instanceof FieldStep) return { f: step.field };
|
|
5139
|
+
if (step instanceof SeqAccessStep) return { f: step.seqField, a: step.keyField };
|
|
5140
|
+
return null;
|
|
5135
5141
|
}
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
warnRawDynStep("lookup", this);
|
|
5149
|
-
return dval;
|
|
5150
|
-
}
|
|
5151
|
-
enterFrame(stack, _next) {
|
|
5152
|
-
warnRawDynStep("enterFrame", this);
|
|
5153
|
-
return stack;
|
|
5154
|
-
}
|
|
5155
|
-
};
|
|
5156
|
-
var DynEachStep = class extends DynStep {
|
|
5157
|
-
constructor(producerCompId, producerSteps, key) {
|
|
5158
|
-
super(producerCompId, producerSteps);
|
|
5159
|
-
this.key = key;
|
|
5142
|
+
function stepFromJson(j) {
|
|
5143
|
+
if (j == null || typeof j.f !== "string") return null;
|
|
5144
|
+
if (j.k !== void 0) return new SeqStep(j.f, j.k);
|
|
5145
|
+
if (j.a !== void 0) return new SeqAccessStep(j.f, j.a);
|
|
5146
|
+
return new FieldStep(j.f);
|
|
5147
|
+
}
|
|
5148
|
+
function pathToJson(path2) {
|
|
5149
|
+
const out = [];
|
|
5150
|
+
for (const step of path2.steps) {
|
|
5151
|
+
const j = stepToJson(step);
|
|
5152
|
+
if (j === null) return null;
|
|
5153
|
+
out.push(j);
|
|
5160
5154
|
}
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5155
|
+
return out;
|
|
5156
|
+
}
|
|
5157
|
+
function pathFromJson(j) {
|
|
5158
|
+
if (!Array.isArray(j)) return null;
|
|
5159
|
+
const steps = [];
|
|
5160
|
+
for (const item of j) {
|
|
5161
|
+
const step = stepFromJson(item);
|
|
5162
|
+
if (step === null) return null;
|
|
5163
|
+
steps.push(step);
|
|
5170
5164
|
}
|
|
5171
|
-
|
|
5165
|
+
return new Path(steps);
|
|
5166
|
+
}
|
|
5172
5167
|
var Path = class _Path {
|
|
5173
5168
|
constructor(steps = []) {
|
|
5174
5169
|
this.steps = steps;
|
|
@@ -5179,40 +5174,13 @@ var Path = class _Path {
|
|
|
5179
5174
|
popStep() {
|
|
5180
5175
|
return new _Path(this.steps.slice(0, -1));
|
|
5181
5176
|
}
|
|
5182
|
-
//
|
|
5183
|
-
//
|
|
5177
|
+
// Frame-only steps removed, one step per crossed component: `popStep` over the
|
|
5178
|
+
// result bubbles through every component.
|
|
5184
5179
|
compact() {
|
|
5185
5180
|
const out = [];
|
|
5186
5181
|
for (const step of this.steps) {
|
|
5187
5182
|
const s = step.toAbstractPathStep();
|
|
5188
|
-
if (s !== null)
|
|
5189
|
-
if (s !== step) s._originCid = step._originCid;
|
|
5190
|
-
out.push(s);
|
|
5191
|
-
}
|
|
5192
|
-
}
|
|
5193
|
-
return new _Path(out);
|
|
5194
|
-
}
|
|
5195
|
-
// The abstract path used to apply a transaction: every DynStep is teleported —
|
|
5196
|
-
// the steps interior to its producer..consumer span are dropped and the
|
|
5197
|
-
// producer's own path spliced in — so a mutation lands on the data's real
|
|
5198
|
-
// location. A path with no DynStep is returned unchanged.
|
|
5199
|
-
toTransactionPath() {
|
|
5200
|
-
let hasDyn = false;
|
|
5201
|
-
for (const step of this.steps)
|
|
5202
|
-
if (step instanceof DynStep) {
|
|
5203
|
-
hasDyn = true;
|
|
5204
|
-
break;
|
|
5205
|
-
}
|
|
5206
|
-
if (!hasDyn) return this;
|
|
5207
|
-
const out = [];
|
|
5208
|
-
for (const step of this.steps) {
|
|
5209
|
-
if (step instanceof DynStep) {
|
|
5210
|
-
while (out.length > 0 && step.interiorCids.has(out[out.length - 1]._originCid)) out.pop();
|
|
5211
|
-
for (const ts of step.teleportSteps()) {
|
|
5212
|
-
ts._originCid = step.producerCompId;
|
|
5213
|
-
out.push(ts);
|
|
5214
|
-
}
|
|
5215
|
-
} else out.push(step);
|
|
5183
|
+
if (s !== null) out.push(s);
|
|
5216
5184
|
}
|
|
5217
5185
|
return new _Path(out);
|
|
5218
5186
|
}
|
|
@@ -5220,7 +5188,6 @@ var Path = class _Path {
|
|
|
5220
5188
|
// key as it is *now* so a later lookup/setValue lands on the same item even if the
|
|
5221
5189
|
// keyField changed meanwhile (e.g. the selected tab moved while an intent was in
|
|
5222
5190
|
// flight). Returns a new Path with those steps replaced; `this` if nothing pinned.
|
|
5223
|
-
// Must be called on a transaction path (no DynSteps — call toTransactionPath first).
|
|
5224
5191
|
pinKeys(root) {
|
|
5225
5192
|
let curVal = root;
|
|
5226
5193
|
let out = null;
|
|
@@ -5243,8 +5210,8 @@ var Path = class _Path {
|
|
|
5243
5210
|
}
|
|
5244
5211
|
// The values entered along the path, root→leaf (root included): index 0 is `root`,
|
|
5245
5212
|
// the last entry is the leaf this path resolves to. Stops early at the first
|
|
5246
|
-
// unresolvable step.
|
|
5247
|
-
//
|
|
5213
|
+
// unresolvable step. Used to walk the component instances on a dispatch path
|
|
5214
|
+
// (filter via Components.getCompFor).
|
|
5248
5215
|
resolveChain(root) {
|
|
5249
5216
|
const out = [root];
|
|
5250
5217
|
let curVal = root;
|
|
@@ -5258,7 +5225,7 @@ var Path = class _Path {
|
|
|
5258
5225
|
// A flat `[{ field, key? }]` list of the addressing steps, skipping frame-only
|
|
5259
5226
|
// steps (binds). Generic path introspection so tooling (e.g. the storybook
|
|
5260
5227
|
// activity log) can identify which subtree a transaction touched without
|
|
5261
|
-
// depending on Step internals.
|
|
5228
|
+
// depending on Step internals.
|
|
5262
5229
|
toKeys() {
|
|
5263
5230
|
const out = [];
|
|
5264
5231
|
for (const step of this.steps) {
|
|
@@ -5279,62 +5246,147 @@ var Path = class _Path {
|
|
|
5279
5246
|
});
|
|
5280
5247
|
}
|
|
5281
5248
|
buildStack(stack) {
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5249
|
+
return walkItems(stack, this.steps, stack.renderPath ?? new DispatchPath(), this)?.[0] ?? null;
|
|
5250
|
+
}
|
|
5251
|
+
};
|
|
5252
|
+
function walkItems(stack, items, renderPath, path2) {
|
|
5253
|
+
let prev = stack.it;
|
|
5254
|
+
for (const step of items) {
|
|
5255
|
+
const next = step.lookup(prev, NONE);
|
|
5256
|
+
if (next === NONE) {
|
|
5257
|
+
console.warn("bad PathItem", { root: stack.it, step, path: path2 });
|
|
5258
|
+
return null;
|
|
5259
|
+
}
|
|
5260
|
+
renderPath = renderPath.pushItem(step);
|
|
5261
|
+
stack = step.enterFrame(stack, next, renderPath);
|
|
5262
|
+
prev = next;
|
|
5263
|
+
}
|
|
5264
|
+
return [stack, renderPath];
|
|
5265
|
+
}
|
|
5266
|
+
var EMPTY_PATH = new Path([]);
|
|
5267
|
+
var DispatchPath = class _DispatchPath {
|
|
5268
|
+
constructor(frames = [{ base: EMPTY_PATH, items: [] }]) {
|
|
5269
|
+
this.frames = frames;
|
|
5270
|
+
}
|
|
5271
|
+
// Plain addressing steps in one frame based at the root: what a caller means
|
|
5272
|
+
// by "this position" when it has no continuation of its own.
|
|
5273
|
+
static ofSteps(steps) {
|
|
5274
|
+
return new _DispatchPath([{ base: EMPTY_PATH, items: steps.slice() }]);
|
|
5275
|
+
}
|
|
5276
|
+
get top() {
|
|
5277
|
+
return this.frames[this.frames.length - 1];
|
|
5278
|
+
}
|
|
5279
|
+
_withTopItems(items) {
|
|
5280
|
+
const frames = this.frames.slice();
|
|
5281
|
+
frames[frames.length - 1] = { base: this.top.base, items };
|
|
5282
|
+
return new _DispatchPath(frames);
|
|
5283
|
+
}
|
|
5284
|
+
concat(steps) {
|
|
5285
|
+
if (this.frames.length === 0) return _DispatchPath.ofSteps(steps);
|
|
5286
|
+
return this._withTopItems(this.top.items.concat(steps));
|
|
5287
|
+
}
|
|
5288
|
+
pushItem(step) {
|
|
5289
|
+
return this.concat([step]);
|
|
5290
|
+
}
|
|
5291
|
+
pushFrame(base) {
|
|
5292
|
+
return new _DispatchPath(this.frames.concat({ base, items: [] }));
|
|
5293
|
+
}
|
|
5294
|
+
// Whether bubbling has anywhere left to go: another step in this frame, or a
|
|
5295
|
+
// visual caller underneath it.
|
|
5296
|
+
canPop() {
|
|
5297
|
+
const n = this.frames.length;
|
|
5298
|
+
return n > 1 || n === 1 && this.frames[0].items.length > 0;
|
|
5299
|
+
}
|
|
5300
|
+
isRoot() {
|
|
5301
|
+
return this.toTransactionPath().steps.length === 0;
|
|
5302
|
+
}
|
|
5303
|
+
// One component closer to the root. At the top of a frame that is popping back
|
|
5304
|
+
// to the visual caller, not to the producer's own parent — the caller is where
|
|
5305
|
+
// the `*name` was written, and where an unhandled message should keep going.
|
|
5306
|
+
popStep() {
|
|
5307
|
+
const n = this.frames.length;
|
|
5308
|
+
if (n === 0) return this;
|
|
5309
|
+
const top = this.frames[n - 1];
|
|
5310
|
+
if (top.items.length > 0) return this._withTopItems(top.items.slice(0, -1));
|
|
5311
|
+
if (n > 1) return new _DispatchPath(this.frames.slice(0, -1));
|
|
5312
|
+
return this;
|
|
5313
|
+
}
|
|
5314
|
+
// Drop frame-only steps inside every frame independently; a frame's base is
|
|
5315
|
+
// already addressing-only.
|
|
5316
|
+
compact() {
|
|
5317
|
+
return new _DispatchPath(
|
|
5318
|
+
this.frames.map(({ base, items }) => ({ base, items: new Path(items).compact().steps }))
|
|
5319
|
+
);
|
|
5320
|
+
}
|
|
5321
|
+
// A stable string for the ADDRESS this path denotes, for the render cache. The
|
|
5322
|
+
// same immutable value can sit at two places in the tree, and a subtree rendered
|
|
5323
|
+
// at one of them bakes that address in — the provides it publishes are located
|
|
5324
|
+
// there. Frame-only steps address nothing, so they are compacted out: two sites
|
|
5325
|
+
// that differ only in binds do render the same subtree.
|
|
5326
|
+
get addressKey() {
|
|
5327
|
+
this._addressKey ??= renderPathText(this.toTransactionPath().compact());
|
|
5328
|
+
return this._addressKey;
|
|
5329
|
+
}
|
|
5330
|
+
// The active transaction address: the top frame's absolute base followed by
|
|
5331
|
+
// its ordinary descendant steps. This is where a mutation lands.
|
|
5332
|
+
toTransactionPath() {
|
|
5333
|
+
const top = this.top;
|
|
5334
|
+
return top === void 0 ? EMPTY_PATH : top.base.concat(top.items);
|
|
5335
|
+
}
|
|
5336
|
+
// Rebuild the render stack this path was dispatched from. A frame with a base
|
|
5337
|
+
// re-enters at that absolute value first — replaying the resume a `*name`
|
|
5338
|
+
// render performed — and then walks its ordinary items.
|
|
5339
|
+
buildStack(stack) {
|
|
5340
|
+
let renderPath = new _DispatchPath();
|
|
5341
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
5342
|
+
const { base, items } = this.frames[i];
|
|
5343
|
+
if (i > 0 || base.steps.length > 0) {
|
|
5344
|
+
const baseValue = base.lookup(stack.root, NONE);
|
|
5345
|
+
if (baseValue === NONE) {
|
|
5346
|
+
console.warn("bad frame base", { base, path: this });
|
|
5347
|
+
return null;
|
|
5348
|
+
}
|
|
5349
|
+
renderPath = renderPath.pushFrame(base);
|
|
5350
|
+
stack = stack.enter(baseValue, {}, true, renderPath);
|
|
5288
5351
|
}
|
|
5289
|
-
|
|
5290
|
-
|
|
5352
|
+
const walked = walkItems(stack, items, renderPath, this);
|
|
5353
|
+
if (walked === null) return null;
|
|
5354
|
+
[stack, renderPath] = walked;
|
|
5291
5355
|
}
|
|
5292
5356
|
return stack;
|
|
5293
5357
|
}
|
|
5294
5358
|
static fromNodeAndEventName(node, eventName, rootNode, maxDepth, comps, stopOnNoEvent = true) {
|
|
5295
|
-
const
|
|
5296
|
-
const pendingDyns = [];
|
|
5359
|
+
const parts = [];
|
|
5297
5360
|
const bubbles = BUBBLING_EVENTS.has(eventName);
|
|
5298
5361
|
let depth = 0;
|
|
5299
5362
|
let eventIds = [];
|
|
5300
5363
|
let handlers = null;
|
|
5301
|
-
let
|
|
5364
|
+
let nodeRefs = [];
|
|
5302
5365
|
let isLeafComponent = true;
|
|
5303
5366
|
const crossComponent = (cidNum, vid) => {
|
|
5304
5367
|
const comp = comps.getComponentForId(cidNum);
|
|
5305
|
-
let
|
|
5368
|
+
let pushPart = true;
|
|
5306
5369
|
if (handlers === null && (isLeafComponent || bubbles)) {
|
|
5307
5370
|
handlers = findHandlers(comp, eventIds, vid, eventName);
|
|
5308
5371
|
if (handlers === null) {
|
|
5309
5372
|
if (isLeafComponent && stopOnNoEvent && !bubbles) return false;
|
|
5310
5373
|
} else if (!isLeafComponent) {
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
pushStep = false;
|
|
5374
|
+
parts.length = 0;
|
|
5375
|
+
pushPart = false;
|
|
5314
5376
|
}
|
|
5315
5377
|
}
|
|
5316
5378
|
isLeafComponent = false;
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
if (step) {
|
|
5321
|
-
step._originCid = cidNum;
|
|
5322
|
-
pathSteps.push(step);
|
|
5323
|
-
if (step instanceof DynStep) {
|
|
5324
|
-
step.interiorCids.add(cidNum);
|
|
5325
|
-
pendingDyns.push(step);
|
|
5326
|
-
}
|
|
5327
|
-
}
|
|
5379
|
+
if (pushPart) {
|
|
5380
|
+
const part = resolvePathPart(comp, nodeRefs, vid);
|
|
5381
|
+
if (part) parts.push(part);
|
|
5328
5382
|
}
|
|
5329
|
-
for (let i = pendingDyns.length - 1; i >= 0; i--)
|
|
5330
|
-
if (pendingDyns[i].producerCompId === cidNum) pendingDyns.splice(i, 1);
|
|
5331
5383
|
eventIds = [];
|
|
5332
|
-
|
|
5384
|
+
nodeRefs = [];
|
|
5333
5385
|
return true;
|
|
5334
5386
|
};
|
|
5335
5387
|
while (node && node !== rootNode && depth < maxDepth) {
|
|
5336
5388
|
if (node?.dataset) {
|
|
5337
|
-
const { eid, cid, vid } = node.dataset;
|
|
5389
|
+
const { eid, cid, vid, rp } = node.dataset;
|
|
5338
5390
|
if (eid !== void 0) eventIds.push(eid);
|
|
5339
5391
|
const metas = metaChain(node.previousSibling);
|
|
5340
5392
|
let sawComp = false;
|
|
@@ -5342,21 +5394,47 @@ var Path = class _Path {
|
|
|
5342
5394
|
if (m.$ === "Comp") {
|
|
5343
5395
|
sawComp = true;
|
|
5344
5396
|
if (!crossComponent(m.cid, m.vid)) return NO_EVENT_INFO;
|
|
5345
|
-
|
|
5397
|
+
nodeRefs.push({ nid: m.nid, base: pathFromJson(m.base) });
|
|
5346
5398
|
} else {
|
|
5347
|
-
|
|
5399
|
+
nodeRefs.push({ nid: m.nid, si: m.si, sk: m.sk });
|
|
5400
|
+
}
|
|
5401
|
+
}
|
|
5402
|
+
if (!sawComp && cid !== void 0) {
|
|
5403
|
+
if (!crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
5404
|
+
if (rp !== void 0) {
|
|
5405
|
+
const base = parseRenderPath(rp);
|
|
5406
|
+
if (base !== null) nodeRefs.push({ base });
|
|
5348
5407
|
}
|
|
5349
5408
|
}
|
|
5350
|
-
if (!sawComp && cid !== void 0 && !crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
5351
5409
|
}
|
|
5352
5410
|
depth += 1;
|
|
5353
5411
|
node = node.parentNode;
|
|
5354
5412
|
}
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5413
|
+
parts.reverse();
|
|
5414
|
+
let path2 = new _DispatchPath();
|
|
5415
|
+
for (const part of parts)
|
|
5416
|
+
path2 = part.base !== void 0 ? path2.pushFrame(part.base) : path2.pushItem(part.step);
|
|
5417
|
+
return [path2, handlers];
|
|
5358
5418
|
}
|
|
5359
5419
|
};
|
|
5420
|
+
function keyedPath(path2, key) {
|
|
5421
|
+
const steps = path2.steps;
|
|
5422
|
+
const last = steps[steps.length - 1];
|
|
5423
|
+
if (last instanceof SeqStep || last instanceof FieldStep)
|
|
5424
|
+
return new Path(steps.slice(0, -1).concat(new SeqStep(last.field, key)));
|
|
5425
|
+
return null;
|
|
5426
|
+
}
|
|
5427
|
+
function renderPathText(path2) {
|
|
5428
|
+
return JSON.stringify(pathToJson(path2));
|
|
5429
|
+
}
|
|
5430
|
+
function parseRenderPath(text) {
|
|
5431
|
+
try {
|
|
5432
|
+
return pathFromJson(JSON.parse(text));
|
|
5433
|
+
} catch (err) {
|
|
5434
|
+
console.warn("bad render path", err, text);
|
|
5435
|
+
return null;
|
|
5436
|
+
}
|
|
5437
|
+
}
|
|
5360
5438
|
function metaChain(n) {
|
|
5361
5439
|
const out = [];
|
|
5362
5440
|
while (n?.nodeType === 8 && n.textContent[0] === "§") {
|
|
@@ -5409,20 +5487,27 @@ var StepCtx = class _StepCtx {
|
|
|
5409
5487
|
return pi;
|
|
5410
5488
|
}
|
|
5411
5489
|
};
|
|
5412
|
-
function
|
|
5413
|
-
for (let i = 0; i <
|
|
5414
|
-
const
|
|
5415
|
-
|
|
5416
|
-
if (
|
|
5490
|
+
function resolvePathPart(comp, nodeRefs, vid) {
|
|
5491
|
+
for (let i = 0; i < nodeRefs.length; i++) {
|
|
5492
|
+
const ref = nodeRefs[i];
|
|
5493
|
+
if (ref.base != null) return { base: ref.base };
|
|
5494
|
+
if (ref.nid === void 0 || ref.nid === null) continue;
|
|
5495
|
+
const ctx = new StepCtx(comp, nodeRefs, i, vid);
|
|
5496
|
+
const step = ctx.resolveNode()?.toPathStep(ctx) ?? null;
|
|
5497
|
+
if (step !== null) return { step };
|
|
5417
5498
|
}
|
|
5418
5499
|
return null;
|
|
5419
5500
|
}
|
|
5420
5501
|
var NO_EVENT_INFO = [null, null];
|
|
5421
5502
|
var BUBBLING_EVENTS = /* @__PURE__ */ new Set(["drop"]);
|
|
5503
|
+
var path = () => new PathBuilder();
|
|
5422
5504
|
var PathBuilder = class {
|
|
5423
5505
|
constructor() {
|
|
5424
5506
|
this.pathChanges = [];
|
|
5425
5507
|
}
|
|
5508
|
+
toPath() {
|
|
5509
|
+
return new Path(this.pathChanges);
|
|
5510
|
+
}
|
|
5426
5511
|
add(pathChange) {
|
|
5427
5512
|
this.pathChanges.push(pathChange);
|
|
5428
5513
|
return this;
|
|
@@ -6579,13 +6664,16 @@ function h(tagName, properties, children, namespace) {
|
|
|
6579
6664
|
}
|
|
6580
6665
|
|
|
6581
6666
|
// src/anode.js
|
|
6582
|
-
function
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6667
|
+
function renderTarget(val, stack) {
|
|
6668
|
+
if (val instanceof DynVal) {
|
|
6669
|
+
const loc = stack.lookupDynamicLocated(val.name);
|
|
6670
|
+
if (loc?.path == null) return [loc?.value ?? null, stack.renderPath, null];
|
|
6671
|
+
return [loc.value, stack.renderPath.pushFrame(loc.path), loc.path];
|
|
6672
|
+
}
|
|
6673
|
+
const step = val.toPathItem?.() ?? null;
|
|
6674
|
+
if (step === null) return [val.eval(stack), stack.renderPath, null];
|
|
6675
|
+
const path2 = stack.renderPath.pushItem(step);
|
|
6676
|
+
return [val.eval(stack), path2, stack.pendingFrame ? path2.toTransactionPath() : null];
|
|
6589
6677
|
}
|
|
6590
6678
|
var BaseNode = class {
|
|
6591
6679
|
render(_stack, _rx) {
|
|
@@ -6907,33 +6995,31 @@ var RenderViewId = class extends ANode {
|
|
|
6907
6995
|
setDataAttr(_key, _val) {
|
|
6908
6996
|
}
|
|
6909
6997
|
};
|
|
6910
|
-
function dynRenderStep(comp, name, key) {
|
|
6911
|
-
const p = resolveDynProducer(comp, name);
|
|
6912
|
-
if (!p) return null;
|
|
6913
|
-
return key === void 0 ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
6914
|
-
}
|
|
6915
6998
|
var RenderNode = class extends RenderViewId {
|
|
6916
6999
|
render(stack, rx) {
|
|
6917
|
-
const
|
|
6918
|
-
|
|
7000
|
+
const [value, renderPath, base] = renderTarget(this.val, stack);
|
|
7001
|
+
const newStack = stack.enter(value, {}, true, renderPath, false);
|
|
7002
|
+
return rx.renderIt(newStack, this, "", this.evalViewName(stack), base);
|
|
6919
7003
|
}
|
|
7004
|
+
// A `*name` target contributes no step: the site recorded the absolute base it
|
|
7005
|
+
// resumed at, and event reconstruction turns that into a continuation frame.
|
|
6920
7006
|
toPathStep(ctx) {
|
|
6921
|
-
if (this.val instanceof DynVal) return
|
|
7007
|
+
if (this.val instanceof DynVal) return null;
|
|
6922
7008
|
return super.toPathStep(ctx);
|
|
6923
7009
|
}
|
|
6924
7010
|
};
|
|
6925
7011
|
var RenderItNode = class extends RenderViewId {
|
|
6926
7012
|
render(stack, rx) {
|
|
6927
|
-
const
|
|
6928
|
-
|
|
7013
|
+
const base = stack.pendingFrame ? stack.renderPath.toTransactionPath() : null;
|
|
7014
|
+
const newStack = stack.enter(stack.it, {}, true, stack.renderPath, false);
|
|
7015
|
+
return rx.renderIt(newStack, this, "", this.evalViewName(stack), base);
|
|
6929
7016
|
}
|
|
6930
7017
|
toPathStep(ctx) {
|
|
6931
7018
|
const next = ctx.next();
|
|
6932
7019
|
if (next === null) return null;
|
|
6933
7020
|
const nextNode = next.resolveNode();
|
|
6934
7021
|
if (nextNode instanceof EachNode && next.hasKey) {
|
|
6935
|
-
if (nextNode.val instanceof DynVal)
|
|
6936
|
-
return dynRenderStep(ctx.comp, nextNode.val.name, next.key);
|
|
7022
|
+
if (nextNode.val instanceof DynVal) return null;
|
|
6937
7023
|
return new EachRenderItStep(nextNode.val.name, next.key);
|
|
6938
7024
|
}
|
|
6939
7025
|
return null;
|
|
@@ -7035,11 +7121,19 @@ var EachNode = class extends WrapperNode {
|
|
|
7035
7121
|
this.iterInfo = new IterInfo(val, null, null, null);
|
|
7036
7122
|
}
|
|
7037
7123
|
render(stack, rx) {
|
|
7038
|
-
return rx.renderEachWhen(stack, this
|
|
7124
|
+
return rx.renderEachWhen(stack, this);
|
|
7039
7125
|
}
|
|
7040
7126
|
toPathStep(ctx) {
|
|
7041
7127
|
return ctx.hasKey ? new EachBindStep(this.iterInfo, ctx.key) : null;
|
|
7042
7128
|
}
|
|
7129
|
+
// Where one item lives, for the render path. `@each` re-binds `it` to the item
|
|
7130
|
+
// whether or not the body is a component, so the position moves either way and
|
|
7131
|
+
// the step has to address it — `.rows` iterated at `key` IS `rows[key]`.
|
|
7132
|
+
// Null for a dynamic sequence: `*rows` carries its own absolute path and enters
|
|
7133
|
+
// a continuation frame instead (see Renderer.renderEachWhen).
|
|
7134
|
+
itemStep(key) {
|
|
7135
|
+
return this.val instanceof FieldVal ? new SeqStep(this.val.name, key) : null;
|
|
7136
|
+
}
|
|
7043
7137
|
static register = true;
|
|
7044
7138
|
};
|
|
7045
7139
|
var IterInfo = class {
|
|
@@ -7378,6 +7472,215 @@ function collectAppClassesInSet(app) {
|
|
|
7378
7472
|
return classes;
|
|
7379
7473
|
}
|
|
7380
7474
|
|
|
7475
|
+
// src/stack.js
|
|
7476
|
+
var STOP = /* @__PURE__ */ Symbol("STOP");
|
|
7477
|
+
var NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
7478
|
+
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
7479
|
+
function routeLookup(route, lex, dyn) {
|
|
7480
|
+
for (let i = 0; i < route.length; i++) {
|
|
7481
|
+
const leg = route[i];
|
|
7482
|
+
if (leg === "dyn") {
|
|
7483
|
+
const v = dyn();
|
|
7484
|
+
if (v != null) return v;
|
|
7485
|
+
} else if (leg === "lex") {
|
|
7486
|
+
const v = lex();
|
|
7487
|
+
if (v != null) return v;
|
|
7488
|
+
} else {
|
|
7489
|
+
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
return null;
|
|
7493
|
+
}
|
|
7494
|
+
var isTypeName = (s) => {
|
|
7495
|
+
const c = s.charCodeAt(0);
|
|
7496
|
+
return c >= 65 && c <= 90;
|
|
7497
|
+
};
|
|
7498
|
+
function lookup(chain, name, dv = null) {
|
|
7499
|
+
let n = chain;
|
|
7500
|
+
while (n !== null) {
|
|
7501
|
+
const r = n[0].lookup(name);
|
|
7502
|
+
if (r === STOP) return dv;
|
|
7503
|
+
if (r !== NEXT) return r;
|
|
7504
|
+
n = n[1];
|
|
7505
|
+
}
|
|
7506
|
+
return dv;
|
|
7507
|
+
}
|
|
7508
|
+
var BindFrame = class {
|
|
7509
|
+
constructor(it, binds, isFrame) {
|
|
7510
|
+
this.it = it;
|
|
7511
|
+
this.binds = binds;
|
|
7512
|
+
this.isFrame = isFrame;
|
|
7513
|
+
}
|
|
7514
|
+
lookup(name) {
|
|
7515
|
+
const v = this.binds[name];
|
|
7516
|
+
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
7517
|
+
}
|
|
7518
|
+
};
|
|
7519
|
+
var DynFrame = class {
|
|
7520
|
+
constructor(binds, types) {
|
|
7521
|
+
this.binds = binds;
|
|
7522
|
+
this.types = types;
|
|
7523
|
+
}
|
|
7524
|
+
lookup(name) {
|
|
7525
|
+
const v = (isTypeName(name) ? this.types : this.binds)[name];
|
|
7526
|
+
return v === void 0 ? NEXT : v;
|
|
7527
|
+
}
|
|
7528
|
+
};
|
|
7529
|
+
function computeViewsId(views) {
|
|
7530
|
+
let s = "";
|
|
7531
|
+
let n = views;
|
|
7532
|
+
while (n !== null) {
|
|
7533
|
+
s += n[0];
|
|
7534
|
+
n = n[1];
|
|
7535
|
+
}
|
|
7536
|
+
return s === "main" ? "" : s;
|
|
7537
|
+
}
|
|
7538
|
+
var Stack = class _Stack {
|
|
7539
|
+
constructor(fields) {
|
|
7540
|
+
Object.assign(this, fields);
|
|
7541
|
+
}
|
|
7542
|
+
_with(patch) {
|
|
7543
|
+
return new _Stack({ ...this, ...patch });
|
|
7544
|
+
}
|
|
7545
|
+
// Evaluate every provide the entered component publishes and push them as one
|
|
7546
|
+
// dynBinds frame, keyed by NAME. A value is published together with the absolute
|
|
7547
|
+
// path it lives at: the same declaration is read as `*name` AND resumed at by
|
|
7548
|
+
// `<x render="*name">`, so a consumer needs both halves. Types go in the same
|
|
7549
|
+
// frame's other map. No-op with no provides.
|
|
7550
|
+
_pushProvides() {
|
|
7551
|
+
const comp = this.comps.getCompFor(this.it);
|
|
7552
|
+
if (comp == null) return this;
|
|
7553
|
+
const { provide, provideType } = comp;
|
|
7554
|
+
const binds = {};
|
|
7555
|
+
const types = {};
|
|
7556
|
+
let has2 = false;
|
|
7557
|
+
const base = this._publishBase();
|
|
7558
|
+
for (const k in provide) {
|
|
7559
|
+
const step = provide[k].val.toPathItem?.() ?? null;
|
|
7560
|
+
if (step === null) continue;
|
|
7561
|
+
const value = provide[k].val.eval(this);
|
|
7562
|
+
binds[k] = { value, path: base === null ? null : base.concat([step]) };
|
|
7563
|
+
has2 = true;
|
|
7564
|
+
}
|
|
7565
|
+
for (const k in provideType) {
|
|
7566
|
+
types[k] = provideType[k];
|
|
7567
|
+
has2 = true;
|
|
7568
|
+
}
|
|
7569
|
+
if (!has2) return this;
|
|
7570
|
+
return this._with({ dynBinds: [new DynFrame(binds, types), this.dynBinds] });
|
|
7571
|
+
}
|
|
7572
|
+
// The absolute address of the component being entered, or null when this
|
|
7573
|
+
// position cannot be written down as one. Frame-only steps carry bindings and
|
|
7574
|
+
// address nothing, so they are compacted away first; what is left is checked
|
|
7575
|
+
// against the value actually being rendered, because a scope CAN move the
|
|
7576
|
+
// render position without contributing an addressing step (a plain `@each`
|
|
7577
|
+
// body re-binds `it` to the item while its rebuild step is an identity).
|
|
7578
|
+
//
|
|
7579
|
+
// A null base still publishes the VALUE — `*name` reads it fine — but there is
|
|
7580
|
+
// nowhere to resume, so `<x render="*name">` renders nothing rather than
|
|
7581
|
+
// editing whatever happens to live at the address we guessed.
|
|
7582
|
+
_publishBase() {
|
|
7583
|
+
const base = this.renderPath.toTransactionPath().compact();
|
|
7584
|
+
return base.lookup(this.root, NOT_FOUND) === this.it ? base : null;
|
|
7585
|
+
}
|
|
7586
|
+
static root(comps, it, ctx = null) {
|
|
7587
|
+
return new _Stack({
|
|
7588
|
+
comps,
|
|
7589
|
+
root: it,
|
|
7590
|
+
it,
|
|
7591
|
+
binds: [new BindFrame(it, {}, true), null],
|
|
7592
|
+
dynBinds: [new DynFrame({}, {}), null],
|
|
7593
|
+
views: ["main", null],
|
|
7594
|
+
viewsId: "",
|
|
7595
|
+
renderPath: new DispatchPath(),
|
|
7596
|
+
pendingFrame: false,
|
|
7597
|
+
ctx
|
|
7598
|
+
})._pushProvides();
|
|
7599
|
+
}
|
|
7600
|
+
// `renderPath` defaults to this stack's own: an ordinary scope does not move.
|
|
7601
|
+
// `pendingFrame` clears on a component frame (which emits the base) and is
|
|
7602
|
+
// inherited by transparent scopes, which have to carry it to the next boundary.
|
|
7603
|
+
enter(it, bindings = {}, isFrame = true, renderPath = this.renderPath, pendingFrame = null) {
|
|
7604
|
+
const stack = this._with({
|
|
7605
|
+
it,
|
|
7606
|
+
binds: [new BindFrame(it, bindings, isFrame), this.binds],
|
|
7607
|
+
renderPath,
|
|
7608
|
+
pendingFrame: pendingFrame ?? (isFrame ? false : this.pendingFrame)
|
|
7609
|
+
});
|
|
7610
|
+
return isFrame ? stack._pushProvides() : stack;
|
|
7611
|
+
}
|
|
7612
|
+
pushViewName(name) {
|
|
7613
|
+
const views = [name, this.views];
|
|
7614
|
+
return this._with({ views, viewsId: computeViewsId(views) });
|
|
7615
|
+
}
|
|
7616
|
+
// Published types are stable per scope and would only churn the render cache, so
|
|
7617
|
+
// the cache key covers values alone.
|
|
7618
|
+
_pushDynBindValuesToArray(arr, comp) {
|
|
7619
|
+
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
7620
|
+
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
7621
|
+
}
|
|
7622
|
+
// `*name`: the nearest binding above (including this component's own provides,
|
|
7623
|
+
// pushed on entering it), else a path registered in the component's lexical
|
|
7624
|
+
// scope, else this component's declared default, else null.
|
|
7625
|
+
//
|
|
7626
|
+
// One chain walk and no producer resolution: a lookup names what it WANTS, so the
|
|
7627
|
+
// frame it wants is keyed by that name. The default belongs to the CONSUMER's
|
|
7628
|
+
// declaration and is evaluated against the consumer's stack, which is why it is
|
|
7629
|
+
// consulted only after the whole chain has missed.
|
|
7630
|
+
lookupDynamicLocated(name) {
|
|
7631
|
+
if (isTypeName(name)) return null;
|
|
7632
|
+
const v = lookup(this.dynBinds, name);
|
|
7633
|
+
if (v != null) return v;
|
|
7634
|
+
const comp = this.comps.getCompFor(this.it);
|
|
7635
|
+
if (comp == null) return null;
|
|
7636
|
+
const path2 = comp.scope?.lookupPath?.(name) ?? null;
|
|
7637
|
+
if (path2 !== null) {
|
|
7638
|
+
const value2 = path2.lookup(this.root, NOT_FOUND);
|
|
7639
|
+
if (value2 !== NOT_FOUND) return { value: value2, path: path2 };
|
|
7640
|
+
}
|
|
7641
|
+
const dval = comp.lookup[name]?.val ?? null;
|
|
7642
|
+
if (dval === null) return null;
|
|
7643
|
+
const step = dval.toPathItem?.() ?? null;
|
|
7644
|
+
const value = dval.eval(this);
|
|
7645
|
+
return step === null ? { value, path: null } : { value, path: this.renderPath.toTransactionPath().concat([step]) };
|
|
7646
|
+
}
|
|
7647
|
+
lookupDynamic(name) {
|
|
7648
|
+
if (isTypeName(name)) return lookup(this.dynBinds, name);
|
|
7649
|
+
return this.lookupDynamicLocated(name)?.value ?? null;
|
|
7650
|
+
}
|
|
7651
|
+
lookupBind(name) {
|
|
7652
|
+
return lookup(this.binds, name);
|
|
7653
|
+
}
|
|
7654
|
+
lookupFieldRaw(name) {
|
|
7655
|
+
return this.it[name] ?? null;
|
|
7656
|
+
}
|
|
7657
|
+
lookupMethod(name) {
|
|
7658
|
+
const fn = this.it[name];
|
|
7659
|
+
return fn instanceof Function ? fn.call(this.it) : null;
|
|
7660
|
+
}
|
|
7661
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
7662
|
+
// `e.<member>` handler args. Null outside a live event transaction.
|
|
7663
|
+
lookupEvent() {
|
|
7664
|
+
return this.ctx?.event ?? null;
|
|
7665
|
+
}
|
|
7666
|
+
lookupDragInfo() {
|
|
7667
|
+
return this.ctx?.dragInfo ?? null;
|
|
7668
|
+
}
|
|
7669
|
+
getHandlerFor(name, key) {
|
|
7670
|
+
return this.comps.getHandlerFor(this.it, name, key);
|
|
7671
|
+
}
|
|
7672
|
+
lookupBestView(views, defaultViewName) {
|
|
7673
|
+
let n = this.views;
|
|
7674
|
+
while (n !== null) {
|
|
7675
|
+
const view = views[n[0]];
|
|
7676
|
+
if (view !== void 0) return view;
|
|
7677
|
+
n = n[1];
|
|
7678
|
+
}
|
|
7679
|
+
return views[defaultViewName];
|
|
7680
|
+
}
|
|
7681
|
+
};
|
|
7682
|
+
var NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
7683
|
+
|
|
7381
7684
|
// src/components.js
|
|
7382
7685
|
var COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
7383
7686
|
var Components = class {
|
|
@@ -7416,12 +7719,14 @@ var ComponentStack = class _ComponentStack {
|
|
|
7416
7719
|
this.byName = {};
|
|
7417
7720
|
this.intentsByName = {};
|
|
7418
7721
|
this.macros = {};
|
|
7722
|
+
this.paths = {};
|
|
7419
7723
|
}
|
|
7420
7724
|
enter() {
|
|
7421
7725
|
return new _ComponentStack(this.comps, this);
|
|
7422
7726
|
}
|
|
7423
7727
|
registerComponents(comps, opts) {
|
|
7424
|
-
const { aliases: aliases2 = {} } = opts ?? {};
|
|
7728
|
+
const { aliases: aliases2 = {}, paths } = opts ?? {};
|
|
7729
|
+
if (paths) this.registerPaths(paths);
|
|
7425
7730
|
for (let i = 0; i < comps.length; i++) {
|
|
7426
7731
|
const Comp = comps[i];
|
|
7427
7732
|
Comp[COMPONENT].scope = this.enter();
|
|
@@ -7435,6 +7740,27 @@ var ComponentStack = class _ComponentStack {
|
|
|
7435
7740
|
else console.warn("alias", alias, "to inexistent component", aliases2[alias]);
|
|
7436
7741
|
}
|
|
7437
7742
|
}
|
|
7743
|
+
// Register lowercase names as absolute paths from the app state root. A
|
|
7744
|
+
// descendant that declares one in its `lookup` reads and renders `*name` without
|
|
7745
|
+
// anything above it publishing one — which is what makes a session, a theme or a
|
|
7746
|
+
// host-owned value available in its natural registration scope, instead of forcing
|
|
7747
|
+
// an application root whose only job is to `provide` it. Register on a nested
|
|
7748
|
+
// scope to narrow a name; nearest registration wins.
|
|
7749
|
+
//
|
|
7750
|
+
// Uppercase names are ignored: a component TYPE is what `lookupComponent` already
|
|
7751
|
+
// answers, and a type has no path.
|
|
7752
|
+
registerPaths(paths) {
|
|
7753
|
+
for (const name in paths) {
|
|
7754
|
+
if (isTypeName(name)) {
|
|
7755
|
+
console.warn("registerPaths: a type name has no path", name);
|
|
7756
|
+
continue;
|
|
7757
|
+
}
|
|
7758
|
+
this.paths[name] = paths[name].toPath?.() ?? paths[name];
|
|
7759
|
+
}
|
|
7760
|
+
}
|
|
7761
|
+
lookupPath(name) {
|
|
7762
|
+
return this.paths[name] ?? this.parent?.lookupPath(name) ?? null;
|
|
7763
|
+
}
|
|
7438
7764
|
registerMacros(macros) {
|
|
7439
7765
|
for (const key in macros) {
|
|
7440
7766
|
const lower = key.toLowerCase();
|
|
@@ -7466,17 +7792,16 @@ var ComponentStack = class _ComponentStack {
|
|
|
7466
7792
|
lookupComponent(name) {
|
|
7467
7793
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
7468
7794
|
}
|
|
7469
|
-
//
|
|
7470
|
-
// names
|
|
7471
|
-
//
|
|
7472
|
-
//
|
|
7473
|
-
//
|
|
7474
|
-
|
|
7795
|
+
// Whether anything in this scope chain provides `name`. Existence only: a lookup
|
|
7796
|
+
// names what it WANTS and takes whoever is nearest above it at render time, so
|
|
7797
|
+
// there is no producer to identify — several components may publish one name and
|
|
7798
|
+
// the live render ancestry decides. Used by the linter to tell a lookup that can
|
|
7799
|
+
// be satisfied from one that never will be.
|
|
7800
|
+
hasProvider(name) {
|
|
7475
7801
|
for (const compName in this.byName) {
|
|
7476
|
-
|
|
7477
|
-
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
7802
|
+
if (this.byName[compName].provide?.[name] !== void 0) return true;
|
|
7478
7803
|
}
|
|
7479
|
-
return this.parent?.
|
|
7804
|
+
return this.parent?.hasProvider(name) ?? false;
|
|
7480
7805
|
}
|
|
7481
7806
|
lookupMacro(name) {
|
|
7482
7807
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
@@ -7493,10 +7818,6 @@ var LookupInfo = class {
|
|
|
7493
7818
|
}
|
|
7494
7819
|
};
|
|
7495
7820
|
var isString = (v) => typeof v === "string";
|
|
7496
|
-
var isTypeName = (s) => {
|
|
7497
|
-
const c = s.charCodeAt(0);
|
|
7498
|
-
return c >= 65 && c <= 90;
|
|
7499
|
-
};
|
|
7500
7821
|
var _rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
7501
7822
|
var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
7502
7823
|
var _compId = 0;
|
|
@@ -9860,7 +10181,6 @@ var DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED";
|
|
|
9860
10181
|
var DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED";
|
|
9861
10182
|
var PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE";
|
|
9862
10183
|
var PROVIDE_TYPE_BAD_SHAPE = "PROVIDE_TYPE_BAD_SHAPE";
|
|
9863
|
-
var PROVIDE_NAME_COLLISION = "PROVIDE_NAME_COLLISION";
|
|
9864
10184
|
var LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE";
|
|
9865
10185
|
var LOOKUP_NO_PROVIDER = "LOOKUP_NO_PROVIDER";
|
|
9866
10186
|
var RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP";
|
|
@@ -9983,7 +10303,6 @@ function checkComponent(Comp, lx = new LintContext(), { wellKnownExtras = EMPTY_
|
|
|
9983
10303
|
checkFieldMethodNameCollisions(lx, Comp);
|
|
9984
10304
|
checkProvidesAreAddressable(lx, Comp);
|
|
9985
10305
|
checkProvidedTypes(lx, Comp);
|
|
9986
|
-
checkProvideNameCollisions(lx, Comp);
|
|
9987
10306
|
checkLookupShapes(lx, Comp);
|
|
9988
10307
|
checkLookupTypesResolve(lx, Comp);
|
|
9989
10308
|
checkLookupsHaveProviders(lx, Comp);
|
|
@@ -10667,19 +10986,6 @@ function checkProvidedTypes(lx, Comp) {
|
|
|
10667
10986
|
if (raw !== "self") lx.error(PROVIDE_TYPE_BAD_SHAPE, { name, value: raw });
|
|
10668
10987
|
}
|
|
10669
10988
|
}
|
|
10670
|
-
function checkProvideNameCollisions(lx, Comp) {
|
|
10671
|
-
const scope = Comp.scope;
|
|
10672
|
-
if (!scope) return;
|
|
10673
|
-
for (const name in Comp.provide) {
|
|
10674
|
-
for (let s = scope; s; s = s.parent) {
|
|
10675
|
-
for (const otherName in s.byName) {
|
|
10676
|
-
const Other = s.byName[otherName];
|
|
10677
|
-
if (Other !== Comp && Other.provide?.[name] !== void 0)
|
|
10678
|
-
lx.error(PROVIDE_NAME_COLLISION, { name, other: Other.name });
|
|
10679
|
-
}
|
|
10680
|
-
}
|
|
10681
|
-
}
|
|
10682
|
-
}
|
|
10683
10989
|
var KNOWN_LOOKUP_KEYS = /* @__PURE__ */ new Set(["name", "default"]);
|
|
10684
10990
|
function checkLookupShapes(lx, Comp) {
|
|
10685
10991
|
const raw = Comp._rawLookup;
|
|
@@ -10721,7 +11027,7 @@ function checkLookupsHaveProviders(lx, Comp) {
|
|
|
10721
11027
|
if (!scope) return;
|
|
10722
11028
|
for (const name in Comp.lookup) {
|
|
10723
11029
|
if (isTypeName2(name)) continue;
|
|
10724
|
-
if (scope.
|
|
11030
|
+
if (scope.hasProvider?.(name) || scope.lookupPath?.(name)) continue;
|
|
10725
11031
|
const info = { name, hasDefault: Comp.lookup[name].val != null };
|
|
10726
11032
|
if (info.hasDefault) lx.hint(LOOKUP_NO_PROVIDER, info);
|
|
10727
11033
|
else lx.error(LOOKUP_NO_PROVIDER, info);
|
|
@@ -11081,160 +11387,6 @@ Component.fromSpec = (opts) => {
|
|
|
11081
11387
|
};
|
|
11082
11388
|
var component = (opts) => Component.fromSpec(opts);
|
|
11083
11389
|
|
|
11084
|
-
// src/stack.js
|
|
11085
|
-
var STOP = /* @__PURE__ */ Symbol("STOP");
|
|
11086
|
-
var NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
11087
|
-
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
11088
|
-
function routeLookup(route, lex, dyn) {
|
|
11089
|
-
for (let i = 0; i < route.length; i++) {
|
|
11090
|
-
const leg = route[i];
|
|
11091
|
-
if (leg === "dyn") {
|
|
11092
|
-
const v = dyn();
|
|
11093
|
-
if (v != null) return v;
|
|
11094
|
-
} else if (leg === "lex") {
|
|
11095
|
-
const v = lex();
|
|
11096
|
-
if (v != null) return v;
|
|
11097
|
-
} else {
|
|
11098
|
-
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
11099
|
-
}
|
|
11100
|
-
}
|
|
11101
|
-
return null;
|
|
11102
|
-
}
|
|
11103
|
-
function lookup(chain, name, dv = null) {
|
|
11104
|
-
let n = chain;
|
|
11105
|
-
while (n !== null) {
|
|
11106
|
-
const r = n[0].lookup(name);
|
|
11107
|
-
if (r === STOP) return dv;
|
|
11108
|
-
if (r !== NEXT) return r;
|
|
11109
|
-
n = n[1];
|
|
11110
|
-
}
|
|
11111
|
-
return dv;
|
|
11112
|
-
}
|
|
11113
|
-
var BindFrame = class {
|
|
11114
|
-
constructor(it, binds, isFrame) {
|
|
11115
|
-
this.it = it;
|
|
11116
|
-
this.binds = binds;
|
|
11117
|
-
this.isFrame = isFrame;
|
|
11118
|
-
}
|
|
11119
|
-
lookup(name) {
|
|
11120
|
-
const v = this.binds[name];
|
|
11121
|
-
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
11122
|
-
}
|
|
11123
|
-
};
|
|
11124
|
-
var ObjectFrame = class {
|
|
11125
|
-
constructor(binds) {
|
|
11126
|
-
this.binds = binds;
|
|
11127
|
-
}
|
|
11128
|
-
lookup(key) {
|
|
11129
|
-
const v = this.binds[key];
|
|
11130
|
-
return v === void 0 ? NEXT : v;
|
|
11131
|
-
}
|
|
11132
|
-
};
|
|
11133
|
-
function computeViewsId(views) {
|
|
11134
|
-
let s = "";
|
|
11135
|
-
let n = views;
|
|
11136
|
-
while (n !== null) {
|
|
11137
|
-
s += n[0];
|
|
11138
|
-
n = n[1];
|
|
11139
|
-
}
|
|
11140
|
-
return s === "main" ? "" : s;
|
|
11141
|
-
}
|
|
11142
|
-
var Stack = class _Stack {
|
|
11143
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
11144
|
-
this.comps = comps;
|
|
11145
|
-
this.it = it;
|
|
11146
|
-
this.binds = binds;
|
|
11147
|
-
this.dynBinds = dynBinds;
|
|
11148
|
-
this.views = views;
|
|
11149
|
-
this.viewsId = viewsId;
|
|
11150
|
-
this.ctx = ctx;
|
|
11151
|
-
}
|
|
11152
|
-
// Evaluate every provide the entered component publishes and push them as one
|
|
11153
|
-
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
11154
|
-
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
11155
|
-
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
11156
|
-
_pushProvides() {
|
|
11157
|
-
const comp = this.comps.getCompFor(this.it);
|
|
11158
|
-
if (comp == null) return this;
|
|
11159
|
-
const { provide, provideType } = comp;
|
|
11160
|
-
const dynObj = {};
|
|
11161
|
-
let has2 = false;
|
|
11162
|
-
for (const k in provide) {
|
|
11163
|
-
dynObj[k] = provide[k].val.eval(this);
|
|
11164
|
-
has2 = true;
|
|
11165
|
-
}
|
|
11166
|
-
for (const k in provideType) {
|
|
11167
|
-
dynObj[k] = provideType[k];
|
|
11168
|
-
has2 = true;
|
|
11169
|
-
}
|
|
11170
|
-
if (!has2) return this;
|
|
11171
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
11172
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
11173
|
-
return new _Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
11174
|
-
}
|
|
11175
|
-
static root(comps, it, ctx) {
|
|
11176
|
-
const binds = [new BindFrame(it, {}, true), null];
|
|
11177
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
11178
|
-
const views = ["main", null];
|
|
11179
|
-
return new _Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
11180
|
-
}
|
|
11181
|
-
enter(it, bindings = {}, isFrame = true) {
|
|
11182
|
-
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
11183
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
11184
|
-
const stack = new _Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
11185
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
11186
|
-
}
|
|
11187
|
-
pushViewName(name) {
|
|
11188
|
-
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
11189
|
-
const newViews = [name, views];
|
|
11190
|
-
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
11191
|
-
}
|
|
11192
|
-
// Published types are stable per scope and would only churn the render cache, so
|
|
11193
|
-
// the cache key covers values alone.
|
|
11194
|
-
_pushDynBindValuesToArray(arr, comp) {
|
|
11195
|
-
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
11196
|
-
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
11197
|
-
}
|
|
11198
|
-
// `*name`: the nearest binding above (including this component's own provides,
|
|
11199
|
-
// pushed on entering it), else this component's declared default, else null.
|
|
11200
|
-
lookupDynamic(name) {
|
|
11201
|
-
const v = lookup(this.dynBinds, name);
|
|
11202
|
-
if (v != null) return v;
|
|
11203
|
-
const comp = this.comps.getCompFor(this.it);
|
|
11204
|
-
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
11205
|
-
}
|
|
11206
|
-
lookupBind(name) {
|
|
11207
|
-
return lookup(this.binds, name);
|
|
11208
|
-
}
|
|
11209
|
-
lookupFieldRaw(name) {
|
|
11210
|
-
return this.it[name] ?? null;
|
|
11211
|
-
}
|
|
11212
|
-
lookupMethod(name) {
|
|
11213
|
-
const fn = this.it[name];
|
|
11214
|
-
return fn instanceof Function ? fn.call(this.it) : null;
|
|
11215
|
-
}
|
|
11216
|
-
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
11217
|
-
// `e.<member>` handler args. Null outside a live event transaction.
|
|
11218
|
-
lookupEvent() {
|
|
11219
|
-
return this.ctx?.event ?? null;
|
|
11220
|
-
}
|
|
11221
|
-
lookupDragInfo() {
|
|
11222
|
-
return this.ctx?.dragInfo ?? null;
|
|
11223
|
-
}
|
|
11224
|
-
getHandlerFor(name, key) {
|
|
11225
|
-
return this.comps.getHandlerFor(this.it, name, key);
|
|
11226
|
-
}
|
|
11227
|
-
lookupBestView(views, defaultViewName) {
|
|
11228
|
-
let n = this.views;
|
|
11229
|
-
while (n !== null) {
|
|
11230
|
-
const view = views[n[0]];
|
|
11231
|
-
if (view !== void 0) return view;
|
|
11232
|
-
n = n[1];
|
|
11233
|
-
}
|
|
11234
|
-
return views[defaultViewName];
|
|
11235
|
-
}
|
|
11236
|
-
};
|
|
11237
|
-
|
|
11238
11390
|
// src/transactor.js
|
|
11239
11391
|
var State2 = class {
|
|
11240
11392
|
constructor(val) {
|
|
@@ -11310,9 +11462,9 @@ var Transactor = class {
|
|
|
11310
11462
|
// `.a[.selId]` render target reconstructed from a DOM event) against the root the
|
|
11311
11463
|
// handler read, so pathKeys carries concrete keys instead of dropping the dynamic
|
|
11312
11464
|
// step. No-op when nobody is observing.
|
|
11313
|
-
_emitRecord(root, { kind, name, args, path, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
11465
|
+
_emitRecord(root, { kind, name, args, path: path2, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
11314
11466
|
if (this._observers.length === 0) return;
|
|
11315
|
-
const pinned =
|
|
11467
|
+
const pinned = path2.pinKeys(root);
|
|
11316
11468
|
this._emit({
|
|
11317
11469
|
kind,
|
|
11318
11470
|
name,
|
|
@@ -11363,18 +11515,20 @@ var Transactor = class {
|
|
|
11363
11515
|
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
11364
11516
|
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
11365
11517
|
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
11366
|
-
pushSend(
|
|
11367
|
-
const t = new SendEvent(
|
|
11368
|
-
t.
|
|
11518
|
+
pushSend(path2, name, args = [], parent = null, origin = null, txnPath = null) {
|
|
11519
|
+
const t = new SendEvent(path2, this, name, args, parent);
|
|
11520
|
+
t.txnPath = txnPath;
|
|
11521
|
+
t.origin = origin;
|
|
11522
|
+
t.originPinned = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
11369
11523
|
this.pushTransaction(t);
|
|
11370
11524
|
return this._link(t, parent);
|
|
11371
11525
|
}
|
|
11372
11526
|
// Raise an intent: a job the sender did not address, walked along a route until
|
|
11373
11527
|
// something answers. `opts.route` is a list of legs (see DEFAULT_ROUTE) and
|
|
11374
11528
|
// `opts.livePath` opts out of pinning the answer's destination keys.
|
|
11375
|
-
pushIntent(
|
|
11529
|
+
pushIntent(path2, name, args = [], opts = {}, parent = null) {
|
|
11376
11530
|
const release = parent ? parent.completion.track() : null;
|
|
11377
|
-
const walk = new IntentWalk(this,
|
|
11531
|
+
const walk = new IntentWalk(this, path2, name, args, opts, parent, release);
|
|
11378
11532
|
walk.advance();
|
|
11379
11533
|
return walk;
|
|
11380
11534
|
}
|
|
@@ -11408,16 +11562,17 @@ var Transactor = class {
|
|
|
11408
11562
|
transaction._completion?.releaseSelf();
|
|
11409
11563
|
}
|
|
11410
11564
|
}
|
|
11411
|
-
transactInputNow(
|
|
11412
|
-
this.transact(new InputEvent(
|
|
11565
|
+
transactInputNow(path2, event, eventHandler, dragInfo) {
|
|
11566
|
+
this.transact(new InputEvent(path2, event, eventHandler, this, dragInfo));
|
|
11413
11567
|
}
|
|
11414
11568
|
};
|
|
11415
11569
|
function nullHandler() {
|
|
11416
11570
|
return this;
|
|
11417
11571
|
}
|
|
11418
11572
|
var Transaction = class {
|
|
11419
|
-
constructor(
|
|
11420
|
-
this.path =
|
|
11573
|
+
constructor(path2, transactor, parentTransaction = null) {
|
|
11574
|
+
this.path = path2;
|
|
11575
|
+
this.txnPath = null;
|
|
11421
11576
|
this.transactor = transactor;
|
|
11422
11577
|
this.parentTransaction = parentTransaction;
|
|
11423
11578
|
this._completion = null;
|
|
@@ -11466,9 +11621,11 @@ var Transaction = class {
|
|
|
11466
11621
|
getHandlerAndArgs(_root, _instance, _comps) {
|
|
11467
11622
|
return null;
|
|
11468
11623
|
}
|
|
11469
|
-
// The path used to apply the mutation
|
|
11470
|
-
//
|
|
11624
|
+
// The path used to apply the mutation: the ACTIVE frame of the dispatch path, so
|
|
11625
|
+
// an event inside a `<x render="*name">` subtree updates the value where it
|
|
11626
|
+
// really lives (the dispatch `this.path` keeps the visual callers, for bubbling).
|
|
11471
11627
|
getTransactionPath() {
|
|
11628
|
+
if (this.txnPath !== null) return this.txnPath;
|
|
11472
11629
|
return this.path.toTransactionPath().compact();
|
|
11473
11630
|
}
|
|
11474
11631
|
run(curRoot, comps) {
|
|
@@ -11486,15 +11643,16 @@ var Transaction = class {
|
|
|
11486
11643
|
}
|
|
11487
11644
|
};
|
|
11488
11645
|
var InputEvent = class extends Transaction {
|
|
11489
|
-
constructor(
|
|
11490
|
-
super(
|
|
11646
|
+
constructor(path2, e, handler, transactor, dragInfo) {
|
|
11647
|
+
super(path2, transactor);
|
|
11491
11648
|
this.e = e;
|
|
11492
11649
|
this.handler = handler;
|
|
11493
11650
|
this.dragInfo = dragInfo;
|
|
11494
11651
|
this._dispatchPath = null;
|
|
11495
11652
|
}
|
|
11496
|
-
// Frame steps removed,
|
|
11497
|
-
//
|
|
11653
|
+
// Frame-only steps removed, one step per crossed component kept — inside every
|
|
11654
|
+
// continuation frame independently, so bubbling it visits every component and
|
|
11655
|
+
// then returns to the caller that wrote the `*name`.
|
|
11498
11656
|
get dispatchPath() {
|
|
11499
11657
|
this._dispatchPath ??= this.path.compact();
|
|
11500
11658
|
return this._dispatchPath;
|
|
@@ -11529,11 +11687,11 @@ var InputEvent = class extends Transaction {
|
|
|
11529
11687
|
this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
|
|
11530
11688
|
}
|
|
11531
11689
|
getHandlerAndArgs(root, _instance, comps) {
|
|
11532
|
-
const stack = this.path.
|
|
11690
|
+
const stack = this.path.buildStack(Stack.root(comps, root, this));
|
|
11533
11691
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
11534
11692
|
this._handlerArgs = [...args];
|
|
11535
|
-
const
|
|
11536
|
-
args.push(new EventContext(
|
|
11693
|
+
const path2 = this.dispatchPath;
|
|
11694
|
+
args.push(new EventContext(path2, this.transactor, this));
|
|
11537
11695
|
return [handler, args];
|
|
11538
11696
|
}
|
|
11539
11697
|
// The dispatched DOM event, read only through `e.<member>` handler args
|
|
@@ -11544,11 +11702,11 @@ var InputEvent = class extends Transaction {
|
|
|
11544
11702
|
}
|
|
11545
11703
|
};
|
|
11546
11704
|
var NameArgsTransaction = class extends Transaction {
|
|
11547
|
-
constructor(
|
|
11548
|
-
super(
|
|
11705
|
+
constructor(path2, transactor, name, args, parentTransaction) {
|
|
11706
|
+
super(path2, transactor, parentTransaction);
|
|
11549
11707
|
this.name = name;
|
|
11550
11708
|
this.args = args;
|
|
11551
|
-
this.targetPath =
|
|
11709
|
+
this.targetPath = path2;
|
|
11552
11710
|
}
|
|
11553
11711
|
handlerProp = null;
|
|
11554
11712
|
// NameArgs verbs map their handler bucket straight to the observed kind:
|
|
@@ -11605,8 +11763,8 @@ var SendEvent = class extends NameArgsTransaction {
|
|
|
11605
11763
|
};
|
|
11606
11764
|
var IntentEvent = class extends NameArgsTransaction {
|
|
11607
11765
|
handlerProp = "intent";
|
|
11608
|
-
constructor(
|
|
11609
|
-
super(
|
|
11766
|
+
constructor(path2, transactor, walk) {
|
|
11767
|
+
super(path2, transactor, walk.name, walk.args, walk.parent);
|
|
11610
11768
|
this.walk = walk;
|
|
11611
11769
|
this.targetPath = walk.origin;
|
|
11612
11770
|
}
|
|
@@ -11633,17 +11791,17 @@ var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
|
|
|
11633
11791
|
var REFUSAL_RING_CAP = 200;
|
|
11634
11792
|
var INTENT_DEPTH = 64;
|
|
11635
11793
|
var IntentWalk = class {
|
|
11636
|
-
constructor(transactor,
|
|
11794
|
+
constructor(transactor, path2, name, args, opts, parent, release) {
|
|
11637
11795
|
this.transactor = transactor;
|
|
11638
11796
|
this.name = name;
|
|
11639
11797
|
this.args = args;
|
|
11640
11798
|
this.route = opts?.route ?? DEFAULT_ROUTE;
|
|
11641
11799
|
this.parent = parent;
|
|
11642
11800
|
this.release = release;
|
|
11643
|
-
this.origin =
|
|
11644
|
-
this.answerPath = opts?.livePath ? null :
|
|
11801
|
+
this.origin = path2;
|
|
11802
|
+
this.answerPath = opts?.livePath ? null : path2.toTransactionPath().pinKeys(transactor.state.val);
|
|
11645
11803
|
this.legIndex = 0;
|
|
11646
|
-
this.dynAt =
|
|
11804
|
+
this.dynAt = path2;
|
|
11647
11805
|
this.hops = 0;
|
|
11648
11806
|
this.ended = false;
|
|
11649
11807
|
}
|
|
@@ -11655,7 +11813,7 @@ var IntentWalk = class {
|
|
|
11655
11813
|
while (this.legIndex < this.route.length) {
|
|
11656
11814
|
const leg = this.route[this.legIndex];
|
|
11657
11815
|
if (leg === "dyn") {
|
|
11658
|
-
if (this.dynAt.
|
|
11816
|
+
if (!this.dynAt.canPop()) {
|
|
11659
11817
|
this.legIndex++;
|
|
11660
11818
|
continue;
|
|
11661
11819
|
}
|
|
@@ -11752,8 +11910,8 @@ var IntentWalk = class {
|
|
|
11752
11910
|
if (this.ended) return;
|
|
11753
11911
|
this.ended = true;
|
|
11754
11912
|
if (name === null) return this.release?.();
|
|
11755
|
-
const
|
|
11756
|
-
|
|
11913
|
+
const t = new SendEvent(this.origin, this.transactor, name, args, this.parent);
|
|
11914
|
+
t.txnPath = this.answerPath;
|
|
11757
11915
|
t._isAnswer = true;
|
|
11758
11916
|
this.transactor.pushTransaction(t);
|
|
11759
11917
|
if (this.release) t.completion.whenSubtreeSettled().then(this.release);
|
|
@@ -11819,8 +11977,8 @@ var Completion = class {
|
|
|
11819
11977
|
}
|
|
11820
11978
|
};
|
|
11821
11979
|
var Dispatcher = class {
|
|
11822
|
-
constructor(
|
|
11823
|
-
this.path =
|
|
11980
|
+
constructor(path2, transactor, parentTransaction, root = transactor.state.val) {
|
|
11981
|
+
this.path = path2;
|
|
11824
11982
|
this.transactor = transactor;
|
|
11825
11983
|
this.parent = parentTransaction;
|
|
11826
11984
|
this.root = root;
|
|
@@ -11848,7 +12006,9 @@ var Dispatcher = class {
|
|
|
11848
12006
|
// replayed; provides are pushed on every component frame either way, so a provide
|
|
11849
12007
|
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
11850
12008
|
_stack() {
|
|
11851
|
-
this._stackMemo ??= this.path.
|
|
12009
|
+
this._stackMemo ??= this.path.buildStack(
|
|
12010
|
+
Stack.root(this.transactor.comps, this.root, this.parent)
|
|
12011
|
+
);
|
|
11852
12012
|
return this._stackMemo;
|
|
11853
12013
|
}
|
|
11854
12014
|
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
@@ -11862,14 +12022,19 @@ var Dispatcher = class {
|
|
|
11862
12022
|
);
|
|
11863
12023
|
}
|
|
11864
12024
|
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
11865
|
-
// running, which is the leaf of this ctx's path.
|
|
12025
|
+
// running, which is the leaf of this ctx's path. A type name resolves to the
|
|
12026
|
+
// component registered under it; a value name to a path registered under it
|
|
12027
|
+
// (see ComponentStack.registerPaths), read against the current root.
|
|
11866
12028
|
_lookupLex(name) {
|
|
11867
12029
|
let Comp = null;
|
|
11868
12030
|
this.walkPath((c) => {
|
|
11869
12031
|
Comp = c;
|
|
11870
12032
|
return false;
|
|
11871
12033
|
});
|
|
11872
|
-
|
|
12034
|
+
const scope = Comp?.scope;
|
|
12035
|
+
if (scope == null) return null;
|
|
12036
|
+
if (isTypeName(name)) return scope.lookupComponent(name) ?? null;
|
|
12037
|
+
return scope.lookupPath(name)?.lookup(this.root) ?? null;
|
|
11873
12038
|
}
|
|
11874
12039
|
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
11875
12040
|
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
@@ -11891,8 +12056,8 @@ var Dispatcher = class {
|
|
|
11891
12056
|
send(name, args) {
|
|
11892
12057
|
return this.sendAtPath(this.path, name, args);
|
|
11893
12058
|
}
|
|
11894
|
-
sendAtPath(
|
|
11895
|
-
return this.transactor.pushSend(
|
|
12059
|
+
sendAtPath(path2, name, args) {
|
|
12060
|
+
return this.transactor.pushSend(path2, name, args, this.parent, this.path);
|
|
11896
12061
|
}
|
|
11897
12062
|
// An intent is ROUTED: it names a job and walks until something answers. The verb
|
|
11898
12063
|
// does not decide which scope answers — `opts.route` does, written here at the call
|
|
@@ -11900,8 +12065,8 @@ var Dispatcher = class {
|
|
|
11900
12065
|
intent(name, args, opts) {
|
|
11901
12066
|
return this.intentAtPath(this.path, name, args, opts);
|
|
11902
12067
|
}
|
|
11903
|
-
intentAtPath(
|
|
11904
|
-
return this.transactor.pushIntent(
|
|
12068
|
+
intentAtPath(path2, name, args, opts) {
|
|
12069
|
+
return this.transactor.pushIntent(path2, name, args, opts, this.parent);
|
|
11905
12070
|
}
|
|
11906
12071
|
};
|
|
11907
12072
|
var EventContext = class extends Dispatcher {
|
|
@@ -11930,7 +12095,14 @@ var EventContext = class extends Dispatcher {
|
|
|
11930
12095
|
this.transactor.refuse("NO_SENDER", { name });
|
|
11931
12096
|
return null;
|
|
11932
12097
|
}
|
|
11933
|
-
return this.
|
|
12098
|
+
return this.transactor.pushSend(
|
|
12099
|
+
origin,
|
|
12100
|
+
name,
|
|
12101
|
+
args,
|
|
12102
|
+
this.parent,
|
|
12103
|
+
this.path,
|
|
12104
|
+
this.parent.originPinned
|
|
12105
|
+
);
|
|
11934
12106
|
}
|
|
11935
12107
|
// End the walk answering nothing — "served, and no answer".
|
|
11936
12108
|
stop() {
|
|
@@ -11962,13 +12134,13 @@ var PathChanges = class extends PathBuilder {
|
|
|
11962
12134
|
}
|
|
11963
12135
|
};
|
|
11964
12136
|
function rootDispatcher(transactor) {
|
|
11965
|
-
return new Dispatcher(new
|
|
12137
|
+
return new Dispatcher(new DispatchPath(), transactor, null);
|
|
11966
12138
|
}
|
|
11967
12139
|
|
|
11968
12140
|
// tools/core/results.js
|
|
11969
12141
|
var ModuleInfo = class {
|
|
11970
|
-
constructor({ path = null, present = /* @__PURE__ */ new Set(), counts = {}, warnings = [] }) {
|
|
11971
|
-
this.path =
|
|
12142
|
+
constructor({ path: path2 = null, present = /* @__PURE__ */ new Set(), counts = {}, warnings = [] }) {
|
|
12143
|
+
this.path = path2;
|
|
11972
12144
|
this.present = present;
|
|
11973
12145
|
this.counts = counts;
|
|
11974
12146
|
this.warnings = warnings;
|
|
@@ -12078,8 +12250,8 @@ var DescribeResult = class {
|
|
|
12078
12250
|
}
|
|
12079
12251
|
};
|
|
12080
12252
|
var ModuleTestReport = class {
|
|
12081
|
-
constructor({ path = null, suites = [], counts = { pass: 0, fail: 0, skip: 0, total: 0 } }) {
|
|
12082
|
-
this.path =
|
|
12253
|
+
constructor({ path: path2 = null, suites = [], counts = { pass: 0, fail: 0, skip: 0, total: 0 } }) {
|
|
12254
|
+
this.path = path2;
|
|
12083
12255
|
this.suites = suites;
|
|
12084
12256
|
this.counts = counts;
|
|
12085
12257
|
}
|
|
@@ -12122,8 +12294,8 @@ var Test = class {
|
|
|
12122
12294
|
}
|
|
12123
12295
|
};
|
|
12124
12296
|
var ModuleTests = class {
|
|
12125
|
-
constructor({ path = null, suites = [] } = {}) {
|
|
12126
|
-
this.path =
|
|
12297
|
+
constructor({ path: path2 = null, suites = [] } = {}) {
|
|
12298
|
+
this.path = path2;
|
|
12127
12299
|
this.suites = suites;
|
|
12128
12300
|
}
|
|
12129
12301
|
};
|
|
@@ -12145,8 +12317,8 @@ function titleFromArg(arg) {
|
|
|
12145
12317
|
if (typeof arg === "function") return arg.name || "(anonymous)";
|
|
12146
12318
|
return String(arg);
|
|
12147
12319
|
}
|
|
12148
|
-
function makeCollector({ path = null, components = [] } = {}) {
|
|
12149
|
-
const moduleTests = new ModuleTests({ path, suites: [] });
|
|
12320
|
+
function makeCollector({ path: path2 = null, components = [] } = {}) {
|
|
12321
|
+
const moduleTests = new ModuleTests({ path: path2, suites: [] });
|
|
12150
12322
|
const stack = [];
|
|
12151
12323
|
function describe(...args) {
|
|
12152
12324
|
let head;
|
|
@@ -12247,7 +12419,7 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
12247
12419
|
val
|
|
12248
12420
|
);
|
|
12249
12421
|
});
|
|
12250
|
-
dispatchPhase(rootDispatcher(transactor), new
|
|
12422
|
+
dispatchPhase(rootDispatcher(transactor), new DispatchPath(), phase, value);
|
|
12251
12423
|
await transactor.settle();
|
|
12252
12424
|
return transactor.state.val;
|
|
12253
12425
|
}
|
|
@@ -12257,7 +12429,7 @@ async function drive(cfg, value, phase, opts = {}) {
|
|
|
12257
12429
|
async function runTests({
|
|
12258
12430
|
getTests,
|
|
12259
12431
|
components = [],
|
|
12260
|
-
path = null,
|
|
12432
|
+
path: path2 = null,
|
|
12261
12433
|
expect: expect2,
|
|
12262
12434
|
name = null,
|
|
12263
12435
|
grep = null,
|
|
@@ -12268,13 +12440,13 @@ async function runTests({
|
|
|
12268
12440
|
const counts = { pass: 0, fail: 0, skip: 0, total: 0 };
|
|
12269
12441
|
if (typeof getTests !== "function") {
|
|
12270
12442
|
return new TestReport({
|
|
12271
|
-
modules: [new ModuleTestReport({ path, suites: [], counts })]
|
|
12443
|
+
modules: [new ModuleTestReport({ path: path2, suites: [], counts })]
|
|
12272
12444
|
});
|
|
12273
12445
|
}
|
|
12274
12446
|
if (typeof expect2 !== "function") {
|
|
12275
12447
|
throw new Error("runTests: expect must be provided (e.g. chai's expect)");
|
|
12276
12448
|
}
|
|
12277
|
-
const { describe, test: test3, moduleTests } = makeCollector({ path, components });
|
|
12449
|
+
const { describe, test: test3, moduleTests } = makeCollector({ path: path2, components });
|
|
12278
12450
|
let _stack = null;
|
|
12279
12451
|
const getStack = () => _stack ??= buildStack({ components, macros, intentHandlers });
|
|
12280
12452
|
const driveLocal = (value, phase, opts = {}) => driveStack(getStack(), value, phase, opts);
|
|
@@ -12337,7 +12509,7 @@ async function runTests({
|
|
|
12337
12509
|
if (r !== null) suiteResults.push(r);
|
|
12338
12510
|
}
|
|
12339
12511
|
return new TestReport({
|
|
12340
|
-
modules: [new ModuleTestReport({ path, suites: suiteResults, counts })]
|
|
12512
|
+
modules: [new ModuleTestReport({ path: path2, suites: suiteResults, counts })]
|
|
12341
12513
|
});
|
|
12342
12514
|
}
|
|
12343
12515
|
|
|
@@ -12506,15 +12678,13 @@ function lintIdToMessage(id, info) {
|
|
|
12506
12678
|
case "DYN_ALIAS_NOT_REFERENCED":
|
|
12507
12679
|
return `Lookup '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
|
|
12508
12680
|
case "PROVIDE_NOT_ADDRESSABLE":
|
|
12509
|
-
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a
|
|
12681
|
+
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`;
|
|
12510
12682
|
case "LOOKUP_BAD_SHAPE":
|
|
12511
12683
|
return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
|
|
12512
12684
|
case "LOOKUP_NO_PROVIDER":
|
|
12513
|
-
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`;
|
|
12685
|
+
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`;
|
|
12514
12686
|
case "PROVIDE_TYPE_BAD_SHAPE":
|
|
12515
12687
|
return `Provide '${info.name}' starts uppercase, so it publishes a component type — its value must be 'self', not '${info.value}'`;
|
|
12516
|
-
case "PROVIDE_NAME_COLLISION":
|
|
12517
|
-
return `Provide '${info.name}' is also provided by '${info.other}' in the same scope — one name, one provider, so a lookup can find it`;
|
|
12518
12688
|
case "UNKNOWN_MACRO_ARG":
|
|
12519
12689
|
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
12520
12690
|
case "UNKNOWN_DIRECTIVE":
|
|
@@ -12680,7 +12850,7 @@ var App = class {
|
|
|
12680
12850
|
const { type: type3 } = e;
|
|
12681
12851
|
const isDrag = type3 === "dragover" || type3 === "dragstart" || type3 === "dragend" || type3 === "drop";
|
|
12682
12852
|
const { rootNode: root, maxEventNodeDepth: maxDepth, comps, transactor } = this;
|
|
12683
|
-
const [
|
|
12853
|
+
const [path2, handlers] = DispatchPath.fromNodeAndEventName(
|
|
12684
12854
|
e.target,
|
|
12685
12855
|
type3,
|
|
12686
12856
|
root,
|
|
@@ -12688,9 +12858,9 @@ var App = class {
|
|
|
12688
12858
|
comps,
|
|
12689
12859
|
!isDrag
|
|
12690
12860
|
);
|
|
12691
|
-
if (isDrag) this._handleDragEvent(e, type3,
|
|
12692
|
-
if (
|
|
12693
|
-
for (const handler of handlers) transactor.transactInputNow(
|
|
12861
|
+
if (isDrag) this._handleDragEvent(e, type3, path2);
|
|
12862
|
+
if (path2 !== null && handlers !== null)
|
|
12863
|
+
for (const handler of handlers) transactor.transactInputNow(path2, e, handler, this.dragInfo);
|
|
12694
12864
|
}
|
|
12695
12865
|
_handleTouchEvent(e) {
|
|
12696
12866
|
const { type: type3 } = e;
|
|
@@ -12733,7 +12903,7 @@ var App = class {
|
|
|
12733
12903
|
this._touch = null;
|
|
12734
12904
|
}
|
|
12735
12905
|
}
|
|
12736
|
-
_handleDragEvent(e, type3,
|
|
12906
|
+
_handleDragEvent(e, type3, path2) {
|
|
12737
12907
|
if (type3 === "dragover") {
|
|
12738
12908
|
const dropTarget = getClosestDropTarget(e.target, this.rootNode, Infinity);
|
|
12739
12909
|
if (dropTarget !== null) {
|
|
@@ -12745,10 +12915,10 @@ var App = class {
|
|
|
12745
12915
|
} else if (type3 === "dragstart") {
|
|
12746
12916
|
e.target.dataset.dragging = 1;
|
|
12747
12917
|
const rootValue = this.state.val;
|
|
12748
|
-
const txnPath =
|
|
12918
|
+
const txnPath = path2.compact().toTransactionPath();
|
|
12749
12919
|
const value = txnPath.lookup(rootValue);
|
|
12750
12920
|
const dragType = e.target.dataset.dragtype ?? "?";
|
|
12751
|
-
const stack =
|
|
12921
|
+
const stack = path2.buildStack(this.makeStack(rootValue));
|
|
12752
12922
|
this.dragInfo = new DragInfo(stack, value, dragType, e.target);
|
|
12753
12923
|
} else if (type3 === "drop") {
|
|
12754
12924
|
e.preventDefault();
|
|
@@ -12823,7 +12993,7 @@ var App = class {
|
|
|
12823
12993
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
12824
12994
|
}
|
|
12825
12995
|
sendAtRoot(name, args) {
|
|
12826
|
-
this.transactor.pushSend(new
|
|
12996
|
+
this.transactor.pushSend(new DispatchPath(), name, args);
|
|
12827
12997
|
}
|
|
12828
12998
|
registerComponents(comps, opts) {
|
|
12829
12999
|
const scope = this.compStack.enter();
|
|
@@ -12963,7 +13133,20 @@ var WeakMapDomCache = class {
|
|
|
12963
13133
|
};
|
|
12964
13134
|
|
|
12965
13135
|
// src/renderer.js
|
|
12966
|
-
var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
13136
|
+
var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk", "rp"];
|
|
13137
|
+
function stampRenderBase(vdom, text) {
|
|
13138
|
+
if (vdom instanceof VNode)
|
|
13139
|
+
return new VNode(
|
|
13140
|
+
vdom.tag,
|
|
13141
|
+
{ ...vdom.attrs, "data-rp": text },
|
|
13142
|
+
vdom.childs,
|
|
13143
|
+
vdom.key,
|
|
13144
|
+
vdom.namespace
|
|
13145
|
+
);
|
|
13146
|
+
if (vdom instanceof VFragment)
|
|
13147
|
+
return new VFragment(vdom.childs.map((c) => stampRenderBase(c, text)));
|
|
13148
|
+
return vdom;
|
|
13149
|
+
}
|
|
12967
13150
|
var Renderer = class {
|
|
12968
13151
|
constructor(comps) {
|
|
12969
13152
|
this.comps = comps;
|
|
@@ -13000,17 +13183,17 @@ var Renderer = class {
|
|
|
13000
13183
|
if (comp === null) return null;
|
|
13001
13184
|
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
13002
13185
|
}
|
|
13003
|
-
renderIt(stack, node, key, viewName) {
|
|
13186
|
+
renderIt(stack, node, key, viewName, base = null) {
|
|
13004
13187
|
const comp = this.comps.getCompFor(stack.it);
|
|
13005
|
-
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName) : null;
|
|
13188
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName, base) : null;
|
|
13006
13189
|
}
|
|
13007
13190
|
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
13008
13191
|
// `render-each`, or the view's root anode for the app root). It keys the
|
|
13009
13192
|
// cache as a globally-unique object: node ids alone are unique only within a
|
|
13010
13193
|
// single view, so the same value rendered by two components (e.g. through a
|
|
13011
13194
|
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
13012
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
13013
|
-
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
13195
|
+
_rValComp(stack, val, comp, node, key, viewName, base = null) {
|
|
13196
|
+
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}${stack.renderPath.addressKey}`;
|
|
13014
13197
|
const cachePath = [node, val];
|
|
13015
13198
|
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
13016
13199
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
@@ -13018,30 +13201,43 @@ var Renderer = class {
|
|
|
13018
13201
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
13019
13202
|
const body = this.renderView(view, stack);
|
|
13020
13203
|
if (body == null) return null;
|
|
13204
|
+
const baseJson = base === null ? null : pathToJson(base);
|
|
13021
13205
|
const meta = this._renderMetadata({
|
|
13022
13206
|
$: "Comp",
|
|
13023
13207
|
nid: node?.nodeId ?? null,
|
|
13024
13208
|
cid: comp.id,
|
|
13025
|
-
vid: view.name
|
|
13209
|
+
vid: view.name,
|
|
13210
|
+
...baseJson === null ? null : { base: baseJson }
|
|
13026
13211
|
});
|
|
13027
|
-
const dom = new VFragment([
|
|
13212
|
+
const dom = new VFragment([
|
|
13213
|
+
meta,
|
|
13214
|
+
baseJson === null ? body : stampRenderBase(body, JSON.stringify(baseJson))
|
|
13215
|
+
]);
|
|
13028
13216
|
this.cache.set(cachePath, cacheKey, dom);
|
|
13029
13217
|
return dom;
|
|
13030
13218
|
}
|
|
13031
13219
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
13032
13220
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
13033
13221
|
}
|
|
13034
|
-
renderEachWhen(stack,
|
|
13222
|
+
renderEachWhen(stack, each2) {
|
|
13223
|
+
const { iterInfo, node: view, nodeId: nid } = each2;
|
|
13035
13224
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
13225
|
+
const seqPath = iterInfo.val instanceof DynVal ? stack.lookupDynamicLocated(iterInfo.val.name)?.path ?? null : null;
|
|
13036
13226
|
const r = [];
|
|
13037
13227
|
const it = stack.it;
|
|
13038
13228
|
const renderOne = (key, value, attrName, binds) => {
|
|
13229
|
+
const itemBase = seqPath === null ? null : keyedPath(seqPath, key);
|
|
13230
|
+
const itemStep = itemBase === null ? each2.itemStep(key) : null;
|
|
13231
|
+
const itemPath = itemBase !== null ? stack.renderPath.pushFrame(itemBase) : itemStep !== null ? stack.renderPath.pushItem(itemStep) : stack.renderPath;
|
|
13039
13232
|
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
13040
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
13233
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}${itemPath.addressKey}`;
|
|
13041
13234
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
13042
13235
|
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
13043
13236
|
else {
|
|
13044
|
-
const dom = this.renderView(
|
|
13237
|
+
const dom = this.renderView(
|
|
13238
|
+
view,
|
|
13239
|
+
stack.enter(value, binds, false, itemPath, itemBase !== null)
|
|
13240
|
+
);
|
|
13045
13241
|
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
13046
13242
|
this.cache.set(cachePath, cacheKey, dom);
|
|
13047
13243
|
}
|
|
@@ -13297,7 +13493,6 @@ export {
|
|
|
13297
13493
|
ModuleTests,
|
|
13298
13494
|
PASS,
|
|
13299
13495
|
PLACEHOLDERLESS_TEMPLATE_STRING,
|
|
13300
|
-
PROVIDE_NAME_COLLISION,
|
|
13301
13496
|
PROVIDE_NOT_ADDRESSABLE,
|
|
13302
13497
|
PROVIDE_TYPE_BAD_SHAPE,
|
|
13303
13498
|
ParseContext,
|
|
@@ -13338,6 +13533,7 @@ export {
|
|
|
13338
13533
|
lintIdToMessage,
|
|
13339
13534
|
macro,
|
|
13340
13535
|
makeCollector,
|
|
13536
|
+
path,
|
|
13341
13537
|
phaseOps,
|
|
13342
13538
|
reportTestReportToConsole,
|
|
13343
13539
|
resolveArgs,
|