tutuca 0.13.2 → 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 +611 -458
- package/dist/tutuca-dev.ext.js +642 -486
- package/dist/tutuca-dev.js +653 -497
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +625 -451
- package/dist/tutuca-extra.js +632 -458
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.ext.js +625 -451
- package/dist/tutuca.js +632 -458
- 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 +7 -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 +625 -451
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;
|
|
@@ -1619,31 +1703,6 @@ function parseBool(s, px) {
|
|
|
1619
1703
|
const val = parseToken(tokens[0], px);
|
|
1620
1704
|
return val !== null && kindOf(val) & G_BOOL ? val : null;
|
|
1621
1705
|
}
|
|
1622
|
-
function parseText(s, px) {
|
|
1623
|
-
return _parseSingle(s, px, G_TEXT);
|
|
1624
|
-
}
|
|
1625
|
-
function parseComponent(s, px) {
|
|
1626
|
-
return _parseSingle(s, px, G_COMPONENT);
|
|
1627
|
-
}
|
|
1628
|
-
function parseSequence(s, px) {
|
|
1629
|
-
return _parseSingle(s, px, G_SEQUENCE);
|
|
1630
|
-
}
|
|
1631
|
-
function parseField(s, px) {
|
|
1632
|
-
return _parseSingle(s, px, G_FIELD);
|
|
1633
|
-
}
|
|
1634
|
-
function parseProvide(s, px) {
|
|
1635
|
-
return _parseSingle(s, px, G_PROVIDE);
|
|
1636
|
-
}
|
|
1637
|
-
function parseMacroAttr(s, px) {
|
|
1638
|
-
return _parseSingle(s, px, G_ALL);
|
|
1639
|
-
}
|
|
1640
|
-
function parseReceiveHandler(s, px) {
|
|
1641
|
-
return _parseHandler(s, px, "receive", true, true, false);
|
|
1642
|
-
}
|
|
1643
|
-
function parseAlterHandler(s, px) {
|
|
1644
|
-
const r = _parseHandler(s, px, "alter", false, false, true);
|
|
1645
|
-
return r === null ? null : r.handlerVal;
|
|
1646
|
-
}
|
|
1647
1706
|
function _parseHandler(s, px, namespace, allowArgs, report, allowMethod) {
|
|
1648
1707
|
const tokens = tokenizeValue(s.trim());
|
|
1649
1708
|
const headTok = tokens[0] ?? "";
|
|
@@ -1713,7 +1772,7 @@ function kindOf(val) {
|
|
|
1713
1772
|
if (val instanceof EventMemberVal) return K_EVENT;
|
|
1714
1773
|
return 0;
|
|
1715
1774
|
}
|
|
1716
|
-
var VALID_VAL_ID_RE, isValidValId, VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal, VAL_TOKEN_RE, tokenizeValue, unescapeStr, K_CONST, K_STRTPL, K_FIELD, K_BIND, K_DYN, K_NAME, K_SEQ, K_METHOD, K_EVENT, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_HANDLER_ARG, G_ALL, toNullIfNaN, predTruthy, PREDICATES, BaseVal, ConstVal, NULL_CONST_VAL, PredicateVal, VarVal, StrTplVal, NameVal, HandlerNameVal, mk404Handler, keyIs, macCtrl, nullSafe, EVENT_CONVENIENCES, EventMemberVal, RenderVal, RenderNameVal, BindVal, BindMemberVal, DynVal, FieldVal, MethodVal, SeqAccessVal;
|
|
1775
|
+
var VALID_VAL_ID_RE, isValidValId, VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal, VAL_TOKEN_RE, tokenizeValue, unescapeStr, K_CONST, K_STRTPL, K_FIELD, K_BIND, K_DYN, K_NAME, K_SEQ, K_METHOD, K_EVENT, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_HANDLER_ARG, G_ALL, toNullIfNaN, predTruthy, PREDICATES, parseText, parseComponent, parseSequence, parseField, parseProvide, parseMacroAttr, parseReceiveHandler, parseAlterHandler, BaseVal, ConstVal, NULL_CONST_VAL, PredicateVal, VarVal, StrTplVal, NameVal, HandlerNameVal, mk404Handler, keyIs, macCtrl, nullSafe, EVENT_CONVENIENCES, EventMemberVal, RenderVal, RenderNameVal, BindVal, BindMemberVal, DynVal, FieldVal, MethodVal, SeqAccessVal;
|
|
1717
1776
|
var init_value = __esm({
|
|
1718
1777
|
"src/value.js"() {
|
|
1719
1778
|
init_collection();
|
|
@@ -1757,6 +1816,14 @@ var init_value = __esm({
|
|
|
1757
1816
|
"null?": { name: "null?", arity: 1, fn: (v) => v == null },
|
|
1758
1817
|
"equals?": { name: "equals?", arity: 2, fn: (a, b) => Object.is(a, b) }
|
|
1759
1818
|
};
|
|
1819
|
+
parseText = (s, px) => _parseSingle(s, px, G_TEXT);
|
|
1820
|
+
parseComponent = (s, px) => _parseSingle(s, px, G_COMPONENT);
|
|
1821
|
+
parseSequence = (s, px) => _parseSingle(s, px, G_SEQUENCE);
|
|
1822
|
+
parseField = (s, px) => _parseSingle(s, px, G_FIELD);
|
|
1823
|
+
parseProvide = (s, px) => _parseSingle(s, px, G_PROVIDE);
|
|
1824
|
+
parseMacroAttr = (s, px) => _parseSingle(s, px, G_ALL);
|
|
1825
|
+
parseReceiveHandler = (s, px) => _parseHandler(s, px, "receive", true, true, false);
|
|
1826
|
+
parseAlterHandler = (s, px) => _parseHandler(s, px, "alter", false, false, true)?.handlerVal ?? null;
|
|
1760
1827
|
BaseVal = class {
|
|
1761
1828
|
render(_stack, _rx) {
|
|
1762
1829
|
}
|
|
@@ -2558,6 +2625,10 @@ function morphChildren(parentDom, oldChilds, newChilds, opts) {
|
|
|
2558
2625
|
if (!used2[i] && domNodes[i].parentNode === parentDom) parentDom.removeChild(domNodes[i]);
|
|
2559
2626
|
}
|
|
2560
2627
|
function render(vnode, container, options, prev) {
|
|
2628
|
+
if (vnode == null) {
|
|
2629
|
+
container.replaceChildren();
|
|
2630
|
+
return { vnode: null, dom: null };
|
|
2631
|
+
}
|
|
2561
2632
|
const isFragment = vnode instanceof VFragment;
|
|
2562
2633
|
if (prev && prev.vnode instanceof VFragment === isFragment) {
|
|
2563
2634
|
const oldDom = isFragment ? container : prev.dom;
|
|
@@ -2607,19 +2678,9 @@ var init_vdom = __esm({
|
|
|
2607
2678
|
};
|
|
2608
2679
|
isForeignObject = (tag) => tag.length === 13 && tag.toLowerCase() === "foreignobject";
|
|
2609
2680
|
effectiveNs = (vnode, opts) => vnode.namespace ?? opts.namespace ?? null;
|
|
2610
|
-
NEVER_ASSIGN =
|
|
2611
|
-
"width"
|
|
2612
|
-
|
|
2613
|
-
"href",
|
|
2614
|
-
"list",
|
|
2615
|
-
"form",
|
|
2616
|
-
"tabIndex",
|
|
2617
|
-
"download",
|
|
2618
|
-
"rowSpan",
|
|
2619
|
-
"colSpan",
|
|
2620
|
-
"role",
|
|
2621
|
-
"popover"
|
|
2622
|
-
]);
|
|
2681
|
+
NEVER_ASSIGN = new Set(
|
|
2682
|
+
"width height href list form tabIndex download rowSpan colSpan role popover".split(" ")
|
|
2683
|
+
);
|
|
2623
2684
|
PROP_ATTR_NAME = { className: "class", htmlFor: "for" };
|
|
2624
2685
|
VBase = class {
|
|
2625
2686
|
};
|
|
@@ -2725,13 +2786,16 @@ var init_vdom = __esm({
|
|
|
2725
2786
|
});
|
|
2726
2787
|
|
|
2727
2788
|
// src/anode.js
|
|
2728
|
-
function
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
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];
|
|
2735
2799
|
}
|
|
2736
2800
|
function optimizeChilds(childs) {
|
|
2737
2801
|
for (let i = 0; i < childs.length; i++) {
|
|
@@ -2839,11 +2903,6 @@ function makeWrapperNode(data, px) {
|
|
|
2839
2903
|
}
|
|
2840
2904
|
return node;
|
|
2841
2905
|
}
|
|
2842
|
-
function dynRenderStep(comp, name, key) {
|
|
2843
|
-
const p = resolveDynProducer(comp, name);
|
|
2844
|
-
if (!p) return null;
|
|
2845
|
-
return key === void 0 ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
2846
|
-
}
|
|
2847
2906
|
function parseRenderEach(px, value, as, attrs) {
|
|
2848
2907
|
const seqVal = parseXOpVal("render-each", value, px, parseSequence);
|
|
2849
2908
|
if (seqVal === null) return null;
|
|
@@ -3113,26 +3172,29 @@ var init_anode = __esm({
|
|
|
3113
3172
|
};
|
|
3114
3173
|
RenderNode = class extends RenderViewId {
|
|
3115
3174
|
render(stack, rx) {
|
|
3116
|
-
const
|
|
3117
|
-
|
|
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);
|
|
3118
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.
|
|
3119
3181
|
toPathStep(ctx) {
|
|
3120
|
-
if (this.val instanceof DynVal) return
|
|
3182
|
+
if (this.val instanceof DynVal) return null;
|
|
3121
3183
|
return super.toPathStep(ctx);
|
|
3122
3184
|
}
|
|
3123
3185
|
};
|
|
3124
3186
|
RenderItNode = class extends RenderViewId {
|
|
3125
3187
|
render(stack, rx) {
|
|
3126
|
-
const
|
|
3127
|
-
|
|
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);
|
|
3128
3191
|
}
|
|
3129
3192
|
toPathStep(ctx) {
|
|
3130
3193
|
const next = ctx.next();
|
|
3131
3194
|
if (next === null) return null;
|
|
3132
3195
|
const nextNode = next.resolveNode();
|
|
3133
3196
|
if (nextNode instanceof EachNode && next.hasKey) {
|
|
3134
|
-
if (nextNode.val instanceof DynVal)
|
|
3135
|
-
return dynRenderStep(ctx.comp, nextNode.val.name, next.key);
|
|
3197
|
+
if (nextNode.val instanceof DynVal) return null;
|
|
3136
3198
|
return new EachRenderItStep(nextNode.val.name, next.key);
|
|
3137
3199
|
}
|
|
3138
3200
|
return null;
|
|
@@ -3222,11 +3284,19 @@ var init_anode = __esm({
|
|
|
3222
3284
|
this.iterInfo = new IterInfo(val, null, null, null);
|
|
3223
3285
|
}
|
|
3224
3286
|
render(stack, rx) {
|
|
3225
|
-
return rx.renderEachWhen(stack, this
|
|
3287
|
+
return rx.renderEachWhen(stack, this);
|
|
3226
3288
|
}
|
|
3227
3289
|
toPathStep(ctx) {
|
|
3228
3290
|
return ctx.hasKey ? new EachBindStep(this.iterInfo, ctx.key) : null;
|
|
3229
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
|
+
}
|
|
3230
3300
|
static register = true;
|
|
3231
3301
|
};
|
|
3232
3302
|
IterInfo = class {
|
|
@@ -3447,11 +3517,227 @@ var init_anode = __esm({
|
|
|
3447
3517
|
}
|
|
3448
3518
|
});
|
|
3449
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
|
+
|
|
3450
3735
|
// src/components.js
|
|
3451
|
-
var COMPONENT, Components, ComponentStack, ProvideInfo, LookupInfo, isString,
|
|
3736
|
+
var COMPONENT, Components, ComponentStack, ProvideInfo, LookupInfo, isString, _rawSpecKeys, KNOWN_SPEC_KEYS, _compId, Component;
|
|
3452
3737
|
var init_components = __esm({
|
|
3453
3738
|
"src/components.js"() {
|
|
3454
3739
|
init_anode();
|
|
3740
|
+
init_stack();
|
|
3455
3741
|
init_value();
|
|
3456
3742
|
COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
3457
3743
|
Components = class {
|
|
@@ -3490,12 +3776,14 @@ var init_components = __esm({
|
|
|
3490
3776
|
this.byName = {};
|
|
3491
3777
|
this.intentsByName = {};
|
|
3492
3778
|
this.macros = {};
|
|
3779
|
+
this.paths = {};
|
|
3493
3780
|
}
|
|
3494
3781
|
enter() {
|
|
3495
3782
|
return new _ComponentStack(this.comps, this);
|
|
3496
3783
|
}
|
|
3497
3784
|
registerComponents(comps, opts) {
|
|
3498
|
-
const { aliases: aliases2 = {} } = opts ?? {};
|
|
3785
|
+
const { aliases: aliases2 = {}, paths } = opts ?? {};
|
|
3786
|
+
if (paths) this.registerPaths(paths);
|
|
3499
3787
|
for (let i = 0; i < comps.length; i++) {
|
|
3500
3788
|
const Comp = comps[i];
|
|
3501
3789
|
Comp[COMPONENT].scope = this.enter();
|
|
@@ -3509,6 +3797,27 @@ var init_components = __esm({
|
|
|
3509
3797
|
else console.warn("alias", alias, "to inexistent component", aliases2[alias]);
|
|
3510
3798
|
}
|
|
3511
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
|
+
}
|
|
3512
3821
|
registerMacros(macros) {
|
|
3513
3822
|
for (const key in macros) {
|
|
3514
3823
|
const lower = key.toLowerCase();
|
|
@@ -3540,17 +3849,16 @@ var init_components = __esm({
|
|
|
3540
3849
|
lookupComponent(name) {
|
|
3541
3850
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
3542
3851
|
}
|
|
3543
|
-
//
|
|
3544
|
-
// names
|
|
3545
|
-
//
|
|
3546
|
-
//
|
|
3547
|
-
//
|
|
3548
|
-
|
|
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) {
|
|
3549
3858
|
for (const compName in this.byName) {
|
|
3550
|
-
|
|
3551
|
-
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
3859
|
+
if (this.byName[compName].provide?.[name] !== void 0) return true;
|
|
3552
3860
|
}
|
|
3553
|
-
return this.parent?.
|
|
3861
|
+
return this.parent?.hasProvider(name) ?? false;
|
|
3554
3862
|
}
|
|
3555
3863
|
lookupMacro(name) {
|
|
3556
3864
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
@@ -3567,10 +3875,6 @@ var init_components = __esm({
|
|
|
3567
3875
|
}
|
|
3568
3876
|
};
|
|
3569
3877
|
isString = (v) => typeof v === "string";
|
|
3570
|
-
isTypeName = (s) => {
|
|
3571
|
-
const c = s.charCodeAt(0);
|
|
3572
|
-
return c >= 65 && c <= 90;
|
|
3573
|
-
};
|
|
3574
3878
|
_rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
3575
3879
|
KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
3576
3880
|
_compId = 0;
|
|
@@ -5981,7 +6285,6 @@ function checkComponent(Comp, lx = new LintContext(), { wellKnownExtras = EMPTY_
|
|
|
5981
6285
|
checkFieldMethodNameCollisions(lx, Comp);
|
|
5982
6286
|
checkProvidesAreAddressable(lx, Comp);
|
|
5983
6287
|
checkProvidedTypes(lx, Comp);
|
|
5984
|
-
checkProvideNameCollisions(lx, Comp);
|
|
5985
6288
|
checkLookupShapes(lx, Comp);
|
|
5986
6289
|
checkLookupTypesResolve(lx, Comp);
|
|
5987
6290
|
checkLookupsHaveProviders(lx, Comp);
|
|
@@ -6556,19 +6859,6 @@ function checkProvidedTypes(lx, Comp) {
|
|
|
6556
6859
|
if (raw !== "self") lx.error(PROVIDE_TYPE_BAD_SHAPE, { name, value: raw });
|
|
6557
6860
|
}
|
|
6558
6861
|
}
|
|
6559
|
-
function checkProvideNameCollisions(lx, Comp) {
|
|
6560
|
-
const scope = Comp.scope;
|
|
6561
|
-
if (!scope) return;
|
|
6562
|
-
for (const name in Comp.provide) {
|
|
6563
|
-
for (let s = scope; s; s = s.parent) {
|
|
6564
|
-
for (const otherName in s.byName) {
|
|
6565
|
-
const Other = s.byName[otherName];
|
|
6566
|
-
if (Other !== Comp && Other.provide?.[name] !== void 0)
|
|
6567
|
-
lx.error(PROVIDE_NAME_COLLISION, { name, other: Other.name });
|
|
6568
|
-
}
|
|
6569
|
-
}
|
|
6570
|
-
}
|
|
6571
|
-
}
|
|
6572
6862
|
function checkLookupShapes(lx, Comp) {
|
|
6573
6863
|
const raw = Comp._rawLookup;
|
|
6574
6864
|
if (!Array.isArray(raw)) {
|
|
@@ -6609,7 +6899,7 @@ function checkLookupsHaveProviders(lx, Comp) {
|
|
|
6609
6899
|
if (!scope) return;
|
|
6610
6900
|
for (const name in Comp.lookup) {
|
|
6611
6901
|
if (isTypeName2(name)) continue;
|
|
6612
|
-
if (scope.
|
|
6902
|
+
if (scope.hasProvider?.(name) || scope.lookupPath?.(name)) continue;
|
|
6613
6903
|
const info = { name, hasDefault: Comp.lookup[name].val != null };
|
|
6614
6904
|
if (info.hasDefault) lx.hint(LOOKUP_NO_PROVIDER, info);
|
|
6615
6905
|
else lx.error(LOOKUP_NO_PROVIDER, info);
|
|
@@ -6631,7 +6921,7 @@ function checkUnreferencedDynamics(lx, Comp, referencedDynamics) {
|
|
|
6631
6921
|
}
|
|
6632
6922
|
}
|
|
6633
6923
|
}
|
|
6634
|
-
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;
|
|
6635
6925
|
var init_lint_check = __esm({
|
|
6636
6926
|
"tools/core/lint-check.js"() {
|
|
6637
6927
|
init_anode();
|
|
@@ -6669,7 +6959,6 @@ var init_lint_check = __esm({
|
|
|
6669
6959
|
DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED";
|
|
6670
6960
|
PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE";
|
|
6671
6961
|
PROVIDE_TYPE_BAD_SHAPE = "PROVIDE_TYPE_BAD_SHAPE";
|
|
6672
|
-
PROVIDE_NAME_COLLISION = "PROVIDE_NAME_COLLISION";
|
|
6673
6962
|
LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE";
|
|
6674
6963
|
LOOKUP_NO_PROVIDER = "LOOKUP_NO_PROVIDER";
|
|
6675
6964
|
RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP";
|
|
@@ -6997,7 +7286,7 @@ var init_lint_rules = __esm({
|
|
|
6997
7286
|
code: LOOKUP_NO_PROVIDER,
|
|
6998
7287
|
level: "error",
|
|
6999
7288
|
group: "Dynamic bindings",
|
|
7000
|
-
summary: "`lookup` name is provided
|
|
7289
|
+
summary: "`lookup` name is neither provided in scope nor a registered path."
|
|
7001
7290
|
},
|
|
7002
7291
|
{
|
|
7003
7292
|
code: PROVIDE_TYPE_BAD_SHAPE,
|
|
@@ -7005,12 +7294,6 @@ var init_lint_rules = __esm({
|
|
|
7005
7294
|
group: "Dynamic bindings",
|
|
7006
7295
|
summary: 'A PascalCase `provide` publishes a component type; its value must be `"self"`.'
|
|
7007
7296
|
},
|
|
7008
|
-
{
|
|
7009
|
-
code: PROVIDE_NAME_COLLISION,
|
|
7010
|
-
level: "error",
|
|
7011
|
-
group: "Dynamic bindings",
|
|
7012
|
-
summary: "Two components in one scope chain `provide` the same name."
|
|
7013
|
-
},
|
|
7014
7297
|
// Templates / events
|
|
7015
7298
|
{
|
|
7016
7299
|
code: RENDER_IT_OUTSIDE_OF_LOOP,
|
|
@@ -7299,15 +7582,13 @@ function lintIdToMessage(id, info) {
|
|
|
7299
7582
|
case "DYN_ALIAS_NOT_REFERENCED":
|
|
7300
7583
|
return `Lookup '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
|
|
7301
7584
|
case "PROVIDE_NOT_ADDRESSABLE":
|
|
7302
|
-
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`;
|
|
7303
7586
|
case "LOOKUP_BAD_SHAPE":
|
|
7304
7587
|
return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
|
|
7305
7588
|
case "LOOKUP_NO_PROVIDER":
|
|
7306
|
-
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`;
|
|
7307
7590
|
case "PROVIDE_TYPE_BAD_SHAPE":
|
|
7308
7591
|
return `Provide '${info.name}' starts uppercase, so it publishes a component type — its value must be 'self', not '${info.value}'`;
|
|
7309
|
-
case "PROVIDE_NAME_COLLISION":
|
|
7310
|
-
return `Provide '${info.name}' is also provided by '${info.other}' in the same scope — one name, one provider, so a lookup can find it`;
|
|
7311
7592
|
case "UNKNOWN_MACRO_ARG":
|
|
7312
7593
|
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
7313
7594
|
case "UNKNOWN_DIRECTIVE":
|
|
@@ -12782,165 +13063,6 @@ var init_list = __esm({
|
|
|
12782
13063
|
}
|
|
12783
13064
|
});
|
|
12784
13065
|
|
|
12785
|
-
// src/stack.js
|
|
12786
|
-
function routeLookup(route, lex, dyn) {
|
|
12787
|
-
for (let i = 0; i < route.length; i++) {
|
|
12788
|
-
const leg = route[i];
|
|
12789
|
-
if (leg === "dyn") {
|
|
12790
|
-
const v = dyn();
|
|
12791
|
-
if (v != null) return v;
|
|
12792
|
-
} else if (leg === "lex") {
|
|
12793
|
-
const v = lex();
|
|
12794
|
-
if (v != null) return v;
|
|
12795
|
-
} else {
|
|
12796
|
-
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
12797
|
-
}
|
|
12798
|
-
}
|
|
12799
|
-
return null;
|
|
12800
|
-
}
|
|
12801
|
-
function lookup(chain, name, dv = null) {
|
|
12802
|
-
let n = chain;
|
|
12803
|
-
while (n !== null) {
|
|
12804
|
-
const r = n[0].lookup(name);
|
|
12805
|
-
if (r === STOP) return dv;
|
|
12806
|
-
if (r !== NEXT) return r;
|
|
12807
|
-
n = n[1];
|
|
12808
|
-
}
|
|
12809
|
-
return dv;
|
|
12810
|
-
}
|
|
12811
|
-
function computeViewsId(views) {
|
|
12812
|
-
let s = "";
|
|
12813
|
-
let n = views;
|
|
12814
|
-
while (n !== null) {
|
|
12815
|
-
s += n[0];
|
|
12816
|
-
n = n[1];
|
|
12817
|
-
}
|
|
12818
|
-
return s === "main" ? "" : s;
|
|
12819
|
-
}
|
|
12820
|
-
var STOP, NEXT, DEFAULT_ROUTE, BindFrame, ObjectFrame, Stack;
|
|
12821
|
-
var init_stack = __esm({
|
|
12822
|
-
"src/stack.js"() {
|
|
12823
|
-
STOP = /* @__PURE__ */ Symbol("STOP");
|
|
12824
|
-
NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
12825
|
-
DEFAULT_ROUTE = ["dyn", "lex"];
|
|
12826
|
-
BindFrame = class {
|
|
12827
|
-
constructor(it, binds, isFrame) {
|
|
12828
|
-
this.it = it;
|
|
12829
|
-
this.binds = binds;
|
|
12830
|
-
this.isFrame = isFrame;
|
|
12831
|
-
}
|
|
12832
|
-
lookup(name) {
|
|
12833
|
-
const v = this.binds[name];
|
|
12834
|
-
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
12835
|
-
}
|
|
12836
|
-
};
|
|
12837
|
-
ObjectFrame = class {
|
|
12838
|
-
constructor(binds) {
|
|
12839
|
-
this.binds = binds;
|
|
12840
|
-
}
|
|
12841
|
-
lookup(key) {
|
|
12842
|
-
const v = this.binds[key];
|
|
12843
|
-
return v === void 0 ? NEXT : v;
|
|
12844
|
-
}
|
|
12845
|
-
};
|
|
12846
|
-
Stack = class _Stack {
|
|
12847
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
12848
|
-
this.comps = comps;
|
|
12849
|
-
this.it = it;
|
|
12850
|
-
this.binds = binds;
|
|
12851
|
-
this.dynBinds = dynBinds;
|
|
12852
|
-
this.views = views;
|
|
12853
|
-
this.viewsId = viewsId;
|
|
12854
|
-
this.ctx = ctx;
|
|
12855
|
-
}
|
|
12856
|
-
// Evaluate every provide the entered component publishes and push them as one
|
|
12857
|
-
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
12858
|
-
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
12859
|
-
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
12860
|
-
_pushProvides() {
|
|
12861
|
-
const comp = this.comps.getCompFor(this.it);
|
|
12862
|
-
if (comp == null) return this;
|
|
12863
|
-
const { provide, provideType } = comp;
|
|
12864
|
-
const dynObj = {};
|
|
12865
|
-
let has2 = false;
|
|
12866
|
-
for (const k in provide) {
|
|
12867
|
-
dynObj[k] = provide[k].val.eval(this);
|
|
12868
|
-
has2 = true;
|
|
12869
|
-
}
|
|
12870
|
-
for (const k in provideType) {
|
|
12871
|
-
dynObj[k] = provideType[k];
|
|
12872
|
-
has2 = true;
|
|
12873
|
-
}
|
|
12874
|
-
if (!has2) return this;
|
|
12875
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
12876
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
12877
|
-
return new _Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
12878
|
-
}
|
|
12879
|
-
static root(comps, it, ctx) {
|
|
12880
|
-
const binds = [new BindFrame(it, {}, true), null];
|
|
12881
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
12882
|
-
const views = ["main", null];
|
|
12883
|
-
return new _Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
12884
|
-
}
|
|
12885
|
-
enter(it, bindings = {}, isFrame = true) {
|
|
12886
|
-
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
12887
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
12888
|
-
const stack = new _Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
12889
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
12890
|
-
}
|
|
12891
|
-
pushViewName(name) {
|
|
12892
|
-
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
12893
|
-
const newViews = [name, views];
|
|
12894
|
-
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
12895
|
-
}
|
|
12896
|
-
// Published types are stable per scope and would only churn the render cache, so
|
|
12897
|
-
// the cache key covers values alone.
|
|
12898
|
-
_pushDynBindValuesToArray(arr, comp) {
|
|
12899
|
-
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
12900
|
-
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
12901
|
-
}
|
|
12902
|
-
// `*name`: the nearest binding above (including this component's own provides,
|
|
12903
|
-
// pushed on entering it), else this component's declared default, else null.
|
|
12904
|
-
lookupDynamic(name) {
|
|
12905
|
-
const v = lookup(this.dynBinds, name);
|
|
12906
|
-
if (v != null) return v;
|
|
12907
|
-
const comp = this.comps.getCompFor(this.it);
|
|
12908
|
-
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
12909
|
-
}
|
|
12910
|
-
lookupBind(name) {
|
|
12911
|
-
return lookup(this.binds, name);
|
|
12912
|
-
}
|
|
12913
|
-
lookupFieldRaw(name) {
|
|
12914
|
-
return this.it[name] ?? null;
|
|
12915
|
-
}
|
|
12916
|
-
lookupMethod(name) {
|
|
12917
|
-
const fn = this.it[name];
|
|
12918
|
-
return fn instanceof Function ? fn.call(this.it) : null;
|
|
12919
|
-
}
|
|
12920
|
-
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
12921
|
-
// `e.<member>` handler args. Null outside a live event transaction.
|
|
12922
|
-
lookupEvent() {
|
|
12923
|
-
return this.ctx?.event ?? null;
|
|
12924
|
-
}
|
|
12925
|
-
lookupDragInfo() {
|
|
12926
|
-
return this.ctx?.dragInfo ?? null;
|
|
12927
|
-
}
|
|
12928
|
-
getHandlerFor(name, key) {
|
|
12929
|
-
return this.comps.getHandlerFor(this.it, name, key);
|
|
12930
|
-
}
|
|
12931
|
-
lookupBestView(views, defaultViewName) {
|
|
12932
|
-
let n = this.views;
|
|
12933
|
-
while (n !== null) {
|
|
12934
|
-
const view = views[n[0]];
|
|
12935
|
-
if (view !== void 0) return view;
|
|
12936
|
-
n = n[1];
|
|
12937
|
-
}
|
|
12938
|
-
return views[defaultViewName];
|
|
12939
|
-
}
|
|
12940
|
-
};
|
|
12941
|
-
}
|
|
12942
|
-
});
|
|
12943
|
-
|
|
12944
13066
|
// src/oo.js
|
|
12945
13067
|
function mkCompField(field, scope, args) {
|
|
12946
13068
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
@@ -12961,8 +13083,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
|
|
|
12961
13083
|
const value = fields[field];
|
|
12962
13084
|
const type3 = typeof value;
|
|
12963
13085
|
if (type3 === "string") b.addField(field, value, FieldString);
|
|
12964
|
-
else if (type3 === "number")
|
|
12965
|
-
b.addField(field, value, Number.isInteger(value) ? FieldInt : FieldFloat);
|
|
13086
|
+
else if (type3 === "number") b.addField(field, value, FieldFloat);
|
|
12966
13087
|
else if (type3 === "boolean") b.addField(field, value, FieldBool);
|
|
12967
13088
|
else if (Array.isArray(value)) b.addField(field, [...value], FieldList);
|
|
12968
13089
|
else if (value instanceof Set) b.addField(field, new Set(value), FieldSet);
|
|
@@ -13003,7 +13124,7 @@ function assertNoReservedComponentStatics(statics = {}) {
|
|
|
13003
13124
|
}
|
|
13004
13125
|
}
|
|
13005
13126
|
}
|
|
13006
|
-
var BAD_VALUE2, nullCoercer, Field, CHECK_TYPE_ANY, CHECK_TYPE_INT, CHECK_TYPE_FLOAT, CHECK_TYPE_BOOL, CHECK_TYPE_STRING, CHECK_TYPE_LIST, CHECK_TYPE_OBJECT, CHECK_TYPE_MAP, CHECK_TYPE_SET, FieldBool, FieldAny, FieldString, FieldInt, FieldFloat, metaOf, getTypeName, FieldComp, FieldList, FieldObject, FieldMap, FieldSet, ClassBuilder, FIELD_CLASS, fieldsByTypeName, META_KEYS, RESERVED_COMPONENT_STATICS;
|
|
13127
|
+
var BAD_VALUE2, nullCoercer, Field, CHECK_TYPE_ANY, CHECK_TYPE_INT, CHECK_TYPE_FLOAT, CHECK_TYPE_BOOL, CHECK_TYPE_STRING, CHECK_TYPE_LIST, CHECK_TYPE_OBJECT, CHECK_TYPE_MAP, CHECK_TYPE_SET, COERCE_NONE, COERCE_BOOL, COERCE_STRING, COERCE_INT, COERCE_LIST, COERCE_OBJECT, COERCE_MAP, COERCE_SET, FieldBool, FieldAny, FieldString, FieldInt, FieldFloat, metaOf, getTypeName, FieldComp, FieldList, FieldObject, FieldMap, FieldSet, ClassBuilder, FIELD_CLASS, fieldsByTypeName, META_KEYS, RESERVED_COMPONENT_STATICS;
|
|
13007
13128
|
var init_oo = __esm({
|
|
13008
13129
|
"src/oo.js"() {
|
|
13009
13130
|
init_collection();
|
|
@@ -13040,9 +13161,22 @@ var init_oo = __esm({
|
|
|
13040
13161
|
CHECK_TYPE_OBJECT = isPlainObject;
|
|
13041
13162
|
CHECK_TYPE_MAP = (v) => v instanceof Map;
|
|
13042
13163
|
CHECK_TYPE_SET = (v) => v instanceof Set;
|
|
13164
|
+
COERCE_NONE = (_v) => null;
|
|
13165
|
+
COERCE_BOOL = (v) => !!v;
|
|
13166
|
+
COERCE_STRING = (v) => v?.toString?.() ?? "";
|
|
13167
|
+
COERCE_INT = (v) => Number.isFinite(v) ? Math.trunc(v) : null;
|
|
13168
|
+
COERCE_LIST = (v) => Array.isArray(v) ? [...v] : null;
|
|
13169
|
+
COERCE_OBJECT = (v) => isPlainObject(v) ? { ...v } : null;
|
|
13170
|
+
COERCE_MAP = (v) => {
|
|
13171
|
+
if (v instanceof Map) return new Map(v);
|
|
13172
|
+
if (Array.isArray(v) || isPlainObject(v))
|
|
13173
|
+
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
13174
|
+
return null;
|
|
13175
|
+
};
|
|
13176
|
+
COERCE_SET = (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null;
|
|
13043
13177
|
FieldBool = class extends Field {
|
|
13044
13178
|
constructor(name, defaultValue = false) {
|
|
13045
|
-
super("bool", name, CHECK_TYPE_BOOL,
|
|
13179
|
+
super("bool", name, CHECK_TYPE_BOOL, COERCE_BOOL, defaultValue);
|
|
13046
13180
|
}
|
|
13047
13181
|
};
|
|
13048
13182
|
FieldAny = class extends Field {
|
|
@@ -13052,23 +13186,17 @@ var init_oo = __esm({
|
|
|
13052
13186
|
};
|
|
13053
13187
|
FieldString = class extends Field {
|
|
13054
13188
|
constructor(name, defaultValue = "") {
|
|
13055
|
-
super("text", name, CHECK_TYPE_STRING,
|
|
13189
|
+
super("text", name, CHECK_TYPE_STRING, COERCE_STRING, defaultValue);
|
|
13056
13190
|
}
|
|
13057
13191
|
};
|
|
13058
13192
|
FieldInt = class extends Field {
|
|
13059
13193
|
constructor(name, defaultValue = 0) {
|
|
13060
|
-
super(
|
|
13061
|
-
"int",
|
|
13062
|
-
name,
|
|
13063
|
-
CHECK_TYPE_INT,
|
|
13064
|
-
(v) => Number.isFinite(v) ? Math.trunc(v) : null,
|
|
13065
|
-
defaultValue
|
|
13066
|
-
);
|
|
13194
|
+
super("int", name, CHECK_TYPE_INT, COERCE_INT, defaultValue);
|
|
13067
13195
|
}
|
|
13068
13196
|
};
|
|
13069
13197
|
FieldFloat = class extends Field {
|
|
13070
13198
|
constructor(name, defaultValue = 0) {
|
|
13071
|
-
super("float", name, CHECK_TYPE_FLOAT,
|
|
13199
|
+
super("float", name, CHECK_TYPE_FLOAT, COERCE_NONE, defaultValue);
|
|
13072
13200
|
}
|
|
13073
13201
|
};
|
|
13074
13202
|
metaOf = (v) => v?.constructor?.[COMPONENT] ?? v?.constructor?.getMetaClass?.();
|
|
@@ -13081,45 +13209,22 @@ var init_oo = __esm({
|
|
|
13081
13209
|
};
|
|
13082
13210
|
FieldList = class extends Field {
|
|
13083
13211
|
constructor(name, defaultValue = []) {
|
|
13084
|
-
super("list", name, CHECK_TYPE_LIST,
|
|
13212
|
+
super("list", name, CHECK_TYPE_LIST, COERCE_LIST, defaultValue);
|
|
13085
13213
|
}
|
|
13086
13214
|
};
|
|
13087
13215
|
FieldObject = class extends Field {
|
|
13088
13216
|
constructor(name, defaultValue = {}) {
|
|
13089
|
-
super(
|
|
13090
|
-
"object",
|
|
13091
|
-
name,
|
|
13092
|
-
CHECK_TYPE_OBJECT,
|
|
13093
|
-
(v) => isPlainObject(v) ? { ...v } : null,
|
|
13094
|
-
defaultValue
|
|
13095
|
-
);
|
|
13217
|
+
super("object", name, CHECK_TYPE_OBJECT, COERCE_OBJECT, defaultValue);
|
|
13096
13218
|
}
|
|
13097
13219
|
};
|
|
13098
13220
|
FieldMap = class extends Field {
|
|
13099
13221
|
constructor(name, defaultValue = /* @__PURE__ */ new Map()) {
|
|
13100
|
-
super(
|
|
13101
|
-
"map",
|
|
13102
|
-
name,
|
|
13103
|
-
CHECK_TYPE_MAP,
|
|
13104
|
-
(v) => {
|
|
13105
|
-
if (v instanceof Map) return new Map(v);
|
|
13106
|
-
if (Array.isArray(v) || isPlainObject(v))
|
|
13107
|
-
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
13108
|
-
return null;
|
|
13109
|
-
},
|
|
13110
|
-
defaultValue
|
|
13111
|
-
);
|
|
13222
|
+
super("map", name, CHECK_TYPE_MAP, COERCE_MAP, defaultValue);
|
|
13112
13223
|
}
|
|
13113
13224
|
};
|
|
13114
13225
|
FieldSet = class extends Field {
|
|
13115
13226
|
constructor(name, defaultValue = /* @__PURE__ */ new Set()) {
|
|
13116
|
-
super(
|
|
13117
|
-
"set",
|
|
13118
|
-
name,
|
|
13119
|
-
CHECK_TYPE_SET,
|
|
13120
|
-
(v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null,
|
|
13121
|
-
defaultValue
|
|
13122
|
-
);
|
|
13227
|
+
super("set", name, CHECK_TYPE_SET, COERCE_SET, defaultValue);
|
|
13123
13228
|
}
|
|
13124
13229
|
};
|
|
13125
13230
|
ClassBuilder = class {
|
|
@@ -13243,7 +13348,7 @@ function warnNotIntent(verb) {
|
|
|
13243
13348
|
console.warn(`ctx.${verb}() is only meaningful in an "intent" handler - ignored`);
|
|
13244
13349
|
}
|
|
13245
13350
|
function rootDispatcher(transactor) {
|
|
13246
|
-
return new Dispatcher(new
|
|
13351
|
+
return new Dispatcher(new DispatchPath(), transactor, null);
|
|
13247
13352
|
}
|
|
13248
13353
|
var State2, Transactor, Transaction, InputEvent, NameArgsTransaction, SendEvent, IntentEvent, PASS, REFUSAL_RING_CAP, INTENT_DEPTH, IntentWalk, Completion, Dispatcher, EventContext, PathChanges;
|
|
13249
13354
|
var init_transactor = __esm({
|
|
@@ -13380,9 +13485,11 @@ var init_transactor = __esm({
|
|
|
13380
13485
|
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
13381
13486
|
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
13382
13487
|
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
13383
|
-
pushSend(path, name, args = [], parent = null, origin = null) {
|
|
13488
|
+
pushSend(path, name, args = [], parent = null, origin = null, txnPath = null) {
|
|
13384
13489
|
const t = new SendEvent(path, this, name, args, parent);
|
|
13385
|
-
t.
|
|
13490
|
+
t.txnPath = txnPath;
|
|
13491
|
+
t.origin = origin;
|
|
13492
|
+
t.originPinned = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
13386
13493
|
this.pushTransaction(t);
|
|
13387
13494
|
return this._link(t, parent);
|
|
13388
13495
|
}
|
|
@@ -13432,6 +13539,7 @@ var init_transactor = __esm({
|
|
|
13432
13539
|
Transaction = class {
|
|
13433
13540
|
constructor(path, transactor, parentTransaction = null) {
|
|
13434
13541
|
this.path = path;
|
|
13542
|
+
this.txnPath = null;
|
|
13435
13543
|
this.transactor = transactor;
|
|
13436
13544
|
this.parentTransaction = parentTransaction;
|
|
13437
13545
|
this._completion = null;
|
|
@@ -13480,9 +13588,11 @@ var init_transactor = __esm({
|
|
|
13480
13588
|
getHandlerAndArgs(_root, _instance, _comps) {
|
|
13481
13589
|
return null;
|
|
13482
13590
|
}
|
|
13483
|
-
// The path used to apply the mutation
|
|
13484
|
-
//
|
|
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).
|
|
13485
13594
|
getTransactionPath() {
|
|
13595
|
+
if (this.txnPath !== null) return this.txnPath;
|
|
13486
13596
|
return this.path.toTransactionPath().compact();
|
|
13487
13597
|
}
|
|
13488
13598
|
run(curRoot, comps) {
|
|
@@ -13507,8 +13617,9 @@ var init_transactor = __esm({
|
|
|
13507
13617
|
this.dragInfo = dragInfo;
|
|
13508
13618
|
this._dispatchPath = null;
|
|
13509
13619
|
}
|
|
13510
|
-
// Frame steps removed,
|
|
13511
|
-
//
|
|
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`.
|
|
13512
13623
|
get dispatchPath() {
|
|
13513
13624
|
this._dispatchPath ??= this.path.compact();
|
|
13514
13625
|
return this._dispatchPath;
|
|
@@ -13543,7 +13654,7 @@ var init_transactor = __esm({
|
|
|
13543
13654
|
this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
|
|
13544
13655
|
}
|
|
13545
13656
|
getHandlerAndArgs(root, _instance, comps) {
|
|
13546
|
-
const stack = this.path.
|
|
13657
|
+
const stack = this.path.buildStack(Stack.root(comps, root, this));
|
|
13547
13658
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
13548
13659
|
this._handlerArgs = [...args];
|
|
13549
13660
|
const path = this.dispatchPath;
|
|
@@ -13669,7 +13780,7 @@ var init_transactor = __esm({
|
|
|
13669
13780
|
while (this.legIndex < this.route.length) {
|
|
13670
13781
|
const leg = this.route[this.legIndex];
|
|
13671
13782
|
if (leg === "dyn") {
|
|
13672
|
-
if (this.dynAt.
|
|
13783
|
+
if (!this.dynAt.canPop()) {
|
|
13673
13784
|
this.legIndex++;
|
|
13674
13785
|
continue;
|
|
13675
13786
|
}
|
|
@@ -13766,8 +13877,8 @@ var init_transactor = __esm({
|
|
|
13766
13877
|
if (this.ended) return;
|
|
13767
13878
|
this.ended = true;
|
|
13768
13879
|
if (name === null) return this.release?.();
|
|
13769
|
-
const
|
|
13770
|
-
|
|
13880
|
+
const t = new SendEvent(this.origin, this.transactor, name, args, this.parent);
|
|
13881
|
+
t.txnPath = this.answerPath;
|
|
13771
13882
|
t._isAnswer = true;
|
|
13772
13883
|
this.transactor.pushTransaction(t);
|
|
13773
13884
|
if (this.release) t.completion.whenSubtreeSettled().then(this.release);
|
|
@@ -13862,7 +13973,9 @@ var init_transactor = __esm({
|
|
|
13862
13973
|
// replayed; provides are pushed on every component frame either way, so a provide
|
|
13863
13974
|
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
13864
13975
|
_stack() {
|
|
13865
|
-
this._stackMemo ??= this.path.
|
|
13976
|
+
this._stackMemo ??= this.path.buildStack(
|
|
13977
|
+
Stack.root(this.transactor.comps, this.root, this.parent)
|
|
13978
|
+
);
|
|
13866
13979
|
return this._stackMemo;
|
|
13867
13980
|
}
|
|
13868
13981
|
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
@@ -13876,14 +13989,19 @@ var init_transactor = __esm({
|
|
|
13876
13989
|
);
|
|
13877
13990
|
}
|
|
13878
13991
|
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
13879
|
-
// 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.
|
|
13880
13995
|
_lookupLex(name) {
|
|
13881
13996
|
let Comp = null;
|
|
13882
13997
|
this.walkPath((c) => {
|
|
13883
13998
|
Comp = c;
|
|
13884
13999
|
return false;
|
|
13885
14000
|
});
|
|
13886
|
-
|
|
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;
|
|
13887
14005
|
}
|
|
13888
14006
|
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
13889
14007
|
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
@@ -13944,7 +14062,14 @@ var init_transactor = __esm({
|
|
|
13944
14062
|
this.transactor.refuse("NO_SENDER", { name });
|
|
13945
14063
|
return null;
|
|
13946
14064
|
}
|
|
13947
|
-
return this.
|
|
14065
|
+
return this.transactor.pushSend(
|
|
14066
|
+
origin,
|
|
14067
|
+
name,
|
|
14068
|
+
args,
|
|
14069
|
+
this.parent,
|
|
14070
|
+
this.path,
|
|
14071
|
+
this.parent.originPinned
|
|
14072
|
+
);
|
|
13948
14073
|
}
|
|
13949
14074
|
// End the walk answering nothing — "served, and no answer".
|
|
13950
14075
|
stop() {
|
|
@@ -14055,7 +14180,7 @@ var init_app = __esm({
|
|
|
14055
14180
|
const { type: type3 } = e;
|
|
14056
14181
|
const isDrag = type3 === "dragover" || type3 === "dragstart" || type3 === "dragend" || type3 === "drop";
|
|
14057
14182
|
const { rootNode: root, maxEventNodeDepth: maxDepth, comps, transactor } = this;
|
|
14058
|
-
const [path, handlers] =
|
|
14183
|
+
const [path, handlers] = DispatchPath.fromNodeAndEventName(
|
|
14059
14184
|
e.target,
|
|
14060
14185
|
type3,
|
|
14061
14186
|
root,
|
|
@@ -14123,7 +14248,7 @@ var init_app = __esm({
|
|
|
14123
14248
|
const txnPath = path.compact().toTransactionPath();
|
|
14124
14249
|
const value = txnPath.lookup(rootValue);
|
|
14125
14250
|
const dragType = e.target.dataset.dragtype ?? "?";
|
|
14126
|
-
const stack = path.
|
|
14251
|
+
const stack = path.buildStack(this.makeStack(rootValue));
|
|
14127
14252
|
this.dragInfo = new DragInfo(stack, value, dragType, e.target);
|
|
14128
14253
|
} else if (type3 === "drop") {
|
|
14129
14254
|
e.preventDefault();
|
|
@@ -14198,7 +14323,7 @@ var init_app = __esm({
|
|
|
14198
14323
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
14199
14324
|
}
|
|
14200
14325
|
sendAtRoot(name, args) {
|
|
14201
|
-
this.transactor.pushSend(new
|
|
14326
|
+
this.transactor.pushSend(new DispatchPath(), name, args);
|
|
14202
14327
|
}
|
|
14203
14328
|
registerComponents(comps, opts) {
|
|
14204
14329
|
const scope = this.compStack.enter();
|
|
@@ -14342,13 +14467,28 @@ var init_cache = __esm({
|
|
|
14342
14467
|
});
|
|
14343
14468
|
|
|
14344
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
|
+
}
|
|
14345
14483
|
var DATASET_ATTRS, Renderer;
|
|
14346
14484
|
var init_renderer = __esm({
|
|
14347
14485
|
"src/renderer.js"() {
|
|
14348
14486
|
init_cache();
|
|
14349
14487
|
init_iteration();
|
|
14488
|
+
init_path();
|
|
14489
|
+
init_value();
|
|
14350
14490
|
init_vdom();
|
|
14351
|
-
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
14491
|
+
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk", "rp"];
|
|
14352
14492
|
Renderer = class {
|
|
14353
14493
|
constructor(comps) {
|
|
14354
14494
|
this.comps = comps;
|
|
@@ -14385,17 +14525,17 @@ var init_renderer = __esm({
|
|
|
14385
14525
|
if (comp === null) return null;
|
|
14386
14526
|
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
14387
14527
|
}
|
|
14388
|
-
renderIt(stack, node, key, viewName) {
|
|
14528
|
+
renderIt(stack, node, key, viewName, base = null) {
|
|
14389
14529
|
const comp = this.comps.getCompFor(stack.it);
|
|
14390
|
-
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;
|
|
14391
14531
|
}
|
|
14392
14532
|
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
14393
14533
|
// `render-each`, or the view's root anode for the app root). It keys the
|
|
14394
14534
|
// cache as a globally-unique object: node ids alone are unique only within a
|
|
14395
14535
|
// single view, so the same value rendered by two components (e.g. through a
|
|
14396
14536
|
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
14397
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
14398
|
-
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}`;
|
|
14399
14539
|
const cachePath = [node, val];
|
|
14400
14540
|
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
14401
14541
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
@@ -14403,30 +14543,43 @@ var init_renderer = __esm({
|
|
|
14403
14543
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
14404
14544
|
const body = this.renderView(view, stack);
|
|
14405
14545
|
if (body == null) return null;
|
|
14546
|
+
const baseJson = base === null ? null : pathToJson(base);
|
|
14406
14547
|
const meta = this._renderMetadata({
|
|
14407
14548
|
$: "Comp",
|
|
14408
14549
|
nid: node?.nodeId ?? null,
|
|
14409
14550
|
cid: comp.id,
|
|
14410
|
-
vid: view.name
|
|
14551
|
+
vid: view.name,
|
|
14552
|
+
...baseJson === null ? null : { base: baseJson }
|
|
14411
14553
|
});
|
|
14412
|
-
const dom = new VFragment([
|
|
14554
|
+
const dom = new VFragment([
|
|
14555
|
+
meta,
|
|
14556
|
+
baseJson === null ? body : stampRenderBase(body, JSON.stringify(baseJson))
|
|
14557
|
+
]);
|
|
14413
14558
|
this.cache.set(cachePath, cacheKey, dom);
|
|
14414
14559
|
return dom;
|
|
14415
14560
|
}
|
|
14416
14561
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
14417
14562
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
14418
14563
|
}
|
|
14419
|
-
renderEachWhen(stack,
|
|
14564
|
+
renderEachWhen(stack, each2) {
|
|
14565
|
+
const { iterInfo, node: view, nodeId: nid } = each2;
|
|
14420
14566
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
14567
|
+
const seqPath = iterInfo.val instanceof DynVal ? stack.lookupDynamicLocated(iterInfo.val.name)?.path ?? null : null;
|
|
14421
14568
|
const r = [];
|
|
14422
14569
|
const it = stack.it;
|
|
14423
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;
|
|
14424
14574
|
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
14425
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
14575
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}${itemPath.addressKey}`;
|
|
14426
14576
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
14427
14577
|
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
14428
14578
|
else {
|
|
14429
|
-
const dom = this.renderView(
|
|
14579
|
+
const dom = this.renderView(
|
|
14580
|
+
view,
|
|
14581
|
+
stack.enter(value, binds, false, itemPath, itemBase !== null)
|
|
14582
|
+
);
|
|
14430
14583
|
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
14431
14584
|
this.cache.set(cachePath, cacheKey, dom);
|
|
14432
14585
|
}
|
|
@@ -14482,7 +14635,7 @@ function renderToHTMLNode(document2, components, macros, rootState, ParseContext
|
|
|
14482
14635
|
const comps = new Components();
|
|
14483
14636
|
const renderer = new Renderer(comps);
|
|
14484
14637
|
const app = new App(container, comps, renderer, ParseContext2);
|
|
14485
|
-
const scope = app.registerComponents(components);
|
|
14638
|
+
const scope = app.registerComponents(components, { paths: opts.paths });
|
|
14486
14639
|
if (macros) scope.registerMacros(macros);
|
|
14487
14640
|
if (opts.intentHandlers) scope.registerIntentHandlers(opts.intentHandlers);
|
|
14488
14641
|
app.rootViewName = opts.view ?? null;
|
|
@@ -14508,7 +14661,7 @@ async function renderToHTMLDriven(document2, components, macros, rootState, Pars
|
|
|
14508
14661
|
);
|
|
14509
14662
|
try {
|
|
14510
14663
|
if (phase) {
|
|
14511
|
-
dispatchPhase(rootDispatcher(app.transactor), new
|
|
14664
|
+
dispatchPhase(rootDispatcher(app.transactor), new DispatchPath(), phase, app.state.val);
|
|
14512
14665
|
await app.transactor.settle();
|
|
14513
14666
|
}
|
|
14514
14667
|
return serializeContainer(container);
|
|
@@ -14746,7 +14899,7 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
14746
14899
|
val
|
|
14747
14900
|
);
|
|
14748
14901
|
});
|
|
14749
|
-
dispatchPhase(rootDispatcher(transactor), new
|
|
14902
|
+
dispatchPhase(rootDispatcher(transactor), new DispatchPath(), phase, value);
|
|
14750
14903
|
await transactor.settle();
|
|
14751
14904
|
return transactor.state.val;
|
|
14752
14905
|
}
|