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-cli.js
CHANGED
|
@@ -1039,8 +1039,68 @@ var init_immer2 = __esm({
|
|
|
1039
1039
|
});
|
|
1040
1040
|
|
|
1041
1041
|
// src/path.js
|
|
1042
|
-
function
|
|
1043
|
-
|
|
1042
|
+
function stepToJson(step) {
|
|
1043
|
+
if (step instanceof SeqStep) return { f: step.field, k: step.key };
|
|
1044
|
+
if (step instanceof FieldStep) return { f: step.field };
|
|
1045
|
+
if (step instanceof SeqAccessStep) return { f: step.seqField, a: step.keyField };
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
function stepFromJson(j) {
|
|
1049
|
+
if (j == null || typeof j.f !== "string") return null;
|
|
1050
|
+
if (j.k !== void 0) return new SeqStep(j.f, j.k);
|
|
1051
|
+
if (j.a !== void 0) return new SeqAccessStep(j.f, j.a);
|
|
1052
|
+
return new FieldStep(j.f);
|
|
1053
|
+
}
|
|
1054
|
+
function pathToJson(path) {
|
|
1055
|
+
const out = [];
|
|
1056
|
+
for (const step of path.steps) {
|
|
1057
|
+
const j = stepToJson(step);
|
|
1058
|
+
if (j === null) return null;
|
|
1059
|
+
out.push(j);
|
|
1060
|
+
}
|
|
1061
|
+
return out;
|
|
1062
|
+
}
|
|
1063
|
+
function pathFromJson(j) {
|
|
1064
|
+
if (!Array.isArray(j)) return null;
|
|
1065
|
+
const steps = [];
|
|
1066
|
+
for (const item of j) {
|
|
1067
|
+
const step = stepFromJson(item);
|
|
1068
|
+
if (step === null) return null;
|
|
1069
|
+
steps.push(step);
|
|
1070
|
+
}
|
|
1071
|
+
return new Path(steps);
|
|
1072
|
+
}
|
|
1073
|
+
function walkItems(stack, items, renderPath, path) {
|
|
1074
|
+
let prev = stack.it;
|
|
1075
|
+
for (const step of items) {
|
|
1076
|
+
const next = step.lookup(prev, NONE);
|
|
1077
|
+
if (next === NONE) {
|
|
1078
|
+
console.warn("bad PathItem", { root: stack.it, step, path });
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
1081
|
+
renderPath = renderPath.pushItem(step);
|
|
1082
|
+
stack = step.enterFrame(stack, next, renderPath);
|
|
1083
|
+
prev = next;
|
|
1084
|
+
}
|
|
1085
|
+
return [stack, renderPath];
|
|
1086
|
+
}
|
|
1087
|
+
function keyedPath(path, key) {
|
|
1088
|
+
const steps = path.steps;
|
|
1089
|
+
const last = steps[steps.length - 1];
|
|
1090
|
+
if (last instanceof SeqStep || last instanceof FieldStep)
|
|
1091
|
+
return new Path(steps.slice(0, -1).concat(new SeqStep(last.field, key)));
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1094
|
+
function renderPathText(path) {
|
|
1095
|
+
return JSON.stringify(pathToJson(path));
|
|
1096
|
+
}
|
|
1097
|
+
function parseRenderPath(text) {
|
|
1098
|
+
try {
|
|
1099
|
+
return pathFromJson(JSON.parse(text));
|
|
1100
|
+
} catch (err) {
|
|
1101
|
+
console.warn("bad render path", err, text);
|
|
1102
|
+
return null;
|
|
1103
|
+
}
|
|
1044
1104
|
}
|
|
1045
1105
|
function metaChain(n) {
|
|
1046
1106
|
const out = [];
|
|
@@ -1061,15 +1121,18 @@ function findHandlers(comp, eventIds, vid, eventName) {
|
|
|
1061
1121
|
}
|
|
1062
1122
|
return null;
|
|
1063
1123
|
}
|
|
1064
|
-
function
|
|
1065
|
-
for (let i = 0; i <
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1068
|
-
if (
|
|
1124
|
+
function resolvePathPart(comp, nodeRefs, vid) {
|
|
1125
|
+
for (let i = 0; i < nodeRefs.length; i++) {
|
|
1126
|
+
const ref = nodeRefs[i];
|
|
1127
|
+
if (ref.base != null) return { base: ref.base };
|
|
1128
|
+
if (ref.nid === void 0 || ref.nid === null) continue;
|
|
1129
|
+
const ctx = new StepCtx(comp, nodeRefs, i, vid);
|
|
1130
|
+
const step = ctx.resolveNode()?.toPathStep(ctx) ?? null;
|
|
1131
|
+
if (step !== null) return { step };
|
|
1069
1132
|
}
|
|
1070
1133
|
return null;
|
|
1071
1134
|
}
|
|
1072
|
-
var NONE, readKey, writeKey, writeSeqKey, Step, BindStep, ScopeBindStep, FieldStep, SeqStep, SeqAccessStep, EachBindStep, EachRenderItStep,
|
|
1135
|
+
var NONE, readKey, writeKey, writeSeqKey, Step, BindStep, ScopeBindStep, FieldStep, SeqStep, SeqAccessStep, EachBindStep, EachRenderItStep, Path, EMPTY_PATH, DispatchPath, StepCtx, NO_EVENT_INFO, BUBBLING_EVENTS, PathBuilder;
|
|
1073
1136
|
var init_path = __esm({
|
|
1074
1137
|
"src/path.js"() {
|
|
1075
1138
|
init_collection();
|
|
@@ -1100,8 +1163,11 @@ var init_path = __esm({
|
|
|
1100
1163
|
}
|
|
1101
1164
|
setDraftValue(_root, _v) {
|
|
1102
1165
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1166
|
+
// Re-enter this step while rebuilding a stack. `renderPath` is the dispatch
|
|
1167
|
+
// position AFTER this step: a rebuilt frame must carry the same render path
|
|
1168
|
+
// the renderer had there, or the provides it publishes would be located wrong.
|
|
1169
|
+
enterFrame(stack, next, renderPath) {
|
|
1170
|
+
return stack.enter(next, {}, true, renderPath);
|
|
1105
1171
|
}
|
|
1106
1172
|
toAbstractPathStep() {
|
|
1107
1173
|
return this;
|
|
@@ -1126,8 +1192,8 @@ var init_path = __esm({
|
|
|
1126
1192
|
lookup(v, _dval) {
|
|
1127
1193
|
return v;
|
|
1128
1194
|
}
|
|
1129
|
-
enterFrame(stack, next) {
|
|
1130
|
-
return stack.enter(next, { ...this.binds }, false);
|
|
1195
|
+
enterFrame(stack, next, renderPath) {
|
|
1196
|
+
return stack.enter(next, { ...this.binds }, false, renderPath);
|
|
1131
1197
|
}
|
|
1132
1198
|
withIndex(i) {
|
|
1133
1199
|
return new _BindStep({ ...this.binds, key: i });
|
|
@@ -1144,9 +1210,9 @@ var init_path = __esm({
|
|
|
1144
1210
|
super(binds);
|
|
1145
1211
|
this.val = val;
|
|
1146
1212
|
}
|
|
1147
|
-
enterFrame(stack, next) {
|
|
1213
|
+
enterFrame(stack, next, renderPath) {
|
|
1148
1214
|
const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
|
|
1149
|
-
return stack.enter(next, { ...this.binds, ...dyn }, false);
|
|
1215
|
+
return stack.enter(next, { ...this.binds, ...dyn }, false, renderPath);
|
|
1150
1216
|
}
|
|
1151
1217
|
withIndex(i) {
|
|
1152
1218
|
return new _ScopeBindStep(this.val, { ...this.binds, key: i });
|
|
@@ -1189,8 +1255,8 @@ var init_path = __esm({
|
|
|
1189
1255
|
const seq = readKey(root, this.field, null);
|
|
1190
1256
|
if (seq != null) writeSeqKey(seq, this.key, v);
|
|
1191
1257
|
}
|
|
1192
|
-
enterFrame(stack, next) {
|
|
1193
|
-
return stack.enter(next, { key: this.key }, true);
|
|
1258
|
+
enterFrame(stack, next, renderPath) {
|
|
1259
|
+
return stack.enter(next, { key: this.key }, true, renderPath);
|
|
1194
1260
|
}
|
|
1195
1261
|
toKey() {
|
|
1196
1262
|
return { field: this.field, key: this.key };
|
|
@@ -1236,57 +1302,21 @@ var init_path = __esm({
|
|
|
1236
1302
|
}
|
|
1237
1303
|
// Replay the renderer's per-item binds (key, value + any @enrich-with binds)
|
|
1238
1304
|
// so a rebuilt stack matches the one @each rendered with.
|
|
1239
|
-
enterFrame(stack, next) {
|
|
1240
|
-
return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false);
|
|
1305
|
+
enterFrame(stack, next, renderPath) {
|
|
1306
|
+
return stack.enter(next, this.iterInfo.enrichBinds(stack, this.key), false, renderPath);
|
|
1241
1307
|
}
|
|
1242
1308
|
toAbstractPathStep() {
|
|
1243
1309
|
return null;
|
|
1244
1310
|
}
|
|
1245
1311
|
};
|
|
1246
1312
|
EachRenderItStep = class extends SeqStep {
|
|
1247
|
-
enterFrame(stack, next) {
|
|
1248
|
-
return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
|
|
1313
|
+
enterFrame(stack, next, renderPath) {
|
|
1314
|
+
return stack.enter(next, { key: this.key, value: next }, false, renderPath).enter(next, {}, true, renderPath);
|
|
1249
1315
|
}
|
|
1250
1316
|
toAbstractPathStep() {
|
|
1251
1317
|
return new SeqStep(this.field, this.key);
|
|
1252
1318
|
}
|
|
1253
1319
|
};
|
|
1254
|
-
DynStep = class extends Step {
|
|
1255
|
-
constructor(producerCompId, producerSteps) {
|
|
1256
|
-
super();
|
|
1257
|
-
this.producerCompId = producerCompId;
|
|
1258
|
-
this.producerSteps = producerSteps;
|
|
1259
|
-
this.interiorCids = /* @__PURE__ */ new Set();
|
|
1260
|
-
}
|
|
1261
|
-
// Steps spliced into the transaction path in place of this marker.
|
|
1262
|
-
teleportSteps() {
|
|
1263
|
-
return this.producerSteps;
|
|
1264
|
-
}
|
|
1265
|
-
lookup(_v, dval = null) {
|
|
1266
|
-
warnRawDynStep("lookup", this);
|
|
1267
|
-
return dval;
|
|
1268
|
-
}
|
|
1269
|
-
enterFrame(stack, _next) {
|
|
1270
|
-
warnRawDynStep("enterFrame", this);
|
|
1271
|
-
return stack;
|
|
1272
|
-
}
|
|
1273
|
-
};
|
|
1274
|
-
DynEachStep = class extends DynStep {
|
|
1275
|
-
constructor(producerCompId, producerSteps, key) {
|
|
1276
|
-
super(producerCompId, producerSteps);
|
|
1277
|
-
this.key = key;
|
|
1278
|
-
}
|
|
1279
|
-
teleportSteps() {
|
|
1280
|
-
const { producerSteps, key } = this;
|
|
1281
|
-
if (producerSteps.length === 0) return producerSteps;
|
|
1282
|
-
const last = producerSteps[producerSteps.length - 1];
|
|
1283
|
-
if (!(last instanceof FieldStep)) {
|
|
1284
|
-
console.warn("DynEachStep: seq-access dynamic cannot be iterated", this);
|
|
1285
|
-
return producerSteps;
|
|
1286
|
-
}
|
|
1287
|
-
return producerSteps.slice(0, -1).concat(new SeqStep(last.field, key));
|
|
1288
|
-
}
|
|
1289
|
-
};
|
|
1290
1320
|
Path = class _Path {
|
|
1291
1321
|
constructor(steps = []) {
|
|
1292
1322
|
this.steps = steps;
|
|
@@ -1297,40 +1327,13 @@ var init_path = __esm({
|
|
|
1297
1327
|
popStep() {
|
|
1298
1328
|
return new _Path(this.steps.slice(0, -1));
|
|
1299
1329
|
}
|
|
1300
|
-
//
|
|
1301
|
-
//
|
|
1330
|
+
// Frame-only steps removed, one step per crossed component: `popStep` over the
|
|
1331
|
+
// result bubbles through every component.
|
|
1302
1332
|
compact() {
|
|
1303
1333
|
const out = [];
|
|
1304
1334
|
for (const step of this.steps) {
|
|
1305
1335
|
const s = step.toAbstractPathStep();
|
|
1306
|
-
if (s !== null)
|
|
1307
|
-
if (s !== step) s._originCid = step._originCid;
|
|
1308
|
-
out.push(s);
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
return new _Path(out);
|
|
1312
|
-
}
|
|
1313
|
-
// The abstract path used to apply a transaction: every DynStep is teleported —
|
|
1314
|
-
// the steps interior to its producer..consumer span are dropped and the
|
|
1315
|
-
// producer's own path spliced in — so a mutation lands on the data's real
|
|
1316
|
-
// location. A path with no DynStep is returned unchanged.
|
|
1317
|
-
toTransactionPath() {
|
|
1318
|
-
let hasDyn = false;
|
|
1319
|
-
for (const step of this.steps)
|
|
1320
|
-
if (step instanceof DynStep) {
|
|
1321
|
-
hasDyn = true;
|
|
1322
|
-
break;
|
|
1323
|
-
}
|
|
1324
|
-
if (!hasDyn) return this;
|
|
1325
|
-
const out = [];
|
|
1326
|
-
for (const step of this.steps) {
|
|
1327
|
-
if (step instanceof DynStep) {
|
|
1328
|
-
while (out.length > 0 && step.interiorCids.has(out[out.length - 1]._originCid)) out.pop();
|
|
1329
|
-
for (const ts of step.teleportSteps()) {
|
|
1330
|
-
ts._originCid = step.producerCompId;
|
|
1331
|
-
out.push(ts);
|
|
1332
|
-
}
|
|
1333
|
-
} else out.push(step);
|
|
1336
|
+
if (s !== null) out.push(s);
|
|
1334
1337
|
}
|
|
1335
1338
|
return new _Path(out);
|
|
1336
1339
|
}
|
|
@@ -1338,7 +1341,6 @@ var init_path = __esm({
|
|
|
1338
1341
|
// key as it is *now* so a later lookup/setValue lands on the same item even if the
|
|
1339
1342
|
// keyField changed meanwhile (e.g. the selected tab moved while an intent was in
|
|
1340
1343
|
// flight). Returns a new Path with those steps replaced; `this` if nothing pinned.
|
|
1341
|
-
// Must be called on a transaction path (no DynSteps — call toTransactionPath first).
|
|
1342
1344
|
pinKeys(root) {
|
|
1343
1345
|
let curVal = root;
|
|
1344
1346
|
let out = null;
|
|
@@ -1361,8 +1363,8 @@ var init_path = __esm({
|
|
|
1361
1363
|
}
|
|
1362
1364
|
// The values entered along the path, root→leaf (root included): index 0 is `root`,
|
|
1363
1365
|
// the last entry is the leaf this path resolves to. Stops early at the first
|
|
1364
|
-
// unresolvable step.
|
|
1365
|
-
//
|
|
1366
|
+
// unresolvable step. Used to walk the component instances on a dispatch path
|
|
1367
|
+
// (filter via Components.getCompFor).
|
|
1366
1368
|
resolveChain(root) {
|
|
1367
1369
|
const out = [root];
|
|
1368
1370
|
let curVal = root;
|
|
@@ -1376,7 +1378,7 @@ var init_path = __esm({
|
|
|
1376
1378
|
// A flat `[{ field, key? }]` list of the addressing steps, skipping frame-only
|
|
1377
1379
|
// steps (binds). Generic path introspection so tooling (e.g. the storybook
|
|
1378
1380
|
// activity log) can identify which subtree a transaction touched without
|
|
1379
|
-
// depending on Step internals.
|
|
1381
|
+
// depending on Step internals.
|
|
1380
1382
|
toKeys() {
|
|
1381
1383
|
const out = [];
|
|
1382
1384
|
for (const step of this.steps) {
|
|
@@ -1397,62 +1399,133 @@ var init_path = __esm({
|
|
|
1397
1399
|
});
|
|
1398
1400
|
}
|
|
1399
1401
|
buildStack(stack) {
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1402
|
+
return walkItems(stack, this.steps, stack.renderPath ?? new DispatchPath(), this)?.[0] ?? null;
|
|
1403
|
+
}
|
|
1404
|
+
};
|
|
1405
|
+
EMPTY_PATH = new Path([]);
|
|
1406
|
+
DispatchPath = class _DispatchPath {
|
|
1407
|
+
constructor(frames = [{ base: EMPTY_PATH, items: [] }]) {
|
|
1408
|
+
this.frames = frames;
|
|
1409
|
+
}
|
|
1410
|
+
// Plain addressing steps in one frame based at the root: what a caller means
|
|
1411
|
+
// by "this position" when it has no continuation of its own.
|
|
1412
|
+
static ofSteps(steps) {
|
|
1413
|
+
return new _DispatchPath([{ base: EMPTY_PATH, items: steps.slice() }]);
|
|
1414
|
+
}
|
|
1415
|
+
get top() {
|
|
1416
|
+
return this.frames[this.frames.length - 1];
|
|
1417
|
+
}
|
|
1418
|
+
_withTopItems(items) {
|
|
1419
|
+
const frames = this.frames.slice();
|
|
1420
|
+
frames[frames.length - 1] = { base: this.top.base, items };
|
|
1421
|
+
return new _DispatchPath(frames);
|
|
1422
|
+
}
|
|
1423
|
+
concat(steps) {
|
|
1424
|
+
if (this.frames.length === 0) return _DispatchPath.ofSteps(steps);
|
|
1425
|
+
return this._withTopItems(this.top.items.concat(steps));
|
|
1426
|
+
}
|
|
1427
|
+
pushItem(step) {
|
|
1428
|
+
return this.concat([step]);
|
|
1429
|
+
}
|
|
1430
|
+
pushFrame(base) {
|
|
1431
|
+
return new _DispatchPath(this.frames.concat({ base, items: [] }));
|
|
1432
|
+
}
|
|
1433
|
+
// Whether bubbling has anywhere left to go: another step in this frame, or a
|
|
1434
|
+
// visual caller underneath it.
|
|
1435
|
+
canPop() {
|
|
1436
|
+
const n = this.frames.length;
|
|
1437
|
+
return n > 1 || n === 1 && this.frames[0].items.length > 0;
|
|
1438
|
+
}
|
|
1439
|
+
isRoot() {
|
|
1440
|
+
return this.toTransactionPath().steps.length === 0;
|
|
1441
|
+
}
|
|
1442
|
+
// One component closer to the root. At the top of a frame that is popping back
|
|
1443
|
+
// to the visual caller, not to the producer's own parent — the caller is where
|
|
1444
|
+
// the `*name` was written, and where an unhandled message should keep going.
|
|
1445
|
+
popStep() {
|
|
1446
|
+
const n = this.frames.length;
|
|
1447
|
+
if (n === 0) return this;
|
|
1448
|
+
const top = this.frames[n - 1];
|
|
1449
|
+
if (top.items.length > 0) return this._withTopItems(top.items.slice(0, -1));
|
|
1450
|
+
if (n > 1) return new _DispatchPath(this.frames.slice(0, -1));
|
|
1451
|
+
return this;
|
|
1452
|
+
}
|
|
1453
|
+
// Drop frame-only steps inside every frame independently; a frame's base is
|
|
1454
|
+
// already addressing-only.
|
|
1455
|
+
compact() {
|
|
1456
|
+
return new _DispatchPath(
|
|
1457
|
+
this.frames.map(({ base, items }) => ({ base, items: new Path(items).compact().steps }))
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
// A stable string for the ADDRESS this path denotes, for the render cache. The
|
|
1461
|
+
// same immutable value can sit at two places in the tree, and a subtree rendered
|
|
1462
|
+
// at one of them bakes that address in — the provides it publishes are located
|
|
1463
|
+
// there. Frame-only steps address nothing, so they are compacted out: two sites
|
|
1464
|
+
// that differ only in binds do render the same subtree.
|
|
1465
|
+
get addressKey() {
|
|
1466
|
+
this._addressKey ??= renderPathText(this.toTransactionPath().compact());
|
|
1467
|
+
return this._addressKey;
|
|
1468
|
+
}
|
|
1469
|
+
// The active transaction address: the top frame's absolute base followed by
|
|
1470
|
+
// its ordinary descendant steps. This is where a mutation lands.
|
|
1471
|
+
toTransactionPath() {
|
|
1472
|
+
const top = this.top;
|
|
1473
|
+
return top === void 0 ? EMPTY_PATH : top.base.concat(top.items);
|
|
1474
|
+
}
|
|
1475
|
+
// Rebuild the render stack this path was dispatched from. A frame with a base
|
|
1476
|
+
// re-enters at that absolute value first — replaying the resume a `*name`
|
|
1477
|
+
// render performed — and then walks its ordinary items.
|
|
1478
|
+
buildStack(stack) {
|
|
1479
|
+
let renderPath = new _DispatchPath();
|
|
1480
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
1481
|
+
const { base, items } = this.frames[i];
|
|
1482
|
+
if (i > 0 || base.steps.length > 0) {
|
|
1483
|
+
const baseValue = base.lookup(stack.root, NONE);
|
|
1484
|
+
if (baseValue === NONE) {
|
|
1485
|
+
console.warn("bad frame base", { base, path: this });
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
renderPath = renderPath.pushFrame(base);
|
|
1489
|
+
stack = stack.enter(baseValue, {}, true, renderPath);
|
|
1406
1490
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1491
|
+
const walked = walkItems(stack, items, renderPath, this);
|
|
1492
|
+
if (walked === null) return null;
|
|
1493
|
+
[stack, renderPath] = walked;
|
|
1409
1494
|
}
|
|
1410
1495
|
return stack;
|
|
1411
1496
|
}
|
|
1412
1497
|
static fromNodeAndEventName(node, eventName, rootNode, maxDepth, comps, stopOnNoEvent = true) {
|
|
1413
|
-
const
|
|
1414
|
-
const pendingDyns = [];
|
|
1498
|
+
const parts = [];
|
|
1415
1499
|
const bubbles = BUBBLING_EVENTS.has(eventName);
|
|
1416
1500
|
let depth = 0;
|
|
1417
1501
|
let eventIds = [];
|
|
1418
1502
|
let handlers = null;
|
|
1419
|
-
let
|
|
1503
|
+
let nodeRefs = [];
|
|
1420
1504
|
let isLeafComponent = true;
|
|
1421
1505
|
const crossComponent = (cidNum, vid) => {
|
|
1422
1506
|
const comp = comps.getComponentForId(cidNum);
|
|
1423
|
-
let
|
|
1507
|
+
let pushPart = true;
|
|
1424
1508
|
if (handlers === null && (isLeafComponent || bubbles)) {
|
|
1425
1509
|
handlers = findHandlers(comp, eventIds, vid, eventName);
|
|
1426
1510
|
if (handlers === null) {
|
|
1427
1511
|
if (isLeafComponent && stopOnNoEvent && !bubbles) return false;
|
|
1428
1512
|
} else if (!isLeafComponent) {
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
pushStep = false;
|
|
1513
|
+
parts.length = 0;
|
|
1514
|
+
pushPart = false;
|
|
1432
1515
|
}
|
|
1433
1516
|
}
|
|
1434
1517
|
isLeafComponent = false;
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
if (step) {
|
|
1439
|
-
step._originCid = cidNum;
|
|
1440
|
-
pathSteps.push(step);
|
|
1441
|
-
if (step instanceof DynStep) {
|
|
1442
|
-
step.interiorCids.add(cidNum);
|
|
1443
|
-
pendingDyns.push(step);
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1518
|
+
if (pushPart) {
|
|
1519
|
+
const part = resolvePathPart(comp, nodeRefs, vid);
|
|
1520
|
+
if (part) parts.push(part);
|
|
1446
1521
|
}
|
|
1447
|
-
for (let i = pendingDyns.length - 1; i >= 0; i--)
|
|
1448
|
-
if (pendingDyns[i].producerCompId === cidNum) pendingDyns.splice(i, 1);
|
|
1449
1522
|
eventIds = [];
|
|
1450
|
-
|
|
1523
|
+
nodeRefs = [];
|
|
1451
1524
|
return true;
|
|
1452
1525
|
};
|
|
1453
1526
|
while (node && node !== rootNode && depth < maxDepth) {
|
|
1454
1527
|
if (node?.dataset) {
|
|
1455
|
-
const { eid, cid, vid } = node.dataset;
|
|
1528
|
+
const { eid, cid, vid, rp } = node.dataset;
|
|
1456
1529
|
if (eid !== void 0) eventIds.push(eid);
|
|
1457
1530
|
const metas = metaChain(node.previousSibling);
|
|
1458
1531
|
let sawComp = false;
|
|
@@ -1460,19 +1533,27 @@ var init_path = __esm({
|
|
|
1460
1533
|
if (m.$ === "Comp") {
|
|
1461
1534
|
sawComp = true;
|
|
1462
1535
|
if (!crossComponent(m.cid, m.vid)) return NO_EVENT_INFO;
|
|
1463
|
-
|
|
1536
|
+
nodeRefs.push({ nid: m.nid, base: pathFromJson(m.base) });
|
|
1464
1537
|
} else {
|
|
1465
|
-
|
|
1538
|
+
nodeRefs.push({ nid: m.nid, si: m.si, sk: m.sk });
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
if (!sawComp && cid !== void 0) {
|
|
1542
|
+
if (!crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
1543
|
+
if (rp !== void 0) {
|
|
1544
|
+
const base = parseRenderPath(rp);
|
|
1545
|
+
if (base !== null) nodeRefs.push({ base });
|
|
1466
1546
|
}
|
|
1467
1547
|
}
|
|
1468
|
-
if (!sawComp && cid !== void 0 && !crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
1469
1548
|
}
|
|
1470
1549
|
depth += 1;
|
|
1471
1550
|
node = node.parentNode;
|
|
1472
1551
|
}
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1552
|
+
parts.reverse();
|
|
1553
|
+
let path = new _DispatchPath();
|
|
1554
|
+
for (const part of parts)
|
|
1555
|
+
path = part.base !== void 0 ? path.pushFrame(part.base) : path.pushItem(part.step);
|
|
1556
|
+
return [path, handlers];
|
|
1476
1557
|
}
|
|
1477
1558
|
};
|
|
1478
1559
|
StepCtx = class _StepCtx {
|
|
@@ -1514,6 +1595,9 @@ var init_path = __esm({
|
|
|
1514
1595
|
constructor() {
|
|
1515
1596
|
this.pathChanges = [];
|
|
1516
1597
|
}
|
|
1598
|
+
toPath() {
|
|
1599
|
+
return new Path(this.pathChanges);
|
|
1600
|
+
}
|
|
1517
1601
|
add(pathChange) {
|
|
1518
1602
|
this.pathChanges.push(pathChange);
|
|
1519
1603
|
return this;
|
|
@@ -2702,13 +2786,16 @@ var init_vdom = __esm({
|
|
|
2702
2786
|
});
|
|
2703
2787
|
|
|
2704
2788
|
// src/anode.js
|
|
2705
|
-
function
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2789
|
+
function renderTarget(val, stack) {
|
|
2790
|
+
if (val instanceof DynVal) {
|
|
2791
|
+
const loc = stack.lookupDynamicLocated(val.name);
|
|
2792
|
+
if (loc?.path == null) return [loc?.value ?? null, stack.renderPath, null];
|
|
2793
|
+
return [loc.value, stack.renderPath.pushFrame(loc.path), loc.path];
|
|
2794
|
+
}
|
|
2795
|
+
const step = val.toPathItem?.() ?? null;
|
|
2796
|
+
if (step === null) return [val.eval(stack), stack.renderPath, null];
|
|
2797
|
+
const path = stack.renderPath.pushItem(step);
|
|
2798
|
+
return [val.eval(stack), path, stack.pendingFrame ? path.toTransactionPath() : null];
|
|
2712
2799
|
}
|
|
2713
2800
|
function optimizeChilds(childs) {
|
|
2714
2801
|
for (let i = 0; i < childs.length; i++) {
|
|
@@ -2816,11 +2903,6 @@ function makeWrapperNode(data, px) {
|
|
|
2816
2903
|
}
|
|
2817
2904
|
return node;
|
|
2818
2905
|
}
|
|
2819
|
-
function dynRenderStep(comp, name, key) {
|
|
2820
|
-
const p = resolveDynProducer(comp, name);
|
|
2821
|
-
if (!p) return null;
|
|
2822
|
-
return key === void 0 ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
2823
|
-
}
|
|
2824
2906
|
function parseRenderEach(px, value, as, attrs) {
|
|
2825
2907
|
const seqVal = parseXOpVal("render-each", value, px, parseSequence);
|
|
2826
2908
|
if (seqVal === null) return null;
|
|
@@ -3090,26 +3172,29 @@ var init_anode = __esm({
|
|
|
3090
3172
|
};
|
|
3091
3173
|
RenderNode = class extends RenderViewId {
|
|
3092
3174
|
render(stack, rx) {
|
|
3093
|
-
const
|
|
3094
|
-
|
|
3175
|
+
const [value, renderPath, base] = renderTarget(this.val, stack);
|
|
3176
|
+
const newStack = stack.enter(value, {}, true, renderPath, false);
|
|
3177
|
+
return rx.renderIt(newStack, this, "", this.evalViewName(stack), base);
|
|
3095
3178
|
}
|
|
3179
|
+
// A `*name` target contributes no step: the site recorded the absolute base it
|
|
3180
|
+
// resumed at, and event reconstruction turns that into a continuation frame.
|
|
3096
3181
|
toPathStep(ctx) {
|
|
3097
|
-
if (this.val instanceof DynVal) return
|
|
3182
|
+
if (this.val instanceof DynVal) return null;
|
|
3098
3183
|
return super.toPathStep(ctx);
|
|
3099
3184
|
}
|
|
3100
3185
|
};
|
|
3101
3186
|
RenderItNode = class extends RenderViewId {
|
|
3102
3187
|
render(stack, rx) {
|
|
3103
|
-
const
|
|
3104
|
-
|
|
3188
|
+
const base = stack.pendingFrame ? stack.renderPath.toTransactionPath() : null;
|
|
3189
|
+
const newStack = stack.enter(stack.it, {}, true, stack.renderPath, false);
|
|
3190
|
+
return rx.renderIt(newStack, this, "", this.evalViewName(stack), base);
|
|
3105
3191
|
}
|
|
3106
3192
|
toPathStep(ctx) {
|
|
3107
3193
|
const next = ctx.next();
|
|
3108
3194
|
if (next === null) return null;
|
|
3109
3195
|
const nextNode = next.resolveNode();
|
|
3110
3196
|
if (nextNode instanceof EachNode && next.hasKey) {
|
|
3111
|
-
if (nextNode.val instanceof DynVal)
|
|
3112
|
-
return dynRenderStep(ctx.comp, nextNode.val.name, next.key);
|
|
3197
|
+
if (nextNode.val instanceof DynVal) return null;
|
|
3113
3198
|
return new EachRenderItStep(nextNode.val.name, next.key);
|
|
3114
3199
|
}
|
|
3115
3200
|
return null;
|
|
@@ -3199,11 +3284,19 @@ var init_anode = __esm({
|
|
|
3199
3284
|
this.iterInfo = new IterInfo(val, null, null, null);
|
|
3200
3285
|
}
|
|
3201
3286
|
render(stack, rx) {
|
|
3202
|
-
return rx.renderEachWhen(stack, this
|
|
3287
|
+
return rx.renderEachWhen(stack, this);
|
|
3203
3288
|
}
|
|
3204
3289
|
toPathStep(ctx) {
|
|
3205
3290
|
return ctx.hasKey ? new EachBindStep(this.iterInfo, ctx.key) : null;
|
|
3206
3291
|
}
|
|
3292
|
+
// Where one item lives, for the render path. `@each` re-binds `it` to the item
|
|
3293
|
+
// whether or not the body is a component, so the position moves either way and
|
|
3294
|
+
// the step has to address it — `.rows` iterated at `key` IS `rows[key]`.
|
|
3295
|
+
// Null for a dynamic sequence: `*rows` carries its own absolute path and enters
|
|
3296
|
+
// a continuation frame instead (see Renderer.renderEachWhen).
|
|
3297
|
+
itemStep(key) {
|
|
3298
|
+
return this.val instanceof FieldVal ? new SeqStep(this.val.name, key) : null;
|
|
3299
|
+
}
|
|
3207
3300
|
static register = true;
|
|
3208
3301
|
};
|
|
3209
3302
|
IterInfo = class {
|
|
@@ -3424,11 +3517,227 @@ var init_anode = __esm({
|
|
|
3424
3517
|
}
|
|
3425
3518
|
});
|
|
3426
3519
|
|
|
3520
|
+
// src/stack.js
|
|
3521
|
+
function routeLookup(route, lex, dyn) {
|
|
3522
|
+
for (let i = 0; i < route.length; i++) {
|
|
3523
|
+
const leg = route[i];
|
|
3524
|
+
if (leg === "dyn") {
|
|
3525
|
+
const v = dyn();
|
|
3526
|
+
if (v != null) return v;
|
|
3527
|
+
} else if (leg === "lex") {
|
|
3528
|
+
const v = lex();
|
|
3529
|
+
if (v != null) return v;
|
|
3530
|
+
} else {
|
|
3531
|
+
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
return null;
|
|
3535
|
+
}
|
|
3536
|
+
function lookup(chain, name, dv = null) {
|
|
3537
|
+
let n = chain;
|
|
3538
|
+
while (n !== null) {
|
|
3539
|
+
const r = n[0].lookup(name);
|
|
3540
|
+
if (r === STOP) return dv;
|
|
3541
|
+
if (r !== NEXT) return r;
|
|
3542
|
+
n = n[1];
|
|
3543
|
+
}
|
|
3544
|
+
return dv;
|
|
3545
|
+
}
|
|
3546
|
+
function computeViewsId(views) {
|
|
3547
|
+
let s = "";
|
|
3548
|
+
let n = views;
|
|
3549
|
+
while (n !== null) {
|
|
3550
|
+
s += n[0];
|
|
3551
|
+
n = n[1];
|
|
3552
|
+
}
|
|
3553
|
+
return s === "main" ? "" : s;
|
|
3554
|
+
}
|
|
3555
|
+
var STOP, NEXT, DEFAULT_ROUTE, isTypeName, BindFrame, DynFrame, Stack, NOT_FOUND;
|
|
3556
|
+
var init_stack = __esm({
|
|
3557
|
+
"src/stack.js"() {
|
|
3558
|
+
init_path();
|
|
3559
|
+
STOP = /* @__PURE__ */ Symbol("STOP");
|
|
3560
|
+
NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
3561
|
+
DEFAULT_ROUTE = ["dyn", "lex"];
|
|
3562
|
+
isTypeName = (s) => {
|
|
3563
|
+
const c = s.charCodeAt(0);
|
|
3564
|
+
return c >= 65 && c <= 90;
|
|
3565
|
+
};
|
|
3566
|
+
BindFrame = class {
|
|
3567
|
+
constructor(it, binds, isFrame) {
|
|
3568
|
+
this.it = it;
|
|
3569
|
+
this.binds = binds;
|
|
3570
|
+
this.isFrame = isFrame;
|
|
3571
|
+
}
|
|
3572
|
+
lookup(name) {
|
|
3573
|
+
const v = this.binds[name];
|
|
3574
|
+
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
3575
|
+
}
|
|
3576
|
+
};
|
|
3577
|
+
DynFrame = class {
|
|
3578
|
+
constructor(binds, types) {
|
|
3579
|
+
this.binds = binds;
|
|
3580
|
+
this.types = types;
|
|
3581
|
+
}
|
|
3582
|
+
lookup(name) {
|
|
3583
|
+
const v = (isTypeName(name) ? this.types : this.binds)[name];
|
|
3584
|
+
return v === void 0 ? NEXT : v;
|
|
3585
|
+
}
|
|
3586
|
+
};
|
|
3587
|
+
Stack = class _Stack {
|
|
3588
|
+
constructor(fields) {
|
|
3589
|
+
Object.assign(this, fields);
|
|
3590
|
+
}
|
|
3591
|
+
_with(patch) {
|
|
3592
|
+
return new _Stack({ ...this, ...patch });
|
|
3593
|
+
}
|
|
3594
|
+
// Evaluate every provide the entered component publishes and push them as one
|
|
3595
|
+
// dynBinds frame, keyed by NAME. A value is published together with the absolute
|
|
3596
|
+
// path it lives at: the same declaration is read as `*name` AND resumed at by
|
|
3597
|
+
// `<x render="*name">`, so a consumer needs both halves. Types go in the same
|
|
3598
|
+
// frame's other map. No-op with no provides.
|
|
3599
|
+
_pushProvides() {
|
|
3600
|
+
const comp = this.comps.getCompFor(this.it);
|
|
3601
|
+
if (comp == null) return this;
|
|
3602
|
+
const { provide, provideType } = comp;
|
|
3603
|
+
const binds = {};
|
|
3604
|
+
const types = {};
|
|
3605
|
+
let has2 = false;
|
|
3606
|
+
const base = this._publishBase();
|
|
3607
|
+
for (const k in provide) {
|
|
3608
|
+
const step = provide[k].val.toPathItem?.() ?? null;
|
|
3609
|
+
if (step === null) continue;
|
|
3610
|
+
const value = provide[k].val.eval(this);
|
|
3611
|
+
binds[k] = { value, path: base === null ? null : base.concat([step]) };
|
|
3612
|
+
has2 = true;
|
|
3613
|
+
}
|
|
3614
|
+
for (const k in provideType) {
|
|
3615
|
+
types[k] = provideType[k];
|
|
3616
|
+
has2 = true;
|
|
3617
|
+
}
|
|
3618
|
+
if (!has2) return this;
|
|
3619
|
+
return this._with({ dynBinds: [new DynFrame(binds, types), this.dynBinds] });
|
|
3620
|
+
}
|
|
3621
|
+
// The absolute address of the component being entered, or null when this
|
|
3622
|
+
// position cannot be written down as one. Frame-only steps carry bindings and
|
|
3623
|
+
// address nothing, so they are compacted away first; what is left is checked
|
|
3624
|
+
// against the value actually being rendered, because a scope CAN move the
|
|
3625
|
+
// render position without contributing an addressing step (a plain `@each`
|
|
3626
|
+
// body re-binds `it` to the item while its rebuild step is an identity).
|
|
3627
|
+
//
|
|
3628
|
+
// A null base still publishes the VALUE — `*name` reads it fine — but there is
|
|
3629
|
+
// nowhere to resume, so `<x render="*name">` renders nothing rather than
|
|
3630
|
+
// editing whatever happens to live at the address we guessed.
|
|
3631
|
+
_publishBase() {
|
|
3632
|
+
const base = this.renderPath.toTransactionPath().compact();
|
|
3633
|
+
return base.lookup(this.root, NOT_FOUND) === this.it ? base : null;
|
|
3634
|
+
}
|
|
3635
|
+
static root(comps, it, ctx = null) {
|
|
3636
|
+
return new _Stack({
|
|
3637
|
+
comps,
|
|
3638
|
+
root: it,
|
|
3639
|
+
it,
|
|
3640
|
+
binds: [new BindFrame(it, {}, true), null],
|
|
3641
|
+
dynBinds: [new DynFrame({}, {}), null],
|
|
3642
|
+
views: ["main", null],
|
|
3643
|
+
viewsId: "",
|
|
3644
|
+
renderPath: new DispatchPath(),
|
|
3645
|
+
pendingFrame: false,
|
|
3646
|
+
ctx
|
|
3647
|
+
})._pushProvides();
|
|
3648
|
+
}
|
|
3649
|
+
// `renderPath` defaults to this stack's own: an ordinary scope does not move.
|
|
3650
|
+
// `pendingFrame` clears on a component frame (which emits the base) and is
|
|
3651
|
+
// inherited by transparent scopes, which have to carry it to the next boundary.
|
|
3652
|
+
enter(it, bindings = {}, isFrame = true, renderPath = this.renderPath, pendingFrame = null) {
|
|
3653
|
+
const stack = this._with({
|
|
3654
|
+
it,
|
|
3655
|
+
binds: [new BindFrame(it, bindings, isFrame), this.binds],
|
|
3656
|
+
renderPath,
|
|
3657
|
+
pendingFrame: pendingFrame ?? (isFrame ? false : this.pendingFrame)
|
|
3658
|
+
});
|
|
3659
|
+
return isFrame ? stack._pushProvides() : stack;
|
|
3660
|
+
}
|
|
3661
|
+
pushViewName(name) {
|
|
3662
|
+
const views = [name, this.views];
|
|
3663
|
+
return this._with({ views, viewsId: computeViewsId(views) });
|
|
3664
|
+
}
|
|
3665
|
+
// Published types are stable per scope and would only churn the render cache, so
|
|
3666
|
+
// the cache key covers values alone.
|
|
3667
|
+
_pushDynBindValuesToArray(arr, comp) {
|
|
3668
|
+
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
3669
|
+
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
3670
|
+
}
|
|
3671
|
+
// `*name`: the nearest binding above (including this component's own provides,
|
|
3672
|
+
// pushed on entering it), else a path registered in the component's lexical
|
|
3673
|
+
// scope, else this component's declared default, else null.
|
|
3674
|
+
//
|
|
3675
|
+
// One chain walk and no producer resolution: a lookup names what it WANTS, so the
|
|
3676
|
+
// frame it wants is keyed by that name. The default belongs to the CONSUMER's
|
|
3677
|
+
// declaration and is evaluated against the consumer's stack, which is why it is
|
|
3678
|
+
// consulted only after the whole chain has missed.
|
|
3679
|
+
lookupDynamicLocated(name) {
|
|
3680
|
+
if (isTypeName(name)) return null;
|
|
3681
|
+
const v = lookup(this.dynBinds, name);
|
|
3682
|
+
if (v != null) return v;
|
|
3683
|
+
const comp = this.comps.getCompFor(this.it);
|
|
3684
|
+
if (comp == null) return null;
|
|
3685
|
+
const path = comp.scope?.lookupPath?.(name) ?? null;
|
|
3686
|
+
if (path !== null) {
|
|
3687
|
+
const value2 = path.lookup(this.root, NOT_FOUND);
|
|
3688
|
+
if (value2 !== NOT_FOUND) return { value: value2, path };
|
|
3689
|
+
}
|
|
3690
|
+
const dval = comp.lookup[name]?.val ?? null;
|
|
3691
|
+
if (dval === null) return null;
|
|
3692
|
+
const step = dval.toPathItem?.() ?? null;
|
|
3693
|
+
const value = dval.eval(this);
|
|
3694
|
+
return step === null ? { value, path: null } : { value, path: this.renderPath.toTransactionPath().concat([step]) };
|
|
3695
|
+
}
|
|
3696
|
+
lookupDynamic(name) {
|
|
3697
|
+
if (isTypeName(name)) return lookup(this.dynBinds, name);
|
|
3698
|
+
return this.lookupDynamicLocated(name)?.value ?? null;
|
|
3699
|
+
}
|
|
3700
|
+
lookupBind(name) {
|
|
3701
|
+
return lookup(this.binds, name);
|
|
3702
|
+
}
|
|
3703
|
+
lookupFieldRaw(name) {
|
|
3704
|
+
return this.it[name] ?? null;
|
|
3705
|
+
}
|
|
3706
|
+
lookupMethod(name) {
|
|
3707
|
+
const fn = this.it[name];
|
|
3708
|
+
return fn instanceof Function ? fn.call(this.it) : null;
|
|
3709
|
+
}
|
|
3710
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
3711
|
+
// `e.<member>` handler args. Null outside a live event transaction.
|
|
3712
|
+
lookupEvent() {
|
|
3713
|
+
return this.ctx?.event ?? null;
|
|
3714
|
+
}
|
|
3715
|
+
lookupDragInfo() {
|
|
3716
|
+
return this.ctx?.dragInfo ?? null;
|
|
3717
|
+
}
|
|
3718
|
+
getHandlerFor(name, key) {
|
|
3719
|
+
return this.comps.getHandlerFor(this.it, name, key);
|
|
3720
|
+
}
|
|
3721
|
+
lookupBestView(views, defaultViewName) {
|
|
3722
|
+
let n = this.views;
|
|
3723
|
+
while (n !== null) {
|
|
3724
|
+
const view = views[n[0]];
|
|
3725
|
+
if (view !== void 0) return view;
|
|
3726
|
+
n = n[1];
|
|
3727
|
+
}
|
|
3728
|
+
return views[defaultViewName];
|
|
3729
|
+
}
|
|
3730
|
+
};
|
|
3731
|
+
NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
3732
|
+
}
|
|
3733
|
+
});
|
|
3734
|
+
|
|
3427
3735
|
// src/components.js
|
|
3428
|
-
var COMPONENT, Components, ComponentStack, ProvideInfo, LookupInfo, isString,
|
|
3736
|
+
var COMPONENT, Components, ComponentStack, ProvideInfo, LookupInfo, isString, _rawSpecKeys, KNOWN_SPEC_KEYS, _compId, Component;
|
|
3429
3737
|
var init_components = __esm({
|
|
3430
3738
|
"src/components.js"() {
|
|
3431
3739
|
init_anode();
|
|
3740
|
+
init_stack();
|
|
3432
3741
|
init_value();
|
|
3433
3742
|
COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
3434
3743
|
Components = class {
|
|
@@ -3467,12 +3776,14 @@ var init_components = __esm({
|
|
|
3467
3776
|
this.byName = {};
|
|
3468
3777
|
this.intentsByName = {};
|
|
3469
3778
|
this.macros = {};
|
|
3779
|
+
this.paths = {};
|
|
3470
3780
|
}
|
|
3471
3781
|
enter() {
|
|
3472
3782
|
return new _ComponentStack(this.comps, this);
|
|
3473
3783
|
}
|
|
3474
3784
|
registerComponents(comps, opts) {
|
|
3475
|
-
const { aliases: aliases2 = {} } = opts ?? {};
|
|
3785
|
+
const { aliases: aliases2 = {}, paths } = opts ?? {};
|
|
3786
|
+
if (paths) this.registerPaths(paths);
|
|
3476
3787
|
for (let i = 0; i < comps.length; i++) {
|
|
3477
3788
|
const Comp = comps[i];
|
|
3478
3789
|
Comp[COMPONENT].scope = this.enter();
|
|
@@ -3486,6 +3797,27 @@ var init_components = __esm({
|
|
|
3486
3797
|
else console.warn("alias", alias, "to inexistent component", aliases2[alias]);
|
|
3487
3798
|
}
|
|
3488
3799
|
}
|
|
3800
|
+
// Register lowercase names as absolute paths from the app state root. A
|
|
3801
|
+
// descendant that declares one in its `lookup` reads and renders `*name` without
|
|
3802
|
+
// anything above it publishing one — which is what makes a session, a theme or a
|
|
3803
|
+
// host-owned value available in its natural registration scope, instead of forcing
|
|
3804
|
+
// an application root whose only job is to `provide` it. Register on a nested
|
|
3805
|
+
// scope to narrow a name; nearest registration wins.
|
|
3806
|
+
//
|
|
3807
|
+
// Uppercase names are ignored: a component TYPE is what `lookupComponent` already
|
|
3808
|
+
// answers, and a type has no path.
|
|
3809
|
+
registerPaths(paths) {
|
|
3810
|
+
for (const name in paths) {
|
|
3811
|
+
if (isTypeName(name)) {
|
|
3812
|
+
console.warn("registerPaths: a type name has no path", name);
|
|
3813
|
+
continue;
|
|
3814
|
+
}
|
|
3815
|
+
this.paths[name] = paths[name].toPath?.() ?? paths[name];
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
lookupPath(name) {
|
|
3819
|
+
return this.paths[name] ?? this.parent?.lookupPath(name) ?? null;
|
|
3820
|
+
}
|
|
3489
3821
|
registerMacros(macros) {
|
|
3490
3822
|
for (const key in macros) {
|
|
3491
3823
|
const lower = key.toLowerCase();
|
|
@@ -3517,17 +3849,16 @@ var init_components = __esm({
|
|
|
3517
3849
|
lookupComponent(name) {
|
|
3518
3850
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
3519
3851
|
}
|
|
3520
|
-
//
|
|
3521
|
-
// names
|
|
3522
|
-
//
|
|
3523
|
-
//
|
|
3524
|
-
//
|
|
3525
|
-
|
|
3852
|
+
// Whether anything in this scope chain provides `name`. Existence only: a lookup
|
|
3853
|
+
// names what it WANTS and takes whoever is nearest above it at render time, so
|
|
3854
|
+
// there is no producer to identify — several components may publish one name and
|
|
3855
|
+
// the live render ancestry decides. Used by the linter to tell a lookup that can
|
|
3856
|
+
// be satisfied from one that never will be.
|
|
3857
|
+
hasProvider(name) {
|
|
3526
3858
|
for (const compName in this.byName) {
|
|
3527
|
-
|
|
3528
|
-
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
3859
|
+
if (this.byName[compName].provide?.[name] !== void 0) return true;
|
|
3529
3860
|
}
|
|
3530
|
-
return this.parent?.
|
|
3861
|
+
return this.parent?.hasProvider(name) ?? false;
|
|
3531
3862
|
}
|
|
3532
3863
|
lookupMacro(name) {
|
|
3533
3864
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
@@ -3544,10 +3875,6 @@ var init_components = __esm({
|
|
|
3544
3875
|
}
|
|
3545
3876
|
};
|
|
3546
3877
|
isString = (v) => typeof v === "string";
|
|
3547
|
-
isTypeName = (s) => {
|
|
3548
|
-
const c = s.charCodeAt(0);
|
|
3549
|
-
return c >= 65 && c <= 90;
|
|
3550
|
-
};
|
|
3551
3878
|
_rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
3552
3879
|
KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
3553
3880
|
_compId = 0;
|
|
@@ -5958,7 +6285,6 @@ function checkComponent(Comp, lx = new LintContext(), { wellKnownExtras = EMPTY_
|
|
|
5958
6285
|
checkFieldMethodNameCollisions(lx, Comp);
|
|
5959
6286
|
checkProvidesAreAddressable(lx, Comp);
|
|
5960
6287
|
checkProvidedTypes(lx, Comp);
|
|
5961
|
-
checkProvideNameCollisions(lx, Comp);
|
|
5962
6288
|
checkLookupShapes(lx, Comp);
|
|
5963
6289
|
checkLookupTypesResolve(lx, Comp);
|
|
5964
6290
|
checkLookupsHaveProviders(lx, Comp);
|
|
@@ -6533,19 +6859,6 @@ function checkProvidedTypes(lx, Comp) {
|
|
|
6533
6859
|
if (raw !== "self") lx.error(PROVIDE_TYPE_BAD_SHAPE, { name, value: raw });
|
|
6534
6860
|
}
|
|
6535
6861
|
}
|
|
6536
|
-
function checkProvideNameCollisions(lx, Comp) {
|
|
6537
|
-
const scope = Comp.scope;
|
|
6538
|
-
if (!scope) return;
|
|
6539
|
-
for (const name in Comp.provide) {
|
|
6540
|
-
for (let s = scope; s; s = s.parent) {
|
|
6541
|
-
for (const otherName in s.byName) {
|
|
6542
|
-
const Other = s.byName[otherName];
|
|
6543
|
-
if (Other !== Comp && Other.provide?.[name] !== void 0)
|
|
6544
|
-
lx.error(PROVIDE_NAME_COLLISION, { name, other: Other.name });
|
|
6545
|
-
}
|
|
6546
|
-
}
|
|
6547
|
-
}
|
|
6548
|
-
}
|
|
6549
6862
|
function checkLookupShapes(lx, Comp) {
|
|
6550
6863
|
const raw = Comp._rawLookup;
|
|
6551
6864
|
if (!Array.isArray(raw)) {
|
|
@@ -6586,7 +6899,7 @@ function checkLookupsHaveProviders(lx, Comp) {
|
|
|
6586
6899
|
if (!scope) return;
|
|
6587
6900
|
for (const name in Comp.lookup) {
|
|
6588
6901
|
if (isTypeName2(name)) continue;
|
|
6589
|
-
if (scope.
|
|
6902
|
+
if (scope.hasProvider?.(name) || scope.lookupPath?.(name)) continue;
|
|
6590
6903
|
const info = { name, hasDefault: Comp.lookup[name].val != null };
|
|
6591
6904
|
if (info.hasDefault) lx.hint(LOOKUP_NO_PROVIDER, info);
|
|
6592
6905
|
else lx.error(LOOKUP_NO_PROVIDER, info);
|
|
@@ -6608,7 +6921,7 @@ function checkUnreferencedDynamics(lx, Comp, referencedDynamics) {
|
|
|
6608
6921
|
}
|
|
6609
6922
|
}
|
|
6610
6923
|
}
|
|
6611
|
-
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, isTypeName2, ALT_HANDLER_NOT_DEFINED, ALT_HANDLER_NOT_REFERENCED, DYN_VAL_NOT_DEFINED, DYN_ALIAS_NOT_REFERENCED, PROVIDE_NOT_ADDRESSABLE, PROVIDE_TYPE_BAD_SHAPE,
|
|
6924
|
+
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, isTypeName2, ALT_HANDLER_NOT_DEFINED, ALT_HANDLER_NOT_REFERENCED, DYN_VAL_NOT_DEFINED, DYN_ALIAS_NOT_REFERENCED, PROVIDE_NOT_ADDRESSABLE, PROVIDE_TYPE_BAD_SHAPE, LOOKUP_BAD_SHAPE, LOOKUP_NO_PROVIDER, RENDER_IT_OUTSIDE_OF_LOOP, UNKNOWN_EVENT_MODIFIER, RECEIVE_HANDLER_NOT_IMPLEMENTED, EVENT_HANDLER_METHOD_NOT_ALLOWED, HANDLER_NAME_COLLISION, FIELD_VAL_NOT_DEFINED, FIELD_VAL_IS_METHOD, METHOD_VAL_NOT_DEFINED, METHOD_VAL_IS_FIELD, DUPLICATE_ATTR_DEFINITION, IF_NO_BRANCH_SET, UNKNOWN_COMPONENT_NAME, UNKNOWN_MACRO_ARG, UNKNOWN_DIRECTIVE, UNKNOWN_X_OP, UNKNOWN_X_ATTR, X_OP_IGNORES_CHILDREN, MAYBE_DROP_AT_PREFIX, MAYBE_ADD_AT_PREFIX, BAD_VALUE, UNSUPPORTED_EXPR_SYNTAX, BINDING_MEMBER_TOO_DEEP, SUGGEST_BINDING_MEMBER, REDUNDANT_TEMPLATE_STRING, PLACEHOLDERLESS_TEMPLATE_STRING, CONSTANT_CONDITION, UNKNOWN_COMPONENT_SPEC_KEY, COMP_FIELD_BAD_SHAPE, ASYNC_HANDLER, TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE, GLOBAL_SELECTOR_IN_SCOPED_STYLE, FIELD_METHOD_NAME_COLLISION, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2, LEVEL_ERROR2, LEVEL_HINT, PARSE_ISSUES, BINDING_MEMBER_TOO_DEEP_RE, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS2, ANY_EVENT_MODIFIERS, fixTo, BOOL_CONDITION_ORIGINS, isBoolConditionCtx, ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun, STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintContext, LintParseContext;
|
|
6612
6925
|
var init_lint_check = __esm({
|
|
6613
6926
|
"tools/core/lint-check.js"() {
|
|
6614
6927
|
init_anode();
|
|
@@ -6646,7 +6959,6 @@ var init_lint_check = __esm({
|
|
|
6646
6959
|
DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED";
|
|
6647
6960
|
PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE";
|
|
6648
6961
|
PROVIDE_TYPE_BAD_SHAPE = "PROVIDE_TYPE_BAD_SHAPE";
|
|
6649
|
-
PROVIDE_NAME_COLLISION = "PROVIDE_NAME_COLLISION";
|
|
6650
6962
|
LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE";
|
|
6651
6963
|
LOOKUP_NO_PROVIDER = "LOOKUP_NO_PROVIDER";
|
|
6652
6964
|
RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP";
|
|
@@ -6974,7 +7286,7 @@ var init_lint_rules = __esm({
|
|
|
6974
7286
|
code: LOOKUP_NO_PROVIDER,
|
|
6975
7287
|
level: "error",
|
|
6976
7288
|
group: "Dynamic bindings",
|
|
6977
|
-
summary: "`lookup` name is provided
|
|
7289
|
+
summary: "`lookup` name is neither provided in scope nor a registered path."
|
|
6978
7290
|
},
|
|
6979
7291
|
{
|
|
6980
7292
|
code: PROVIDE_TYPE_BAD_SHAPE,
|
|
@@ -6982,12 +7294,6 @@ var init_lint_rules = __esm({
|
|
|
6982
7294
|
group: "Dynamic bindings",
|
|
6983
7295
|
summary: 'A PascalCase `provide` publishes a component type; its value must be `"self"`.'
|
|
6984
7296
|
},
|
|
6985
|
-
{
|
|
6986
|
-
code: PROVIDE_NAME_COLLISION,
|
|
6987
|
-
level: "error",
|
|
6988
|
-
group: "Dynamic bindings",
|
|
6989
|
-
summary: "Two components in one scope chain `provide` the same name."
|
|
6990
|
-
},
|
|
6991
7297
|
// Templates / events
|
|
6992
7298
|
{
|
|
6993
7299
|
code: RENDER_IT_OUTSIDE_OF_LOOP,
|
|
@@ -7276,15 +7582,13 @@ function lintIdToMessage(id, info) {
|
|
|
7276
7582
|
case "DYN_ALIAS_NOT_REFERENCED":
|
|
7277
7583
|
return `Lookup '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
|
|
7278
7584
|
case "PROVIDE_NOT_ADDRESSABLE":
|
|
7279
|
-
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a
|
|
7585
|
+
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`;
|
|
7280
7586
|
case "LOOKUP_BAD_SHAPE":
|
|
7281
7587
|
return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
|
|
7282
7588
|
case "LOOKUP_NO_PROVIDER":
|
|
7283
|
-
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`;
|
|
7589
|
+
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`;
|
|
7284
7590
|
case "PROVIDE_TYPE_BAD_SHAPE":
|
|
7285
7591
|
return `Provide '${info.name}' starts uppercase, so it publishes a component type — its value must be 'self', not '${info.value}'`;
|
|
7286
|
-
case "PROVIDE_NAME_COLLISION":
|
|
7287
|
-
return `Provide '${info.name}' is also provided by '${info.other}' in the same scope — one name, one provider, so a lookup can find it`;
|
|
7288
7592
|
case "UNKNOWN_MACRO_ARG":
|
|
7289
7593
|
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
7290
7594
|
case "UNKNOWN_DIRECTIVE":
|
|
@@ -12759,165 +13063,6 @@ var init_list = __esm({
|
|
|
12759
13063
|
}
|
|
12760
13064
|
});
|
|
12761
13065
|
|
|
12762
|
-
// src/stack.js
|
|
12763
|
-
function routeLookup(route, lex, dyn) {
|
|
12764
|
-
for (let i = 0; i < route.length; i++) {
|
|
12765
|
-
const leg = route[i];
|
|
12766
|
-
if (leg === "dyn") {
|
|
12767
|
-
const v = dyn();
|
|
12768
|
-
if (v != null) return v;
|
|
12769
|
-
} else if (leg === "lex") {
|
|
12770
|
-
const v = lex();
|
|
12771
|
-
if (v != null) return v;
|
|
12772
|
-
} else {
|
|
12773
|
-
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
12774
|
-
}
|
|
12775
|
-
}
|
|
12776
|
-
return null;
|
|
12777
|
-
}
|
|
12778
|
-
function lookup(chain, name, dv = null) {
|
|
12779
|
-
let n = chain;
|
|
12780
|
-
while (n !== null) {
|
|
12781
|
-
const r = n[0].lookup(name);
|
|
12782
|
-
if (r === STOP) return dv;
|
|
12783
|
-
if (r !== NEXT) return r;
|
|
12784
|
-
n = n[1];
|
|
12785
|
-
}
|
|
12786
|
-
return dv;
|
|
12787
|
-
}
|
|
12788
|
-
function computeViewsId(views) {
|
|
12789
|
-
let s = "";
|
|
12790
|
-
let n = views;
|
|
12791
|
-
while (n !== null) {
|
|
12792
|
-
s += n[0];
|
|
12793
|
-
n = n[1];
|
|
12794
|
-
}
|
|
12795
|
-
return s === "main" ? "" : s;
|
|
12796
|
-
}
|
|
12797
|
-
var STOP, NEXT, DEFAULT_ROUTE, BindFrame, ObjectFrame, Stack;
|
|
12798
|
-
var init_stack = __esm({
|
|
12799
|
-
"src/stack.js"() {
|
|
12800
|
-
STOP = /* @__PURE__ */ Symbol("STOP");
|
|
12801
|
-
NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
12802
|
-
DEFAULT_ROUTE = ["dyn", "lex"];
|
|
12803
|
-
BindFrame = class {
|
|
12804
|
-
constructor(it, binds, isFrame) {
|
|
12805
|
-
this.it = it;
|
|
12806
|
-
this.binds = binds;
|
|
12807
|
-
this.isFrame = isFrame;
|
|
12808
|
-
}
|
|
12809
|
-
lookup(name) {
|
|
12810
|
-
const v = this.binds[name];
|
|
12811
|
-
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
12812
|
-
}
|
|
12813
|
-
};
|
|
12814
|
-
ObjectFrame = class {
|
|
12815
|
-
constructor(binds) {
|
|
12816
|
-
this.binds = binds;
|
|
12817
|
-
}
|
|
12818
|
-
lookup(key) {
|
|
12819
|
-
const v = this.binds[key];
|
|
12820
|
-
return v === void 0 ? NEXT : v;
|
|
12821
|
-
}
|
|
12822
|
-
};
|
|
12823
|
-
Stack = class _Stack {
|
|
12824
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
12825
|
-
this.comps = comps;
|
|
12826
|
-
this.it = it;
|
|
12827
|
-
this.binds = binds;
|
|
12828
|
-
this.dynBinds = dynBinds;
|
|
12829
|
-
this.views = views;
|
|
12830
|
-
this.viewsId = viewsId;
|
|
12831
|
-
this.ctx = ctx;
|
|
12832
|
-
}
|
|
12833
|
-
// Evaluate every provide the entered component publishes and push them as one
|
|
12834
|
-
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
12835
|
-
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
12836
|
-
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
12837
|
-
_pushProvides() {
|
|
12838
|
-
const comp = this.comps.getCompFor(this.it);
|
|
12839
|
-
if (comp == null) return this;
|
|
12840
|
-
const { provide, provideType } = comp;
|
|
12841
|
-
const dynObj = {};
|
|
12842
|
-
let has2 = false;
|
|
12843
|
-
for (const k in provide) {
|
|
12844
|
-
dynObj[k] = provide[k].val.eval(this);
|
|
12845
|
-
has2 = true;
|
|
12846
|
-
}
|
|
12847
|
-
for (const k in provideType) {
|
|
12848
|
-
dynObj[k] = provideType[k];
|
|
12849
|
-
has2 = true;
|
|
12850
|
-
}
|
|
12851
|
-
if (!has2) return this;
|
|
12852
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
12853
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
12854
|
-
return new _Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
12855
|
-
}
|
|
12856
|
-
static root(comps, it, ctx) {
|
|
12857
|
-
const binds = [new BindFrame(it, {}, true), null];
|
|
12858
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
12859
|
-
const views = ["main", null];
|
|
12860
|
-
return new _Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
12861
|
-
}
|
|
12862
|
-
enter(it, bindings = {}, isFrame = true) {
|
|
12863
|
-
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
12864
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
12865
|
-
const stack = new _Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
12866
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
12867
|
-
}
|
|
12868
|
-
pushViewName(name) {
|
|
12869
|
-
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
12870
|
-
const newViews = [name, views];
|
|
12871
|
-
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
12872
|
-
}
|
|
12873
|
-
// Published types are stable per scope and would only churn the render cache, so
|
|
12874
|
-
// the cache key covers values alone.
|
|
12875
|
-
_pushDynBindValuesToArray(arr, comp) {
|
|
12876
|
-
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
12877
|
-
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
12878
|
-
}
|
|
12879
|
-
// `*name`: the nearest binding above (including this component's own provides,
|
|
12880
|
-
// pushed on entering it), else this component's declared default, else null.
|
|
12881
|
-
lookupDynamic(name) {
|
|
12882
|
-
const v = lookup(this.dynBinds, name);
|
|
12883
|
-
if (v != null) return v;
|
|
12884
|
-
const comp = this.comps.getCompFor(this.it);
|
|
12885
|
-
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
12886
|
-
}
|
|
12887
|
-
lookupBind(name) {
|
|
12888
|
-
return lookup(this.binds, name);
|
|
12889
|
-
}
|
|
12890
|
-
lookupFieldRaw(name) {
|
|
12891
|
-
return this.it[name] ?? null;
|
|
12892
|
-
}
|
|
12893
|
-
lookupMethod(name) {
|
|
12894
|
-
const fn = this.it[name];
|
|
12895
|
-
return fn instanceof Function ? fn.call(this.it) : null;
|
|
12896
|
-
}
|
|
12897
|
-
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
12898
|
-
// `e.<member>` handler args. Null outside a live event transaction.
|
|
12899
|
-
lookupEvent() {
|
|
12900
|
-
return this.ctx?.event ?? null;
|
|
12901
|
-
}
|
|
12902
|
-
lookupDragInfo() {
|
|
12903
|
-
return this.ctx?.dragInfo ?? null;
|
|
12904
|
-
}
|
|
12905
|
-
getHandlerFor(name, key) {
|
|
12906
|
-
return this.comps.getHandlerFor(this.it, name, key);
|
|
12907
|
-
}
|
|
12908
|
-
lookupBestView(views, defaultViewName) {
|
|
12909
|
-
let n = this.views;
|
|
12910
|
-
while (n !== null) {
|
|
12911
|
-
const view = views[n[0]];
|
|
12912
|
-
if (view !== void 0) return view;
|
|
12913
|
-
n = n[1];
|
|
12914
|
-
}
|
|
12915
|
-
return views[defaultViewName];
|
|
12916
|
-
}
|
|
12917
|
-
};
|
|
12918
|
-
}
|
|
12919
|
-
});
|
|
12920
|
-
|
|
12921
13066
|
// src/oo.js
|
|
12922
13067
|
function mkCompField(field, scope, args) {
|
|
12923
13068
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
@@ -13203,7 +13348,7 @@ function warnNotIntent(verb) {
|
|
|
13203
13348
|
console.warn(`ctx.${verb}() is only meaningful in an "intent" handler - ignored`);
|
|
13204
13349
|
}
|
|
13205
13350
|
function rootDispatcher(transactor) {
|
|
13206
|
-
return new Dispatcher(new
|
|
13351
|
+
return new Dispatcher(new DispatchPath(), transactor, null);
|
|
13207
13352
|
}
|
|
13208
13353
|
var State2, Transactor, Transaction, InputEvent, NameArgsTransaction, SendEvent, IntentEvent, PASS, REFUSAL_RING_CAP, INTENT_DEPTH, IntentWalk, Completion, Dispatcher, EventContext, PathChanges;
|
|
13209
13354
|
var init_transactor = __esm({
|
|
@@ -13340,9 +13485,11 @@ var init_transactor = __esm({
|
|
|
13340
13485
|
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
13341
13486
|
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
13342
13487
|
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
13343
|
-
pushSend(path, name, args = [], parent = null, origin = null) {
|
|
13488
|
+
pushSend(path, name, args = [], parent = null, origin = null, txnPath = null) {
|
|
13344
13489
|
const t = new SendEvent(path, this, name, args, parent);
|
|
13345
|
-
t.
|
|
13490
|
+
t.txnPath = txnPath;
|
|
13491
|
+
t.origin = origin;
|
|
13492
|
+
t.originPinned = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
13346
13493
|
this.pushTransaction(t);
|
|
13347
13494
|
return this._link(t, parent);
|
|
13348
13495
|
}
|
|
@@ -13392,6 +13539,7 @@ var init_transactor = __esm({
|
|
|
13392
13539
|
Transaction = class {
|
|
13393
13540
|
constructor(path, transactor, parentTransaction = null) {
|
|
13394
13541
|
this.path = path;
|
|
13542
|
+
this.txnPath = null;
|
|
13395
13543
|
this.transactor = transactor;
|
|
13396
13544
|
this.parentTransaction = parentTransaction;
|
|
13397
13545
|
this._completion = null;
|
|
@@ -13440,9 +13588,11 @@ var init_transactor = __esm({
|
|
|
13440
13588
|
getHandlerAndArgs(_root, _instance, _comps) {
|
|
13441
13589
|
return null;
|
|
13442
13590
|
}
|
|
13443
|
-
// The path used to apply the mutation
|
|
13444
|
-
//
|
|
13591
|
+
// The path used to apply the mutation: the ACTIVE frame of the dispatch path, so
|
|
13592
|
+
// an event inside a `<x render="*name">` subtree updates the value where it
|
|
13593
|
+
// really lives (the dispatch `this.path` keeps the visual callers, for bubbling).
|
|
13445
13594
|
getTransactionPath() {
|
|
13595
|
+
if (this.txnPath !== null) return this.txnPath;
|
|
13446
13596
|
return this.path.toTransactionPath().compact();
|
|
13447
13597
|
}
|
|
13448
13598
|
run(curRoot, comps) {
|
|
@@ -13467,8 +13617,9 @@ var init_transactor = __esm({
|
|
|
13467
13617
|
this.dragInfo = dragInfo;
|
|
13468
13618
|
this._dispatchPath = null;
|
|
13469
13619
|
}
|
|
13470
|
-
// Frame steps removed,
|
|
13471
|
-
//
|
|
13620
|
+
// Frame-only steps removed, one step per crossed component kept — inside every
|
|
13621
|
+
// continuation frame independently, so bubbling it visits every component and
|
|
13622
|
+
// then returns to the caller that wrote the `*name`.
|
|
13472
13623
|
get dispatchPath() {
|
|
13473
13624
|
this._dispatchPath ??= this.path.compact();
|
|
13474
13625
|
return this._dispatchPath;
|
|
@@ -13503,7 +13654,7 @@ var init_transactor = __esm({
|
|
|
13503
13654
|
this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
|
|
13504
13655
|
}
|
|
13505
13656
|
getHandlerAndArgs(root, _instance, comps) {
|
|
13506
|
-
const stack = this.path.
|
|
13657
|
+
const stack = this.path.buildStack(Stack.root(comps, root, this));
|
|
13507
13658
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
13508
13659
|
this._handlerArgs = [...args];
|
|
13509
13660
|
const path = this.dispatchPath;
|
|
@@ -13629,7 +13780,7 @@ var init_transactor = __esm({
|
|
|
13629
13780
|
while (this.legIndex < this.route.length) {
|
|
13630
13781
|
const leg = this.route[this.legIndex];
|
|
13631
13782
|
if (leg === "dyn") {
|
|
13632
|
-
if (this.dynAt.
|
|
13783
|
+
if (!this.dynAt.canPop()) {
|
|
13633
13784
|
this.legIndex++;
|
|
13634
13785
|
continue;
|
|
13635
13786
|
}
|
|
@@ -13726,8 +13877,8 @@ var init_transactor = __esm({
|
|
|
13726
13877
|
if (this.ended) return;
|
|
13727
13878
|
this.ended = true;
|
|
13728
13879
|
if (name === null) return this.release?.();
|
|
13729
|
-
const
|
|
13730
|
-
|
|
13880
|
+
const t = new SendEvent(this.origin, this.transactor, name, args, this.parent);
|
|
13881
|
+
t.txnPath = this.answerPath;
|
|
13731
13882
|
t._isAnswer = true;
|
|
13732
13883
|
this.transactor.pushTransaction(t);
|
|
13733
13884
|
if (this.release) t.completion.whenSubtreeSettled().then(this.release);
|
|
@@ -13822,7 +13973,9 @@ var init_transactor = __esm({
|
|
|
13822
13973
|
// replayed; provides are pushed on every component frame either way, so a provide
|
|
13823
13974
|
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
13824
13975
|
_stack() {
|
|
13825
|
-
this._stackMemo ??= this.path.
|
|
13976
|
+
this._stackMemo ??= this.path.buildStack(
|
|
13977
|
+
Stack.root(this.transactor.comps, this.root, this.parent)
|
|
13978
|
+
);
|
|
13826
13979
|
return this._stackMemo;
|
|
13827
13980
|
}
|
|
13828
13981
|
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
@@ -13836,14 +13989,19 @@ var init_transactor = __esm({
|
|
|
13836
13989
|
);
|
|
13837
13990
|
}
|
|
13838
13991
|
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
13839
|
-
// running, which is the leaf of this ctx's path.
|
|
13992
|
+
// running, which is the leaf of this ctx's path. A type name resolves to the
|
|
13993
|
+
// component registered under it; a value name to a path registered under it
|
|
13994
|
+
// (see ComponentStack.registerPaths), read against the current root.
|
|
13840
13995
|
_lookupLex(name) {
|
|
13841
13996
|
let Comp = null;
|
|
13842
13997
|
this.walkPath((c) => {
|
|
13843
13998
|
Comp = c;
|
|
13844
13999
|
return false;
|
|
13845
14000
|
});
|
|
13846
|
-
|
|
14001
|
+
const scope = Comp?.scope;
|
|
14002
|
+
if (scope == null) return null;
|
|
14003
|
+
if (isTypeName(name)) return scope.lookupComponent(name) ?? null;
|
|
14004
|
+
return scope.lookupPath(name)?.lookup(this.root) ?? null;
|
|
13847
14005
|
}
|
|
13848
14006
|
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
13849
14007
|
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
@@ -13904,7 +14062,14 @@ var init_transactor = __esm({
|
|
|
13904
14062
|
this.transactor.refuse("NO_SENDER", { name });
|
|
13905
14063
|
return null;
|
|
13906
14064
|
}
|
|
13907
|
-
return this.
|
|
14065
|
+
return this.transactor.pushSend(
|
|
14066
|
+
origin,
|
|
14067
|
+
name,
|
|
14068
|
+
args,
|
|
14069
|
+
this.parent,
|
|
14070
|
+
this.path,
|
|
14071
|
+
this.parent.originPinned
|
|
14072
|
+
);
|
|
13908
14073
|
}
|
|
13909
14074
|
// End the walk answering nothing — "served, and no answer".
|
|
13910
14075
|
stop() {
|
|
@@ -14015,7 +14180,7 @@ var init_app = __esm({
|
|
|
14015
14180
|
const { type: type3 } = e;
|
|
14016
14181
|
const isDrag = type3 === "dragover" || type3 === "dragstart" || type3 === "dragend" || type3 === "drop";
|
|
14017
14182
|
const { rootNode: root, maxEventNodeDepth: maxDepth, comps, transactor } = this;
|
|
14018
|
-
const [path, handlers] =
|
|
14183
|
+
const [path, handlers] = DispatchPath.fromNodeAndEventName(
|
|
14019
14184
|
e.target,
|
|
14020
14185
|
type3,
|
|
14021
14186
|
root,
|
|
@@ -14083,7 +14248,7 @@ var init_app = __esm({
|
|
|
14083
14248
|
const txnPath = path.compact().toTransactionPath();
|
|
14084
14249
|
const value = txnPath.lookup(rootValue);
|
|
14085
14250
|
const dragType = e.target.dataset.dragtype ?? "?";
|
|
14086
|
-
const stack = path.
|
|
14251
|
+
const stack = path.buildStack(this.makeStack(rootValue));
|
|
14087
14252
|
this.dragInfo = new DragInfo(stack, value, dragType, e.target);
|
|
14088
14253
|
} else if (type3 === "drop") {
|
|
14089
14254
|
e.preventDefault();
|
|
@@ -14158,7 +14323,7 @@ var init_app = __esm({
|
|
|
14158
14323
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
14159
14324
|
}
|
|
14160
14325
|
sendAtRoot(name, args) {
|
|
14161
|
-
this.transactor.pushSend(new
|
|
14326
|
+
this.transactor.pushSend(new DispatchPath(), name, args);
|
|
14162
14327
|
}
|
|
14163
14328
|
registerComponents(comps, opts) {
|
|
14164
14329
|
const scope = this.compStack.enter();
|
|
@@ -14302,13 +14467,28 @@ var init_cache = __esm({
|
|
|
14302
14467
|
});
|
|
14303
14468
|
|
|
14304
14469
|
// src/renderer.js
|
|
14470
|
+
function stampRenderBase(vdom, text) {
|
|
14471
|
+
if (vdom instanceof VNode)
|
|
14472
|
+
return new VNode(
|
|
14473
|
+
vdom.tag,
|
|
14474
|
+
{ ...vdom.attrs, "data-rp": text },
|
|
14475
|
+
vdom.childs,
|
|
14476
|
+
vdom.key,
|
|
14477
|
+
vdom.namespace
|
|
14478
|
+
);
|
|
14479
|
+
if (vdom instanceof VFragment)
|
|
14480
|
+
return new VFragment(vdom.childs.map((c) => stampRenderBase(c, text)));
|
|
14481
|
+
return vdom;
|
|
14482
|
+
}
|
|
14305
14483
|
var DATASET_ATTRS, Renderer;
|
|
14306
14484
|
var init_renderer = __esm({
|
|
14307
14485
|
"src/renderer.js"() {
|
|
14308
14486
|
init_cache();
|
|
14309
14487
|
init_iteration();
|
|
14488
|
+
init_path();
|
|
14489
|
+
init_value();
|
|
14310
14490
|
init_vdom();
|
|
14311
|
-
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
14491
|
+
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk", "rp"];
|
|
14312
14492
|
Renderer = class {
|
|
14313
14493
|
constructor(comps) {
|
|
14314
14494
|
this.comps = comps;
|
|
@@ -14345,17 +14525,17 @@ var init_renderer = __esm({
|
|
|
14345
14525
|
if (comp === null) return null;
|
|
14346
14526
|
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
14347
14527
|
}
|
|
14348
|
-
renderIt(stack, node, key, viewName) {
|
|
14528
|
+
renderIt(stack, node, key, viewName, base = null) {
|
|
14349
14529
|
const comp = this.comps.getCompFor(stack.it);
|
|
14350
|
-
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName) : null;
|
|
14530
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName, base) : null;
|
|
14351
14531
|
}
|
|
14352
14532
|
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
14353
14533
|
// `render-each`, or the view's root anode for the app root). It keys the
|
|
14354
14534
|
// cache as a globally-unique object: node ids alone are unique only within a
|
|
14355
14535
|
// single view, so the same value rendered by two components (e.g. through a
|
|
14356
14536
|
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
14357
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
14358
|
-
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
14537
|
+
_rValComp(stack, val, comp, node, key, viewName, base = null) {
|
|
14538
|
+
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}${stack.renderPath.addressKey}`;
|
|
14359
14539
|
const cachePath = [node, val];
|
|
14360
14540
|
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
14361
14541
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
@@ -14363,30 +14543,43 @@ var init_renderer = __esm({
|
|
|
14363
14543
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
14364
14544
|
const body = this.renderView(view, stack);
|
|
14365
14545
|
if (body == null) return null;
|
|
14546
|
+
const baseJson = base === null ? null : pathToJson(base);
|
|
14366
14547
|
const meta = this._renderMetadata({
|
|
14367
14548
|
$: "Comp",
|
|
14368
14549
|
nid: node?.nodeId ?? null,
|
|
14369
14550
|
cid: comp.id,
|
|
14370
|
-
vid: view.name
|
|
14551
|
+
vid: view.name,
|
|
14552
|
+
...baseJson === null ? null : { base: baseJson }
|
|
14371
14553
|
});
|
|
14372
|
-
const dom = new VFragment([
|
|
14554
|
+
const dom = new VFragment([
|
|
14555
|
+
meta,
|
|
14556
|
+
baseJson === null ? body : stampRenderBase(body, JSON.stringify(baseJson))
|
|
14557
|
+
]);
|
|
14373
14558
|
this.cache.set(cachePath, cacheKey, dom);
|
|
14374
14559
|
return dom;
|
|
14375
14560
|
}
|
|
14376
14561
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
14377
14562
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
14378
14563
|
}
|
|
14379
|
-
renderEachWhen(stack,
|
|
14564
|
+
renderEachWhen(stack, each2) {
|
|
14565
|
+
const { iterInfo, node: view, nodeId: nid } = each2;
|
|
14380
14566
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
14567
|
+
const seqPath = iterInfo.val instanceof DynVal ? stack.lookupDynamicLocated(iterInfo.val.name)?.path ?? null : null;
|
|
14381
14568
|
const r = [];
|
|
14382
14569
|
const it = stack.it;
|
|
14383
14570
|
const renderOne = (key, value, attrName, binds) => {
|
|
14571
|
+
const itemBase = seqPath === null ? null : keyedPath(seqPath, key);
|
|
14572
|
+
const itemStep = itemBase === null ? each2.itemStep(key) : null;
|
|
14573
|
+
const itemPath = itemBase !== null ? stack.renderPath.pushFrame(itemBase) : itemStep !== null ? stack.renderPath.pushItem(itemStep) : stack.renderPath;
|
|
14384
14574
|
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
14385
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
14575
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}${itemPath.addressKey}`;
|
|
14386
14576
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
14387
14577
|
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
14388
14578
|
else {
|
|
14389
|
-
const dom = this.renderView(
|
|
14579
|
+
const dom = this.renderView(
|
|
14580
|
+
view,
|
|
14581
|
+
stack.enter(value, binds, false, itemPath, itemBase !== null)
|
|
14582
|
+
);
|
|
14390
14583
|
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
14391
14584
|
this.cache.set(cachePath, cacheKey, dom);
|
|
14392
14585
|
}
|
|
@@ -14442,7 +14635,7 @@ function renderToHTMLNode(document2, components, macros, rootState, ParseContext
|
|
|
14442
14635
|
const comps = new Components();
|
|
14443
14636
|
const renderer = new Renderer(comps);
|
|
14444
14637
|
const app = new App(container, comps, renderer, ParseContext2);
|
|
14445
|
-
const scope = app.registerComponents(components);
|
|
14638
|
+
const scope = app.registerComponents(components, { paths: opts.paths });
|
|
14446
14639
|
if (macros) scope.registerMacros(macros);
|
|
14447
14640
|
if (opts.intentHandlers) scope.registerIntentHandlers(opts.intentHandlers);
|
|
14448
14641
|
app.rootViewName = opts.view ?? null;
|
|
@@ -14468,7 +14661,7 @@ async function renderToHTMLDriven(document2, components, macros, rootState, Pars
|
|
|
14468
14661
|
);
|
|
14469
14662
|
try {
|
|
14470
14663
|
if (phase) {
|
|
14471
|
-
dispatchPhase(rootDispatcher(app.transactor), new
|
|
14664
|
+
dispatchPhase(rootDispatcher(app.transactor), new DispatchPath(), phase, app.state.val);
|
|
14472
14665
|
await app.transactor.settle();
|
|
14473
14666
|
}
|
|
14474
14667
|
return serializeContainer(container);
|
|
@@ -14706,7 +14899,7 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
14706
14899
|
val
|
|
14707
14900
|
);
|
|
14708
14901
|
});
|
|
14709
|
-
dispatchPhase(rootDispatcher(transactor), new
|
|
14902
|
+
dispatchPhase(rootDispatcher(transactor), new DispatchPath(), phase, value);
|
|
14710
14903
|
await transactor.settle();
|
|
14711
14904
|
return transactor.state.val;
|
|
14712
14905
|
}
|