@lark.js/mvc 0.0.2 → 0.0.4
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/README.md +554 -786
- package/dist/{chunk-5OEHRF3U.js → chunk-ANWA22AX.js} +100 -89
- package/dist/index.cjs +942 -691
- package/dist/index.d.cts +1475 -726
- package/dist/index.d.ts +1475 -726
- package/dist/index.js +939 -686
- package/dist/vite.cjs +100 -89
- package/dist/vite.d.cts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +100 -89
- package/dist/webpack.js +1 -1
- package/package.json +9 -6
- package/lark.d.ts +0 -1176
package/dist/index.js
CHANGED
|
@@ -6,10 +6,15 @@ var ROUTER_EVENTS = {
|
|
|
6
6
|
CHANGED: "changed",
|
|
7
7
|
PAGE_UNLOAD: "page_unload"
|
|
8
8
|
};
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
var LARK_KEYS = {
|
|
10
|
+
/** Attribute name: ldk (static key for skipping VDOM diff) */
|
|
11
|
+
DIFF_KEY: "ldk",
|
|
12
|
+
/** Attribute name: lak (static attribute key) */
|
|
13
|
+
ATTR_KEY: "lak",
|
|
14
|
+
/** Attribute name: lvk (view key for assign) */
|
|
15
|
+
VIEW_KEY: "lvk"
|
|
16
|
+
};
|
|
17
|
+
var LARK_VIEW = "v-lark";
|
|
13
18
|
var EVENT_METHOD_REGEXP = new RegExp(
|
|
14
19
|
`(?:([\\w-]+)${SPLITTER})?([^(]+)\\(([\\s\\S]*?)?\\)`
|
|
15
20
|
);
|
|
@@ -33,7 +38,6 @@ function isPlainObject(value) {
|
|
|
33
38
|
if (proto === null) return true;
|
|
34
39
|
return proto === Object.prototype || proto === null;
|
|
35
40
|
}
|
|
36
|
-
var isArray = Array.isArray;
|
|
37
41
|
function isPrimitiveOrFunc(value) {
|
|
38
42
|
return !value || typeof value !== "object" && typeof value !== "function";
|
|
39
43
|
}
|
|
@@ -74,13 +78,13 @@ function assign(target, ...sources) {
|
|
|
74
78
|
return target;
|
|
75
79
|
}
|
|
76
80
|
function funcWithTry(fns, args, context, configError) {
|
|
77
|
-
const fnArray = isArray(fns) ? fns : [fns];
|
|
81
|
+
const fnArray = Array.isArray(fns) ? fns : [fns];
|
|
78
82
|
let ret;
|
|
79
83
|
for (const fn of fnArray) {
|
|
80
84
|
try {
|
|
81
85
|
ret = Function.prototype.apply.call(fn, context, args);
|
|
82
86
|
} catch (e) {
|
|
83
|
-
configError(e);
|
|
87
|
+
configError?.(e);
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
return ret;
|
|
@@ -108,7 +112,7 @@ function translateData(data, value) {
|
|
|
108
112
|
}
|
|
109
113
|
return value;
|
|
110
114
|
}
|
|
111
|
-
if (isPlainObject(value) || isArray(value)) {
|
|
115
|
+
if (isPlainObject(value) || Array.isArray(value)) {
|
|
112
116
|
for (const p in value) {
|
|
113
117
|
if (has(value, p)) {
|
|
114
118
|
const val = value[p];
|
|
@@ -201,13 +205,13 @@ function toMap(list, key) {
|
|
|
201
205
|
function now() {
|
|
202
206
|
return Date.now ? Date.now() : (/* @__PURE__ */ new Date()).getTime();
|
|
203
207
|
}
|
|
204
|
-
function classExtend(
|
|
208
|
+
function classExtend(make, base, props, statics) {
|
|
205
209
|
const baseProto = base["prototype"] ?? {};
|
|
206
|
-
const
|
|
207
|
-
assign(
|
|
208
|
-
Object.assign(
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
const classProto = Object.create(baseProto);
|
|
211
|
+
assign(classProto, props);
|
|
212
|
+
Object.assign(make, statics);
|
|
213
|
+
classProto.constructor = make;
|
|
214
|
+
make["prototype"] = classProto;
|
|
211
215
|
}
|
|
212
216
|
|
|
213
217
|
// src/apply-style.ts
|
|
@@ -248,8 +252,8 @@ function applyStyle(styleIdOrPairs, css) {
|
|
|
248
252
|
}
|
|
249
253
|
|
|
250
254
|
// src/mark.ts
|
|
251
|
-
var DELETED_KEY = SPLITTER + "$
|
|
252
|
-
var MARK_OBJECT_KEY = SPLITTER + "$
|
|
255
|
+
var DELETED_KEY = SPLITTER + "$delFlag";
|
|
256
|
+
var MARK_OBJECT_KEY = SPLITTER + "$markKey";
|
|
253
257
|
function mark(host, key) {
|
|
254
258
|
let sign = 0;
|
|
255
259
|
const hostRecord = host;
|
|
@@ -273,9 +277,9 @@ function unmark(host) {
|
|
|
273
277
|
|
|
274
278
|
// src/safeguard.ts
|
|
275
279
|
var proxiesPool = /* @__PURE__ */ new Map();
|
|
276
|
-
var SAFEGUARD_SENTINEL = "
|
|
280
|
+
var SAFEGUARD_SENTINEL = "_safe_";
|
|
277
281
|
function safeguard(data, getter, setter, isRoot) {
|
|
278
|
-
if (typeof window.
|
|
282
|
+
if (typeof window.__lark_Debug === "undefined" || !window.__lark_Debug) {
|
|
279
283
|
return data;
|
|
280
284
|
}
|
|
281
285
|
if (typeof Proxy === "undefined") {
|
|
@@ -314,7 +318,7 @@ function safeguard(data, getter, setter, isRoot) {
|
|
|
314
318
|
if (!prefix && getter) {
|
|
315
319
|
getter(property);
|
|
316
320
|
}
|
|
317
|
-
if (!isRoot && has(target, property) && (isArray(out) || isPlainObject(out))) {
|
|
321
|
+
if (!isRoot && has(target, property) && (Array.isArray(out) || isPlainObject(out))) {
|
|
318
322
|
return build(prefix + property + ".", out);
|
|
319
323
|
}
|
|
320
324
|
return out;
|
|
@@ -489,7 +493,10 @@ var EventEmitter = class {
|
|
|
489
493
|
}
|
|
490
494
|
} else {
|
|
491
495
|
this.listeners.delete(key);
|
|
492
|
-
Reflect.deleteProperty(
|
|
496
|
+
Reflect.deleteProperty(
|
|
497
|
+
this,
|
|
498
|
+
`on${event[0].toUpperCase() + event.slice(1)}`
|
|
499
|
+
);
|
|
493
500
|
}
|
|
494
501
|
return this;
|
|
495
502
|
}
|
|
@@ -530,7 +537,7 @@ var EventEmitter = class {
|
|
|
530
537
|
}
|
|
531
538
|
}
|
|
532
539
|
}
|
|
533
|
-
const onMethodName = `on${event}`;
|
|
540
|
+
const onMethodName = `on${event[0].toUpperCase() + event.slice(1)}`;
|
|
534
541
|
const onMethod = this[onMethodName];
|
|
535
542
|
if (typeof onMethod === "function") {
|
|
536
543
|
funcWithTry(
|
|
@@ -577,7 +584,7 @@ function teardownKeysRef(keyList) {
|
|
|
577
584
|
if (count <= 0) {
|
|
578
585
|
Reflect.deleteProperty(keyRefCounts, key);
|
|
579
586
|
Reflect.deleteProperty(appData, key);
|
|
580
|
-
if (typeof window.
|
|
587
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
581
588
|
Reflect.deleteProperty(dataWhereSet, key);
|
|
582
589
|
}
|
|
583
590
|
}
|
|
@@ -620,7 +627,7 @@ var State = {
|
|
|
620
627
|
*/
|
|
621
628
|
get(key) {
|
|
622
629
|
const result = key ? appData[key] : appData;
|
|
623
|
-
if (typeof window.
|
|
630
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
624
631
|
return safeguard(
|
|
625
632
|
result,
|
|
626
633
|
(dataKey) => {
|
|
@@ -646,7 +653,7 @@ var State = {
|
|
|
646
653
|
*/
|
|
647
654
|
set(data, excludes) {
|
|
648
655
|
dataIsChanged = setData(data, appData, changedKeys, excludes || /* @__PURE__ */ new Set()) || dataIsChanged;
|
|
649
|
-
if (typeof window.
|
|
656
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && booted) {
|
|
650
657
|
for (const p in data) {
|
|
651
658
|
dataWhereSet[p] = window.location.pathname;
|
|
652
659
|
}
|
|
@@ -661,7 +668,7 @@ var State = {
|
|
|
661
668
|
State.set(data, excludes);
|
|
662
669
|
}
|
|
663
670
|
if (dataIsChanged) {
|
|
664
|
-
if (typeof window.
|
|
671
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
665
672
|
for (const p in changedKeys) {
|
|
666
673
|
if (has(changedKeys, p)) {
|
|
667
674
|
clearNotify(p);
|
|
@@ -692,7 +699,7 @@ var State = {
|
|
|
692
699
|
*/
|
|
693
700
|
clean(keys2) {
|
|
694
701
|
return {
|
|
695
|
-
|
|
702
|
+
make: function() {
|
|
696
703
|
const keyList = setupKeysRef(keys2);
|
|
697
704
|
this.on("destroy", () => {
|
|
698
705
|
teardownKeysRef(keyList);
|
|
@@ -721,6 +728,7 @@ var State = {
|
|
|
721
728
|
emitter.fire(event, data, remove);
|
|
722
729
|
return State;
|
|
723
730
|
}
|
|
731
|
+
// onChanged: noop,
|
|
724
732
|
};
|
|
725
733
|
|
|
726
734
|
// src/router.ts
|
|
@@ -873,7 +881,7 @@ var Router = {
|
|
|
873
881
|
attachViewAndPath(location);
|
|
874
882
|
hrefCache.set(href, location);
|
|
875
883
|
}
|
|
876
|
-
if (typeof window.
|
|
884
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
877
885
|
location["params"] = safeguard(location["params"]);
|
|
878
886
|
}
|
|
879
887
|
return location;
|
|
@@ -897,7 +905,7 @@ var Router = {
|
|
|
897
905
|
);
|
|
898
906
|
}
|
|
899
907
|
silent = 0;
|
|
900
|
-
if (typeof window.
|
|
908
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && lastChanged) {
|
|
901
909
|
lastChanged = safeguard(lastChanged);
|
|
902
910
|
}
|
|
903
911
|
return lastChanged;
|
|
@@ -1026,9 +1034,9 @@ var Router = {
|
|
|
1026
1034
|
window.addEventListener("hashchange", watchChange);
|
|
1027
1035
|
window.addEventListener("popstate", watchChange);
|
|
1028
1036
|
window.addEventListener("beforeunload", (domEvent) => {
|
|
1029
|
-
const
|
|
1030
|
-
Router.fire(ROUTER_EVENTS.PAGE_UNLOAD,
|
|
1031
|
-
const msg =
|
|
1037
|
+
const data = {};
|
|
1038
|
+
Router.fire(ROUTER_EVENTS.PAGE_UNLOAD, data);
|
|
1039
|
+
const msg = data["msg"];
|
|
1032
1040
|
if (msg) {
|
|
1033
1041
|
domEvent.returnValue = msg;
|
|
1034
1042
|
}
|
|
@@ -1060,26 +1068,26 @@ var frameGetter;
|
|
|
1060
1068
|
function parseEventInfo(eventInfo) {
|
|
1061
1069
|
const cached = eventInfoCache.get(eventInfo);
|
|
1062
1070
|
if (cached) {
|
|
1063
|
-
return assign({}, cached, {
|
|
1071
|
+
return assign({}, cached, { value: eventInfo });
|
|
1064
1072
|
}
|
|
1065
1073
|
const match = eventInfo.match(EVENT_METHOD_REGEXP) || [];
|
|
1066
1074
|
const result = {
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1075
|
+
id: match[1] || "",
|
|
1076
|
+
name: match[2] || "",
|
|
1077
|
+
params: match[3] || ""
|
|
1070
1078
|
};
|
|
1071
1079
|
eventInfoCache.set(eventInfo, result);
|
|
1072
|
-
return assign({}, result, {
|
|
1080
|
+
return assign({}, result, { value: eventInfo });
|
|
1073
1081
|
}
|
|
1074
1082
|
function findFrameInfo(current, eventType) {
|
|
1075
1083
|
const eventInfos = [];
|
|
1076
1084
|
let begin = current;
|
|
1077
|
-
const info = current.getAttribute(
|
|
1085
|
+
const info = current.getAttribute(`@${eventType}`);
|
|
1078
1086
|
let match;
|
|
1079
1087
|
if (info) {
|
|
1080
1088
|
match = parseEventInfo(info);
|
|
1081
1089
|
}
|
|
1082
|
-
if (match && !match.
|
|
1090
|
+
if (match && !match.id || selectorEvents[eventType]) {
|
|
1083
1091
|
let selectorFrameId = "#";
|
|
1084
1092
|
let backtrace = 0;
|
|
1085
1093
|
while (begin && begin !== document.body) {
|
|
@@ -1105,10 +1113,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1105
1113
|
if (selectorEntry) {
|
|
1106
1114
|
for (const selectorName of selectorEntry.selectors) {
|
|
1107
1115
|
const entry = {
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1116
|
+
value: selectorName,
|
|
1117
|
+
id: frameId,
|
|
1118
|
+
name: selectorName,
|
|
1119
|
+
params: ""
|
|
1112
1120
|
};
|
|
1113
1121
|
if (selectorName) {
|
|
1114
1122
|
if (!backtrace && elementMatchesSelector(current, selectorName)) {
|
|
@@ -1120,8 +1128,8 @@ function findFrameInfo(current, eventType) {
|
|
|
1120
1128
|
}
|
|
1121
1129
|
}
|
|
1122
1130
|
if (view.template && !backtrace) {
|
|
1123
|
-
if (match && !match.
|
|
1124
|
-
match.
|
|
1131
|
+
if (match && !match.id) {
|
|
1132
|
+
match.id = frameId;
|
|
1125
1133
|
}
|
|
1126
1134
|
break;
|
|
1127
1135
|
}
|
|
@@ -1137,10 +1145,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1137
1145
|
}
|
|
1138
1146
|
if (match) {
|
|
1139
1147
|
eventInfos.push({
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1148
|
+
id: match.id,
|
|
1149
|
+
value: match.value,
|
|
1150
|
+
name: match.name,
|
|
1151
|
+
params: match.params
|
|
1144
1152
|
});
|
|
1145
1153
|
}
|
|
1146
1154
|
return eventInfos;
|
|
@@ -1161,7 +1169,7 @@ function domEventProcessor(domEvent) {
|
|
|
1161
1169
|
const eventInfos = findFrameInfo(current, eventType);
|
|
1162
1170
|
if (eventInfos.length) {
|
|
1163
1171
|
for (const info of eventInfos) {
|
|
1164
|
-
const {
|
|
1172
|
+
const { id: frameId, name: handlerName, params } = info;
|
|
1165
1173
|
if (lastFrameId !== frameId) {
|
|
1166
1174
|
if (lastFrameId && domEvent.isPropagationStopped?.()) {
|
|
1167
1175
|
break;
|
|
@@ -1260,8 +1268,8 @@ var WrapMeta = {
|
|
|
1260
1268
|
td: [3, "<table><tbody><tr>"],
|
|
1261
1269
|
area: [1, "<map>"],
|
|
1262
1270
|
param: [1, "<object>"],
|
|
1263
|
-
|
|
1264
|
-
|
|
1271
|
+
svg: [1, '<svg xmlns="' + SVG_NS + '">'],
|
|
1272
|
+
math: [1, '<math xmlns="' + MATH_NS + '">'],
|
|
1265
1273
|
_: [0, ""]
|
|
1266
1274
|
};
|
|
1267
1275
|
WrapMeta["optgroup"] = WrapMeta["option"];
|
|
@@ -1294,9 +1302,9 @@ function vdomGetNode(html, refNode) {
|
|
|
1294
1302
|
const ns = refNode.namespaceURI;
|
|
1295
1303
|
let tag;
|
|
1296
1304
|
if (ns === SVG_NS) {
|
|
1297
|
-
tag = "
|
|
1305
|
+
tag = "svg";
|
|
1298
1306
|
} else if (ns === MATH_NS) {
|
|
1299
|
-
tag = "
|
|
1307
|
+
tag = "math";
|
|
1300
1308
|
} else {
|
|
1301
1309
|
const match = TAG_NAME_REGEXP.exec(html);
|
|
1302
1310
|
tag = match ? match[1] : "";
|
|
@@ -1318,7 +1326,7 @@ function vdomGetCompareKey(node) {
|
|
|
1318
1326
|
}
|
|
1319
1327
|
let key = el.autoId ? "" : el.getAttribute("id") || void 0;
|
|
1320
1328
|
if (!key) {
|
|
1321
|
-
key = el.getAttribute(
|
|
1329
|
+
key = el.getAttribute(LARK_KEYS.DIFF_KEY) || void 0;
|
|
1322
1330
|
}
|
|
1323
1331
|
if (!key) {
|
|
1324
1332
|
const larkView = el.getAttribute(LARK_VIEW);
|
|
@@ -1446,17 +1454,17 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1446
1454
|
}
|
|
1447
1455
|
}
|
|
1448
1456
|
function vdomSetNode(oldNode, newNode, oldParent, ref, frame, keys_) {
|
|
1449
|
-
if (vdomSpecialDiff(oldNode, newNode) || oldNode.nodeType === 1 && oldNode.hasAttribute(
|
|
1457
|
+
if (vdomSpecialDiff(oldNode, newNode) || oldNode.nodeType === 1 && oldNode.hasAttribute(LARK_KEYS.VIEW_KEY) || !(oldNode.isEqualNode && oldNode.isEqualNode(newNode))) {
|
|
1450
1458
|
if (oldNode.nodeType === newNode.nodeType && oldNode.nodeName === newNode.nodeName) {
|
|
1451
1459
|
if (oldNode.nodeType === 1) {
|
|
1452
1460
|
const oldEl = oldNode;
|
|
1453
1461
|
const newEl = newNode;
|
|
1454
|
-
const staticKey = newEl.getAttribute(
|
|
1455
|
-
if (staticKey && staticKey === oldEl.getAttribute(
|
|
1462
|
+
const staticKey = newEl.getAttribute(LARK_KEYS.DIFF_KEY);
|
|
1463
|
+
if (staticKey && staticKey === oldEl.getAttribute(LARK_KEYS.DIFF_KEY)) {
|
|
1456
1464
|
return;
|
|
1457
1465
|
}
|
|
1458
1466
|
const newLarkView = newEl.getAttribute(LARK_VIEW);
|
|
1459
|
-
const updateAttribute = !newEl.getAttribute(
|
|
1467
|
+
const updateAttribute = !newEl.getAttribute(LARK_KEYS.ATTR_KEY) || newEl.getAttribute(LARK_KEYS.ATTR_KEY) !== oldEl.getAttribute(LARK_KEYS.ATTR_KEY);
|
|
1460
1468
|
let updateChildren = true;
|
|
1461
1469
|
if (newLarkView) {
|
|
1462
1470
|
const oldFrameId = oldEl.getAttribute("id") || "";
|
|
@@ -1601,7 +1609,7 @@ var Updater = class {
|
|
|
1601
1609
|
if (key) {
|
|
1602
1610
|
result = this.data[key];
|
|
1603
1611
|
}
|
|
1604
|
-
if (typeof window !== "undefined" && window.
|
|
1612
|
+
if (typeof window !== "undefined" && window.__lark_Debug) {
|
|
1605
1613
|
return safeguard(result);
|
|
1606
1614
|
}
|
|
1607
1615
|
return result;
|
|
@@ -1736,225 +1744,10 @@ var Updater = class {
|
|
|
1736
1744
|
// src/view.ts
|
|
1737
1745
|
var VIEW_GLOBALS = {};
|
|
1738
1746
|
if (typeof window !== "undefined") {
|
|
1739
|
-
VIEW_GLOBALS["
|
|
1747
|
+
VIEW_GLOBALS["window"] = window;
|
|
1740
1748
|
}
|
|
1741
1749
|
if (typeof document !== "undefined") {
|
|
1742
|
-
VIEW_GLOBALS["
|
|
1743
|
-
}
|
|
1744
|
-
function viewPrepare(oView) {
|
|
1745
|
-
if (oView.ctors) {
|
|
1746
|
-
return oView.ctors;
|
|
1747
|
-
}
|
|
1748
|
-
const ctors = [];
|
|
1749
|
-
oView.ctors = ctors;
|
|
1750
|
-
const proto = oView.prototype;
|
|
1751
|
-
const eventsObject = {};
|
|
1752
|
-
const eventsList = [];
|
|
1753
|
-
const selectorObject = {};
|
|
1754
|
-
const mixins = proto["mixins"];
|
|
1755
|
-
if (mixins && Array.isArray(mixins)) {
|
|
1756
|
-
viewMergeMixins(mixins, oView, ctors);
|
|
1757
|
-
}
|
|
1758
|
-
for (const p in proto) {
|
|
1759
|
-
if (!has(proto, p)) continue;
|
|
1760
|
-
const currentFn = proto[p];
|
|
1761
|
-
if (typeof currentFn !== "function") continue;
|
|
1762
|
-
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
1763
|
-
if (!matches) continue;
|
|
1764
|
-
const isSelector = matches[1];
|
|
1765
|
-
const selectorOrCallback = matches[2];
|
|
1766
|
-
const events = matches[3];
|
|
1767
|
-
const modifiers = matches[4];
|
|
1768
|
-
const mod = {};
|
|
1769
|
-
if (modifiers) {
|
|
1770
|
-
for (const item of modifiers.split(",")) {
|
|
1771
|
-
mod[item] = true;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
const eventTypes = events.split(",");
|
|
1775
|
-
for (const item of eventTypes) {
|
|
1776
|
-
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
1777
|
-
let mask = 1;
|
|
1778
|
-
if (isSelector) {
|
|
1779
|
-
if (globalNode) {
|
|
1780
|
-
eventsList.push({
|
|
1781
|
-
handler: currentFn,
|
|
1782
|
-
element: globalNode,
|
|
1783
|
-
eventName: item,
|
|
1784
|
-
modifiers: mod
|
|
1785
|
-
});
|
|
1786
|
-
continue;
|
|
1787
|
-
}
|
|
1788
|
-
mask = 2;
|
|
1789
|
-
let selectorEntry = selectorObject[item];
|
|
1790
|
-
if (!selectorEntry) {
|
|
1791
|
-
selectorEntry = selectorObject[item] = {
|
|
1792
|
-
selectors: []
|
|
1793
|
-
};
|
|
1794
|
-
}
|
|
1795
|
-
if (!selectorEntry[selectorOrCallback]) {
|
|
1796
|
-
selectorEntry[selectorOrCallback] = 1;
|
|
1797
|
-
selectorEntry.selectors.push(selectorOrCallback);
|
|
1798
|
-
}
|
|
1799
|
-
}
|
|
1800
|
-
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
1801
|
-
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
1802
|
-
const existingFn = proto[combinedKey];
|
|
1803
|
-
if (!existingFn) {
|
|
1804
|
-
proto[combinedKey] = currentFn;
|
|
1805
|
-
} else {
|
|
1806
|
-
const mixinFn = currentFn;
|
|
1807
|
-
const existingMixin = existingFn;
|
|
1808
|
-
if (existingMixin.b) {
|
|
1809
|
-
if (mixinFn.b) {
|
|
1810
|
-
proto[combinedKey] = processMixinsSameEvent(
|
|
1811
|
-
currentFn,
|
|
1812
|
-
existingFn
|
|
1813
|
-
);
|
|
1814
|
-
} else if (has(proto, p)) {
|
|
1815
|
-
proto[combinedKey] = currentFn;
|
|
1816
|
-
}
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1821
|
-
viewWrapMethod(proto, "render", "$b");
|
|
1822
|
-
proto["$eo"] = eventsObject;
|
|
1823
|
-
proto["$el"] = eventsList;
|
|
1824
|
-
proto["$so"] = selectorObject;
|
|
1825
|
-
proto["$f"] = proto["assign"];
|
|
1826
|
-
return ctors;
|
|
1827
|
-
}
|
|
1828
|
-
function viewWrapMethod(proto, fnName, shortKey) {
|
|
1829
|
-
const originalFn = proto[fnName];
|
|
1830
|
-
if (typeof originalFn !== "function") return;
|
|
1831
|
-
const wrapped = function(...args) {
|
|
1832
|
-
if (this.signature > 0) {
|
|
1833
|
-
this.signature++;
|
|
1834
|
-
this.fire("rendercall");
|
|
1835
|
-
destroyAllResources(this, false);
|
|
1836
|
-
const instanceFn = typeof this[fnName] === "function" ? this[fnName] : originalFn;
|
|
1837
|
-
const fnToCall = instanceFn === wrapped ? originalFn : instanceFn;
|
|
1838
|
-
return funcWithTry(fnToCall, args, this, noop);
|
|
1839
|
-
}
|
|
1840
|
-
return void 0;
|
|
1841
|
-
};
|
|
1842
|
-
proto[fnName] = wrapped;
|
|
1843
|
-
proto[shortKey] = wrapped;
|
|
1844
|
-
}
|
|
1845
|
-
function processMixinsSameEvent(additional, exist) {
|
|
1846
|
-
let temp;
|
|
1847
|
-
const existMixin = exist;
|
|
1848
|
-
if (existMixin.a) {
|
|
1849
|
-
temp = existMixin;
|
|
1850
|
-
} else {
|
|
1851
|
-
temp = function(...e) {
|
|
1852
|
-
funcWithTry(temp.a ?? [], e, this, noop);
|
|
1853
|
-
};
|
|
1854
|
-
temp.a = [exist];
|
|
1855
|
-
temp.b = 1;
|
|
1856
|
-
}
|
|
1857
|
-
const additionalMixin = additional;
|
|
1858
|
-
temp.a = (temp.a ?? []).concat(additionalMixin.a ?? [additional]);
|
|
1859
|
-
return temp;
|
|
1860
|
-
}
|
|
1861
|
-
function viewMergeMixins(mixins, viewClass, ctors) {
|
|
1862
|
-
const proto = viewClass.prototype;
|
|
1863
|
-
const temp = {};
|
|
1864
|
-
for (const node of mixins) {
|
|
1865
|
-
for (const p in node) {
|
|
1866
|
-
if (!has(node, p)) continue;
|
|
1867
|
-
const fn = node[p];
|
|
1868
|
-
const exist = temp[p];
|
|
1869
|
-
if (p === "ctor") {
|
|
1870
|
-
ctors.push(fn);
|
|
1871
|
-
continue;
|
|
1872
|
-
}
|
|
1873
|
-
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
1874
|
-
if (exist) {
|
|
1875
|
-
temp[p] = processMixinsSameEvent(fn, exist);
|
|
1876
|
-
} else {
|
|
1877
|
-
fn.b = 1;
|
|
1878
|
-
temp[p] = fn;
|
|
1879
|
-
}
|
|
1880
|
-
} else {
|
|
1881
|
-
if (!exist) {
|
|
1882
|
-
temp[p] = fn;
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
for (const p in temp) {
|
|
1888
|
-
if (!has(proto, p)) {
|
|
1889
|
-
proto[p] = temp[p];
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
function viewDelegateEvents(view, destroy = false) {
|
|
1894
|
-
const proto = Object.getPrototypeOf(view) ?? {};
|
|
1895
|
-
const eventsObject = proto["$eo"] || view.eventObjectMap;
|
|
1896
|
-
const selectorObject = proto["$so"] || view.eventSelectorMap;
|
|
1897
|
-
const eventsList = proto["$el"] || view.globalEventList;
|
|
1898
|
-
for (const e in eventsObject) {
|
|
1899
|
-
if (has(eventsObject, e)) {
|
|
1900
|
-
if (destroy) {
|
|
1901
|
-
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
1902
|
-
} else {
|
|
1903
|
-
EventDelegator.bind(e, !!selectorObject[e]);
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
}
|
|
1907
|
-
for (const entry of eventsList) {
|
|
1908
|
-
if (destroy) {
|
|
1909
|
-
entry.element.removeEventListener(
|
|
1910
|
-
entry.eventName,
|
|
1911
|
-
entry.boundHandler
|
|
1912
|
-
);
|
|
1913
|
-
} else {
|
|
1914
|
-
const handler = entry.handler;
|
|
1915
|
-
const element = entry.element;
|
|
1916
|
-
const modifiers = entry.modifiers;
|
|
1917
|
-
entry.boundHandler = function(domEvent) {
|
|
1918
|
-
const extendedEvent = domEvent;
|
|
1919
|
-
extendedEvent.eventTarget = element;
|
|
1920
|
-
if (modifiers) {
|
|
1921
|
-
const kbEvent = domEvent;
|
|
1922
|
-
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
1923
|
-
return;
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
funcWithTry(handler, [domEvent], view, noop);
|
|
1927
|
-
};
|
|
1928
|
-
entry.element.addEventListener(
|
|
1929
|
-
entry.eventName,
|
|
1930
|
-
entry.boundHandler
|
|
1931
|
-
);
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
function destroyAllResources(view, lastly) {
|
|
1936
|
-
const cache = view.resources;
|
|
1937
|
-
for (const p in cache) {
|
|
1938
|
-
if (has(cache, p)) {
|
|
1939
|
-
const entry = cache[p];
|
|
1940
|
-
if (lastly || entry.destroyOnRender) {
|
|
1941
|
-
destroyResource(cache, p, true);
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
function destroyResource(cache, key, callDestroy, oldEntity) {
|
|
1947
|
-
const entry = cache[key];
|
|
1948
|
-
if (!entry || entry.entity === oldEntity) return void 0;
|
|
1949
|
-
const entity = entry.entity;
|
|
1950
|
-
if (entity && typeof entity === "object") {
|
|
1951
|
-
const destroyFn = entity["destroy"];
|
|
1952
|
-
if (typeof destroyFn === "function" && callDestroy) {
|
|
1953
|
-
funcWithTry(destroyFn, [], entity, noop);
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
Reflect.deleteProperty(cache, key);
|
|
1957
|
-
return entity;
|
|
1750
|
+
VIEW_GLOBALS["document"] = document;
|
|
1958
1751
|
}
|
|
1959
1752
|
var View = class _View {
|
|
1960
1753
|
/** View ID (same as owner frame ID) */
|
|
@@ -1979,18 +1772,43 @@ var View = class _View {
|
|
|
1979
1772
|
observedStateKeys;
|
|
1980
1773
|
/** Resource map */
|
|
1981
1774
|
resources = {};
|
|
1982
|
-
/** Selector event map: eventType -> handler name list */
|
|
1983
|
-
eventSelectorMap = {};
|
|
1984
|
-
/** Event object map: eventType -> bitmask */
|
|
1985
|
-
eventObjectMap = {};
|
|
1986
|
-
/** Global event list */
|
|
1987
|
-
globalEventList = [];
|
|
1988
1775
|
/** Assign method reference */
|
|
1989
1776
|
assignMethod;
|
|
1990
1777
|
/** Whether endUpdate pending */
|
|
1991
1778
|
endUpdatePending;
|
|
1992
1779
|
/** Internal event storage */
|
|
1993
1780
|
_events = new EventEmitter();
|
|
1781
|
+
// ============================================================
|
|
1782
|
+
// Getters for prototype-stored event maps
|
|
1783
|
+
// ============================================================
|
|
1784
|
+
/**
|
|
1785
|
+
* Event bitmask map: eventType -> bitmask (1=root, 2=selector).
|
|
1786
|
+
* Read from prototype ($evtObjMap) set by View.prepare.
|
|
1787
|
+
* Using a getter avoids ES6 class field shadowing the prototype value.
|
|
1788
|
+
*/
|
|
1789
|
+
get eventObjectMap() {
|
|
1790
|
+
const proto = Object.getPrototypeOf(this);
|
|
1791
|
+
return proto["$evtObjMap"] || {};
|
|
1792
|
+
}
|
|
1793
|
+
/**
|
|
1794
|
+
* Selector event map: eventType -> selector list.
|
|
1795
|
+
* Read from prototype ($selMap) set by View.prepare.
|
|
1796
|
+
*/
|
|
1797
|
+
get eventSelectorMap() {
|
|
1798
|
+
const proto = Object.getPrototypeOf(this);
|
|
1799
|
+
return proto["$selMap"] || {};
|
|
1800
|
+
}
|
|
1801
|
+
/**
|
|
1802
|
+
* Global event list: [{handler, element, eventName, modifiers}].
|
|
1803
|
+
* Read from prototype ($globalEvtList) set by View.prepare.
|
|
1804
|
+
*/
|
|
1805
|
+
get globalEventList() {
|
|
1806
|
+
const proto = Object.getPrototypeOf(this);
|
|
1807
|
+
return proto["$globalEvtList"] || [];
|
|
1808
|
+
}
|
|
1809
|
+
// ============================================================
|
|
1810
|
+
// Instance lifecycle methods
|
|
1811
|
+
// ============================================================
|
|
1994
1812
|
/**
|
|
1995
1813
|
* Initialize view (called by Frame when mounting).
|
|
1996
1814
|
*/
|
|
@@ -1998,14 +1816,7 @@ var View = class _View {
|
|
|
1998
1816
|
}
|
|
1999
1817
|
/**
|
|
2000
1818
|
* Render view template (called by Frame after init).
|
|
2001
|
-
* Wrapped by
|
|
2002
|
-
*
|
|
2003
|
-
* Default implementation calls updater.digest() which:
|
|
2004
|
-
* 1. Executes the template function with current data
|
|
2005
|
-
* 2. Runs VDOM diff against previous DOM
|
|
2006
|
-
* 3. Applies DOM operations
|
|
2007
|
-
* 4. Calls endUpdate to mount child frames
|
|
2008
|
-
*
|
|
1819
|
+
* Wrapped by View.wrapMethod to manage signature + resources.
|
|
2009
1820
|
*/
|
|
2010
1821
|
render() {
|
|
2011
1822
|
this.updater.digest();
|
|
@@ -2057,7 +1868,7 @@ var View = class _View {
|
|
|
2057
1868
|
if (!flag) {
|
|
2058
1869
|
setTimeout(
|
|
2059
1870
|
this.wrapAsync(() => {
|
|
2060
|
-
runInvokes(ownerFrame);
|
|
1871
|
+
_View.runInvokes(ownerFrame);
|
|
2061
1872
|
}),
|
|
2062
1873
|
0
|
|
2063
1874
|
);
|
|
@@ -2133,7 +1944,7 @@ var View = class _View {
|
|
|
2133
1944
|
capture(key, resource, destroyOnRender = false) {
|
|
2134
1945
|
const cache = this.resources;
|
|
2135
1946
|
if (resource) {
|
|
2136
|
-
destroyResource(cache, key, true, resource);
|
|
1947
|
+
_View.destroyResource(cache, key, true, resource);
|
|
2137
1948
|
cache[key] = {
|
|
2138
1949
|
entity: resource,
|
|
2139
1950
|
destroyOnRender
|
|
@@ -2149,7 +1960,7 @@ var View = class _View {
|
|
|
2149
1960
|
* If destroy=true, calls the resource's destroy() method.
|
|
2150
1961
|
*/
|
|
2151
1962
|
release(key, destroy = true) {
|
|
2152
|
-
return destroyResource(this.resources, key, destroy);
|
|
1963
|
+
return _View.destroyResource(this.resources, key, destroy);
|
|
2153
1964
|
}
|
|
2154
1965
|
// ============================================================
|
|
2155
1966
|
// Leave tip
|
|
@@ -2195,31 +2006,294 @@ var View = class _View {
|
|
|
2195
2006
|
});
|
|
2196
2007
|
}
|
|
2197
2008
|
// ============================================================
|
|
2198
|
-
// Static
|
|
2009
|
+
// Static public methods
|
|
2199
2010
|
// ============================================================
|
|
2200
2011
|
/** Collected ctors from mixins */
|
|
2201
2012
|
static ctors;
|
|
2013
|
+
/**
|
|
2014
|
+
* Prepare a View subclass by scanning its prototype for event method patterns.
|
|
2015
|
+
* Pattern: `$?name<eventType1,eventType2>(&modifiers)`
|
|
2016
|
+
*
|
|
2017
|
+
* Only runs once per View subclass (guarded by ctors marker).
|
|
2018
|
+
* Called from Frame.mountView before creating the view instance.
|
|
2019
|
+
*/
|
|
2020
|
+
static prepare(oView) {
|
|
2021
|
+
if (oView.ctors) {
|
|
2022
|
+
return oView.ctors;
|
|
2023
|
+
}
|
|
2024
|
+
const ctors = [];
|
|
2025
|
+
oView.ctors = ctors;
|
|
2026
|
+
const proto = oView.prototype;
|
|
2027
|
+
const eventsObject = {};
|
|
2028
|
+
const eventsList = [];
|
|
2029
|
+
const selectorObject = {};
|
|
2030
|
+
const mixins = proto["mixins"];
|
|
2031
|
+
if (mixins && Array.isArray(mixins)) {
|
|
2032
|
+
_View.mergeMixins(mixins, oView, ctors);
|
|
2033
|
+
}
|
|
2034
|
+
for (const p in proto) {
|
|
2035
|
+
if (!has(proto, p)) continue;
|
|
2036
|
+
const currentFn = proto[p];
|
|
2037
|
+
if (typeof currentFn !== "function") continue;
|
|
2038
|
+
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
2039
|
+
if (!matches) continue;
|
|
2040
|
+
const isSelector = matches[1];
|
|
2041
|
+
const selectorOrCallback = matches[2];
|
|
2042
|
+
const events = matches[3];
|
|
2043
|
+
const modifiers = matches[4];
|
|
2044
|
+
const mod = {};
|
|
2045
|
+
if (modifiers) {
|
|
2046
|
+
for (const item of modifiers.split(",")) {
|
|
2047
|
+
mod[item] = true;
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
const eventTypes = events.split(",");
|
|
2051
|
+
for (const item of eventTypes) {
|
|
2052
|
+
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
2053
|
+
let mask = 1;
|
|
2054
|
+
if (isSelector) {
|
|
2055
|
+
if (globalNode) {
|
|
2056
|
+
eventsList.push({
|
|
2057
|
+
handler: currentFn,
|
|
2058
|
+
element: globalNode,
|
|
2059
|
+
eventName: item,
|
|
2060
|
+
modifiers: mod
|
|
2061
|
+
});
|
|
2062
|
+
continue;
|
|
2063
|
+
}
|
|
2064
|
+
mask = 2;
|
|
2065
|
+
let selectorEntry = selectorObject[item];
|
|
2066
|
+
if (!selectorEntry) {
|
|
2067
|
+
selectorEntry = selectorObject[item] = {
|
|
2068
|
+
selectors: []
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
if (!selectorEntry[selectorOrCallback]) {
|
|
2072
|
+
selectorEntry[selectorOrCallback] = 1;
|
|
2073
|
+
selectorEntry.selectors.push(selectorOrCallback);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
2077
|
+
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
2078
|
+
const existingFn = proto[combinedKey];
|
|
2079
|
+
if (!existingFn) {
|
|
2080
|
+
proto[combinedKey] = currentFn;
|
|
2081
|
+
} else {
|
|
2082
|
+
const mixinFn = currentFn;
|
|
2083
|
+
const existingMixin = existingFn;
|
|
2084
|
+
if (existingMixin.marker) {
|
|
2085
|
+
if (mixinFn.marker) {
|
|
2086
|
+
proto[combinedKey] = _View.processMixinsSameEvent(
|
|
2087
|
+
currentFn,
|
|
2088
|
+
existingFn
|
|
2089
|
+
);
|
|
2090
|
+
} else if (has(proto, p)) {
|
|
2091
|
+
proto[combinedKey] = currentFn;
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
_View.wrapMethod(proto, "render", "$renderWrap");
|
|
2098
|
+
proto["$evtObjMap"] = eventsObject;
|
|
2099
|
+
proto["$globalEvtList"] = eventsList;
|
|
2100
|
+
proto["$selMap"] = selectorObject;
|
|
2101
|
+
proto["$assignFn"] = proto["assign"];
|
|
2102
|
+
return ctors;
|
|
2103
|
+
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Bind or unbind event delegation for a view instance.
|
|
2106
|
+
* Called from Frame during mount/unmount.
|
|
2107
|
+
*/
|
|
2108
|
+
static delegateEvents(view, destroy = false) {
|
|
2109
|
+
const eventsObject = view.eventObjectMap;
|
|
2110
|
+
const selectorObject = view.eventSelectorMap;
|
|
2111
|
+
const eventsList = view.globalEventList;
|
|
2112
|
+
for (const e in eventsObject) {
|
|
2113
|
+
if (has(eventsObject, e)) {
|
|
2114
|
+
if (destroy) {
|
|
2115
|
+
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
2116
|
+
} else {
|
|
2117
|
+
EventDelegator.bind(e, !!selectorObject[e]);
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
for (const entry of eventsList) {
|
|
2122
|
+
if (destroy) {
|
|
2123
|
+
entry.element.removeEventListener(
|
|
2124
|
+
entry.eventName,
|
|
2125
|
+
entry.boundHandler
|
|
2126
|
+
);
|
|
2127
|
+
} else {
|
|
2128
|
+
const handler = entry.handler;
|
|
2129
|
+
const element = entry.element;
|
|
2130
|
+
const modifiers = entry.modifiers;
|
|
2131
|
+
entry.boundHandler = function(domEvent) {
|
|
2132
|
+
const extendedEvent = domEvent;
|
|
2133
|
+
extendedEvent.eventTarget = element;
|
|
2134
|
+
if (modifiers) {
|
|
2135
|
+
const kbEvent = domEvent;
|
|
2136
|
+
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
funcWithTry(handler, [domEvent], view, noop);
|
|
2141
|
+
};
|
|
2142
|
+
entry.element.addEventListener(
|
|
2143
|
+
entry.eventName,
|
|
2144
|
+
entry.boundHandler
|
|
2145
|
+
);
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
/**
|
|
2150
|
+
* Destroy all resources managed by a view.
|
|
2151
|
+
* If lastly=true, destroy ALL resources; otherwise only destroyOnRender ones.
|
|
2152
|
+
*/
|
|
2153
|
+
static destroyAllResources(view, lastly) {
|
|
2154
|
+
const cache = view.resources;
|
|
2155
|
+
for (const p in cache) {
|
|
2156
|
+
if (has(cache, p)) {
|
|
2157
|
+
const entry = cache[p];
|
|
2158
|
+
if (lastly || entry.destroyOnRender) {
|
|
2159
|
+
_View.destroyResource(cache, p, true);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
/**
|
|
2165
|
+
* Process deferred invoke calls on a frame.
|
|
2166
|
+
*/
|
|
2167
|
+
static runInvokes(frame) {
|
|
2168
|
+
const list = frame.invokeList;
|
|
2169
|
+
if (!list) return;
|
|
2170
|
+
while (list.length) {
|
|
2171
|
+
const entry = list.shift();
|
|
2172
|
+
if (entry && !entry.removed) {
|
|
2173
|
+
frame.invoke(entry.name, entry.args);
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
// ============================================================
|
|
2178
|
+
// Static private methods
|
|
2179
|
+
// ============================================================
|
|
2180
|
+
/**
|
|
2181
|
+
* Wrap a method on the prototype to add signature checking and resource cleanup.
|
|
2182
|
+
*/
|
|
2183
|
+
static wrapMethod(proto, fnName, shortKey) {
|
|
2184
|
+
const originalFn = proto[fnName];
|
|
2185
|
+
if (typeof originalFn !== "function") return;
|
|
2186
|
+
const wrapped = function(...args) {
|
|
2187
|
+
if (this.signature > 0) {
|
|
2188
|
+
this.signature++;
|
|
2189
|
+
this.fire("render");
|
|
2190
|
+
_View.destroyAllResources(this, false);
|
|
2191
|
+
const instanceFn = typeof this[fnName] === "function" ? this[fnName] : originalFn;
|
|
2192
|
+
const fnToCall = instanceFn === wrapped ? originalFn : instanceFn;
|
|
2193
|
+
return funcWithTry(fnToCall, args, this, noop);
|
|
2194
|
+
}
|
|
2195
|
+
return void 0;
|
|
2196
|
+
};
|
|
2197
|
+
proto[fnName] = wrapped;
|
|
2198
|
+
proto[shortKey] = wrapped;
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* When two mixins define the same event method, merge them into
|
|
2202
|
+
* a single function that calls both in sequence.
|
|
2203
|
+
*/
|
|
2204
|
+
static processMixinsSameEvent(additional, exist) {
|
|
2205
|
+
let temp;
|
|
2206
|
+
const existMixin = exist;
|
|
2207
|
+
if (existMixin.handlerList) {
|
|
2208
|
+
temp = existMixin;
|
|
2209
|
+
} else {
|
|
2210
|
+
temp = function(...e) {
|
|
2211
|
+
funcWithTry(temp.handlerList ?? [], e, this, noop);
|
|
2212
|
+
};
|
|
2213
|
+
temp.handlerList = [exist];
|
|
2214
|
+
temp.marker = 1;
|
|
2215
|
+
}
|
|
2216
|
+
const additionalMixin = additional;
|
|
2217
|
+
temp.handlerList = (temp.handlerList ?? []).concat(
|
|
2218
|
+
additionalMixin.handlerList ?? [additional]
|
|
2219
|
+
);
|
|
2220
|
+
return temp;
|
|
2221
|
+
}
|
|
2222
|
+
/**
|
|
2223
|
+
* Merge an array of mixin objects into the view prototype.
|
|
2224
|
+
*/
|
|
2225
|
+
static mergeMixins(mixins, viewClass, ctors) {
|
|
2226
|
+
const proto = viewClass.prototype;
|
|
2227
|
+
const temp = {};
|
|
2228
|
+
for (const node of mixins) {
|
|
2229
|
+
for (const p in node) {
|
|
2230
|
+
if (!has(node, p)) continue;
|
|
2231
|
+
const fn = node[p];
|
|
2232
|
+
const exist = temp[p];
|
|
2233
|
+
if (p === "make") {
|
|
2234
|
+
ctors.push(fn);
|
|
2235
|
+
continue;
|
|
2236
|
+
}
|
|
2237
|
+
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
2238
|
+
if (exist) {
|
|
2239
|
+
temp[p] = _View.processMixinsSameEvent(fn, exist);
|
|
2240
|
+
} else {
|
|
2241
|
+
fn.marker = 1;
|
|
2242
|
+
temp[p] = fn;
|
|
2243
|
+
}
|
|
2244
|
+
} else {
|
|
2245
|
+
if (!exist) {
|
|
2246
|
+
temp[p] = fn;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
for (const p in temp) {
|
|
2252
|
+
if (!has(proto, p)) {
|
|
2253
|
+
proto[p] = temp[p];
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Destroy a single resource entry.
|
|
2259
|
+
*/
|
|
2260
|
+
static destroyResource(cache, key, callDestroy, oldEntity) {
|
|
2261
|
+
const entry = cache[key];
|
|
2262
|
+
if (!entry || entry.entity === oldEntity) return void 0;
|
|
2263
|
+
const entity = entry.entity;
|
|
2264
|
+
if (entity && typeof entity === "object") {
|
|
2265
|
+
const destroyFn = entity["destroy"];
|
|
2266
|
+
if (typeof destroyFn === "function" && callDestroy) {
|
|
2267
|
+
funcWithTry(destroyFn, [], entity, noop);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
Reflect.deleteProperty(cache, key);
|
|
2271
|
+
return entity;
|
|
2272
|
+
}
|
|
2273
|
+
// ============================================================
|
|
2274
|
+
// Static: extend and merge
|
|
2275
|
+
// ============================================================
|
|
2202
2276
|
/**
|
|
2203
2277
|
* Extend View to create a new View subclass.
|
|
2204
2278
|
*
|
|
2205
2279
|
* Supports:
|
|
2206
|
-
* - props.
|
|
2280
|
+
* - props.make: constructor-like init (called with initParams + {node, deep})
|
|
2207
2281
|
* - props.mixins: array of mixin objects
|
|
2208
2282
|
* - Event method patterns: `'name<click>'` etc.
|
|
2209
2283
|
*/
|
|
2210
2284
|
static extend(props, statics) {
|
|
2211
2285
|
props = props || {};
|
|
2212
|
-
const
|
|
2286
|
+
const make = props["make"];
|
|
2213
2287
|
const ctors = [];
|
|
2214
|
-
if (
|
|
2215
|
-
ctors.push(
|
|
2288
|
+
if (make) {
|
|
2289
|
+
ctors.push(make);
|
|
2216
2290
|
}
|
|
2217
2291
|
const ParentView = this;
|
|
2218
2292
|
const ChildView = class extends ParentView {
|
|
2219
2293
|
constructor(nodeId, ownerFrame, initParams, node, mixinCtors) {
|
|
2220
2294
|
super(nodeId, ownerFrame, initParams, node, []);
|
|
2221
2295
|
for (const key in props) {
|
|
2222
|
-
if (has(props, key) && key !== "
|
|
2296
|
+
if (has(props, key) && key !== "make" && key !== "render") {
|
|
2223
2297
|
this[key] = props[key];
|
|
2224
2298
|
}
|
|
2225
2299
|
}
|
|
@@ -2241,7 +2315,7 @@ var View = class _View {
|
|
|
2241
2315
|
};
|
|
2242
2316
|
const proto = ChildView.prototype;
|
|
2243
2317
|
for (const key in props) {
|
|
2244
|
-
if (has(props, key) && key !== "
|
|
2318
|
+
if (has(props, key) && key !== "make") {
|
|
2245
2319
|
proto[key] = props[key];
|
|
2246
2320
|
}
|
|
2247
2321
|
}
|
|
@@ -2252,36 +2326,17 @@ var View = class _View {
|
|
|
2252
2326
|
}
|
|
2253
2327
|
}
|
|
2254
2328
|
}
|
|
2255
|
-
ChildView.merge = viewMerge;
|
|
2256
|
-
ChildView.extend = _View.extend;
|
|
2257
2329
|
return ChildView;
|
|
2258
2330
|
}
|
|
2259
2331
|
/**
|
|
2260
2332
|
* Merge mixins into View prototype.
|
|
2261
2333
|
*/
|
|
2262
2334
|
static merge(...mixins) {
|
|
2263
|
-
const
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
return self;
|
|
2335
|
+
const existingCtors = this.ctors || [];
|
|
2336
|
+
_View.mergeMixins(mixins, this, existingCtors);
|
|
2337
|
+
return this;
|
|
2267
2338
|
}
|
|
2268
2339
|
};
|
|
2269
|
-
function viewMerge(...mixins) {
|
|
2270
|
-
const self = this;
|
|
2271
|
-
const existingCtors = self.ctors || [];
|
|
2272
|
-
viewMergeMixins(mixins, self, existingCtors);
|
|
2273
|
-
return self;
|
|
2274
|
-
}
|
|
2275
|
-
function runInvokes(frame) {
|
|
2276
|
-
const list = frame.invokeList;
|
|
2277
|
-
if (!list) return;
|
|
2278
|
-
while (list.length) {
|
|
2279
|
-
const entry = list.shift();
|
|
2280
|
-
if (entry && !entry.removed) {
|
|
2281
|
-
frame.invoke(entry.name, entry.args);
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
}
|
|
2285
2340
|
|
|
2286
2341
|
// src/frame.ts
|
|
2287
2342
|
var frameRegistry = /* @__PURE__ */ new Map();
|
|
@@ -2320,7 +2375,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2320
2375
|
hasAltered = 0;
|
|
2321
2376
|
/** Whether view is destroyed */
|
|
2322
2377
|
destroyed = 0;
|
|
2323
|
-
/** View path (lark
|
|
2378
|
+
/** View path (v-lark attribute value) */
|
|
2324
2379
|
viewPath;
|
|
2325
2380
|
/** Original template before mount */
|
|
2326
2381
|
originalTemplate;
|
|
@@ -2389,7 +2444,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2389
2444
|
*/
|
|
2390
2445
|
doMountView(ViewClass, params, node, sign) {
|
|
2391
2446
|
if (sign !== this.signature) return;
|
|
2392
|
-
const mixinCtors =
|
|
2447
|
+
const mixinCtors = View.prepare(ViewClass);
|
|
2393
2448
|
const ViewConstructor = ViewClass;
|
|
2394
2449
|
const view = new ViewConstructor(
|
|
2395
2450
|
this.id,
|
|
@@ -2400,7 +2455,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2400
2455
|
);
|
|
2401
2456
|
this.viewInstance = view;
|
|
2402
2457
|
view.signature = 1;
|
|
2403
|
-
|
|
2458
|
+
View.delegateEvents(view);
|
|
2404
2459
|
const initResult = funcWithTry(
|
|
2405
2460
|
view.init,
|
|
2406
2461
|
[params, { node, deep: !view.template }],
|
|
@@ -2411,13 +2466,10 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2411
2466
|
Promise.resolve(initResult).then(() => {
|
|
2412
2467
|
if (nextSign !== this.signature) return;
|
|
2413
2468
|
if (view.template) {
|
|
2414
|
-
|
|
2415
|
-
if (renderFn) {
|
|
2416
|
-
renderFn.call(view);
|
|
2417
|
-
}
|
|
2469
|
+
view.render();
|
|
2418
2470
|
} else {
|
|
2419
2471
|
this.hasAltered = 0;
|
|
2420
|
-
if (!view
|
|
2472
|
+
if (!view.endUpdatePendingFlag) {
|
|
2421
2473
|
view.endUpdate();
|
|
2422
2474
|
}
|
|
2423
2475
|
}
|
|
@@ -2604,7 +2656,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2604
2656
|
/** Get or create root frame */
|
|
2605
2657
|
static root(rootId) {
|
|
2606
2658
|
if (!rootFrame) {
|
|
2607
|
-
rootId = rootId || "
|
|
2659
|
+
rootId = rootId || "root";
|
|
2608
2660
|
let rootElement = document.getElementById(rootId);
|
|
2609
2661
|
if (!rootElement) {
|
|
2610
2662
|
rootElement = document.body;
|
|
@@ -2725,19 +2777,19 @@ function registerViewClass(viewPath, ViewClass) {
|
|
|
2725
2777
|
}
|
|
2726
2778
|
|
|
2727
2779
|
// src/service.ts
|
|
2728
|
-
var
|
|
2729
|
-
/**
|
|
2780
|
+
var Payload = class {
|
|
2781
|
+
/** Payload data */
|
|
2730
2782
|
data;
|
|
2731
2783
|
/** Internal cache info */
|
|
2732
2784
|
cacheInfo;
|
|
2733
2785
|
constructor(data = {}) {
|
|
2734
2786
|
this.data = data;
|
|
2735
2787
|
}
|
|
2736
|
-
/** Get a value from
|
|
2788
|
+
/** Get a value from payload data */
|
|
2737
2789
|
get(key) {
|
|
2738
2790
|
return this.data[key];
|
|
2739
2791
|
}
|
|
2740
|
-
/** Set a value in
|
|
2792
|
+
/** Set a value in payload data */
|
|
2741
2793
|
set(keyOrData, value) {
|
|
2742
2794
|
if (typeof keyOrData === "string") {
|
|
2743
2795
|
this.data[keyOrData] = value;
|
|
@@ -2749,287 +2801,366 @@ var Bag = class {
|
|
|
2749
2801
|
};
|
|
2750
2802
|
var FETCH_FLAGS_ALL = 1;
|
|
2751
2803
|
var FETCH_FLAGS_ONE = 2;
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2804
|
+
var Service = class {
|
|
2805
|
+
/** Service instance ID */
|
|
2806
|
+
id = "";
|
|
2807
|
+
/** Whether service is busy (1 = busy) */
|
|
2808
|
+
busy = 0;
|
|
2809
|
+
/** Whether service is destroyed (1 = destroyed) */
|
|
2810
|
+
destroyed = 0;
|
|
2811
|
+
/** Task queue for sequential operations */
|
|
2812
|
+
taskQueue = [];
|
|
2813
|
+
/** Previous dequeue arguments */
|
|
2814
|
+
prevArgs = [];
|
|
2815
|
+
/** Instance event emitter */
|
|
2816
|
+
_emitter = new EventEmitter();
|
|
2817
|
+
constructor() {
|
|
2818
|
+
this.id = generateId("service");
|
|
2819
|
+
}
|
|
2820
|
+
// ============================================================
|
|
2821
|
+
// Instance accessors for type-level data
|
|
2822
|
+
// ============================================================
|
|
2823
|
+
/** Instance event emitter (public accessor) */
|
|
2824
|
+
get emitter() {
|
|
2825
|
+
return this._emitter;
|
|
2826
|
+
}
|
|
2827
|
+
/**
|
|
2828
|
+
* Get internals object for serviceSend compatibility.
|
|
2829
|
+
* References per-type static state from the current class.
|
|
2830
|
+
*/
|
|
2831
|
+
get internals() {
|
|
2832
|
+
const ctor = this.constructor;
|
|
2833
|
+
return {
|
|
2834
|
+
metaList: ctor._metaList,
|
|
2835
|
+
payloadCache: ctor._payloadCache,
|
|
2836
|
+
pendingCacheKeys: ctor._pendingCacheKeys,
|
|
2837
|
+
syncFn: ctor._syncFn,
|
|
2838
|
+
staticEmitter: ctor._staticEmitter
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
/**
|
|
2842
|
+
* Get type reference (the constructor) for serviceSend compatibility.
|
|
2843
|
+
* Static methods like get/create are accessible via the constructor.
|
|
2844
|
+
*/
|
|
2845
|
+
get type() {
|
|
2846
|
+
return this.constructor;
|
|
2847
|
+
}
|
|
2848
|
+
// ============================================================
|
|
2849
|
+
// Instance methods
|
|
2850
|
+
// ============================================================
|
|
2851
|
+
/**
|
|
2852
|
+
* Fetch all endpoints, callback when all complete.
|
|
2853
|
+
* Uses cache when available.
|
|
2854
|
+
*/
|
|
2855
|
+
all(attrs, done) {
|
|
2856
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
2857
|
+
return this;
|
|
2858
|
+
}
|
|
2859
|
+
/**
|
|
2860
|
+
* Fetch all endpoints, callback on each completion.
|
|
2861
|
+
*/
|
|
2862
|
+
one(attrs, done) {
|
|
2863
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
2864
|
+
return this;
|
|
2865
|
+
}
|
|
2866
|
+
/**
|
|
2867
|
+
* Fetch all endpoints, skip cache (always request).
|
|
2868
|
+
*/
|
|
2869
|
+
save(attrs, done) {
|
|
2870
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
2871
|
+
return this;
|
|
2872
|
+
}
|
|
2873
|
+
/**
|
|
2874
|
+
* Enqueue a task for sequential execution.
|
|
2875
|
+
*/
|
|
2876
|
+
enqueue(callback) {
|
|
2877
|
+
if (!this.destroyed) {
|
|
2878
|
+
this.taskQueue.push(callback);
|
|
2879
|
+
this.dequeue(...this.prevArgs);
|
|
2880
|
+
}
|
|
2881
|
+
return this;
|
|
2882
|
+
}
|
|
2883
|
+
/**
|
|
2884
|
+
* Dequeue and execute the next task in queue.
|
|
2885
|
+
*/
|
|
2886
|
+
dequeue(...args) {
|
|
2887
|
+
if (!this.busy && !this.destroyed) {
|
|
2888
|
+
this.busy = 1;
|
|
2889
|
+
setTimeout(() => {
|
|
2890
|
+
this.busy = 0;
|
|
2891
|
+
if (!this.destroyed) {
|
|
2892
|
+
const task2 = this.taskQueue.shift();
|
|
2893
|
+
if (task2) {
|
|
2894
|
+
this.prevArgs = args;
|
|
2895
|
+
funcWithTry(task2, args, this, noop);
|
|
2829
2896
|
}
|
|
2830
|
-
return cached;
|
|
2831
2897
|
}
|
|
2898
|
+
}, 0);
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Destroy the service instance.
|
|
2903
|
+
* After destruction, no new requests can be sent.
|
|
2904
|
+
*/
|
|
2905
|
+
destroy() {
|
|
2906
|
+
this.destroyed = 1;
|
|
2907
|
+
this.taskQueue = [];
|
|
2908
|
+
}
|
|
2909
|
+
// Instance event methods (delegate to instance emitter)
|
|
2910
|
+
on(event, handler) {
|
|
2911
|
+
this._emitter.on(event, handler);
|
|
2912
|
+
return this;
|
|
2913
|
+
}
|
|
2914
|
+
off(event, handler) {
|
|
2915
|
+
this._emitter.off(event, handler);
|
|
2916
|
+
return this;
|
|
2917
|
+
}
|
|
2918
|
+
fire(event, data) {
|
|
2919
|
+
this._emitter.fire(event, data);
|
|
2920
|
+
return this;
|
|
2921
|
+
}
|
|
2922
|
+
// ============================================================
|
|
2923
|
+
// Per-type static state
|
|
2924
|
+
// ============================================================
|
|
2925
|
+
/** Per-type metadata registry */
|
|
2926
|
+
static _metaList = {};
|
|
2927
|
+
/** Per-type payload cache (LFU with frequency eviction) */
|
|
2928
|
+
static _payloadCache = new Cache({
|
|
2929
|
+
maxSize: 20,
|
|
2930
|
+
bufferSize: 5
|
|
2931
|
+
});
|
|
2932
|
+
/** Per-type pending cache keys for deduplication */
|
|
2933
|
+
static _pendingCacheKeys = {};
|
|
2934
|
+
/** Per-type sync function */
|
|
2935
|
+
static _syncFn = noop;
|
|
2936
|
+
/** Per-type static event emitter */
|
|
2937
|
+
static _staticEmitter = new EventEmitter();
|
|
2938
|
+
/** Per-type cache max size */
|
|
2939
|
+
static _cacheMax = 20;
|
|
2940
|
+
/** Per-type cache buffer size */
|
|
2941
|
+
static _cacheBuffer = 5;
|
|
2942
|
+
// ============================================================
|
|
2943
|
+
// Static methods (operate on per-type state via `this`)
|
|
2944
|
+
// ============================================================
|
|
2945
|
+
/**
|
|
2946
|
+
* Register API endpoint metadata.
|
|
2947
|
+
*/
|
|
2948
|
+
static add(attrs) {
|
|
2949
|
+
if (!Array.isArray(attrs)) {
|
|
2950
|
+
attrs = [attrs];
|
|
2951
|
+
}
|
|
2952
|
+
for (const payload of attrs) {
|
|
2953
|
+
if (payload) {
|
|
2954
|
+
const name = payload.name;
|
|
2955
|
+
const cache = payload.cache;
|
|
2956
|
+
payload.cache = cache ? cache | 0 : 0;
|
|
2957
|
+
this._metaList[name] = payload;
|
|
2832
2958
|
}
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
/**
|
|
2962
|
+
* Get metadata for an API endpoint.
|
|
2963
|
+
*/
|
|
2964
|
+
static meta(attrs) {
|
|
2965
|
+
const name = typeof attrs === "string" ? attrs : attrs["name"];
|
|
2966
|
+
return this._metaList[name] || attrs;
|
|
2967
|
+
}
|
|
2968
|
+
/**
|
|
2969
|
+
* Create a Payload for an API request.
|
|
2970
|
+
*/
|
|
2971
|
+
static create(attrs) {
|
|
2972
|
+
const meta = this.meta(attrs);
|
|
2973
|
+
const cache = attrs["cache"] | 0 || meta.cache || 0;
|
|
2974
|
+
const entity = new Payload();
|
|
2975
|
+
entity.set(meta);
|
|
2976
|
+
entity.cacheInfo = {
|
|
2977
|
+
name: meta.name,
|
|
2978
|
+
after: meta.after,
|
|
2979
|
+
cleans: meta.cleanKeys,
|
|
2980
|
+
key: cache ? defaultCacheKey(meta, attrs) : "",
|
|
2981
|
+
time: 0
|
|
2982
|
+
};
|
|
2983
|
+
if (typeof attrs === "object" && attrs !== null) {
|
|
2984
|
+
entity.set(attrs);
|
|
2985
|
+
}
|
|
2986
|
+
const before = meta.before;
|
|
2987
|
+
if (before) {
|
|
2988
|
+
funcWithTry(before, [entity], entity, noop);
|
|
2989
|
+
}
|
|
2990
|
+
this._staticEmitter.fire("begin", { payload: entity });
|
|
2991
|
+
return entity;
|
|
2992
|
+
}
|
|
2993
|
+
/**
|
|
2994
|
+
* Get or create a Payload for an API request.
|
|
2995
|
+
*/
|
|
2996
|
+
static get(attrs, createNew) {
|
|
2997
|
+
let entity;
|
|
2998
|
+
let needsUpdate = false;
|
|
2999
|
+
if (!createNew) {
|
|
3000
|
+
entity = this.cached(attrs);
|
|
3001
|
+
}
|
|
3002
|
+
if (!entity) {
|
|
3003
|
+
entity = this.create(attrs);
|
|
3004
|
+
needsUpdate = true;
|
|
3005
|
+
}
|
|
3006
|
+
return { entity, needsUpdate };
|
|
3007
|
+
}
|
|
3008
|
+
/**
|
|
3009
|
+
* Get cached Payload if available and not expired.
|
|
3010
|
+
*/
|
|
3011
|
+
static cached(attrs) {
|
|
3012
|
+
const meta = this.meta(attrs);
|
|
3013
|
+
const cache = attrs["cache"] | 0 || meta.cache || 0;
|
|
3014
|
+
let cacheKey = "";
|
|
3015
|
+
if (cache) {
|
|
3016
|
+
cacheKey = defaultCacheKey(meta, attrs);
|
|
3017
|
+
}
|
|
3018
|
+
if (cacheKey) {
|
|
3019
|
+
const info = this._pendingCacheKeys[cacheKey];
|
|
3020
|
+
if (info) {
|
|
3021
|
+
return info.entity;
|
|
2840
3022
|
}
|
|
2841
|
-
const
|
|
2842
|
-
|
|
2843
|
-
if (
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
}
|
|
3023
|
+
const cached = this._payloadCache.get(cacheKey);
|
|
3024
|
+
if (cached && cached.cacheInfo) {
|
|
3025
|
+
if (now() - cached.cacheInfo.time > cache) {
|
|
3026
|
+
this._payloadCache.del(cacheKey);
|
|
3027
|
+
return void 0;
|
|
2847
3028
|
}
|
|
2848
|
-
|
|
2849
|
-
for (const key of keysToDelete) {
|
|
2850
|
-
bagCache.del(key);
|
|
3029
|
+
return cached;
|
|
2851
3030
|
}
|
|
2852
|
-
},
|
|
2853
|
-
on(event, handler) {
|
|
2854
|
-
staticEmitter2.on(event, handler);
|
|
2855
|
-
},
|
|
2856
|
-
off(event, handler) {
|
|
2857
|
-
staticEmitter2.off(event, handler);
|
|
2858
|
-
},
|
|
2859
|
-
fire(event, data) {
|
|
2860
|
-
staticEmitter2.fire(event, data);
|
|
2861
|
-
},
|
|
2862
|
-
extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
2863
|
-
return createServiceType(
|
|
2864
|
-
newSyncFn,
|
|
2865
|
-
newCacheMax || cacheMax,
|
|
2866
|
-
newCacheBuffer || cacheBuffer
|
|
2867
|
-
);
|
|
2868
3031
|
}
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
this
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
}
|
|
2887
|
-
ServiceInstance.prototype = {
|
|
2888
|
-
all(attrs, done) {
|
|
2889
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
2890
|
-
return this;
|
|
2891
|
-
},
|
|
2892
|
-
one(attrs, done) {
|
|
2893
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
2894
|
-
return this;
|
|
2895
|
-
},
|
|
2896
|
-
save(attrs, done) {
|
|
2897
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
2898
|
-
return this;
|
|
2899
|
-
},
|
|
2900
|
-
enqueue(callback) {
|
|
2901
|
-
if (!this["$d"]) {
|
|
2902
|
-
this["$g"].push(callback);
|
|
2903
|
-
this.dequeue(...this["$h"]);
|
|
2904
|
-
}
|
|
2905
|
-
return this;
|
|
2906
|
-
},
|
|
2907
|
-
dequeue(...args) {
|
|
2908
|
-
if (!this["$e"] && !this["$d"]) {
|
|
2909
|
-
this["$e"] = 1;
|
|
2910
|
-
setTimeout(() => {
|
|
2911
|
-
this["$e"] = 0;
|
|
2912
|
-
if (!this["$d"]) {
|
|
2913
|
-
const task2 = this["$g"].shift();
|
|
2914
|
-
if (task2) {
|
|
2915
|
-
this["$h"] = args;
|
|
2916
|
-
funcWithTry(task2, args, this, noop);
|
|
2917
|
-
}
|
|
2918
|
-
}
|
|
2919
|
-
}, 0);
|
|
3032
|
+
return void 0;
|
|
3033
|
+
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Clear cached payloads by endpoint name.
|
|
3036
|
+
*/
|
|
3037
|
+
static clear(names) {
|
|
3038
|
+
const nameList = (typeof names === "string" ? names : names.join(",")).split(",");
|
|
3039
|
+
const nameSet = {};
|
|
3040
|
+
for (const n of nameList) {
|
|
3041
|
+
nameSet[n] = 1;
|
|
3042
|
+
}
|
|
3043
|
+
const keysToDelete = [];
|
|
3044
|
+
this._payloadCache.forEach((payload) => {
|
|
3045
|
+
if (payload?.cacheInfo && nameSet[payload.cacheInfo.name]) {
|
|
3046
|
+
if (payload.cacheInfo.key) {
|
|
3047
|
+
keysToDelete.push(payload.cacheInfo.key);
|
|
3048
|
+
}
|
|
2920
3049
|
}
|
|
2921
|
-
}
|
|
2922
|
-
|
|
2923
|
-
this
|
|
2924
|
-
this["$g"] = [];
|
|
2925
|
-
},
|
|
2926
|
-
on(event, handler) {
|
|
2927
|
-
this._emitter.on(event, handler);
|
|
2928
|
-
return this;
|
|
2929
|
-
},
|
|
2930
|
-
off(event, handler) {
|
|
2931
|
-
this._emitter.off(event, handler);
|
|
2932
|
-
return this;
|
|
2933
|
-
},
|
|
2934
|
-
fire(event, data) {
|
|
2935
|
-
this._emitter.fire(event, data);
|
|
2936
|
-
return this;
|
|
3050
|
+
});
|
|
3051
|
+
for (const key of keysToDelete) {
|
|
3052
|
+
this._payloadCache.del(key);
|
|
2937
3053
|
}
|
|
2938
|
-
}
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
}
|
|
2958
|
-
|
|
3054
|
+
}
|
|
3055
|
+
// Static event methods (operate on per-type emitter)
|
|
3056
|
+
static on(event, handler) {
|
|
3057
|
+
this._staticEmitter.on(event, handler);
|
|
3058
|
+
}
|
|
3059
|
+
static off(event, handler) {
|
|
3060
|
+
this._staticEmitter.off(event, handler);
|
|
3061
|
+
}
|
|
3062
|
+
static fire(event, data) {
|
|
3063
|
+
this._staticEmitter.fire(event, data);
|
|
3064
|
+
}
|
|
3065
|
+
/**
|
|
3066
|
+
* Create a new Service subclass with a custom sync function.
|
|
3067
|
+
* Each subclass gets its own per-type state (metaList, cache, etc.)
|
|
3068
|
+
* to ensure isolation between different Service types.
|
|
3069
|
+
*/
|
|
3070
|
+
static extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
3071
|
+
const ParentService = this;
|
|
3072
|
+
class ChildService extends ParentService {
|
|
3073
|
+
static _metaList = {};
|
|
3074
|
+
static _payloadCache = new Cache({
|
|
3075
|
+
maxSize: newCacheMax || ParentService._cacheMax,
|
|
3076
|
+
bufferSize: newCacheBuffer || ParentService._cacheBuffer
|
|
3077
|
+
});
|
|
3078
|
+
static _pendingCacheKeys = {};
|
|
3079
|
+
static _syncFn = newSyncFn;
|
|
3080
|
+
static _staticEmitter = new EventEmitter();
|
|
3081
|
+
static _cacheMax = newCacheMax || ParentService._cacheMax;
|
|
3082
|
+
static _cacheBuffer = newCacheBuffer || ParentService._cacheBuffer;
|
|
3083
|
+
}
|
|
3084
|
+
return ChildService;
|
|
3085
|
+
}
|
|
3086
|
+
};
|
|
2959
3087
|
function defaultCacheKey(meta, attrs) {
|
|
2960
3088
|
return JSON.stringify(attrs) + SPLITTER + JSON.stringify(meta);
|
|
2961
3089
|
}
|
|
2962
3090
|
function serviceSend(service, attrs, done, flag, save) {
|
|
2963
|
-
if (service["
|
|
2964
|
-
if (service["
|
|
3091
|
+
if (service["destroyed"]) return;
|
|
3092
|
+
if (service["busy"]) {
|
|
2965
3093
|
service.enqueue(
|
|
2966
3094
|
serviceSend.bind(null, service, attrs, done, flag, save)
|
|
2967
3095
|
);
|
|
2968
3096
|
return;
|
|
2969
3097
|
}
|
|
2970
|
-
service["
|
|
3098
|
+
service["busy"] = 1;
|
|
2971
3099
|
let attrList;
|
|
2972
3100
|
if (typeof attrs === "string") {
|
|
2973
3101
|
attrList = [{ name: attrs }];
|
|
2974
|
-
} else if (isArray(attrs)) {
|
|
3102
|
+
} else if (Array.isArray(attrs)) {
|
|
2975
3103
|
attrList = attrs;
|
|
2976
3104
|
} else {
|
|
2977
3105
|
attrList = [attrs];
|
|
2978
3106
|
}
|
|
2979
|
-
const internals = service.
|
|
3107
|
+
const internals = service.internals;
|
|
2980
3108
|
const { syncFn, pendingCacheKeys, staticEmitter: staticEmitter2 } = internals;
|
|
2981
3109
|
let requestCount = 0;
|
|
2982
3110
|
const total = attrList.length;
|
|
2983
3111
|
const doneArr = new Array(total + 1);
|
|
2984
3112
|
const errorArgs = [];
|
|
2985
3113
|
const remoteComplete = (idx, error) => {
|
|
2986
|
-
const
|
|
2987
|
-
let
|
|
3114
|
+
const payload = doneArr[idx + 1];
|
|
3115
|
+
let newPayload = false;
|
|
2988
3116
|
if (error) {
|
|
2989
3117
|
errorArgs[idx] = error;
|
|
2990
|
-
staticEmitter2.fire("fail", {
|
|
3118
|
+
staticEmitter2.fire("fail", { payload, error });
|
|
2991
3119
|
} else {
|
|
2992
|
-
|
|
2993
|
-
staticEmitter2.fire("done", {
|
|
3120
|
+
newPayload = true;
|
|
3121
|
+
staticEmitter2.fire("done", { payload });
|
|
2994
3122
|
}
|
|
2995
|
-
if (!service["
|
|
3123
|
+
if (!service["destroyed"]) {
|
|
2996
3124
|
const finish = requestCount === total;
|
|
2997
3125
|
if (finish) {
|
|
2998
|
-
service["
|
|
3126
|
+
service["busy"] = 0;
|
|
2999
3127
|
if (flag === FETCH_FLAGS_ALL) {
|
|
3000
3128
|
doneArr[0] = errorArgs;
|
|
3001
3129
|
funcWithTry(done, doneArr, service, noop);
|
|
3002
3130
|
}
|
|
3003
3131
|
}
|
|
3004
3132
|
if (flag === FETCH_FLAGS_ONE) {
|
|
3005
|
-
funcWithTry(done, [error || null,
|
|
3133
|
+
funcWithTry(done, [error || null, payload, finish, idx], service, noop);
|
|
3006
3134
|
}
|
|
3007
3135
|
}
|
|
3008
|
-
if (
|
|
3009
|
-
staticEmitter2.fire("end", {
|
|
3136
|
+
if (newPayload) {
|
|
3137
|
+
staticEmitter2.fire("end", { payload, error });
|
|
3010
3138
|
}
|
|
3011
3139
|
};
|
|
3012
3140
|
for (const attr of attrList) {
|
|
3013
3141
|
if (!attr) continue;
|
|
3014
3142
|
const attrObj = typeof attr === "string" ? { name: attr } : attr;
|
|
3015
|
-
const
|
|
3016
|
-
|
|
3017
|
-
|
|
3143
|
+
const payloadInfo = service.type.get(
|
|
3144
|
+
attrObj,
|
|
3145
|
+
save
|
|
3146
|
+
);
|
|
3147
|
+
const payloadEntity = payloadInfo.entity;
|
|
3148
|
+
const cacheKey = payloadEntity.cacheInfo?.key || "";
|
|
3018
3149
|
const complete = remoteComplete.bind(null, requestCount++);
|
|
3019
3150
|
if (cacheKey && pendingCacheKeys[cacheKey]) {
|
|
3020
3151
|
pendingCacheKeys[cacheKey].push(complete);
|
|
3021
|
-
} else if (
|
|
3152
|
+
} else if (payloadInfo.needsUpdate) {
|
|
3022
3153
|
if (cacheKey) {
|
|
3023
3154
|
const cacheList = [complete];
|
|
3024
|
-
cacheList.
|
|
3155
|
+
cacheList.entity = payloadEntity;
|
|
3025
3156
|
pendingCacheKeys[cacheKey] = cacheList;
|
|
3026
3157
|
const cacheComplete = () => {
|
|
3027
3158
|
const list = pendingCacheKeys[cacheKey];
|
|
3028
|
-
const entity = list.
|
|
3159
|
+
const entity = list.entity;
|
|
3029
3160
|
if (entity.cacheInfo) {
|
|
3030
3161
|
entity.cacheInfo.time = now();
|
|
3031
3162
|
}
|
|
3032
|
-
internals.
|
|
3163
|
+
internals.payloadCache.set(cacheKey, entity);
|
|
3033
3164
|
Reflect.deleteProperty(pendingCacheKeys, cacheKey);
|
|
3034
3165
|
for (const cb of list) {
|
|
3035
3166
|
if (typeof cb === "function") {
|
|
@@ -3037,9 +3168,9 @@ function serviceSend(service, attrs, done, flag, save) {
|
|
|
3037
3168
|
}
|
|
3038
3169
|
}
|
|
3039
3170
|
};
|
|
3040
|
-
syncFn(
|
|
3171
|
+
syncFn(payloadEntity, cacheComplete);
|
|
3041
3172
|
} else {
|
|
3042
|
-
syncFn(
|
|
3173
|
+
syncFn(payloadEntity, complete);
|
|
3043
3174
|
}
|
|
3044
3175
|
} else {
|
|
3045
3176
|
complete();
|
|
@@ -3047,9 +3178,117 @@ function serviceSend(service, attrs, done, flag, save) {
|
|
|
3047
3178
|
}
|
|
3048
3179
|
}
|
|
3049
3180
|
|
|
3181
|
+
// src/frame-visualizer.ts
|
|
3182
|
+
var MSG_PING = "LARK_VISUALIZER_PING";
|
|
3183
|
+
var MSG_PONG = "LARK_VISUALIZER_PONG";
|
|
3184
|
+
var MSG_REQUEST_TREE = "LARK_VISUALIZER_REQUEST_TREE";
|
|
3185
|
+
var MSG_TREE = "LARK_VISUALIZER_TREE";
|
|
3186
|
+
var MSG_TREE_DELTA = "LARK_VISUALIZER_TREE_DELTA";
|
|
3187
|
+
function serializeView(view) {
|
|
3188
|
+
return {
|
|
3189
|
+
id: view.id,
|
|
3190
|
+
rendered: !!view.rendered,
|
|
3191
|
+
signature: view.signature,
|
|
3192
|
+
observedStateKeys: view.observedStateKeys ?? null,
|
|
3193
|
+
locationObserved: {
|
|
3194
|
+
flag: view.locationObserved.flag,
|
|
3195
|
+
keys: view.locationObserved.keys,
|
|
3196
|
+
observePath: view.locationObserved.observePath
|
|
3197
|
+
},
|
|
3198
|
+
hasTemplate: !!view.template
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
3201
|
+
function serializeFrame(frameId) {
|
|
3202
|
+
const frame = Frame.get(frameId);
|
|
3203
|
+
if (!frame) return null;
|
|
3204
|
+
const view = frame.view;
|
|
3205
|
+
const children = [];
|
|
3206
|
+
for (const childId of frame.children()) {
|
|
3207
|
+
const childNode = serializeFrame(childId);
|
|
3208
|
+
if (childNode) {
|
|
3209
|
+
children.push(childNode);
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
return {
|
|
3213
|
+
id: frame.id,
|
|
3214
|
+
parentId: frame.parentId ?? null,
|
|
3215
|
+
viewPath: frame.viewPath ?? null,
|
|
3216
|
+
childrenCount: frame.childrenCount,
|
|
3217
|
+
readyCount: frame.readyCount,
|
|
3218
|
+
childrenCreated: frame.childrenCreated,
|
|
3219
|
+
childrenAlter: frame.childrenAlter,
|
|
3220
|
+
destroyed: frame.destroyed,
|
|
3221
|
+
view: view ? serializeView(view) : null,
|
|
3222
|
+
children
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
function serializeFrameTree() {
|
|
3226
|
+
const root = Frame.root();
|
|
3227
|
+
const rootNode = serializeFrame(root.id);
|
|
3228
|
+
let totalFrames = 0;
|
|
3229
|
+
const countFrames = (node) => {
|
|
3230
|
+
if (!node) return;
|
|
3231
|
+
totalFrames++;
|
|
3232
|
+
for (const child of node.children) {
|
|
3233
|
+
countFrames(child);
|
|
3234
|
+
}
|
|
3235
|
+
};
|
|
3236
|
+
countFrames(rootNode);
|
|
3237
|
+
return {
|
|
3238
|
+
root: rootNode,
|
|
3239
|
+
totalFrames,
|
|
3240
|
+
timestamp: Date.now(),
|
|
3241
|
+
rootId: root.id
|
|
3242
|
+
};
|
|
3243
|
+
}
|
|
3244
|
+
var bridgeInstalled = false;
|
|
3245
|
+
var lastTreeJson = "";
|
|
3246
|
+
function installFrameVisualizerBridge() {
|
|
3247
|
+
if (bridgeInstalled) return;
|
|
3248
|
+
if (typeof window === "undefined") return;
|
|
3249
|
+
bridgeInstalled = true;
|
|
3250
|
+
window.addEventListener("message", (event) => {
|
|
3251
|
+
const data = event.data;
|
|
3252
|
+
if (!data || typeof data !== "object") return;
|
|
3253
|
+
const type = data.type;
|
|
3254
|
+
if (type === MSG_PING) {
|
|
3255
|
+
const source = event.source;
|
|
3256
|
+
if (source) {
|
|
3257
|
+
source.postMessage({ type: MSG_PONG }, { targetOrigin: "*" });
|
|
3258
|
+
}
|
|
3259
|
+
return;
|
|
3260
|
+
}
|
|
3261
|
+
if (type === MSG_REQUEST_TREE) {
|
|
3262
|
+
const tree = serializeFrameTree();
|
|
3263
|
+
const source = event.source;
|
|
3264
|
+
if (source) {
|
|
3265
|
+
source.postMessage(
|
|
3266
|
+
{ type: MSG_TREE, data: tree },
|
|
3267
|
+
{ targetOrigin: "*" }
|
|
3268
|
+
);
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
});
|
|
3272
|
+
Frame.on("add", () => {
|
|
3273
|
+
pushTreeUpdate();
|
|
3274
|
+
});
|
|
3275
|
+
Frame.on("remove", () => {
|
|
3276
|
+
pushTreeUpdate();
|
|
3277
|
+
});
|
|
3278
|
+
}
|
|
3279
|
+
function pushTreeUpdate() {
|
|
3280
|
+
if (window === window.parent) return;
|
|
3281
|
+
const tree = serializeFrameTree();
|
|
3282
|
+
const treeJson = JSON.stringify(tree);
|
|
3283
|
+
if (treeJson !== lastTreeJson) {
|
|
3284
|
+
lastTreeJson = treeJson;
|
|
3285
|
+
window.parent.postMessage({ type: MSG_TREE_DELTA, data: tree }, "*");
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3050
3289
|
// src/framework.ts
|
|
3051
3290
|
var config = {
|
|
3052
|
-
rootId: "
|
|
3291
|
+
rootId: "root",
|
|
3053
3292
|
hashbang: "#!",
|
|
3054
3293
|
error: (error) => {
|
|
3055
3294
|
throw error;
|
|
@@ -3142,7 +3381,12 @@ function dispatcherUpdate(frame, stateKeys) {
|
|
|
3142
3381
|
const isChanged = stateKeys ? stateIsObserveChanged(view, stateKeys) : viewIsObserveChanged(view);
|
|
3143
3382
|
let renderPromise;
|
|
3144
3383
|
if (isChanged) {
|
|
3145
|
-
const renderResult = funcWithTry(
|
|
3384
|
+
const renderResult = funcWithTry(
|
|
3385
|
+
view.renderMethod ?? view.render,
|
|
3386
|
+
[],
|
|
3387
|
+
view,
|
|
3388
|
+
noop
|
|
3389
|
+
);
|
|
3146
3390
|
if (renderResult && typeof renderResult.then === "function") {
|
|
3147
3391
|
renderPromise = renderResult;
|
|
3148
3392
|
}
|
|
@@ -3164,13 +3408,13 @@ function dispatcherUpdate(frame, stateKeys) {
|
|
|
3164
3408
|
}
|
|
3165
3409
|
function dispatcherNotifyChange(e) {
|
|
3166
3410
|
const rootFrame2 = Frame.root();
|
|
3167
|
-
const view = e
|
|
3411
|
+
const view = e.view;
|
|
3168
3412
|
if (view) {
|
|
3169
3413
|
const viewPath = typeof view === "object" && view !== null ? String(view.to || "") : String(view);
|
|
3170
3414
|
rootFrame2.mountView(viewPath);
|
|
3171
3415
|
} else {
|
|
3172
3416
|
dispatcherUpdateTag++;
|
|
3173
|
-
dispatcherUpdate(rootFrame2, e
|
|
3417
|
+
dispatcherUpdate(rootFrame2, e.keys);
|
|
3174
3418
|
}
|
|
3175
3419
|
}
|
|
3176
3420
|
function dispatchEvent(target, eventType, eventInit) {
|
|
@@ -3181,8 +3425,6 @@ function dispatchEvent(target, eventType, eventInit) {
|
|
|
3181
3425
|
});
|
|
3182
3426
|
target.dispatchEvent(event);
|
|
3183
3427
|
}
|
|
3184
|
-
var Base = class extends EventEmitter {
|
|
3185
|
-
};
|
|
3186
3428
|
function use(names, callback) {
|
|
3187
3429
|
if (!config.require) {
|
|
3188
3430
|
if (callback) callback();
|
|
@@ -3197,7 +3439,7 @@ function use(names, callback) {
|
|
|
3197
3439
|
}
|
|
3198
3440
|
}
|
|
3199
3441
|
var WAIT_OK = 1;
|
|
3200
|
-
var
|
|
3442
|
+
var WAIT_TIMEOUT_OR_NOT_FOUND = 0;
|
|
3201
3443
|
function waitZoneViewsRendered(viewId, timeout) {
|
|
3202
3444
|
if (timeout == null) {
|
|
3203
3445
|
timeout = 30 * 1e3;
|
|
@@ -3208,7 +3450,7 @@ function waitZoneViewsRendered(viewId, timeout) {
|
|
|
3208
3450
|
const check = () => {
|
|
3209
3451
|
const currentTime = now();
|
|
3210
3452
|
if (currentTime > endTime || !checkFrame) {
|
|
3211
|
-
resolve(
|
|
3453
|
+
resolve(WAIT_TIMEOUT_OR_NOT_FOUND);
|
|
3212
3454
|
} else if (checkFrame.childrenCount === checkFrame.readyCount) {
|
|
3213
3455
|
resolve(WAIT_OK);
|
|
3214
3456
|
} else {
|
|
@@ -3245,14 +3487,15 @@ var Framework = {
|
|
|
3245
3487
|
Router._setConfig(config);
|
|
3246
3488
|
EventDelegator.setFrameGetter((id) => Frame.get(id));
|
|
3247
3489
|
Router.on(ROUTER_EVENTS.CHANGED, (data) => {
|
|
3248
|
-
dispatcherNotifyChange(data);
|
|
3490
|
+
if (data) dispatcherNotifyChange(data);
|
|
3249
3491
|
});
|
|
3250
3492
|
State.on(ROUTER_EVENTS.CHANGED, (data) => {
|
|
3251
|
-
dispatcherNotifyChange(data);
|
|
3493
|
+
if (data) dispatcherNotifyChange(data);
|
|
3252
3494
|
});
|
|
3253
3495
|
booted3 = true;
|
|
3254
3496
|
markBooted();
|
|
3255
3497
|
markRouterBooted();
|
|
3498
|
+
installFrameVisualizerBridge();
|
|
3256
3499
|
const rootFrame2 = Frame.root(config.rootId);
|
|
3257
3500
|
Router._bind();
|
|
3258
3501
|
const defaultView = config.defaultView || "";
|
|
@@ -3284,7 +3527,7 @@ var Framework = {
|
|
|
3284
3527
|
/** Wait for zone views to be rendered */
|
|
3285
3528
|
waitZoneViewsRendered,
|
|
3286
3529
|
WAIT_OK,
|
|
3287
|
-
|
|
3530
|
+
WAIT_TIMEOUT_OR_NOT_FOUND,
|
|
3288
3531
|
/**
|
|
3289
3532
|
* Convert array to hash map.
|
|
3290
3533
|
*/
|
|
@@ -3349,7 +3592,7 @@ var Framework = {
|
|
|
3349
3592
|
/**
|
|
3350
3593
|
* Base class with EventEmitter.
|
|
3351
3594
|
*/
|
|
3352
|
-
Base,
|
|
3595
|
+
Base: EventEmitter,
|
|
3353
3596
|
// ============================================================
|
|
3354
3597
|
// Module access
|
|
3355
3598
|
// ============================================================
|
|
@@ -3367,10 +3610,11 @@ if (typeof window !== "undefined") {
|
|
|
3367
3610
|
window.__lark_State = State;
|
|
3368
3611
|
window.__lark_Router = Router;
|
|
3369
3612
|
window.__lark_Frame = Frame;
|
|
3613
|
+
window.__lark_View = View;
|
|
3370
3614
|
}
|
|
3371
3615
|
|
|
3372
3616
|
// src/store.ts
|
|
3373
|
-
var LARK_GLOBAL = "
|
|
3617
|
+
var LARK_GLOBAL = "lark-global";
|
|
3374
3618
|
var Platform = /* @__PURE__ */ ((Platform2) => {
|
|
3375
3619
|
Platform2["Lark"] = "lark";
|
|
3376
3620
|
Platform2["React"] = "react";
|
|
@@ -3413,8 +3657,10 @@ var Queue = class {
|
|
|
3413
3657
|
const flushTickTask = () => {
|
|
3414
3658
|
while (queue.length > 0) {
|
|
3415
3659
|
const task2 = queue.shift();
|
|
3416
|
-
|
|
3417
|
-
|
|
3660
|
+
if (task2) {
|
|
3661
|
+
pendingTasks.delete(task2);
|
|
3662
|
+
runTask(task2);
|
|
3663
|
+
}
|
|
3418
3664
|
}
|
|
3419
3665
|
};
|
|
3420
3666
|
Promise.resolve().then(flushTickTask);
|
|
@@ -3513,9 +3759,11 @@ var setStateConfig = (target, config2) => {
|
|
|
3513
3759
|
if (target && isObject(config2)) StateConfigMap.set(target, config2);
|
|
3514
3760
|
};
|
|
3515
3761
|
var getStateConfig = (target, key) => {
|
|
3516
|
-
if (!StateConfigMap.has(target))
|
|
3762
|
+
if (!StateConfigMap.has(target)) {
|
|
3763
|
+
return void 0;
|
|
3764
|
+
}
|
|
3517
3765
|
const config2 = StateConfigMap.get(target);
|
|
3518
|
-
return key ? config2[key] : config2;
|
|
3766
|
+
return key ? config2?.[key] : config2;
|
|
3519
3767
|
};
|
|
3520
3768
|
var isState = (target) => isObject(target) && StateConfigMap.has(target);
|
|
3521
3769
|
var createLinkKeys = (target, property) => {
|
|
@@ -3685,20 +3933,20 @@ function createState(initialData, config2) {
|
|
|
3685
3933
|
lazySet(state, initialData);
|
|
3686
3934
|
return state;
|
|
3687
3935
|
}
|
|
3688
|
-
var
|
|
3936
|
+
var curLazySetKey = null;
|
|
3689
3937
|
function lazySet(target, data) {
|
|
3690
3938
|
if (isObject(data)) {
|
|
3691
3939
|
Reflect.ownKeys(data).forEach((key) => {
|
|
3692
3940
|
const strKey = key;
|
|
3693
|
-
if (
|
|
3694
|
-
|
|
3941
|
+
if (curLazySetKey) throw new Error("[lark-store] lazy set key conflict");
|
|
3942
|
+
curLazySetKey = strKey;
|
|
3695
3943
|
target[strKey] = data[strKey];
|
|
3696
3944
|
});
|
|
3697
3945
|
}
|
|
3698
3946
|
}
|
|
3699
3947
|
function isLazySet(property) {
|
|
3700
|
-
if (
|
|
3701
|
-
|
|
3948
|
+
if (curLazySetKey === property) {
|
|
3949
|
+
curLazySetKey = "";
|
|
3702
3950
|
return true;
|
|
3703
3951
|
}
|
|
3704
3952
|
return false;
|
|
@@ -4082,14 +4330,11 @@ function defineStore(name, creator, config2) {
|
|
|
4082
4330
|
const useStore = adapter.useStore;
|
|
4083
4331
|
const store = new StoreClass(name, config2);
|
|
4084
4332
|
store[_storeCreate](
|
|
4085
|
-
creator(
|
|
4086
|
-
store[_innerStore](),
|
|
4087
|
-
extendApis
|
|
4088
|
-
)
|
|
4333
|
+
creator(store[_innerStore](), extendApis)
|
|
4089
4334
|
);
|
|
4090
4335
|
Object.defineProperties(useStore, {
|
|
4091
4336
|
$storeName: { value: name, configurable: true },
|
|
4092
|
-
$
|
|
4337
|
+
$destroyFn: { value: () => store[_storeDestroy](), configurable: true }
|
|
4093
4338
|
});
|
|
4094
4339
|
if (!StoreCache.has(name)) {
|
|
4095
4340
|
StoreCache.set(name, { store, creator, config: config2, useStore });
|
|
@@ -4154,7 +4399,7 @@ function observeCell(state, cb, immediate = true) {
|
|
|
4154
4399
|
}
|
|
4155
4400
|
function multi(useStore) {
|
|
4156
4401
|
const storeName = useStore["$storeName"];
|
|
4157
|
-
const flagSym = `
|
|
4402
|
+
const flagSym = `lark-comp-${storeName}`;
|
|
4158
4403
|
const map = /* @__PURE__ */ new Map();
|
|
4159
4404
|
let rootViewPath;
|
|
4160
4405
|
const getFlag = (viewContext) => {
|
|
@@ -4163,7 +4408,7 @@ function multi(useStore) {
|
|
|
4163
4408
|
const viewId = owner?.["id"] || "";
|
|
4164
4409
|
let flag;
|
|
4165
4410
|
if (viewPath === rootViewPath) {
|
|
4166
|
-
flag = `${flagSym}
|
|
4411
|
+
flag = `${flagSym}-${viewId}`;
|
|
4167
4412
|
} else {
|
|
4168
4413
|
flag = owner?.["viewInitParams"]?.[flagSym];
|
|
4169
4414
|
}
|
|
@@ -4180,19 +4425,18 @@ function multi(useStore) {
|
|
|
4180
4425
|
};
|
|
4181
4426
|
const useFn = ((view) => {
|
|
4182
4427
|
if (!view)
|
|
4183
|
-
throw new Error(
|
|
4428
|
+
throw new Error(
|
|
4429
|
+
"[@lark.js/mvc error] multi: cannot find the view instance"
|
|
4430
|
+
);
|
|
4184
4431
|
const viewCtx = view;
|
|
4185
4432
|
const flag = viewCtx[flagSym];
|
|
4186
4433
|
if (map.has(flag)) return map.get(flag);
|
|
4187
|
-
const newFn = cloneStore(
|
|
4188
|
-
flag,
|
|
4189
|
-
useStore
|
|
4190
|
-
);
|
|
4434
|
+
const newFn = cloneStore(flag, useStore);
|
|
4191
4435
|
map.set(flag, newFn);
|
|
4192
4436
|
return useFn(view);
|
|
4193
4437
|
});
|
|
4194
4438
|
const mixinObj = {
|
|
4195
|
-
|
|
4439
|
+
make() {
|
|
4196
4440
|
if (!rootViewPath) {
|
|
4197
4441
|
const owner = this["owner"];
|
|
4198
4442
|
rootViewPath = owner?.["path"] || "";
|
|
@@ -4242,17 +4486,17 @@ function restoreComments(source, comments) {
|
|
|
4242
4486
|
}
|
|
4243
4487
|
function processViewEvents(source) {
|
|
4244
4488
|
return source.replace(
|
|
4245
|
-
|
|
4489
|
+
/@(\w+)="([^"]+)"/g,
|
|
4246
4490
|
(fullAttr, eventName, attrValue) => {
|
|
4247
4491
|
const eventMatch = attrValue.match(/^(\w+)\((.*)\)$/s);
|
|
4248
4492
|
if (!eventMatch) return fullAttr;
|
|
4249
4493
|
const handlerName = eventMatch[1];
|
|
4250
4494
|
const paramsStr = eventMatch[2].trim();
|
|
4251
4495
|
if (!paramsStr) {
|
|
4252
|
-
return
|
|
4496
|
+
return `@${eventName}="${VIEW_ID_PLACEHOLDER}${SPLITTER2}${handlerName}()"`;
|
|
4253
4497
|
}
|
|
4254
4498
|
const urlParams = jsObjectToUrlParams(paramsStr);
|
|
4255
|
-
return
|
|
4499
|
+
return `@${eventName}="${VIEW_ID_PLACEHOLDER}${SPLITTER2}${handlerName}(${urlParams})"`;
|
|
4256
4500
|
}
|
|
4257
4501
|
);
|
|
4258
4502
|
}
|
|
@@ -4325,7 +4569,7 @@ function convertArtSyntax(source, debug) {
|
|
|
4325
4569
|
}
|
|
4326
4570
|
if (blockStack.length > 0) {
|
|
4327
4571
|
const unclosed = blockStack.map((b) => `"${b.ctrl}" at line ${b.line}`).join(", ");
|
|
4328
|
-
throw new Error(`[@lark/mvc error] unclosed block(s): ${unclosed}`);
|
|
4572
|
+
throw new Error(`[@lark.js/mvc error] unclosed block(s): ${unclosed}`);
|
|
4329
4573
|
}
|
|
4330
4574
|
return result.join("");
|
|
4331
4575
|
}
|
|
@@ -4419,12 +4663,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4419
4663
|
}
|
|
4420
4664
|
return `${debugPrefix}<%}else{%>`;
|
|
4421
4665
|
}
|
|
4422
|
-
case "
|
|
4423
|
-
blockStack.push({ ctrl: "
|
|
4666
|
+
case "forOf": {
|
|
4667
|
+
blockStack.push({ ctrl: "forOf", line: lineNo });
|
|
4424
4668
|
const object = tokens[0];
|
|
4425
4669
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4426
4670
|
throw new Error(
|
|
4427
|
-
`[@lark/mvc error] bad
|
|
4671
|
+
`[@lark.js/mvc error] bad forOf syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{forOf list as item [index]}}`
|
|
4428
4672
|
);
|
|
4429
4673
|
}
|
|
4430
4674
|
const restTokens = tokens.slice(2);
|
|
@@ -4446,12 +4690,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4446
4690
|
}
|
|
4447
4691
|
return `${debugPrefix}<%for(let ${index}=0${refExpr},${refObjCount}=${refObj}.length${lastCount};${index}<${refObjCount};${index}++){${firstAndLast}${valueDecl}%>`;
|
|
4448
4692
|
}
|
|
4449
|
-
case "
|
|
4450
|
-
blockStack.push({ ctrl: "
|
|
4693
|
+
case "forIn": {
|
|
4694
|
+
blockStack.push({ ctrl: "forIn", line: lineNo });
|
|
4451
4695
|
const object = tokens[0];
|
|
4452
4696
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4453
4697
|
throw new Error(
|
|
4454
|
-
`[@lark/mvc error] bad
|
|
4698
|
+
`[@lark.js/mvc error] bad forIn syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{for-in obj as val [key]}}`
|
|
4455
4699
|
);
|
|
4456
4700
|
}
|
|
4457
4701
|
const restTokens2 = tokens.slice(2);
|
|
@@ -4471,19 +4715,19 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4471
4715
|
case "set":
|
|
4472
4716
|
return `${debugPrefix}<%let ${tokens.join(" ")};%>`;
|
|
4473
4717
|
case "/if":
|
|
4474
|
-
case "/
|
|
4475
|
-
case "/
|
|
4718
|
+
case "/forOf":
|
|
4719
|
+
case "/forIn":
|
|
4476
4720
|
case "/for": {
|
|
4477
4721
|
const expectedCtrl = keyword.substring(1);
|
|
4478
4722
|
const last = blockStack.pop();
|
|
4479
4723
|
if (!last) {
|
|
4480
4724
|
throw new Error(
|
|
4481
|
-
`[@lark/mvc error
|
|
4725
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: no matching open block`
|
|
4482
4726
|
);
|
|
4483
4727
|
}
|
|
4484
4728
|
if (last.ctrl !== expectedCtrl) {
|
|
4485
4729
|
throw new Error(
|
|
4486
|
-
`[@lark/mvc error
|
|
4730
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: expected {{/${last.ctrl}}} to close block opened at line ${last.line}`
|
|
4487
4731
|
);
|
|
4488
4732
|
}
|
|
4489
4733
|
return `${debugPrefix}<%}%>`;
|
|
@@ -4547,7 +4791,7 @@ function parseAsExpr(expr) {
|
|
|
4547
4791
|
function compileToFunction(source, debug, file) {
|
|
4548
4792
|
const matcher = /<%([@=!:])?([\s\S]*?)%>|$/g;
|
|
4549
4793
|
let index = 0;
|
|
4550
|
-
let funcSource = `$
|
|
4794
|
+
let funcSource = `$out+='`;
|
|
4551
4795
|
let hasAtRule = false;
|
|
4552
4796
|
const escapeSlashRegExp = /\\|'/g;
|
|
4553
4797
|
const escapeBreakReturnRegExp = /\r|\n/g;
|
|
@@ -4573,17 +4817,17 @@ function compileToFunction(source, debug, file) {
|
|
|
4573
4817
|
}
|
|
4574
4818
|
if (operate === "@") {
|
|
4575
4819
|
hasAtRule = true;
|
|
4576
|
-
funcSource += `'+($
|
|
4820
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$refFn($refAlt,${content}))+'`;
|
|
4577
4821
|
} else if (operate === "=" || operate === ":") {
|
|
4578
|
-
funcSource += `'+($
|
|
4822
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$encHtml(${content}))+'`;
|
|
4579
4823
|
} else if (operate === "!") {
|
|
4580
|
-
if (!content.startsWith("$
|
|
4581
|
-
content = `$
|
|
4824
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
4825
|
+
content = `$strSafe(${content})`;
|
|
4582
4826
|
}
|
|
4583
|
-
funcSource += `'+($
|
|
4827
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',${content})+'`;
|
|
4584
4828
|
} else if (content) {
|
|
4585
4829
|
if (line > -1) {
|
|
4586
|
-
funcSource += `';$
|
|
4830
|
+
funcSource += `';$dbgLine=${line};$dbgArt='${art}';`;
|
|
4587
4831
|
content = "";
|
|
4588
4832
|
} else {
|
|
4589
4833
|
funcSource += `';`;
|
|
@@ -4592,19 +4836,19 @@ function compileToFunction(source, debug, file) {
|
|
|
4592
4836
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4593
4837
|
}
|
|
4594
4838
|
if (expr) {
|
|
4595
|
-
funcSource += `$
|
|
4839
|
+
funcSource += `$dbgExpr='<%${expr}%>';`;
|
|
4596
4840
|
}
|
|
4597
|
-
funcSource += content + `;$
|
|
4841
|
+
funcSource += content + `;$out+='`;
|
|
4598
4842
|
}
|
|
4599
4843
|
} else {
|
|
4600
4844
|
if (operate === "@") {
|
|
4601
4845
|
hasAtRule = true;
|
|
4602
|
-
funcSource += `'+$
|
|
4846
|
+
funcSource += `'+$refFn($refAlt,${content})+'`;
|
|
4603
4847
|
} else if (operate === "=" || operate === ":") {
|
|
4604
|
-
funcSource += `'+$
|
|
4848
|
+
funcSource += `'+$encHtml(${content})+'`;
|
|
4605
4849
|
} else if (operate === "!") {
|
|
4606
|
-
if (!content.startsWith("$
|
|
4607
|
-
content = `$
|
|
4850
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
4851
|
+
content = `$strSafe(${content})`;
|
|
4608
4852
|
}
|
|
4609
4853
|
funcSource += `'+${content}+'`;
|
|
4610
4854
|
} else if (content) {
|
|
@@ -4612,28 +4856,28 @@ function compileToFunction(source, debug, file) {
|
|
|
4612
4856
|
if (funcSource.endsWith(`+'';`)) {
|
|
4613
4857
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4614
4858
|
}
|
|
4615
|
-
funcSource += `${content};$
|
|
4859
|
+
funcSource += `${content};$out+='`;
|
|
4616
4860
|
}
|
|
4617
4861
|
}
|
|
4618
4862
|
return match;
|
|
4619
4863
|
});
|
|
4620
4864
|
funcSource += `';`;
|
|
4621
|
-
funcSource = funcSource.replace(/\$
|
|
4622
|
-
funcSource = funcSource.replace(/\$
|
|
4865
|
+
funcSource = funcSource.replace(/\$out\+='';/g, "");
|
|
4866
|
+
funcSource = funcSource.replace(/\$out\+=''\+/g, "$out+=");
|
|
4623
4867
|
if (debug) {
|
|
4624
4868
|
const filePart = file ? `\\r\\n\\tat file:${file}` : "";
|
|
4625
|
-
funcSource = `let $
|
|
4869
|
+
funcSource = `let $dbgExpr,$dbgArt,$dbgLine;try{${funcSource}}catch(ex){let msg='render view error:'+(ex.message||ex);if($dbgArt)msg+='\\r\\n\\tsrc art:{{'+$dbgArt+'}}\\r\\n\\tat line:'+$dbgLine;msg+='\\r\\n\\t'+($dbgArt?'translate to:':'expr:');msg+=$dbgExpr+'${filePart}';throw msg;}`;
|
|
4626
4870
|
}
|
|
4627
4871
|
const viewIdRegExp = new RegExp(String.fromCharCode(31), "g");
|
|
4628
4872
|
funcSource = funcSource.replace(viewIdRegExp, `'+$viewId+'`);
|
|
4629
|
-
const atRule = hasAtRule ? `if(!$
|
|
4630
|
-
const encode = `if(!$
|
|
4631
|
-
const encodeURIMore = `if(!$
|
|
4632
|
-
const encodeQuote = `if(!$
|
|
4633
|
-
const refFallback = "if(
|
|
4873
|
+
const atRule = hasAtRule ? `if(!$refFn){$refFn=(ref,v,k,f)=>{for(f=ref[$splitter];--f;)if(ref[k=$splitter+f]===v)return k;ref[k=$splitter+ref[$splitter]++]=v;return k;}}` : "";
|
|
4874
|
+
const encode = `if(!$strSafe){let $entMap={'&':'amp','<':'lt','>':'gt','"':'#34','\\'':'#39','\`':'#96'},$entReg=/[&<>"'\`]/g,$entFn=m=>'&'+$entMap[m]+';';$strSafe=v=>''+(v==null?'':v);$encHtml=v=>$strSafe(v).replace($entReg,$entFn)}`;
|
|
4875
|
+
const encodeURIMore = `if(!$encUri){let $uriMap={'!':'%21','\\'':'%27','(':'%28',')':'%29','*':'%2A'},$uriFn=m=>$uriMap[m],$uriReg=/[!')(*]/g;$encUri=v=>encodeURIComponent($strSafe(v)).replace($uriReg,$uriFn)}`;
|
|
4876
|
+
const encodeQuote = `if(!$encQuote){let $qReg=/['"\\\\]/g;$encQuote=v=>$strSafe(v).replace($qReg,'\\\\$&')}`;
|
|
4877
|
+
const refFallback = "if(!$refAlt)$refAlt=$data;";
|
|
4634
4878
|
const fns = `${refFallback}${encode}${encodeURIMore}${encodeQuote}${atRule};`;
|
|
4635
|
-
const fullSource = `${fns}let $
|
|
4636
|
-
return `(
|
|
4879
|
+
const fullSource = `${fns}let $splitter='\\x1e',$tmp,$out=''{{VARS}};${funcSource}return $out`;
|
|
4880
|
+
return `($data,$viewId,$refAlt,$encHtml,$strSafe,$encUri,$refFn,$encQuote)=>{${fullSource}}`;
|
|
4637
4881
|
}
|
|
4638
4882
|
function compileTemplate(source, options = {}) {
|
|
4639
4883
|
const { debug = false, globalVars = [], file } = options;
|
|
@@ -4642,17 +4886,17 @@ function compileTemplate(source, options = {}) {
|
|
|
4642
4886
|
const viewEventProcessed = processViewEvents(converted);
|
|
4643
4887
|
const finalSource = restoreComments(viewEventProcessed, comments);
|
|
4644
4888
|
const funcBody = compileToFunction(finalSource, debug, file);
|
|
4645
|
-
const varDeclarations = globalVars.map((key) => `,${key}
|
|
4889
|
+
const varDeclarations = globalVars.map((key) => `,${key}=$data.${key}`).join("");
|
|
4646
4890
|
const funcWithVars = funcBody.replace("{{VARS}}", () => varDeclarations);
|
|
4647
4891
|
return `export default function(data, selfId, refData) {
|
|
4648
|
-
let
|
|
4892
|
+
let $data = data || {},
|
|
4649
4893
|
$viewId = selfId || '';
|
|
4650
|
-
return (${funcWithVars})(
|
|
4651
|
-
/* $
|
|
4652
|
-
/* $
|
|
4653
|
-
/* $
|
|
4654
|
-
/* $
|
|
4655
|
-
/* $
|
|
4894
|
+
return (${funcWithVars})($data, $viewId, refData,
|
|
4895
|
+
/* $encHtml */ v => String(v == null ? '' : v).replace(/[&<>"'\`]/g, m => '&' + ({'&':'amp','<':'lt','>':'gt','"':'#34',"'":'#39','\`':'#96'})[m] + ';'),
|
|
4896
|
+
/* $strSafe */ v => String(v == null ? '' : v),
|
|
4897
|
+
/* $encUri */ null,
|
|
4898
|
+
/* $refFn */ null,
|
|
4899
|
+
/* $encQuote */ null
|
|
4656
4900
|
);
|
|
4657
4901
|
}`;
|
|
4658
4902
|
}
|
|
@@ -4761,7 +5005,7 @@ function fallbackExtractVariables(source) {
|
|
|
4761
5005
|
while ((m = outputRegExp.exec(source)) !== null) {
|
|
4762
5006
|
vars.add(m[1]);
|
|
4763
5007
|
}
|
|
4764
|
-
const eachRegExp = /\{\{
|
|
5008
|
+
const eachRegExp = /\{\{forOf\s+([a-zA-Z_$][\w$]*)\s+as/g;
|
|
4765
5009
|
while ((m = eachRegExp.exec(source)) !== null) {
|
|
4766
5010
|
vars.add(m[1]);
|
|
4767
5011
|
}
|
|
@@ -4807,77 +5051,88 @@ var BUILTIN_GLOBALS = {
|
|
|
4807
5051
|
//
|
|
4808
5052
|
// These variables appear in the generated template function signature
|
|
4809
5053
|
// or body. They must be excluded from extractGlobalVars() so that
|
|
4810
|
-
// they are not mistaken for user data variables and destructured from
|
|
5054
|
+
// they are not mistaken for user data variables and destructured from $data.
|
|
4811
5055
|
// SPLITTER character constant (same as \x1e), used as namespace separator
|
|
4812
5056
|
// for refData keys, event attribute encoding, and internal data structures.
|
|
4813
|
-
// Declared as: let $
|
|
4814
|
-
$
|
|
4815
|
-
//
|
|
4816
|
-
// User variables are destructured from
|
|
4817
|
-
// let {name, age} =
|
|
5057
|
+
// Declared as: let $splitter='\x1e'
|
|
5058
|
+
$splitter: 1,
|
|
5059
|
+
// Data — the data object passed from Updater to the template function.
|
|
5060
|
+
// User variables are destructured from $data at the top of the function:
|
|
5061
|
+
// let {name, age} = $data;
|
|
4818
5062
|
// This is the first parameter of the generated arrow function.
|
|
4819
|
-
|
|
5063
|
+
$data: 1,
|
|
4820
5064
|
// Null-safe toString: v => '' + (v == null ? '' : v)
|
|
4821
5065
|
// Converts null/undefined to empty string, otherwise calls toString().
|
|
4822
5066
|
// Wraps every {{!raw}} output to prevent "null" / "undefined" rendering.
|
|
4823
|
-
$
|
|
4824
|
-
// HTML entity encoder: v => $
|
|
5067
|
+
$strSafe: 1,
|
|
5068
|
+
// HTML entity encoder: v => $strSafe(v).replace(/[&<>"'`]/g, entityMap)
|
|
4825
5069
|
// Encodes &, <, >, ", ', ` to HTML entities (& < etc.)
|
|
4826
5070
|
// Applied to all {{=escaped}} and {{:binding}} outputs.
|
|
4827
|
-
$
|
|
4828
|
-
// HTML entity map — internal object used by $
|
|
5071
|
+
$encHtml: 1,
|
|
5072
|
+
// HTML entity map — internal object used by $encHtml:
|
|
4829
5073
|
// {'&':'amp','<':'gt','>':'gt','"':'#34','\'':'#39','`':'#96'}
|
|
4830
|
-
// Not a standalone function; referenced inside $
|
|
4831
|
-
$
|
|
4832
|
-
// HTML entity RegExp — internal regexp used by $
|
|
5074
|
+
// Not a standalone function; referenced inside $encHtml's closure.
|
|
5075
|
+
$entMap: 1,
|
|
5076
|
+
// HTML entity RegExp — internal regexp used by $encHtml:
|
|
4833
5077
|
// /[&<>"'`]/g
|
|
4834
|
-
$
|
|
4835
|
-
// HTML entity replacer function — internal helper used by $
|
|
4836
|
-
// m => '&' + $
|
|
4837
|
-
// Maps
|
|
4838
|
-
$
|
|
5078
|
+
$entReg: 1,
|
|
5079
|
+
// HTML entity replacer function — internal helper used by $encHtml:
|
|
5080
|
+
// m => '&' + $entMap[m] + ';'
|
|
5081
|
+
// Maps matched character to its entity string.
|
|
5082
|
+
$entFn: 1,
|
|
4839
5083
|
// Output buffer — the string accumulator for rendered HTML.
|
|
4840
|
-
// All template output is appended via $
|
|
4841
|
-
// Declared as: let $
|
|
4842
|
-
$
|
|
5084
|
+
// All template output is appended via $out += '...'.
|
|
5085
|
+
// Declared as: let $out = ''
|
|
5086
|
+
$out: 1,
|
|
4843
5087
|
// Reference lookup: (refData, value) => key
|
|
4844
5088
|
// Finds or allocates a SPLITTER-prefixed key in refData for a given
|
|
4845
5089
|
// object reference. Used by {{@ref}} operator for passing object
|
|
4846
|
-
// references to child views via lark
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
// URI encoder: v => encodeURIComponent($n(v)).replace(/[!')(*]/g, extraMap)
|
|
5090
|
+
// references to child views via v-lark attributes.
|
|
5091
|
+
$refFn: 1,
|
|
5092
|
+
// URI encoder: v => encodeURIComponent($strSafe(v)).replace(/[!')(*]/g, extraMap)
|
|
4850
5093
|
// Extends encodeURIComponent with encoding of ! ' ( ) *.
|
|
4851
|
-
// Applied to values in
|
|
4852
|
-
$
|
|
4853
|
-
//
|
|
5094
|
+
// Applied to values in @event URL parameters and {{!uri}} contexts.
|
|
5095
|
+
$encUri: 1,
|
|
5096
|
+
// URI encode map — internal object used by $encUri:
|
|
5097
|
+
// {'!':'%21','\'':'%27','(':'%28',')':'%29','*':'%2A'}
|
|
5098
|
+
$uriMap: 1,
|
|
5099
|
+
// URI encode replacer — internal helper used by $encUri:
|
|
5100
|
+
// m => $uriMap[m]
|
|
5101
|
+
$uriFn: 1,
|
|
5102
|
+
// URI encode regexp — internal regexp used by $encUri:
|
|
5103
|
+
// /[!')(*]/g
|
|
5104
|
+
$uriReg: 1,
|
|
5105
|
+
// Quote encoder: v => $strSafe(v).replace(/['"\\]/g, '\\$&')
|
|
4854
5106
|
// Escapes quotes and backslashes for safe embedding in HTML attribute
|
|
4855
5107
|
// values (e.g. data-json='...').
|
|
4856
|
-
$
|
|
5108
|
+
$encQuote: 1,
|
|
5109
|
+
// Quote encode regexp — internal regexp used by $encQuote:
|
|
5110
|
+
// /['"\\]/g
|
|
5111
|
+
$qReg: 1,
|
|
4857
5112
|
// View ID — the unique identifier of the owning View instance.
|
|
4858
|
-
// Injected into
|
|
5113
|
+
// Injected into @event attribute values at render time so that
|
|
4859
5114
|
// EventDelegator can dispatch events to the correct View handler.
|
|
4860
5115
|
// The \x1f placeholder in compiled output is replaced with '+$viewId+'.
|
|
4861
5116
|
$viewId: 1,
|
|
4862
5117
|
// Debug: current expression text — stores the template expression being
|
|
4863
5118
|
// evaluated, for error reporting. Only present in debug mode.
|
|
4864
|
-
// e.g. $
|
|
4865
|
-
$
|
|
5119
|
+
// e.g. $dbgExpr='<%=user.name%>'
|
|
5120
|
+
$dbgExpr: 1,
|
|
4866
5121
|
// Debug: original art syntax — stores the {{}} template syntax before
|
|
4867
5122
|
// conversion, for error reporting. Only present in debug mode.
|
|
4868
|
-
// e.g. $
|
|
4869
|
-
$
|
|
5123
|
+
// e.g. $dbgArt='{{=user.name}}'
|
|
5124
|
+
$dbgArt: 1,
|
|
4870
5125
|
// Debug: source line number — tracks the current line in the template
|
|
4871
5126
|
// source, for error reporting. Only present in debug mode.
|
|
4872
|
-
$
|
|
4873
|
-
//
|
|
4874
|
-
// Defaults to
|
|
4875
|
-
// Ensures $
|
|
4876
|
-
|
|
5127
|
+
$dbgLine: 1,
|
|
5128
|
+
// RefData alias — fallback reference lookup table.
|
|
5129
|
+
// Defaults to $data when no explicit $refAlt is provided.
|
|
5130
|
+
// Ensures $refFn() does not crash when @ operator is used without refData.
|
|
5131
|
+
$refAlt: 1,
|
|
4877
5132
|
// Temporary variable — used by the compiler for intermediate
|
|
4878
5133
|
// expression results in generated code (e.g. loop variables,
|
|
4879
|
-
// conditional branches). Declared as: let $
|
|
4880
|
-
$
|
|
5134
|
+
// conditional branches). Declared as: let $tmp
|
|
5135
|
+
$tmp: 1,
|
|
4881
5136
|
// JS literals
|
|
4882
5137
|
undefined: 1,
|
|
4883
5138
|
null: 1,
|
|
@@ -4942,7 +5197,6 @@ var BUILTIN_GLOBALS = {
|
|
|
4942
5197
|
};
|
|
4943
5198
|
var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
4944
5199
|
export {
|
|
4945
|
-
Bag,
|
|
4946
5200
|
CALL_BREAK_TIME,
|
|
4947
5201
|
Cache,
|
|
4948
5202
|
EVENT_METHOD_REGEXP,
|
|
@@ -4951,16 +5205,14 @@ export {
|
|
|
4951
5205
|
Frame,
|
|
4952
5206
|
Framework,
|
|
4953
5207
|
LARK_VIEW,
|
|
5208
|
+
Payload,
|
|
4954
5209
|
Platform,
|
|
4955
5210
|
ROUTER_EVENTS,
|
|
4956
5211
|
Router,
|
|
4957
5212
|
SPLITTER,
|
|
4958
5213
|
Service,
|
|
4959
5214
|
State,
|
|
4960
|
-
TAG_ATTR_KEY,
|
|
4961
|
-
TAG_KEY,
|
|
4962
5215
|
TAG_NAME_REGEXP,
|
|
4963
|
-
TAG_VIEW_KEY,
|
|
4964
5216
|
Updater,
|
|
4965
5217
|
VIEW_EVENT_METHOD_REGEXP,
|
|
4966
5218
|
View,
|
|
@@ -4991,7 +5243,7 @@ export {
|
|
|
4991
5243
|
getStore,
|
|
4992
5244
|
getUseStore,
|
|
4993
5245
|
has,
|
|
4994
|
-
|
|
5246
|
+
installFrameVisualizerBridge,
|
|
4995
5247
|
isPlainObject,
|
|
4996
5248
|
isPrimitive,
|
|
4997
5249
|
isPrimitiveOrFunc,
|
|
@@ -5011,6 +5263,7 @@ export {
|
|
|
5011
5263
|
parseUri,
|
|
5012
5264
|
registerViewClass,
|
|
5013
5265
|
safeguard,
|
|
5266
|
+
serializeFrameTree,
|
|
5014
5267
|
setData,
|
|
5015
5268
|
shallowSet,
|
|
5016
5269
|
mark2 as storeMark,
|