tutuca 0.9.106 → 0.9.108
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 +355 -140
- package/dist/tutuca-components.js +134 -8
- package/dist/tutuca-dev.ext.js +336 -135
- package/dist/tutuca-dev.js +336 -135
- package/dist/tutuca-dev.min.js +3 -3
- package/dist/tutuca-extra.ext.js +217 -120
- package/dist/tutuca-extra.js +217 -120
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca-storybook.js +47 -6
- package/dist/tutuca.ext.js +217 -120
- package/dist/tutuca.js +217 -120
- package/dist/tutuca.min.js +2 -2
- package/package.json +1 -1
- package/skill/tutuca/core.md +10 -8
- package/skill/tutuca/iteration.md +3 -3
- package/skill/tutuca/patterns/filter-a-list.md +1 -1
- package/skill/tutuca/patterns/show-or-hide-content.md +1 -1
- package/skill/tutuca/request-response.md +3 -5
- package/skill/tutuca/semantics.md +1 -1
- package/skill/tutuca-source/tutuca.ext.js +217 -120
package/dist/tutuca-cli.js
CHANGED
|
@@ -4248,6 +4248,9 @@ class Step {
|
|
|
4248
4248
|
pinKey(_v) {
|
|
4249
4249
|
return this;
|
|
4250
4250
|
}
|
|
4251
|
+
toKey() {
|
|
4252
|
+
return null;
|
|
4253
|
+
}
|
|
4251
4254
|
}
|
|
4252
4255
|
function warnRawDynStep(op, step) {
|
|
4253
4256
|
console.warn(`Path.${op} reached a DynStep: call toTransactionPath() first`, step);
|
|
@@ -4332,6 +4335,15 @@ class Path {
|
|
|
4332
4335
|
}
|
|
4333
4336
|
return out;
|
|
4334
4337
|
}
|
|
4338
|
+
toKeys() {
|
|
4339
|
+
const out = [];
|
|
4340
|
+
for (const step of this.steps) {
|
|
4341
|
+
const k = step.toKey();
|
|
4342
|
+
if (k !== null)
|
|
4343
|
+
out.push(k);
|
|
4344
|
+
}
|
|
4345
|
+
return out;
|
|
4346
|
+
}
|
|
4335
4347
|
setValue(root, v) {
|
|
4336
4348
|
const intermediates = new Array(this.steps.length);
|
|
4337
4349
|
let curVal = root;
|
|
@@ -4412,19 +4424,12 @@ class Path {
|
|
|
4412
4424
|
eventIds.push(eid);
|
|
4413
4425
|
const metas = metaChain(node.previousSibling);
|
|
4414
4426
|
let sawComp = false;
|
|
4415
|
-
for (
|
|
4416
|
-
const m = metas[i];
|
|
4427
|
+
for (const m of metas) {
|
|
4417
4428
|
if (m.$ === "Comp") {
|
|
4418
4429
|
sawComp = true;
|
|
4419
4430
|
if (!crossComponent(m.cid, m.vid))
|
|
4420
4431
|
return NO_EVENT_INFO;
|
|
4421
|
-
|
|
4422
|
-
if (outer?.$ === "Each" && outer.nid === m.nid) {
|
|
4423
|
-
nodeIds.push({ nid: outer.nid, si: outer.si, sk: outer.sk });
|
|
4424
|
-
i += 1;
|
|
4425
|
-
} else {
|
|
4426
|
-
nodeIds.push({ nid: m.nid });
|
|
4427
|
-
}
|
|
4432
|
+
nodeIds.push({ nid: m.nid });
|
|
4428
4433
|
} else {
|
|
4429
4434
|
nodeIds.push({ nid: m.nid, si: m.si, sk: m.sk });
|
|
4430
4435
|
}
|
|
@@ -4589,6 +4594,9 @@ var init_path = __esm(() => {
|
|
|
4589
4594
|
withKey(k) {
|
|
4590
4595
|
return new SeqStep(this.field, k);
|
|
4591
4596
|
}
|
|
4597
|
+
toKey() {
|
|
4598
|
+
return { field: this.field };
|
|
4599
|
+
}
|
|
4592
4600
|
};
|
|
4593
4601
|
SeqStep = class SeqStep extends Step {
|
|
4594
4602
|
constructor(field, key) {
|
|
@@ -4607,6 +4615,9 @@ var init_path = __esm(() => {
|
|
|
4607
4615
|
enterFrame(stack, _prev, next) {
|
|
4608
4616
|
return stack.enter(next, { key: this.key }, true);
|
|
4609
4617
|
}
|
|
4618
|
+
toKey() {
|
|
4619
|
+
return { field: this.field, key: this.key };
|
|
4620
|
+
}
|
|
4610
4621
|
};
|
|
4611
4622
|
SeqAccessStep = class SeqAccessStep extends Step {
|
|
4612
4623
|
constructor(seqField, keyField) {
|
|
@@ -4628,6 +4639,9 @@ var init_path = __esm(() => {
|
|
|
4628
4639
|
const key = v?.get(this.keyField, NONE);
|
|
4629
4640
|
return key === NONE ? this : new SeqStep(this.seqField, key);
|
|
4630
4641
|
}
|
|
4642
|
+
toKey() {
|
|
4643
|
+
return { field: this.seqField };
|
|
4644
|
+
}
|
|
4631
4645
|
};
|
|
4632
4646
|
EachBindStep = class EachBindStep extends Step {
|
|
4633
4647
|
constructor(iterInfo, key) {
|
|
@@ -4722,7 +4736,7 @@ class ValParser {
|
|
|
4722
4736
|
parseToken(s, px) {
|
|
4723
4737
|
const c0 = s.charCodeAt(0);
|
|
4724
4738
|
if (c0 === 39)
|
|
4725
|
-
return s.length >= 2 && s.charCodeAt(s.length - 1) === 39 ? new ConstVal(unescapeStr(s.slice(1, -1))
|
|
4739
|
+
return s.length >= 2 && s.charCodeAt(s.length - 1) === 39 ? new ConstVal(unescapeStr(s.slice(1, -1))) : null;
|
|
4726
4740
|
if (c0 === 36 && s.charCodeAt(1) === 39)
|
|
4727
4741
|
return s.length >= 3 && s.charCodeAt(s.length - 1) === 39 ? StrTplVal.parse(s.slice(2, -1), px) : null;
|
|
4728
4742
|
if (s.indexOf("[") !== -1 || s.indexOf("]") !== -1)
|
|
@@ -4747,14 +4761,18 @@ class ValParser {
|
|
|
4747
4761
|
}
|
|
4748
4762
|
case 36:
|
|
4749
4763
|
return mkVal(s.slice(1), MethodVal);
|
|
4750
|
-
case 64:
|
|
4751
|
-
|
|
4764
|
+
case 64: {
|
|
4765
|
+
const dot = s.indexOf(".", 1);
|
|
4766
|
+
if (dot === -1)
|
|
4767
|
+
return mkVal(s.slice(1), BindVal);
|
|
4768
|
+
const name = s.slice(1, dot);
|
|
4769
|
+
const member = s.slice(dot + 1);
|
|
4770
|
+
return isValidValId(name) && isValidValId(member) ? new BindMemberVal(name, member) : null;
|
|
4771
|
+
}
|
|
4752
4772
|
case 42:
|
|
4753
4773
|
return mkVal(s.slice(1), DynVal);
|
|
4754
4774
|
case 46:
|
|
4755
4775
|
return mkVal(s.slice(1), FieldVal);
|
|
4756
|
-
case 33:
|
|
4757
|
-
return mkVal(s.slice(1), RequestVal);
|
|
4758
4776
|
}
|
|
4759
4777
|
const num = VALID_FLOAT_RE.test(s) ? parseFloat(s) : null;
|
|
4760
4778
|
if (Number.isFinite(num))
|
|
@@ -4807,7 +4825,7 @@ class ValParser {
|
|
|
4807
4825
|
return this._parseSingle(s, px, G_PROVIDE);
|
|
4808
4826
|
}
|
|
4809
4827
|
parseHandlerArg(s, px) {
|
|
4810
|
-
return this._parseSingle(s, px,
|
|
4828
|
+
return this._parseSingle(s, px, G_VALUE);
|
|
4811
4829
|
}
|
|
4812
4830
|
parseMacroAttr(s, px) {
|
|
4813
4831
|
return this._parseSingle(s, px, G_ALL);
|
|
@@ -4839,7 +4857,7 @@ class ValParser {
|
|
|
4839
4857
|
const args = new Array(tokens.length - 1);
|
|
4840
4858
|
for (let i = 1;i < tokens.length; i++) {
|
|
4841
4859
|
const val = this.parseToken(tokens[i], px);
|
|
4842
|
-
if (val !== null && kindOf(val) &
|
|
4860
|
+
if (val !== null && kindOf(val) & G_VALUE)
|
|
4843
4861
|
args[i - 1] = val;
|
|
4844
4862
|
else {
|
|
4845
4863
|
if (report)
|
|
@@ -4865,7 +4883,7 @@ class ValParser {
|
|
|
4865
4883
|
for (let i = 0;i < arity; i++) {
|
|
4866
4884
|
const tok = tokens[i + 1];
|
|
4867
4885
|
const val = this.parseToken(tok, px);
|
|
4868
|
-
if (val === null || !(kindOf(val) &
|
|
4886
|
+
if (val === null || !(kindOf(val) & G_BOOL)) {
|
|
4869
4887
|
px.onParseIssue("bad-value", { role: "predicate-arg", value: tok });
|
|
4870
4888
|
return null;
|
|
4871
4889
|
}
|
|
@@ -4880,7 +4898,7 @@ function kindOf(val) {
|
|
|
4880
4898
|
if (val instanceof ConstVal)
|
|
4881
4899
|
return val.kind;
|
|
4882
4900
|
if (val instanceof StrTplVal)
|
|
4883
|
-
return
|
|
4901
|
+
return val.kind;
|
|
4884
4902
|
if (val instanceof SeqAccessVal)
|
|
4885
4903
|
return K_SEQ;
|
|
4886
4904
|
if (val instanceof FieldVal)
|
|
@@ -4891,8 +4909,6 @@ function kindOf(val) {
|
|
|
4891
4909
|
return K_BIND;
|
|
4892
4910
|
if (val instanceof DynVal)
|
|
4893
4911
|
return K_DYN;
|
|
4894
|
-
if (val instanceof RequestVal)
|
|
4895
|
-
return K_REQUEST;
|
|
4896
4912
|
if (val instanceof TypeVal)
|
|
4897
4913
|
return K_TYPE;
|
|
4898
4914
|
if (val instanceof NameVal)
|
|
@@ -4910,13 +4926,13 @@ class BaseVal {
|
|
|
4910
4926
|
return this.eval(stack);
|
|
4911
4927
|
}
|
|
4912
4928
|
}
|
|
4913
|
-
var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal = (name, Cls) => isValidValId(name) ? new Cls(name) : null, VAL_TOKEN_RE, tokenizeValue = (s) => s.match(VAL_TOKEN_RE) ?? [], unescapeStr = (s) => s.replace(/\\(['\\])/g, "$1"), K_CONST = 1, K_STRTPL = 2, K_FIELD = 4, K_BIND = 8, K_DYN = 16, K_NAME = 32, K_TYPE = 64,
|
|
4929
|
+
var VALID_VAL_ID_RE, isValidValId = (name) => VALID_VAL_ID_RE.test(name), VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal = (name, Cls) => isValidValId(name) ? new Cls(name) : null, VAL_TOKEN_RE, tokenizeValue = (s) => s.match(VAL_TOKEN_RE) ?? [], unescapeStr = (s) => s.replace(/\\(['\\])/g, "$1"), K_CONST = 1, K_STRTPL = 2, K_FIELD = 4, K_BIND = 8, K_DYN = 16, K_NAME = 32, K_TYPE = 64, K_SEQ = 256, K_METHOD = 1024, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_ALL, predTruthy = (v) => {
|
|
4914
4930
|
const n = sizeOf(v);
|
|
4915
4931
|
return n === null ? !!v : n > 0;
|
|
4916
4932
|
}, PREDICATES, ConstVal, PredicateVal, VarVal, StrTplVal, NameVal, HandlerNameVal, mk404Handler = (type, name) => function(...args) {
|
|
4917
4933
|
console.warn("handler not found", { type, name, args }, this);
|
|
4918
4934
|
return this;
|
|
4919
|
-
}, TypeVal,
|
|
4935
|
+
}, TypeVal, RenderVal, RenderNameVal, BindVal, BindMemberVal, DynVal, FieldVal, MethodVal, SeqAccessVal, vp;
|
|
4920
4936
|
var init_value = __esm(() => {
|
|
4921
4937
|
init_immutable();
|
|
4922
4938
|
init_path();
|
|
@@ -4929,10 +4945,8 @@ var init_value = __esm(() => {
|
|
|
4929
4945
|
G_COMPONENT = K_FIELD | K_SEQ | K_DYN;
|
|
4930
4946
|
G_SEQUENCE = K_FIELD | K_DYN;
|
|
4931
4947
|
G_PROVIDE = K_FIELD | K_SEQ;
|
|
4932
|
-
G_FIELD = K_FIELD | K_METHOD | K_CONST |
|
|
4933
|
-
G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE |
|
|
4934
|
-
G_PRED_ARG = G_BOOL | K_STR;
|
|
4935
|
-
G_HANDLER_ARG = G_VALUE | K_STR;
|
|
4948
|
+
G_FIELD = K_FIELD | K_METHOD | K_CONST | K_SEQ;
|
|
4949
|
+
G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_CONST;
|
|
4936
4950
|
G_ALL = G_VALUE | K_STRTPL | K_SEQ;
|
|
4937
4951
|
PREDICATES = {
|
|
4938
4952
|
"empty?": { name: "empty?", arity: 1, fn: (v) => v == null || sizeOf(v) === 0 },
|
|
@@ -4981,6 +4995,13 @@ var init_value = __esm(() => {
|
|
|
4981
4995
|
constructor(vals) {
|
|
4982
4996
|
super();
|
|
4983
4997
|
this.vals = vals;
|
|
4998
|
+
this.kind = this.isLiteral() ? K_CONST : K_STRTPL;
|
|
4999
|
+
}
|
|
5000
|
+
isLiteral() {
|
|
5001
|
+
for (const v of this.vals)
|
|
5002
|
+
if (!(v instanceof ConstVal) || v.fromMacroVar)
|
|
5003
|
+
return false;
|
|
5004
|
+
return true;
|
|
4984
5005
|
}
|
|
4985
5006
|
render(stack, _rx) {
|
|
4986
5007
|
return this.eval(stack);
|
|
@@ -4992,12 +5013,11 @@ var init_value = __esm(() => {
|
|
|
4992
5013
|
return strs.join("");
|
|
4993
5014
|
}
|
|
4994
5015
|
toLiteralSource() {
|
|
5016
|
+
if (!this.isLiteral())
|
|
5017
|
+
return null;
|
|
4995
5018
|
let out = "";
|
|
4996
|
-
for (const v of this.vals)
|
|
4997
|
-
if (!(v instanceof ConstVal) || v.fromMacroVar)
|
|
4998
|
-
return null;
|
|
5019
|
+
for (const v of this.vals)
|
|
4999
5020
|
out += v.val;
|
|
5000
|
-
}
|
|
5001
5021
|
return new ConstVal(out).toString();
|
|
5002
5022
|
}
|
|
5003
5023
|
static parse(s, px) {
|
|
@@ -5044,14 +5064,6 @@ var init_value = __esm(() => {
|
|
|
5044
5064
|
return stack.lookupType(this.name);
|
|
5045
5065
|
}
|
|
5046
5066
|
};
|
|
5047
|
-
RequestVal = class RequestVal extends NameVal {
|
|
5048
|
-
eval(stack) {
|
|
5049
|
-
return stack.lookupRequest(this.name);
|
|
5050
|
-
}
|
|
5051
|
-
toString() {
|
|
5052
|
-
return `!${this.name}`;
|
|
5053
|
-
}
|
|
5054
|
-
};
|
|
5055
5067
|
RenderVal = class RenderVal extends BaseVal {
|
|
5056
5068
|
render(stack, _rx) {
|
|
5057
5069
|
return this.eval(stack);
|
|
@@ -5071,6 +5083,19 @@ var init_value = __esm(() => {
|
|
|
5071
5083
|
return `@${this.name}`;
|
|
5072
5084
|
}
|
|
5073
5085
|
};
|
|
5086
|
+
BindMemberVal = class BindMemberVal extends BindVal {
|
|
5087
|
+
constructor(name, member) {
|
|
5088
|
+
super(name);
|
|
5089
|
+
this.member = member;
|
|
5090
|
+
}
|
|
5091
|
+
eval(stack) {
|
|
5092
|
+
const v = stack.lookupBind(this.name);
|
|
5093
|
+
return typeof v?.get === "function" ? v.get(this.member, null) : v?.[this.member] ?? null;
|
|
5094
|
+
}
|
|
5095
|
+
toString() {
|
|
5096
|
+
return `@${this.name}.${this.member}`;
|
|
5097
|
+
}
|
|
5098
|
+
};
|
|
5074
5099
|
DynVal = class DynVal extends RenderNameVal {
|
|
5075
5100
|
eval(stack) {
|
|
5076
5101
|
return stack.lookupDynamic(this.name);
|
|
@@ -5213,9 +5238,6 @@ class AttrParser {
|
|
|
5213
5238
|
this.attrs.push(new RawHtmlAttr(this._parseDirectiveValue(directiveName, s, vp.parseText)));
|
|
5214
5239
|
this.hasDynamic = true;
|
|
5215
5240
|
return;
|
|
5216
|
-
case "slot":
|
|
5217
|
-
this.pushWrapper("slot", s, vp.const(s));
|
|
5218
|
-
return;
|
|
5219
5241
|
case "push-view":
|
|
5220
5242
|
this.pushWrapper("push-view", s, this._parseDirectiveValue(directiveName, s, vp.parseText));
|
|
5221
5243
|
return;
|
|
@@ -5325,11 +5347,6 @@ class RequestHandler {
|
|
|
5325
5347
|
this.name = name;
|
|
5326
5348
|
this.fn = fn;
|
|
5327
5349
|
}
|
|
5328
|
-
toHandlerArg(disp) {
|
|
5329
|
-
const f = (...args) => disp.request(this.name, args);
|
|
5330
|
-
f.withOpts = (...args) => disp.request(this.name, args.slice(0, -1), args.at(-1));
|
|
5331
|
-
return f;
|
|
5332
|
-
}
|
|
5333
5350
|
}
|
|
5334
5351
|
var booleanAttrsRaw = "itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected", booleanAttrs, ConstAttrs, DynAttrs, Attr, ConstAttr, RawHtmlAttr, NOT_SET_VAL, IfAttr, _attrParser = null;
|
|
5335
5352
|
var init_attribute = __esm(() => {
|
|
@@ -5921,24 +5938,6 @@ class Renderer {
|
|
|
5921
5938
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
5922
5939
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
5923
5940
|
}
|
|
5924
|
-
renderEach(stack, iterInfo, node, viewName) {
|
|
5925
|
-
const { seq, filter, loopWith } = iterInfo.eval(stack);
|
|
5926
|
-
const r = [];
|
|
5927
|
-
const { iterData, start, end, keys } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
5928
|
-
const renderOne = (key, value, attrName) => {
|
|
5929
|
-
const dom = this.renderIt(stack.enter(value, { key }, true), node, key, viewName);
|
|
5930
|
-
if (dom != null)
|
|
5931
|
-
this.pushEachEntry(r, node.nodeId, attrName, key, dom);
|
|
5932
|
-
};
|
|
5933
|
-
if (keys)
|
|
5934
|
-
imKeysIter(seq, renderOne, keys);
|
|
5935
|
-
else
|
|
5936
|
-
getSeqInfo(seq)(seq, (key, value, attrName) => {
|
|
5937
|
-
if (filter.call(stack.it, key, value, iterData))
|
|
5938
|
-
renderOne(key, value, attrName);
|
|
5939
|
-
}, start, end);
|
|
5940
|
-
return r;
|
|
5941
|
-
}
|
|
5942
5941
|
renderEachWhen(stack, iterInfo, view, nid) {
|
|
5943
5942
|
const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
|
|
5944
5943
|
const r = [];
|
|
@@ -5949,7 +5948,7 @@ class Renderer {
|
|
|
5949
5948
|
const binds = { key, value };
|
|
5950
5949
|
const cacheKey = `${stack.viewsId ?? ""}\x1F${nid}\x1F${key}`;
|
|
5951
5950
|
if (enricher)
|
|
5952
|
-
enricher
|
|
5951
|
+
callEnricher(enricher, it, binds, key, value, iterData);
|
|
5953
5952
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
5954
5953
|
if (cachedNode)
|
|
5955
5954
|
this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
@@ -5996,6 +5995,11 @@ var DATASET_ATTRS, getSeqInfo = (seq) => isIndexed(seq) ? imIndexedIter : isKeye
|
|
|
5996
5995
|
s = s < 0 ? 0 : s > size ? size : s;
|
|
5997
5996
|
e = e < 0 ? 0 : e > size ? size : e;
|
|
5998
5997
|
return [s, e < s ? s : e];
|
|
5998
|
+
}, callEnricher = (enricher, it, binds, key, value, iterData) => {
|
|
5999
|
+
enricher.call(it, binds, key, value, iterData);
|
|
6000
|
+
console.assert(binds.key === key && binds.value === value, "@enrich-with handlers must not overwrite binds.key or binds.value");
|
|
6001
|
+
binds.key = key;
|
|
6002
|
+
binds.value = value;
|
|
5999
6003
|
}, filterAlwaysTrue = (_v, _k, _seq) => true, nullLoopWith = (seq) => ({ iterData: { seq } }), unpackLoopResult = (result, seq) => {
|
|
6000
6004
|
const r = result ?? {};
|
|
6001
6005
|
return { iterData: r.iterData ?? { seq }, start: r.start, end: r.end, keys: r.keys };
|
|
@@ -6064,6 +6068,9 @@ class BaseNode {
|
|
|
6064
6068
|
isConstant() {
|
|
6065
6069
|
return false;
|
|
6066
6070
|
}
|
|
6071
|
+
isWhiteSpace() {
|
|
6072
|
+
return false;
|
|
6073
|
+
}
|
|
6067
6074
|
optimize() {}
|
|
6068
6075
|
}
|
|
6069
6076
|
function optimizeChilds(childs) {
|
|
@@ -6085,6 +6092,8 @@ function parseXOp(attrs, childs, opIdx, px) {
|
|
|
6085
6092
|
if (attrs.length <= opIdx)
|
|
6086
6093
|
return maybeFragment(childs);
|
|
6087
6094
|
const { name, value } = attrs[opIdx];
|
|
6095
|
+
if (X_OPS[name]?.ignoresChildren && hasMeaningfulChilds(childs))
|
|
6096
|
+
px.onParseIssue("x-op-ignores-children", { op: name });
|
|
6088
6097
|
const asAttr = attrs.getNamedItem("as")?.value ?? null;
|
|
6089
6098
|
const as = asAttr === null ? null : parseViewName(asAttr, px);
|
|
6090
6099
|
let node;
|
|
@@ -6102,7 +6111,7 @@ function parseXOp(attrs, childs, opIdx, px) {
|
|
|
6102
6111
|
node = px.addNodeIf(RenderItNode, vp.bindValIt, as);
|
|
6103
6112
|
break;
|
|
6104
6113
|
case "render-each":
|
|
6105
|
-
node =
|
|
6114
|
+
node = parseRenderEach(px, value, as, attrs);
|
|
6106
6115
|
break;
|
|
6107
6116
|
case "show": {
|
|
6108
6117
|
const val = parseXOpVal(name, value, px, vp.parseBool);
|
|
@@ -6137,8 +6146,12 @@ function processXExtras(node, attrs, opName, startIdx, px) {
|
|
|
6137
6146
|
const aName = a.name;
|
|
6138
6147
|
if (consumed.has(aName))
|
|
6139
6148
|
continue;
|
|
6140
|
-
const
|
|
6149
|
+
const atPrefixed = aName.charCodeAt(0) === 64;
|
|
6150
|
+
const baseName = atPrefixed ? aName.slice(1) : aName;
|
|
6151
|
+
const wrapper = wrappable ? X_OPS[baseName]?.wrapper : null;
|
|
6141
6152
|
if (wrapper) {
|
|
6153
|
+
if (!atPrefixed)
|
|
6154
|
+
maybeDeprecateBareXDirective(px, opName, baseName);
|
|
6142
6155
|
wrappers.push([wrapper, vp.parseBool(a.value, px)]);
|
|
6143
6156
|
continue;
|
|
6144
6157
|
}
|
|
@@ -6153,6 +6166,9 @@ function processXExtras(node, attrs, opName, startIdx, px) {
|
|
|
6153
6166
|
}
|
|
6154
6167
|
return node;
|
|
6155
6168
|
}
|
|
6169
|
+
function maybeDeprecateBareXDirective(px, opName, name) {
|
|
6170
|
+
px.onDeprecatedSyntax("bare-x-directive", { op: opName, name });
|
|
6171
|
+
}
|
|
6156
6172
|
function wrap(node, px, wrappers) {
|
|
6157
6173
|
if (wrappers) {
|
|
6158
6174
|
for (let i = wrappers.length - 1;i >= 0; i--) {
|
|
@@ -6181,6 +6197,29 @@ function dynRenderStep(comp, name, key) {
|
|
|
6181
6197
|
return null;
|
|
6182
6198
|
return key === undefined ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
6183
6199
|
}
|
|
6200
|
+
function parseRenderEach(px, value, as, attrs) {
|
|
6201
|
+
const seqVal = parseXOpVal("render-each", value, px, vp.parseSequence);
|
|
6202
|
+
if (seqVal === null)
|
|
6203
|
+
return null;
|
|
6204
|
+
const renderIt = px.addNodeIf(RenderItNode, vp.bindValIt, as);
|
|
6205
|
+
const attrParser = getAttrParser(px);
|
|
6206
|
+
const eachAttr = attrParser.eachAttr = attrParser.pushWrapper("each", value, seqVal);
|
|
6207
|
+
const when = attrs.getNamedItem("@when") ?? attrs.getNamedItem("when");
|
|
6208
|
+
if (when) {
|
|
6209
|
+
if (when.name.charCodeAt(0) !== 64)
|
|
6210
|
+
maybeDeprecateBareXDirective(px, "render-each", "when");
|
|
6211
|
+
attrParser._parseWhen(when.value);
|
|
6212
|
+
}
|
|
6213
|
+
const lWith = attrs.getNamedItem("loop-with");
|
|
6214
|
+
if (lWith)
|
|
6215
|
+
attrParser._parseLoopWith(lWith.value);
|
|
6216
|
+
const each = px.addNodeIf(EachNode, seqVal);
|
|
6217
|
+
each.iterInfo.whenVal = eachAttr.whenVal ?? null;
|
|
6218
|
+
each.iterInfo.loopWithVal = eachAttr.loopWithVal ?? null;
|
|
6219
|
+
each.fromRenderEach = true;
|
|
6220
|
+
each.wrapNode(renderIt);
|
|
6221
|
+
return each;
|
|
6222
|
+
}
|
|
6184
6223
|
|
|
6185
6224
|
class IterInfo {
|
|
6186
6225
|
constructor(val, whenVal, loopWithVal, enrichWithVal) {
|
|
@@ -6202,13 +6241,13 @@ class IterInfo {
|
|
|
6202
6241
|
const binds = { key, value };
|
|
6203
6242
|
if (enricher) {
|
|
6204
6243
|
const { iterData } = unpackLoopResult(loopWith.call(stack.it, seq, makeLoopCtx(stack, filter)), seq);
|
|
6205
|
-
enricher
|
|
6244
|
+
callEnricher(enricher, stack.it, binds, key, value, iterData);
|
|
6206
6245
|
}
|
|
6207
6246
|
return binds;
|
|
6208
6247
|
}
|
|
6209
6248
|
}
|
|
6210
|
-
function xOp(consumed = [], { wrappable = false, wrapper = null } = {}) {
|
|
6211
|
-
return { consumed: new Set(consumed), wrappable, wrapper };
|
|
6249
|
+
function xOp(consumed = [], { wrappable = false, wrapper = null, ignoresChildren = false } = {}) {
|
|
6250
|
+
return { consumed: new Set(consumed), wrappable, wrapper, ignoresChildren };
|
|
6212
6251
|
}
|
|
6213
6252
|
|
|
6214
6253
|
class ParseContext {
|
|
@@ -6256,9 +6295,9 @@ class ParseContext {
|
|
|
6256
6295
|
const anySlot = [];
|
|
6257
6296
|
const slots = { _: new FragmentNode(anySlot) };
|
|
6258
6297
|
for (const child of childs)
|
|
6259
|
-
if (child
|
|
6298
|
+
if (child.isSlotNode)
|
|
6260
6299
|
slots[child.val.val] = child.node;
|
|
6261
|
-
else if (!
|
|
6300
|
+
else if (!child.isWhiteSpace())
|
|
6262
6301
|
anySlot.push(child);
|
|
6263
6302
|
const node = new MacroNode(macroName, mAttrs, slots, this);
|
|
6264
6303
|
this.macroNodes.push(node);
|
|
@@ -6282,6 +6321,7 @@ class ParseContext {
|
|
|
6282
6321
|
onParseIssue(kind, info) {
|
|
6283
6322
|
console.warn(`tutuca parse issue [${kind}]`, info);
|
|
6284
6323
|
}
|
|
6324
|
+
onDeprecatedSyntax(_kind, _info) {}
|
|
6285
6325
|
}
|
|
6286
6326
|
function trimEdgeWhite(node) {
|
|
6287
6327
|
if (!node.isWhiteSpace?.())
|
|
@@ -6361,10 +6401,10 @@ function compileModifiers(eventName, names) {
|
|
|
6361
6401
|
return w(this, f, args, ctx);
|
|
6362
6402
|
};
|
|
6363
6403
|
}
|
|
6364
|
-
var TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs), VALID_NODE_RE, ANode, MacroNode, RenderViewId, RenderNode, RenderItNode,
|
|
6404
|
+
var TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment = (xs) => xs.length === 1 ? xs[0] : new FragmentNode(xs), VALID_NODE_RE, ANode, MacroNode, RenderViewId, RenderNode, RenderItNode, RenderTextNode, RenderOnceNode, WrapperNode, ShowNode, HideNode, PushViewNameNode, SlotNode, ScopeNode, EachNode, X_OPS, WRAPPER_NODES, _htmlBlockTags = "ADDRESS,ARTICLE,ASIDE,BLOCKQUOTE,CAPTION,COL,COLGROUP,DETAILS,DIALOG,DIV,DD,DL,DT,FIELDSET,FIGCAPTION,FIGURE,FOOTER,FORM,H1,H2,H3,H4,H5,H6,HEADER,HGROUP,HR,LEGEND,LI,MAIN,MENU,NAV,OL,P,PRE,SECTION,SUMMARY,TABLE,TBODY,TD,TFOOT,TH,THEAD,TR,UL", HTML_BLOCK_TAGS, isBlockDomNode = (n) => {
|
|
6365
6405
|
const node = n instanceof FragmentNode ? n.childs[0] : n;
|
|
6366
6406
|
return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
|
|
6367
|
-
}, isEmptyText = (c) => c instanceof TextNode && c.val === "", fwdIfCtxPred = (pred) => (w) => (that, f, args, ctx) => pred(ctx) ? w(that, f, args, ctx) : that, fwdIfKey = (keyName) => fwdIfCtxPred((ctx) => ctx.e.key === keyName), fwdCtrl, fwdMeta, fwdAlt, metaWraps, MOD_WRAPPERS_BY_EVENT, identityModifierWrapper = (f, _ctx) => f;
|
|
6407
|
+
}, isEmptyText = (c) => c instanceof TextNode && c.val === "", isIgnorableXChild = (c) => c instanceof CommentNode || (c.isWhiteSpace?.() ?? false), hasMeaningfulChilds = (childs) => childs.some((c) => !isIgnorableXChild(c)), fwdIfCtxPred = (pred) => (w) => (that, f, args, ctx) => pred(ctx) ? w(that, f, args, ctx) : that, fwdIfKey = (keyName) => fwdIfCtxPred((ctx) => ctx.e.key === keyName), fwdCtrl, fwdMeta, fwdAlt, metaWraps, MOD_WRAPPERS_BY_EVENT, identityModifierWrapper = (f, _ctx) => f;
|
|
6368
6408
|
var init_anode = __esm(() => {
|
|
6369
6409
|
init_attribute();
|
|
6370
6410
|
init_path();
|
|
@@ -6596,36 +6636,6 @@ var init_anode = __esm(() => {
|
|
|
6596
6636
|
return null;
|
|
6597
6637
|
}
|
|
6598
6638
|
};
|
|
6599
|
-
RenderEachNode = class RenderEachNode extends RenderViewId {
|
|
6600
|
-
constructor(nodeId, val, viewVal) {
|
|
6601
|
-
super(nodeId, val, viewVal);
|
|
6602
|
-
this.iterInfo = new IterInfo(val, null, null, null);
|
|
6603
|
-
}
|
|
6604
|
-
render(stack, rx) {
|
|
6605
|
-
return rx.renderEach(stack, this.iterInfo, this, this.evalViewName(stack));
|
|
6606
|
-
}
|
|
6607
|
-
toPathStep(ctx) {
|
|
6608
|
-
if (this.val instanceof DynVal)
|
|
6609
|
-
return ctx.hasKey ? dynRenderStep(ctx.comp, this.val.name, ctx.key) : null;
|
|
6610
|
-
return super.toPathStep(ctx);
|
|
6611
|
-
}
|
|
6612
|
-
static parse(px, vp2, s, as, attrs) {
|
|
6613
|
-
const node = px.addNodeIf(RenderEachNode, parseXOpVal("render-each", s, px, vp2.parseSequence), as);
|
|
6614
|
-
if (node !== null) {
|
|
6615
|
-
const attrParser = getAttrParser(px);
|
|
6616
|
-
attrParser.eachAttr = attrParser.pushWrapper("each", s, node.val);
|
|
6617
|
-
const when = attrs.getNamedItem("when");
|
|
6618
|
-
if (when)
|
|
6619
|
-
attrParser._parseWhen(when.value);
|
|
6620
|
-
const lWith = attrs.getNamedItem("loop-with");
|
|
6621
|
-
if (lWith)
|
|
6622
|
-
attrParser._parseLoopWith(lWith.value);
|
|
6623
|
-
node.iterInfo.whenVal = attrParser.eachAttr.whenVal ?? null;
|
|
6624
|
-
node.iterInfo.loopWithVal = attrParser.eachAttr.loopWithVal ?? null;
|
|
6625
|
-
}
|
|
6626
|
-
return node;
|
|
6627
|
-
}
|
|
6628
|
-
};
|
|
6629
6639
|
RenderTextNode = class RenderTextNode extends ANode {
|
|
6630
6640
|
render(stack, _rx) {
|
|
6631
6641
|
return this.val.eval(stack);
|
|
@@ -6678,6 +6688,7 @@ var init_anode = __esm(() => {
|
|
|
6678
6688
|
}
|
|
6679
6689
|
};
|
|
6680
6690
|
SlotNode = class SlotNode extends WrapperNode {
|
|
6691
|
+
isSlotNode = true;
|
|
6681
6692
|
optimize() {
|
|
6682
6693
|
this.node.optimize();
|
|
6683
6694
|
}
|
|
@@ -6712,15 +6723,17 @@ var init_anode = __esm(() => {
|
|
|
6712
6723
|
};
|
|
6713
6724
|
X_OPS = {
|
|
6714
6725
|
slot: xOp(),
|
|
6715
|
-
text: xOp([], { wrappable: true }),
|
|
6716
|
-
render: xOp(["as"], { wrappable: true }),
|
|
6717
|
-
"render-it": xOp(["as"], { wrappable: true }),
|
|
6718
|
-
"render-each": xOp(["as", "when", "loop-with"], {
|
|
6726
|
+
text: xOp([], { wrappable: true, ignoresChildren: true }),
|
|
6727
|
+
render: xOp(["as"], { wrappable: true, ignoresChildren: true }),
|
|
6728
|
+
"render-it": xOp(["as"], { wrappable: true, ignoresChildren: true }),
|
|
6729
|
+
"render-each": xOp(["as", "when", "loop-with", "@when"], {
|
|
6730
|
+
wrappable: true,
|
|
6731
|
+
ignoresChildren: true
|
|
6732
|
+
}),
|
|
6719
6733
|
show: xOp([], { wrapper: ShowNode }),
|
|
6720
6734
|
hide: xOp([], { wrapper: HideNode })
|
|
6721
6735
|
};
|
|
6722
6736
|
WRAPPER_NODES = {
|
|
6723
|
-
slot: SlotNode,
|
|
6724
6737
|
show: ShowNode,
|
|
6725
6738
|
hide: HideNode,
|
|
6726
6739
|
each: EachNode,
|
|
@@ -8990,14 +9003,17 @@ function closestName(name, candidates, maxDistance = 2) {
|
|
|
8990
9003
|
|
|
8991
9004
|
// tools/core/lint-check.js
|
|
8992
9005
|
function protoHasMethod(proto, name) {
|
|
9006
|
+
return protoMethodValue(proto, name) !== null;
|
|
9007
|
+
}
|
|
9008
|
+
function protoMethodValue(proto, name) {
|
|
8993
9009
|
let cursor = proto;
|
|
8994
9010
|
while (cursor && cursor !== Object.prototype) {
|
|
8995
9011
|
const desc = Object.getOwnPropertyDescriptor(cursor, name);
|
|
8996
9012
|
if (desc !== undefined)
|
|
8997
|
-
return typeof desc.value === "function";
|
|
9013
|
+
return typeof desc.value === "function" ? desc.value : null;
|
|
8998
9014
|
cursor = Object.getPrototypeOf(cursor);
|
|
8999
9015
|
}
|
|
9000
|
-
return
|
|
9016
|
+
return null;
|
|
9001
9017
|
}
|
|
9002
9018
|
function collectProtoMethodNames(proto) {
|
|
9003
9019
|
const out = [];
|
|
@@ -9041,6 +9057,8 @@ function classifyBadValue(value) {
|
|
|
9041
9057
|
return "logical";
|
|
9042
9058
|
if (/^[.$][A-Za-z_]\w*\s+\S/.test(s))
|
|
9043
9059
|
return "call-with-args";
|
|
9060
|
+
if (/^\.[A-Za-z_]\w*\??(\.[A-Za-z_]\w*\??)+$/.test(s))
|
|
9061
|
+
return "field-path";
|
|
9044
9062
|
return null;
|
|
9045
9063
|
}
|
|
9046
9064
|
function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SET2 } = {}) {
|
|
@@ -9069,6 +9087,7 @@ function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SE
|
|
|
9069
9087
|
function checkView(lx, view, Comp, referencedAlters, referencedDynamics) {
|
|
9070
9088
|
checkParseIssues(lx, view);
|
|
9071
9089
|
checkRenderItInLoop(lx, view);
|
|
9090
|
+
checkEnrichProjection(lx, view, Comp);
|
|
9072
9091
|
checkEventModifiers(lx, view);
|
|
9073
9092
|
checkKnownHandlerNames(lx, view, Comp, referencedAlters, referencedDynamics);
|
|
9074
9093
|
checkMacroCallArgs(lx, view, Comp);
|
|
@@ -9084,11 +9103,31 @@ function checkParseIssues(lx, view) {
|
|
|
9084
9103
|
if (!issues)
|
|
9085
9104
|
return;
|
|
9086
9105
|
for (const { kind, info } of issues) {
|
|
9106
|
+
if (kind === "deprecated:bare-x-directive") {
|
|
9107
|
+
lx.warn(DEPRECATED_BARE_X_DIRECTIVE, info, {
|
|
9108
|
+
kind: "add-prefix",
|
|
9109
|
+
from: info.name,
|
|
9110
|
+
to: `@${info.name}`
|
|
9111
|
+
});
|
|
9112
|
+
continue;
|
|
9113
|
+
}
|
|
9114
|
+
if (kind === "x-op-ignores-children") {
|
|
9115
|
+
lx.warn(X_OP_IGNORES_CHILDREN, info, { kind: "remove", what: "the ignored children" });
|
|
9116
|
+
continue;
|
|
9117
|
+
}
|
|
9087
9118
|
const rule = PARSE_ISSUES[kind];
|
|
9088
9119
|
if (!rule)
|
|
9089
9120
|
continue;
|
|
9090
9121
|
const id = rule.id;
|
|
9091
9122
|
if (kind === "bad-value") {
|
|
9123
|
+
if (typeof info.value === "string" && BINDING_MEMBER_TOO_DEEP_RE.test(info.value.trim())) {
|
|
9124
|
+
lx.error(BINDING_MEMBER_TOO_DEEP, info, {
|
|
9125
|
+
kind: "rephrase",
|
|
9126
|
+
from: info.value,
|
|
9127
|
+
text: "Read one level off the binding and compute the rest in a method or an '@enrich-with' handler."
|
|
9128
|
+
});
|
|
9129
|
+
continue;
|
|
9130
|
+
}
|
|
9092
9131
|
const detected = classifyBadValue(info.value);
|
|
9093
9132
|
if (detected) {
|
|
9094
9133
|
lx.error(UNSUPPORTED_EXPR_SYNTAX, { ...info, detected }, { kind: "rephrase", from: info.value, text: UNSUPPORTED_EXPR_GUIDANCE[detected] });
|
|
@@ -9135,6 +9174,54 @@ function checkRenderItInLoop(lx, view) {
|
|
|
9135
9174
|
return;
|
|
9136
9175
|
walkForRenderIt(lx, view.anode, 0);
|
|
9137
9176
|
}
|
|
9177
|
+
function pureProjectionBinds(fn) {
|
|
9178
|
+
const src = Function.prototype.toString.call(fn);
|
|
9179
|
+
const head = src.match(/^[^(]*\(([^)]*)\)\s*(?:=>)?\s*/);
|
|
9180
|
+
if (!head)
|
|
9181
|
+
return null;
|
|
9182
|
+
const params = head[1].split(",").map((p) => p.trim());
|
|
9183
|
+
const [bindsName, , valueName] = params;
|
|
9184
|
+
if (!/^\w+$/.test(bindsName ?? "") || !/^\w+$/.test(valueName ?? ""))
|
|
9185
|
+
return null;
|
|
9186
|
+
let body = src.slice(head[0].length).trim();
|
|
9187
|
+
if (body.startsWith("{")) {
|
|
9188
|
+
if (!body.endsWith("}"))
|
|
9189
|
+
return null;
|
|
9190
|
+
body = body.slice(1, -1);
|
|
9191
|
+
}
|
|
9192
|
+
const statements = body.split(/[;\n]/).map((s) => s.trim()).filter((s) => s !== "" && !s.startsWith("//"));
|
|
9193
|
+
if (statements.length === 0)
|
|
9194
|
+
return null;
|
|
9195
|
+
const projectionRe = new RegExp(`^${bindsName}\\.(\\w+)\\s*=\\s*${valueName}(?:\\.(\\w+)|\\.get\\((['"])(\\w+)\\3\\))$`);
|
|
9196
|
+
const members = [];
|
|
9197
|
+
for (const statement of statements) {
|
|
9198
|
+
const m = statement.match(projectionRe);
|
|
9199
|
+
if (!m)
|
|
9200
|
+
return null;
|
|
9201
|
+
members.push({ bind: m[1], member: m[2] ?? m[4] });
|
|
9202
|
+
}
|
|
9203
|
+
return members;
|
|
9204
|
+
}
|
|
9205
|
+
function checkEnrichProjection(lx, view, Comp) {
|
|
9206
|
+
for (const node of view.ctx.nodes) {
|
|
9207
|
+
if (node.constructor.name !== "EachNode")
|
|
9208
|
+
continue;
|
|
9209
|
+
const enrich = node.iterInfo?.enrichWithVal;
|
|
9210
|
+
if (!enrich?.name)
|
|
9211
|
+
continue;
|
|
9212
|
+
const fn = enrich.constructor.name === "MethodVal" ? protoMethodValue(Comp.Class?.prototype, enrich.name) : Comp.alter?.[enrich.name];
|
|
9213
|
+
if (typeof fn !== "function")
|
|
9214
|
+
continue;
|
|
9215
|
+
const members = pureProjectionBinds(fn);
|
|
9216
|
+
if (members === null)
|
|
9217
|
+
continue;
|
|
9218
|
+
const rewrites = members.map(({ bind, member }) => `'@${bind}' -> '@value.${member}'`);
|
|
9219
|
+
lx.hint(SUGGEST_BINDING_MEMBER, { name: enrich.name, members }, {
|
|
9220
|
+
kind: "rephrase",
|
|
9221
|
+
text: `Replace ${rewrites.join(", ")} in the view, then remove the '@enrich-with' and the '${enrich.name}' alter handler.`
|
|
9222
|
+
});
|
|
9223
|
+
}
|
|
9224
|
+
}
|
|
9138
9225
|
function walkForRenderIt(lx, node, loopDepth) {
|
|
9139
9226
|
if (node === null || node === undefined)
|
|
9140
9227
|
return;
|
|
@@ -9382,7 +9469,7 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedDynamics) {
|
|
|
9382
9469
|
if (node.val) {
|
|
9383
9470
|
checkConsistentAttrVal(lx, node.val, env, false, baseCtx);
|
|
9384
9471
|
}
|
|
9385
|
-
if (nodeKind === "
|
|
9472
|
+
if (nodeKind === "EachNode" && node.fromRenderEach) {
|
|
9386
9473
|
const iter = node.iterInfo;
|
|
9387
9474
|
if (iter.whenVal)
|
|
9388
9475
|
checkConsistentAttrVal(lx, iter.whenVal, env, false, {
|
|
@@ -9609,7 +9696,7 @@ class LintContext {
|
|
|
9609
9696
|
this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
|
|
9610
9697
|
}
|
|
9611
9698
|
}
|
|
9612
|
-
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE", LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE", LOOKUP_TARGET_MALFORMED = "LOOKUP_TARGET_MALFORMED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET",
|
|
9699
|
+
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE", LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE", LOOKUP_TARGET_MALFORMED = "LOOKUP_TARGET_MALFORMED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", X_OP_IGNORES_CHILDREN = "X_OP_IGNORES_CHILDREN", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX", DEPRECATED_BARE_X_DIRECTIVE = "DEPRECATED_BARE_X_DIRECTIVE", BAD_VALUE = "BAD_VALUE", UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX", BINDING_MEMBER_TOO_DEEP = "BINDING_MEMBER_TOO_DEEP", SUGGEST_BINDING_MEMBER = "SUGGEST_BINDING_MEMBER", REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING", PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING", CONSTANT_CONDITION = "CONSTANT_CONDITION", UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY", COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE", ASYNC_HANDLER = "ASYNC_HANDLER", TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE = "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE", GLOBAL_SELECTOR_IN_SCOPED_STYLE = "GLOBAL_SELECTOR_IN_SCOPED_STYLE", FIELD_NAME_RESERVED_BY_RECORD = "FIELD_NAME_RESERVED_BY_RECORD", RECORD_FIELD_NAME_COLLISIONS, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2 = "warn", LEVEL_ERROR2 = "error", LEVEL_HINT = "hint", PARSE_ISSUES, BINDING_MEMBER_TOO_DEEP_RE, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS, KNOWN_HANDLER_NAMES, fixTo = (from, to) => ({ kind: "rewrite", from, to }), BOOL_CONDITION_ORIGINS, isBoolConditionCtx = (errCtx) => errCtx != null && (BOOL_CONDITION_ORIGINS.has(errCtx.originAttr) || errCtx.branch === "@if"), ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun = (m) => m.replace(/[^\n]/g, " "), STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintParseContext;
|
|
9613
9700
|
var init_lint_check = __esm(() => {
|
|
9614
9701
|
init_anode();
|
|
9615
9702
|
init_htmllinter();
|
|
@@ -9652,11 +9739,13 @@ var init_lint_check = __esm(() => {
|
|
|
9652
9739
|
},
|
|
9653
9740
|
"bad-value": { id: BAD_VALUE }
|
|
9654
9741
|
};
|
|
9742
|
+
BINDING_MEMBER_TOO_DEEP_RE = /^@[a-zA-Z]\w*\??(\.[a-zA-Z]\w*\??){2,}$/;
|
|
9655
9743
|
UNSUPPORTED_EXPR_GUIDANCE = {
|
|
9656
9744
|
ternary: "Ternary expressions aren't supported in dynamic attributes. Define a method or computed field on the component that returns the value, then reference it as '$methodName'.",
|
|
9657
9745
|
comparison: "Comparisons aren't supported in dynamic attributes. Define a method like 'isFooSelected' that returns the boolean, then reference it as '$isFooSelected'.",
|
|
9658
9746
|
logical: "Logical operators aren't supported in dynamic attributes. Combine the conditions in a method on the component and reference it as '$methodName'.",
|
|
9659
|
-
"call-with-args": "Method calls with arguments aren't supported here. Reference a no-arg method ('$methodName') and read what you need from component state, or split into per-case methods."
|
|
9747
|
+
"call-with-args": "Method calls with arguments aren't supported here. Reference a no-arg method ('$methodName') and read what you need from component state, or split into per-case methods.",
|
|
9748
|
+
"field-path": "Fields can't be read through a dotted path. Define a method that returns the value, render a child component for the nested data, or — inside a loop — read one member off a binding ('@value.member')."
|
|
9660
9749
|
};
|
|
9661
9750
|
HTML_LINT_OPTS = {
|
|
9662
9751
|
fragmentContext: "template",
|
|
@@ -9683,7 +9772,12 @@ var init_lint_check = __esm(() => {
|
|
|
9683
9772
|
"ctx",
|
|
9684
9773
|
"dragInfo"
|
|
9685
9774
|
]);
|
|
9775
|
+
BOOL_CONDITION_ORIGINS = new Set(["@show", "@hide", "<x show>", "<x hide>"]);
|
|
9686
9776
|
ATTR_VAL_CHECKERS = {
|
|
9777
|
+
ConstVal({ lx, val, errCtx }) {
|
|
9778
|
+
if (isBoolConditionCtx(errCtx) && typeof val.val !== "boolean")
|
|
9779
|
+
lx.warn(CONSTANT_CONDITION, { ...errCtx, literal: String(val) });
|
|
9780
|
+
},
|
|
9687
9781
|
FieldVal({ lx, val, env, errCtx }) {
|
|
9688
9782
|
const { fields, proto } = env;
|
|
9689
9783
|
const { name } = val;
|
|
@@ -9711,10 +9805,6 @@ var init_lint_check = __esm(() => {
|
|
|
9711
9805
|
recurse(val.seqVal);
|
|
9712
9806
|
recurse(val.keyVal);
|
|
9713
9807
|
},
|
|
9714
|
-
RequestVal({ lx, val, env, errCtx }) {
|
|
9715
|
-
if (env.scope.lookupRequest(val.name) === null)
|
|
9716
|
-
reportUnknownName(lx, UNKNOWN_REQUEST_NAME, val.name, scopeKeysAlong(env.scope, "reqsByName"), errCtx);
|
|
9717
|
-
},
|
|
9718
9808
|
TypeVal({ lx, val, env, errCtx }) {
|
|
9719
9809
|
if (env.scope.lookupComponent(val.name) === null)
|
|
9720
9810
|
reportUnknownName(lx, UNKNOWN_COMPONENT_NAME, val.name, scopeKeysAlong(env.scope, "byName"), errCtx);
|
|
@@ -9727,7 +9817,11 @@ var init_lint_check = __esm(() => {
|
|
|
9727
9817
|
const vs = val.vals;
|
|
9728
9818
|
const literal = val.toLiteralSource();
|
|
9729
9819
|
if (literal !== null) {
|
|
9730
|
-
|
|
9820
|
+
if (isBoolConditionCtx(errCtx))
|
|
9821
|
+
lx.warn(CONSTANT_CONDITION, { ...errCtx, literal });
|
|
9822
|
+
else
|
|
9823
|
+
lx.hint(PLACEHOLDERLESS_TEMPLATE_STRING, { ...errCtx, literal }, fixTo(`$${literal}`, literal));
|
|
9824
|
+
return;
|
|
9731
9825
|
} else if (vs.length === 1) {
|
|
9732
9826
|
const simpler = String(vs[0]);
|
|
9733
9827
|
lx.warn(REDUNDANT_TEMPLATE_STRING, { ...errCtx, simpler }, fixTo(`$'{${simpler}}'`, simpler));
|
|
@@ -9754,7 +9848,6 @@ var init_lint_check = __esm(() => {
|
|
|
9754
9848
|
RenderTextNode: { originAttr: "<x text>" },
|
|
9755
9849
|
RenderNode: { originAttr: "<x render>" },
|
|
9756
9850
|
RenderItNode: { originAttr: "<x render-it>" },
|
|
9757
|
-
RenderEachNode: { originAttr: "<x render-each>" },
|
|
9758
9851
|
ShowNode: { originAttr: "<x show>" },
|
|
9759
9852
|
HideNode: { originAttr: "<x hide>" },
|
|
9760
9853
|
PushViewNameNode: { originAttr: "<x push-view>" }
|
|
@@ -9779,6 +9872,13 @@ var init_lint_check = __esm(() => {
|
|
|
9779
9872
|
const tag = this.currentTag;
|
|
9780
9873
|
this.parseIssues.push({ kind, info: tag && info.tag === undefined ? { ...info, tag } : info });
|
|
9781
9874
|
}
|
|
9875
|
+
onDeprecatedSyntax(kind, info) {
|
|
9876
|
+
const tag = this.currentTag;
|
|
9877
|
+
this.parseIssues.push({
|
|
9878
|
+
kind: `deprecated:${kind}`,
|
|
9879
|
+
info: tag && info.tag === undefined ? { ...info, tag } : info
|
|
9880
|
+
});
|
|
9881
|
+
}
|
|
9782
9882
|
};
|
|
9783
9883
|
});
|
|
9784
9884
|
|
|
@@ -9867,6 +9967,12 @@ var init_lint_rules = __esm(() => {
|
|
|
9867
9967
|
group: "Iteration helpers (`alter`)",
|
|
9868
9968
|
summary: "`alter` entry is defined but never used."
|
|
9869
9969
|
},
|
|
9970
|
+
{
|
|
9971
|
+
code: SUGGEST_BINDING_MEMBER,
|
|
9972
|
+
level: "hint",
|
|
9973
|
+
group: "Iteration helpers (`alter`)",
|
|
9974
|
+
summary: "`@enrich-with` handler only copies members of the loop value — read them directly as `@value.member` and drop the enrich."
|
|
9975
|
+
},
|
|
9870
9976
|
{
|
|
9871
9977
|
code: DYN_VAL_NOT_DEFINED,
|
|
9872
9978
|
level: "error",
|
|
@@ -9945,6 +10051,12 @@ var init_lint_rules = __esm(() => {
|
|
|
9945
10051
|
group: "Templates / events",
|
|
9946
10052
|
summary: "Extra attribute on `<x op>` not consumed by the op and not a known wrapper."
|
|
9947
10053
|
},
|
|
10054
|
+
{
|
|
10055
|
+
code: X_OP_IGNORES_CHILDREN,
|
|
10056
|
+
level: "warn",
|
|
10057
|
+
group: "Templates / events",
|
|
10058
|
+
summary: "`<x text/render/render-it/render-each>` has child content the op silently drops."
|
|
10059
|
+
},
|
|
9948
10060
|
{
|
|
9949
10061
|
code: MAYBE_DROP_AT_PREFIX,
|
|
9950
10062
|
level: "hint",
|
|
@@ -9957,6 +10069,12 @@ var init_lint_rules = __esm(() => {
|
|
|
9957
10069
|
group: "Templates / events",
|
|
9958
10070
|
summary: "A directive name (`when`/`enrich-with`/`loop-with`/`show`/`hide`) was written as a plain attribute on a host element — add the `@` prefix."
|
|
9959
10071
|
},
|
|
10072
|
+
{
|
|
10073
|
+
code: DEPRECATED_BARE_X_DIRECTIVE,
|
|
10074
|
+
level: "warn",
|
|
10075
|
+
group: "Templates / events",
|
|
10076
|
+
summary: "Bare `show`/`hide`/`when` on an `<x>` op is deprecated — use the `@`-prefixed directive (`@show`/`@hide`/`@when`)."
|
|
10077
|
+
},
|
|
9960
10078
|
{
|
|
9961
10079
|
code: BAD_VALUE,
|
|
9962
10080
|
level: "error",
|
|
@@ -9967,7 +10085,13 @@ var init_lint_rules = __esm(() => {
|
|
|
9967
10085
|
code: UNSUPPORTED_EXPR_SYNTAX,
|
|
9968
10086
|
level: "error",
|
|
9969
10087
|
group: "Value expressions",
|
|
9970
|
-
summary: "Value uses JS-style syntax (ternary, comparison, logical, call-with-args) tutuca does not support — move the logic into a method."
|
|
10088
|
+
summary: "Value uses JS-style syntax (ternary, comparison, logical, call-with-args, dotted field path) tutuca does not support — move the logic into a method."
|
|
10089
|
+
},
|
|
10090
|
+
{
|
|
10091
|
+
code: BINDING_MEMBER_TOO_DEEP,
|
|
10092
|
+
level: "error",
|
|
10093
|
+
group: "Value expressions",
|
|
10094
|
+
summary: "A binding member read goes more than one level deep (`@x.a.b`) — only one member is allowed."
|
|
9971
10095
|
},
|
|
9972
10096
|
{
|
|
9973
10097
|
code: REDUNDANT_TEMPLATE_STRING,
|
|
@@ -9982,10 +10106,10 @@ var init_lint_rules = __esm(() => {
|
|
|
9982
10106
|
summary: "`$'…'` template has no `{}` placeholder — use a plain string literal."
|
|
9983
10107
|
},
|
|
9984
10108
|
{
|
|
9985
|
-
code:
|
|
9986
|
-
level: "
|
|
9987
|
-
group: "
|
|
9988
|
-
summary: "
|
|
10109
|
+
code: CONSTANT_CONDITION,
|
|
10110
|
+
level: "warn",
|
|
10111
|
+
group: "Value expressions",
|
|
10112
|
+
summary: "A non-boolean literal in a boolean condition (`@show`, `@hide`, `@if`) never changes — reference a field or method instead."
|
|
9989
10113
|
},
|
|
9990
10114
|
{
|
|
9991
10115
|
code: UNKNOWN_COMPONENT_NAME,
|
|
@@ -10158,8 +10282,6 @@ function lintIdToMessage(id, info) {
|
|
|
10158
10282
|
}
|
|
10159
10283
|
case "IF_NO_BRANCH_SET":
|
|
10160
10284
|
return `'@if.${info.attr}' has no '@then' or '@else' branch — add '@then="…"' or '@else="…"' (or both)${fmtTagSuffix(info)}`;
|
|
10161
|
-
case "UNKNOWN_REQUEST_NAME":
|
|
10162
|
-
return `Unknown request '!${info.name}'${fmtOriginSuffix(info)}`;
|
|
10163
10285
|
case "UNKNOWN_COMPONENT_NAME":
|
|
10164
10286
|
return `Unknown component '${info.name}'${fmtOriginSuffix(info)}`;
|
|
10165
10287
|
case "ALT_HANDLER_NOT_DEFINED":
|
|
@@ -10184,20 +10306,32 @@ function lintIdToMessage(id, info) {
|
|
|
10184
10306
|
return `Unknown <x> op '${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
|
|
10185
10307
|
case "UNKNOWN_X_ATTR":
|
|
10186
10308
|
return `Unknown attribute '${info.name}=${JSON.stringify(info.value)}' on <x ${info.op}>${fmtTagSuffix(info)}`;
|
|
10309
|
+
case "X_OP_IGNORES_CHILDREN":
|
|
10310
|
+
return `<x ${info.op}> has child content, but the '${info.op}' op ignores its children — they are silently dropped when the template is parsed; remove them${fmtTagSuffix(info)}`;
|
|
10187
10311
|
case "MAYBE_DROP_AT_PREFIX": {
|
|
10188
10312
|
const written = info.value !== undefined ? `${info.name}=${JSON.stringify(info.value)}` : info.name;
|
|
10189
10313
|
return `'${written}' on <x> looks like a directive but is actually an x op/attr written with a leading '@'`;
|
|
10190
10314
|
}
|
|
10191
10315
|
case "MAYBE_ADD_AT_PREFIX":
|
|
10192
10316
|
return `'${info.name}' on <${(info.tag ?? "").toLowerCase()}> is a plain attribute, but '@${info.name}' is a directive — add the leading '@'`;
|
|
10317
|
+
case "DEPRECATED_BARE_X_DIRECTIVE":
|
|
10318
|
+
return `'${info.name}' on <x ${info.op}> is deprecated — write '@${info.name}' instead${fmtTagSuffix(info)}`;
|
|
10193
10319
|
case "BAD_VALUE":
|
|
10194
10320
|
return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
|
|
10195
10321
|
case "UNSUPPORTED_EXPR_SYNTAX":
|
|
10196
10322
|
return `${unsupportedExprMessage(info)}${fmtTagSuffix(info)}`;
|
|
10323
|
+
case "BINDING_MEMBER_TOO_DEEP":
|
|
10324
|
+
return `Binding member read ${JSON.stringify(info.value)} goes more than one level deep — only one member is allowed (like '@value.title')${fmtTagSuffix(info)}`;
|
|
10325
|
+
case "SUGGEST_BINDING_MEMBER": {
|
|
10326
|
+
const reads = (info.members ?? []).map(({ member }) => `'@value.${member}'`).join(", ");
|
|
10327
|
+
return `Enrich handler '${info.name}' only copies members of the loop value — read them directly${reads ? ` (${reads})` : ""} and remove the '@enrich-with'`;
|
|
10328
|
+
}
|
|
10197
10329
|
case "REDUNDANT_TEMPLATE_STRING":
|
|
10198
10330
|
return `Redundant template string — '{${info.simpler}}' should be just '${info.simpler}'${fmtOriginSuffix(info)}`;
|
|
10199
10331
|
case "PLACEHOLDERLESS_TEMPLATE_STRING":
|
|
10200
10332
|
return `Template string has no dynamic parts — use the string literal ${info.literal} instead${fmtOriginSuffix(info)}`;
|
|
10333
|
+
case "CONSTANT_CONDITION":
|
|
10334
|
+
return `Condition is the constant literal ${info.literal} — it never changes; reference a field ('.name') or a method ('$name') instead${fmtOriginSuffix(info)}`;
|
|
10201
10335
|
case "UNKNOWN_COMPONENT_SPEC_KEY":
|
|
10202
10336
|
return `Unknown component spec key '${info.key}' — value will be ignored at runtime`;
|
|
10203
10337
|
case "COMP_FIELD_BAD_SHAPE":
|
|
@@ -10300,7 +10434,8 @@ var init_lint = __esm(() => {
|
|
|
10300
10434
|
ternary: "ternary expression",
|
|
10301
10435
|
comparison: "comparison",
|
|
10302
10436
|
logical: "logical expression",
|
|
10303
|
-
"call-with-args": "method call with arguments"
|
|
10437
|
+
"call-with-args": "method call with arguments",
|
|
10438
|
+
"field-path": "dotted field path"
|
|
10304
10439
|
};
|
|
10305
10440
|
});
|
|
10306
10441
|
|
|
@@ -15108,9 +15243,6 @@ class Stack2 {
|
|
|
15108
15243
|
getHandlerFor(name, key) {
|
|
15109
15244
|
return this.comps.getHandlerFor(this.it, name, key);
|
|
15110
15245
|
}
|
|
15111
|
-
lookupRequest(name) {
|
|
15112
|
-
return this.comps.getRequestFor(this.it, name);
|
|
15113
|
-
}
|
|
15114
15246
|
lookupBestView(views, defaultViewName) {
|
|
15115
15247
|
let n = this.views;
|
|
15116
15248
|
while (n !== null) {
|
|
@@ -15154,12 +15286,47 @@ class Transactor {
|
|
|
15154
15286
|
this.transactions = [];
|
|
15155
15287
|
this.state = new State2(rootValue);
|
|
15156
15288
|
this.onTransactionPushed = () => {};
|
|
15289
|
+
this._observers = [];
|
|
15157
15290
|
this._inflight = new Set;
|
|
15158
15291
|
}
|
|
15159
15292
|
pushTransaction(t) {
|
|
15160
15293
|
this.transactions.push(t);
|
|
15161
15294
|
this.onTransactionPushed(t);
|
|
15162
15295
|
}
|
|
15296
|
+
observe(cb) {
|
|
15297
|
+
this._observers.push(cb);
|
|
15298
|
+
return () => {
|
|
15299
|
+
const i = this._observers.indexOf(cb);
|
|
15300
|
+
if (i !== -1)
|
|
15301
|
+
this._observers.splice(i, 1);
|
|
15302
|
+
};
|
|
15303
|
+
}
|
|
15304
|
+
_emit(record) {
|
|
15305
|
+
for (const cb of this._observers)
|
|
15306
|
+
cb(record);
|
|
15307
|
+
}
|
|
15308
|
+
_emitTransaction(transaction, root) {
|
|
15309
|
+
if (this._observers.length === 0)
|
|
15310
|
+
return;
|
|
15311
|
+
if (transaction._resolvedHandler === undefined)
|
|
15312
|
+
return;
|
|
15313
|
+
const path = transaction.getTransactionPath().pinKeys(root);
|
|
15314
|
+
this._emit({
|
|
15315
|
+
kind: transaction.observeKind,
|
|
15316
|
+
name: transaction.observeName,
|
|
15317
|
+
args: transaction.args ?? null,
|
|
15318
|
+
path,
|
|
15319
|
+
pathKeys: path.toKeys(),
|
|
15320
|
+
targetPath: transaction.targetPath ?? transaction.path,
|
|
15321
|
+
handler: transaction._resolvedHandler ?? null,
|
|
15322
|
+
handlerName: transaction._resolvedHandler?.name || null,
|
|
15323
|
+
matched: transaction._matched ?? null,
|
|
15324
|
+
before: transaction._before,
|
|
15325
|
+
after: transaction._after,
|
|
15326
|
+
parent: transaction.parentTransaction,
|
|
15327
|
+
timestamp: Date.now()
|
|
15328
|
+
});
|
|
15329
|
+
}
|
|
15163
15330
|
_link(child, parent) {
|
|
15164
15331
|
if (parent) {
|
|
15165
15332
|
const release = parent.completion.track();
|
|
@@ -15210,7 +15377,26 @@ class Transactor {
|
|
|
15210
15377
|
const curRoot = this.state.val;
|
|
15211
15378
|
const txnPath = path.toTransactionPath();
|
|
15212
15379
|
const curLeaf = txnPath.lookup(curRoot);
|
|
15213
|
-
const
|
|
15380
|
+
const found = this.comps.getRequestFor(curLeaf, name);
|
|
15381
|
+
const handler = found ?? mkReq404(name);
|
|
15382
|
+
if (this._observers.length > 0) {
|
|
15383
|
+
const reqPath = txnPath.pinKeys(curRoot);
|
|
15384
|
+
this._emit({
|
|
15385
|
+
kind: "request",
|
|
15386
|
+
name,
|
|
15387
|
+
args,
|
|
15388
|
+
path: reqPath,
|
|
15389
|
+
pathKeys: reqPath.toKeys(),
|
|
15390
|
+
targetPath: path,
|
|
15391
|
+
handler: found?.fn ?? null,
|
|
15392
|
+
handlerName: found?.fn?.name || name,
|
|
15393
|
+
matched: found ? "exact" : "none",
|
|
15394
|
+
before: curLeaf,
|
|
15395
|
+
after: undefined,
|
|
15396
|
+
parent,
|
|
15397
|
+
timestamp: Date.now()
|
|
15398
|
+
});
|
|
15399
|
+
}
|
|
15214
15400
|
const reqCtx = new RequestContext(path, this, parent, curRoot);
|
|
15215
15401
|
const resHandlerName = opts?.onResName ?? name;
|
|
15216
15402
|
const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
|
|
@@ -15245,6 +15431,7 @@ class Transactor {
|
|
|
15245
15431
|
if (newState !== undefined) {
|
|
15246
15432
|
this.state.set(newState, { transaction });
|
|
15247
15433
|
transaction.afterTransaction();
|
|
15434
|
+
this._emitTransaction(transaction, curState);
|
|
15248
15435
|
} else
|
|
15249
15436
|
console.warn("undefined new state", { curState, transaction });
|
|
15250
15437
|
} finally {
|
|
@@ -15293,8 +15480,15 @@ class Transaction {
|
|
|
15293
15480
|
buildStack(root, comps) {
|
|
15294
15481
|
return this.path.toTransactionPath().buildStack(this.buildRootStack(root, comps));
|
|
15295
15482
|
}
|
|
15483
|
+
get observeKind() {
|
|
15484
|
+
return null;
|
|
15485
|
+
}
|
|
15486
|
+
get observeName() {
|
|
15487
|
+
return null;
|
|
15488
|
+
}
|
|
15296
15489
|
callHandler(root, instance, comps) {
|
|
15297
15490
|
const [handler, args] = this.getHandlerAndArgs(root, instance, comps);
|
|
15491
|
+
this._resolvedHandler = handler;
|
|
15298
15492
|
return handler.apply(instance, args);
|
|
15299
15493
|
}
|
|
15300
15494
|
getHandlerAndArgs(_root, _instance, _comps) {
|
|
@@ -15307,6 +15501,8 @@ class Transaction {
|
|
|
15307
15501
|
const txnPath = this.getTransactionPath();
|
|
15308
15502
|
const curLeaf = txnPath.lookup(curRoot);
|
|
15309
15503
|
const newLeaf = this.callHandler(curRoot, curLeaf, comps);
|
|
15504
|
+
this._before = curLeaf;
|
|
15505
|
+
this._after = newLeaf;
|
|
15310
15506
|
this._completion?.markSelfSettled({ value: newLeaf, old: curLeaf });
|
|
15311
15507
|
return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
|
|
15312
15508
|
}
|
|
@@ -15442,6 +15638,12 @@ var init_transactor = __esm(() => {
|
|
|
15442
15638
|
this._dispatchPath ??= this.path.compact();
|
|
15443
15639
|
return this._dispatchPath;
|
|
15444
15640
|
}
|
|
15641
|
+
get observeKind() {
|
|
15642
|
+
return "input";
|
|
15643
|
+
}
|
|
15644
|
+
get observeName() {
|
|
15645
|
+
return this.e?.type ?? null;
|
|
15646
|
+
}
|
|
15445
15647
|
buildRootStack(root, comps) {
|
|
15446
15648
|
return Stack2.root(comps, root, this);
|
|
15447
15649
|
}
|
|
@@ -15449,13 +15651,6 @@ var init_transactor = __esm(() => {
|
|
|
15449
15651
|
const stack = this.buildStack(root, comps);
|
|
15450
15652
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
15451
15653
|
const path = this.dispatchPath;
|
|
15452
|
-
let dispatcher;
|
|
15453
|
-
for (let i = 0;i < args.length; i++) {
|
|
15454
|
-
if (args[i]?.toHandlerArg) {
|
|
15455
|
-
dispatcher ??= new Dispatcher(path, this.transactor, this);
|
|
15456
|
-
args[i] = args[i].toHandlerArg(dispatcher);
|
|
15457
|
-
}
|
|
15458
|
-
}
|
|
15459
15654
|
args.push(new EventContext(path, this.transactor, this));
|
|
15460
15655
|
return [handler, args];
|
|
15461
15656
|
}
|
|
@@ -15510,9 +15705,26 @@ var init_transactor = __esm(() => {
|
|
|
15510
15705
|
this.targetPath = path;
|
|
15511
15706
|
}
|
|
15512
15707
|
handlerProp = null;
|
|
15708
|
+
get observeKind() {
|
|
15709
|
+
return this.handlerProp;
|
|
15710
|
+
}
|
|
15711
|
+
get observeName() {
|
|
15712
|
+
return this.name;
|
|
15713
|
+
}
|
|
15513
15714
|
getHandlerForName(comp) {
|
|
15514
15715
|
const handlers = comp?.[this.handlerProp];
|
|
15515
|
-
|
|
15716
|
+
const exact = handlers?.[this.name];
|
|
15717
|
+
if (exact) {
|
|
15718
|
+
this._matched = "exact";
|
|
15719
|
+
return exact;
|
|
15720
|
+
}
|
|
15721
|
+
const unknown = handlers?.$unknown;
|
|
15722
|
+
if (unknown) {
|
|
15723
|
+
this._matched = "unknown";
|
|
15724
|
+
return unknown;
|
|
15725
|
+
}
|
|
15726
|
+
this._matched = "none";
|
|
15727
|
+
return nullHandler;
|
|
15516
15728
|
}
|
|
15517
15729
|
getHandlerAndArgs(_root, instance, comps) {
|
|
15518
15730
|
const handler = this.getHandlerForName(comps.getCompFor(instance));
|
|
@@ -15722,6 +15934,9 @@ class App {
|
|
|
15722
15934
|
onChange(callback) {
|
|
15723
15935
|
this.transactor.state.onChange(callback);
|
|
15724
15936
|
}
|
|
15937
|
+
observe(callback) {
|
|
15938
|
+
return this.transactor.observe(callback);
|
|
15939
|
+
}
|
|
15725
15940
|
compile() {
|
|
15726
15941
|
for (const Comp of this.comps.byId.values()) {
|
|
15727
15942
|
Comp.compile(this.ParseContext);
|