tutuca 0.12.1 → 0.13.1
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 +601 -475
- package/dist/tutuca-components.js +3 -3
- package/dist/tutuca-dev.ext.js +563 -491
- package/dist/tutuca-dev.js +564 -492
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +470 -410
- package/dist/tutuca-extra.js +470 -410
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca-storybook.js +4 -4
- package/dist/tutuca.ext.js +470 -410
- package/dist/tutuca.js +470 -410
- package/dist/tutuca.min.js +3 -3
- package/package.json +1 -1
- package/skill/tutuca/advanced.md +56 -7
- package/skill/tutuca/core.md +25 -15
- package/skill/tutuca/messages-and-intents.md +17 -0
- package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +1 -1
- package/skill/tutuca/patterns/handle-events.md +3 -2
- package/skill/tutuca/patterns/share-state-across-the-tree.md +1 -1
- package/skill/tutuca/semantics.md +4 -4
- package/skill/tutuca/testing.md +1 -1
- package/skill/tutuca-source/tutuca.ext.js +470 -410
package/dist/tutuca-cli.js
CHANGED
|
@@ -1102,9 +1102,6 @@ var init_path = __esm({
|
|
|
1102
1102
|
lookup(_v, dval = null) {
|
|
1103
1103
|
return dval;
|
|
1104
1104
|
}
|
|
1105
|
-
setValue(root, _v) {
|
|
1106
|
-
return root;
|
|
1107
|
-
}
|
|
1108
1105
|
setDraftValue(_root, _v) {
|
|
1109
1106
|
}
|
|
1110
1107
|
enterFrame(stack, _prev, next) {
|
|
@@ -1133,9 +1130,6 @@ var init_path = __esm({
|
|
|
1133
1130
|
lookup(v, _dval) {
|
|
1134
1131
|
return v;
|
|
1135
1132
|
}
|
|
1136
|
-
setValue(_root, v) {
|
|
1137
|
-
return v;
|
|
1138
|
-
}
|
|
1139
1133
|
enterFrame(stack, _prev, next) {
|
|
1140
1134
|
return stack.enter(next, { ...this.binds }, false);
|
|
1141
1135
|
}
|
|
@@ -1173,9 +1167,6 @@ var init_path = __esm({
|
|
|
1173
1167
|
lookup(v, dval = null) {
|
|
1174
1168
|
return readKey(v, this.field, dval);
|
|
1175
1169
|
}
|
|
1176
|
-
setValue(root, v) {
|
|
1177
|
-
return produce(root, (draft) => this.setDraftValue(draft, v));
|
|
1178
|
-
}
|
|
1179
1170
|
setDraftValue(root, v) {
|
|
1180
1171
|
writeKey(root, this.field, v);
|
|
1181
1172
|
}
|
|
@@ -1198,9 +1189,6 @@ var init_path = __esm({
|
|
|
1198
1189
|
lookup(v, dval = null) {
|
|
1199
1190
|
return readSeqKey(readKey(v, this.field, null), this.key, dval);
|
|
1200
1191
|
}
|
|
1201
|
-
setValue(root, v) {
|
|
1202
|
-
return produce(root, (draft) => this.setDraftValue(draft, v));
|
|
1203
|
-
}
|
|
1204
1192
|
setDraftValue(root, v) {
|
|
1205
1193
|
const seq = readKey(root, this.field, null);
|
|
1206
1194
|
if (seq != null) writeSeqKey(seq, this.key, v);
|
|
@@ -1223,9 +1211,6 @@ var init_path = __esm({
|
|
|
1223
1211
|
const key = readKey(v, this.keyField, NONE);
|
|
1224
1212
|
return key !== NONE && seq !== NONE ? readSeqKey(seq, key, dval) : dval;
|
|
1225
1213
|
}
|
|
1226
|
-
setValue(root, v) {
|
|
1227
|
-
return produce(root, (draft) => this.setDraftValue(draft, v));
|
|
1228
|
-
}
|
|
1229
1214
|
setDraftValue(root, v) {
|
|
1230
1215
|
const seq = readKey(root, this.seqField, NONE);
|
|
1231
1216
|
const key = readKey(root, this.keyField, NONE);
|
|
@@ -1253,9 +1238,6 @@ var init_path = __esm({
|
|
|
1253
1238
|
lookup(v, _dval) {
|
|
1254
1239
|
return v;
|
|
1255
1240
|
}
|
|
1256
|
-
setValue(_root, v) {
|
|
1257
|
-
return v;
|
|
1258
|
-
}
|
|
1259
1241
|
// Replay the renderer's per-item binds (key, value + any @enrich-with binds)
|
|
1260
1242
|
// so a rebuilt stack matches the one @each rendered with.
|
|
1261
1243
|
enterFrame(stack, _prev, next) {
|
|
@@ -1288,10 +1270,6 @@ var init_path = __esm({
|
|
|
1288
1270
|
warnRawDynStep("lookup", this);
|
|
1289
1271
|
return dval;
|
|
1290
1272
|
}
|
|
1291
|
-
setValue(root, _v) {
|
|
1292
|
-
warnRawDynStep("setValue", this);
|
|
1293
|
-
return root;
|
|
1294
|
-
}
|
|
1295
1273
|
enterFrame(stack, _prev, _next) {
|
|
1296
1274
|
warnRawDynStep("enterFrame", this);
|
|
1297
1275
|
return stack;
|
|
@@ -1362,7 +1340,7 @@ var init_path = __esm({
|
|
|
1362
1340
|
}
|
|
1363
1341
|
// Resolve every field-keyed step (e.g. `SeqAccessStep`) against `root`, freezing the
|
|
1364
1342
|
// key as it is *now* so a later lookup/setValue lands on the same item even if the
|
|
1365
|
-
// keyField changed meanwhile (e.g. the selected tab moved while
|
|
1343
|
+
// keyField changed meanwhile (e.g. the selected tab moved while an intent was in
|
|
1366
1344
|
// flight). Returns a new Path with those steps replaced; `this` if nothing pinned.
|
|
1367
1345
|
// Must be called on a transaction path (no DynSteps — call toTransactionPath first).
|
|
1368
1346
|
pinKeys(root) {
|
|
@@ -1625,7 +1603,6 @@ function parseToken(s, px) {
|
|
|
1625
1603
|
if (m !== null) return new EventMemberVal(s.split(".").slice(1));
|
|
1626
1604
|
}
|
|
1627
1605
|
if (c0 >= 97 && c0 <= 122) return mkVal(s, NameVal);
|
|
1628
|
-
if (c0 >= 65 && c0 <= 90) return mkVal(s, TypeVal);
|
|
1629
1606
|
return null;
|
|
1630
1607
|
}
|
|
1631
1608
|
function _parseSeqAccess(s, px) {
|
|
@@ -1740,12 +1717,11 @@ function kindOf(val) {
|
|
|
1740
1717
|
if (val instanceof MethodVal) return K_METHOD;
|
|
1741
1718
|
if (val instanceof BindVal) return K_BIND;
|
|
1742
1719
|
if (val instanceof DynVal) return K_DYN;
|
|
1743
|
-
if (val instanceof TypeVal) return K_TYPE;
|
|
1744
1720
|
if (val instanceof NameVal) return K_NAME;
|
|
1745
1721
|
if (val instanceof EventMemberVal) return K_EVENT;
|
|
1746
1722
|
return 0;
|
|
1747
1723
|
}
|
|
1748
|
-
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,
|
|
1724
|
+
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;
|
|
1749
1725
|
var init_value = __esm({
|
|
1750
1726
|
"src/value.js"() {
|
|
1751
1727
|
init_collection();
|
|
@@ -1765,7 +1741,6 @@ var init_value = __esm({
|
|
|
1765
1741
|
K_BIND = 8;
|
|
1766
1742
|
K_DYN = 16;
|
|
1767
1743
|
K_NAME = 32;
|
|
1768
|
-
K_TYPE = 64;
|
|
1769
1744
|
K_SEQ = 256;
|
|
1770
1745
|
K_METHOD = 1024;
|
|
1771
1746
|
K_EVENT = 2048;
|
|
@@ -1775,7 +1750,7 @@ var init_value = __esm({
|
|
|
1775
1750
|
G_SEQUENCE = K_FIELD | K_DYN;
|
|
1776
1751
|
G_PROVIDE = K_FIELD | K_SEQ;
|
|
1777
1752
|
G_FIELD = K_FIELD | K_METHOD | K_CONST | K_SEQ;
|
|
1778
|
-
G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME |
|
|
1753
|
+
G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_CONST;
|
|
1779
1754
|
G_HANDLER_ARG = G_VALUE & ~K_NAME | K_EVENT;
|
|
1780
1755
|
G_ALL = G_VALUE | K_STRTPL | K_SEQ;
|
|
1781
1756
|
toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
@@ -1899,9 +1874,6 @@ var init_value = __esm({
|
|
|
1899
1874
|
super();
|
|
1900
1875
|
this.name = name;
|
|
1901
1876
|
}
|
|
1902
|
-
eval(stack) {
|
|
1903
|
-
return stack.lookupName(this.name);
|
|
1904
|
-
}
|
|
1905
1877
|
toString() {
|
|
1906
1878
|
return this.name;
|
|
1907
1879
|
}
|
|
@@ -1922,11 +1894,6 @@ var init_value = __esm({
|
|
|
1922
1894
|
else console.warn("handler not found", { type: type3, name });
|
|
1923
1895
|
return this;
|
|
1924
1896
|
};
|
|
1925
|
-
TypeVal = class extends NameVal {
|
|
1926
|
-
eval(stack) {
|
|
1927
|
-
return stack.lookupType(this.name);
|
|
1928
|
-
}
|
|
1929
|
-
};
|
|
1930
1897
|
keyIs = (k) => (e) => e.key === k;
|
|
1931
1898
|
macCtrl = (e) => isMac && e.metaKey || e.ctrlKey;
|
|
1932
1899
|
nullSafe = (fn) => (e, stack) => {
|
|
@@ -2057,12 +2024,28 @@ var init_value = __esm({
|
|
|
2057
2024
|
});
|
|
2058
2025
|
|
|
2059
2026
|
// src/attribute.js
|
|
2027
|
+
function parseDirectiveValue(px, directiveName, source, parser) {
|
|
2028
|
+
const val = parser(source, px);
|
|
2029
|
+
if (val === null) {
|
|
2030
|
+
px.onParseIssue("bad-value", {
|
|
2031
|
+
role: "directive",
|
|
2032
|
+
directive: directiveName,
|
|
2033
|
+
value: source
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
return val;
|
|
2037
|
+
}
|
|
2038
|
+
function parseIterationDirectives(attributes, px) {
|
|
2039
|
+
const parseNamed = (name) => {
|
|
2040
|
+
const attr = attributes.getNamedItem(`@${name}`);
|
|
2041
|
+
return attr ? parseDirectiveValue(px, name, attr.value, parseAlterHandler) : null;
|
|
2042
|
+
};
|
|
2043
|
+
return { whenVal: parseNamed("when"), loopWithVal: parseNamed("loop-with") };
|
|
2044
|
+
}
|
|
2060
2045
|
function getAttrParser(px) {
|
|
2061
|
-
|
|
2062
|
-
_attrParser.clear(px);
|
|
2063
|
-
return _attrParser;
|
|
2046
|
+
return new AttrParser(px);
|
|
2064
2047
|
}
|
|
2065
|
-
var Attributes, booleanAttrsRaw, booleanAttrs, AttrParser, ConstAttrs, DynAttrs, BaseAttr, Attr, ConstAttr, RawHtmlAttr, NOT_SET_VAL, IfAttr,
|
|
2048
|
+
var Attributes, booleanAttrsRaw, booleanAttrs, AttrParser, ConstAttrs, DynAttrs, BaseAttr, Attr, ConstAttr, RawHtmlAttr, NOT_SET_VAL, IfAttr, EventHandler, IntentHandler;
|
|
2066
2049
|
var init_attribute = __esm({
|
|
2067
2050
|
"src/attribute.js"() {
|
|
2068
2051
|
init_value();
|
|
@@ -2070,9 +2053,6 @@ var init_attribute = __esm({
|
|
|
2070
2053
|
constructor(items) {
|
|
2071
2054
|
this.items = items;
|
|
2072
2055
|
}
|
|
2073
|
-
eval(_stack) {
|
|
2074
|
-
return {};
|
|
2075
|
-
}
|
|
2076
2056
|
static parse(attributes, px, parseAll = false) {
|
|
2077
2057
|
return getAttrParser(px).parse(attributes, parseAll);
|
|
2078
2058
|
}
|
|
@@ -2084,9 +2064,6 @@ var init_attribute = __esm({
|
|
|
2084
2064
|
booleanAttrs = new Set(booleanAttrsRaw.split(","));
|
|
2085
2065
|
AttrParser = class {
|
|
2086
2066
|
constructor(px) {
|
|
2087
|
-
this.clear(px);
|
|
2088
|
-
}
|
|
2089
|
-
clear(px) {
|
|
2090
2067
|
this.px = px;
|
|
2091
2068
|
this.attrs = null;
|
|
2092
2069
|
this.hasDynamic = false;
|
|
@@ -2141,12 +2118,7 @@ var init_attribute = __esm({
|
|
|
2141
2118
|
}
|
|
2142
2119
|
}
|
|
2143
2120
|
_parseDirectiveValue(directiveName, s, parserFn) {
|
|
2144
|
-
|
|
2145
|
-
if (val === null) {
|
|
2146
|
-
const info = { role: "directive", directive: directiveName, value: s };
|
|
2147
|
-
this.px.onParseIssue("bad-value", info);
|
|
2148
|
-
}
|
|
2149
|
-
return val;
|
|
2121
|
+
return parseDirectiveValue(this.px, directiveName, s, parserFn);
|
|
2150
2122
|
}
|
|
2151
2123
|
parseDirective(s, directiveName) {
|
|
2152
2124
|
switch (directiveName) {
|
|
@@ -2310,7 +2282,6 @@ var init_attribute = __esm({
|
|
|
2310
2282
|
return this.condVal.eval(stack) ? this.thenVal.eval(stack) : this.elseVal.eval(stack);
|
|
2311
2283
|
}
|
|
2312
2284
|
};
|
|
2313
|
-
_attrParser = null;
|
|
2314
2285
|
EventHandler = class _EventHandler {
|
|
2315
2286
|
constructor(handlerVal, args = []) {
|
|
2316
2287
|
this.handlerVal = handlerVal;
|
|
@@ -2335,73 +2306,81 @@ var init_attribute = __esm({
|
|
|
2335
2306
|
}
|
|
2336
2307
|
});
|
|
2337
2308
|
|
|
2338
|
-
// src/
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2309
|
+
// src/iteration.js
|
|
2310
|
+
function walkLoopBindings({ seq, it, filter, loopWith, enricher, ctx }, visit) {
|
|
2311
|
+
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(it, seq, ctx), seq);
|
|
2312
|
+
const visitOne = (key, value, attrName) => {
|
|
2313
|
+
const binds = { key, value };
|
|
2314
|
+
if (enricher) callEnricher(enricher, it, binds, key, value, iterData);
|
|
2315
|
+
visit(key, value, attrName, binds);
|
|
2316
|
+
};
|
|
2317
|
+
if (keys) visitKeys(seq, keys, visitOne);
|
|
2318
|
+
else
|
|
2319
|
+
getSeqInfo(seq)(
|
|
2320
|
+
seq,
|
|
2321
|
+
(key, value, attrName) => {
|
|
2322
|
+
if (filter.call(it, key, value, iterData)) visitOne(key, value, attrName);
|
|
2323
|
+
},
|
|
2324
|
+
start,
|
|
2325
|
+
end
|
|
2326
|
+
);
|
|
2327
|
+
}
|
|
2328
|
+
var SEQ_INFO, normalizeRange, nativeIndexedIter, nativeKeyedIter, unknownIter, getSeqInfo, filterAlwaysTrue, nullLoopWith, unpackLoopResult, makeLoopCtx, callEnricher, visitKeys;
|
|
2329
|
+
var init_iteration = __esm({
|
|
2330
|
+
"src/iteration.js"() {
|
|
2331
|
+
init_collection();
|
|
2332
|
+
SEQ_INFO = /* @__PURE__ */ Symbol.for("tutuca.seqInfo");
|
|
2333
|
+
normalizeRange = (start, end, size) => {
|
|
2334
|
+
let s = start == null ? 0 : start < 0 ? size + start : start;
|
|
2335
|
+
let e = end == null ? size : end < 0 ? size + end : end;
|
|
2336
|
+
s = s < 0 ? 0 : s > size ? size : s;
|
|
2337
|
+
e = e < 0 ? 0 : e > size ? size : e;
|
|
2338
|
+
return [s, e < s ? s : e];
|
|
2351
2339
|
};
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
const len = keys.length;
|
|
2364
|
-
let cur = this.keysByLen.get(len);
|
|
2365
|
-
if (!cur) return this._returnValue(void 0);
|
|
2366
|
-
for (let i = 0; i < len - 1; i++) {
|
|
2367
|
-
cur = cur.get(keys[i]);
|
|
2368
|
-
if (!cur) return this._returnValue(void 0);
|
|
2369
|
-
}
|
|
2370
|
-
return this._returnValue(cur.get(keys[len - 1])?.[cacheKey]);
|
|
2371
|
-
}
|
|
2372
|
-
set(keys, cacheKey, v) {
|
|
2373
|
-
const len = keys.length;
|
|
2374
|
-
let cur = this.keysByLen.get(len);
|
|
2375
|
-
if (!cur) {
|
|
2376
|
-
cur = /* @__PURE__ */ new WeakMap();
|
|
2377
|
-
this.keysByLen.set(len, cur);
|
|
2378
|
-
}
|
|
2379
|
-
for (let i = 0; i < len - 1; i++) {
|
|
2380
|
-
const key = keys[i];
|
|
2381
|
-
let next = cur.get(key);
|
|
2382
|
-
if (!next) {
|
|
2383
|
-
if (!isWeakKey(key)) {
|
|
2384
|
-
this.badKey += 1;
|
|
2385
|
-
return;
|
|
2386
|
-
}
|
|
2387
|
-
next = /* @__PURE__ */ new WeakMap();
|
|
2388
|
-
cur.set(key, next);
|
|
2389
|
-
}
|
|
2390
|
-
cur = next;
|
|
2391
|
-
}
|
|
2392
|
-
const lastKey = keys[len - 1];
|
|
2393
|
-
const leaf = cur.get(lastKey);
|
|
2394
|
-
if (leaf) leaf[cacheKey] = v;
|
|
2395
|
-
else if (isWeakKey(lastKey)) cur.set(lastKey, { [cacheKey]: v });
|
|
2396
|
-
else this.badKey += 1;
|
|
2397
|
-
}
|
|
2398
|
-
evict() {
|
|
2399
|
-
const { hit, miss, badKey } = this;
|
|
2400
|
-
this.hit = this.miss = this.badKey = 0;
|
|
2401
|
-
this.keysByLen = /* @__PURE__ */ new Map();
|
|
2402
|
-
return { hit, miss, badKey };
|
|
2340
|
+
nativeIndexedIter = (seq, visit, start, end) => {
|
|
2341
|
+
const [s, e] = normalizeRange(start, end, seqSize(seq));
|
|
2342
|
+
for (let i = s; i < e; i++) visit(i, seq[i], "si");
|
|
2343
|
+
};
|
|
2344
|
+
nativeKeyedIter = (seq, visit, start, end) => {
|
|
2345
|
+
const [s, e] = normalizeRange(start, end, seqSize(seq));
|
|
2346
|
+
let i = 0;
|
|
2347
|
+
for (const [key, value] of seqEntries(seq)) {
|
|
2348
|
+
if (i >= e) break;
|
|
2349
|
+
if (i >= s) visit(key, value, "sk");
|
|
2350
|
+
i++;
|
|
2403
2351
|
}
|
|
2404
2352
|
};
|
|
2353
|
+
unknownIter = () => {
|
|
2354
|
+
};
|
|
2355
|
+
getSeqInfo = (seq) => isIndexedSeq(seq) ? nativeIndexedIter : isKeyedSeq(seq) || isSetSeq(seq) ? nativeKeyedIter : seq?.[SEQ_INFO] ?? unknownIter;
|
|
2356
|
+
filterAlwaysTrue = (_key, _value, _iterData) => true;
|
|
2357
|
+
nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
2358
|
+
unpackLoopResult = (result, seq) => {
|
|
2359
|
+
const value = result ?? {};
|
|
2360
|
+
return {
|
|
2361
|
+
iterData: value.iterData ?? { seq },
|
|
2362
|
+
start: value.start,
|
|
2363
|
+
end: value.end,
|
|
2364
|
+
keys: value.keys
|
|
2365
|
+
};
|
|
2366
|
+
};
|
|
2367
|
+
makeLoopCtx = (stack, filter) => ({
|
|
2368
|
+
lookup: (name) => stack.lookupBind(name),
|
|
2369
|
+
filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
|
|
2370
|
+
});
|
|
2371
|
+
callEnricher = (enricher, it, binds, key, value, iterData) => {
|
|
2372
|
+
enricher.call(it, binds, key, value, iterData);
|
|
2373
|
+
console.assert(
|
|
2374
|
+
binds.key === key && binds.value === value,
|
|
2375
|
+
"@enrich-with handlers must not overwrite binds.key or binds.value"
|
|
2376
|
+
);
|
|
2377
|
+
binds.key = key;
|
|
2378
|
+
binds.value = value;
|
|
2379
|
+
};
|
|
2380
|
+
visitKeys = (seq, keys, visit) => {
|
|
2381
|
+
const attrName = isIndexedSeq(seq) ? "si" : "sk";
|
|
2382
|
+
for (const key of keys) visit(key, seqGet(seq, key), attrName);
|
|
2383
|
+
};
|
|
2405
2384
|
}
|
|
2406
2385
|
});
|
|
2407
2386
|
|
|
@@ -2753,197 +2732,11 @@ var init_vdom = __esm({
|
|
|
2753
2732
|
}
|
|
2754
2733
|
});
|
|
2755
2734
|
|
|
2756
|
-
// src/renderer.js
|
|
2757
|
-
var DATASET_ATTRS, Renderer, getSeqInfo, normalizeRange, callEnricher, filterAlwaysTrue, nullLoopWith, unpackLoopResult, keysIter, makeLoopCtx, nativeIndexedIter, nativeKeyedIter, unkIter, SEQ_INFO;
|
|
2758
|
-
var init_renderer = __esm({
|
|
2759
|
-
"src/renderer.js"() {
|
|
2760
|
-
init_cache();
|
|
2761
|
-
init_collection();
|
|
2762
|
-
init_vdom();
|
|
2763
|
-
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
2764
|
-
Renderer = class {
|
|
2765
|
-
constructor(comps) {
|
|
2766
|
-
this.comps = comps;
|
|
2767
|
-
this.cache = new WeakMapDomCache();
|
|
2768
|
-
this.renderTag = h;
|
|
2769
|
-
}
|
|
2770
|
-
renderFragment(childs) {
|
|
2771
|
-
return new VFragment(childs);
|
|
2772
|
-
}
|
|
2773
|
-
renderComment(text) {
|
|
2774
|
-
return new VComment(text);
|
|
2775
|
-
}
|
|
2776
|
-
setNullCache() {
|
|
2777
|
-
this.cache = new NullDomCache();
|
|
2778
|
-
}
|
|
2779
|
-
renderToDOM(stack, val) {
|
|
2780
|
-
const rootNode = document.createElement("div");
|
|
2781
|
-
const rOpts = { document };
|
|
2782
|
-
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
2783
|
-
return rootNode.childNodes[0];
|
|
2784
|
-
}
|
|
2785
|
-
renderToString(stack, val, cleanAttrs = true) {
|
|
2786
|
-
const dom = this.renderToDOM(stack, val);
|
|
2787
|
-
if (cleanAttrs) {
|
|
2788
|
-
const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
|
|
2789
|
-
for (const { dataset } of nodes) for (const name of DATASET_ATTRS) delete dataset[name];
|
|
2790
|
-
}
|
|
2791
|
-
return dom.innerHTML;
|
|
2792
|
-
}
|
|
2793
|
-
renderRoot(stack, val, viewName = null) {
|
|
2794
|
-
const comp = this.comps.getCompFor(val);
|
|
2795
|
-
if (comp === null) return null;
|
|
2796
|
-
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
2797
|
-
}
|
|
2798
|
-
renderIt(stack, node, key, viewName) {
|
|
2799
|
-
const comp = this.comps.getCompFor(stack.it);
|
|
2800
|
-
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName) : null;
|
|
2801
|
-
}
|
|
2802
|
-
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
2803
|
-
// `render-each`, or the view's root anode for the app root). It keys the
|
|
2804
|
-
// cache as a globally-unique object: node ids alone are unique only within a
|
|
2805
|
-
// single view, so the same value rendered by two components (e.g. through a
|
|
2806
|
-
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
2807
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
2808
|
-
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
2809
|
-
const cachePath = [node, val];
|
|
2810
|
-
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
2811
|
-
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
2812
|
-
if (cachedNode) return cachedNode;
|
|
2813
|
-
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
2814
|
-
const body = this.renderView(view, stack);
|
|
2815
|
-
if (body == null) return null;
|
|
2816
|
-
const meta = this._renderMetadata({
|
|
2817
|
-
$: "Comp",
|
|
2818
|
-
nid: node?.nodeId ?? null,
|
|
2819
|
-
cid: comp.id,
|
|
2820
|
-
vid: view.name
|
|
2821
|
-
});
|
|
2822
|
-
const dom = new VFragment([meta, body]);
|
|
2823
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
2824
|
-
return dom;
|
|
2825
|
-
}
|
|
2826
|
-
pushEachEntry(r, nid, attrName, key, dom) {
|
|
2827
|
-
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
2828
|
-
}
|
|
2829
|
-
renderEachWhen(stack, iterInfo, view, nid) {
|
|
2830
|
-
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
2831
|
-
const r = [];
|
|
2832
|
-
const it = stack.it;
|
|
2833
|
-
const { iterData, start, end, keys } = unpackLoopResult(
|
|
2834
|
-
loopWith.call(it, seq, makeLoopCtx(stack, filter)),
|
|
2835
|
-
seq
|
|
2836
|
-
);
|
|
2837
|
-
const renderOne = (key, value, attrName) => {
|
|
2838
|
-
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
2839
|
-
const binds = { key, value };
|
|
2840
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
2841
|
-
if (enricher) callEnricher(enricher, it, binds, key, value, iterData);
|
|
2842
|
-
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
2843
|
-
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
2844
|
-
else {
|
|
2845
|
-
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
2846
|
-
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
2847
|
-
this.cache.set(cachePath, cacheKey, dom);
|
|
2848
|
-
}
|
|
2849
|
-
};
|
|
2850
|
-
if (keys) keysIter(seq, renderOne, keys);
|
|
2851
|
-
else
|
|
2852
|
-
getSeqInfo(seq)(
|
|
2853
|
-
seq,
|
|
2854
|
-
(key, value, attrName) => {
|
|
2855
|
-
if (filter.call(it, key, value, iterData)) renderOne(key, value, attrName);
|
|
2856
|
-
},
|
|
2857
|
-
start,
|
|
2858
|
-
end
|
|
2859
|
-
);
|
|
2860
|
-
return r;
|
|
2861
|
-
}
|
|
2862
|
-
renderView(view, stack) {
|
|
2863
|
-
let n = stack.binds[1];
|
|
2864
|
-
while (n !== null) {
|
|
2865
|
-
const b = n[0];
|
|
2866
|
-
if (b.isFrame) {
|
|
2867
|
-
if (stack.it !== b.it) break;
|
|
2868
|
-
console.error("recursion detected", stack.it, b.it);
|
|
2869
|
-
return new VComment("RECURSION AVOIDED");
|
|
2870
|
-
}
|
|
2871
|
-
n = n[1];
|
|
2872
|
-
}
|
|
2873
|
-
return view.render(stack, this);
|
|
2874
|
-
}
|
|
2875
|
-
_renderMetadata(info) {
|
|
2876
|
-
return new VComment(`§${JSON.stringify(info)}§`);
|
|
2877
|
-
}
|
|
2878
|
-
// Prefix a loop-less @enrich-with subtree with a boundary meta so event-path
|
|
2879
|
-
// reconstruction replays its binds (mirrors the §Each§ / §Comp§ metas).
|
|
2880
|
-
renderScopeMeta(nid, dom) {
|
|
2881
|
-
return new VFragment([this._renderMetadata({ $: "Scope", nid }), dom]);
|
|
2882
|
-
}
|
|
2883
|
-
};
|
|
2884
|
-
getSeqInfo = (seq) => isIndexedSeq(seq) ? nativeIndexedIter : isKeyedSeq(seq) || isSetSeq(seq) ? nativeKeyedIter : seq?.[SEQ_INFO] ?? unkIter;
|
|
2885
|
-
normalizeRange = (start, end, size) => {
|
|
2886
|
-
let s = start == null ? 0 : start < 0 ? size + start : start;
|
|
2887
|
-
let e = end == null ? size : end < 0 ? size + end : end;
|
|
2888
|
-
s = s < 0 ? 0 : s > size ? size : s;
|
|
2889
|
-
e = e < 0 ? 0 : e > size ? size : e;
|
|
2890
|
-
return [s, e < s ? s : e];
|
|
2891
|
-
};
|
|
2892
|
-
callEnricher = (enricher, it, binds, key, value, iterData) => {
|
|
2893
|
-
enricher.call(it, binds, key, value, iterData);
|
|
2894
|
-
console.assert(
|
|
2895
|
-
binds.key === key && binds.value === value,
|
|
2896
|
-
"@enrich-with handlers must not overwrite binds.key or binds.value"
|
|
2897
|
-
);
|
|
2898
|
-
binds.key = key;
|
|
2899
|
-
binds.value = value;
|
|
2900
|
-
};
|
|
2901
|
-
filterAlwaysTrue = (_v, _k, _seq) => true;
|
|
2902
|
-
nullLoopWith = (seq) => ({ iterData: { seq } });
|
|
2903
|
-
unpackLoopResult = (result, seq) => {
|
|
2904
|
-
const r = result ?? {};
|
|
2905
|
-
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
|
|
2906
|
-
};
|
|
2907
|
-
keysIter = (seq, visit, keys) => {
|
|
2908
|
-
const attrName = isIndexedSeq(seq) ? "si" : "sk";
|
|
2909
|
-
for (const key of keys) visit(key, seqGet(seq, key), attrName);
|
|
2910
|
-
};
|
|
2911
|
-
makeLoopCtx = (stack, filter) => ({
|
|
2912
|
-
lookup: (name) => stack.lookupBind(name),
|
|
2913
|
-
filter: (key, value, iterData) => filter.call(stack.it, key, value, iterData)
|
|
2914
|
-
});
|
|
2915
|
-
nativeIndexedIter = (seq, visit, start, end) => {
|
|
2916
|
-
const [s, e] = normalizeRange(start, end, seqSize(seq));
|
|
2917
|
-
for (let i = s; i < e; i++) visit(i, seq[i], "si");
|
|
2918
|
-
};
|
|
2919
|
-
nativeKeyedIter = (seq, visit, start, end) => {
|
|
2920
|
-
const [s, e] = normalizeRange(start, end, seqSize(seq));
|
|
2921
|
-
let i = 0;
|
|
2922
|
-
for (const [k, v] of seqEntries(seq)) {
|
|
2923
|
-
if (i >= e) break;
|
|
2924
|
-
if (i >= s) visit(k, v, "sk");
|
|
2925
|
-
i++;
|
|
2926
|
-
}
|
|
2927
|
-
};
|
|
2928
|
-
unkIter = () => {
|
|
2929
|
-
};
|
|
2930
|
-
SEQ_INFO = /* @__PURE__ */ Symbol.for("tutuca.seqInfo");
|
|
2931
|
-
}
|
|
2932
|
-
});
|
|
2933
|
-
|
|
2934
2735
|
// src/anode.js
|
|
2935
2736
|
function resolveDynProducer(comp, name) {
|
|
2936
|
-
|
|
2937
|
-
const
|
|
2938
|
-
|
|
2939
|
-
producerComp = comp.scope?.lookupComponent(lk.compName);
|
|
2940
|
-
producerProvide = producerComp?.provide?.[lk.provideName];
|
|
2941
|
-
} else {
|
|
2942
|
-
const p = comp?.provide?.[name];
|
|
2943
|
-
if (p == null) return null;
|
|
2944
|
-
producerComp = comp;
|
|
2945
|
-
producerProvide = p;
|
|
2946
|
-
}
|
|
2737
|
+
const own = comp?.provide?.[name];
|
|
2738
|
+
const producerComp = own != null ? comp : comp?.scope?.lookupProvider(name) ?? null;
|
|
2739
|
+
const producerProvide = own ?? producerComp?.provide?.[name];
|
|
2947
2740
|
if (producerComp == null || producerProvide == null) return null;
|
|
2948
2741
|
const pi = producerProvide.val?.toPathItem?.() ?? null;
|
|
2949
2742
|
return { producerCompId: producerComp.id, producerSteps: pi ? [pi] : [] };
|
|
@@ -3063,16 +2856,10 @@ function parseRenderEach(px, value, as, attrs) {
|
|
|
3063
2856
|
const seqVal = parseXOpVal("render-each", value, px, parseSequence);
|
|
3064
2857
|
if (seqVal === null) return null;
|
|
3065
2858
|
const renderIt = px.addNode(RenderItNode, as);
|
|
3066
|
-
const
|
|
3067
|
-
const eachAttr = attrParser.pushWrapper("each", value, seqVal);
|
|
3068
|
-
attrParser.eachAttr = eachAttr;
|
|
3069
|
-
const when = attrs.getNamedItem("@when");
|
|
3070
|
-
if (when) attrParser._parseWhen(when.value);
|
|
3071
|
-
const lWith = attrs.getNamedItem("@loop-with");
|
|
3072
|
-
if (lWith) attrParser._parseLoopWith(lWith.value);
|
|
2859
|
+
const { whenVal, loopWithVal } = parseIterationDirectives(attrs, px);
|
|
3073
2860
|
const each2 = px.addNodeIf(EachNode, seqVal);
|
|
3074
|
-
each2.iterInfo.whenVal =
|
|
3075
|
-
each2.iterInfo.loopWithVal =
|
|
2861
|
+
each2.iterInfo.whenVal = whenVal;
|
|
2862
|
+
each2.iterInfo.loopWithVal = loopWithVal;
|
|
3076
2863
|
each2.fromRenderEach = true;
|
|
3077
2864
|
each2.wrapNode(renderIt);
|
|
3078
2865
|
return each2;
|
|
@@ -3124,8 +2911,8 @@ var init_anode = __esm({
|
|
|
3124
2911
|
"src/anode.js"() {
|
|
3125
2912
|
init_attribute();
|
|
3126
2913
|
init_collection();
|
|
2914
|
+
init_iteration();
|
|
3127
2915
|
init_path();
|
|
3128
|
-
init_renderer();
|
|
3129
2916
|
init_env();
|
|
3130
2917
|
init_value();
|
|
3131
2918
|
init_vdom();
|
|
@@ -3679,7 +3466,7 @@ var init_anode = __esm({
|
|
|
3679
3466
|
});
|
|
3680
3467
|
|
|
3681
3468
|
// src/components.js
|
|
3682
|
-
var COMPONENT, Components, ComponentStack, ProvideInfo, LookupInfo, isString, _rawSpecKeys, KNOWN_SPEC_KEYS, _compId, Component;
|
|
3469
|
+
var COMPONENT, Components, ComponentStack, ProvideInfo, LookupInfo, isString, isTypeName, _rawSpecKeys, KNOWN_SPEC_KEYS, _compId, Component;
|
|
3683
3470
|
var init_components = __esm({
|
|
3684
3471
|
"src/components.js"() {
|
|
3685
3472
|
init_anode();
|
|
@@ -3711,7 +3498,7 @@ var init_components = __esm({
|
|
|
3711
3498
|
}
|
|
3712
3499
|
compileStyles() {
|
|
3713
3500
|
const styles2 = [];
|
|
3714
|
-
for (const
|
|
3501
|
+
for (const Comp of this.byId.values()) styles2.push(Comp[COMPONENT].compileStyle());
|
|
3715
3502
|
return styles2.join("\n");
|
|
3716
3503
|
}
|
|
3717
3504
|
};
|
|
@@ -3770,32 +3557,39 @@ var init_components = __esm({
|
|
|
3770
3557
|
lookupComponent(name) {
|
|
3771
3558
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
3772
3559
|
}
|
|
3560
|
+
// The component in this scope chain that provides `name`, innermost first. A lookup
|
|
3561
|
+
// names a value without naming its producer, so the render-target teleport
|
|
3562
|
+
// (resolveDynProducer) recovers the producer here instead. Sound because
|
|
3563
|
+
// PROVIDE_NAME_COLLISION keeps a provide name to one producer per chain; with two,
|
|
3564
|
+
// this returns the innermost and the linter has already reported the ambiguity.
|
|
3565
|
+
lookupProvider(name) {
|
|
3566
|
+
for (const compName in this.byName) {
|
|
3567
|
+
const Comp = this.byName[compName];
|
|
3568
|
+
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
3569
|
+
}
|
|
3570
|
+
return this.parent?.lookupProvider(name) ?? null;
|
|
3571
|
+
}
|
|
3773
3572
|
lookupMacro(name) {
|
|
3774
3573
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
3775
3574
|
}
|
|
3776
3575
|
};
|
|
3777
3576
|
ProvideInfo = class {
|
|
3778
|
-
constructor(name, val
|
|
3577
|
+
constructor(name, val) {
|
|
3779
3578
|
this.name = name;
|
|
3780
3579
|
this.val = val;
|
|
3781
|
-
this.symbol = symbol;
|
|
3782
3580
|
}
|
|
3783
3581
|
};
|
|
3784
3582
|
LookupInfo = class {
|
|
3785
|
-
constructor(name,
|
|
3583
|
+
constructor(name, val) {
|
|
3786
3584
|
this.name = name;
|
|
3787
|
-
this.compName = compName;
|
|
3788
|
-
this.provideName = provideName;
|
|
3789
3585
|
this.val = val;
|
|
3790
|
-
this._sym = void 0;
|
|
3791
|
-
}
|
|
3792
|
-
getProducerSymbol(stack) {
|
|
3793
|
-
if (this._sym === void 0)
|
|
3794
|
-
this._sym = stack.lookupType(this.compName)?.provide?.[this.provideName]?.symbol ?? null;
|
|
3795
|
-
return this._sym;
|
|
3796
3586
|
}
|
|
3797
3587
|
};
|
|
3798
3588
|
isString = (v) => typeof v === "string";
|
|
3589
|
+
isTypeName = (s) => {
|
|
3590
|
+
const c = s.charCodeAt(0);
|
|
3591
|
+
return c >= 65 && c <= 90;
|
|
3592
|
+
};
|
|
3799
3593
|
_rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
3800
3594
|
KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
3801
3595
|
_compId = 0;
|
|
@@ -3816,8 +3610,9 @@ var init_components = __esm({
|
|
|
3816
3610
|
this.views[name] = new View(name, view, style);
|
|
3817
3611
|
}
|
|
3818
3612
|
this._rawProvide = o.provide ?? {};
|
|
3819
|
-
this._rawLookup = o.lookup ??
|
|
3613
|
+
this._rawLookup = o.lookup ?? [];
|
|
3820
3614
|
this.provide = {};
|
|
3615
|
+
this.provideType = {};
|
|
3821
3616
|
this.lookup = {};
|
|
3822
3617
|
this.scope = null;
|
|
3823
3618
|
this.spec = o;
|
|
@@ -3829,25 +3624,23 @@ var init_components = __esm({
|
|
|
3829
3624
|
this.views[name].compile(new ParseContext2(), this.scope, this.id);
|
|
3830
3625
|
const ctx = this.views.main.ctx;
|
|
3831
3626
|
for (const key in this._rawProvide) {
|
|
3627
|
+
if (isTypeName(key)) {
|
|
3628
|
+
if (this._rawProvide[key] === "self") this.provideType[key] = this.Class;
|
|
3629
|
+
continue;
|
|
3630
|
+
}
|
|
3832
3631
|
const val = parseProvide(this._rawProvide[key], ctx);
|
|
3833
|
-
if (val) this.provide[key] = new ProvideInfo(key, val
|
|
3632
|
+
if (val) this.provide[key] = new ProvideInfo(key, val);
|
|
3834
3633
|
}
|
|
3835
|
-
for (const
|
|
3836
|
-
const
|
|
3837
|
-
|
|
3838
|
-
const
|
|
3839
|
-
|
|
3840
|
-
const defStr = isString(linfo?.default) ? linfo.default : null;
|
|
3841
|
-
const val = defStr === null ? null : parseField(defStr, ctx);
|
|
3842
|
-
this.lookup[key] = new LookupInfo(key, compName, provideName, val);
|
|
3634
|
+
for (const entry of this._rawLookup) {
|
|
3635
|
+
const name = isString(entry) ? entry : isString(entry?.name) ? entry.name : null;
|
|
3636
|
+
if (name === null) continue;
|
|
3637
|
+
const defStr = isString(entry?.default) ? entry.default : null;
|
|
3638
|
+
this.lookup[name] = new LookupInfo(name, defStr === null ? null : parseField(defStr, ctx));
|
|
3843
3639
|
}
|
|
3844
3640
|
for (const key in this.lookup)
|
|
3845
3641
|
if (this.provide[key] !== void 0)
|
|
3846
3642
|
console.warn("name declared in both provide and lookup", this.name, key);
|
|
3847
3643
|
}
|
|
3848
|
-
make(args, opts) {
|
|
3849
|
-
return this.Class.make(args, opts ?? { scope: this.scope });
|
|
3850
|
-
}
|
|
3851
3644
|
getView(name) {
|
|
3852
3645
|
return this.views[name] ?? this.views.main;
|
|
3853
3646
|
}
|
|
@@ -6206,7 +5999,11 @@ function checkComponent(Comp, lx = new LintContext(), { wellKnownExtras = EMPTY_
|
|
|
6206
5999
|
checkFieldDeclarations(lx, Comp);
|
|
6207
6000
|
checkFieldMethodNameCollisions(lx, Comp);
|
|
6208
6001
|
checkProvidesAreAddressable(lx, Comp);
|
|
6002
|
+
checkProvidedTypes(lx, Comp);
|
|
6003
|
+
checkProvideNameCollisions(lx, Comp);
|
|
6209
6004
|
checkLookupShapes(lx, Comp);
|
|
6005
|
+
checkLookupTypesResolve(lx, Comp);
|
|
6006
|
+
checkLookupsHaveProviders(lx, Comp);
|
|
6210
6007
|
checkHandlersNotAsync(lx, Comp);
|
|
6211
6008
|
checkHandlerNameCollisions(lx, Comp);
|
|
6212
6009
|
checkScopedStyleTopLevel(lx, Comp);
|
|
@@ -6765,53 +6562,95 @@ function checkScopedStyleTopLevel(lx, Comp) {
|
|
|
6765
6562
|
}
|
|
6766
6563
|
function checkProvidesAreAddressable(lx, Comp) {
|
|
6767
6564
|
for (const name in Comp._rawProvide) {
|
|
6565
|
+
if (isTypeName2(name)) continue;
|
|
6768
6566
|
if (Comp.provide[name] === void 0) {
|
|
6769
6567
|
lx.error(PROVIDE_NOT_ADDRESSABLE, { name, value: Comp._rawProvide[name] });
|
|
6770
6568
|
}
|
|
6771
|
-
}
|
|
6772
|
-
}
|
|
6773
|
-
function
|
|
6774
|
-
for (const name in Comp.
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
if (
|
|
6778
|
-
|
|
6779
|
-
|
|
6569
|
+
}
|
|
6570
|
+
}
|
|
6571
|
+
function checkProvidedTypes(lx, Comp) {
|
|
6572
|
+
for (const name in Comp._rawProvide) {
|
|
6573
|
+
if (!isTypeName2(name)) continue;
|
|
6574
|
+
const raw = Comp._rawProvide[name];
|
|
6575
|
+
if (raw !== "self") lx.error(PROVIDE_TYPE_BAD_SHAPE, { name, value: raw });
|
|
6576
|
+
}
|
|
6577
|
+
}
|
|
6578
|
+
function checkProvideNameCollisions(lx, Comp) {
|
|
6579
|
+
const scope = Comp.scope;
|
|
6580
|
+
if (!scope) return;
|
|
6581
|
+
for (const name in Comp.provide) {
|
|
6582
|
+
for (let s = scope; s; s = s.parent) {
|
|
6583
|
+
for (const otherName in s.byName) {
|
|
6584
|
+
const Other = s.byName[otherName];
|
|
6585
|
+
if (Other !== Comp && Other.provide?.[name] !== void 0)
|
|
6586
|
+
lx.error(PROVIDE_NAME_COLLISION, { name, other: Other.name });
|
|
6587
|
+
}
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
}
|
|
6591
|
+
function checkLookupShapes(lx, Comp) {
|
|
6592
|
+
const raw = Comp._rawLookup;
|
|
6593
|
+
if (!Array.isArray(raw)) {
|
|
6594
|
+
if (raw !== void 0 && Object.keys(raw).length > 0)
|
|
6595
|
+
lx.error(LOOKUP_BAD_SHAPE, { name: "lookup", problem: "must be a list of names" });
|
|
6596
|
+
return;
|
|
6597
|
+
}
|
|
6598
|
+
for (const entry of raw) {
|
|
6599
|
+
if (typeof entry === "string") continue;
|
|
6600
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
6601
|
+
lx.error(LOOKUP_BAD_SHAPE, {
|
|
6602
|
+
name: String(entry),
|
|
6603
|
+
problem: 'must be a "name" string or a { name, default } object'
|
|
6604
|
+
});
|
|
6605
|
+
continue;
|
|
6606
|
+
}
|
|
6607
|
+
const extra = Object.keys(entry).filter((k) => !KNOWN_LOOKUP_KEYS.has(k));
|
|
6608
|
+
if (extra.length > 0) {
|
|
6780
6609
|
lx.error(LOOKUP_BAD_SHAPE, {
|
|
6781
|
-
name,
|
|
6782
|
-
problem:
|
|
6610
|
+
name: String(entry.name),
|
|
6611
|
+
problem: `unknown key(s): ${extra.join(", ")}`
|
|
6783
6612
|
});
|
|
6784
6613
|
continue;
|
|
6785
|
-
} else {
|
|
6786
|
-
const extra = Object.keys(raw).filter((k) => !KNOWN_LOOKUP_KEYS.has(k));
|
|
6787
|
-
if (extra.length > 0) {
|
|
6788
|
-
lx.error(LOOKUP_BAD_SHAPE, { name, problem: `unknown key(s): ${extra.join(", ")}` });
|
|
6789
|
-
continue;
|
|
6790
|
-
}
|
|
6791
|
-
if (typeof raw.for !== "string") {
|
|
6792
|
-
lx.error(LOOKUP_BAD_SHAPE, { name, problem: "'for' is required and must be a string" });
|
|
6793
|
-
continue;
|
|
6794
|
-
}
|
|
6795
|
-
if (raw.default !== void 0 && typeof raw.default !== "string") {
|
|
6796
|
-
lx.error(LOOKUP_BAD_SHAPE, { name, problem: "'default' must be a string" });
|
|
6797
|
-
continue;
|
|
6798
|
-
}
|
|
6799
|
-
target = raw.for;
|
|
6800
6614
|
}
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6615
|
+
if (typeof entry.name !== "string" || entry.name === "") {
|
|
6616
|
+
lx.error(LOOKUP_BAD_SHAPE, {
|
|
6617
|
+
name: String(entry.name),
|
|
6618
|
+
problem: "'name' is required and must be a string"
|
|
6619
|
+
});
|
|
6620
|
+
continue;
|
|
6804
6621
|
}
|
|
6622
|
+
if (entry.default !== void 0 && typeof entry.default !== "string")
|
|
6623
|
+
lx.error(LOOKUP_BAD_SHAPE, { name: entry.name, problem: "'default' must be a string" });
|
|
6624
|
+
}
|
|
6625
|
+
}
|
|
6626
|
+
function checkLookupsHaveProviders(lx, Comp) {
|
|
6627
|
+
const scope = Comp.scope;
|
|
6628
|
+
if (!scope) return;
|
|
6629
|
+
for (const name in Comp.lookup) {
|
|
6630
|
+
if (isTypeName2(name)) continue;
|
|
6631
|
+
if (scope.lookupProvider?.(name)) continue;
|
|
6632
|
+
const info = { name, hasDefault: Comp.lookup[name].val != null };
|
|
6633
|
+
if (info.hasDefault) lx.hint(LOOKUP_NO_PROVIDER, info);
|
|
6634
|
+
else lx.error(LOOKUP_NO_PROVIDER, info);
|
|
6635
|
+
}
|
|
6636
|
+
}
|
|
6637
|
+
function checkLookupTypesResolve(lx, Comp) {
|
|
6638
|
+
if (!Comp.scope) return;
|
|
6639
|
+
for (const name in Comp.lookup) {
|
|
6640
|
+
if (!isTypeName2(name)) continue;
|
|
6641
|
+
if (Comp.scope.lookupComponent(name) === null)
|
|
6642
|
+
reportUnknownName(lx, UNKNOWN_COMPONENT_NAME, name, scopeKeysAlong(Comp.scope, "byName"), {});
|
|
6805
6643
|
}
|
|
6806
6644
|
}
|
|
6807
6645
|
function checkUnreferencedDynamics(lx, Comp, referencedDynamics) {
|
|
6808
6646
|
for (const name in Comp.lookup) {
|
|
6647
|
+
if (isTypeName2(name)) continue;
|
|
6809
6648
|
if (!referencedDynamics.has(name)) {
|
|
6810
6649
|
lx.hint(DYN_ALIAS_NOT_REFERENCED, { name });
|
|
6811
6650
|
}
|
|
6812
6651
|
}
|
|
6813
6652
|
}
|
|
6814
|
-
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED, ALT_HANDLER_NOT_REFERENCED, DYN_VAL_NOT_DEFINED, DYN_ALIAS_NOT_REFERENCED, PROVIDE_NOT_ADDRESSABLE, LOOKUP_BAD_SHAPE,
|
|
6653
|
+
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, PROVIDE_NAME_COLLISION, 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;
|
|
6815
6654
|
var init_lint_check = __esm({
|
|
6816
6655
|
"tools/core/lint-check.js"() {
|
|
6817
6656
|
init_anode();
|
|
@@ -6839,13 +6678,19 @@ var init_lint_check = __esm({
|
|
|
6839
6678
|
"then",
|
|
6840
6679
|
"else"
|
|
6841
6680
|
]);
|
|
6681
|
+
isTypeName2 = (s) => {
|
|
6682
|
+
const c = s.charCodeAt(0);
|
|
6683
|
+
return c >= 65 && c <= 90;
|
|
6684
|
+
};
|
|
6842
6685
|
ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED";
|
|
6843
6686
|
ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED";
|
|
6844
6687
|
DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED";
|
|
6845
6688
|
DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED";
|
|
6846
6689
|
PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE";
|
|
6690
|
+
PROVIDE_TYPE_BAD_SHAPE = "PROVIDE_TYPE_BAD_SHAPE";
|
|
6691
|
+
PROVIDE_NAME_COLLISION = "PROVIDE_NAME_COLLISION";
|
|
6847
6692
|
LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE";
|
|
6848
|
-
|
|
6693
|
+
LOOKUP_NO_PROVIDER = "LOOKUP_NO_PROVIDER";
|
|
6849
6694
|
RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP";
|
|
6850
6695
|
UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER";
|
|
6851
6696
|
RECEIVE_HANDLER_NOT_IMPLEMENTED = "RECEIVE_HANDLER_NOT_IMPLEMENTED";
|
|
@@ -6962,16 +6807,6 @@ var init_lint_check = __esm({
|
|
|
6962
6807
|
recurse(val.seqVal);
|
|
6963
6808
|
recurse(val.keyVal);
|
|
6964
6809
|
},
|
|
6965
|
-
TypeVal({ lx, val, env, errCtx }) {
|
|
6966
|
-
if (env.scope.lookupComponent(val.name) === null)
|
|
6967
|
-
reportUnknownName(
|
|
6968
|
-
lx,
|
|
6969
|
-
UNKNOWN_COMPONENT_NAME,
|
|
6970
|
-
val.name,
|
|
6971
|
-
scopeKeysAlong(env.scope, "byName"),
|
|
6972
|
-
errCtx
|
|
6973
|
-
);
|
|
6974
|
-
},
|
|
6975
6810
|
// NameVals on a macro call-site attribute are macro-param bindings, not
|
|
6976
6811
|
// handler args — their role is determined inside the macro body after
|
|
6977
6812
|
// ^-substitution, where re-parsing handles validation. No checker: a NameVal
|
|
@@ -7030,7 +6865,7 @@ var init_lint_check = __esm({
|
|
|
7030
6865
|
IGNORE_DIRECTIVE = /\/\*\s*tutuca-lint-ignore\s*\*\//g;
|
|
7031
6866
|
blankRun = (m) => m.replace(/[^\n]/g, " ");
|
|
7032
6867
|
STYLE_TO_GLOBAL_HELP = "Move it to the component's 'globalStyle' key, which is injected without the component-scoping wrapper. To suppress a false positive, put a /* tutuca-lint-ignore */ comment on the same line.";
|
|
7033
|
-
KNOWN_LOOKUP_KEYS = /* @__PURE__ */ new Set(["
|
|
6868
|
+
KNOWN_LOOKUP_KEYS = /* @__PURE__ */ new Set(["name", "default"]);
|
|
7034
6869
|
LintContext = class {
|
|
7035
6870
|
constructor() {
|
|
7036
6871
|
this.reports = [];
|
|
@@ -7175,13 +7010,25 @@ var init_lint_rules = __esm({
|
|
|
7175
7010
|
code: LOOKUP_BAD_SHAPE,
|
|
7176
7011
|
level: "error",
|
|
7177
7012
|
group: "Dynamic bindings",
|
|
7178
|
-
summary: "`lookup` entry must be a string or `{
|
|
7013
|
+
summary: "`lookup` entry must be a name string or `{ name, default }`."
|
|
7014
|
+
},
|
|
7015
|
+
{
|
|
7016
|
+
code: LOOKUP_NO_PROVIDER,
|
|
7017
|
+
level: "error",
|
|
7018
|
+
group: "Dynamic bindings",
|
|
7019
|
+
summary: "`lookup` name is provided by no component in scope."
|
|
7020
|
+
},
|
|
7021
|
+
{
|
|
7022
|
+
code: PROVIDE_TYPE_BAD_SHAPE,
|
|
7023
|
+
level: "error",
|
|
7024
|
+
group: "Dynamic bindings",
|
|
7025
|
+
summary: 'A PascalCase `provide` publishes a component type; its value must be `"self"`.'
|
|
7179
7026
|
},
|
|
7180
7027
|
{
|
|
7181
|
-
code:
|
|
7028
|
+
code: PROVIDE_NAME_COLLISION,
|
|
7182
7029
|
level: "error",
|
|
7183
7030
|
group: "Dynamic bindings",
|
|
7184
|
-
summary:
|
|
7031
|
+
summary: "Two components in one scope chain `provide` the same name."
|
|
7185
7032
|
},
|
|
7186
7033
|
// Templates / events
|
|
7187
7034
|
{
|
|
@@ -7474,8 +7321,12 @@ function lintIdToMessage(id, info) {
|
|
|
7474
7321
|
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a method/constant can't be a render target`;
|
|
7475
7322
|
case "LOOKUP_BAD_SHAPE":
|
|
7476
7323
|
return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
|
|
7477
|
-
case "
|
|
7478
|
-
return `Lookup '${info.name}'
|
|
7324
|
+
case "LOOKUP_NO_PROVIDER":
|
|
7325
|
+
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`;
|
|
7326
|
+
case "PROVIDE_TYPE_BAD_SHAPE":
|
|
7327
|
+
return `Provide '${info.name}' starts uppercase, so it publishes a component type — its value must be 'self', not '${info.value}'`;
|
|
7328
|
+
case "PROVIDE_NAME_COLLISION":
|
|
7329
|
+
return `Provide '${info.name}' is also provided by '${info.other}' in the same scope — one name, one provider, so a lookup can find it`;
|
|
7479
7330
|
case "UNKNOWN_MACRO_ARG":
|
|
7480
7331
|
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
7481
7332
|
case "UNKNOWN_DIRECTIVE":
|
|
@@ -12951,6 +12802,21 @@ var init_list = __esm({
|
|
|
12951
12802
|
});
|
|
12952
12803
|
|
|
12953
12804
|
// src/stack.js
|
|
12805
|
+
function routeLookup(route, lex, dyn) {
|
|
12806
|
+
for (let i = 0; i < route.length; i++) {
|
|
12807
|
+
const leg = route[i];
|
|
12808
|
+
if (leg === "dyn") {
|
|
12809
|
+
const v = dyn();
|
|
12810
|
+
if (v != null) return v;
|
|
12811
|
+
} else if (leg === "lex") {
|
|
12812
|
+
const v = lex();
|
|
12813
|
+
if (v != null) return v;
|
|
12814
|
+
} else {
|
|
12815
|
+
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
12816
|
+
}
|
|
12817
|
+
}
|
|
12818
|
+
return null;
|
|
12819
|
+
}
|
|
12954
12820
|
function lookup(chain, name, dv = null) {
|
|
12955
12821
|
let n = chain;
|
|
12956
12822
|
while (n !== null) {
|
|
@@ -12970,11 +12836,12 @@ function computeViewsId(views) {
|
|
|
12970
12836
|
}
|
|
12971
12837
|
return s === "main" ? "" : s;
|
|
12972
12838
|
}
|
|
12973
|
-
var STOP, NEXT, BindFrame, ObjectFrame, Stack;
|
|
12839
|
+
var STOP, NEXT, DEFAULT_LOOKUP_ROUTE, BindFrame, ObjectFrame, Stack;
|
|
12974
12840
|
var init_stack = __esm({
|
|
12975
12841
|
"src/stack.js"() {
|
|
12976
12842
|
STOP = /* @__PURE__ */ Symbol("STOP");
|
|
12977
12843
|
NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
12844
|
+
DEFAULT_LOOKUP_ROUTE = ["dyn", "lex"];
|
|
12978
12845
|
BindFrame = class {
|
|
12979
12846
|
constructor(it, binds, isFrame) {
|
|
12980
12847
|
this.it = it;
|
|
@@ -13006,14 +12873,21 @@ var init_stack = __esm({
|
|
|
13006
12873
|
this.ctx = ctx;
|
|
13007
12874
|
}
|
|
13008
12875
|
// Evaluate every provide the entered component publishes and push them as one
|
|
13009
|
-
// dynBinds frame
|
|
12876
|
+
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
12877
|
+
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
12878
|
+
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
13010
12879
|
_pushProvides() {
|
|
13011
|
-
const
|
|
13012
|
-
if (
|
|
12880
|
+
const comp = this.comps.getCompFor(this.it);
|
|
12881
|
+
if (comp == null) return this;
|
|
12882
|
+
const { provide, provideType } = comp;
|
|
13013
12883
|
const dynObj = {};
|
|
13014
12884
|
let has2 = false;
|
|
13015
12885
|
for (const k in provide) {
|
|
13016
|
-
dynObj[
|
|
12886
|
+
dynObj[k] = provide[k].val.eval(this);
|
|
12887
|
+
has2 = true;
|
|
12888
|
+
}
|
|
12889
|
+
for (const k in provideType) {
|
|
12890
|
+
dynObj[k] = provideType[k];
|
|
13017
12891
|
has2 = true;
|
|
13018
12892
|
}
|
|
13019
12893
|
if (!has2) return this;
|
|
@@ -13038,30 +12912,36 @@ var init_stack = __esm({
|
|
|
13038
12912
|
const newViews = [name, views];
|
|
13039
12913
|
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
13040
12914
|
}
|
|
12915
|
+
// Published types are stable per scope and would only churn the render cache, so
|
|
12916
|
+
// the cache key covers values alone.
|
|
13041
12917
|
_pushDynBindValuesToArray(arr, comp) {
|
|
13042
|
-
for (const k in comp.provide) arr.push(this.
|
|
13043
|
-
for (const k in comp.lookup) arr.push(this.
|
|
13044
|
-
}
|
|
13045
|
-
_lookupProvide(p) {
|
|
13046
|
-
return lookup(this.dynBinds, p.symbol) ?? p.val.eval(this) ?? null;
|
|
13047
|
-
}
|
|
13048
|
-
_lookupAlias(lk) {
|
|
13049
|
-
const sym = lk.getProducerSymbol(this);
|
|
13050
|
-
return (sym != null ? lookup(this.dynBinds, sym) : null) ?? lk.val?.eval(this) ?? null;
|
|
12918
|
+
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
12919
|
+
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
13051
12920
|
}
|
|
12921
|
+
// `*name`: the nearest binding above (including this component's own provides,
|
|
12922
|
+
// pushed on entering it), else this component's declared default, else null.
|
|
13052
12923
|
lookupDynamic(name) {
|
|
12924
|
+
const v = lookup(this.dynBinds, name);
|
|
12925
|
+
if (v != null) return v;
|
|
13053
12926
|
const comp = this.comps.getCompFor(this.it);
|
|
13054
|
-
|
|
13055
|
-
const lk = comp.lookup[name];
|
|
13056
|
-
if (lk !== void 0) return this._lookupAlias(lk);
|
|
13057
|
-
const p = comp.provide[name];
|
|
13058
|
-
return p !== void 0 ? this._lookupProvide(p) : null;
|
|
12927
|
+
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
13059
12928
|
}
|
|
13060
12929
|
lookupBind(name) {
|
|
13061
12930
|
return lookup(this.binds, name);
|
|
13062
12931
|
}
|
|
13063
|
-
|
|
13064
|
-
|
|
12932
|
+
// The `lex` leg: what a name means in the registration scope of the component being
|
|
12933
|
+
// rendered. The scope chain holds components, so this leg only ever answers for a
|
|
12934
|
+
// type name — for a value name it is a miss, which is why one default route serves
|
|
12935
|
+
// both. Guarded: a non-component `it` has no scope to ask.
|
|
12936
|
+
_lookupLex(name) {
|
|
12937
|
+
return this.comps.getCompFor(this.it)?.scope.lookupComponent(name) ?? null;
|
|
12938
|
+
}
|
|
12939
|
+
lookupRouted(name, route = DEFAULT_LOOKUP_ROUTE) {
|
|
12940
|
+
return routeLookup(
|
|
12941
|
+
route,
|
|
12942
|
+
() => this._lookupLex(name),
|
|
12943
|
+
() => this.lookupDynamic(name)
|
|
12944
|
+
);
|
|
13065
12945
|
}
|
|
13066
12946
|
lookupFieldRaw(name) {
|
|
13067
12947
|
return this.it[name] ?? null;
|
|
@@ -13070,12 +12950,6 @@ var init_stack = __esm({
|
|
|
13070
12950
|
const fn = this.it[name];
|
|
13071
12951
|
return fn instanceof Function ? fn.call(this.it) : null;
|
|
13072
12952
|
}
|
|
13073
|
-
// Bare implicit event names are gone: a sigil-less word cannot reach a
|
|
13074
|
-
// handler-arg slot anymore, so this only ever serves stale NameVals parsed
|
|
13075
|
-
// before the removal (e.g. macro-attr pass-throughs). Always null.
|
|
13076
|
-
lookupName(_name) {
|
|
13077
|
-
return null;
|
|
13078
|
-
}
|
|
13079
12953
|
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
13080
12954
|
// `e.<member>` handler args. Null outside a live event transaction.
|
|
13081
12955
|
lookupEvent() {
|
|
@@ -13136,7 +13010,7 @@ function classFromData(name, { fields = {}, methods, statics }) {
|
|
|
13136
13010
|
b.addField(field, dval, FieldCls);
|
|
13137
13011
|
} else if (value?.component && value?.args !== void 0)
|
|
13138
13012
|
b.addCompField(field, value.component, value.args);
|
|
13139
|
-
else if (
|
|
13013
|
+
else if (isPlainObject(value)) b.addField(field, { ...value }, FieldObject);
|
|
13140
13014
|
else {
|
|
13141
13015
|
const FieldCls = value?.[FIELD_CLASS] ?? FieldAny;
|
|
13142
13016
|
b.addField(field, value, FieldCls);
|
|
@@ -13160,18 +13034,21 @@ function validateDraftFields(current2, draft) {
|
|
|
13160
13034
|
}
|
|
13161
13035
|
}
|
|
13162
13036
|
}
|
|
13163
|
-
|
|
13037
|
+
function assertNoReservedComponentStatics(statics = {}) {
|
|
13038
|
+
for (const name in statics) {
|
|
13039
|
+
if (RESERVED_COMPONENT_STATICS.has(name)) {
|
|
13040
|
+
throw new TypeError(`component static "${name}" is reserved by the framework`);
|
|
13041
|
+
}
|
|
13042
|
+
}
|
|
13043
|
+
}
|
|
13044
|
+
var BAD_VALUE2, nullCoercer, Field, Check, CheckTypeAny, CHECK_TYPE_ANY, FnCheck, check, 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, getTypeName, CheckTypeName, FieldComp, FieldList, FieldObject, FieldMap, FieldSet, ClassBuilder, FIELD_CLASS, fieldsByTypeName, META_KEYS, RESERVED_COMPONENT_STATICS;
|
|
13164
13045
|
var init_oo = __esm({
|
|
13165
13046
|
"src/oo.js"() {
|
|
13047
|
+
init_collection();
|
|
13166
13048
|
init_components();
|
|
13167
13049
|
init_immer2();
|
|
13168
13050
|
BAD_VALUE2 = /* @__PURE__ */ Symbol("BadValue");
|
|
13169
13051
|
nullCoercer = (v) => v;
|
|
13170
|
-
isPlainObject4 = (v) => {
|
|
13171
|
-
if (v === null || typeof v !== "object") return false;
|
|
13172
|
-
const proto = Object.getPrototypeOf(v);
|
|
13173
|
-
return proto === Object.prototype || proto === null;
|
|
13174
|
-
};
|
|
13175
13052
|
Field = class {
|
|
13176
13053
|
constructor(type3, name, typeCheck, coercer, defaultValue = null) {
|
|
13177
13054
|
this.type = type3;
|
|
@@ -13235,7 +13112,7 @@ var init_oo = __esm({
|
|
|
13235
13112
|
CHECK_TYPE_BOOL = check((v) => typeof v === "boolean", "Boolean expected");
|
|
13236
13113
|
CHECK_TYPE_STRING = check((v) => typeof v === "string", "String expected");
|
|
13237
13114
|
CHECK_TYPE_LIST = check(Array.isArray, "Array expected");
|
|
13238
|
-
CHECK_TYPE_OBJECT = check(
|
|
13115
|
+
CHECK_TYPE_OBJECT = check(isPlainObject, "Plain object expected");
|
|
13239
13116
|
CHECK_TYPE_MAP = check((v) => v instanceof Map, "Map expected");
|
|
13240
13117
|
CHECK_TYPE_SET = check((v) => v instanceof Set, "Set expected");
|
|
13241
13118
|
FieldBool = class extends Field {
|
|
@@ -13304,7 +13181,7 @@ var init_oo = __esm({
|
|
|
13304
13181
|
"object",
|
|
13305
13182
|
name,
|
|
13306
13183
|
CHECK_TYPE_OBJECT,
|
|
13307
|
-
(v) =>
|
|
13184
|
+
(v) => isPlainObject(v) ? { ...v } : null,
|
|
13308
13185
|
defaultValue
|
|
13309
13186
|
);
|
|
13310
13187
|
}
|
|
@@ -13317,7 +13194,7 @@ var init_oo = __esm({
|
|
|
13317
13194
|
CHECK_TYPE_MAP,
|
|
13318
13195
|
(v) => {
|
|
13319
13196
|
if (v instanceof Map) return new Map(v);
|
|
13320
|
-
if (Array.isArray(v) ||
|
|
13197
|
+
if (Array.isArray(v) || isPlainObject(v))
|
|
13321
13198
|
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
13322
13199
|
return null;
|
|
13323
13200
|
},
|
|
@@ -13412,10 +13289,17 @@ var init_oo = __esm({
|
|
|
13412
13289
|
set: FieldSet,
|
|
13413
13290
|
any: FieldAny
|
|
13414
13291
|
};
|
|
13415
|
-
META_KEYS = "name id fields methods views receive intent alter provide lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
|
|
13292
|
+
META_KEYS = "name id fields methods views receive intent alter provide provideType lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
|
|
13416
13293
|
" "
|
|
13417
13294
|
);
|
|
13295
|
+
RESERVED_COMPONENT_STATICS = /* @__PURE__ */ new Set([
|
|
13296
|
+
...META_KEYS,
|
|
13297
|
+
"make",
|
|
13298
|
+
"getMetaClass",
|
|
13299
|
+
...Object.getOwnPropertyNames(Component.prototype)
|
|
13300
|
+
]);
|
|
13418
13301
|
Component.fromSpec = (opts) => {
|
|
13302
|
+
assertNoReservedComponentStatics(opts.statics);
|
|
13419
13303
|
const Class = classFromData(opts.name, opts);
|
|
13420
13304
|
const comp = new Component(Class, opts);
|
|
13421
13305
|
const metaClass = Class.getMetaClass();
|
|
@@ -13435,7 +13319,7 @@ var init_oo = __esm({
|
|
|
13435
13319
|
configurable: true
|
|
13436
13320
|
});
|
|
13437
13321
|
for (const key of Object.getOwnPropertyNames(Component.prototype))
|
|
13438
|
-
if (key !== "constructor" &&
|
|
13322
|
+
if (key !== "constructor" && !Object.hasOwn(Class, key))
|
|
13439
13323
|
Class[key] = (...args) => comp[key](...args);
|
|
13440
13324
|
return Class;
|
|
13441
13325
|
};
|
|
@@ -13452,9 +13336,10 @@ function warnNotIntent(verb) {
|
|
|
13452
13336
|
function rootDispatcher(transactor) {
|
|
13453
13337
|
return new Dispatcher(new Path([]), transactor, null);
|
|
13454
13338
|
}
|
|
13455
|
-
var State2, Transactor, Transaction, InputEvent, NameArgsTransaction, SendEvent, IntentEvent, PASS, REFUSAL_RING_CAP, DEFAULT_ROUTE, INTENT_DEPTH, IntentWalk, Completion, Dispatcher, EventContext,
|
|
13339
|
+
var State2, Transactor, Transaction, InputEvent, NameArgsTransaction, SendEvent, IntentEvent, PASS, REFUSAL_RING_CAP, DEFAULT_ROUTE, INTENT_DEPTH, IntentWalk, Completion, Dispatcher, EventContext, PathChanges;
|
|
13456
13340
|
var init_transactor = __esm({
|
|
13457
13341
|
"src/transactor.js"() {
|
|
13342
|
+
init_components();
|
|
13458
13343
|
init_immer2();
|
|
13459
13344
|
init_oo();
|
|
13460
13345
|
init_path();
|
|
@@ -13472,9 +13357,6 @@ var init_transactor = __esm({
|
|
|
13472
13357
|
this.val = val;
|
|
13473
13358
|
for (const sub of this.changeSubs) sub({ val, old, info, timestamp: Date.now() });
|
|
13474
13359
|
}
|
|
13475
|
-
update(fn, info) {
|
|
13476
|
-
return this.set(fn(this.val), info);
|
|
13477
|
-
}
|
|
13478
13360
|
};
|
|
13479
13361
|
Transactor = class {
|
|
13480
13362
|
constructor(comps, rootValue) {
|
|
@@ -13535,7 +13417,7 @@ var init_transactor = __esm({
|
|
|
13535
13417
|
// Build and dispatch the observer record for a settled transaction. The
|
|
13536
13418
|
// resolved handler (`_resolvedHandler`/`_matched`) and per-leaf before/after
|
|
13537
13419
|
// (`_before`/`_after`) were captured while the handler ran (see callHandler /
|
|
13538
|
-
//
|
|
13420
|
+
// Transaction.run). No-op when nobody is observing.
|
|
13539
13421
|
_emitTransaction(transaction, root) {
|
|
13540
13422
|
if (this._observers.length === 0) return;
|
|
13541
13423
|
if (transaction._resolvedHandler === void 0) return;
|
|
@@ -13567,8 +13449,13 @@ var init_transactor = __esm({
|
|
|
13567
13449
|
}
|
|
13568
13450
|
return child;
|
|
13569
13451
|
}
|
|
13570
|
-
|
|
13571
|
-
|
|
13452
|
+
// `origin` is where the message came FROM, pinned now for the same reason an
|
|
13453
|
+
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
13454
|
+
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
13455
|
+
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
13456
|
+
pushSend(path, name, args = [], parent = null, origin = null) {
|
|
13457
|
+
const t = new SendEvent(path, this, name, args, parent);
|
|
13458
|
+
t.origin = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
13572
13459
|
this.pushTransaction(t);
|
|
13573
13460
|
return this._link(t, parent);
|
|
13574
13461
|
}
|
|
@@ -13581,9 +13468,9 @@ var init_transactor = __esm({
|
|
|
13581
13468
|
walk.advance();
|
|
13582
13469
|
return walk;
|
|
13583
13470
|
}
|
|
13584
|
-
// Drain queued transactions and await
|
|
13585
|
-
//
|
|
13586
|
-
//
|
|
13471
|
+
// Drain queued transactions and await async intent handlers until quiescent. A
|
|
13472
|
+
// completed handler may enqueue an answer, which may dispatch more work, so we loop.
|
|
13473
|
+
// `maxTurns` backstops a pathological non-terminating cascade.
|
|
13587
13474
|
async settle(maxTurns = 1e4) {
|
|
13588
13475
|
while ((this.hasPendingTransactions || this._inflight.size) && maxTurns-- > 0) {
|
|
13589
13476
|
while (this.hasPendingTransactions) this.transactNext();
|
|
@@ -13637,9 +13524,6 @@ var init_transactor = __esm({
|
|
|
13637
13524
|
whenSubtreeSettled() {
|
|
13638
13525
|
return this.completion.whenSubtreeSettled();
|
|
13639
13526
|
}
|
|
13640
|
-
run(rootValue, comps) {
|
|
13641
|
-
return this.updateRootValue(rootValue, comps);
|
|
13642
|
-
}
|
|
13643
13527
|
afterTransaction() {
|
|
13644
13528
|
}
|
|
13645
13529
|
// Ending a walk and forwarding belong to the two dispatch buckets; the base warns
|
|
@@ -13651,12 +13535,6 @@ var init_transactor = __esm({
|
|
|
13651
13535
|
forward(_opts) {
|
|
13652
13536
|
console.warn('ctx.forward() needs a "receive" or "intent" handler - ignored');
|
|
13653
13537
|
}
|
|
13654
|
-
buildRootStack(root, comps) {
|
|
13655
|
-
return Stack.root(comps, root);
|
|
13656
|
-
}
|
|
13657
|
-
buildStack(root, comps) {
|
|
13658
|
-
return this.path.toTransactionPath().buildStack(this.buildRootStack(root, comps));
|
|
13659
|
-
}
|
|
13660
13538
|
// The kind reported to observers (see Transactor.observe); null on the base.
|
|
13661
13539
|
get observeKind() {
|
|
13662
13540
|
return null;
|
|
@@ -13676,12 +13554,11 @@ var init_transactor = __esm({
|
|
|
13676
13554
|
return null;
|
|
13677
13555
|
}
|
|
13678
13556
|
// The path used to apply the mutation. Teleports dynamic-var renders so it lands on
|
|
13679
|
-
// the data's real location (the dispatch `this.path` keeps intermediates).
|
|
13680
|
-
// may override to supply a pre-resolved path (see ResponseEvent's pinned keys).
|
|
13557
|
+
// the data's real location (the dispatch `this.path` keeps intermediates).
|
|
13681
13558
|
getTransactionPath() {
|
|
13682
13559
|
return this.path.toTransactionPath().compact();
|
|
13683
13560
|
}
|
|
13684
|
-
|
|
13561
|
+
run(curRoot, comps) {
|
|
13685
13562
|
const txnPath = this.getTransactionPath();
|
|
13686
13563
|
const curLeaf = txnPath.lookup(curRoot);
|
|
13687
13564
|
const newLeaf = produce(curLeaf, (draft) => {
|
|
@@ -13738,8 +13615,8 @@ var init_transactor = __esm({
|
|
|
13738
13615
|
}
|
|
13739
13616
|
this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
|
|
13740
13617
|
}
|
|
13741
|
-
|
|
13742
|
-
return Stack.root(comps, root, this);
|
|
13618
|
+
buildStack(root, comps) {
|
|
13619
|
+
return this.path.toTransactionPath().buildStack(Stack.root(comps, root, this));
|
|
13743
13620
|
}
|
|
13744
13621
|
getHandlerAndArgs(root, _instance, comps) {
|
|
13745
13622
|
const stack = this.buildStack(root, comps);
|
|
@@ -13757,11 +13634,10 @@ var init_transactor = __esm({
|
|
|
13757
13634
|
}
|
|
13758
13635
|
};
|
|
13759
13636
|
NameArgsTransaction = class extends Transaction {
|
|
13760
|
-
constructor(path, transactor, name, args, parentTransaction
|
|
13637
|
+
constructor(path, transactor, name, args, parentTransaction) {
|
|
13761
13638
|
super(path, transactor, parentTransaction);
|
|
13762
13639
|
this.name = name;
|
|
13763
13640
|
this.args = args;
|
|
13764
|
-
this.opts = opts;
|
|
13765
13641
|
this.targetPath = path;
|
|
13766
13642
|
}
|
|
13767
13643
|
handlerProp = null;
|
|
@@ -13820,7 +13696,7 @@ var init_transactor = __esm({
|
|
|
13820
13696
|
IntentEvent = class extends NameArgsTransaction {
|
|
13821
13697
|
handlerProp = "intent";
|
|
13822
13698
|
constructor(path, transactor, walk) {
|
|
13823
|
-
super(path, transactor, walk.name, walk.args, walk.parent
|
|
13699
|
+
super(path, transactor, walk.name, walk.args, walk.parent);
|
|
13824
13700
|
this.walk = walk;
|
|
13825
13701
|
this.targetPath = walk.origin;
|
|
13826
13702
|
}
|
|
@@ -13920,7 +13796,7 @@ var init_transactor = __esm({
|
|
|
13920
13796
|
async _runLex(chain, i) {
|
|
13921
13797
|
if (this.ended) return;
|
|
13922
13798
|
if (i >= chain.length) return this.advance();
|
|
13923
|
-
const ctx = new
|
|
13799
|
+
const ctx = new Dispatcher(this.origin, this.transactor, this.parent);
|
|
13924
13800
|
try {
|
|
13925
13801
|
const res = await chain[i].fn.apply(null, [...this.args, ctx]);
|
|
13926
13802
|
if (res === PASS) return this._runLex(chain, i + 1);
|
|
@@ -13973,7 +13849,7 @@ var init_transactor = __esm({
|
|
|
13973
13849
|
this.ended = true;
|
|
13974
13850
|
if (name === null) return this.release?.();
|
|
13975
13851
|
const path = this.answerPath ?? this.origin;
|
|
13976
|
-
const t = new SendEvent(path, this.transactor, name, args, this.parent
|
|
13852
|
+
const t = new SendEvent(path, this.transactor, name, args, this.parent);
|
|
13977
13853
|
t._isAnswer = true;
|
|
13978
13854
|
this.transactor.pushTransaction(t);
|
|
13979
13855
|
if (this.release) t.completion.whenSubtreeSettled().then(this.release);
|
|
@@ -14012,7 +13888,7 @@ var init_transactor = __esm({
|
|
|
14012
13888
|
this.val = val;
|
|
14013
13889
|
this._selfResolve?.(val);
|
|
14014
13890
|
}
|
|
14015
|
-
// Settle self even when no handler produced a value (
|
|
13891
|
+
// Settle self even when no handler produced a value (undefined-state / throw paths).
|
|
14016
13892
|
ensureSelfSettled() {
|
|
14017
13893
|
if (!this.selfSettled) this.markSelfSettled(this.val);
|
|
14018
13894
|
}
|
|
@@ -14058,12 +13934,64 @@ var init_transactor = __esm({
|
|
|
14058
13934
|
get at() {
|
|
14059
13935
|
return new PathChanges(this);
|
|
14060
13936
|
}
|
|
13937
|
+
// The render-time Stack, rebuilt on demand. A handler does not get one: the stack
|
|
13938
|
+
// that evaluated its arguments is a local in getHandlerAndArgs and is gone by the
|
|
13939
|
+
// time the body runs, and send/intent transactions never build one at all. Both
|
|
13940
|
+
// halves it needs are pinned on this ctx, so the `dyn` leg reconstructs it — and
|
|
13941
|
+
// only the `dyn` leg does, which is why this is lazy rather than eager.
|
|
13942
|
+
//
|
|
13943
|
+
// The path is compacted, so per-item binds (`@each`, `@enrich-with`) are not
|
|
13944
|
+
// replayed; provides are pushed on every component frame either way, so a provide
|
|
13945
|
+
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
13946
|
+
_stack() {
|
|
13947
|
+
this._stackMemo ??= this.path.toTransactionPath().buildStack(Stack.root(this.transactor.comps, this.root, this.parent));
|
|
13948
|
+
return this._stackMemo;
|
|
13949
|
+
}
|
|
13950
|
+
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
13951
|
+
// the same spelling as `ctx.intent` — `["dyn"]` the render ancestry, `["lex"]` the
|
|
13952
|
+
// registration scope, default both.
|
|
13953
|
+
lookup(name, opts) {
|
|
13954
|
+
const route = opts?.route ?? DEFAULT_LOOKUP_ROUTE;
|
|
13955
|
+
return routeLookup(
|
|
13956
|
+
route,
|
|
13957
|
+
() => this._lookupLex(name),
|
|
13958
|
+
() => this._stack()?.lookupDynamic(name) ?? null
|
|
13959
|
+
);
|
|
13960
|
+
}
|
|
13961
|
+
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
13962
|
+
// running, which is the leaf of this ctx's path.
|
|
13963
|
+
_lookupLex(name) {
|
|
13964
|
+
let Comp = null;
|
|
13965
|
+
this.walkPath((c) => {
|
|
13966
|
+
Comp = c;
|
|
13967
|
+
return false;
|
|
13968
|
+
});
|
|
13969
|
+
return Comp?.scope?.lookupComponent(name) ?? null;
|
|
13970
|
+
}
|
|
13971
|
+
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
13972
|
+
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
13973
|
+
// published, so it is the leg that has to be checked.
|
|
13974
|
+
lookupType(name, opts) {
|
|
13975
|
+
const v = this.lookup(name, opts);
|
|
13976
|
+
if (v == null) {
|
|
13977
|
+
this.transactor.refuse("TYPE_NOT_FOUND", {
|
|
13978
|
+
name,
|
|
13979
|
+
route: opts?.route ?? DEFAULT_LOOKUP_ROUTE
|
|
13980
|
+
});
|
|
13981
|
+
return null;
|
|
13982
|
+
}
|
|
13983
|
+
if (v?.[COMPONENT] == null) {
|
|
13984
|
+
this.transactor.refuse("TYPE_NOT_COMPONENT", { name, got: typeof v });
|
|
13985
|
+
return null;
|
|
13986
|
+
}
|
|
13987
|
+
return v;
|
|
13988
|
+
}
|
|
14061
13989
|
// A message is ADDRESSED: it names one component and stops there.
|
|
14062
|
-
send(name, args
|
|
14063
|
-
return this.sendAtPath(this.path, name, args
|
|
13990
|
+
send(name, args) {
|
|
13991
|
+
return this.sendAtPath(this.path, name, args);
|
|
14064
13992
|
}
|
|
14065
|
-
sendAtPath(path, name, args
|
|
14066
|
-
return this.transactor.pushSend(path, name, args,
|
|
13993
|
+
sendAtPath(path, name, args) {
|
|
13994
|
+
return this.transactor.pushSend(path, name, args, this.parent, this.path);
|
|
14067
13995
|
}
|
|
14068
13996
|
// An intent is ROUTED: it names a job and walks until something answers. The verb
|
|
14069
13997
|
// does not decide which scope answers — `opts.route` does, written here at the call
|
|
@@ -14074,9 +14002,6 @@ var init_transactor = __esm({
|
|
|
14074
14002
|
intentAtPath(path, name, args, opts) {
|
|
14075
14003
|
return this.transactor.pushIntent(path, name, args, opts, this.parent);
|
|
14076
14004
|
}
|
|
14077
|
-
lookupTypeFor(name, inst) {
|
|
14078
|
-
return this.transactor.comps.getCompFor(inst).scope.lookupComponent(name);
|
|
14079
|
-
}
|
|
14080
14005
|
};
|
|
14081
14006
|
EventContext = class extends Dispatcher {
|
|
14082
14007
|
get name() {
|
|
@@ -14093,6 +14018,19 @@ var init_transactor = __esm({
|
|
|
14093
14018
|
fail(error) {
|
|
14094
14019
|
return this.parent.walk === void 0 ? warnNotIntent("fail") : this.parent.walk.answer("Error", error);
|
|
14095
14020
|
}
|
|
14021
|
+
// Reply to the sender of the MESSAGE being handled. An intent answers under a name
|
|
14022
|
+
// the runtime derives (`<name>Ok`), because the raiser asked a question and declared
|
|
14023
|
+
// arms for it; a message did not, so the replier names the reply itself and the
|
|
14024
|
+
// sender handles it like any other message. Refuses when nobody sent this — a view's
|
|
14025
|
+
// own `@on.*`, or a host sendAtRoot.
|
|
14026
|
+
sendReply(name, args) {
|
|
14027
|
+
const origin = this.parent?.origin ?? null;
|
|
14028
|
+
if (origin == null) {
|
|
14029
|
+
this.transactor.refuse("NO_SENDER", { name });
|
|
14030
|
+
return null;
|
|
14031
|
+
}
|
|
14032
|
+
return this.sendAtPath(origin, name, args);
|
|
14033
|
+
}
|
|
14096
14034
|
// End the walk answering nothing — "served, and no answer".
|
|
14097
14035
|
stop() {
|
|
14098
14036
|
return this.parent.stop();
|
|
@@ -14104,15 +14042,13 @@ var init_transactor = __esm({
|
|
|
14104
14042
|
return this.parent.forward(opts);
|
|
14105
14043
|
}
|
|
14106
14044
|
};
|
|
14107
|
-
IntentContext = class extends Dispatcher {
|
|
14108
|
-
};
|
|
14109
14045
|
PathChanges = class extends PathBuilder {
|
|
14110
14046
|
constructor(dispatcher) {
|
|
14111
14047
|
super();
|
|
14112
14048
|
this.dispatcher = dispatcher;
|
|
14113
14049
|
}
|
|
14114
|
-
send(name, args
|
|
14115
|
-
return this.dispatcher.sendAtPath(this.buildPath(), name, args
|
|
14050
|
+
send(name, args) {
|
|
14051
|
+
return this.dispatcher.sendAtPath(this.buildPath(), name, args);
|
|
14116
14052
|
}
|
|
14117
14053
|
intent(name, args, opts) {
|
|
14118
14054
|
return this.dispatcher.intentAtPath(this.buildPath(), name, args, opts);
|
|
@@ -14310,9 +14246,10 @@ var init_app = __esm({
|
|
|
14310
14246
|
}
|
|
14311
14247
|
compile() {
|
|
14312
14248
|
for (const Comp of this.comps.byId.values()) {
|
|
14313
|
-
Comp
|
|
14314
|
-
|
|
14315
|
-
|
|
14249
|
+
const meta = Comp[COMPONENT];
|
|
14250
|
+
meta.compile(this.ParseContext);
|
|
14251
|
+
for (const key in meta.views)
|
|
14252
|
+
for (const name of meta.views[key].ctx.genEventNames()) this._eventNames.add(name);
|
|
14316
14253
|
}
|
|
14317
14254
|
this._compiled = true;
|
|
14318
14255
|
}
|
|
@@ -14338,8 +14275,8 @@ var init_app = __esm({
|
|
|
14338
14275
|
for (const name of this._eventNames)
|
|
14339
14276
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
14340
14277
|
}
|
|
14341
|
-
sendAtRoot(name, args
|
|
14342
|
-
this.transactor.pushSend(new Path([]), name, args
|
|
14278
|
+
sendAtRoot(name, args) {
|
|
14279
|
+
this.transactor.pushSend(new Path([]), name, args);
|
|
14343
14280
|
}
|
|
14344
14281
|
registerComponents(comps, opts) {
|
|
14345
14282
|
const scope = this.compStack.enter();
|
|
@@ -14399,7 +14336,7 @@ function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
|
14399
14336
|
const args = resolveArgs(op.args, self);
|
|
14400
14337
|
switch (op.type) {
|
|
14401
14338
|
case "send":
|
|
14402
|
-
dispatcher.sendAtPath(targetPath, op.name, args
|
|
14339
|
+
dispatcher.sendAtPath(targetPath, op.name, args);
|
|
14403
14340
|
break;
|
|
14404
14341
|
case "intent":
|
|
14405
14342
|
dispatcher.intentAtPath(targetPath, op.name, args, op.opts);
|
|
@@ -14414,6 +14351,195 @@ var init_on = __esm({
|
|
|
14414
14351
|
}
|
|
14415
14352
|
});
|
|
14416
14353
|
|
|
14354
|
+
// src/cache.js
|
|
14355
|
+
var isWeakKey, NullDomCache, WeakMapDomCache;
|
|
14356
|
+
var init_cache = __esm({
|
|
14357
|
+
"src/cache.js"() {
|
|
14358
|
+
isWeakKey = (k) => k !== null && (typeof k === "object" || typeof k === "function");
|
|
14359
|
+
NullDomCache = class {
|
|
14360
|
+
get(_keys, _cacheKey) {
|
|
14361
|
+
}
|
|
14362
|
+
set(_keys, _cacheKey, _v) {
|
|
14363
|
+
}
|
|
14364
|
+
evict() {
|
|
14365
|
+
return { hit: 0, miss: 0, badKey: 0 };
|
|
14366
|
+
}
|
|
14367
|
+
};
|
|
14368
|
+
WeakMapDomCache = class {
|
|
14369
|
+
constructor() {
|
|
14370
|
+
this.hit = this.miss = this.badKey = 0;
|
|
14371
|
+
this.keysByLen = /* @__PURE__ */ new Map();
|
|
14372
|
+
}
|
|
14373
|
+
_returnValue(r) {
|
|
14374
|
+
if (r === void 0) this.miss += 1;
|
|
14375
|
+
else this.hit += 1;
|
|
14376
|
+
return r;
|
|
14377
|
+
}
|
|
14378
|
+
get(keys, cacheKey) {
|
|
14379
|
+
const len = keys.length;
|
|
14380
|
+
let cur = this.keysByLen.get(len);
|
|
14381
|
+
if (!cur) return this._returnValue(void 0);
|
|
14382
|
+
for (let i = 0; i < len - 1; i++) {
|
|
14383
|
+
cur = cur.get(keys[i]);
|
|
14384
|
+
if (!cur) return this._returnValue(void 0);
|
|
14385
|
+
}
|
|
14386
|
+
return this._returnValue(cur.get(keys[len - 1])?.[cacheKey]);
|
|
14387
|
+
}
|
|
14388
|
+
set(keys, cacheKey, v) {
|
|
14389
|
+
const len = keys.length;
|
|
14390
|
+
let cur = this.keysByLen.get(len);
|
|
14391
|
+
if (!cur) {
|
|
14392
|
+
cur = /* @__PURE__ */ new WeakMap();
|
|
14393
|
+
this.keysByLen.set(len, cur);
|
|
14394
|
+
}
|
|
14395
|
+
for (let i = 0; i < len - 1; i++) {
|
|
14396
|
+
const key = keys[i];
|
|
14397
|
+
let next = cur.get(key);
|
|
14398
|
+
if (!next) {
|
|
14399
|
+
if (!isWeakKey(key)) {
|
|
14400
|
+
this.badKey += 1;
|
|
14401
|
+
return;
|
|
14402
|
+
}
|
|
14403
|
+
next = /* @__PURE__ */ new WeakMap();
|
|
14404
|
+
cur.set(key, next);
|
|
14405
|
+
}
|
|
14406
|
+
cur = next;
|
|
14407
|
+
}
|
|
14408
|
+
const lastKey = keys[len - 1];
|
|
14409
|
+
const leaf = cur.get(lastKey);
|
|
14410
|
+
if (leaf) leaf[cacheKey] = v;
|
|
14411
|
+
else if (isWeakKey(lastKey)) cur.set(lastKey, { [cacheKey]: v });
|
|
14412
|
+
else this.badKey += 1;
|
|
14413
|
+
}
|
|
14414
|
+
evict() {
|
|
14415
|
+
const { hit, miss, badKey } = this;
|
|
14416
|
+
this.hit = this.miss = this.badKey = 0;
|
|
14417
|
+
this.keysByLen = /* @__PURE__ */ new Map();
|
|
14418
|
+
return { hit, miss, badKey };
|
|
14419
|
+
}
|
|
14420
|
+
};
|
|
14421
|
+
}
|
|
14422
|
+
});
|
|
14423
|
+
|
|
14424
|
+
// src/renderer.js
|
|
14425
|
+
var DATASET_ATTRS, Renderer;
|
|
14426
|
+
var init_renderer = __esm({
|
|
14427
|
+
"src/renderer.js"() {
|
|
14428
|
+
init_cache();
|
|
14429
|
+
init_iteration();
|
|
14430
|
+
init_vdom();
|
|
14431
|
+
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
14432
|
+
Renderer = class {
|
|
14433
|
+
constructor(comps) {
|
|
14434
|
+
this.comps = comps;
|
|
14435
|
+
this.cache = new WeakMapDomCache();
|
|
14436
|
+
this.renderTag = h;
|
|
14437
|
+
}
|
|
14438
|
+
renderFragment(childs) {
|
|
14439
|
+
return new VFragment(childs);
|
|
14440
|
+
}
|
|
14441
|
+
renderComment(text) {
|
|
14442
|
+
return new VComment(text);
|
|
14443
|
+
}
|
|
14444
|
+
setNullCache() {
|
|
14445
|
+
this.cache = new NullDomCache();
|
|
14446
|
+
}
|
|
14447
|
+
renderToDOM(stack, val) {
|
|
14448
|
+
const rootNode = document.createElement("div");
|
|
14449
|
+
const rOpts = { document };
|
|
14450
|
+
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
14451
|
+
return rootNode.childNodes[0];
|
|
14452
|
+
}
|
|
14453
|
+
renderToString(stack, val, cleanAttrs = true) {
|
|
14454
|
+
const dom = this.renderToDOM(stack, val);
|
|
14455
|
+
if (cleanAttrs) {
|
|
14456
|
+
const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
|
|
14457
|
+
for (const { dataset } of nodes) for (const name of DATASET_ATTRS) delete dataset[name];
|
|
14458
|
+
}
|
|
14459
|
+
return dom.innerHTML;
|
|
14460
|
+
}
|
|
14461
|
+
renderRoot(stack, val, viewName = null) {
|
|
14462
|
+
const comp = this.comps.getCompFor(val);
|
|
14463
|
+
if (comp === null) return null;
|
|
14464
|
+
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
14465
|
+
}
|
|
14466
|
+
renderIt(stack, node, key, viewName) {
|
|
14467
|
+
const comp = this.comps.getCompFor(stack.it);
|
|
14468
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, key, viewName) : null;
|
|
14469
|
+
}
|
|
14470
|
+
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
14471
|
+
// `render-each`, or the view's root anode for the app root). It keys the
|
|
14472
|
+
// cache as a globally-unique object: node ids alone are unique only within a
|
|
14473
|
+
// single view, so the same value rendered by two components (e.g. through a
|
|
14474
|
+
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
14475
|
+
_rValComp(stack, val, comp, node, key, viewName) {
|
|
14476
|
+
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
14477
|
+
const cachePath = [node, val];
|
|
14478
|
+
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
14479
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
14480
|
+
if (cachedNode) return cachedNode;
|
|
14481
|
+
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
14482
|
+
const body = this.renderView(view, stack);
|
|
14483
|
+
if (body == null) return null;
|
|
14484
|
+
const meta = this._renderMetadata({
|
|
14485
|
+
$: "Comp",
|
|
14486
|
+
nid: node?.nodeId ?? null,
|
|
14487
|
+
cid: comp.id,
|
|
14488
|
+
vid: view.name
|
|
14489
|
+
});
|
|
14490
|
+
const dom = new VFragment([meta, body]);
|
|
14491
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
14492
|
+
return dom;
|
|
14493
|
+
}
|
|
14494
|
+
pushEachEntry(r, nid, attrName, key, dom) {
|
|
14495
|
+
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
14496
|
+
}
|
|
14497
|
+
renderEachWhen(stack, iterInfo, view, nid) {
|
|
14498
|
+
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
14499
|
+
const r = [];
|
|
14500
|
+
const it = stack.it;
|
|
14501
|
+
const renderOne = (key, value, attrName, binds) => {
|
|
14502
|
+
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
14503
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
14504
|
+
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
14505
|
+
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
14506
|
+
else {
|
|
14507
|
+
const dom = this.renderView(view, stack.enter(value, binds, false));
|
|
14508
|
+
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
14509
|
+
this.cache.set(cachePath, cacheKey, dom);
|
|
14510
|
+
}
|
|
14511
|
+
};
|
|
14512
|
+
walkLoopBindings(
|
|
14513
|
+
{ seq, it, filter, loopWith, enricher, ctx: makeLoopCtx(stack, filter) },
|
|
14514
|
+
renderOne
|
|
14515
|
+
);
|
|
14516
|
+
return r;
|
|
14517
|
+
}
|
|
14518
|
+
renderView(view, stack) {
|
|
14519
|
+
let n = stack.binds[1];
|
|
14520
|
+
while (n !== null) {
|
|
14521
|
+
const b = n[0];
|
|
14522
|
+
if (b.isFrame) {
|
|
14523
|
+
if (stack.it !== b.it) break;
|
|
14524
|
+
console.error("recursion detected", stack.it, b.it);
|
|
14525
|
+
return new VComment("RECURSION AVOIDED");
|
|
14526
|
+
}
|
|
14527
|
+
n = n[1];
|
|
14528
|
+
}
|
|
14529
|
+
return view.render(stack, this);
|
|
14530
|
+
}
|
|
14531
|
+
_renderMetadata(info) {
|
|
14532
|
+
return new VComment(`§${JSON.stringify(info)}§`);
|
|
14533
|
+
}
|
|
14534
|
+
// Prefix a loop-less @enrich-with subtree with a boundary meta so event-path
|
|
14535
|
+
// reconstruction replays its binds (mirrors the §Each§ / §Comp§ metas).
|
|
14536
|
+
renderScopeMeta(nid, dom) {
|
|
14537
|
+
return new VFragment([this._renderMetadata({ $: "Scope", nid }), dom]);
|
|
14538
|
+
}
|
|
14539
|
+
};
|
|
14540
|
+
}
|
|
14541
|
+
});
|
|
14542
|
+
|
|
14417
14543
|
// src/util/render.js
|
|
14418
14544
|
function reindexComponents(comps) {
|
|
14419
14545
|
for (let i = 0; i < comps.length; i++) {
|