tutuca 0.13.3 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tutuca-cli.js +1079 -1254
- package/dist/tutuca-dev.ext.js +1086 -1216
- package/dist/tutuca-dev.js +1095 -1225
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +1055 -1133
- package/dist/tutuca-extra.js +1061 -1139
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.ext.js +1054 -1116
- package/dist/tutuca.js +1060 -1122
- package/dist/tutuca.min.js +3 -3
- package/package.json +1 -1
- package/skill/tutuca/SKILL.md +2 -2
- package/skill/tutuca/advanced.md +48 -17
- package/skill/tutuca/component-design.md +2 -2
- package/skill/tutuca/core.md +5 -4
- package/skill/tutuca/messages-and-intents.md +9 -11
- package/skill/tutuca/patterns/README.md +1 -1
- package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +11 -6
- package/skill/tutuca/patterns/share-state-across-the-tree.md +18 -3
- package/skill/tutuca/semantics.md +63 -39
- package/skill/tutuca-source/tutuca.ext.js +1054 -1116
package/dist/tutuca-extra.js
CHANGED
|
@@ -293,7 +293,7 @@ function processResult(result, scope) {
|
|
|
293
293
|
}
|
|
294
294
|
return result !== NOTHING ? result : void 0;
|
|
295
295
|
}
|
|
296
|
-
function finalize(rootScope, value,
|
|
296
|
+
function finalize(rootScope, value, path2) {
|
|
297
297
|
if (isFrozen(value))
|
|
298
298
|
return value;
|
|
299
299
|
const useStrictIteration = rootScope.immer_.shouldUseStrictIteration();
|
|
@@ -301,7 +301,7 @@ function finalize(rootScope, value, path) {
|
|
|
301
301
|
if (!state) {
|
|
302
302
|
each(
|
|
303
303
|
value,
|
|
304
|
-
(key, childValue) => finalizeProperty(rootScope, state, value, key, childValue,
|
|
304
|
+
(key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path2),
|
|
305
305
|
useStrictIteration
|
|
306
306
|
);
|
|
307
307
|
return value;
|
|
@@ -331,16 +331,16 @@ function finalize(rootScope, value, path) {
|
|
|
331
331
|
result,
|
|
332
332
|
key,
|
|
333
333
|
childValue,
|
|
334
|
-
|
|
334
|
+
path2,
|
|
335
335
|
isSet2
|
|
336
336
|
),
|
|
337
337
|
useStrictIteration
|
|
338
338
|
);
|
|
339
339
|
maybeFreeze(rootScope, result, false);
|
|
340
|
-
if (
|
|
340
|
+
if (path2 && rootScope.patches_) {
|
|
341
341
|
getPlugin("Patches").generatePatches_(
|
|
342
342
|
state,
|
|
343
|
-
|
|
343
|
+
path2,
|
|
344
344
|
rootScope.patches_,
|
|
345
345
|
rootScope.inversePatches_
|
|
346
346
|
);
|
|
@@ -362,9 +362,9 @@ function finalizeProperty(rootScope, parentState, targetObject, prop, childValue
|
|
|
362
362
|
if (childValue === targetObject)
|
|
363
363
|
die(5);
|
|
364
364
|
if (isDraft(childValue)) {
|
|
365
|
-
const
|
|
365
|
+
const path2 = rootPath && parentState && parentState.type_ !== 3 && // Set objects are atomic since they have no keys.
|
|
366
366
|
!has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0;
|
|
367
|
-
const res = finalize(rootScope, childValue,
|
|
367
|
+
const res = finalize(rootScope, childValue, path2);
|
|
368
368
|
set(targetObject, prop, res);
|
|
369
369
|
if (isDraft(res)) {
|
|
370
370
|
rootScope.canAutoFreeze_ = false;
|
|
@@ -754,12 +754,6 @@ var produce = immer.produce;
|
|
|
754
754
|
|
|
755
755
|
// src/path.js
|
|
756
756
|
var NONE = /* @__PURE__ */ Symbol("NONE");
|
|
757
|
-
var readKey = (value, key, dval = null) => {
|
|
758
|
-
if (value == null) return dval;
|
|
759
|
-
if (value instanceof Map) return value.has(key) ? value.get(key) : dval;
|
|
760
|
-
if (value instanceof Set) return value.has(key) ? key : dval;
|
|
761
|
-
return Object.hasOwn(value, key) ? value[key] : dval;
|
|
762
|
-
};
|
|
763
757
|
var writeKey = (value, key, next) => {
|
|
764
758
|
if (value instanceof Map) value.set(key, next);
|
|
765
759
|
else if (value instanceof Set) {
|
|
@@ -767,20 +761,15 @@ var writeKey = (value, key, next) => {
|
|
|
767
761
|
value.add(next);
|
|
768
762
|
} else value[key] = next;
|
|
769
763
|
};
|
|
770
|
-
var writeSeqKey = (value, key, next) =>
|
|
771
|
-
if (value instanceof Map || value instanceof Set || Array.isArray(value) || Object.hasOwn(value, key))
|
|
772
|
-
writeKey(value, key, next);
|
|
773
|
-
else if (typeof value?.set === "function") value.set(key, next);
|
|
774
|
-
else writeKey(value, key, next);
|
|
775
|
-
};
|
|
764
|
+
var writeSeqKey = (value, key, next) => !(value instanceof Map || value instanceof Set || Array.isArray(value)) && !Object.hasOwn(value, key) && typeof value?.set === "function" ? value.set(key, next) : writeKey(value, key, next);
|
|
776
765
|
var Step = class {
|
|
777
|
-
lookup(_v, dval = null) {
|
|
778
|
-
return dval;
|
|
779
|
-
}
|
|
780
766
|
setDraftValue(_root, _v) {
|
|
781
767
|
}
|
|
782
|
-
|
|
783
|
-
|
|
768
|
+
// Re-enter this step while rebuilding a stack. `renderPath` is the dispatch
|
|
769
|
+
// position AFTER this step: a rebuilt frame must carry the same render path
|
|
770
|
+
// the renderer had there, or the provides it publishes would be located wrong.
|
|
771
|
+
enterFrame(stack, next, renderPath) {
|
|
772
|
+
return stack.enter(next, {}, true, renderPath);
|
|
784
773
|
}
|
|
785
774
|
toAbstractPathStep() {
|
|
786
775
|
return this;
|
|
@@ -797,41 +786,29 @@ var Step = class {
|
|
|
797
786
|
return null;
|
|
798
787
|
}
|
|
799
788
|
};
|
|
800
|
-
var BindStep = class
|
|
789
|
+
var BindStep = class extends Step {
|
|
801
790
|
constructor(binds) {
|
|
802
791
|
super();
|
|
803
792
|
this.binds = binds;
|
|
804
793
|
}
|
|
805
|
-
lookup(v
|
|
794
|
+
lookup(v) {
|
|
806
795
|
return v;
|
|
807
796
|
}
|
|
808
|
-
enterFrame(stack, next) {
|
|
809
|
-
return stack.enter(next, { ...this.binds }, false);
|
|
810
|
-
}
|
|
811
|
-
withIndex(i) {
|
|
812
|
-
return new _BindStep({ ...this.binds, key: i });
|
|
813
|
-
}
|
|
814
|
-
withKey(key) {
|
|
815
|
-
return new _BindStep({ ...this.binds, key });
|
|
797
|
+
enterFrame(stack, next, renderPath) {
|
|
798
|
+
return stack.enter(next, { ...this.binds }, false, renderPath);
|
|
816
799
|
}
|
|
817
800
|
toAbstractPathStep() {
|
|
818
801
|
return null;
|
|
819
802
|
}
|
|
820
803
|
};
|
|
821
|
-
var ScopeBindStep = class
|
|
804
|
+
var ScopeBindStep = class extends BindStep {
|
|
822
805
|
constructor(val, binds = {}) {
|
|
823
806
|
super(binds);
|
|
824
807
|
this.val = val;
|
|
825
808
|
}
|
|
826
|
-
enterFrame(stack, next) {
|
|
809
|
+
enterFrame(stack, next, renderPath) {
|
|
827
810
|
const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
|
|
828
|
-
return stack.enter(next, { ...this.binds, ...dyn }, false);
|
|
829
|
-
}
|
|
830
|
-
withIndex(i) {
|
|
831
|
-
return new _ScopeBindStep(this.val, { ...this.binds, key: i });
|
|
832
|
-
}
|
|
833
|
-
withKey(key) {
|
|
834
|
-
return new _ScopeBindStep(this.val, { ...this.binds, key });
|
|
811
|
+
return stack.enter(next, { ...this.binds, ...dyn }, false, renderPath);
|
|
835
812
|
}
|
|
836
813
|
};
|
|
837
814
|
var FieldStep = class extends Step {
|
|
@@ -839,18 +816,12 @@ var FieldStep = class extends Step {
|
|
|
839
816
|
super();
|
|
840
817
|
this.field = field;
|
|
841
818
|
}
|
|
842
|
-
lookup(v
|
|
843
|
-
return
|
|
819
|
+
lookup(v) {
|
|
820
|
+
return seqGet(v, this.field, NONE);
|
|
844
821
|
}
|
|
845
822
|
setDraftValue(root, v) {
|
|
846
823
|
writeKey(root, this.field, v);
|
|
847
824
|
}
|
|
848
|
-
withIndex(i) {
|
|
849
|
-
return new SeqStep(this.field, i);
|
|
850
|
-
}
|
|
851
|
-
withKey(k) {
|
|
852
|
-
return new SeqStep(this.field, k);
|
|
853
|
-
}
|
|
854
825
|
toKey() {
|
|
855
826
|
return { field: this.field };
|
|
856
827
|
}
|
|
@@ -861,15 +832,15 @@ var SeqStep = class extends Step {
|
|
|
861
832
|
this.field = field;
|
|
862
833
|
this.key = key;
|
|
863
834
|
}
|
|
864
|
-
lookup(v
|
|
865
|
-
return seqGet(
|
|
835
|
+
lookup(v) {
|
|
836
|
+
return seqGet(seqGet(v, this.field, null), this.key, NONE);
|
|
866
837
|
}
|
|
867
838
|
setDraftValue(root, v) {
|
|
868
|
-
const seq =
|
|
839
|
+
const seq = seqGet(root, this.field, null);
|
|
869
840
|
if (seq != null) writeSeqKey(seq, this.key, v);
|
|
870
841
|
}
|
|
871
|
-
enterFrame(stack, next) {
|
|
872
|
-
return stack.enter(next, { key: this.key }, true);
|
|
842
|
+
enterFrame(stack, next, renderPath) {
|
|
843
|
+
return stack.enter(next, { key: this.key }, true, renderPath);
|
|
873
844
|
}
|
|
874
845
|
toKey() {
|
|
875
846
|
return { field: this.field, key: this.key };
|
|
@@ -881,20 +852,20 @@ var SeqAccessStep = class extends Step {
|
|
|
881
852
|
this.seqField = seqField;
|
|
882
853
|
this.keyField = keyField;
|
|
883
854
|
}
|
|
884
|
-
lookup(v
|
|
885
|
-
const seq =
|
|
886
|
-
const key =
|
|
887
|
-
return key !== NONE && seq !== NONE ? seqGet(seq, key,
|
|
855
|
+
lookup(v) {
|
|
856
|
+
const seq = seqGet(v, this.seqField, NONE);
|
|
857
|
+
const key = seqGet(v, this.keyField, NONE);
|
|
858
|
+
return key !== NONE && seq !== NONE ? seqGet(seq, key, NONE) : NONE;
|
|
888
859
|
}
|
|
889
860
|
setDraftValue(root, v) {
|
|
890
|
-
const seq =
|
|
891
|
-
const key =
|
|
861
|
+
const seq = seqGet(root, this.seqField, NONE);
|
|
862
|
+
const key = seqGet(root, this.keyField, NONE);
|
|
892
863
|
if (seq !== NONE && key !== NONE) writeSeqKey(seq, key, v);
|
|
893
864
|
}
|
|
894
865
|
// Resolve `keyField` against `v` now and freeze it as a literal-key `SeqStep`, so a
|
|
895
866
|
// later lookup/setValue lands on this same item even if `keyField` changes meanwhile.
|
|
896
867
|
pinKey(v) {
|
|
897
|
-
const key =
|
|
868
|
+
const key = seqGet(v, this.keyField, NONE);
|
|
898
869
|
return key === NONE ? this : new SeqStep(this.seqField, key);
|
|
899
870
|
}
|
|
900
871
|
// The key is a *field reference* resolved live, so it is unknown without a value;
|
|
@@ -905,70 +876,62 @@ var SeqAccessStep = class extends Step {
|
|
|
905
876
|
}
|
|
906
877
|
};
|
|
907
878
|
var EachBindStep = class extends Step {
|
|
908
|
-
constructor(
|
|
879
|
+
constructor(eachNode, key) {
|
|
909
880
|
super();
|
|
910
|
-
this.
|
|
881
|
+
this.eachNode = eachNode;
|
|
911
882
|
this.key = key;
|
|
912
883
|
}
|
|
913
|
-
lookup(v
|
|
884
|
+
lookup(v) {
|
|
914
885
|
return v;
|
|
915
886
|
}
|
|
916
887
|
// Replay the renderer's per-item binds (key, value + any @enrich-with binds)
|
|
917
888
|
// so a rebuilt stack matches the one @each rendered with.
|
|
918
|
-
enterFrame(stack, next) {
|
|
919
|
-
return stack.enter(next, this.
|
|
889
|
+
enterFrame(stack, next, renderPath) {
|
|
890
|
+
return stack.enter(next, this.eachNode.enrichBinds(stack, this.key), false, renderPath);
|
|
920
891
|
}
|
|
921
892
|
toAbstractPathStep() {
|
|
922
893
|
return null;
|
|
923
894
|
}
|
|
924
895
|
};
|
|
925
896
|
var EachRenderItStep = class extends SeqStep {
|
|
926
|
-
enterFrame(stack, next) {
|
|
927
|
-
return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
|
|
897
|
+
enterFrame(stack, next, renderPath) {
|
|
898
|
+
return stack.enter(next, { key: this.key, value: next }, false, renderPath).enter(next, {}, true, renderPath);
|
|
928
899
|
}
|
|
929
900
|
toAbstractPathStep() {
|
|
930
901
|
return new SeqStep(this.field, this.key);
|
|
931
902
|
}
|
|
932
903
|
};
|
|
933
|
-
function
|
|
934
|
-
|
|
904
|
+
function stepToJson(step) {
|
|
905
|
+
if (step instanceof SeqStep) return { f: step.field, k: step.key };
|
|
906
|
+
if (step instanceof FieldStep) return { f: step.field };
|
|
907
|
+
if (step instanceof SeqAccessStep) return { f: step.seqField, a: step.keyField };
|
|
908
|
+
return null;
|
|
935
909
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
warnRawDynStep("lookup", this);
|
|
949
|
-
return dval;
|
|
950
|
-
}
|
|
951
|
-
enterFrame(stack, _next) {
|
|
952
|
-
warnRawDynStep("enterFrame", this);
|
|
953
|
-
return stack;
|
|
954
|
-
}
|
|
955
|
-
};
|
|
956
|
-
var DynEachStep = class extends DynStep {
|
|
957
|
-
constructor(producerCompId, producerSteps, key) {
|
|
958
|
-
super(producerCompId, producerSteps);
|
|
959
|
-
this.key = key;
|
|
960
|
-
}
|
|
961
|
-
teleportSteps() {
|
|
962
|
-
const { producerSteps, key } = this;
|
|
963
|
-
if (producerSteps.length === 0) return producerSteps;
|
|
964
|
-
const last = producerSteps[producerSteps.length - 1];
|
|
965
|
-
if (!(last instanceof FieldStep)) {
|
|
966
|
-
console.warn("DynEachStep: seq-access dynamic cannot be iterated", this);
|
|
967
|
-
return producerSteps;
|
|
968
|
-
}
|
|
969
|
-
return producerSteps.slice(0, -1).concat(new SeqStep(last.field, key));
|
|
910
|
+
function stepFromJson(j) {
|
|
911
|
+
if (j == null || typeof j.f !== "string") return null;
|
|
912
|
+
if (j.k !== void 0) return new SeqStep(j.f, j.k);
|
|
913
|
+
if (j.a !== void 0) return new SeqAccessStep(j.f, j.a);
|
|
914
|
+
return new FieldStep(j.f);
|
|
915
|
+
}
|
|
916
|
+
function pathToJson(path2) {
|
|
917
|
+
const out = [];
|
|
918
|
+
for (const step of path2.steps) {
|
|
919
|
+
const j = stepToJson(step);
|
|
920
|
+
if (j === null) return null;
|
|
921
|
+
out.push(j);
|
|
970
922
|
}
|
|
971
|
-
|
|
923
|
+
return out;
|
|
924
|
+
}
|
|
925
|
+
function pathFromJson(j) {
|
|
926
|
+
if (!Array.isArray(j)) return null;
|
|
927
|
+
const steps = [];
|
|
928
|
+
for (const item of j) {
|
|
929
|
+
const step = stepFromJson(item);
|
|
930
|
+
if (step === null) return null;
|
|
931
|
+
steps.push(step);
|
|
932
|
+
}
|
|
933
|
+
return new Path(steps);
|
|
934
|
+
}
|
|
972
935
|
var Path = class _Path {
|
|
973
936
|
constructor(steps = []) {
|
|
974
937
|
this.steps = steps;
|
|
@@ -976,43 +939,13 @@ var Path = class _Path {
|
|
|
976
939
|
concat(steps) {
|
|
977
940
|
return new _Path(this.steps.concat(steps));
|
|
978
941
|
}
|
|
979
|
-
popStep
|
|
980
|
-
|
|
981
|
-
}
|
|
982
|
-
// The dispatch path: frame-only steps removed, one step per crossed component
|
|
983
|
-
// (DynStep included). `popStep` over it bubbles through every component.
|
|
942
|
+
// Frame-only steps removed, one step per crossed component: `popStep` over the
|
|
943
|
+
// result bubbles through every component.
|
|
984
944
|
compact() {
|
|
985
945
|
const out = [];
|
|
986
946
|
for (const step of this.steps) {
|
|
987
947
|
const s = step.toAbstractPathStep();
|
|
988
|
-
if (s !== null)
|
|
989
|
-
if (s !== step) s._originCid = step._originCid;
|
|
990
|
-
out.push(s);
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
return new _Path(out);
|
|
994
|
-
}
|
|
995
|
-
// The abstract path used to apply a transaction: every DynStep is teleported —
|
|
996
|
-
// the steps interior to its producer..consumer span are dropped and the
|
|
997
|
-
// producer's own path spliced in — so a mutation lands on the data's real
|
|
998
|
-
// location. A path with no DynStep is returned unchanged.
|
|
999
|
-
toTransactionPath() {
|
|
1000
|
-
let hasDyn = false;
|
|
1001
|
-
for (const step of this.steps)
|
|
1002
|
-
if (step instanceof DynStep) {
|
|
1003
|
-
hasDyn = true;
|
|
1004
|
-
break;
|
|
1005
|
-
}
|
|
1006
|
-
if (!hasDyn) return this;
|
|
1007
|
-
const out = [];
|
|
1008
|
-
for (const step of this.steps) {
|
|
1009
|
-
if (step instanceof DynStep) {
|
|
1010
|
-
while (out.length > 0 && step.interiorCids.has(out[out.length - 1]._originCid)) out.pop();
|
|
1011
|
-
for (const ts of step.teleportSteps()) {
|
|
1012
|
-
ts._originCid = step.producerCompId;
|
|
1013
|
-
out.push(ts);
|
|
1014
|
-
}
|
|
1015
|
-
} else out.push(step);
|
|
948
|
+
if (s !== null) out.push(s);
|
|
1016
949
|
}
|
|
1017
950
|
return new _Path(out);
|
|
1018
951
|
}
|
|
@@ -1020,7 +953,6 @@ var Path = class _Path {
|
|
|
1020
953
|
// key as it is *now* so a later lookup/setValue lands on the same item even if the
|
|
1021
954
|
// keyField changed meanwhile (e.g. the selected tab moved while an intent was in
|
|
1022
955
|
// flight). Returns a new Path with those steps replaced; `this` if nothing pinned.
|
|
1023
|
-
// Must be called on a transaction path (no DynSteps — call toTransactionPath first).
|
|
1024
956
|
pinKeys(root) {
|
|
1025
957
|
let curVal = root;
|
|
1026
958
|
let out = null;
|
|
@@ -1028,7 +960,7 @@ var Path = class _Path {
|
|
|
1028
960
|
const step = this.steps[i];
|
|
1029
961
|
const pinned = step.pinKey(curVal);
|
|
1030
962
|
if (pinned !== step) (out ??= this.steps.slice())[i] = pinned;
|
|
1031
|
-
curVal = step.lookup(curVal
|
|
963
|
+
curVal = step.lookup(curVal);
|
|
1032
964
|
if (curVal === NONE) break;
|
|
1033
965
|
}
|
|
1034
966
|
return out ? new _Path(out) : this;
|
|
@@ -1036,20 +968,20 @@ var Path = class _Path {
|
|
|
1036
968
|
lookup(v, dval = null) {
|
|
1037
969
|
let curVal = v;
|
|
1038
970
|
for (const step of this.steps) {
|
|
1039
|
-
curVal = step.lookup(curVal
|
|
971
|
+
curVal = step.lookup(curVal);
|
|
1040
972
|
if (curVal === NONE) return dval;
|
|
1041
973
|
}
|
|
1042
974
|
return curVal;
|
|
1043
975
|
}
|
|
1044
976
|
// The values entered along the path, root→leaf (root included): index 0 is `root`,
|
|
1045
977
|
// the last entry is the leaf this path resolves to. Stops early at the first
|
|
1046
|
-
// unresolvable step.
|
|
1047
|
-
//
|
|
978
|
+
// unresolvable step. Used to walk the component instances on a dispatch path
|
|
979
|
+
// (filter via Components.getCompFor).
|
|
1048
980
|
resolveChain(root) {
|
|
1049
981
|
const out = [root];
|
|
1050
982
|
let curVal = root;
|
|
1051
983
|
for (const step of this.steps) {
|
|
1052
|
-
curVal = step.lookup(curVal
|
|
984
|
+
curVal = step.lookup(curVal);
|
|
1053
985
|
if (curVal === NONE) break;
|
|
1054
986
|
out.push(curVal);
|
|
1055
987
|
}
|
|
@@ -1058,7 +990,7 @@ var Path = class _Path {
|
|
|
1058
990
|
// A flat `[{ field, key? }]` list of the addressing steps, skipping frame-only
|
|
1059
991
|
// steps (binds). Generic path introspection so tooling (e.g. the storybook
|
|
1060
992
|
// activity log) can identify which subtree a transaction touched without
|
|
1061
|
-
// depending on Step internals.
|
|
993
|
+
// depending on Step internals.
|
|
1062
994
|
toKeys() {
|
|
1063
995
|
const out = [];
|
|
1064
996
|
for (const step of this.steps) {
|
|
@@ -1072,69 +1004,146 @@ var Path = class _Path {
|
|
|
1072
1004
|
return produce(root, (draft) => {
|
|
1073
1005
|
let parent = draft;
|
|
1074
1006
|
for (let i = 0; i < this.steps.length - 1; i++) {
|
|
1075
|
-
parent = this.steps[i].lookup(parent
|
|
1007
|
+
parent = this.steps[i].lookup(parent);
|
|
1076
1008
|
if (parent === NONE) return;
|
|
1077
1009
|
}
|
|
1078
1010
|
this.steps.at(-1).setDraftValue(parent, v);
|
|
1079
1011
|
});
|
|
1080
1012
|
}
|
|
1013
|
+
};
|
|
1014
|
+
function walkItems(stack, items, renderPath, path2) {
|
|
1015
|
+
let prev = stack.it;
|
|
1016
|
+
for (const step of items) {
|
|
1017
|
+
const next = step.lookup(prev);
|
|
1018
|
+
if (next === NONE) {
|
|
1019
|
+
console.warn("bad PathItem", { root: stack.it, step, path: path2 });
|
|
1020
|
+
return null;
|
|
1021
|
+
}
|
|
1022
|
+
renderPath = renderPath.pushItem(step);
|
|
1023
|
+
stack = step.enterFrame(stack, next, renderPath);
|
|
1024
|
+
prev = next;
|
|
1025
|
+
}
|
|
1026
|
+
return [stack, renderPath];
|
|
1027
|
+
}
|
|
1028
|
+
var EMPTY_PATH = new Path([]);
|
|
1029
|
+
var DispatchPath = class _DispatchPath {
|
|
1030
|
+
constructor(frames = [{ base: EMPTY_PATH, items: [] }]) {
|
|
1031
|
+
this.frames = frames;
|
|
1032
|
+
}
|
|
1033
|
+
// Plain addressing steps in one frame based at the root: what a caller means
|
|
1034
|
+
// by "this position" when it has no continuation of its own.
|
|
1035
|
+
static ofSteps(steps) {
|
|
1036
|
+
return new _DispatchPath([{ base: EMPTY_PATH, items: steps.slice() }]);
|
|
1037
|
+
}
|
|
1038
|
+
get top() {
|
|
1039
|
+
return this.frames[this.frames.length - 1];
|
|
1040
|
+
}
|
|
1041
|
+
_withTopItems(items) {
|
|
1042
|
+
const frames = this.frames.slice();
|
|
1043
|
+
frames[frames.length - 1] = { base: this.top.base, items };
|
|
1044
|
+
return new _DispatchPath(frames);
|
|
1045
|
+
}
|
|
1046
|
+
concat(steps) {
|
|
1047
|
+
return this._withTopItems(this.top.items.concat(steps));
|
|
1048
|
+
}
|
|
1049
|
+
pushItem(step) {
|
|
1050
|
+
return this.concat([step]);
|
|
1051
|
+
}
|
|
1052
|
+
pushFrame(base) {
|
|
1053
|
+
return new _DispatchPath(this.frames.concat({ base, items: [] }));
|
|
1054
|
+
}
|
|
1055
|
+
// Whether bubbling has anywhere left to go: another step in this frame, or a
|
|
1056
|
+
// visual caller underneath it. (A path always has at least one frame.)
|
|
1057
|
+
canPop() {
|
|
1058
|
+
return this.frames.length > 1 || this.frames[0].items.length > 0;
|
|
1059
|
+
}
|
|
1060
|
+
// One component closer to the root. At the top of a frame that is popping back
|
|
1061
|
+
// to the visual caller, not to the producer's own parent — the caller is where
|
|
1062
|
+
// the `*name` was written, and where an unhandled message should keep going.
|
|
1063
|
+
popStep() {
|
|
1064
|
+
const { top } = this;
|
|
1065
|
+
if (top.items.length > 0) return this._withTopItems(top.items.slice(0, -1));
|
|
1066
|
+
if (this.frames.length > 1) return new _DispatchPath(this.frames.slice(0, -1));
|
|
1067
|
+
return this;
|
|
1068
|
+
}
|
|
1069
|
+
// Drop frame-only steps inside every frame independently; a frame's base is
|
|
1070
|
+
// already addressing-only.
|
|
1071
|
+
compact() {
|
|
1072
|
+
return new _DispatchPath(
|
|
1073
|
+
this.frames.map(({ base, items }) => ({ base, items: new Path(items).compact().steps }))
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
// A stable string for the ADDRESS this path denotes, for the render cache. The
|
|
1077
|
+
// same immutable value can sit at two places in the tree, and a subtree rendered
|
|
1078
|
+
// at one of them bakes that address in — the provides it publishes are located
|
|
1079
|
+
// there. Frame-only steps address nothing, so they are compacted out: two sites
|
|
1080
|
+
// that differ only in binds do render the same subtree.
|
|
1081
|
+
get addressKey() {
|
|
1082
|
+
this._addressKey ??= renderPathText(this.toTransactionPath().compact());
|
|
1083
|
+
return this._addressKey;
|
|
1084
|
+
}
|
|
1085
|
+
// The active transaction address: the top frame's absolute base followed by
|
|
1086
|
+
// its ordinary descendant steps. This is where a mutation lands.
|
|
1087
|
+
toTransactionPath() {
|
|
1088
|
+
const { base, items } = this.top;
|
|
1089
|
+
return base.concat(items);
|
|
1090
|
+
}
|
|
1091
|
+
// Rebuild the render stack this path was dispatched from. A frame with a base
|
|
1092
|
+
// re-enters at that absolute value first — replaying the resume a `*name`
|
|
1093
|
+
// render performed — and then walks its ordinary items.
|
|
1081
1094
|
buildStack(stack) {
|
|
1082
|
-
let
|
|
1083
|
-
for (
|
|
1084
|
-
const
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
1087
|
-
|
|
1095
|
+
let renderPath = new _DispatchPath();
|
|
1096
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
1097
|
+
const { base, items } = this.frames[i];
|
|
1098
|
+
if (i > 0 || base.steps.length > 0) {
|
|
1099
|
+
const baseValue = base.lookup(stack.root, NONE);
|
|
1100
|
+
if (baseValue === NONE) {
|
|
1101
|
+
console.warn("bad frame base", { base, path: this });
|
|
1102
|
+
return null;
|
|
1103
|
+
}
|
|
1104
|
+
renderPath = renderPath.pushFrame(base);
|
|
1105
|
+
stack = stack.enter(baseValue, {}, true, renderPath);
|
|
1088
1106
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1107
|
+
const walked = walkItems(stack, items, renderPath, this);
|
|
1108
|
+
if (walked === null) return null;
|
|
1109
|
+
[stack, renderPath] = walked;
|
|
1091
1110
|
}
|
|
1092
1111
|
return stack;
|
|
1093
1112
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1113
|
+
// Reconstruct the dispatch position of a DOM event from the `data-*` stamps and
|
|
1114
|
+
// `§…§` meta comments the renderer left on the way down. `stopOnNoEvent` is off for
|
|
1115
|
+
// drag events, whose path is needed even where no handler is registered.
|
|
1116
|
+
static fromNodeAndEventName(node, eventName, rootNode, comps, stopOnNoEvent = true) {
|
|
1117
|
+
const parts = [];
|
|
1097
1118
|
const bubbles = BUBBLING_EVENTS.has(eventName);
|
|
1098
|
-
let depth = 0;
|
|
1099
1119
|
let eventIds = [];
|
|
1100
1120
|
let handlers = null;
|
|
1101
|
-
let
|
|
1121
|
+
let nodeRefs = [];
|
|
1102
1122
|
let isLeafComponent = true;
|
|
1103
1123
|
const crossComponent = (cidNum, vid) => {
|
|
1104
1124
|
const comp = comps.getComponentForId(cidNum);
|
|
1105
|
-
let
|
|
1125
|
+
let pushPart = true;
|
|
1106
1126
|
if (handlers === null && (isLeafComponent || bubbles)) {
|
|
1107
1127
|
handlers = findHandlers(comp, eventIds, vid, eventName);
|
|
1108
1128
|
if (handlers === null) {
|
|
1109
1129
|
if (isLeafComponent && stopOnNoEvent && !bubbles) return false;
|
|
1110
1130
|
} else if (!isLeafComponent) {
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
pushStep = false;
|
|
1131
|
+
parts.length = 0;
|
|
1132
|
+
pushPart = false;
|
|
1114
1133
|
}
|
|
1115
1134
|
}
|
|
1116
1135
|
isLeafComponent = false;
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
if (step) {
|
|
1121
|
-
step._originCid = cidNum;
|
|
1122
|
-
pathSteps.push(step);
|
|
1123
|
-
if (step instanceof DynStep) {
|
|
1124
|
-
step.interiorCids.add(cidNum);
|
|
1125
|
-
pendingDyns.push(step);
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1136
|
+
if (pushPart) {
|
|
1137
|
+
const part = resolvePathPart(comp, nodeRefs, vid);
|
|
1138
|
+
if (part) parts.push(part);
|
|
1128
1139
|
}
|
|
1129
|
-
for (let i = pendingDyns.length - 1; i >= 0; i--)
|
|
1130
|
-
if (pendingDyns[i].producerCompId === cidNum) pendingDyns.splice(i, 1);
|
|
1131
1140
|
eventIds = [];
|
|
1132
|
-
|
|
1141
|
+
nodeRefs = [];
|
|
1133
1142
|
return true;
|
|
1134
1143
|
};
|
|
1135
|
-
while (node && node !== rootNode
|
|
1144
|
+
while (node && node !== rootNode) {
|
|
1136
1145
|
if (node?.dataset) {
|
|
1137
|
-
const { eid, cid, vid } = node.dataset;
|
|
1146
|
+
const { eid, cid, vid, rp } = node.dataset;
|
|
1138
1147
|
if (eid !== void 0) eventIds.push(eid);
|
|
1139
1148
|
const metas = metaChain(node.previousSibling);
|
|
1140
1149
|
let sawComp = false;
|
|
@@ -1142,21 +1151,46 @@ var Path = class _Path {
|
|
|
1142
1151
|
if (m.$ === "Comp") {
|
|
1143
1152
|
sawComp = true;
|
|
1144
1153
|
if (!crossComponent(m.cid, m.vid)) return NO_EVENT_INFO;
|
|
1145
|
-
|
|
1154
|
+
nodeRefs.push({ nid: m.nid, base: pathFromJson(m.base) });
|
|
1146
1155
|
} else {
|
|
1147
|
-
|
|
1156
|
+
nodeRefs.push({ nid: m.nid, si: m.si, sk: m.sk });
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
if (!sawComp && cid !== void 0) {
|
|
1160
|
+
if (!crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
1161
|
+
if (rp !== void 0) {
|
|
1162
|
+
const base = parseRenderPath(rp);
|
|
1163
|
+
if (base !== null) nodeRefs.push({ base });
|
|
1148
1164
|
}
|
|
1149
1165
|
}
|
|
1150
|
-
if (!sawComp && cid !== void 0 && !crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
1151
1166
|
}
|
|
1152
|
-
depth += 1;
|
|
1153
1167
|
node = node.parentNode;
|
|
1154
1168
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1169
|
+
parts.reverse();
|
|
1170
|
+
let path2 = new _DispatchPath();
|
|
1171
|
+
for (const part of parts)
|
|
1172
|
+
path2 = part.base !== void 0 ? path2.pushFrame(part.base) : path2.pushItem(part.step);
|
|
1173
|
+
return [path2, handlers];
|
|
1174
|
+
}
|
|
1175
|
+
};
|
|
1176
|
+
function keyedPath(path2, key) {
|
|
1177
|
+
const steps = path2.steps;
|
|
1178
|
+
const last = steps[steps.length - 1];
|
|
1179
|
+
if (last instanceof SeqStep || last instanceof FieldStep)
|
|
1180
|
+
return new Path(steps.slice(0, -1).concat(new SeqStep(last.field, key)));
|
|
1181
|
+
return null;
|
|
1182
|
+
}
|
|
1183
|
+
function renderPathText(path2) {
|
|
1184
|
+
return JSON.stringify(pathToJson(path2));
|
|
1185
|
+
}
|
|
1186
|
+
function parseRenderPath(text) {
|
|
1187
|
+
try {
|
|
1188
|
+
return pathFromJson(JSON.parse(text));
|
|
1189
|
+
} catch (err) {
|
|
1190
|
+
console.warn("bad render path", err, text);
|
|
1191
|
+
return null;
|
|
1158
1192
|
}
|
|
1159
|
-
}
|
|
1193
|
+
}
|
|
1160
1194
|
function metaChain(n) {
|
|
1161
1195
|
const out = [];
|
|
1162
1196
|
while (n?.nodeType === 8 && n.textContent[0] === "§") {
|
|
@@ -1201,28 +1235,28 @@ var StepCtx = class _StepCtx {
|
|
|
1201
1235
|
resolveNode() {
|
|
1202
1236
|
return this.comp.getNodeForId(+this.meta.nid, this.vid);
|
|
1203
1237
|
}
|
|
1204
|
-
applyKey(pi) {
|
|
1205
|
-
if (pi === null) return null;
|
|
1206
|
-
const m = this.meta;
|
|
1207
|
-
if (m.si !== void 0) return pi.withIndex(+m.si);
|
|
1208
|
-
if (m.sk !== void 0) return pi.withKey(m.sk);
|
|
1209
|
-
return pi;
|
|
1210
|
-
}
|
|
1211
1238
|
};
|
|
1212
|
-
function
|
|
1213
|
-
for (let i = 0; i <
|
|
1214
|
-
const
|
|
1215
|
-
|
|
1216
|
-
if (
|
|
1239
|
+
function resolvePathPart(comp, nodeRefs, vid) {
|
|
1240
|
+
for (let i = 0; i < nodeRefs.length; i++) {
|
|
1241
|
+
const ref = nodeRefs[i];
|
|
1242
|
+
if (ref.base != null) return { base: ref.base };
|
|
1243
|
+
if (ref.nid === void 0 || ref.nid === null) continue;
|
|
1244
|
+
const ctx = new StepCtx(comp, nodeRefs, i, vid);
|
|
1245
|
+
const step = ctx.resolveNode()?.toPathStep(ctx) ?? null;
|
|
1246
|
+
if (step !== null) return { step };
|
|
1217
1247
|
}
|
|
1218
1248
|
return null;
|
|
1219
1249
|
}
|
|
1220
1250
|
var NO_EVENT_INFO = [null, null];
|
|
1221
1251
|
var BUBBLING_EVENTS = /* @__PURE__ */ new Set(["drop"]);
|
|
1252
|
+
var path = () => new PathBuilder();
|
|
1222
1253
|
var PathBuilder = class {
|
|
1223
1254
|
constructor() {
|
|
1224
1255
|
this.pathChanges = [];
|
|
1225
1256
|
}
|
|
1257
|
+
toPath() {
|
|
1258
|
+
return new Path(this.pathChanges);
|
|
1259
|
+
}
|
|
1226
1260
|
add(pathChange) {
|
|
1227
1261
|
this.pathChanges.push(pathChange);
|
|
1228
1262
|
return this;
|
|
@@ -1238,10 +1272,8 @@ var PathBuilder = class {
|
|
|
1238
1272
|
}
|
|
1239
1273
|
};
|
|
1240
1274
|
|
|
1241
|
-
// src/util/env.js
|
|
1242
|
-
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1243
|
-
|
|
1244
1275
|
// src/value.js
|
|
1276
|
+
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1245
1277
|
var VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*\??$/;
|
|
1246
1278
|
var isValidValId = (name) => VALID_VAL_ID_RE.test(name);
|
|
1247
1279
|
var VALID_FLOAT_RE = /^-?[0-9]+(\.[0-9]+)?$/;
|
|
@@ -1423,22 +1455,10 @@ function _parsePredicate(s, tokens, px) {
|
|
|
1423
1455
|
}
|
|
1424
1456
|
return new PredicateVal(pred, args);
|
|
1425
1457
|
}
|
|
1426
|
-
|
|
1427
|
-
if (val === null) return 0;
|
|
1428
|
-
if (val instanceof ConstVal) return val.kind;
|
|
1429
|
-
if (val instanceof StrTplVal) return val.kind;
|
|
1430
|
-
if (val instanceof SeqAccessVal) return K_SEQ;
|
|
1431
|
-
if (val instanceof FieldVal) return K_FIELD;
|
|
1432
|
-
if (val instanceof MethodVal) return K_METHOD;
|
|
1433
|
-
if (val instanceof BindVal) return K_BIND;
|
|
1434
|
-
if (val instanceof DynVal) return K_DYN;
|
|
1435
|
-
if (val instanceof NameVal) return K_NAME;
|
|
1436
|
-
if (val instanceof EventMemberVal) return K_EVENT;
|
|
1437
|
-
return 0;
|
|
1438
|
-
}
|
|
1458
|
+
var kindOf = (val) => val?.kind ?? 0;
|
|
1439
1459
|
var BaseVal = class {
|
|
1440
|
-
|
|
1441
|
-
|
|
1460
|
+
// No kind: never accepted by a group (PredicateVal, which only parseBool builds).
|
|
1461
|
+
kind = 0;
|
|
1442
1462
|
eval(_stack) {
|
|
1443
1463
|
}
|
|
1444
1464
|
toPathItem() {
|
|
@@ -1458,9 +1478,6 @@ var ConstVal = class extends BaseVal {
|
|
|
1458
1478
|
this.val = val;
|
|
1459
1479
|
this.kind = kind;
|
|
1460
1480
|
}
|
|
1461
|
-
render(_stack, _rx) {
|
|
1462
|
-
return this.val;
|
|
1463
|
-
}
|
|
1464
1481
|
eval(_stack) {
|
|
1465
1482
|
return this.val;
|
|
1466
1483
|
}
|
|
@@ -1486,9 +1503,7 @@ var PredicateVal = class extends BaseVal {
|
|
|
1486
1503
|
return `${this.pred.name} ${this.args.map(String).join(" ")}`;
|
|
1487
1504
|
}
|
|
1488
1505
|
};
|
|
1489
|
-
var
|
|
1490
|
-
};
|
|
1491
|
-
var StrTplVal = class _StrTplVal extends VarVal {
|
|
1506
|
+
var StrTplVal = class _StrTplVal extends BaseVal {
|
|
1492
1507
|
constructor(vals) {
|
|
1493
1508
|
super();
|
|
1494
1509
|
this.vals = vals;
|
|
@@ -1501,9 +1516,6 @@ var StrTplVal = class _StrTplVal extends VarVal {
|
|
|
1501
1516
|
for (const v of this.vals) if (!(v instanceof ConstVal) || v.fromMacroVar) return false;
|
|
1502
1517
|
return true;
|
|
1503
1518
|
}
|
|
1504
|
-
render(stack, _rx) {
|
|
1505
|
-
return this.eval(stack);
|
|
1506
|
-
}
|
|
1507
1519
|
eval(stack) {
|
|
1508
1520
|
const strs = new Array(this.vals.length);
|
|
1509
1521
|
for (let i = 0; i < this.vals.length; i++) strs[i] = this.vals[i]?.eval(stack, "");
|
|
@@ -1540,7 +1552,8 @@ var StrTplVal = class _StrTplVal extends VarVal {
|
|
|
1540
1552
|
return new _StrTplVal(lo === 0 && hi === vals.length ? vals : vals.slice(lo, hi));
|
|
1541
1553
|
}
|
|
1542
1554
|
};
|
|
1543
|
-
var NameVal = class extends
|
|
1555
|
+
var NameVal = class extends BaseVal {
|
|
1556
|
+
kind = K_NAME;
|
|
1544
1557
|
constructor(name) {
|
|
1545
1558
|
super();
|
|
1546
1559
|
this.name = name;
|
|
@@ -1590,6 +1603,7 @@ var EVENT_CONVENIENCES = {
|
|
|
1590
1603
|
dragKey: nullSafe((info) => info.lookupBind("key"))
|
|
1591
1604
|
};
|
|
1592
1605
|
var EventMemberVal = class extends BaseVal {
|
|
1606
|
+
kind = K_EVENT;
|
|
1593
1607
|
constructor(members) {
|
|
1594
1608
|
super();
|
|
1595
1609
|
this.members = members;
|
|
@@ -1612,24 +1626,21 @@ var EventMemberVal = class extends BaseVal {
|
|
|
1612
1626
|
return `e.${this.members.join(".")}`;
|
|
1613
1627
|
}
|
|
1614
1628
|
};
|
|
1615
|
-
var
|
|
1616
|
-
render(stack, _rx) {
|
|
1617
|
-
return this.eval(stack);
|
|
1618
|
-
}
|
|
1619
|
-
};
|
|
1620
|
-
var RenderNameVal = class extends RenderVal {
|
|
1629
|
+
var SigilNameVal = class extends BaseVal {
|
|
1621
1630
|
constructor(name) {
|
|
1622
1631
|
super();
|
|
1623
1632
|
this.name = name;
|
|
1624
1633
|
}
|
|
1634
|
+
toString() {
|
|
1635
|
+
return this.sigil + this.name;
|
|
1636
|
+
}
|
|
1625
1637
|
};
|
|
1626
|
-
var BindVal = class extends
|
|
1638
|
+
var BindVal = class extends SigilNameVal {
|
|
1639
|
+
kind = K_BIND;
|
|
1640
|
+
sigil = "@";
|
|
1627
1641
|
eval(stack) {
|
|
1628
1642
|
return stack.lookupBind(this.name);
|
|
1629
1643
|
}
|
|
1630
|
-
toString() {
|
|
1631
|
-
return `@${this.name}`;
|
|
1632
|
-
}
|
|
1633
1644
|
};
|
|
1634
1645
|
var BindMemberVal = class extends BindVal {
|
|
1635
1646
|
constructor(name, member) {
|
|
@@ -1644,37 +1655,35 @@ var BindMemberVal = class extends BindVal {
|
|
|
1644
1655
|
return `@${this.name}.${this.member}`;
|
|
1645
1656
|
}
|
|
1646
1657
|
};
|
|
1647
|
-
var DynVal = class extends
|
|
1658
|
+
var DynVal = class extends SigilNameVal {
|
|
1659
|
+
kind = K_DYN;
|
|
1660
|
+
sigil = "*";
|
|
1648
1661
|
eval(stack) {
|
|
1649
1662
|
return stack.lookupDynamic(this.name);
|
|
1650
1663
|
}
|
|
1651
|
-
toString() {
|
|
1652
|
-
return `*${this.name}`;
|
|
1653
|
-
}
|
|
1654
1664
|
};
|
|
1655
|
-
var FieldVal = class extends
|
|
1665
|
+
var FieldVal = class extends SigilNameVal {
|
|
1666
|
+
kind = K_FIELD;
|
|
1667
|
+
sigil = ".";
|
|
1656
1668
|
eval(stack) {
|
|
1657
1669
|
return stack.lookupFieldRaw(this.name);
|
|
1658
1670
|
}
|
|
1659
1671
|
toPathItem() {
|
|
1660
1672
|
return new FieldStep(this.name);
|
|
1661
1673
|
}
|
|
1662
|
-
toString() {
|
|
1663
|
-
return `.${this.name}`;
|
|
1664
|
-
}
|
|
1665
1674
|
};
|
|
1666
|
-
var MethodVal = class extends
|
|
1675
|
+
var MethodVal = class extends SigilNameVal {
|
|
1676
|
+
kind = K_METHOD;
|
|
1677
|
+
sigil = "$";
|
|
1667
1678
|
eval(stack) {
|
|
1668
1679
|
return stack.lookupMethod(this.name);
|
|
1669
1680
|
}
|
|
1670
1681
|
evalAsHandler(stack) {
|
|
1671
1682
|
return stack.lookupFieldRaw(this.name);
|
|
1672
1683
|
}
|
|
1673
|
-
toString() {
|
|
1674
|
-
return `$${this.name}`;
|
|
1675
|
-
}
|
|
1676
1684
|
};
|
|
1677
|
-
var SeqAccessVal = class extends
|
|
1685
|
+
var SeqAccessVal = class extends BaseVal {
|
|
1686
|
+
kind = K_SEQ;
|
|
1678
1687
|
constructor(seqVal, keyVal) {
|
|
1679
1688
|
super();
|
|
1680
1689
|
this.seqVal = seqVal;
|
|
@@ -1697,9 +1706,6 @@ var Attributes = class {
|
|
|
1697
1706
|
constructor(items) {
|
|
1698
1707
|
this.items = items;
|
|
1699
1708
|
}
|
|
1700
|
-
static parse(attributes, px, parseAll = false) {
|
|
1701
|
-
return new AttrParser(px).parse(attributes, parseAll);
|
|
1702
|
-
}
|
|
1703
1709
|
isConstant() {
|
|
1704
1710
|
return false;
|
|
1705
1711
|
}
|
|
@@ -1717,10 +1723,16 @@ function parseDirectiveValue(px, directiveName, source, parser) {
|
|
|
1717
1723
|
}
|
|
1718
1724
|
return val;
|
|
1719
1725
|
}
|
|
1726
|
+
var ITER_DIRECTIVES = {
|
|
1727
|
+
when: "whenVal",
|
|
1728
|
+
"loop-with": "loopWithVal",
|
|
1729
|
+
"enrich-with": "enrichWithVal"
|
|
1730
|
+
};
|
|
1731
|
+
var parseIterDirective = (px, name, s) => parseDirectiveValue(px, name, s, parseAlterHandler);
|
|
1720
1732
|
function parseIterationDirectives(attributes, px) {
|
|
1721
1733
|
const parseNamed = (name) => {
|
|
1722
1734
|
const attr = attributes.getNamedItem(`@${name}`);
|
|
1723
|
-
return attr ?
|
|
1735
|
+
return attr ? parseIterDirective(px, name, attr.value) : null;
|
|
1724
1736
|
};
|
|
1725
1737
|
return { whenVal: parseNamed("when"), loopWithVal: parseNamed("loop-with") };
|
|
1726
1738
|
}
|
|
@@ -1761,11 +1773,22 @@ var AttrParser = class {
|
|
|
1761
1773
|
this.px.onParseIssue("bad-value", info);
|
|
1762
1774
|
}
|
|
1763
1775
|
}
|
|
1764
|
-
|
|
1765
|
-
|
|
1776
|
+
// `@then` / `@else` fill the branches of the `@if.<attr>` on the same element.
|
|
1777
|
+
parseBranch(slot, name, s) {
|
|
1778
|
+
if (this.ifAttr === null) return this._orphan(name, s, "if");
|
|
1779
|
+
this.ifAttr[slot] = parseText(s, this.px) ?? NOT_SET_VAL;
|
|
1780
|
+
}
|
|
1781
|
+
// `@when` / `@loop-with` / `@enrich-with` amend the `@each` on the same element. A
|
|
1782
|
+
// loop-less `@enrich-with` is a scope of its own; the other two need the loop.
|
|
1783
|
+
parseIter(name, s) {
|
|
1784
|
+
const val = parseIterDirective(this.px, name, s);
|
|
1785
|
+
if (this.eachAttr !== null) this.eachAttr[ITER_DIRECTIVES[name]] = val;
|
|
1786
|
+
else if (name === "enrich-with") this.pushWrapper("scope", s, val);
|
|
1787
|
+
else this._orphan(name, s, "each");
|
|
1766
1788
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1789
|
+
// A directive that only means something next to another one, written alone.
|
|
1790
|
+
_orphan(name, value, needs) {
|
|
1791
|
+
this.px.onParseIssue("orphan-directive", { name, value, needs });
|
|
1769
1792
|
}
|
|
1770
1793
|
parseEvent(directiveName, value) {
|
|
1771
1794
|
const [eventName, ...modifiers] = directiveName.slice(3).split("+");
|
|
@@ -1779,77 +1802,51 @@ var AttrParser = class {
|
|
|
1779
1802
|
this.events.add(eventName, handler, modifiers);
|
|
1780
1803
|
}
|
|
1781
1804
|
}
|
|
1782
|
-
_parseDirectiveValue(directiveName, s, parserFn) {
|
|
1783
|
-
return parseDirectiveValue(this.px, directiveName, s, parserFn);
|
|
1784
|
-
}
|
|
1785
1805
|
parseDirective(s, directiveName) {
|
|
1786
1806
|
switch (directiveName) {
|
|
1787
1807
|
case "dangerouslysetinnerhtml":
|
|
1788
1808
|
this.attrs ??= [];
|
|
1789
|
-
this.attrs.push(new RawHtmlAttr(this.
|
|
1809
|
+
this.attrs.push(new RawHtmlAttr(parseDirectiveValue(this.px, directiveName, s, parseText)));
|
|
1790
1810
|
this.hasDynamic = true;
|
|
1791
1811
|
return;
|
|
1792
1812
|
case "push-view":
|
|
1793
|
-
this.pushWrapper("push-view", s, this.
|
|
1813
|
+
this.pushWrapper("push-view", s, parseDirectiveValue(this.px, directiveName, s, parseText));
|
|
1794
1814
|
return;
|
|
1795
1815
|
case "text":
|
|
1796
|
-
this.textChild = this.
|
|
1816
|
+
this.textChild = parseDirectiveValue(this.px, directiveName, s, parseText);
|
|
1797
1817
|
return;
|
|
1798
1818
|
case "show":
|
|
1799
|
-
this.pushWrapper("show", s, this.
|
|
1819
|
+
this.pushWrapper("show", s, parseDirectiveValue(this.px, directiveName, s, parseBool));
|
|
1800
1820
|
return;
|
|
1801
1821
|
case "hide":
|
|
1802
|
-
this.pushWrapper("hide", s, this.
|
|
1822
|
+
this.pushWrapper("hide", s, parseDirectiveValue(this.px, directiveName, s, parseBool));
|
|
1803
1823
|
return;
|
|
1804
1824
|
case "each": {
|
|
1805
|
-
const val = this.
|
|
1825
|
+
const val = parseDirectiveValue(this.px, directiveName, s, parseSequence);
|
|
1806
1826
|
this.eachAttr = this.pushWrapper("each", s, val);
|
|
1807
1827
|
return;
|
|
1808
1828
|
}
|
|
1809
|
-
case "enrich-with":
|
|
1810
|
-
if (this.eachAttr !== null)
|
|
1811
|
-
this.eachAttr.enrichWithVal = this._parseDirectiveValue(
|
|
1812
|
-
directiveName,
|
|
1813
|
-
s,
|
|
1814
|
-
parseAlterHandler
|
|
1815
|
-
);
|
|
1816
|
-
else
|
|
1817
|
-
this.pushWrapper(
|
|
1818
|
-
"scope",
|
|
1819
|
-
s,
|
|
1820
|
-
this._parseDirectiveValue(directiveName, s, parseAlterHandler)
|
|
1821
|
-
);
|
|
1822
|
-
return;
|
|
1823
1829
|
case "when":
|
|
1824
|
-
this._parseWhen(s);
|
|
1825
|
-
return;
|
|
1826
1830
|
case "loop-with":
|
|
1827
|
-
|
|
1831
|
+
case "enrich-with":
|
|
1832
|
+
this.parseIter(directiveName, s);
|
|
1828
1833
|
return;
|
|
1829
1834
|
case "then":
|
|
1830
|
-
this.
|
|
1835
|
+
this.parseBranch("thenVal", directiveName, s);
|
|
1831
1836
|
return;
|
|
1832
1837
|
case "else":
|
|
1833
|
-
this.
|
|
1838
|
+
this.parseBranch("elseVal", directiveName, s);
|
|
1834
1839
|
return;
|
|
1835
1840
|
}
|
|
1836
1841
|
if (directiveName.startsWith("on.")) this.parseEvent(directiveName, s);
|
|
1837
1842
|
else if (directiveName.startsWith("if.")) this.parseIf(directiveName, s);
|
|
1838
|
-
else if (directiveName.startsWith("then.")) this.
|
|
1839
|
-
else if (directiveName.startsWith("else.")) this.
|
|
1843
|
+
else if (directiveName.startsWith("then.")) this.parseBranch("thenVal", directiveName, s);
|
|
1844
|
+
else if (directiveName.startsWith("else.")) this.parseBranch("elseVal", directiveName, s);
|
|
1840
1845
|
else {
|
|
1841
1846
|
const info = { name: directiveName, value: s };
|
|
1842
1847
|
this.px.onParseIssue("unknown-directive", info);
|
|
1843
1848
|
}
|
|
1844
1849
|
}
|
|
1845
|
-
_parseWhen(s) {
|
|
1846
|
-
if (this.eachAttr !== null)
|
|
1847
|
-
this.eachAttr.whenVal = this._parseDirectiveValue("when", s, parseAlterHandler);
|
|
1848
|
-
}
|
|
1849
|
-
_parseLoopWith(s) {
|
|
1850
|
-
if (this.eachAttr !== null)
|
|
1851
|
-
this.eachAttr.loopWithVal = this._parseDirectiveValue("loop-with", s, parseAlterHandler);
|
|
1852
|
-
}
|
|
1853
1850
|
parse(attributes, parseAll = false) {
|
|
1854
1851
|
for (const { name, value } of attributes) {
|
|
1855
1852
|
const charCode = name.charCodeAt(0);
|
|
@@ -2202,19 +2199,21 @@ var VNode = class _VNode extends VBase {
|
|
|
2202
2199
|
const createOpts = attrs.is != null ? { is: attrs.is } : void 0;
|
|
2203
2200
|
const node = ns === null ? doc.createElement(tag, createOpts) : doc.createElementNS(ns, tag, createOpts);
|
|
2204
2201
|
const cOpts = childOpts(this, ns, opts);
|
|
2205
|
-
|
|
2206
|
-
const { value, checked, ...rest } = attrs;
|
|
2207
|
-
applyProperties(node, rest);
|
|
2208
|
-
appendChildNodes(node, this.childs, cOpts);
|
|
2209
|
-
if (value !== void 0) applyValueLast(node, value);
|
|
2210
|
-
if (checked !== void 0) setProp(node, "checked", checked, false);
|
|
2211
|
-
} else {
|
|
2212
|
-
applyProperties(node, attrs);
|
|
2213
|
-
appendChildNodes(node, this.childs, cOpts);
|
|
2214
|
-
}
|
|
2202
|
+
applyAttrs(node, attrs, () => appendChildNodes(node, this.childs, cOpts));
|
|
2215
2203
|
return node;
|
|
2216
2204
|
}
|
|
2217
2205
|
};
|
|
2206
|
+
function applyAttrs(node, attrs, placeChildren) {
|
|
2207
|
+
const hasValue = "value" in attrs;
|
|
2208
|
+
const hasChecked = "checked" in attrs;
|
|
2209
|
+
if (hasValue || hasChecked) {
|
|
2210
|
+
const { value: _v, checked: _c, ...rest } = attrs;
|
|
2211
|
+
applyProperties(node, rest);
|
|
2212
|
+
} else applyProperties(node, attrs);
|
|
2213
|
+
placeChildren();
|
|
2214
|
+
if (hasValue) applyValueLast(node, attrs.value);
|
|
2215
|
+
if (hasChecked) setProp(node, "checked", attrs.checked, isNamespaced(node));
|
|
2216
|
+
}
|
|
2218
2217
|
function diffProps(a, b) {
|
|
2219
2218
|
if (a === b) return null;
|
|
2220
2219
|
let diff = null;
|
|
@@ -2245,22 +2244,16 @@ function morphNode(domNode, source, target, opts) {
|
|
|
2245
2244
|
}
|
|
2246
2245
|
if (type === 1 && source.isSameKind(target)) {
|
|
2247
2246
|
const propsDiff = diffProps(source.attrs, target.attrs);
|
|
2248
|
-
const
|
|
2249
|
-
|
|
2250
|
-
if (propsDiff) {
|
|
2251
|
-
if (hasValue || hasChecked) {
|
|
2252
|
-
const { value: _v, checked: _c, ...rest } = propsDiff;
|
|
2253
|
-
applyProperties(domNode, rest);
|
|
2254
|
-
} else applyProperties(domNode, propsDiff);
|
|
2255
|
-
}
|
|
2256
|
-
if (!target.attrs.dangerouslySetInnerHTML) {
|
|
2247
|
+
const placeChildren = () => {
|
|
2248
|
+
if (target.attrs.dangerouslySetInnerHTML) return;
|
|
2257
2249
|
const ns = effectiveNs(target, opts);
|
|
2258
2250
|
morphChildren(domNode, source.childs, target.childs, childOpts(target, ns, opts));
|
|
2251
|
+
};
|
|
2252
|
+
if (propsDiff) applyAttrs(domNode, propsDiff, placeChildren);
|
|
2253
|
+
else placeChildren();
|
|
2254
|
+
if (!(propsDiff && "value" in propsDiff) && source.tag === "SELECT") {
|
|
2255
|
+
if (target.attrs.value !== void 0) applyValueLast(domNode, target.attrs.value);
|
|
2259
2256
|
}
|
|
2260
|
-
if (hasValue) applyValueLast(domNode, propsDiff.value);
|
|
2261
|
-
else if (source.tag === "SELECT" && target.attrs.value !== void 0)
|
|
2262
|
-
applyValueLast(domNode, target.attrs.value);
|
|
2263
|
-
if (hasChecked) setProp(domNode, "checked", propsDiff.checked, false);
|
|
2264
2257
|
return domNode;
|
|
2265
2258
|
}
|
|
2266
2259
|
if (type === 11) {
|
|
@@ -2379,20 +2372,26 @@ function h(tagName, properties, children, namespace) {
|
|
|
2379
2372
|
}
|
|
2380
2373
|
|
|
2381
2374
|
// src/anode.js
|
|
2382
|
-
function
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2375
|
+
function renderTarget(val, stack) {
|
|
2376
|
+
if (val instanceof DynVal) {
|
|
2377
|
+
const loc = stack.lookupDynamicLocated(val.name);
|
|
2378
|
+
if (loc?.path == null) return [loc?.value ?? null, stack.renderPath, null];
|
|
2379
|
+
return [loc.value, stack.renderPath.pushFrame(loc.path), loc.path];
|
|
2380
|
+
}
|
|
2381
|
+
const step = val.toPathItem?.() ?? null;
|
|
2382
|
+
if (step === null) return [val.eval(stack), stack.renderPath, null];
|
|
2383
|
+
const path2 = stack.renderPath.pushItem(step);
|
|
2384
|
+
return [val.eval(stack), path2, stack.pendingFrame ? path2.toTransactionPath() : null];
|
|
2389
2385
|
}
|
|
2390
2386
|
var BaseNode = class {
|
|
2391
2387
|
render(_stack, _rx) {
|
|
2392
2388
|
return null;
|
|
2393
2389
|
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2390
|
+
// Stamp a `data-*` attribute on the element(s) this node renders. A no-op for
|
|
2391
|
+
// nodes that produce no element of their own (text, `<x render*>`): a view whose
|
|
2392
|
+
// root is one of those records its component boundary in the `§Comp§` meta
|
|
2393
|
+
// comment instead (see Renderer._rValComp).
|
|
2394
|
+
setDataAttr(_key, _val) {
|
|
2396
2395
|
}
|
|
2397
2396
|
isConstant() {
|
|
2398
2397
|
return false;
|
|
@@ -2431,21 +2430,12 @@ var TextNode = class extends BaseNode {
|
|
|
2431
2430
|
isConstant() {
|
|
2432
2431
|
return true;
|
|
2433
2432
|
}
|
|
2434
|
-
setDataAttr(_key, _val) {
|
|
2435
|
-
}
|
|
2436
2433
|
};
|
|
2437
2434
|
var CommentNode = class extends TextNode {
|
|
2438
2435
|
render(_stack, rx) {
|
|
2439
2436
|
return rx.renderComment(this.val);
|
|
2440
2437
|
}
|
|
2441
2438
|
};
|
|
2442
|
-
function optimizeChilds(childs) {
|
|
2443
|
-
for (let i = 0; i < childs.length; i++) {
|
|
2444
|
-
const child = childs[i];
|
|
2445
|
-
if (child.isConstant()) childs[i] = new RenderOnceNode(child);
|
|
2446
|
-
else child.optimize();
|
|
2447
|
-
}
|
|
2448
|
-
}
|
|
2449
2439
|
function optimizeNode(node) {
|
|
2450
2440
|
if (node.isConstant()) return new RenderOnceNode(node);
|
|
2451
2441
|
node.optimize();
|
|
@@ -2460,7 +2450,8 @@ var ChildsNode = class extends BaseNode {
|
|
|
2460
2450
|
return this.childs.every((v) => v.isConstant());
|
|
2461
2451
|
}
|
|
2462
2452
|
optimize() {
|
|
2463
|
-
|
|
2453
|
+
const { childs } = this;
|
|
2454
|
+
for (let i = 0; i < childs.length; i++) childs[i] = optimizeNode(childs[i]);
|
|
2464
2455
|
}
|
|
2465
2456
|
};
|
|
2466
2457
|
var DomNode = class extends ChildsNode {
|
|
@@ -2472,8 +2463,7 @@ var DomNode = class extends ChildsNode {
|
|
|
2472
2463
|
}
|
|
2473
2464
|
render(stack, rx) {
|
|
2474
2465
|
const childNodes = new Array(this.childs.length);
|
|
2475
|
-
for (let i = 0; i < childNodes.length; i++)
|
|
2476
|
-
childNodes[i] = this.childs[i]?.render?.(stack, rx) ?? null;
|
|
2466
|
+
for (let i = 0; i < childNodes.length; i++) childNodes[i] = this.childs[i].render(stack, rx);
|
|
2477
2467
|
return rx.renderTag(this.tagName, this.attrs.eval(stack), childNodes, this.namespace);
|
|
2478
2468
|
}
|
|
2479
2469
|
setDataAttr(key, val) {
|
|
@@ -2485,7 +2475,7 @@ var DomNode = class extends ChildsNode {
|
|
|
2485
2475
|
};
|
|
2486
2476
|
var FragmentNode = class extends ChildsNode {
|
|
2487
2477
|
render(stack, rx) {
|
|
2488
|
-
return rx.renderFragment(this.childs.map((c) => c
|
|
2478
|
+
return rx.renderFragment(this.childs.map((c) => c.render(stack, rx)));
|
|
2489
2479
|
}
|
|
2490
2480
|
setDataAttr(key, val) {
|
|
2491
2481
|
for (const child of this.childs) child.setDataAttr(key, val);
|
|
@@ -2499,8 +2489,10 @@ var ANode = class _ANode extends BaseNode {
|
|
|
2499
2489
|
this.nodeId = nodeId;
|
|
2500
2490
|
this.val = val;
|
|
2501
2491
|
}
|
|
2502
|
-
|
|
2503
|
-
|
|
2492
|
+
// The addressing step this node contributes to an event's dispatch path, given
|
|
2493
|
+
// the `StepCtx` of the meta that named it; null when it addresses nothing.
|
|
2494
|
+
toPathStep(_ctx) {
|
|
2495
|
+
return this.val?.toPathItem?.() ?? null;
|
|
2504
2496
|
}
|
|
2505
2497
|
static parse(html2, px) {
|
|
2506
2498
|
const nodes = px.parseHTML(html2);
|
|
@@ -2516,8 +2508,8 @@ var ANode = class _ANode extends BaseNode {
|
|
|
2516
2508
|
return maybeFragment(trimmed);
|
|
2517
2509
|
}
|
|
2518
2510
|
static fromDOM(node, px) {
|
|
2519
|
-
if (node
|
|
2520
|
-
|
|
2511
|
+
if (node.nodeType === 3) return new TextNode(node.textContent);
|
|
2512
|
+
if (node.nodeType === 8) return new CommentNode(node.textContent);
|
|
2521
2513
|
const { childNodes, attributes: attrs, tagName: tag } = node;
|
|
2522
2514
|
const childs = [];
|
|
2523
2515
|
for (let i = 0; i < childNodes.length; i++) {
|
|
@@ -2535,11 +2527,11 @@ var ANode = class _ANode extends BaseNode {
|
|
|
2535
2527
|
const slotName = attrs.getNamedItem("name")?.value ?? "_";
|
|
2536
2528
|
return px.frame.macroSlots[slotName] ?? maybeFragment(childs);
|
|
2537
2529
|
}
|
|
2538
|
-
const [nAttrs, wrappers] =
|
|
2530
|
+
const [nAttrs, wrappers] = new AttrParser(px).parse(attrs, true);
|
|
2539
2531
|
px.onAttributes(nAttrs, wrappers, null, true, tag);
|
|
2540
2532
|
return wrap(px.newMacroNode(macroName, nAttrs.toMacroVars(), childs), px, wrappers);
|
|
2541
2533
|
} else if (VALID_NODE_RE.test(tag)) {
|
|
2542
|
-
const [nAttrs, wrappers, textChild] =
|
|
2534
|
+
const [nAttrs, wrappers, textChild] = new AttrParser(px).parse(attrs);
|
|
2543
2535
|
px.onAttributes(nAttrs, wrappers, textChild, false, tag);
|
|
2544
2536
|
if (textChild) childs.unshift(new RenderTextNode(null, textChild));
|
|
2545
2537
|
const domChilds = tag !== "PRE" ? condenseChildsWhites(childs) : childs;
|
|
@@ -2701,39 +2693,32 @@ var RenderViewId = class extends ANode {
|
|
|
2701
2693
|
evalViewName(stack) {
|
|
2702
2694
|
return this.viewVal ? this.viewVal.eval(stack) : null;
|
|
2703
2695
|
}
|
|
2704
|
-
// A `<x render*>` produces no DOM element of its own to carry `data-cid`;
|
|
2705
|
-
// when it is a view's root the component boundary is recorded in the `Comp`
|
|
2706
|
-
// meta comment instead (see Renderer._rValComp), so this is a no-op.
|
|
2707
|
-
setDataAttr(_key, _val) {
|
|
2708
|
-
}
|
|
2709
2696
|
};
|
|
2710
|
-
function dynRenderStep(comp, name, key) {
|
|
2711
|
-
const p = resolveDynProducer(comp, name);
|
|
2712
|
-
if (!p) return null;
|
|
2713
|
-
return key === void 0 ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
2714
|
-
}
|
|
2715
2697
|
var RenderNode = class extends RenderViewId {
|
|
2716
2698
|
render(stack, rx) {
|
|
2717
|
-
const
|
|
2718
|
-
|
|
2699
|
+
const [value, renderPath, base] = renderTarget(this.val, stack);
|
|
2700
|
+
const newStack = stack.enter(value, {}, true, renderPath, false);
|
|
2701
|
+
return rx.renderIt(newStack, this, this.evalViewName(stack), base);
|
|
2719
2702
|
}
|
|
2703
|
+
// A `*name` target contributes no step: the site recorded the absolute base it
|
|
2704
|
+
// resumed at, and event reconstruction turns that into a continuation frame.
|
|
2720
2705
|
toPathStep(ctx) {
|
|
2721
|
-
if (this.val instanceof DynVal) return
|
|
2706
|
+
if (this.val instanceof DynVal) return null;
|
|
2722
2707
|
return super.toPathStep(ctx);
|
|
2723
2708
|
}
|
|
2724
2709
|
};
|
|
2725
2710
|
var RenderItNode = class extends RenderViewId {
|
|
2726
2711
|
render(stack, rx) {
|
|
2727
|
-
const
|
|
2728
|
-
|
|
2712
|
+
const base = stack.pendingFrame ? stack.renderPath.toTransactionPath() : null;
|
|
2713
|
+
const newStack = stack.enter(stack.it, {}, true, stack.renderPath, false);
|
|
2714
|
+
return rx.renderIt(newStack, this, this.evalViewName(stack), base);
|
|
2729
2715
|
}
|
|
2730
2716
|
toPathStep(ctx) {
|
|
2731
2717
|
const next = ctx.next();
|
|
2732
2718
|
if (next === null) return null;
|
|
2733
2719
|
const nextNode = next.resolveNode();
|
|
2734
2720
|
if (nextNode instanceof EachNode && next.hasKey) {
|
|
2735
|
-
if (nextNode.val instanceof DynVal)
|
|
2736
|
-
return dynRenderStep(ctx.comp, nextNode.val.name, next.key);
|
|
2721
|
+
if (nextNode.val instanceof DynVal) return null;
|
|
2737
2722
|
return new EachRenderItStep(nextNode.val.name, next.key);
|
|
2738
2723
|
}
|
|
2739
2724
|
return null;
|
|
@@ -2755,9 +2740,6 @@ var RenderTextNode = class extends ANode {
|
|
|
2755
2740
|
render(stack, _rx) {
|
|
2756
2741
|
return this.val.eval(stack);
|
|
2757
2742
|
}
|
|
2758
|
-
// Renders to a text node, which can't carry `data-cid`.
|
|
2759
|
-
setDataAttr(_key, _val) {
|
|
2760
|
-
}
|
|
2761
2743
|
};
|
|
2762
2744
|
var RenderOnceNode = class extends BaseNode {
|
|
2763
2745
|
constructor(node) {
|
|
@@ -2832,36 +2814,46 @@ var ScopeNode = class extends WrapperNode {
|
|
|
2832
2814
|
var EachNode = class extends WrapperNode {
|
|
2833
2815
|
constructor(nodeId, val) {
|
|
2834
2816
|
super(nodeId, val);
|
|
2835
|
-
this.iterInfo = new IterInfo(
|
|
2817
|
+
this.iterInfo = new IterInfo();
|
|
2836
2818
|
}
|
|
2837
2819
|
render(stack, rx) {
|
|
2838
|
-
return rx.renderEachWhen(stack, this
|
|
2839
|
-
}
|
|
2840
|
-
toPathStep(ctx) {
|
|
2841
|
-
return ctx.hasKey ? new EachBindStep(this.iterInfo, ctx.key) : null;
|
|
2842
|
-
}
|
|
2843
|
-
static register = true;
|
|
2844
|
-
};
|
|
2845
|
-
var IterInfo = class {
|
|
2846
|
-
constructor(val, whenVal, loopWithVal, enrichWithVal) {
|
|
2847
|
-
this.val = val;
|
|
2848
|
-
this.whenVal = whenVal;
|
|
2849
|
-
this.loopWithVal = loopWithVal;
|
|
2850
|
-
this.enrichWithVal = enrichWithVal;
|
|
2820
|
+
return rx.renderEachWhen(stack, this);
|
|
2851
2821
|
}
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
const
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2822
|
+
// The sequence and the three loop handlers, resolved against `stack`.
|
|
2823
|
+
evalIter(stack) {
|
|
2824
|
+
const { whenVal, loopWithVal, enrichWithVal } = this.iterInfo;
|
|
2825
|
+
return {
|
|
2826
|
+
seq: this.val.eval(stack) ?? [],
|
|
2827
|
+
filter: whenVal?.evalAsHandler(stack) ?? filterAlwaysTrue,
|
|
2828
|
+
loopWith: loopWithVal?.evalAsHandler(stack) ?? nullLoopWith,
|
|
2829
|
+
enricher: enrichWithVal?.evalAsHandler(stack) ?? null
|
|
2830
|
+
};
|
|
2858
2831
|
}
|
|
2859
2832
|
// Rebuild the per-item binds for `key` (see iteration.js bindsForKey).
|
|
2860
2833
|
enrichBinds(stack, key) {
|
|
2861
|
-
const { seq, filter, loopWith, enricher } = this.
|
|
2834
|
+
const { seq, filter, loopWith, enricher } = this.evalIter(stack);
|
|
2862
2835
|
const ctx = makeLoopCtx(stack, filter);
|
|
2863
2836
|
return bindsForKey({ seq, it: stack.it, loopWith, enricher, ctx }, key);
|
|
2864
2837
|
}
|
|
2838
|
+
toPathStep(ctx) {
|
|
2839
|
+
return ctx.hasKey ? new EachBindStep(this, ctx.key) : null;
|
|
2840
|
+
}
|
|
2841
|
+
// Where one item lives, for the render path. `@each` re-binds `it` to the item
|
|
2842
|
+
// whether or not the body is a component, so the position moves either way and
|
|
2843
|
+
// the step has to address it — `.rows` iterated at `key` IS `rows[key]`.
|
|
2844
|
+
// Null for a dynamic sequence: `*rows` carries its own absolute path and enters
|
|
2845
|
+
// a continuation frame instead (see Renderer.renderEachWhen).
|
|
2846
|
+
itemStep(key) {
|
|
2847
|
+
return this.val instanceof FieldVal ? new SeqStep(this.val.name, key) : null;
|
|
2848
|
+
}
|
|
2849
|
+
static register = true;
|
|
2850
|
+
};
|
|
2851
|
+
var IterInfo = class {
|
|
2852
|
+
constructor() {
|
|
2853
|
+
this.whenVal = null;
|
|
2854
|
+
this.loopWithVal = null;
|
|
2855
|
+
this.enrichWithVal = null;
|
|
2856
|
+
}
|
|
2865
2857
|
};
|
|
2866
2858
|
function xOp(consumed = [], { wrappable = false, wrapper = null, ignoresChildren = false } = {}) {
|
|
2867
2859
|
return { consumed: new Set(consumed), wrappable, wrapper, ignoresChildren };
|
|
@@ -2888,26 +2880,31 @@ var WRAPPER_NODES = {
|
|
|
2888
2880
|
scope: ScopeNode,
|
|
2889
2881
|
"push-view": PushViewNameNode
|
|
2890
2882
|
};
|
|
2891
|
-
var ParseContext = class
|
|
2892
|
-
constructor(document2
|
|
2893
|
-
this.
|
|
2894
|
-
this.
|
|
2895
|
-
this.
|
|
2896
|
-
this.
|
|
2897
|
-
this.
|
|
2898
|
-
this.
|
|
2899
|
-
this.Text = Text ?? globalThis.Text;
|
|
2900
|
-
this.Comment = Comment ?? globalThis.Comment;
|
|
2901
|
-
this.cacheConstNodes = true;
|
|
2883
|
+
var ParseContext = class {
|
|
2884
|
+
constructor(document2 = globalThis.document) {
|
|
2885
|
+
this.document = document2;
|
|
2886
|
+
this.nodes = [];
|
|
2887
|
+
this.events = [];
|
|
2888
|
+
this.macroNodes = [];
|
|
2889
|
+
this.parent = null;
|
|
2890
|
+
this.frame = {};
|
|
2902
2891
|
this.currentTag = null;
|
|
2903
2892
|
}
|
|
2904
2893
|
isInsideMacro(name) {
|
|
2905
2894
|
return this.frame.macroName === name || this.parent?.isInsideMacro(name);
|
|
2906
2895
|
}
|
|
2896
|
+
// A macro body parses in a child context that shares every accumulator with
|
|
2897
|
+
// its parent (nodes, events, macroNodes, and whatever a subclass collects) and
|
|
2898
|
+
// differs only in its frame. Cloned rather than constructed so a subclass
|
|
2899
|
+
// keeps collecting inside macro bodies without re-implementing this — the
|
|
2900
|
+
// lint and class-set contexts used to lose (or had to copy) exactly that.
|
|
2907
2901
|
enterMacro(macroName, macroVars, macroSlots) {
|
|
2908
|
-
const
|
|
2909
|
-
|
|
2910
|
-
|
|
2902
|
+
const child = Object.create(Object.getPrototypeOf(this));
|
|
2903
|
+
return Object.assign(child, this, {
|
|
2904
|
+
frame: { macroName, macroVars, macroSlots },
|
|
2905
|
+
parent: this,
|
|
2906
|
+
currentTag: null
|
|
2907
|
+
});
|
|
2911
2908
|
}
|
|
2912
2909
|
parseHTML(html2) {
|
|
2913
2910
|
const t = this.document.createElement("template");
|
|
@@ -2972,10 +2969,10 @@ var isBlockDomNode = (n) => {
|
|
|
2972
2969
|
return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
|
|
2973
2970
|
};
|
|
2974
2971
|
var isEmptyText = (c) => c instanceof TextNode && c.val === "";
|
|
2975
|
-
var isIgnorableXChild = (c) => c instanceof CommentNode ||
|
|
2972
|
+
var isIgnorableXChild = (c) => c instanceof CommentNode || c.isWhiteSpace();
|
|
2976
2973
|
var hasMeaningfulChilds = (childs) => childs.some((c) => !isIgnorableXChild(c));
|
|
2977
2974
|
function trimEdgeWhite(node) {
|
|
2978
|
-
if (!node.isWhiteSpace
|
|
2975
|
+
if (!node.isWhiteSpace()) return false;
|
|
2979
2976
|
node.condenseWhiteSpace();
|
|
2980
2977
|
return true;
|
|
2981
2978
|
}
|
|
@@ -2986,7 +2983,7 @@ function condenseChildsWhites(childs) {
|
|
|
2986
2983
|
if (last > 0 && trimEdgeWhite(childs[last])) emptied = true;
|
|
2987
2984
|
for (let i = 1; i < last; i++) {
|
|
2988
2985
|
const cur = childs[i];
|
|
2989
|
-
if (!(cur.isWhiteSpace
|
|
2986
|
+
if (!(cur.isWhiteSpace() && cur.hasNewLine())) continue;
|
|
2990
2987
|
const bothBlock = isBlockDomNode(childs[i - 1]) && isBlockDomNode(childs[i + 1]);
|
|
2991
2988
|
cur.condenseWhiteSpace(bothBlock ? "" : " ");
|
|
2992
2989
|
if (bothBlock) emptied = true;
|
|
@@ -2994,12 +2991,12 @@ function condenseChildsWhites(childs) {
|
|
|
2994
2991
|
return emptied ? childs.filter((c) => !isEmptyText(c)) : childs;
|
|
2995
2992
|
}
|
|
2996
2993
|
var View = class {
|
|
2997
|
-
constructor(name, rawView = "No View Defined", style = ""
|
|
2994
|
+
constructor(name, rawView = "No View Defined", style = "") {
|
|
2998
2995
|
this.name = name;
|
|
2999
|
-
this.anode = anode;
|
|
3000
|
-
this.style = style;
|
|
3001
|
-
this.ctx = ctx;
|
|
3002
2996
|
this.rawView = rawView;
|
|
2997
|
+
this.style = style;
|
|
2998
|
+
this.anode = null;
|
|
2999
|
+
this.ctx = null;
|
|
3003
3000
|
}
|
|
3004
3001
|
compile(ctx, scope, cid) {
|
|
3005
3002
|
this.ctx = ctx;
|
|
@@ -3007,7 +3004,7 @@ var View = class {
|
|
|
3007
3004
|
this.anode.setDataAttr("data-cid", cid);
|
|
3008
3005
|
this.anode.setDataAttr("data-vid", this.name);
|
|
3009
3006
|
this.ctx.compile(scope);
|
|
3010
|
-
|
|
3007
|
+
this.anode = optimizeNode(this.anode);
|
|
3011
3008
|
}
|
|
3012
3009
|
render(stack, rx) {
|
|
3013
3010
|
if (this.anode === null) {
|
|
@@ -3032,7 +3029,7 @@ var NodeEvents = class {
|
|
|
3032
3029
|
getHandlersFor(eventName) {
|
|
3033
3030
|
let r = null;
|
|
3034
3031
|
for (const handler of this.handlers)
|
|
3035
|
-
if (handler.
|
|
3032
|
+
if (handler.name === eventName) {
|
|
3036
3033
|
r ??= [];
|
|
3037
3034
|
r.push(handler);
|
|
3038
3035
|
}
|
|
@@ -3046,9 +3043,6 @@ var NodeEvent = class {
|
|
|
3046
3043
|
this.modifierWrapper = compileModifiers(name, modifiers);
|
|
3047
3044
|
this.modifiers = modifiers;
|
|
3048
3045
|
}
|
|
3049
|
-
handlesEventName(name) {
|
|
3050
|
-
return this.name === name;
|
|
3051
|
-
}
|
|
3052
3046
|
getHandlerAndArgs(stack, event) {
|
|
3053
3047
|
const r = this.handlerCall.getHandlerAndArgs(stack, event);
|
|
3054
3048
|
r[0] = this.modifierWrapper(r[0], event);
|
|
@@ -3100,68 +3094,286 @@ function compileModifiers(eventName, names) {
|
|
|
3100
3094
|
};
|
|
3101
3095
|
}
|
|
3102
3096
|
|
|
3103
|
-
// src/
|
|
3104
|
-
var
|
|
3105
|
-
var
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3097
|
+
// src/stack.js
|
|
3098
|
+
var STOP = /* @__PURE__ */ Symbol("STOP");
|
|
3099
|
+
var NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
3100
|
+
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
3101
|
+
var isTypeName = (s) => {
|
|
3102
|
+
const c = s.charCodeAt(0);
|
|
3103
|
+
return c >= 65 && c <= 90;
|
|
3104
|
+
};
|
|
3105
|
+
function lookup(chain, name, dv = null) {
|
|
3106
|
+
let n = chain;
|
|
3107
|
+
while (n !== null) {
|
|
3108
|
+
const r = n[0].lookup(name);
|
|
3109
|
+
if (r === STOP) return dv;
|
|
3110
|
+
if (r !== NEXT) return r;
|
|
3111
|
+
n = n[1];
|
|
3114
3112
|
}
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3113
|
+
return dv;
|
|
3114
|
+
}
|
|
3115
|
+
var BindFrame = class {
|
|
3116
|
+
constructor(it, binds, isFrame) {
|
|
3117
|
+
this.it = it;
|
|
3118
|
+
this.binds = binds;
|
|
3119
|
+
this.isFrame = isFrame;
|
|
3118
3120
|
}
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
+
lookup(name) {
|
|
3122
|
+
const v = this.binds[name];
|
|
3123
|
+
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
3121
3124
|
}
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3125
|
+
};
|
|
3126
|
+
var DynFrame = class {
|
|
3127
|
+
constructor(binds, types) {
|
|
3128
|
+
this.binds = binds;
|
|
3129
|
+
this.types = types;
|
|
3127
3130
|
}
|
|
3128
|
-
|
|
3129
|
-
const
|
|
3130
|
-
|
|
3131
|
-
return styles.join("\n");
|
|
3131
|
+
lookup(name) {
|
|
3132
|
+
const v = (isTypeName(name) ? this.types : this.binds)[name];
|
|
3133
|
+
return v === void 0 ? NEXT : v;
|
|
3132
3134
|
}
|
|
3133
3135
|
};
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
this.macros = {};
|
|
3136
|
+
function computeViewsId(views) {
|
|
3137
|
+
let s = "";
|
|
3138
|
+
let n = views;
|
|
3139
|
+
while (n !== null) {
|
|
3140
|
+
s += n[0];
|
|
3141
|
+
n = n[1];
|
|
3141
3142
|
}
|
|
3142
|
-
|
|
3143
|
-
|
|
3143
|
+
return s === "main" ? "" : s;
|
|
3144
|
+
}
|
|
3145
|
+
var Stack = class _Stack {
|
|
3146
|
+
constructor(fields) {
|
|
3147
|
+
Object.assign(this, fields);
|
|
3144
3148
|
}
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3149
|
+
_with(patch) {
|
|
3150
|
+
return new _Stack({ ...this, ...patch });
|
|
3151
|
+
}
|
|
3152
|
+
// Evaluate every provide the entered component publishes and push them as one
|
|
3153
|
+
// dynBinds frame, keyed by NAME. A value is published together with the absolute
|
|
3154
|
+
// path it lives at: the same declaration is read as `*name` AND resumed at by
|
|
3155
|
+
// `<x render="*name">`, so a consumer needs both halves. Types go in the same
|
|
3156
|
+
// frame's other map. No-op with no provides.
|
|
3157
|
+
_pushProvides() {
|
|
3158
|
+
const comp = this.comps.getCompFor(this.it);
|
|
3159
|
+
if (comp == null) return this;
|
|
3160
|
+
const { provide, provideType } = comp;
|
|
3161
|
+
const binds = {};
|
|
3162
|
+
const types = {};
|
|
3163
|
+
let has2 = false;
|
|
3164
|
+
const base = this._publishBase();
|
|
3165
|
+
for (const k in provide) {
|
|
3166
|
+
const step = provide[k].toPathItem?.() ?? null;
|
|
3167
|
+
if (step === null) continue;
|
|
3168
|
+
const value = provide[k].eval(this);
|
|
3169
|
+
binds[k] = { value, path: base === null ? null : base.concat([step]) };
|
|
3170
|
+
has2 = true;
|
|
3152
3171
|
}
|
|
3153
|
-
for (const
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
if (comp !== void 0) this.byName[alias] = comp;
|
|
3157
|
-
else console.warn("alias", alias, "to inexistent component", aliases[alias]);
|
|
3172
|
+
for (const k in provideType) {
|
|
3173
|
+
types[k] = provideType[k];
|
|
3174
|
+
has2 = true;
|
|
3158
3175
|
}
|
|
3176
|
+
if (!has2) return this;
|
|
3177
|
+
return this._with({ dynBinds: [new DynFrame(binds, types), this.dynBinds] });
|
|
3178
|
+
}
|
|
3179
|
+
// The absolute address of the component being entered, or null when this
|
|
3180
|
+
// position cannot be written down as one. Frame-only steps carry bindings and
|
|
3181
|
+
// address nothing, so they are compacted away first; what is left is checked
|
|
3182
|
+
// against the value actually being rendered, because a scope CAN move the
|
|
3183
|
+
// render position without contributing an addressing step (a plain `@each`
|
|
3184
|
+
// body re-binds `it` to the item while its rebuild step is an identity).
|
|
3185
|
+
//
|
|
3186
|
+
// A null base still publishes the VALUE — `*name` reads it fine — but there is
|
|
3187
|
+
// nowhere to resume, so `<x render="*name">` renders nothing rather than
|
|
3188
|
+
// editing whatever happens to live at the address we guessed.
|
|
3189
|
+
_publishBase() {
|
|
3190
|
+
const base = this.renderPath.toTransactionPath().compact();
|
|
3191
|
+
return base.lookup(this.root, NOT_FOUND) === this.it ? base : null;
|
|
3192
|
+
}
|
|
3193
|
+
static root(comps, it, ctx = null) {
|
|
3194
|
+
return new _Stack({
|
|
3195
|
+
comps,
|
|
3196
|
+
root: it,
|
|
3197
|
+
it,
|
|
3198
|
+
binds: [new BindFrame(it, {}, true), null],
|
|
3199
|
+
dynBinds: [new DynFrame({}, {}), null],
|
|
3200
|
+
views: ["main", null],
|
|
3201
|
+
viewsId: "",
|
|
3202
|
+
renderPath: new DispatchPath(),
|
|
3203
|
+
pendingFrame: false,
|
|
3204
|
+
ctx
|
|
3205
|
+
})._pushProvides();
|
|
3206
|
+
}
|
|
3207
|
+
// `renderPath` defaults to this stack's own: an ordinary scope does not move.
|
|
3208
|
+
// `pendingFrame` clears on a component frame (which emits the base) and is
|
|
3209
|
+
// inherited by transparent scopes, which have to carry it to the next boundary.
|
|
3210
|
+
enter(it, bindings = {}, isFrame = true, renderPath = this.renderPath, pendingFrame = null) {
|
|
3211
|
+
const stack = this._with({
|
|
3212
|
+
it,
|
|
3213
|
+
binds: [new BindFrame(it, bindings, isFrame), this.binds],
|
|
3214
|
+
renderPath,
|
|
3215
|
+
pendingFrame: pendingFrame ?? (isFrame ? false : this.pendingFrame)
|
|
3216
|
+
});
|
|
3217
|
+
return isFrame ? stack._pushProvides() : stack;
|
|
3159
3218
|
}
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3219
|
+
pushViewName(name) {
|
|
3220
|
+
const views = [name, this.views];
|
|
3221
|
+
return this._with({ views, viewsId: computeViewsId(views) });
|
|
3222
|
+
}
|
|
3223
|
+
// Published types are stable per scope and would only churn the render cache, so
|
|
3224
|
+
// the cache key covers values alone.
|
|
3225
|
+
_pushDynBindValuesToArray(arr, comp) {
|
|
3226
|
+
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
3227
|
+
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
3228
|
+
}
|
|
3229
|
+
// `*name`: the nearest binding above (including this component's own provides,
|
|
3230
|
+
// pushed on entering it), else a path registered in the component's lexical
|
|
3231
|
+
// scope, else this component's declared default, else null.
|
|
3232
|
+
//
|
|
3233
|
+
// One chain walk and no producer resolution: a lookup names what it WANTS, so the
|
|
3234
|
+
// frame it wants is keyed by that name. The default belongs to the CONSUMER's
|
|
3235
|
+
// declaration and is evaluated against the consumer's stack, which is why it is
|
|
3236
|
+
// consulted only after the whole chain has missed.
|
|
3237
|
+
lookupDynamicLocated(name) {
|
|
3238
|
+
if (isTypeName(name)) return null;
|
|
3239
|
+
const v = lookup(this.dynBinds, name);
|
|
3240
|
+
if (v != null) return v;
|
|
3241
|
+
const comp = this.comps.getCompFor(this.it);
|
|
3242
|
+
if (comp == null) return null;
|
|
3243
|
+
const path2 = comp.scope?.lookupPath?.(name) ?? null;
|
|
3244
|
+
if (path2 !== null) {
|
|
3245
|
+
const value2 = path2.lookup(this.root, NOT_FOUND);
|
|
3246
|
+
if (value2 !== NOT_FOUND) return { value: value2, path: path2 };
|
|
3247
|
+
}
|
|
3248
|
+
const dval = comp.lookup[name] ?? null;
|
|
3249
|
+
if (dval === null) return null;
|
|
3250
|
+
const step = dval.toPathItem?.() ?? null;
|
|
3251
|
+
const value = dval.eval(this);
|
|
3252
|
+
return step === null ? { value, path: null } : { value, path: this.renderPath.toTransactionPath().concat([step]) };
|
|
3253
|
+
}
|
|
3254
|
+
lookupDynamic(name) {
|
|
3255
|
+
if (isTypeName(name)) return lookup(this.dynBinds, name);
|
|
3256
|
+
return this.lookupDynamicLocated(name)?.value ?? null;
|
|
3257
|
+
}
|
|
3258
|
+
lookupBind(name) {
|
|
3259
|
+
return lookup(this.binds, name);
|
|
3260
|
+
}
|
|
3261
|
+
lookupFieldRaw(name) {
|
|
3262
|
+
return this.it[name] ?? null;
|
|
3263
|
+
}
|
|
3264
|
+
lookupMethod(name) {
|
|
3265
|
+
const fn = this.it[name];
|
|
3266
|
+
return fn instanceof Function ? fn.call(this.it) : null;
|
|
3267
|
+
}
|
|
3268
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
3269
|
+
// `e.<member>` handler args. Null outside a live event transaction (`ctx` is
|
|
3270
|
+
// then a send/intent transaction, which carries no `e`).
|
|
3271
|
+
lookupEvent() {
|
|
3272
|
+
return this.ctx?.e ?? null;
|
|
3273
|
+
}
|
|
3274
|
+
lookupDragInfo() {
|
|
3275
|
+
return this.ctx?.dragInfo ?? null;
|
|
3276
|
+
}
|
|
3277
|
+
getHandlerFor(name, key) {
|
|
3278
|
+
return this.comps.getHandlerFor(this.it, name, key);
|
|
3279
|
+
}
|
|
3280
|
+
lookupBestView(views, defaultViewName) {
|
|
3281
|
+
let n = this.views;
|
|
3282
|
+
while (n !== null) {
|
|
3283
|
+
const view = views[n[0]];
|
|
3284
|
+
if (view !== void 0) return view;
|
|
3285
|
+
n = n[1];
|
|
3286
|
+
}
|
|
3287
|
+
return views[defaultViewName];
|
|
3288
|
+
}
|
|
3289
|
+
};
|
|
3290
|
+
var NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
3291
|
+
|
|
3292
|
+
// src/components.js
|
|
3293
|
+
var COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
3294
|
+
var Components = class {
|
|
3295
|
+
constructor() {
|
|
3296
|
+
this.byId = /* @__PURE__ */ new Map();
|
|
3297
|
+
}
|
|
3298
|
+
registerComponent(Comp) {
|
|
3299
|
+
this.byId.set(Comp.id, Comp);
|
|
3300
|
+
}
|
|
3301
|
+
getComponentForId(id) {
|
|
3302
|
+
return this.byId.get(id) ?? null;
|
|
3303
|
+
}
|
|
3304
|
+
getCompFor(v) {
|
|
3305
|
+
const Comp = v?.constructor;
|
|
3306
|
+
return Comp?.[COMPONENT] ? Comp : null;
|
|
3307
|
+
}
|
|
3308
|
+
getHandlerFor(v, name, key) {
|
|
3309
|
+
return this.getCompFor(v)?.[key][name] ?? null;
|
|
3310
|
+
}
|
|
3311
|
+
// The `lex` leg of an intent's route: the handlers registered on the scope chain of
|
|
3312
|
+
// the component that raised it, innermost first. A list, not a first match — see
|
|
3313
|
+
// ComponentStack.lookupIntentChain.
|
|
3314
|
+
getIntentChainFor(v, name) {
|
|
3315
|
+
return this.getCompFor(v)?.scope.lookupIntentChain(name) ?? [];
|
|
3316
|
+
}
|
|
3317
|
+
compileStyles() {
|
|
3318
|
+
const styles = [];
|
|
3319
|
+
for (const Comp of this.byId.values()) styles.push(Comp.compileStyle());
|
|
3320
|
+
return styles.join("\n");
|
|
3321
|
+
}
|
|
3322
|
+
};
|
|
3323
|
+
var ComponentStack = class _ComponentStack {
|
|
3324
|
+
constructor(comps = new Components(), parent = null) {
|
|
3325
|
+
this.comps = comps;
|
|
3326
|
+
this.parent = parent;
|
|
3327
|
+
this.byName = {};
|
|
3328
|
+
this.intentsByName = {};
|
|
3329
|
+
this.macros = {};
|
|
3330
|
+
this.paths = {};
|
|
3331
|
+
}
|
|
3332
|
+
enter() {
|
|
3333
|
+
return new _ComponentStack(this.comps, this);
|
|
3334
|
+
}
|
|
3335
|
+
registerComponents(comps, opts) {
|
|
3336
|
+
const { aliases = {}, paths } = opts ?? {};
|
|
3337
|
+
if (paths) this.registerPaths(paths);
|
|
3338
|
+
for (let i = 0; i < comps.length; i++) {
|
|
3339
|
+
const Comp = comps[i];
|
|
3340
|
+
Comp.scope = this.enter();
|
|
3341
|
+
this.comps.registerComponent(Comp);
|
|
3342
|
+
this.byName[Comp.name] = Comp;
|
|
3343
|
+
}
|
|
3344
|
+
for (const alias in aliases) {
|
|
3345
|
+
const comp = this.byName[aliases[alias]];
|
|
3346
|
+
console.assert(this.byName[alias] === void 0, "alias overrides component", alias);
|
|
3347
|
+
if (comp !== void 0) this.byName[alias] = comp;
|
|
3348
|
+
else console.warn("alias", alias, "to inexistent component", aliases[alias]);
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
// Register lowercase names as absolute paths from the app state root. A
|
|
3352
|
+
// descendant that declares one in its `lookup` reads and renders `*name` without
|
|
3353
|
+
// anything above it publishing one — which is what makes a session, a theme or a
|
|
3354
|
+
// host-owned value available in its natural registration scope, instead of forcing
|
|
3355
|
+
// an application root whose only job is to `provide` it. Register on a nested
|
|
3356
|
+
// scope to narrow a name; nearest registration wins.
|
|
3357
|
+
//
|
|
3358
|
+
// Uppercase names are ignored: a component TYPE is what `lookupComponent` already
|
|
3359
|
+
// answers, and a type has no path.
|
|
3360
|
+
registerPaths(paths) {
|
|
3361
|
+
for (const name in paths) {
|
|
3362
|
+
if (isTypeName(name)) {
|
|
3363
|
+
console.warn("registerPaths: a type name has no path", name);
|
|
3364
|
+
continue;
|
|
3365
|
+
}
|
|
3366
|
+
this.paths[name] = paths[name].toPath();
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
lookupPath(name) {
|
|
3370
|
+
return this.paths[name] ?? this.parent?.lookupPath(name) ?? null;
|
|
3371
|
+
}
|
|
3372
|
+
registerMacros(macros) {
|
|
3373
|
+
for (const key in macros) {
|
|
3374
|
+
const lower = key.toLowerCase();
|
|
3375
|
+
console.assert(this.macros[lower] === void 0, "macro key collision", lower);
|
|
3376
|
+
this.macros[lower] = macros[key];
|
|
3165
3377
|
}
|
|
3166
3378
|
}
|
|
3167
3379
|
getCompFor(v) {
|
|
@@ -3188,97 +3400,82 @@ var ComponentStack = class _ComponentStack {
|
|
|
3188
3400
|
lookupComponent(name) {
|
|
3189
3401
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
3190
3402
|
}
|
|
3191
|
-
//
|
|
3192
|
-
// names
|
|
3193
|
-
//
|
|
3194
|
-
//
|
|
3195
|
-
//
|
|
3196
|
-
|
|
3403
|
+
// Whether anything in this scope chain provides `name`. Existence only: a lookup
|
|
3404
|
+
// names what it WANTS and takes whoever is nearest above it at render time, so
|
|
3405
|
+
// there is no producer to identify — several components may publish one name and
|
|
3406
|
+
// the live render ancestry decides. Used by the linter to tell a lookup that can
|
|
3407
|
+
// be satisfied from one that never will be.
|
|
3408
|
+
hasProvider(name) {
|
|
3197
3409
|
for (const compName in this.byName) {
|
|
3198
|
-
|
|
3199
|
-
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
3410
|
+
if (this.byName[compName].provide?.[name] !== void 0) return true;
|
|
3200
3411
|
}
|
|
3201
|
-
return this.parent?.
|
|
3412
|
+
return this.parent?.hasProvider(name) ?? false;
|
|
3202
3413
|
}
|
|
3203
3414
|
lookupMacro(name) {
|
|
3204
3415
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
3205
3416
|
}
|
|
3206
3417
|
};
|
|
3207
|
-
var ProvideInfo = class {
|
|
3208
|
-
constructor(val) {
|
|
3209
|
-
this.val = val;
|
|
3210
|
-
}
|
|
3211
|
-
};
|
|
3212
|
-
var LookupInfo = class {
|
|
3213
|
-
constructor(val) {
|
|
3214
|
-
this.val = val;
|
|
3215
|
-
}
|
|
3216
|
-
};
|
|
3217
3418
|
var isString = (v) => typeof v === "string";
|
|
3218
|
-
var isTypeName = (s) => {
|
|
3219
|
-
const c = s.charCodeAt(0);
|
|
3220
|
-
return c >= 65 && c <= 90;
|
|
3221
|
-
};
|
|
3222
3419
|
var _rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
3223
3420
|
var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
3224
3421
|
var _compId = 0;
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3422
|
+
function initComponent(Class, o) {
|
|
3423
|
+
Class[COMPONENT] = Class;
|
|
3424
|
+
Class.id = _compId++;
|
|
3425
|
+
Class.views = { main: new View("main", o.view, o.style) };
|
|
3426
|
+
Class.commonStyle = o.commonStyle ?? "";
|
|
3427
|
+
Class.globalStyle = o.globalStyle ?? "";
|
|
3428
|
+
Class.receive = o.receive ?? {};
|
|
3429
|
+
Class.intent = o.intent ?? {};
|
|
3430
|
+
Class.alter = o.alter ?? {};
|
|
3431
|
+
for (const name in o.views ?? {}) {
|
|
3432
|
+
const v = o.views[name];
|
|
3433
|
+
const { view, style } = isString(v) ? { view: v } : v;
|
|
3434
|
+
Class.views[name] = new View(name, view, style);
|
|
3435
|
+
}
|
|
3436
|
+
Class._rawProvide = o.provide ?? {};
|
|
3437
|
+
Class._rawLookup = o.lookup ?? [];
|
|
3438
|
+
Class.provide = {};
|
|
3439
|
+
Class.provideType = {};
|
|
3440
|
+
Class.lookup = {};
|
|
3441
|
+
Class.scope = null;
|
|
3442
|
+
Class.spec = o;
|
|
3443
|
+
Class.extra = {};
|
|
3444
|
+
for (const key of Object.keys(o)) if (!KNOWN_SPEC_KEYS.has(key)) Class.extra[key] = o[key];
|
|
3445
|
+
return Object.assign(Class, COMPONENT_METHODS);
|
|
3446
|
+
}
|
|
3447
|
+
var COMPONENT_METHODS = {
|
|
3251
3448
|
compile(ParseContext2) {
|
|
3252
3449
|
for (const name in this.views)
|
|
3253
3450
|
this.views[name].compile(new ParseContext2(), this.scope, this.id);
|
|
3254
3451
|
const ctx = this.views.main.ctx;
|
|
3255
3452
|
for (const key in this._rawProvide) {
|
|
3256
3453
|
if (isTypeName(key)) {
|
|
3257
|
-
if (this._rawProvide[key] === "self") this.provideType[key] = this
|
|
3454
|
+
if (this._rawProvide[key] === "self") this.provideType[key] = this;
|
|
3258
3455
|
continue;
|
|
3259
3456
|
}
|
|
3260
3457
|
const val = parseProvide(this._rawProvide[key], ctx);
|
|
3261
|
-
if (val) this.provide[key] =
|
|
3458
|
+
if (val) this.provide[key] = val;
|
|
3262
3459
|
}
|
|
3263
3460
|
for (const entry of this._rawLookup) {
|
|
3264
3461
|
const name = isString(entry) ? entry : isString(entry?.name) ? entry.name : null;
|
|
3265
3462
|
if (name === null) continue;
|
|
3266
3463
|
const defStr = isString(entry?.default) ? entry.default : null;
|
|
3267
|
-
this.lookup[name] =
|
|
3464
|
+
this.lookup[name] = defStr === null ? null : parseField(defStr, ctx);
|
|
3268
3465
|
}
|
|
3269
3466
|
for (const key in this.lookup)
|
|
3270
3467
|
if (this.provide[key] !== void 0)
|
|
3271
3468
|
console.warn("name declared in both provide and lookup", this.name, key);
|
|
3272
|
-
}
|
|
3469
|
+
},
|
|
3273
3470
|
getView(name) {
|
|
3274
3471
|
return this.views[name] ?? this.views.main;
|
|
3275
|
-
}
|
|
3276
|
-
getEventForId(id,
|
|
3277
|
-
return this.getView(
|
|
3278
|
-
}
|
|
3279
|
-
getNodeForId(id,
|
|
3280
|
-
return this.getView(
|
|
3281
|
-
}
|
|
3472
|
+
},
|
|
3473
|
+
getEventForId(id, viewName) {
|
|
3474
|
+
return this.getView(viewName).ctx.getEventForId(id);
|
|
3475
|
+
},
|
|
3476
|
+
getNodeForId(id, viewName) {
|
|
3477
|
+
return this.getView(viewName).ctx.getNodeForId(id);
|
|
3478
|
+
},
|
|
3282
3479
|
compileStyle() {
|
|
3283
3480
|
const { id, commonStyle, globalStyle, views } = this;
|
|
3284
3481
|
const styles = commonStyle ? [`[data-cid="${id}"]{${commonStyle}}`] : [];
|
|
@@ -3291,170 +3488,38 @@ var Component = class {
|
|
|
3291
3488
|
}
|
|
3292
3489
|
};
|
|
3293
3490
|
|
|
3294
|
-
// src/
|
|
3295
|
-
var
|
|
3296
|
-
var
|
|
3297
|
-
var
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
if (leg === "dyn") {
|
|
3302
|
-
const v = dyn();
|
|
3303
|
-
if (v != null) return v;
|
|
3304
|
-
} else if (leg === "lex") {
|
|
3305
|
-
const v = lex();
|
|
3306
|
-
if (v != null) return v;
|
|
3307
|
-
} else {
|
|
3308
|
-
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
3309
|
-
}
|
|
3310
|
-
}
|
|
3491
|
+
// src/oo.js
|
|
3492
|
+
var BAD_VALUE = /* @__PURE__ */ Symbol("BadValue");
|
|
3493
|
+
var COERCE_NONE = (_v) => null;
|
|
3494
|
+
var COERCE_MAP = (v) => {
|
|
3495
|
+
if (v instanceof Map) return new Map(v);
|
|
3496
|
+
if (Array.isArray(v) || isPlainObject(v))
|
|
3497
|
+
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
3311
3498
|
return null;
|
|
3312
|
-
}
|
|
3313
|
-
function lookup(chain, name, dv = null) {
|
|
3314
|
-
let n = chain;
|
|
3315
|
-
while (n !== null) {
|
|
3316
|
-
const r = n[0].lookup(name);
|
|
3317
|
-
if (r === STOP) return dv;
|
|
3318
|
-
if (r !== NEXT) return r;
|
|
3319
|
-
n = n[1];
|
|
3320
|
-
}
|
|
3321
|
-
return dv;
|
|
3322
|
-
}
|
|
3323
|
-
var BindFrame = class {
|
|
3324
|
-
constructor(it, binds, isFrame) {
|
|
3325
|
-
this.it = it;
|
|
3326
|
-
this.binds = binds;
|
|
3327
|
-
this.isFrame = isFrame;
|
|
3328
|
-
}
|
|
3329
|
-
lookup(name) {
|
|
3330
|
-
const v = this.binds[name];
|
|
3331
|
-
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
3332
|
-
}
|
|
3333
3499
|
};
|
|
3334
|
-
var
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
}
|
|
3500
|
+
var FIELD_TYPES = {
|
|
3501
|
+
any: [(_v) => true, COERCE_NONE, () => null],
|
|
3502
|
+
text: [(v) => typeof v === "string", (v) => v?.toString?.() ?? "", () => ""],
|
|
3503
|
+
int: [Number.isInteger, (v) => Number.isFinite(v) ? Math.trunc(v) : null, () => 0],
|
|
3504
|
+
float: [Number.isFinite, COERCE_NONE, () => 0],
|
|
3505
|
+
bool: [(v) => typeof v === "boolean", (v) => !!v, () => false],
|
|
3506
|
+
list: [Array.isArray, (v) => Array.isArray(v) ? [...v] : null, () => []],
|
|
3507
|
+
object: [isPlainObject, (v) => isPlainObject(v) ? { ...v } : null, () => ({})],
|
|
3508
|
+
map: [(v) => v instanceof Map, COERCE_MAP, () => /* @__PURE__ */ new Map()],
|
|
3509
|
+
set: [
|
|
3510
|
+
(v) => v instanceof Set,
|
|
3511
|
+
(v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null,
|
|
3512
|
+
() => /* @__PURE__ */ new Set()
|
|
3513
|
+
]
|
|
3342
3514
|
};
|
|
3343
|
-
function computeViewsId(views) {
|
|
3344
|
-
let s = "";
|
|
3345
|
-
let n = views;
|
|
3346
|
-
while (n !== null) {
|
|
3347
|
-
s += n[0];
|
|
3348
|
-
n = n[1];
|
|
3349
|
-
}
|
|
3350
|
-
return s === "main" ? "" : s;
|
|
3351
|
-
}
|
|
3352
|
-
var Stack = class _Stack {
|
|
3353
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
3354
|
-
this.comps = comps;
|
|
3355
|
-
this.it = it;
|
|
3356
|
-
this.binds = binds;
|
|
3357
|
-
this.dynBinds = dynBinds;
|
|
3358
|
-
this.views = views;
|
|
3359
|
-
this.viewsId = viewsId;
|
|
3360
|
-
this.ctx = ctx;
|
|
3361
|
-
}
|
|
3362
|
-
// Evaluate every provide the entered component publishes and push them as one
|
|
3363
|
-
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
3364
|
-
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
3365
|
-
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
3366
|
-
_pushProvides() {
|
|
3367
|
-
const comp = this.comps.getCompFor(this.it);
|
|
3368
|
-
if (comp == null) return this;
|
|
3369
|
-
const { provide, provideType } = comp;
|
|
3370
|
-
const dynObj = {};
|
|
3371
|
-
let has2 = false;
|
|
3372
|
-
for (const k in provide) {
|
|
3373
|
-
dynObj[k] = provide[k].val.eval(this);
|
|
3374
|
-
has2 = true;
|
|
3375
|
-
}
|
|
3376
|
-
for (const k in provideType) {
|
|
3377
|
-
dynObj[k] = provideType[k];
|
|
3378
|
-
has2 = true;
|
|
3379
|
-
}
|
|
3380
|
-
if (!has2) return this;
|
|
3381
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
3382
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
3383
|
-
return new _Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
3384
|
-
}
|
|
3385
|
-
static root(comps, it, ctx) {
|
|
3386
|
-
const binds = [new BindFrame(it, {}, true), null];
|
|
3387
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
3388
|
-
const views = ["main", null];
|
|
3389
|
-
return new _Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
3390
|
-
}
|
|
3391
|
-
enter(it, bindings = {}, isFrame = true) {
|
|
3392
|
-
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
3393
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
3394
|
-
const stack = new _Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
3395
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
3396
|
-
}
|
|
3397
|
-
pushViewName(name) {
|
|
3398
|
-
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
3399
|
-
const newViews = [name, views];
|
|
3400
|
-
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
3401
|
-
}
|
|
3402
|
-
// Published types are stable per scope and would only churn the render cache, so
|
|
3403
|
-
// the cache key covers values alone.
|
|
3404
|
-
_pushDynBindValuesToArray(arr, comp) {
|
|
3405
|
-
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
3406
|
-
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
3407
|
-
}
|
|
3408
|
-
// `*name`: the nearest binding above (including this component's own provides,
|
|
3409
|
-
// pushed on entering it), else this component's declared default, else null.
|
|
3410
|
-
lookupDynamic(name) {
|
|
3411
|
-
const v = lookup(this.dynBinds, name);
|
|
3412
|
-
if (v != null) return v;
|
|
3413
|
-
const comp = this.comps.getCompFor(this.it);
|
|
3414
|
-
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
3415
|
-
}
|
|
3416
|
-
lookupBind(name) {
|
|
3417
|
-
return lookup(this.binds, name);
|
|
3418
|
-
}
|
|
3419
|
-
lookupFieldRaw(name) {
|
|
3420
|
-
return this.it[name] ?? null;
|
|
3421
|
-
}
|
|
3422
|
-
lookupMethod(name) {
|
|
3423
|
-
const fn = this.it[name];
|
|
3424
|
-
return fn instanceof Function ? fn.call(this.it) : null;
|
|
3425
|
-
}
|
|
3426
|
-
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
3427
|
-
// `e.<member>` handler args. Null outside a live event transaction.
|
|
3428
|
-
lookupEvent() {
|
|
3429
|
-
return this.ctx?.event ?? null;
|
|
3430
|
-
}
|
|
3431
|
-
lookupDragInfo() {
|
|
3432
|
-
return this.ctx?.dragInfo ?? null;
|
|
3433
|
-
}
|
|
3434
|
-
getHandlerFor(name, key) {
|
|
3435
|
-
return this.comps.getHandlerFor(this.it, name, key);
|
|
3436
|
-
}
|
|
3437
|
-
lookupBestView(views, defaultViewName) {
|
|
3438
|
-
let n = this.views;
|
|
3439
|
-
while (n !== null) {
|
|
3440
|
-
const view = views[n[0]];
|
|
3441
|
-
if (view !== void 0) return view;
|
|
3442
|
-
n = n[1];
|
|
3443
|
-
}
|
|
3444
|
-
return views[defaultViewName];
|
|
3445
|
-
}
|
|
3446
|
-
};
|
|
3447
|
-
|
|
3448
|
-
// src/oo.js
|
|
3449
|
-
var BAD_VALUE = /* @__PURE__ */ Symbol("BadValue");
|
|
3450
|
-
var nullCoercer = (v) => v;
|
|
3451
3515
|
var Field = class {
|
|
3452
|
-
|
|
3516
|
+
// `type` names an entry of FIELD_TYPES; `defaultValue` falls back to the type's own.
|
|
3517
|
+
constructor(type, name, defaultValue, [typeCheck, coercer, makeDefault] = FIELD_TYPES[type]) {
|
|
3453
3518
|
this.type = type;
|
|
3454
3519
|
this.name = name;
|
|
3455
3520
|
this.typeCheck = typeCheck;
|
|
3456
3521
|
this.coercer = coercer;
|
|
3457
|
-
this.defaultValue = defaultValue;
|
|
3522
|
+
this.defaultValue = defaultValue === void 0 ? makeDefault() : defaultValue;
|
|
3458
3523
|
}
|
|
3459
3524
|
isValid(v) {
|
|
3460
3525
|
return this.typeCheck(v);
|
|
@@ -3468,81 +3533,14 @@ var Field = class {
|
|
|
3468
3533
|
return this.coerceOr(v, this.defaultValue);
|
|
3469
3534
|
}
|
|
3470
3535
|
};
|
|
3471
|
-
var
|
|
3472
|
-
var CHECK_TYPE_INT = Number.isInteger;
|
|
3473
|
-
var CHECK_TYPE_FLOAT = Number.isFinite;
|
|
3474
|
-
var CHECK_TYPE_BOOL = (v) => typeof v === "boolean";
|
|
3475
|
-
var CHECK_TYPE_STRING = (v) => typeof v === "string";
|
|
3476
|
-
var CHECK_TYPE_LIST = Array.isArray;
|
|
3477
|
-
var CHECK_TYPE_OBJECT = isPlainObject;
|
|
3478
|
-
var CHECK_TYPE_MAP = (v) => v instanceof Map;
|
|
3479
|
-
var CHECK_TYPE_SET = (v) => v instanceof Set;
|
|
3480
|
-
var COERCE_NONE = (_v) => null;
|
|
3481
|
-
var COERCE_BOOL = (v) => !!v;
|
|
3482
|
-
var COERCE_STRING = (v) => v?.toString?.() ?? "";
|
|
3483
|
-
var COERCE_INT = (v) => Number.isFinite(v) ? Math.trunc(v) : null;
|
|
3484
|
-
var COERCE_LIST = (v) => Array.isArray(v) ? [...v] : null;
|
|
3485
|
-
var COERCE_OBJECT = (v) => isPlainObject(v) ? { ...v } : null;
|
|
3486
|
-
var COERCE_MAP = (v) => {
|
|
3487
|
-
if (v instanceof Map) return new Map(v);
|
|
3488
|
-
if (Array.isArray(v) || isPlainObject(v))
|
|
3489
|
-
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
3490
|
-
return null;
|
|
3491
|
-
};
|
|
3492
|
-
var COERCE_SET = (v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null;
|
|
3493
|
-
var FieldBool = class extends Field {
|
|
3494
|
-
constructor(name, defaultValue = false) {
|
|
3495
|
-
super("bool", name, CHECK_TYPE_BOOL, COERCE_BOOL, defaultValue);
|
|
3496
|
-
}
|
|
3497
|
-
};
|
|
3498
|
-
var FieldAny = class extends Field {
|
|
3499
|
-
constructor(name, defaultValue = null) {
|
|
3500
|
-
super("any", name, CHECK_TYPE_ANY, nullCoercer, defaultValue);
|
|
3501
|
-
}
|
|
3502
|
-
};
|
|
3503
|
-
var FieldString = class extends Field {
|
|
3504
|
-
constructor(name, defaultValue = "") {
|
|
3505
|
-
super("text", name, CHECK_TYPE_STRING, COERCE_STRING, defaultValue);
|
|
3506
|
-
}
|
|
3507
|
-
};
|
|
3508
|
-
var FieldInt = class extends Field {
|
|
3509
|
-
constructor(name, defaultValue = 0) {
|
|
3510
|
-
super("int", name, CHECK_TYPE_INT, COERCE_INT, defaultValue);
|
|
3511
|
-
}
|
|
3512
|
-
};
|
|
3513
|
-
var FieldFloat = class extends Field {
|
|
3514
|
-
constructor(name, defaultValue = 0) {
|
|
3515
|
-
super("float", name, CHECK_TYPE_FLOAT, COERCE_NONE, defaultValue);
|
|
3516
|
-
}
|
|
3517
|
-
};
|
|
3518
|
-
var metaOf = (v) => v?.constructor?.[COMPONENT] ?? v?.constructor?.getMetaClass?.();
|
|
3536
|
+
var metaOf = (v) => v?.constructor?.getMetaClass?.();
|
|
3519
3537
|
var getTypeName = (v) => metaOf(v)?.name ?? null;
|
|
3520
3538
|
var FieldComp = class extends Field {
|
|
3521
3539
|
constructor(type, name, args) {
|
|
3522
|
-
super(type, name, (v) => getTypeName(v) === type,
|
|
3540
|
+
super(type, name, null, [(v) => getTypeName(v) === type, COERCE_NONE, () => null]);
|
|
3523
3541
|
this.args = args;
|
|
3524
3542
|
}
|
|
3525
3543
|
};
|
|
3526
|
-
var FieldList = class extends Field {
|
|
3527
|
-
constructor(name, defaultValue = []) {
|
|
3528
|
-
super("list", name, CHECK_TYPE_LIST, COERCE_LIST, defaultValue);
|
|
3529
|
-
}
|
|
3530
|
-
};
|
|
3531
|
-
var FieldObject = class extends Field {
|
|
3532
|
-
constructor(name, defaultValue = {}) {
|
|
3533
|
-
super("object", name, CHECK_TYPE_OBJECT, COERCE_OBJECT, defaultValue);
|
|
3534
|
-
}
|
|
3535
|
-
};
|
|
3536
|
-
var FieldMap = class extends Field {
|
|
3537
|
-
constructor(name, defaultValue = /* @__PURE__ */ new Map()) {
|
|
3538
|
-
super("map", name, CHECK_TYPE_MAP, COERCE_MAP, defaultValue);
|
|
3539
|
-
}
|
|
3540
|
-
};
|
|
3541
|
-
var FieldSet = class extends Field {
|
|
3542
|
-
constructor(name, defaultValue = /* @__PURE__ */ new Set()) {
|
|
3543
|
-
super("set", name, CHECK_TYPE_SET, COERCE_SET, defaultValue);
|
|
3544
|
-
}
|
|
3545
|
-
};
|
|
3546
3544
|
function mkCompField(field, scope, args) {
|
|
3547
3545
|
const Comp = scope?.lookupComponent(field.type) ?? null;
|
|
3548
3546
|
if (Comp === null)
|
|
@@ -3551,112 +3549,66 @@ function mkCompField(field, scope, args) {
|
|
|
3551
3549
|
);
|
|
3552
3550
|
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
3553
3551
|
}
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
const
|
|
3564
|
-
const
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
}
|
|
3572
|
-
}
|
|
3573
|
-
}[name];
|
|
3574
|
-
Class[DRAFTABLE] = true;
|
|
3575
|
-
Object.assign(Class.prototype, _methods);
|
|
3576
|
-
const metaClass = { fields, name, methods: _methods };
|
|
3577
|
-
Object.assign(
|
|
3578
|
-
Class,
|
|
3579
|
-
{
|
|
3580
|
-
getMetaClass: () => metaClass,
|
|
3581
|
-
make(inArgs = {}, opts = {}) {
|
|
3582
|
-
const args = {};
|
|
3583
|
-
const scope = opts.scope ?? this[COMPONENT]?.scope ?? this.scope;
|
|
3584
|
-
for (const key in inArgs) {
|
|
3585
|
-
const field = fields[key];
|
|
3586
|
-
if (compFields.has(key)) args[key] = mkCompField(field, scope, inArgs[key]);
|
|
3587
|
-
else if (field === void 0)
|
|
3588
|
-
console.warn("extra argument to constructor:", name, key, inArgs);
|
|
3589
|
-
else args[key] = field.coerceOrDefault(inArgs[key]);
|
|
3590
|
-
}
|
|
3591
|
-
for (const key of compFields)
|
|
3592
|
-
if (args[key] === void 0) args[key] = mkCompField(fields[key], scope, inArgs[key]);
|
|
3593
|
-
return freeze(new this(args), true);
|
|
3594
|
-
}
|
|
3595
|
-
},
|
|
3596
|
-
this._statics
|
|
3597
|
-
);
|
|
3598
|
-
return Class;
|
|
3599
|
-
}
|
|
3600
|
-
methods(proto) {
|
|
3601
|
-
for (const k in proto) this._methods[k] = proto[k];
|
|
3602
|
-
}
|
|
3603
|
-
statics(proto) {
|
|
3604
|
-
for (const k in proto) this._statics[k] = proto[k];
|
|
3605
|
-
}
|
|
3606
|
-
addField(name, dval, FieldCls) {
|
|
3607
|
-
const field = new FieldCls(name, dval);
|
|
3608
|
-
this.fields[name] = field;
|
|
3609
|
-
return field;
|
|
3610
|
-
}
|
|
3611
|
-
addCompField(name, type, args) {
|
|
3612
|
-
const field = new FieldComp(type, name, args);
|
|
3613
|
-
this.compFields.add(name);
|
|
3614
|
-
this.fields[name] = field;
|
|
3615
|
-
return field;
|
|
3616
|
-
}
|
|
3617
|
-
};
|
|
3618
|
-
var FIELD_CLASS = /* @__PURE__ */ Symbol.for("tutuca.fieldClass");
|
|
3619
|
-
var fieldsByTypeName = {
|
|
3620
|
-
text: FieldString,
|
|
3621
|
-
int: FieldInt,
|
|
3622
|
-
float: FieldFloat,
|
|
3623
|
-
bool: FieldBool,
|
|
3624
|
-
list: FieldList,
|
|
3625
|
-
object: FieldObject,
|
|
3626
|
-
map: FieldMap,
|
|
3627
|
-
set: FieldSet,
|
|
3628
|
-
any: FieldAny
|
|
3629
|
-
};
|
|
3630
|
-
function fieldFromDescriptor(name, value) {
|
|
3631
|
-
const FieldCls = fieldsByTypeName[value.type] ?? FieldAny;
|
|
3632
|
-
const probe = new FieldCls(name);
|
|
3633
|
-
return [FieldCls, probe.coerceOr(value.defaultValue, probe.defaultValue)];
|
|
3552
|
+
function fieldFromSpec(name, value) {
|
|
3553
|
+
const type = typeof value;
|
|
3554
|
+
if (type === "string") return new Field("text", name, value);
|
|
3555
|
+
if (type === "number") return new Field("float", name, value);
|
|
3556
|
+
if (type === "boolean") return new Field("bool", name, value);
|
|
3557
|
+
if (Array.isArray(value)) return new Field("list", name, [...value]);
|
|
3558
|
+
if (value instanceof Set) return new Field("set", name, new Set(value));
|
|
3559
|
+
if (value instanceof Map) return new Field("map", name, new Map(value));
|
|
3560
|
+
if (value?.type && Object.hasOwn(value, "defaultValue")) {
|
|
3561
|
+
const t = value.type in FIELD_TYPES ? value.type : "any";
|
|
3562
|
+
const probe = new Field(t, name);
|
|
3563
|
+
return new Field(t, name, probe.coerceOr(value.defaultValue, probe.defaultValue));
|
|
3564
|
+
}
|
|
3565
|
+
if (value?.component && value?.args !== void 0)
|
|
3566
|
+
return new FieldComp(value.component, name, value.args);
|
|
3567
|
+
if (isPlainObject(value)) return new Field("object", name, { ...value });
|
|
3568
|
+
return new Field("any", name, value);
|
|
3634
3569
|
}
|
|
3635
|
-
function classFromData(name, { fields = {}, methods, statics }) {
|
|
3636
|
-
const
|
|
3637
|
-
for (const
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
else if (value?.type && Object.hasOwn(value, "defaultValue")) {
|
|
3647
|
-
const [FieldCls, dval] = fieldFromDescriptor(field, value);
|
|
3648
|
-
b.addField(field, dval, FieldCls);
|
|
3649
|
-
} else if (value?.component && value?.args !== void 0)
|
|
3650
|
-
b.addCompField(field, value.component, value.args);
|
|
3651
|
-
else if (isPlainObject(value)) b.addField(field, { ...value }, FieldObject);
|
|
3652
|
-
else {
|
|
3653
|
-
const FieldCls = value?.[FIELD_CLASS] ?? FieldAny;
|
|
3654
|
-
b.addField(field, value, FieldCls);
|
|
3570
|
+
function classFromData(name, { fields: spec = {}, methods = {}, statics = {} }) {
|
|
3571
|
+
const fields = {};
|
|
3572
|
+
for (const key in spec) fields[key] = fieldFromSpec(key, spec[key]);
|
|
3573
|
+
const defaults = Object.fromEntries(
|
|
3574
|
+
Object.entries(fields).map(([key, field]) => [key, field.defaultValue])
|
|
3575
|
+
);
|
|
3576
|
+
const Class = {
|
|
3577
|
+
[name]: class {
|
|
3578
|
+
constructor(values = {}) {
|
|
3579
|
+
Object.assign(this, defaults, values);
|
|
3580
|
+
}
|
|
3655
3581
|
}
|
|
3656
|
-
}
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3582
|
+
}[name];
|
|
3583
|
+
Class[DRAFTABLE] = true;
|
|
3584
|
+
Object.assign(Class.prototype, methods);
|
|
3585
|
+
Object.assign(
|
|
3586
|
+
Class,
|
|
3587
|
+
{
|
|
3588
|
+
fields,
|
|
3589
|
+
methods,
|
|
3590
|
+
// The documented way for instance code to reach its class's fields
|
|
3591
|
+
// (`this.constructor.getMetaClass().fields.x.defaultValue`).
|
|
3592
|
+
getMetaClass: () => Class,
|
|
3593
|
+
make(inArgs = {}, opts = {}) {
|
|
3594
|
+
const args = {};
|
|
3595
|
+
const scope = opts.scope ?? this.scope;
|
|
3596
|
+
for (const key in inArgs) {
|
|
3597
|
+
const field = fields[key];
|
|
3598
|
+
if (field === void 0)
|
|
3599
|
+
console.warn("extra argument to constructor:", name, key, inArgs);
|
|
3600
|
+
else if (field instanceof FieldComp) args[key] = mkCompField(field, scope, inArgs[key]);
|
|
3601
|
+
else args[key] = field.coerceOrDefault(inArgs[key]);
|
|
3602
|
+
}
|
|
3603
|
+
for (const key in fields)
|
|
3604
|
+
if (fields[key] instanceof FieldComp && args[key] === void 0)
|
|
3605
|
+
args[key] = mkCompField(fields[key], scope, void 0);
|
|
3606
|
+
return freeze(new this(args), true);
|
|
3607
|
+
}
|
|
3608
|
+
},
|
|
3609
|
+
statics
|
|
3610
|
+
);
|
|
3611
|
+
return Class;
|
|
3660
3612
|
}
|
|
3661
3613
|
function validateDraftFields(current2, draft) {
|
|
3662
3614
|
const meta = metaOf(current2);
|
|
@@ -3672,14 +3624,11 @@ function validateDraftFields(current2, draft) {
|
|
|
3672
3624
|
}
|
|
3673
3625
|
}
|
|
3674
3626
|
}
|
|
3675
|
-
var META_KEYS = "name id fields methods views receive intent alter provide provideType lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
|
|
3676
|
-
" "
|
|
3677
|
-
);
|
|
3678
3627
|
var RESERVED_COMPONENT_STATICS = /* @__PURE__ */ new Set([
|
|
3679
|
-
...
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
...Object.
|
|
3628
|
+
..."name id fields methods views receive intent alter provide provideType lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup make getMetaClass".split(
|
|
3629
|
+
" "
|
|
3630
|
+
),
|
|
3631
|
+
...Object.keys(COMPONENT_METHODS)
|
|
3683
3632
|
]);
|
|
3684
3633
|
function assertNoReservedComponentStatics(statics = {}) {
|
|
3685
3634
|
for (const name in statics) {
|
|
@@ -3688,32 +3637,10 @@ function assertNoReservedComponentStatics(statics = {}) {
|
|
|
3688
3637
|
}
|
|
3689
3638
|
}
|
|
3690
3639
|
}
|
|
3691
|
-
|
|
3640
|
+
function component(opts) {
|
|
3692
3641
|
assertNoReservedComponentStatics(opts.statics);
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
const metaClass = Class.getMetaClass();
|
|
3696
|
-
comp.fields = metaClass.fields;
|
|
3697
|
-
comp.methods = metaClass.methods;
|
|
3698
|
-
Class.getMetaClass = () => comp;
|
|
3699
|
-
Class[COMPONENT] = comp;
|
|
3700
|
-
for (const key of META_KEYS)
|
|
3701
|
-
if (!Object.hasOwn(Class, key))
|
|
3702
|
-
Object.defineProperty(Class, key, {
|
|
3703
|
-
get() {
|
|
3704
|
-
return comp[key];
|
|
3705
|
-
},
|
|
3706
|
-
set(v) {
|
|
3707
|
-
comp[key] = v;
|
|
3708
|
-
},
|
|
3709
|
-
configurable: true
|
|
3710
|
-
});
|
|
3711
|
-
for (const key of Object.getOwnPropertyNames(Component.prototype))
|
|
3712
|
-
if (key !== "constructor" && !Object.hasOwn(Class, key))
|
|
3713
|
-
Class[key] = (...args) => comp[key](...args);
|
|
3714
|
-
return Class;
|
|
3715
|
-
};
|
|
3716
|
-
var component = (opts) => Component.fromSpec(opts);
|
|
3642
|
+
return initComponent(classFromData(opts.name ?? "UnkComp", opts), opts);
|
|
3643
|
+
}
|
|
3717
3644
|
|
|
3718
3645
|
// src/transactor.js
|
|
3719
3646
|
var State = class {
|
|
@@ -3754,14 +3681,7 @@ var Transactor = class {
|
|
|
3754
3681
|
// carry: kind, name, args, path, pathKeys, targetPath, handler, handlerName,
|
|
3755
3682
|
// matched, before, after, parent, timestamp. Purely observational.
|
|
3756
3683
|
observe(cb) {
|
|
3757
|
-
this._observers
|
|
3758
|
-
return () => {
|
|
3759
|
-
const i = this._observers.indexOf(cb);
|
|
3760
|
-
if (i !== -1) this._observers.splice(i, 1);
|
|
3761
|
-
};
|
|
3762
|
-
}
|
|
3763
|
-
_emit(record) {
|
|
3764
|
-
for (const cb of this._observers) cb(record);
|
|
3684
|
+
return subscribe(this._observers, cb);
|
|
3765
3685
|
}
|
|
3766
3686
|
// Record a refusal: a dispatch the runtime could not carry out. Kinds are
|
|
3767
3687
|
// open strings; today the runtime raises NO_HANDLER (a receive name with no
|
|
@@ -3780,20 +3700,16 @@ var Transactor = class {
|
|
|
3780
3700
|
// Subscribe to refusal records as they happen. Returns an unsubscribe fn,
|
|
3781
3701
|
// like observe().
|
|
3782
3702
|
observeRefusals(cb) {
|
|
3783
|
-
this._refusalObservers
|
|
3784
|
-
return () => {
|
|
3785
|
-
const i = this._refusalObservers.indexOf(cb);
|
|
3786
|
-
if (i !== -1) this._refusalObservers.splice(i, 1);
|
|
3787
|
-
};
|
|
3703
|
+
return subscribe(this._refusalObservers, cb);
|
|
3788
3704
|
}
|
|
3789
3705
|
// Build and dispatch one observer record. Pins field-resolved keys (e.g. a
|
|
3790
3706
|
// `.a[.selId]` render target reconstructed from a DOM event) against the root the
|
|
3791
3707
|
// handler read, so pathKeys carries concrete keys instead of dropping the dynamic
|
|
3792
3708
|
// step. No-op when nobody is observing.
|
|
3793
|
-
_emitRecord(root, { kind, name, args, path, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
3709
|
+
_emitRecord(root, { kind, name, args, path: path2, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
3794
3710
|
if (this._observers.length === 0) return;
|
|
3795
|
-
const pinned =
|
|
3796
|
-
|
|
3711
|
+
const pinned = path2.pinKeys(root);
|
|
3712
|
+
const record = {
|
|
3797
3713
|
kind,
|
|
3798
3714
|
name,
|
|
3799
3715
|
args: args ?? null,
|
|
@@ -3807,14 +3723,14 @@ var Transactor = class {
|
|
|
3807
3723
|
after,
|
|
3808
3724
|
parent,
|
|
3809
3725
|
timestamp: Date.now()
|
|
3810
|
-
}
|
|
3726
|
+
};
|
|
3727
|
+
for (const cb of this._observers) cb(record);
|
|
3811
3728
|
}
|
|
3812
3729
|
// The observer record for a settled transaction. The resolved handler
|
|
3813
3730
|
// (`_resolvedHandler`/`_matched`) and per-leaf before/after (`_before`/`_after`)
|
|
3814
3731
|
// were captured while the handler ran (see callHandler / Transaction.run).
|
|
3815
3732
|
_emitTransaction(transaction, root) {
|
|
3816
3733
|
if (this._observers.length === 0) return;
|
|
3817
|
-
if (transaction._resolvedHandler === void 0) return;
|
|
3818
3734
|
this._emitRecord(root, {
|
|
3819
3735
|
kind: transaction.observeKind,
|
|
3820
3736
|
name: transaction.observeName,
|
|
@@ -3828,33 +3744,29 @@ var Transactor = class {
|
|
|
3828
3744
|
parent: transaction.parentTransaction
|
|
3829
3745
|
});
|
|
3830
3746
|
}
|
|
3831
|
-
// Make `child` a tracked unit of `parent`'s subtree: the parent's completion stays open
|
|
3832
|
-
// until the child's *whole* subtree settles. Tracking happens at dispatch time — during
|
|
3833
|
-
// the parent's handler or afterTransaction — while the parent's self-unit is still held,
|
|
3834
|
-
// so the parent counter can't reach zero before the child is registered. Returns `child`.
|
|
3835
|
-
_link(child, parent) {
|
|
3836
|
-
if (parent) {
|
|
3837
|
-
const release = parent.completion.track();
|
|
3838
|
-
child.completion.whenSubtreeSettled().then(release);
|
|
3839
|
-
}
|
|
3840
|
-
return child;
|
|
3841
|
-
}
|
|
3842
3747
|
// `origin` is where the message came FROM, pinned now for the same reason an
|
|
3843
3748
|
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
3844
3749
|
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
3845
3750
|
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3751
|
+
//
|
|
3752
|
+
// The parent's subtree stays open until this message's whole subtree settles. The
|
|
3753
|
+
// unit is taken now, at dispatch — during the parent's handler or afterTransaction,
|
|
3754
|
+
// while the parent's self-unit is still held — so its counter can't reach zero first.
|
|
3755
|
+
pushSend(path2, name, args = [], parent = null, origin = null, txnPath = null) {
|
|
3756
|
+
const t = new SendEvent(path2, this, name, args, parent);
|
|
3757
|
+
t.txnPath = txnPath;
|
|
3758
|
+
t.origin = origin;
|
|
3759
|
+
t.originPinned = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
3849
3760
|
this.pushTransaction(t);
|
|
3850
|
-
|
|
3761
|
+
if (parent) t.completion.carry(parent.completion.track());
|
|
3762
|
+
return t;
|
|
3851
3763
|
}
|
|
3852
3764
|
// Raise an intent: a job the sender did not address, walked along a route until
|
|
3853
3765
|
// something answers. `opts.route` is a list of legs (see DEFAULT_ROUTE) and
|
|
3854
3766
|
// `opts.livePath` opts out of pinning the answer's destination keys.
|
|
3855
|
-
pushIntent(
|
|
3767
|
+
pushIntent(path2, name, args = [], opts = {}, parent = null) {
|
|
3856
3768
|
const release = parent ? parent.completion.track() : null;
|
|
3857
|
-
const walk = new IntentWalk(this,
|
|
3769
|
+
const walk = new IntentWalk(this, path2, name, args, opts, parent, release);
|
|
3858
3770
|
walk.advance();
|
|
3859
3771
|
return walk;
|
|
3860
3772
|
}
|
|
@@ -3871,7 +3783,7 @@ var Transactor = class {
|
|
|
3871
3783
|
return this.transactions.length > 0;
|
|
3872
3784
|
}
|
|
3873
3785
|
transactNext() {
|
|
3874
|
-
|
|
3786
|
+
this.transact(this.transactions.shift());
|
|
3875
3787
|
}
|
|
3876
3788
|
transact(transaction) {
|
|
3877
3789
|
try {
|
|
@@ -3884,20 +3796,31 @@ var Transactor = class {
|
|
|
3884
3796
|
} else console.warn("undefined new state", { curState, transaction });
|
|
3885
3797
|
} finally {
|
|
3886
3798
|
transaction.ensureWalkAdvanced?.();
|
|
3887
|
-
transaction._completion?.
|
|
3888
|
-
transaction._completion?.releaseSelf();
|
|
3799
|
+
transaction._completion?.finish();
|
|
3889
3800
|
}
|
|
3890
3801
|
}
|
|
3891
|
-
transactInputNow(
|
|
3892
|
-
this.transact(new InputEvent(
|
|
3802
|
+
transactInputNow(path2, event, eventHandler, dragInfo) {
|
|
3803
|
+
this.transact(new InputEvent(path2, event, eventHandler, this, dragInfo));
|
|
3893
3804
|
}
|
|
3894
3805
|
};
|
|
3895
3806
|
function nullHandler() {
|
|
3896
3807
|
return this;
|
|
3897
3808
|
}
|
|
3809
|
+
function subscribe(list, cb) {
|
|
3810
|
+
list.push(cb);
|
|
3811
|
+
return () => {
|
|
3812
|
+
const i = list.indexOf(cb);
|
|
3813
|
+
if (i !== -1) list.splice(i, 1);
|
|
3814
|
+
};
|
|
3815
|
+
}
|
|
3816
|
+
function warnUnknownLeg(what, leg) {
|
|
3817
|
+
console.warn(`unknown ${what} route leg`, leg, '- expected "dyn" or "lex"');
|
|
3818
|
+
return null;
|
|
3819
|
+
}
|
|
3898
3820
|
var Transaction = class {
|
|
3899
|
-
constructor(
|
|
3900
|
-
this.path =
|
|
3821
|
+
constructor(path2, transactor, parentTransaction = null) {
|
|
3822
|
+
this.path = path2;
|
|
3823
|
+
this.txnPath = null;
|
|
3901
3824
|
this.transactor = transactor;
|
|
3902
3825
|
this.parentTransaction = parentTransaction;
|
|
3903
3826
|
this._completion = null;
|
|
@@ -3917,39 +3840,41 @@ var Transaction = class {
|
|
|
3917
3840
|
whenSubtreeSettled() {
|
|
3918
3841
|
return this.completion.whenSubtreeSettled();
|
|
3919
3842
|
}
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
//
|
|
3923
|
-
// rather than throwing, so a stray call from the wrong place is a message and not a
|
|
3924
|
-
// crash. `walk` is undefined here, which is how ctx.reply/ctx.fail tell the two apart.
|
|
3925
|
-
stop() {
|
|
3926
|
-
warnNotIntent("stop");
|
|
3927
|
-
}
|
|
3928
|
-
forward(_opts) {
|
|
3929
|
-
console.warn('ctx.forward() needs a "receive" or "intent" handler - ignored');
|
|
3930
|
-
}
|
|
3931
|
-
// The kind reported to observers (see Transactor.observe); null on the base.
|
|
3932
|
-
get observeKind() {
|
|
3933
|
-
return null;
|
|
3934
|
-
}
|
|
3935
|
-
// The name reported to observers; null on the base. Overridden by NameArgs (the
|
|
3936
|
-
// dispatched message name) and InputEvent (the DOM event type). Kept separate from
|
|
3937
|
-
// `name`/`ctx.name` so it can't change handler-visible behavior.
|
|
3938
|
-
get observeName() {
|
|
3939
|
-
return null;
|
|
3940
|
-
}
|
|
3843
|
+
// Every transaction kind defines `observeKind` / `observeName` (what observers see;
|
|
3844
|
+
// kept apart from `name`/`ctx.name` so they can't change handler-visible behavior),
|
|
3845
|
+
// `getHandlerAndArgs(root, instance, comps)`, and the three `_forward*` hooks below.
|
|
3941
3846
|
callHandler(root, instance, draft, comps) {
|
|
3942
3847
|
const [handler, args] = this.getHandlerAndArgs(root, instance, comps);
|
|
3943
3848
|
this._resolvedHandler = handler;
|
|
3944
3849
|
return handler.apply(instance, [draft, ...args]);
|
|
3945
3850
|
}
|
|
3946
|
-
|
|
3947
|
-
|
|
3851
|
+
// `forward` is where a name can LEAVE the component: the message being handled is
|
|
3852
|
+
// raised again as an INTENT under the same name (`_forwardName()`) with the same
|
|
3853
|
+
// arguments unless `opts.args` says otherwise, from the position `_forwardPath()`
|
|
3854
|
+
// names. Deferred to afterTransaction so the state the handler produced is in place
|
|
3855
|
+
// before the walk starts. (`IntentEvent` overrides both: in an intent body, forward
|
|
3856
|
+
// amends the walk that is already running.)
|
|
3857
|
+
forward(opts) {
|
|
3858
|
+
this._forward = opts ?? {};
|
|
3948
3859
|
}
|
|
3949
|
-
|
|
3950
|
-
|
|
3860
|
+
afterTransaction() {
|
|
3861
|
+
const f = this._forward;
|
|
3862
|
+
if (f === void 0) return;
|
|
3863
|
+
this._forward = void 0;
|
|
3864
|
+
const name = this._forwardName();
|
|
3865
|
+
if (name === void 0) {
|
|
3866
|
+
this.transactor.refuse("FORWARD_NO_NAME", {});
|
|
3867
|
+
return;
|
|
3868
|
+
}
|
|
3869
|
+
const { args = this._forwardArgs(), ...rest } = f;
|
|
3870
|
+
this.transactor.pushIntent(this._forwardPath(), name, args, rest, this);
|
|
3871
|
+
}
|
|
3872
|
+
// The path used to apply the mutation: the ACTIVE frame of the dispatch path, so
|
|
3873
|
+
// an event inside a `<x render="*name">` subtree updates the value where it
|
|
3874
|
+
// really lives (the dispatch `this.path` keeps the visual callers, for bubbling).
|
|
3875
|
+
// `txnPath`, when pinned by the sender, wins.
|
|
3951
3876
|
getTransactionPath() {
|
|
3952
|
-
return this.path.toTransactionPath()
|
|
3877
|
+
return this.txnPath ?? this.path.toTransactionPath();
|
|
3953
3878
|
}
|
|
3954
3879
|
run(curRoot, comps) {
|
|
3955
3880
|
const txnPath = this.getTransactionPath();
|
|
@@ -3966,19 +3891,27 @@ var Transaction = class {
|
|
|
3966
3891
|
}
|
|
3967
3892
|
};
|
|
3968
3893
|
var InputEvent = class extends Transaction {
|
|
3969
|
-
constructor(
|
|
3970
|
-
super(
|
|
3894
|
+
constructor(path2, e, handler, transactor, dragInfo) {
|
|
3895
|
+
super(path2, transactor);
|
|
3971
3896
|
this.e = e;
|
|
3972
3897
|
this.handler = handler;
|
|
3973
3898
|
this.dragInfo = dragInfo;
|
|
3974
3899
|
this._dispatchPath = null;
|
|
3975
3900
|
}
|
|
3976
|
-
// Frame steps removed,
|
|
3977
|
-
//
|
|
3901
|
+
// Frame-only steps removed, one step per crossed component kept — inside every
|
|
3902
|
+
// continuation frame independently, so bubbling it visits every component and
|
|
3903
|
+
// then returns to the caller that wrote the `*name`.
|
|
3978
3904
|
get dispatchPath() {
|
|
3979
3905
|
this._dispatchPath ??= this.path.compact();
|
|
3980
3906
|
return this._dispatchPath;
|
|
3981
3907
|
}
|
|
3908
|
+
// Only a DOM event's path carries frame-only bind steps (they replay the handler's
|
|
3909
|
+
// arguments, but address no state); the compacted path is where the mutation lands,
|
|
3910
|
+
// so a handler inside @each still updates the component that owns the view. Every
|
|
3911
|
+
// other transaction is dispatched at an already-compacted position.
|
|
3912
|
+
getTransactionPath() {
|
|
3913
|
+
return this.dispatchPath.toTransactionPath();
|
|
3914
|
+
}
|
|
3982
3915
|
// A DOM event is an ADDRESSED message like any other — it reaches the component that
|
|
3983
3916
|
// owns the view and stops. It keeps its own class only because it resolves its handler
|
|
3984
3917
|
// from the compiled view and runs synchronously, not because it is a different channel.
|
|
@@ -3988,47 +3921,36 @@ var InputEvent = class extends Transaction {
|
|
|
3988
3921
|
get observeName() {
|
|
3989
3922
|
return this.e?.type ?? null;
|
|
3990
3923
|
}
|
|
3991
|
-
// A view's name is a message
|
|
3992
|
-
//
|
|
3993
|
-
//
|
|
3994
|
-
//
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
}
|
|
3998
|
-
afterTransaction() {
|
|
3999
|
-
const f = this._forward;
|
|
4000
|
-
if (f === void 0) return;
|
|
4001
|
-
this._forward = void 0;
|
|
4002
|
-
const { args = this._handlerArgs ?? [], ...rest } = f;
|
|
3924
|
+
// A view's name is a message, and forwarding it means a view that says
|
|
3925
|
+
// `@on.click="saveDraft .text"` never has to change when an ancestor takes the job
|
|
3926
|
+
// over. (A `$method` handler has a name too, so forwarding one raises an intent under
|
|
3927
|
+
// it.) `handler` is a NodeEvent, whose own `name` is the DOM event type; the MESSAGE
|
|
3928
|
+
// name is the one the view wrote, on the handler call it wraps.
|
|
3929
|
+
_forwardName() {
|
|
4003
3930
|
const hv = this.handler?.handlerCall?.handlerVal ?? this.handler?.handlerVal;
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
3931
|
+
return hv?.name;
|
|
3932
|
+
}
|
|
3933
|
+
_forwardArgs() {
|
|
3934
|
+
return this._handlerArgs ?? [];
|
|
3935
|
+
}
|
|
3936
|
+
_forwardPath() {
|
|
3937
|
+
return this.dispatchPath;
|
|
4010
3938
|
}
|
|
4011
3939
|
getHandlerAndArgs(root, _instance, comps) {
|
|
4012
|
-
const stack = this.path.
|
|
3940
|
+
const stack = this.path.buildStack(Stack.root(comps, root, this));
|
|
4013
3941
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
4014
3942
|
this._handlerArgs = [...args];
|
|
4015
|
-
const
|
|
4016
|
-
args.push(new EventContext(
|
|
3943
|
+
const path2 = this.dispatchPath;
|
|
3944
|
+
args.push(new EventContext(path2, this.transactor, this));
|
|
4017
3945
|
return [handler, args];
|
|
4018
3946
|
}
|
|
4019
|
-
// The dispatched DOM event, read only through `e.<member>` handler args
|
|
4020
|
-
// (src/value.js EventMemberVal via Stack.lookupEvent). There is no bare
|
|
4021
|
-
// implicit-name vocabulary anymore: every arg carries a sigil.
|
|
4022
|
-
get event() {
|
|
4023
|
-
return this.e;
|
|
4024
|
-
}
|
|
4025
3947
|
};
|
|
4026
3948
|
var NameArgsTransaction = class extends Transaction {
|
|
4027
|
-
constructor(
|
|
4028
|
-
super(
|
|
3949
|
+
constructor(path2, transactor, name, args, parentTransaction) {
|
|
3950
|
+
super(path2, transactor, parentTransaction);
|
|
4029
3951
|
this.name = name;
|
|
4030
3952
|
this.args = args;
|
|
4031
|
-
this.targetPath =
|
|
3953
|
+
this.targetPath = path2;
|
|
4032
3954
|
}
|
|
4033
3955
|
handlerProp = null;
|
|
4034
3956
|
// NameArgs verbs map their handler bucket straight to the observed kind:
|
|
@@ -4039,6 +3961,17 @@ var NameArgsTransaction = class extends Transaction {
|
|
|
4039
3961
|
get observeName() {
|
|
4040
3962
|
return this.name;
|
|
4041
3963
|
}
|
|
3964
|
+
// `forward` in a RECEIVE body starts a walk: the message that arrived becomes an
|
|
3965
|
+
// intent, keeping its name and payload.
|
|
3966
|
+
_forwardName() {
|
|
3967
|
+
return this.name;
|
|
3968
|
+
}
|
|
3969
|
+
_forwardArgs() {
|
|
3970
|
+
return this.args;
|
|
3971
|
+
}
|
|
3972
|
+
_forwardPath() {
|
|
3973
|
+
return this.path;
|
|
3974
|
+
}
|
|
4042
3975
|
getHandlerForName(comp) {
|
|
4043
3976
|
const handlers = comp?.[this.handlerProp];
|
|
4044
3977
|
const exact = handlers?.[this.name];
|
|
@@ -4069,24 +4002,11 @@ var SendEvent = class extends NameArgsTransaction {
|
|
|
4069
4002
|
get observeKind() {
|
|
4070
4003
|
return this._isAnswer ? "answer" : "receive";
|
|
4071
4004
|
}
|
|
4072
|
-
// `forward` in a RECEIVE body starts a walk: the message that arrived becomes an
|
|
4073
|
-
// intent, keeping its name and payload. This is what lets a view's name leave the
|
|
4074
|
-
// component without the view changing.
|
|
4075
|
-
forward(opts) {
|
|
4076
|
-
this._forward = opts ?? {};
|
|
4077
|
-
}
|
|
4078
|
-
afterTransaction() {
|
|
4079
|
-
const f = this._forward;
|
|
4080
|
-
if (f === void 0) return;
|
|
4081
|
-
this._forward = void 0;
|
|
4082
|
-
const { args = this.args, ...rest } = f;
|
|
4083
|
-
this.transactor.pushIntent(this.path, this.name, args, rest, this);
|
|
4084
|
-
}
|
|
4085
4005
|
};
|
|
4086
4006
|
var IntentEvent = class extends NameArgsTransaction {
|
|
4087
4007
|
handlerProp = "intent";
|
|
4088
|
-
constructor(
|
|
4089
|
-
super(
|
|
4008
|
+
constructor(path2, transactor, walk) {
|
|
4009
|
+
super(path2, transactor, walk.name, walk.args, walk.parent);
|
|
4090
4010
|
this.walk = walk;
|
|
4091
4011
|
this.targetPath = walk.origin;
|
|
4092
4012
|
}
|
|
@@ -4095,9 +4015,6 @@ var IntentEvent = class extends NameArgsTransaction {
|
|
|
4095
4015
|
forward(opts) {
|
|
4096
4016
|
this.walk.amend(opts, this.path);
|
|
4097
4017
|
}
|
|
4098
|
-
stop() {
|
|
4099
|
-
this.walk.finish(null, null);
|
|
4100
|
-
}
|
|
4101
4018
|
afterTransaction() {
|
|
4102
4019
|
this.ensureWalkAdvanced();
|
|
4103
4020
|
}
|
|
@@ -4113,17 +4030,17 @@ var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
|
|
|
4113
4030
|
var REFUSAL_RING_CAP = 200;
|
|
4114
4031
|
var INTENT_DEPTH = 64;
|
|
4115
4032
|
var IntentWalk = class {
|
|
4116
|
-
constructor(transactor,
|
|
4033
|
+
constructor(transactor, path2, name, args, opts, parent, release) {
|
|
4117
4034
|
this.transactor = transactor;
|
|
4118
4035
|
this.name = name;
|
|
4119
4036
|
this.args = args;
|
|
4120
4037
|
this.route = opts?.route ?? DEFAULT_ROUTE;
|
|
4121
4038
|
this.parent = parent;
|
|
4122
4039
|
this.release = release;
|
|
4123
|
-
this.origin =
|
|
4124
|
-
this.answerPath = opts?.livePath ? null :
|
|
4040
|
+
this.origin = path2;
|
|
4041
|
+
this.answerPath = opts?.livePath ? null : path2.toTransactionPath().pinKeys(transactor.state.val);
|
|
4125
4042
|
this.legIndex = 0;
|
|
4126
|
-
this.dynAt =
|
|
4043
|
+
this.dynAt = path2;
|
|
4127
4044
|
this.hops = 0;
|
|
4128
4045
|
this.ended = false;
|
|
4129
4046
|
}
|
|
@@ -4135,7 +4052,7 @@ var IntentWalk = class {
|
|
|
4135
4052
|
while (this.legIndex < this.route.length) {
|
|
4136
4053
|
const leg = this.route[this.legIndex];
|
|
4137
4054
|
if (leg === "dyn") {
|
|
4138
|
-
if (this.dynAt.
|
|
4055
|
+
if (!this.dynAt.canPop()) {
|
|
4139
4056
|
this.legIndex++;
|
|
4140
4057
|
continue;
|
|
4141
4058
|
}
|
|
@@ -4147,7 +4064,7 @@ var IntentWalk = class {
|
|
|
4147
4064
|
this.legIndex++;
|
|
4148
4065
|
return this._tryLex();
|
|
4149
4066
|
}
|
|
4150
|
-
|
|
4067
|
+
warnUnknownLeg("intent", leg);
|
|
4151
4068
|
this.legIndex++;
|
|
4152
4069
|
}
|
|
4153
4070
|
this.exhaust("noHandler");
|
|
@@ -4232,11 +4149,11 @@ var IntentWalk = class {
|
|
|
4232
4149
|
if (this.ended) return;
|
|
4233
4150
|
this.ended = true;
|
|
4234
4151
|
if (name === null) return this.release?.();
|
|
4235
|
-
const
|
|
4236
|
-
|
|
4152
|
+
const t = new SendEvent(this.origin, this.transactor, name, args, this.parent);
|
|
4153
|
+
t.txnPath = this.answerPath;
|
|
4237
4154
|
t._isAnswer = true;
|
|
4238
4155
|
this.transactor.pushTransaction(t);
|
|
4239
|
-
if (this.release) t.completion.
|
|
4156
|
+
if (this.release) t.completion.carry(this.release);
|
|
4240
4157
|
}
|
|
4241
4158
|
};
|
|
4242
4159
|
var Completion = class {
|
|
@@ -4244,12 +4161,12 @@ var Completion = class {
|
|
|
4244
4161
|
this.val = void 0;
|
|
4245
4162
|
this.selfSettled = false;
|
|
4246
4163
|
this.subtreeSettled = false;
|
|
4247
|
-
this.pending =
|
|
4164
|
+
this.pending = 0;
|
|
4248
4165
|
this._selfResolve = null;
|
|
4249
4166
|
this._selfPromise = null;
|
|
4250
4167
|
this._subtreeResolve = null;
|
|
4251
4168
|
this._subtreePromise = null;
|
|
4252
|
-
this.
|
|
4169
|
+
this._releaseSelf = this.track();
|
|
4253
4170
|
}
|
|
4254
4171
|
whenSettled() {
|
|
4255
4172
|
if (this.selfSettled) return Promise.resolve(this.val);
|
|
@@ -4272,38 +4189,38 @@ var Completion = class {
|
|
|
4272
4189
|
this.val = val;
|
|
4273
4190
|
this._selfResolve?.(val);
|
|
4274
4191
|
}
|
|
4275
|
-
//
|
|
4276
|
-
|
|
4277
|
-
|
|
4192
|
+
// The transaction is done processing: self is settled (with the value the handler
|
|
4193
|
+
// produced, or none on the undefined-state / throw paths) and the self-unit goes.
|
|
4194
|
+
finish() {
|
|
4195
|
+
this.markSelfSettled(this.val);
|
|
4196
|
+
this._releaseSelf();
|
|
4278
4197
|
}
|
|
4279
|
-
// Register an outstanding unit; returns
|
|
4198
|
+
// Register an outstanding unit; returns its one-shot release. The subtree settles
|
|
4199
|
+
// when the last unit is released.
|
|
4280
4200
|
track() {
|
|
4281
4201
|
this.pending++;
|
|
4282
4202
|
let done = false;
|
|
4283
4203
|
return () => {
|
|
4284
4204
|
if (done) return;
|
|
4285
4205
|
done = true;
|
|
4286
|
-
this.
|
|
4206
|
+
if (--this.pending === 0) {
|
|
4207
|
+
this.subtreeSettled = true;
|
|
4208
|
+
this._subtreeResolve?.(this.val);
|
|
4209
|
+
}
|
|
4287
4210
|
};
|
|
4288
4211
|
}
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
this.
|
|
4293
|
-
}
|
|
4294
|
-
_release() {
|
|
4295
|
-
if (--this.pending === 0) {
|
|
4296
|
-
this.subtreeSettled = true;
|
|
4297
|
-
this._subtreeResolve?.(this.val);
|
|
4298
|
-
}
|
|
4212
|
+
// Hand a unit held elsewhere to this subtree: `release` runs once this transaction
|
|
4213
|
+
// and everything it spawned have settled.
|
|
4214
|
+
carry(release) {
|
|
4215
|
+
this.whenSubtreeSettled().then(release);
|
|
4299
4216
|
}
|
|
4300
4217
|
};
|
|
4301
4218
|
var Dispatcher = class {
|
|
4302
|
-
constructor(
|
|
4303
|
-
this.path =
|
|
4219
|
+
constructor(path2, transactor, parentTransaction) {
|
|
4220
|
+
this.path = path2;
|
|
4304
4221
|
this.transactor = transactor;
|
|
4305
4222
|
this.parent = parentTransaction;
|
|
4306
|
-
this.root =
|
|
4223
|
+
this.root = transactor.state.val;
|
|
4307
4224
|
}
|
|
4308
4225
|
// Walk the component instances on this ctx's path, leaf→root, calling
|
|
4309
4226
|
// callback(Component, instance). Return false from the callback to stop early.
|
|
@@ -4328,28 +4245,37 @@ var Dispatcher = class {
|
|
|
4328
4245
|
// replayed; provides are pushed on every component frame either way, so a provide
|
|
4329
4246
|
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
4330
4247
|
_stack() {
|
|
4331
|
-
this._stackMemo ??= this.path.
|
|
4248
|
+
this._stackMemo ??= this.path.buildStack(
|
|
4249
|
+
Stack.root(this.transactor.comps, this.root, this.parent)
|
|
4250
|
+
);
|
|
4332
4251
|
return this._stackMemo;
|
|
4333
4252
|
}
|
|
4334
4253
|
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
4335
4254
|
// the same spelling as `ctx.intent` — `["dyn"]` the render ancestry, `["lex"]` the
|
|
4336
4255
|
// registration scope, default both.
|
|
4256
|
+
// Legs are tried in route order, like the intent walker's; an unknown leg warns and
|
|
4257
|
+
// is skipped, and an empty route resolves to null.
|
|
4337
4258
|
lookup(name, opts) {
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
()
|
|
4341
|
-
|
|
4342
|
-
|
|
4259
|
+
for (const leg of opts?.route ?? DEFAULT_ROUTE) {
|
|
4260
|
+
const v = leg === "dyn" ? this._stack()?.lookupDynamic(name) ?? null : leg === "lex" ? this._lookupLex(name) : warnUnknownLeg("lookup", leg);
|
|
4261
|
+
if (v != null) return v;
|
|
4262
|
+
}
|
|
4263
|
+
return null;
|
|
4343
4264
|
}
|
|
4344
4265
|
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
4345
|
-
// running, which is the leaf of this ctx's path.
|
|
4266
|
+
// running, which is the leaf of this ctx's path. A type name resolves to the
|
|
4267
|
+
// component registered under it; a value name to a path registered under it
|
|
4268
|
+
// (see ComponentStack.registerPaths), read against the current root.
|
|
4346
4269
|
_lookupLex(name) {
|
|
4347
4270
|
let Comp = null;
|
|
4348
4271
|
this.walkPath((c) => {
|
|
4349
4272
|
Comp = c;
|
|
4350
4273
|
return false;
|
|
4351
4274
|
});
|
|
4352
|
-
|
|
4275
|
+
const scope = Comp?.scope;
|
|
4276
|
+
if (scope == null) return null;
|
|
4277
|
+
if (isTypeName(name)) return scope.lookupComponent(name) ?? null;
|
|
4278
|
+
return scope.lookupPath(name)?.lookup(this.root) ?? null;
|
|
4353
4279
|
}
|
|
4354
4280
|
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
4355
4281
|
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
@@ -4371,8 +4297,8 @@ var Dispatcher = class {
|
|
|
4371
4297
|
send(name, args) {
|
|
4372
4298
|
return this.sendAtPath(this.path, name, args);
|
|
4373
4299
|
}
|
|
4374
|
-
sendAtPath(
|
|
4375
|
-
return this.transactor.pushSend(
|
|
4300
|
+
sendAtPath(path2, name, args) {
|
|
4301
|
+
return this.transactor.pushSend(path2, name, args, this.parent, this.path);
|
|
4376
4302
|
}
|
|
4377
4303
|
// An intent is ROUTED: it names a job and walks until something answers. The verb
|
|
4378
4304
|
// does not decide which scope answers — `opts.route` does, written here at the call
|
|
@@ -4380,8 +4306,8 @@ var Dispatcher = class {
|
|
|
4380
4306
|
intent(name, args, opts) {
|
|
4381
4307
|
return this.intentAtPath(this.path, name, args, opts);
|
|
4382
4308
|
}
|
|
4383
|
-
intentAtPath(
|
|
4384
|
-
return this.transactor.pushIntent(
|
|
4309
|
+
intentAtPath(path2, name, args, opts) {
|
|
4310
|
+
return this.transactor.pushIntent(path2, name, args, opts, this.parent);
|
|
4385
4311
|
}
|
|
4386
4312
|
};
|
|
4387
4313
|
var EventContext = class extends Dispatcher {
|
|
@@ -4410,11 +4336,19 @@ var EventContext = class extends Dispatcher {
|
|
|
4410
4336
|
this.transactor.refuse("NO_SENDER", { name });
|
|
4411
4337
|
return null;
|
|
4412
4338
|
}
|
|
4413
|
-
return this.
|
|
4339
|
+
return this.transactor.pushSend(
|
|
4340
|
+
origin,
|
|
4341
|
+
name,
|
|
4342
|
+
args,
|
|
4343
|
+
this.parent,
|
|
4344
|
+
this.path,
|
|
4345
|
+
this.parent.originPinned
|
|
4346
|
+
);
|
|
4414
4347
|
}
|
|
4415
|
-
// End the walk answering nothing — "served, and no answer".
|
|
4348
|
+
// End the walk answering nothing — "served, and no answer". Like reply/fail,
|
|
4349
|
+
// legal only in an `intent` handler.
|
|
4416
4350
|
stop() {
|
|
4417
|
-
return this.parent.stop();
|
|
4351
|
+
return this.parent.walk === void 0 ? warnNotIntent("stop") : this.parent.walk.finish(null, null);
|
|
4418
4352
|
}
|
|
4419
4353
|
// From an `intent` body: hand the intent to the next hop, optionally amending it.
|
|
4420
4354
|
// From a `receive` body: turn the message that arrived into an intent. One word from
|
|
@@ -4442,7 +4376,7 @@ var PathChanges = class extends PathBuilder {
|
|
|
4442
4376
|
}
|
|
4443
4377
|
};
|
|
4444
4378
|
function rootDispatcher(transactor) {
|
|
4445
|
-
return new Dispatcher(new
|
|
4379
|
+
return new Dispatcher(new DispatchPath(), transactor, null);
|
|
4446
4380
|
}
|
|
4447
4381
|
|
|
4448
4382
|
// src/app.js
|
|
@@ -4455,7 +4389,6 @@ var App = class {
|
|
|
4455
4389
|
this.transactor = new Transactor(comps, null);
|
|
4456
4390
|
this.ParseContext = ParseContext2;
|
|
4457
4391
|
this.renderer = renderer;
|
|
4458
|
-
this.maxEventNodeDepth = Infinity;
|
|
4459
4392
|
this._transactNextBatchId = this._evictCacheId = null;
|
|
4460
4393
|
this._eventNames = new Set(_evs);
|
|
4461
4394
|
this.dragInfo = this.curDragOver = null;
|
|
@@ -4482,18 +4415,17 @@ var App = class {
|
|
|
4482
4415
|
_dispatchEvent(e) {
|
|
4483
4416
|
const { type } = e;
|
|
4484
4417
|
const isDrag = type === "dragover" || type === "dragstart" || type === "dragend" || type === "drop";
|
|
4485
|
-
const { rootNode
|
|
4486
|
-
const [
|
|
4418
|
+
const { rootNode, comps, transactor } = this;
|
|
4419
|
+
const [path2, handlers] = DispatchPath.fromNodeAndEventName(
|
|
4487
4420
|
e.target,
|
|
4488
4421
|
type,
|
|
4489
|
-
|
|
4490
|
-
maxDepth,
|
|
4422
|
+
rootNode,
|
|
4491
4423
|
comps,
|
|
4492
4424
|
!isDrag
|
|
4493
4425
|
);
|
|
4494
|
-
if (isDrag) this._handleDragEvent(e, type,
|
|
4495
|
-
if (
|
|
4496
|
-
for (const handler of handlers) transactor.transactInputNow(
|
|
4426
|
+
if (isDrag) this._handleDragEvent(e, type, path2);
|
|
4427
|
+
if (path2 !== null && handlers !== null)
|
|
4428
|
+
for (const handler of handlers) transactor.transactInputNow(path2, e, handler, this.dragInfo);
|
|
4497
4429
|
}
|
|
4498
4430
|
_handleTouchEvent(e) {
|
|
4499
4431
|
const { type } = e;
|
|
@@ -4536,7 +4468,7 @@ var App = class {
|
|
|
4536
4468
|
this._touch = null;
|
|
4537
4469
|
}
|
|
4538
4470
|
}
|
|
4539
|
-
_handleDragEvent(e, type,
|
|
4471
|
+
_handleDragEvent(e, type, path2) {
|
|
4540
4472
|
if (type === "dragover") {
|
|
4541
4473
|
const dropTarget = getClosestDropTarget(e.target, this.rootNode, Infinity);
|
|
4542
4474
|
if (dropTarget !== null) {
|
|
@@ -4548,10 +4480,10 @@ var App = class {
|
|
|
4548
4480
|
} else if (type === "dragstart") {
|
|
4549
4481
|
e.target.dataset.dragging = 1;
|
|
4550
4482
|
const rootValue = this.state.val;
|
|
4551
|
-
const txnPath =
|
|
4483
|
+
const txnPath = path2.compact().toTransactionPath();
|
|
4552
4484
|
const value = txnPath.lookup(rootValue);
|
|
4553
4485
|
const dragType = e.target.dataset.dragtype ?? "?";
|
|
4554
|
-
const stack =
|
|
4486
|
+
const stack = path2.buildStack(this.makeStack(rootValue));
|
|
4555
4487
|
this.dragInfo = new DragInfo(stack, value, dragType, e.target);
|
|
4556
4488
|
} else if (type === "drop") {
|
|
4557
4489
|
e.preventDefault();
|
|
@@ -4596,10 +4528,9 @@ var App = class {
|
|
|
4596
4528
|
}
|
|
4597
4529
|
compile() {
|
|
4598
4530
|
for (const Comp of this.comps.byId.values()) {
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
for (const name of meta.views[key].ctx.genEventNames()) this._eventNames.add(name);
|
|
4531
|
+
Comp.compile(this.ParseContext);
|
|
4532
|
+
for (const key in Comp.views)
|
|
4533
|
+
for (const name of Comp.views[key].ctx.genEventNames()) this._eventNames.add(name);
|
|
4603
4534
|
}
|
|
4604
4535
|
this._compiled = true;
|
|
4605
4536
|
}
|
|
@@ -4622,11 +4553,13 @@ var App = class {
|
|
|
4622
4553
|
}
|
|
4623
4554
|
stop() {
|
|
4624
4555
|
this.stopCacheEvictionInterval();
|
|
4556
|
+
clearTimeout(this._transactNextBatchId);
|
|
4557
|
+
this._transactNextBatchId = null;
|
|
4625
4558
|
for (const name of this._eventNames)
|
|
4626
4559
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
4627
4560
|
}
|
|
4628
4561
|
sendAtRoot(name, args) {
|
|
4629
|
-
this.transactor.pushSend(new
|
|
4562
|
+
this.transactor.pushSend(new DispatchPath(), name, args);
|
|
4630
4563
|
}
|
|
4631
4564
|
registerComponents(comps, opts) {
|
|
4632
4565
|
const scope = this.compStack.enter();
|
|
@@ -4701,7 +4634,7 @@ var DragInfo = class {
|
|
|
4701
4634
|
};
|
|
4702
4635
|
|
|
4703
4636
|
// src/util/parsectx.js
|
|
4704
|
-
var ParseCtxClassSetCollector = class
|
|
4637
|
+
var ParseCtxClassSetCollector = class extends ParseContext {
|
|
4705
4638
|
constructor(...args) {
|
|
4706
4639
|
super(...args);
|
|
4707
4640
|
this.classes = /* @__PURE__ */ new Set();
|
|
@@ -4711,22 +4644,6 @@ var ParseCtxClassSetCollector = class _ParseCtxClassSetCollector extends ParseCo
|
|
|
4711
4644
|
this.classes.add(v);
|
|
4712
4645
|
}
|
|
4713
4646
|
}
|
|
4714
|
-
enterMacro(macroName, macroVars, macroSlots) {
|
|
4715
|
-
const { document: document2, Text, Comment, nodes, events, macroNodes } = this;
|
|
4716
|
-
const frame = { macroName, macroVars, macroSlots };
|
|
4717
|
-
const v = new _ParseCtxClassSetCollector(
|
|
4718
|
-
document2,
|
|
4719
|
-
Text,
|
|
4720
|
-
Comment,
|
|
4721
|
-
nodes,
|
|
4722
|
-
events,
|
|
4723
|
-
macroNodes,
|
|
4724
|
-
frame,
|
|
4725
|
-
this
|
|
4726
|
-
);
|
|
4727
|
-
v.classes = this.classes;
|
|
4728
|
-
return v;
|
|
4729
|
-
}
|
|
4730
4647
|
onAttributes(attrs, _wrapperAttrs, _textChild, _isMacroCall, _tag) {
|
|
4731
4648
|
if (Array.isArray(attrs.items)) {
|
|
4732
4649
|
for (const attr of attrs.items) {
|
|
@@ -4786,28 +4703,21 @@ var NullDomCache = class {
|
|
|
4786
4703
|
set(_keys, _cacheKey, _v) {
|
|
4787
4704
|
}
|
|
4788
4705
|
evict() {
|
|
4789
|
-
return { hit: 0, miss: 0, badKey: 0 };
|
|
4790
4706
|
}
|
|
4791
4707
|
};
|
|
4792
4708
|
var WeakMapDomCache = class {
|
|
4793
4709
|
constructor() {
|
|
4794
|
-
this.hit = this.miss = this.badKey = 0;
|
|
4795
4710
|
this.keysByLen = /* @__PURE__ */ new Map();
|
|
4796
4711
|
}
|
|
4797
|
-
_returnValue(r) {
|
|
4798
|
-
if (r === void 0) this.miss += 1;
|
|
4799
|
-
else this.hit += 1;
|
|
4800
|
-
return r;
|
|
4801
|
-
}
|
|
4802
4712
|
get(keys, cacheKey) {
|
|
4803
4713
|
const len = keys.length;
|
|
4804
4714
|
let cur = this.keysByLen.get(len);
|
|
4805
|
-
if (!cur) return
|
|
4715
|
+
if (!cur) return void 0;
|
|
4806
4716
|
for (let i = 0; i < len - 1; i++) {
|
|
4807
4717
|
cur = cur.get(keys[i]);
|
|
4808
|
-
if (!cur) return
|
|
4718
|
+
if (!cur) return void 0;
|
|
4809
4719
|
}
|
|
4810
|
-
return
|
|
4720
|
+
return cur.get(keys[len - 1])?.[cacheKey];
|
|
4811
4721
|
}
|
|
4812
4722
|
set(keys, cacheKey, v) {
|
|
4813
4723
|
const len = keys.length;
|
|
@@ -4820,10 +4730,7 @@ var WeakMapDomCache = class {
|
|
|
4820
4730
|
const key = keys[i];
|
|
4821
4731
|
let next = cur.get(key);
|
|
4822
4732
|
if (!next) {
|
|
4823
|
-
if (!isWeakKey(key))
|
|
4824
|
-
this.badKey += 1;
|
|
4825
|
-
return;
|
|
4826
|
-
}
|
|
4733
|
+
if (!isWeakKey(key)) return;
|
|
4827
4734
|
next = /* @__PURE__ */ new WeakMap();
|
|
4828
4735
|
cur.set(key, next);
|
|
4829
4736
|
}
|
|
@@ -4833,23 +4740,38 @@ var WeakMapDomCache = class {
|
|
|
4833
4740
|
const leaf = cur.get(lastKey);
|
|
4834
4741
|
if (leaf) leaf[cacheKey] = v;
|
|
4835
4742
|
else if (isWeakKey(lastKey)) cur.set(lastKey, { [cacheKey]: v });
|
|
4836
|
-
else this.badKey += 1;
|
|
4837
4743
|
}
|
|
4838
4744
|
evict() {
|
|
4839
|
-
const { hit, miss, badKey } = this;
|
|
4840
|
-
this.hit = this.miss = this.badKey = 0;
|
|
4841
4745
|
this.keysByLen = /* @__PURE__ */ new Map();
|
|
4842
|
-
return { hit, miss, badKey };
|
|
4843
4746
|
}
|
|
4844
4747
|
};
|
|
4845
4748
|
|
|
4846
4749
|
// src/renderer.js
|
|
4847
|
-
|
|
4750
|
+
function stampRenderBase(vdom, text) {
|
|
4751
|
+
if (vdom instanceof VNode)
|
|
4752
|
+
return new VNode(
|
|
4753
|
+
vdom.tag,
|
|
4754
|
+
{ ...vdom.attrs, "data-rp": text },
|
|
4755
|
+
vdom.childs,
|
|
4756
|
+
vdom.key,
|
|
4757
|
+
vdom.namespace
|
|
4758
|
+
);
|
|
4759
|
+
if (vdom instanceof VFragment)
|
|
4760
|
+
return new VFragment(vdom.childs.map((c) => stampRenderBase(c, text)));
|
|
4761
|
+
return vdom;
|
|
4762
|
+
}
|
|
4848
4763
|
var Renderer = class {
|
|
4849
4764
|
constructor(comps) {
|
|
4850
4765
|
this.comps = comps;
|
|
4851
4766
|
this.cache = new WeakMapDomCache();
|
|
4852
|
-
|
|
4767
|
+
}
|
|
4768
|
+
// Parse nodes build their VDOM through the renderer, never by importing vdom.js
|
|
4769
|
+
// themselves: a component may have been compiled by ANOTHER copy of the library
|
|
4770
|
+
// (a docs example imports the dist bundle while the host app runs from src), and
|
|
4771
|
+
// `render()` recognizes VNodes by `instanceof` against ITS copy's classes. Going
|
|
4772
|
+
// through `rx` guarantees the rendering copy makes them.
|
|
4773
|
+
renderTag(tag, attrs, childs, namespace) {
|
|
4774
|
+
return h(tag, attrs, childs, namespace);
|
|
4853
4775
|
}
|
|
4854
4776
|
renderFragment(childs) {
|
|
4855
4777
|
return new VFragment(childs);
|
|
@@ -4860,38 +4782,24 @@ var Renderer = class {
|
|
|
4860
4782
|
setNullCache() {
|
|
4861
4783
|
this.cache = new NullDomCache();
|
|
4862
4784
|
}
|
|
4863
|
-
// Library utilities for consumers embedding tutuca: render a value to a detached
|
|
4864
|
-
// DOM node / an HTML string. Not called by the framework itself.
|
|
4865
|
-
renderToDOM(stack, val) {
|
|
4866
|
-
const rootNode = document.createElement("div");
|
|
4867
|
-
const rOpts = { document };
|
|
4868
|
-
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
4869
|
-
return rootNode.childNodes[0];
|
|
4870
|
-
}
|
|
4871
|
-
renderToString(stack, val, cleanAttrs = true) {
|
|
4872
|
-
const dom = this.renderToDOM(stack, val);
|
|
4873
|
-
if (cleanAttrs) {
|
|
4874
|
-
const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
|
|
4875
|
-
for (const { dataset } of nodes) for (const name of DATASET_ATTRS) delete dataset[name];
|
|
4876
|
-
}
|
|
4877
|
-
return dom.innerHTML;
|
|
4878
|
-
}
|
|
4879
4785
|
renderRoot(stack, val, viewName = null) {
|
|
4880
4786
|
const comp = this.comps.getCompFor(val);
|
|
4881
4787
|
if (comp === null) return null;
|
|
4882
4788
|
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
4883
4789
|
}
|
|
4884
|
-
|
|
4790
|
+
// Render `stack.it` at a `<x render*>` site (`node`). `base` is the absolute
|
|
4791
|
+
// path the site resumed at, when it rendered a `*name` (see _rValComp).
|
|
4792
|
+
renderIt(stack, node, viewName, base = null) {
|
|
4885
4793
|
const comp = this.comps.getCompFor(stack.it);
|
|
4886
|
-
return comp ? this._rValComp(stack, stack.it, comp, node,
|
|
4794
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, "", viewName, base) : null;
|
|
4887
4795
|
}
|
|
4888
4796
|
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
4889
4797
|
// `render-each`, or the view's root anode for the app root). It keys the
|
|
4890
4798
|
// cache as a globally-unique object: node ids alone are unique only within a
|
|
4891
4799
|
// single view, so the same value rendered by two components (e.g. through a
|
|
4892
4800
|
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
4893
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
4894
|
-
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
4801
|
+
_rValComp(stack, val, comp, node, key, viewName, base = null) {
|
|
4802
|
+
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}${stack.renderPath.addressKey}`;
|
|
4895
4803
|
const cachePath = [node, val];
|
|
4896
4804
|
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
4897
4805
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
@@ -4899,30 +4807,43 @@ var Renderer = class {
|
|
|
4899
4807
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
4900
4808
|
const body = this.renderView(view, stack);
|
|
4901
4809
|
if (body == null) return null;
|
|
4810
|
+
const baseJson = base === null ? null : pathToJson(base);
|
|
4902
4811
|
const meta = this._renderMetadata({
|
|
4903
4812
|
$: "Comp",
|
|
4904
4813
|
nid: node?.nodeId ?? null,
|
|
4905
4814
|
cid: comp.id,
|
|
4906
|
-
vid: view.name
|
|
4815
|
+
vid: view.name,
|
|
4816
|
+
...baseJson === null ? null : { base: baseJson }
|
|
4907
4817
|
});
|
|
4908
|
-
const dom = new VFragment([
|
|
4818
|
+
const dom = new VFragment([
|
|
4819
|
+
meta,
|
|
4820
|
+
baseJson === null ? body : stampRenderBase(body, JSON.stringify(baseJson))
|
|
4821
|
+
]);
|
|
4909
4822
|
this.cache.set(cachePath, cacheKey, dom);
|
|
4910
4823
|
return dom;
|
|
4911
4824
|
}
|
|
4912
4825
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
4913
4826
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
4914
4827
|
}
|
|
4915
|
-
renderEachWhen(stack,
|
|
4916
|
-
const {
|
|
4828
|
+
renderEachWhen(stack, each2) {
|
|
4829
|
+
const { val: seqVal, node: view, nodeId: nid } = each2;
|
|
4830
|
+
const { seq, filter, loopWith, enricher } = each2.evalIter(stack);
|
|
4831
|
+
const seqPath = seqVal instanceof DynVal ? stack.lookupDynamicLocated(seqVal.name)?.path ?? null : null;
|
|
4917
4832
|
const r = [];
|
|
4918
4833
|
const it = stack.it;
|
|
4919
4834
|
const renderOne = (key, value, attrName, binds) => {
|
|
4835
|
+
const itemBase = seqPath === null ? null : keyedPath(seqPath, key);
|
|
4836
|
+
const itemStep = itemBase === null ? each2.itemStep(key) : null;
|
|
4837
|
+
const itemPath = itemBase !== null ? stack.renderPath.pushFrame(itemBase) : itemStep !== null ? stack.renderPath.pushItem(itemStep) : stack.renderPath;
|
|
4920
4838
|
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
4921
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
4839
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}${itemPath.addressKey}`;
|
|
4922
4840
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
4923
4841
|
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
4924
4842
|
else {
|
|
4925
|
-
const dom = this.renderView(
|
|
4843
|
+
const dom = this.renderView(
|
|
4844
|
+
view,
|
|
4845
|
+
stack.enter(value, binds, false, itemPath, itemBase !== null)
|
|
4846
|
+
);
|
|
4926
4847
|
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
4927
4848
|
this.cache.set(cachePath, cacheKey, dom);
|
|
4928
4849
|
}
|
|
@@ -4986,17 +4907,18 @@ function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
|
4986
4907
|
var css = String.raw;
|
|
4987
4908
|
var html = String.raw;
|
|
4988
4909
|
var macro = (defaults, rawView) => new Macro(defaults, rawView);
|
|
4910
|
+
var devOnly = (name, result) => {
|
|
4911
|
+
console.warn(`${name} is a no-op in the core tutuca build; import tutuca/dev for the real one`);
|
|
4912
|
+
return result;
|
|
4913
|
+
};
|
|
4989
4914
|
function check(_app) {
|
|
4990
|
-
return { error: 0, warn: 0, hint: 0
|
|
4915
|
+
return devOnly("check", { error: 0, warn: 0, hint: 0 });
|
|
4991
4916
|
}
|
|
4992
4917
|
async function test(_opts) {
|
|
4993
|
-
return null;
|
|
4918
|
+
return devOnly("test", null);
|
|
4994
4919
|
}
|
|
4995
4920
|
function collectIterBindings() {
|
|
4996
|
-
|
|
4997
|
-
"collectIterBindings is a no-op in the core tutuca build; use the tutuca-dev build for a functional implementation"
|
|
4998
|
-
);
|
|
4999
|
-
return [];
|
|
4921
|
+
return devOnly("collectIterBindings", []);
|
|
5000
4922
|
}
|
|
5001
4923
|
function tutuca(nodeOrSelector) {
|
|
5002
4924
|
const rootNode = typeof nodeOrSelector === "string" ? document.querySelector(nodeOrSelector) : nodeOrSelector;
|
|
@@ -5020,7 +4942,6 @@ async function compileClassesToStyleText(app, compileClasses, Ctx = ParseCtxClas
|
|
|
5020
4942
|
}
|
|
5021
4943
|
export {
|
|
5022
4944
|
COMPONENT,
|
|
5023
|
-
FIELD_CLASS,
|
|
5024
4945
|
PASS,
|
|
5025
4946
|
ParseContext,
|
|
5026
4947
|
SEQ_INFO,
|
|
@@ -5034,6 +4955,7 @@ export {
|
|
|
5034
4955
|
html,
|
|
5035
4956
|
injectCss,
|
|
5036
4957
|
macro,
|
|
4958
|
+
path,
|
|
5037
4959
|
phaseOps,
|
|
5038
4960
|
resolveArgs,
|
|
5039
4961
|
rootDispatcher,
|