@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.cjs
CHANGED
|
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
Bag: () => Bag,
|
|
24
23
|
CALL_BREAK_TIME: () => CALL_BREAK_TIME,
|
|
25
24
|
Cache: () => Cache,
|
|
26
25
|
EVENT_METHOD_REGEXP: () => EVENT_METHOD_REGEXP,
|
|
@@ -29,16 +28,14 @@ __export(index_exports, {
|
|
|
29
28
|
Frame: () => Frame,
|
|
30
29
|
Framework: () => Framework,
|
|
31
30
|
LARK_VIEW: () => LARK_VIEW,
|
|
31
|
+
Payload: () => Payload,
|
|
32
32
|
Platform: () => Platform,
|
|
33
33
|
ROUTER_EVENTS: () => ROUTER_EVENTS,
|
|
34
34
|
Router: () => Router,
|
|
35
35
|
SPLITTER: () => SPLITTER,
|
|
36
36
|
Service: () => Service,
|
|
37
37
|
State: () => State,
|
|
38
|
-
TAG_ATTR_KEY: () => TAG_ATTR_KEY,
|
|
39
|
-
TAG_KEY: () => TAG_KEY,
|
|
40
38
|
TAG_NAME_REGEXP: () => TAG_NAME_REGEXP,
|
|
41
|
-
TAG_VIEW_KEY: () => TAG_VIEW_KEY,
|
|
42
39
|
Updater: () => Updater,
|
|
43
40
|
VIEW_EVENT_METHOD_REGEXP: () => VIEW_EVENT_METHOD_REGEXP,
|
|
44
41
|
View: () => View,
|
|
@@ -69,7 +66,7 @@ __export(index_exports, {
|
|
|
69
66
|
getStore: () => getStore,
|
|
70
67
|
getUseStore: () => getUseStore,
|
|
71
68
|
has: () => has,
|
|
72
|
-
|
|
69
|
+
installFrameVisualizerBridge: () => installFrameVisualizerBridge,
|
|
73
70
|
isPlainObject: () => isPlainObject,
|
|
74
71
|
isPrimitive: () => isPrimitive,
|
|
75
72
|
isPrimitiveOrFunc: () => isPrimitiveOrFunc,
|
|
@@ -89,6 +86,7 @@ __export(index_exports, {
|
|
|
89
86
|
parseUri: () => parseUri,
|
|
90
87
|
registerViewClass: () => registerViewClass,
|
|
91
88
|
safeguard: () => safeguard,
|
|
89
|
+
serializeFrameTree: () => serializeFrameTree,
|
|
92
90
|
setData: () => setData,
|
|
93
91
|
shallowSet: () => shallowSet,
|
|
94
92
|
storeMark: () => mark2,
|
|
@@ -116,10 +114,15 @@ var ROUTER_EVENTS = {
|
|
|
116
114
|
CHANGED: "changed",
|
|
117
115
|
PAGE_UNLOAD: "page_unload"
|
|
118
116
|
};
|
|
119
|
-
var
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
var LARK_KEYS = {
|
|
118
|
+
/** Attribute name: ldk (static key for skipping VDOM diff) */
|
|
119
|
+
DIFF_KEY: "ldk",
|
|
120
|
+
/** Attribute name: lak (static attribute key) */
|
|
121
|
+
ATTR_KEY: "lak",
|
|
122
|
+
/** Attribute name: lvk (view key for assign) */
|
|
123
|
+
VIEW_KEY: "lvk"
|
|
124
|
+
};
|
|
125
|
+
var LARK_VIEW = "v-lark";
|
|
123
126
|
var EVENT_METHOD_REGEXP = new RegExp(
|
|
124
127
|
`(?:([\\w-]+)${SPLITTER})?([^(]+)\\(([\\s\\S]*?)?\\)`
|
|
125
128
|
);
|
|
@@ -143,7 +146,6 @@ function isPlainObject(value) {
|
|
|
143
146
|
if (proto === null) return true;
|
|
144
147
|
return proto === Object.prototype || proto === null;
|
|
145
148
|
}
|
|
146
|
-
var isArray = Array.isArray;
|
|
147
149
|
function isPrimitiveOrFunc(value) {
|
|
148
150
|
return !value || typeof value !== "object" && typeof value !== "function";
|
|
149
151
|
}
|
|
@@ -184,13 +186,13 @@ function assign(target, ...sources) {
|
|
|
184
186
|
return target;
|
|
185
187
|
}
|
|
186
188
|
function funcWithTry(fns, args, context, configError) {
|
|
187
|
-
const fnArray = isArray(fns) ? fns : [fns];
|
|
189
|
+
const fnArray = Array.isArray(fns) ? fns : [fns];
|
|
188
190
|
let ret;
|
|
189
191
|
for (const fn of fnArray) {
|
|
190
192
|
try {
|
|
191
193
|
ret = Function.prototype.apply.call(fn, context, args);
|
|
192
194
|
} catch (e) {
|
|
193
|
-
configError(e);
|
|
195
|
+
configError?.(e);
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
198
|
return ret;
|
|
@@ -218,7 +220,7 @@ function translateData(data, value) {
|
|
|
218
220
|
}
|
|
219
221
|
return value;
|
|
220
222
|
}
|
|
221
|
-
if (isPlainObject(value) || isArray(value)) {
|
|
223
|
+
if (isPlainObject(value) || Array.isArray(value)) {
|
|
222
224
|
for (const p in value) {
|
|
223
225
|
if (has(value, p)) {
|
|
224
226
|
const val = value[p];
|
|
@@ -311,13 +313,13 @@ function toMap(list, key) {
|
|
|
311
313
|
function now() {
|
|
312
314
|
return Date.now ? Date.now() : (/* @__PURE__ */ new Date()).getTime();
|
|
313
315
|
}
|
|
314
|
-
function classExtend(
|
|
316
|
+
function classExtend(make, base, props, statics) {
|
|
315
317
|
const baseProto = base["prototype"] ?? {};
|
|
316
|
-
const
|
|
317
|
-
assign(
|
|
318
|
-
Object.assign(
|
|
319
|
-
|
|
320
|
-
|
|
318
|
+
const classProto = Object.create(baseProto);
|
|
319
|
+
assign(classProto, props);
|
|
320
|
+
Object.assign(make, statics);
|
|
321
|
+
classProto.constructor = make;
|
|
322
|
+
make["prototype"] = classProto;
|
|
321
323
|
}
|
|
322
324
|
|
|
323
325
|
// src/apply-style.ts
|
|
@@ -358,8 +360,8 @@ function applyStyle(styleIdOrPairs, css) {
|
|
|
358
360
|
}
|
|
359
361
|
|
|
360
362
|
// src/mark.ts
|
|
361
|
-
var DELETED_KEY = SPLITTER + "$
|
|
362
|
-
var MARK_OBJECT_KEY = SPLITTER + "$
|
|
363
|
+
var DELETED_KEY = SPLITTER + "$delFlag";
|
|
364
|
+
var MARK_OBJECT_KEY = SPLITTER + "$markKey";
|
|
363
365
|
function mark(host, key) {
|
|
364
366
|
let sign = 0;
|
|
365
367
|
const hostRecord = host;
|
|
@@ -383,9 +385,9 @@ function unmark(host) {
|
|
|
383
385
|
|
|
384
386
|
// src/safeguard.ts
|
|
385
387
|
var proxiesPool = /* @__PURE__ */ new Map();
|
|
386
|
-
var SAFEGUARD_SENTINEL = "
|
|
388
|
+
var SAFEGUARD_SENTINEL = "_safe_";
|
|
387
389
|
function safeguard(data, getter, setter, isRoot) {
|
|
388
|
-
if (typeof window.
|
|
390
|
+
if (typeof window.__lark_Debug === "undefined" || !window.__lark_Debug) {
|
|
389
391
|
return data;
|
|
390
392
|
}
|
|
391
393
|
if (typeof Proxy === "undefined") {
|
|
@@ -424,7 +426,7 @@ function safeguard(data, getter, setter, isRoot) {
|
|
|
424
426
|
if (!prefix && getter) {
|
|
425
427
|
getter(property);
|
|
426
428
|
}
|
|
427
|
-
if (!isRoot && has(target, property) && (isArray(out) || isPlainObject(out))) {
|
|
429
|
+
if (!isRoot && has(target, property) && (Array.isArray(out) || isPlainObject(out))) {
|
|
428
430
|
return build(prefix + property + ".", out);
|
|
429
431
|
}
|
|
430
432
|
return out;
|
|
@@ -599,7 +601,10 @@ var EventEmitter = class {
|
|
|
599
601
|
}
|
|
600
602
|
} else {
|
|
601
603
|
this.listeners.delete(key);
|
|
602
|
-
Reflect.deleteProperty(
|
|
604
|
+
Reflect.deleteProperty(
|
|
605
|
+
this,
|
|
606
|
+
`on${event[0].toUpperCase() + event.slice(1)}`
|
|
607
|
+
);
|
|
603
608
|
}
|
|
604
609
|
return this;
|
|
605
610
|
}
|
|
@@ -640,7 +645,7 @@ var EventEmitter = class {
|
|
|
640
645
|
}
|
|
641
646
|
}
|
|
642
647
|
}
|
|
643
|
-
const onMethodName = `on${event}`;
|
|
648
|
+
const onMethodName = `on${event[0].toUpperCase() + event.slice(1)}`;
|
|
644
649
|
const onMethod = this[onMethodName];
|
|
645
650
|
if (typeof onMethod === "function") {
|
|
646
651
|
funcWithTry(
|
|
@@ -687,7 +692,7 @@ function teardownKeysRef(keyList) {
|
|
|
687
692
|
if (count <= 0) {
|
|
688
693
|
Reflect.deleteProperty(keyRefCounts, key);
|
|
689
694
|
Reflect.deleteProperty(appData, key);
|
|
690
|
-
if (typeof window.
|
|
695
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
691
696
|
Reflect.deleteProperty(dataWhereSet, key);
|
|
692
697
|
}
|
|
693
698
|
}
|
|
@@ -730,7 +735,7 @@ var State = {
|
|
|
730
735
|
*/
|
|
731
736
|
get(key) {
|
|
732
737
|
const result = key ? appData[key] : appData;
|
|
733
|
-
if (typeof window.
|
|
738
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
734
739
|
return safeguard(
|
|
735
740
|
result,
|
|
736
741
|
(dataKey) => {
|
|
@@ -756,7 +761,7 @@ var State = {
|
|
|
756
761
|
*/
|
|
757
762
|
set(data, excludes) {
|
|
758
763
|
dataIsChanged = setData(data, appData, changedKeys, excludes || /* @__PURE__ */ new Set()) || dataIsChanged;
|
|
759
|
-
if (typeof window.
|
|
764
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && booted) {
|
|
760
765
|
for (const p in data) {
|
|
761
766
|
dataWhereSet[p] = window.location.pathname;
|
|
762
767
|
}
|
|
@@ -771,7 +776,7 @@ var State = {
|
|
|
771
776
|
State.set(data, excludes);
|
|
772
777
|
}
|
|
773
778
|
if (dataIsChanged) {
|
|
774
|
-
if (typeof window.
|
|
779
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
775
780
|
for (const p in changedKeys) {
|
|
776
781
|
if (has(changedKeys, p)) {
|
|
777
782
|
clearNotify(p);
|
|
@@ -802,7 +807,7 @@ var State = {
|
|
|
802
807
|
*/
|
|
803
808
|
clean(keys2) {
|
|
804
809
|
return {
|
|
805
|
-
|
|
810
|
+
make: function() {
|
|
806
811
|
const keyList = setupKeysRef(keys2);
|
|
807
812
|
this.on("destroy", () => {
|
|
808
813
|
teardownKeysRef(keyList);
|
|
@@ -831,6 +836,7 @@ var State = {
|
|
|
831
836
|
emitter.fire(event, data, remove);
|
|
832
837
|
return State;
|
|
833
838
|
}
|
|
839
|
+
// onChanged: noop,
|
|
834
840
|
};
|
|
835
841
|
|
|
836
842
|
// src/router.ts
|
|
@@ -983,7 +989,7 @@ var Router = {
|
|
|
983
989
|
attachViewAndPath(location);
|
|
984
990
|
hrefCache.set(href, location);
|
|
985
991
|
}
|
|
986
|
-
if (typeof window.
|
|
992
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
987
993
|
location["params"] = safeguard(location["params"]);
|
|
988
994
|
}
|
|
989
995
|
return location;
|
|
@@ -1007,7 +1013,7 @@ var Router = {
|
|
|
1007
1013
|
);
|
|
1008
1014
|
}
|
|
1009
1015
|
silent = 0;
|
|
1010
|
-
if (typeof window.
|
|
1016
|
+
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && lastChanged) {
|
|
1011
1017
|
lastChanged = safeguard(lastChanged);
|
|
1012
1018
|
}
|
|
1013
1019
|
return lastChanged;
|
|
@@ -1136,9 +1142,9 @@ var Router = {
|
|
|
1136
1142
|
window.addEventListener("hashchange", watchChange);
|
|
1137
1143
|
window.addEventListener("popstate", watchChange);
|
|
1138
1144
|
window.addEventListener("beforeunload", (domEvent) => {
|
|
1139
|
-
const
|
|
1140
|
-
Router.fire(ROUTER_EVENTS.PAGE_UNLOAD,
|
|
1141
|
-
const msg =
|
|
1145
|
+
const data = {};
|
|
1146
|
+
Router.fire(ROUTER_EVENTS.PAGE_UNLOAD, data);
|
|
1147
|
+
const msg = data["msg"];
|
|
1142
1148
|
if (msg) {
|
|
1143
1149
|
domEvent.returnValue = msg;
|
|
1144
1150
|
}
|
|
@@ -1170,26 +1176,26 @@ var frameGetter;
|
|
|
1170
1176
|
function parseEventInfo(eventInfo) {
|
|
1171
1177
|
const cached = eventInfoCache.get(eventInfo);
|
|
1172
1178
|
if (cached) {
|
|
1173
|
-
return assign({}, cached, {
|
|
1179
|
+
return assign({}, cached, { value: eventInfo });
|
|
1174
1180
|
}
|
|
1175
1181
|
const match = eventInfo.match(EVENT_METHOD_REGEXP) || [];
|
|
1176
1182
|
const result = {
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1183
|
+
id: match[1] || "",
|
|
1184
|
+
name: match[2] || "",
|
|
1185
|
+
params: match[3] || ""
|
|
1180
1186
|
};
|
|
1181
1187
|
eventInfoCache.set(eventInfo, result);
|
|
1182
|
-
return assign({}, result, {
|
|
1188
|
+
return assign({}, result, { value: eventInfo });
|
|
1183
1189
|
}
|
|
1184
1190
|
function findFrameInfo(current, eventType) {
|
|
1185
1191
|
const eventInfos = [];
|
|
1186
1192
|
let begin = current;
|
|
1187
|
-
const info = current.getAttribute(
|
|
1193
|
+
const info = current.getAttribute(`@${eventType}`);
|
|
1188
1194
|
let match;
|
|
1189
1195
|
if (info) {
|
|
1190
1196
|
match = parseEventInfo(info);
|
|
1191
1197
|
}
|
|
1192
|
-
if (match && !match.
|
|
1198
|
+
if (match && !match.id || selectorEvents[eventType]) {
|
|
1193
1199
|
let selectorFrameId = "#";
|
|
1194
1200
|
let backtrace = 0;
|
|
1195
1201
|
while (begin && begin !== document.body) {
|
|
@@ -1215,10 +1221,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1215
1221
|
if (selectorEntry) {
|
|
1216
1222
|
for (const selectorName of selectorEntry.selectors) {
|
|
1217
1223
|
const entry = {
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1224
|
+
value: selectorName,
|
|
1225
|
+
id: frameId,
|
|
1226
|
+
name: selectorName,
|
|
1227
|
+
params: ""
|
|
1222
1228
|
};
|
|
1223
1229
|
if (selectorName) {
|
|
1224
1230
|
if (!backtrace && elementMatchesSelector(current, selectorName)) {
|
|
@@ -1230,8 +1236,8 @@ function findFrameInfo(current, eventType) {
|
|
|
1230
1236
|
}
|
|
1231
1237
|
}
|
|
1232
1238
|
if (view.template && !backtrace) {
|
|
1233
|
-
if (match && !match.
|
|
1234
|
-
match.
|
|
1239
|
+
if (match && !match.id) {
|
|
1240
|
+
match.id = frameId;
|
|
1235
1241
|
}
|
|
1236
1242
|
break;
|
|
1237
1243
|
}
|
|
@@ -1247,10 +1253,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1247
1253
|
}
|
|
1248
1254
|
if (match) {
|
|
1249
1255
|
eventInfos.push({
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1256
|
+
id: match.id,
|
|
1257
|
+
value: match.value,
|
|
1258
|
+
name: match.name,
|
|
1259
|
+
params: match.params
|
|
1254
1260
|
});
|
|
1255
1261
|
}
|
|
1256
1262
|
return eventInfos;
|
|
@@ -1271,7 +1277,7 @@ function domEventProcessor(domEvent) {
|
|
|
1271
1277
|
const eventInfos = findFrameInfo(current, eventType);
|
|
1272
1278
|
if (eventInfos.length) {
|
|
1273
1279
|
for (const info of eventInfos) {
|
|
1274
|
-
const {
|
|
1280
|
+
const { id: frameId, name: handlerName, params } = info;
|
|
1275
1281
|
if (lastFrameId !== frameId) {
|
|
1276
1282
|
if (lastFrameId && domEvent.isPropagationStopped?.()) {
|
|
1277
1283
|
break;
|
|
@@ -1370,8 +1376,8 @@ var WrapMeta = {
|
|
|
1370
1376
|
td: [3, "<table><tbody><tr>"],
|
|
1371
1377
|
area: [1, "<map>"],
|
|
1372
1378
|
param: [1, "<object>"],
|
|
1373
|
-
|
|
1374
|
-
|
|
1379
|
+
svg: [1, '<svg xmlns="' + SVG_NS + '">'],
|
|
1380
|
+
math: [1, '<math xmlns="' + MATH_NS + '">'],
|
|
1375
1381
|
_: [0, ""]
|
|
1376
1382
|
};
|
|
1377
1383
|
WrapMeta["optgroup"] = WrapMeta["option"];
|
|
@@ -1404,9 +1410,9 @@ function vdomGetNode(html, refNode) {
|
|
|
1404
1410
|
const ns = refNode.namespaceURI;
|
|
1405
1411
|
let tag;
|
|
1406
1412
|
if (ns === SVG_NS) {
|
|
1407
|
-
tag = "
|
|
1413
|
+
tag = "svg";
|
|
1408
1414
|
} else if (ns === MATH_NS) {
|
|
1409
|
-
tag = "
|
|
1415
|
+
tag = "math";
|
|
1410
1416
|
} else {
|
|
1411
1417
|
const match = TAG_NAME_REGEXP.exec(html);
|
|
1412
1418
|
tag = match ? match[1] : "";
|
|
@@ -1428,7 +1434,7 @@ function vdomGetCompareKey(node) {
|
|
|
1428
1434
|
}
|
|
1429
1435
|
let key = el.autoId ? "" : el.getAttribute("id") || void 0;
|
|
1430
1436
|
if (!key) {
|
|
1431
|
-
key = el.getAttribute(
|
|
1437
|
+
key = el.getAttribute(LARK_KEYS.DIFF_KEY) || void 0;
|
|
1432
1438
|
}
|
|
1433
1439
|
if (!key) {
|
|
1434
1440
|
const larkView = el.getAttribute(LARK_VIEW);
|
|
@@ -1556,17 +1562,17 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1556
1562
|
}
|
|
1557
1563
|
}
|
|
1558
1564
|
function vdomSetNode(oldNode, newNode, oldParent, ref, frame, keys_) {
|
|
1559
|
-
if (vdomSpecialDiff(oldNode, newNode) || oldNode.nodeType === 1 && oldNode.hasAttribute(
|
|
1565
|
+
if (vdomSpecialDiff(oldNode, newNode) || oldNode.nodeType === 1 && oldNode.hasAttribute(LARK_KEYS.VIEW_KEY) || !(oldNode.isEqualNode && oldNode.isEqualNode(newNode))) {
|
|
1560
1566
|
if (oldNode.nodeType === newNode.nodeType && oldNode.nodeName === newNode.nodeName) {
|
|
1561
1567
|
if (oldNode.nodeType === 1) {
|
|
1562
1568
|
const oldEl = oldNode;
|
|
1563
1569
|
const newEl = newNode;
|
|
1564
|
-
const staticKey = newEl.getAttribute(
|
|
1565
|
-
if (staticKey && staticKey === oldEl.getAttribute(
|
|
1570
|
+
const staticKey = newEl.getAttribute(LARK_KEYS.DIFF_KEY);
|
|
1571
|
+
if (staticKey && staticKey === oldEl.getAttribute(LARK_KEYS.DIFF_KEY)) {
|
|
1566
1572
|
return;
|
|
1567
1573
|
}
|
|
1568
1574
|
const newLarkView = newEl.getAttribute(LARK_VIEW);
|
|
1569
|
-
const updateAttribute = !newEl.getAttribute(
|
|
1575
|
+
const updateAttribute = !newEl.getAttribute(LARK_KEYS.ATTR_KEY) || newEl.getAttribute(LARK_KEYS.ATTR_KEY) !== oldEl.getAttribute(LARK_KEYS.ATTR_KEY);
|
|
1570
1576
|
let updateChildren = true;
|
|
1571
1577
|
if (newLarkView) {
|
|
1572
1578
|
const oldFrameId = oldEl.getAttribute("id") || "";
|
|
@@ -1711,7 +1717,7 @@ var Updater = class {
|
|
|
1711
1717
|
if (key) {
|
|
1712
1718
|
result = this.data[key];
|
|
1713
1719
|
}
|
|
1714
|
-
if (typeof window !== "undefined" && window.
|
|
1720
|
+
if (typeof window !== "undefined" && window.__lark_Debug) {
|
|
1715
1721
|
return safeguard(result);
|
|
1716
1722
|
}
|
|
1717
1723
|
return result;
|
|
@@ -1846,225 +1852,10 @@ var Updater = class {
|
|
|
1846
1852
|
// src/view.ts
|
|
1847
1853
|
var VIEW_GLOBALS = {};
|
|
1848
1854
|
if (typeof window !== "undefined") {
|
|
1849
|
-
VIEW_GLOBALS["
|
|
1855
|
+
VIEW_GLOBALS["window"] = window;
|
|
1850
1856
|
}
|
|
1851
1857
|
if (typeof document !== "undefined") {
|
|
1852
|
-
VIEW_GLOBALS["
|
|
1853
|
-
}
|
|
1854
|
-
function viewPrepare(oView) {
|
|
1855
|
-
if (oView.ctors) {
|
|
1856
|
-
return oView.ctors;
|
|
1857
|
-
}
|
|
1858
|
-
const ctors = [];
|
|
1859
|
-
oView.ctors = ctors;
|
|
1860
|
-
const proto = oView.prototype;
|
|
1861
|
-
const eventsObject = {};
|
|
1862
|
-
const eventsList = [];
|
|
1863
|
-
const selectorObject = {};
|
|
1864
|
-
const mixins = proto["mixins"];
|
|
1865
|
-
if (mixins && Array.isArray(mixins)) {
|
|
1866
|
-
viewMergeMixins(mixins, oView, ctors);
|
|
1867
|
-
}
|
|
1868
|
-
for (const p in proto) {
|
|
1869
|
-
if (!has(proto, p)) continue;
|
|
1870
|
-
const currentFn = proto[p];
|
|
1871
|
-
if (typeof currentFn !== "function") continue;
|
|
1872
|
-
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
1873
|
-
if (!matches) continue;
|
|
1874
|
-
const isSelector = matches[1];
|
|
1875
|
-
const selectorOrCallback = matches[2];
|
|
1876
|
-
const events = matches[3];
|
|
1877
|
-
const modifiers = matches[4];
|
|
1878
|
-
const mod = {};
|
|
1879
|
-
if (modifiers) {
|
|
1880
|
-
for (const item of modifiers.split(",")) {
|
|
1881
|
-
mod[item] = true;
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
const eventTypes = events.split(",");
|
|
1885
|
-
for (const item of eventTypes) {
|
|
1886
|
-
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
1887
|
-
let mask = 1;
|
|
1888
|
-
if (isSelector) {
|
|
1889
|
-
if (globalNode) {
|
|
1890
|
-
eventsList.push({
|
|
1891
|
-
handler: currentFn,
|
|
1892
|
-
element: globalNode,
|
|
1893
|
-
eventName: item,
|
|
1894
|
-
modifiers: mod
|
|
1895
|
-
});
|
|
1896
|
-
continue;
|
|
1897
|
-
}
|
|
1898
|
-
mask = 2;
|
|
1899
|
-
let selectorEntry = selectorObject[item];
|
|
1900
|
-
if (!selectorEntry) {
|
|
1901
|
-
selectorEntry = selectorObject[item] = {
|
|
1902
|
-
selectors: []
|
|
1903
|
-
};
|
|
1904
|
-
}
|
|
1905
|
-
if (!selectorEntry[selectorOrCallback]) {
|
|
1906
|
-
selectorEntry[selectorOrCallback] = 1;
|
|
1907
|
-
selectorEntry.selectors.push(selectorOrCallback);
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
1911
|
-
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
1912
|
-
const existingFn = proto[combinedKey];
|
|
1913
|
-
if (!existingFn) {
|
|
1914
|
-
proto[combinedKey] = currentFn;
|
|
1915
|
-
} else {
|
|
1916
|
-
const mixinFn = currentFn;
|
|
1917
|
-
const existingMixin = existingFn;
|
|
1918
|
-
if (existingMixin.b) {
|
|
1919
|
-
if (mixinFn.b) {
|
|
1920
|
-
proto[combinedKey] = processMixinsSameEvent(
|
|
1921
|
-
currentFn,
|
|
1922
|
-
existingFn
|
|
1923
|
-
);
|
|
1924
|
-
} else if (has(proto, p)) {
|
|
1925
|
-
proto[combinedKey] = currentFn;
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1931
|
-
viewWrapMethod(proto, "render", "$b");
|
|
1932
|
-
proto["$eo"] = eventsObject;
|
|
1933
|
-
proto["$el"] = eventsList;
|
|
1934
|
-
proto["$so"] = selectorObject;
|
|
1935
|
-
proto["$f"] = proto["assign"];
|
|
1936
|
-
return ctors;
|
|
1937
|
-
}
|
|
1938
|
-
function viewWrapMethod(proto, fnName, shortKey) {
|
|
1939
|
-
const originalFn = proto[fnName];
|
|
1940
|
-
if (typeof originalFn !== "function") return;
|
|
1941
|
-
const wrapped = function(...args) {
|
|
1942
|
-
if (this.signature > 0) {
|
|
1943
|
-
this.signature++;
|
|
1944
|
-
this.fire("rendercall");
|
|
1945
|
-
destroyAllResources(this, false);
|
|
1946
|
-
const instanceFn = typeof this[fnName] === "function" ? this[fnName] : originalFn;
|
|
1947
|
-
const fnToCall = instanceFn === wrapped ? originalFn : instanceFn;
|
|
1948
|
-
return funcWithTry(fnToCall, args, this, noop);
|
|
1949
|
-
}
|
|
1950
|
-
return void 0;
|
|
1951
|
-
};
|
|
1952
|
-
proto[fnName] = wrapped;
|
|
1953
|
-
proto[shortKey] = wrapped;
|
|
1954
|
-
}
|
|
1955
|
-
function processMixinsSameEvent(additional, exist) {
|
|
1956
|
-
let temp;
|
|
1957
|
-
const existMixin = exist;
|
|
1958
|
-
if (existMixin.a) {
|
|
1959
|
-
temp = existMixin;
|
|
1960
|
-
} else {
|
|
1961
|
-
temp = function(...e) {
|
|
1962
|
-
funcWithTry(temp.a ?? [], e, this, noop);
|
|
1963
|
-
};
|
|
1964
|
-
temp.a = [exist];
|
|
1965
|
-
temp.b = 1;
|
|
1966
|
-
}
|
|
1967
|
-
const additionalMixin = additional;
|
|
1968
|
-
temp.a = (temp.a ?? []).concat(additionalMixin.a ?? [additional]);
|
|
1969
|
-
return temp;
|
|
1970
|
-
}
|
|
1971
|
-
function viewMergeMixins(mixins, viewClass, ctors) {
|
|
1972
|
-
const proto = viewClass.prototype;
|
|
1973
|
-
const temp = {};
|
|
1974
|
-
for (const node of mixins) {
|
|
1975
|
-
for (const p in node) {
|
|
1976
|
-
if (!has(node, p)) continue;
|
|
1977
|
-
const fn = node[p];
|
|
1978
|
-
const exist = temp[p];
|
|
1979
|
-
if (p === "ctor") {
|
|
1980
|
-
ctors.push(fn);
|
|
1981
|
-
continue;
|
|
1982
|
-
}
|
|
1983
|
-
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
1984
|
-
if (exist) {
|
|
1985
|
-
temp[p] = processMixinsSameEvent(fn, exist);
|
|
1986
|
-
} else {
|
|
1987
|
-
fn.b = 1;
|
|
1988
|
-
temp[p] = fn;
|
|
1989
|
-
}
|
|
1990
|
-
} else {
|
|
1991
|
-
if (!exist) {
|
|
1992
|
-
temp[p] = fn;
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
for (const p in temp) {
|
|
1998
|
-
if (!has(proto, p)) {
|
|
1999
|
-
proto[p] = temp[p];
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
function viewDelegateEvents(view, destroy = false) {
|
|
2004
|
-
const proto = Object.getPrototypeOf(view) ?? {};
|
|
2005
|
-
const eventsObject = proto["$eo"] || view.eventObjectMap;
|
|
2006
|
-
const selectorObject = proto["$so"] || view.eventSelectorMap;
|
|
2007
|
-
const eventsList = proto["$el"] || view.globalEventList;
|
|
2008
|
-
for (const e in eventsObject) {
|
|
2009
|
-
if (has(eventsObject, e)) {
|
|
2010
|
-
if (destroy) {
|
|
2011
|
-
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
2012
|
-
} else {
|
|
2013
|
-
EventDelegator.bind(e, !!selectorObject[e]);
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
for (const entry of eventsList) {
|
|
2018
|
-
if (destroy) {
|
|
2019
|
-
entry.element.removeEventListener(
|
|
2020
|
-
entry.eventName,
|
|
2021
|
-
entry.boundHandler
|
|
2022
|
-
);
|
|
2023
|
-
} else {
|
|
2024
|
-
const handler = entry.handler;
|
|
2025
|
-
const element = entry.element;
|
|
2026
|
-
const modifiers = entry.modifiers;
|
|
2027
|
-
entry.boundHandler = function(domEvent) {
|
|
2028
|
-
const extendedEvent = domEvent;
|
|
2029
|
-
extendedEvent.eventTarget = element;
|
|
2030
|
-
if (modifiers) {
|
|
2031
|
-
const kbEvent = domEvent;
|
|
2032
|
-
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
2033
|
-
return;
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
funcWithTry(handler, [domEvent], view, noop);
|
|
2037
|
-
};
|
|
2038
|
-
entry.element.addEventListener(
|
|
2039
|
-
entry.eventName,
|
|
2040
|
-
entry.boundHandler
|
|
2041
|
-
);
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
}
|
|
2045
|
-
function destroyAllResources(view, lastly) {
|
|
2046
|
-
const cache = view.resources;
|
|
2047
|
-
for (const p in cache) {
|
|
2048
|
-
if (has(cache, p)) {
|
|
2049
|
-
const entry = cache[p];
|
|
2050
|
-
if (lastly || entry.destroyOnRender) {
|
|
2051
|
-
destroyResource(cache, p, true);
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
function destroyResource(cache, key, callDestroy, oldEntity) {
|
|
2057
|
-
const entry = cache[key];
|
|
2058
|
-
if (!entry || entry.entity === oldEntity) return void 0;
|
|
2059
|
-
const entity = entry.entity;
|
|
2060
|
-
if (entity && typeof entity === "object") {
|
|
2061
|
-
const destroyFn = entity["destroy"];
|
|
2062
|
-
if (typeof destroyFn === "function" && callDestroy) {
|
|
2063
|
-
funcWithTry(destroyFn, [], entity, noop);
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
Reflect.deleteProperty(cache, key);
|
|
2067
|
-
return entity;
|
|
1858
|
+
VIEW_GLOBALS["document"] = document;
|
|
2068
1859
|
}
|
|
2069
1860
|
var View = class _View {
|
|
2070
1861
|
/** View ID (same as owner frame ID) */
|
|
@@ -2089,18 +1880,43 @@ var View = class _View {
|
|
|
2089
1880
|
observedStateKeys;
|
|
2090
1881
|
/** Resource map */
|
|
2091
1882
|
resources = {};
|
|
2092
|
-
/** Selector event map: eventType -> handler name list */
|
|
2093
|
-
eventSelectorMap = {};
|
|
2094
|
-
/** Event object map: eventType -> bitmask */
|
|
2095
|
-
eventObjectMap = {};
|
|
2096
|
-
/** Global event list */
|
|
2097
|
-
globalEventList = [];
|
|
2098
1883
|
/** Assign method reference */
|
|
2099
1884
|
assignMethod;
|
|
2100
1885
|
/** Whether endUpdate pending */
|
|
2101
1886
|
endUpdatePending;
|
|
2102
1887
|
/** Internal event storage */
|
|
2103
1888
|
_events = new EventEmitter();
|
|
1889
|
+
// ============================================================
|
|
1890
|
+
// Getters for prototype-stored event maps
|
|
1891
|
+
// ============================================================
|
|
1892
|
+
/**
|
|
1893
|
+
* Event bitmask map: eventType -> bitmask (1=root, 2=selector).
|
|
1894
|
+
* Read from prototype ($evtObjMap) set by View.prepare.
|
|
1895
|
+
* Using a getter avoids ES6 class field shadowing the prototype value.
|
|
1896
|
+
*/
|
|
1897
|
+
get eventObjectMap() {
|
|
1898
|
+
const proto = Object.getPrototypeOf(this);
|
|
1899
|
+
return proto["$evtObjMap"] || {};
|
|
1900
|
+
}
|
|
1901
|
+
/**
|
|
1902
|
+
* Selector event map: eventType -> selector list.
|
|
1903
|
+
* Read from prototype ($selMap) set by View.prepare.
|
|
1904
|
+
*/
|
|
1905
|
+
get eventSelectorMap() {
|
|
1906
|
+
const proto = Object.getPrototypeOf(this);
|
|
1907
|
+
return proto["$selMap"] || {};
|
|
1908
|
+
}
|
|
1909
|
+
/**
|
|
1910
|
+
* Global event list: [{handler, element, eventName, modifiers}].
|
|
1911
|
+
* Read from prototype ($globalEvtList) set by View.prepare.
|
|
1912
|
+
*/
|
|
1913
|
+
get globalEventList() {
|
|
1914
|
+
const proto = Object.getPrototypeOf(this);
|
|
1915
|
+
return proto["$globalEvtList"] || [];
|
|
1916
|
+
}
|
|
1917
|
+
// ============================================================
|
|
1918
|
+
// Instance lifecycle methods
|
|
1919
|
+
// ============================================================
|
|
2104
1920
|
/**
|
|
2105
1921
|
* Initialize view (called by Frame when mounting).
|
|
2106
1922
|
*/
|
|
@@ -2108,14 +1924,7 @@ var View = class _View {
|
|
|
2108
1924
|
}
|
|
2109
1925
|
/**
|
|
2110
1926
|
* Render view template (called by Frame after init).
|
|
2111
|
-
* Wrapped by
|
|
2112
|
-
*
|
|
2113
|
-
* Default implementation calls updater.digest() which:
|
|
2114
|
-
* 1. Executes the template function with current data
|
|
2115
|
-
* 2. Runs VDOM diff against previous DOM
|
|
2116
|
-
* 3. Applies DOM operations
|
|
2117
|
-
* 4. Calls endUpdate to mount child frames
|
|
2118
|
-
*
|
|
1927
|
+
* Wrapped by View.wrapMethod to manage signature + resources.
|
|
2119
1928
|
*/
|
|
2120
1929
|
render() {
|
|
2121
1930
|
this.updater.digest();
|
|
@@ -2167,7 +1976,7 @@ var View = class _View {
|
|
|
2167
1976
|
if (!flag) {
|
|
2168
1977
|
setTimeout(
|
|
2169
1978
|
this.wrapAsync(() => {
|
|
2170
|
-
runInvokes(ownerFrame);
|
|
1979
|
+
_View.runInvokes(ownerFrame);
|
|
2171
1980
|
}),
|
|
2172
1981
|
0
|
|
2173
1982
|
);
|
|
@@ -2243,7 +2052,7 @@ var View = class _View {
|
|
|
2243
2052
|
capture(key, resource, destroyOnRender = false) {
|
|
2244
2053
|
const cache = this.resources;
|
|
2245
2054
|
if (resource) {
|
|
2246
|
-
destroyResource(cache, key, true, resource);
|
|
2055
|
+
_View.destroyResource(cache, key, true, resource);
|
|
2247
2056
|
cache[key] = {
|
|
2248
2057
|
entity: resource,
|
|
2249
2058
|
destroyOnRender
|
|
@@ -2259,7 +2068,7 @@ var View = class _View {
|
|
|
2259
2068
|
* If destroy=true, calls the resource's destroy() method.
|
|
2260
2069
|
*/
|
|
2261
2070
|
release(key, destroy = true) {
|
|
2262
|
-
return destroyResource(this.resources, key, destroy);
|
|
2071
|
+
return _View.destroyResource(this.resources, key, destroy);
|
|
2263
2072
|
}
|
|
2264
2073
|
// ============================================================
|
|
2265
2074
|
// Leave tip
|
|
@@ -2305,31 +2114,294 @@ var View = class _View {
|
|
|
2305
2114
|
});
|
|
2306
2115
|
}
|
|
2307
2116
|
// ============================================================
|
|
2308
|
-
// Static
|
|
2117
|
+
// Static public methods
|
|
2309
2118
|
// ============================================================
|
|
2310
2119
|
/** Collected ctors from mixins */
|
|
2311
2120
|
static ctors;
|
|
2121
|
+
/**
|
|
2122
|
+
* Prepare a View subclass by scanning its prototype for event method patterns.
|
|
2123
|
+
* Pattern: `$?name<eventType1,eventType2>(&modifiers)`
|
|
2124
|
+
*
|
|
2125
|
+
* Only runs once per View subclass (guarded by ctors marker).
|
|
2126
|
+
* Called from Frame.mountView before creating the view instance.
|
|
2127
|
+
*/
|
|
2128
|
+
static prepare(oView) {
|
|
2129
|
+
if (oView.ctors) {
|
|
2130
|
+
return oView.ctors;
|
|
2131
|
+
}
|
|
2132
|
+
const ctors = [];
|
|
2133
|
+
oView.ctors = ctors;
|
|
2134
|
+
const proto = oView.prototype;
|
|
2135
|
+
const eventsObject = {};
|
|
2136
|
+
const eventsList = [];
|
|
2137
|
+
const selectorObject = {};
|
|
2138
|
+
const mixins = proto["mixins"];
|
|
2139
|
+
if (mixins && Array.isArray(mixins)) {
|
|
2140
|
+
_View.mergeMixins(mixins, oView, ctors);
|
|
2141
|
+
}
|
|
2142
|
+
for (const p in proto) {
|
|
2143
|
+
if (!has(proto, p)) continue;
|
|
2144
|
+
const currentFn = proto[p];
|
|
2145
|
+
if (typeof currentFn !== "function") continue;
|
|
2146
|
+
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
2147
|
+
if (!matches) continue;
|
|
2148
|
+
const isSelector = matches[1];
|
|
2149
|
+
const selectorOrCallback = matches[2];
|
|
2150
|
+
const events = matches[3];
|
|
2151
|
+
const modifiers = matches[4];
|
|
2152
|
+
const mod = {};
|
|
2153
|
+
if (modifiers) {
|
|
2154
|
+
for (const item of modifiers.split(",")) {
|
|
2155
|
+
mod[item] = true;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
const eventTypes = events.split(",");
|
|
2159
|
+
for (const item of eventTypes) {
|
|
2160
|
+
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
2161
|
+
let mask = 1;
|
|
2162
|
+
if (isSelector) {
|
|
2163
|
+
if (globalNode) {
|
|
2164
|
+
eventsList.push({
|
|
2165
|
+
handler: currentFn,
|
|
2166
|
+
element: globalNode,
|
|
2167
|
+
eventName: item,
|
|
2168
|
+
modifiers: mod
|
|
2169
|
+
});
|
|
2170
|
+
continue;
|
|
2171
|
+
}
|
|
2172
|
+
mask = 2;
|
|
2173
|
+
let selectorEntry = selectorObject[item];
|
|
2174
|
+
if (!selectorEntry) {
|
|
2175
|
+
selectorEntry = selectorObject[item] = {
|
|
2176
|
+
selectors: []
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
if (!selectorEntry[selectorOrCallback]) {
|
|
2180
|
+
selectorEntry[selectorOrCallback] = 1;
|
|
2181
|
+
selectorEntry.selectors.push(selectorOrCallback);
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
2185
|
+
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
2186
|
+
const existingFn = proto[combinedKey];
|
|
2187
|
+
if (!existingFn) {
|
|
2188
|
+
proto[combinedKey] = currentFn;
|
|
2189
|
+
} else {
|
|
2190
|
+
const mixinFn = currentFn;
|
|
2191
|
+
const existingMixin = existingFn;
|
|
2192
|
+
if (existingMixin.marker) {
|
|
2193
|
+
if (mixinFn.marker) {
|
|
2194
|
+
proto[combinedKey] = _View.processMixinsSameEvent(
|
|
2195
|
+
currentFn,
|
|
2196
|
+
existingFn
|
|
2197
|
+
);
|
|
2198
|
+
} else if (has(proto, p)) {
|
|
2199
|
+
proto[combinedKey] = currentFn;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
_View.wrapMethod(proto, "render", "$renderWrap");
|
|
2206
|
+
proto["$evtObjMap"] = eventsObject;
|
|
2207
|
+
proto["$globalEvtList"] = eventsList;
|
|
2208
|
+
proto["$selMap"] = selectorObject;
|
|
2209
|
+
proto["$assignFn"] = proto["assign"];
|
|
2210
|
+
return ctors;
|
|
2211
|
+
}
|
|
2212
|
+
/**
|
|
2213
|
+
* Bind or unbind event delegation for a view instance.
|
|
2214
|
+
* Called from Frame during mount/unmount.
|
|
2215
|
+
*/
|
|
2216
|
+
static delegateEvents(view, destroy = false) {
|
|
2217
|
+
const eventsObject = view.eventObjectMap;
|
|
2218
|
+
const selectorObject = view.eventSelectorMap;
|
|
2219
|
+
const eventsList = view.globalEventList;
|
|
2220
|
+
for (const e in eventsObject) {
|
|
2221
|
+
if (has(eventsObject, e)) {
|
|
2222
|
+
if (destroy) {
|
|
2223
|
+
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
2224
|
+
} else {
|
|
2225
|
+
EventDelegator.bind(e, !!selectorObject[e]);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
for (const entry of eventsList) {
|
|
2230
|
+
if (destroy) {
|
|
2231
|
+
entry.element.removeEventListener(
|
|
2232
|
+
entry.eventName,
|
|
2233
|
+
entry.boundHandler
|
|
2234
|
+
);
|
|
2235
|
+
} else {
|
|
2236
|
+
const handler = entry.handler;
|
|
2237
|
+
const element = entry.element;
|
|
2238
|
+
const modifiers = entry.modifiers;
|
|
2239
|
+
entry.boundHandler = function(domEvent) {
|
|
2240
|
+
const extendedEvent = domEvent;
|
|
2241
|
+
extendedEvent.eventTarget = element;
|
|
2242
|
+
if (modifiers) {
|
|
2243
|
+
const kbEvent = domEvent;
|
|
2244
|
+
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
2245
|
+
return;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
funcWithTry(handler, [domEvent], view, noop);
|
|
2249
|
+
};
|
|
2250
|
+
entry.element.addEventListener(
|
|
2251
|
+
entry.eventName,
|
|
2252
|
+
entry.boundHandler
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Destroy all resources managed by a view.
|
|
2259
|
+
* If lastly=true, destroy ALL resources; otherwise only destroyOnRender ones.
|
|
2260
|
+
*/
|
|
2261
|
+
static destroyAllResources(view, lastly) {
|
|
2262
|
+
const cache = view.resources;
|
|
2263
|
+
for (const p in cache) {
|
|
2264
|
+
if (has(cache, p)) {
|
|
2265
|
+
const entry = cache[p];
|
|
2266
|
+
if (lastly || entry.destroyOnRender) {
|
|
2267
|
+
_View.destroyResource(cache, p, true);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
/**
|
|
2273
|
+
* Process deferred invoke calls on a frame.
|
|
2274
|
+
*/
|
|
2275
|
+
static 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
|
+
// ============================================================
|
|
2286
|
+
// Static private methods
|
|
2287
|
+
// ============================================================
|
|
2288
|
+
/**
|
|
2289
|
+
* Wrap a method on the prototype to add signature checking and resource cleanup.
|
|
2290
|
+
*/
|
|
2291
|
+
static wrapMethod(proto, fnName, shortKey) {
|
|
2292
|
+
const originalFn = proto[fnName];
|
|
2293
|
+
if (typeof originalFn !== "function") return;
|
|
2294
|
+
const wrapped = function(...args) {
|
|
2295
|
+
if (this.signature > 0) {
|
|
2296
|
+
this.signature++;
|
|
2297
|
+
this.fire("render");
|
|
2298
|
+
_View.destroyAllResources(this, false);
|
|
2299
|
+
const instanceFn = typeof this[fnName] === "function" ? this[fnName] : originalFn;
|
|
2300
|
+
const fnToCall = instanceFn === wrapped ? originalFn : instanceFn;
|
|
2301
|
+
return funcWithTry(fnToCall, args, this, noop);
|
|
2302
|
+
}
|
|
2303
|
+
return void 0;
|
|
2304
|
+
};
|
|
2305
|
+
proto[fnName] = wrapped;
|
|
2306
|
+
proto[shortKey] = wrapped;
|
|
2307
|
+
}
|
|
2308
|
+
/**
|
|
2309
|
+
* When two mixins define the same event method, merge them into
|
|
2310
|
+
* a single function that calls both in sequence.
|
|
2311
|
+
*/
|
|
2312
|
+
static processMixinsSameEvent(additional, exist) {
|
|
2313
|
+
let temp;
|
|
2314
|
+
const existMixin = exist;
|
|
2315
|
+
if (existMixin.handlerList) {
|
|
2316
|
+
temp = existMixin;
|
|
2317
|
+
} else {
|
|
2318
|
+
temp = function(...e) {
|
|
2319
|
+
funcWithTry(temp.handlerList ?? [], e, this, noop);
|
|
2320
|
+
};
|
|
2321
|
+
temp.handlerList = [exist];
|
|
2322
|
+
temp.marker = 1;
|
|
2323
|
+
}
|
|
2324
|
+
const additionalMixin = additional;
|
|
2325
|
+
temp.handlerList = (temp.handlerList ?? []).concat(
|
|
2326
|
+
additionalMixin.handlerList ?? [additional]
|
|
2327
|
+
);
|
|
2328
|
+
return temp;
|
|
2329
|
+
}
|
|
2330
|
+
/**
|
|
2331
|
+
* Merge an array of mixin objects into the view prototype.
|
|
2332
|
+
*/
|
|
2333
|
+
static mergeMixins(mixins, viewClass, ctors) {
|
|
2334
|
+
const proto = viewClass.prototype;
|
|
2335
|
+
const temp = {};
|
|
2336
|
+
for (const node of mixins) {
|
|
2337
|
+
for (const p in node) {
|
|
2338
|
+
if (!has(node, p)) continue;
|
|
2339
|
+
const fn = node[p];
|
|
2340
|
+
const exist = temp[p];
|
|
2341
|
+
if (p === "make") {
|
|
2342
|
+
ctors.push(fn);
|
|
2343
|
+
continue;
|
|
2344
|
+
}
|
|
2345
|
+
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
2346
|
+
if (exist) {
|
|
2347
|
+
temp[p] = _View.processMixinsSameEvent(fn, exist);
|
|
2348
|
+
} else {
|
|
2349
|
+
fn.marker = 1;
|
|
2350
|
+
temp[p] = fn;
|
|
2351
|
+
}
|
|
2352
|
+
} else {
|
|
2353
|
+
if (!exist) {
|
|
2354
|
+
temp[p] = fn;
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
for (const p in temp) {
|
|
2360
|
+
if (!has(proto, p)) {
|
|
2361
|
+
proto[p] = temp[p];
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Destroy a single resource entry.
|
|
2367
|
+
*/
|
|
2368
|
+
static destroyResource(cache, key, callDestroy, oldEntity) {
|
|
2369
|
+
const entry = cache[key];
|
|
2370
|
+
if (!entry || entry.entity === oldEntity) return void 0;
|
|
2371
|
+
const entity = entry.entity;
|
|
2372
|
+
if (entity && typeof entity === "object") {
|
|
2373
|
+
const destroyFn = entity["destroy"];
|
|
2374
|
+
if (typeof destroyFn === "function" && callDestroy) {
|
|
2375
|
+
funcWithTry(destroyFn, [], entity, noop);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
Reflect.deleteProperty(cache, key);
|
|
2379
|
+
return entity;
|
|
2380
|
+
}
|
|
2381
|
+
// ============================================================
|
|
2382
|
+
// Static: extend and merge
|
|
2383
|
+
// ============================================================
|
|
2312
2384
|
/**
|
|
2313
2385
|
* Extend View to create a new View subclass.
|
|
2314
2386
|
*
|
|
2315
2387
|
* Supports:
|
|
2316
|
-
* - props.
|
|
2388
|
+
* - props.make: constructor-like init (called with initParams + {node, deep})
|
|
2317
2389
|
* - props.mixins: array of mixin objects
|
|
2318
2390
|
* - Event method patterns: `'name<click>'` etc.
|
|
2319
2391
|
*/
|
|
2320
2392
|
static extend(props, statics) {
|
|
2321
2393
|
props = props || {};
|
|
2322
|
-
const
|
|
2394
|
+
const make = props["make"];
|
|
2323
2395
|
const ctors = [];
|
|
2324
|
-
if (
|
|
2325
|
-
ctors.push(
|
|
2396
|
+
if (make) {
|
|
2397
|
+
ctors.push(make);
|
|
2326
2398
|
}
|
|
2327
2399
|
const ParentView = this;
|
|
2328
2400
|
const ChildView = class extends ParentView {
|
|
2329
2401
|
constructor(nodeId, ownerFrame, initParams, node, mixinCtors) {
|
|
2330
2402
|
super(nodeId, ownerFrame, initParams, node, []);
|
|
2331
2403
|
for (const key in props) {
|
|
2332
|
-
if (has(props, key) && key !== "
|
|
2404
|
+
if (has(props, key) && key !== "make" && key !== "render") {
|
|
2333
2405
|
this[key] = props[key];
|
|
2334
2406
|
}
|
|
2335
2407
|
}
|
|
@@ -2351,7 +2423,7 @@ var View = class _View {
|
|
|
2351
2423
|
};
|
|
2352
2424
|
const proto = ChildView.prototype;
|
|
2353
2425
|
for (const key in props) {
|
|
2354
|
-
if (has(props, key) && key !== "
|
|
2426
|
+
if (has(props, key) && key !== "make") {
|
|
2355
2427
|
proto[key] = props[key];
|
|
2356
2428
|
}
|
|
2357
2429
|
}
|
|
@@ -2362,36 +2434,17 @@ var View = class _View {
|
|
|
2362
2434
|
}
|
|
2363
2435
|
}
|
|
2364
2436
|
}
|
|
2365
|
-
ChildView.merge = viewMerge;
|
|
2366
|
-
ChildView.extend = _View.extend;
|
|
2367
2437
|
return ChildView;
|
|
2368
2438
|
}
|
|
2369
2439
|
/**
|
|
2370
2440
|
* Merge mixins into View prototype.
|
|
2371
2441
|
*/
|
|
2372
2442
|
static merge(...mixins) {
|
|
2373
|
-
const
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
return self;
|
|
2443
|
+
const existingCtors = this.ctors || [];
|
|
2444
|
+
_View.mergeMixins(mixins, this, existingCtors);
|
|
2445
|
+
return this;
|
|
2377
2446
|
}
|
|
2378
2447
|
};
|
|
2379
|
-
function viewMerge(...mixins) {
|
|
2380
|
-
const self = this;
|
|
2381
|
-
const existingCtors = self.ctors || [];
|
|
2382
|
-
viewMergeMixins(mixins, self, existingCtors);
|
|
2383
|
-
return self;
|
|
2384
|
-
}
|
|
2385
|
-
function runInvokes(frame) {
|
|
2386
|
-
const list = frame.invokeList;
|
|
2387
|
-
if (!list) return;
|
|
2388
|
-
while (list.length) {
|
|
2389
|
-
const entry = list.shift();
|
|
2390
|
-
if (entry && !entry.removed) {
|
|
2391
|
-
frame.invoke(entry.name, entry.args);
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
}
|
|
2395
2448
|
|
|
2396
2449
|
// src/frame.ts
|
|
2397
2450
|
var frameRegistry = /* @__PURE__ */ new Map();
|
|
@@ -2430,7 +2483,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2430
2483
|
hasAltered = 0;
|
|
2431
2484
|
/** Whether view is destroyed */
|
|
2432
2485
|
destroyed = 0;
|
|
2433
|
-
/** View path (lark
|
|
2486
|
+
/** View path (v-lark attribute value) */
|
|
2434
2487
|
viewPath;
|
|
2435
2488
|
/** Original template before mount */
|
|
2436
2489
|
originalTemplate;
|
|
@@ -2499,7 +2552,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2499
2552
|
*/
|
|
2500
2553
|
doMountView(ViewClass, params, node, sign) {
|
|
2501
2554
|
if (sign !== this.signature) return;
|
|
2502
|
-
const mixinCtors =
|
|
2555
|
+
const mixinCtors = View.prepare(ViewClass);
|
|
2503
2556
|
const ViewConstructor = ViewClass;
|
|
2504
2557
|
const view = new ViewConstructor(
|
|
2505
2558
|
this.id,
|
|
@@ -2510,7 +2563,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2510
2563
|
);
|
|
2511
2564
|
this.viewInstance = view;
|
|
2512
2565
|
view.signature = 1;
|
|
2513
|
-
|
|
2566
|
+
View.delegateEvents(view);
|
|
2514
2567
|
const initResult = funcWithTry(
|
|
2515
2568
|
view.init,
|
|
2516
2569
|
[params, { node, deep: !view.template }],
|
|
@@ -2521,13 +2574,10 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2521
2574
|
Promise.resolve(initResult).then(() => {
|
|
2522
2575
|
if (nextSign !== this.signature) return;
|
|
2523
2576
|
if (view.template) {
|
|
2524
|
-
|
|
2525
|
-
if (renderFn) {
|
|
2526
|
-
renderFn.call(view);
|
|
2527
|
-
}
|
|
2577
|
+
view.render();
|
|
2528
2578
|
} else {
|
|
2529
2579
|
this.hasAltered = 0;
|
|
2530
|
-
if (!view
|
|
2580
|
+
if (!view.endUpdatePendingFlag) {
|
|
2531
2581
|
view.endUpdate();
|
|
2532
2582
|
}
|
|
2533
2583
|
}
|
|
@@ -2714,7 +2764,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2714
2764
|
/** Get or create root frame */
|
|
2715
2765
|
static root(rootId) {
|
|
2716
2766
|
if (!rootFrame) {
|
|
2717
|
-
rootId = rootId || "
|
|
2767
|
+
rootId = rootId || "root";
|
|
2718
2768
|
let rootElement = document.getElementById(rootId);
|
|
2719
2769
|
if (!rootElement) {
|
|
2720
2770
|
rootElement = document.body;
|
|
@@ -2835,19 +2885,19 @@ function registerViewClass(viewPath, ViewClass) {
|
|
|
2835
2885
|
}
|
|
2836
2886
|
|
|
2837
2887
|
// src/service.ts
|
|
2838
|
-
var
|
|
2839
|
-
/**
|
|
2888
|
+
var Payload = class {
|
|
2889
|
+
/** Payload data */
|
|
2840
2890
|
data;
|
|
2841
2891
|
/** Internal cache info */
|
|
2842
2892
|
cacheInfo;
|
|
2843
2893
|
constructor(data = {}) {
|
|
2844
2894
|
this.data = data;
|
|
2845
2895
|
}
|
|
2846
|
-
/** Get a value from
|
|
2896
|
+
/** Get a value from payload data */
|
|
2847
2897
|
get(key) {
|
|
2848
2898
|
return this.data[key];
|
|
2849
2899
|
}
|
|
2850
|
-
/** Set a value in
|
|
2900
|
+
/** Set a value in payload data */
|
|
2851
2901
|
set(keyOrData, value) {
|
|
2852
2902
|
if (typeof keyOrData === "string") {
|
|
2853
2903
|
this.data[keyOrData] = value;
|
|
@@ -2859,287 +2909,366 @@ var Bag = class {
|
|
|
2859
2909
|
};
|
|
2860
2910
|
var FETCH_FLAGS_ALL = 1;
|
|
2861
2911
|
var FETCH_FLAGS_ONE = 2;
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2912
|
+
var Service = class {
|
|
2913
|
+
/** Service instance ID */
|
|
2914
|
+
id = "";
|
|
2915
|
+
/** Whether service is busy (1 = busy) */
|
|
2916
|
+
busy = 0;
|
|
2917
|
+
/** Whether service is destroyed (1 = destroyed) */
|
|
2918
|
+
destroyed = 0;
|
|
2919
|
+
/** Task queue for sequential operations */
|
|
2920
|
+
taskQueue = [];
|
|
2921
|
+
/** Previous dequeue arguments */
|
|
2922
|
+
prevArgs = [];
|
|
2923
|
+
/** Instance event emitter */
|
|
2924
|
+
_emitter = new EventEmitter();
|
|
2925
|
+
constructor() {
|
|
2926
|
+
this.id = generateId("service");
|
|
2927
|
+
}
|
|
2928
|
+
// ============================================================
|
|
2929
|
+
// Instance accessors for type-level data
|
|
2930
|
+
// ============================================================
|
|
2931
|
+
/** Instance event emitter (public accessor) */
|
|
2932
|
+
get emitter() {
|
|
2933
|
+
return this._emitter;
|
|
2934
|
+
}
|
|
2935
|
+
/**
|
|
2936
|
+
* Get internals object for serviceSend compatibility.
|
|
2937
|
+
* References per-type static state from the current class.
|
|
2938
|
+
*/
|
|
2939
|
+
get internals() {
|
|
2940
|
+
const ctor = this.constructor;
|
|
2941
|
+
return {
|
|
2942
|
+
metaList: ctor._metaList,
|
|
2943
|
+
payloadCache: ctor._payloadCache,
|
|
2944
|
+
pendingCacheKeys: ctor._pendingCacheKeys,
|
|
2945
|
+
syncFn: ctor._syncFn,
|
|
2946
|
+
staticEmitter: ctor._staticEmitter
|
|
2947
|
+
};
|
|
2948
|
+
}
|
|
2949
|
+
/**
|
|
2950
|
+
* Get type reference (the constructor) for serviceSend compatibility.
|
|
2951
|
+
* Static methods like get/create are accessible via the constructor.
|
|
2952
|
+
*/
|
|
2953
|
+
get type() {
|
|
2954
|
+
return this.constructor;
|
|
2955
|
+
}
|
|
2956
|
+
// ============================================================
|
|
2957
|
+
// Instance methods
|
|
2958
|
+
// ============================================================
|
|
2959
|
+
/**
|
|
2960
|
+
* Fetch all endpoints, callback when all complete.
|
|
2961
|
+
* Uses cache when available.
|
|
2962
|
+
*/
|
|
2963
|
+
all(attrs, done) {
|
|
2964
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
2965
|
+
return this;
|
|
2966
|
+
}
|
|
2967
|
+
/**
|
|
2968
|
+
* Fetch all endpoints, callback on each completion.
|
|
2969
|
+
*/
|
|
2970
|
+
one(attrs, done) {
|
|
2971
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
2972
|
+
return this;
|
|
2973
|
+
}
|
|
2974
|
+
/**
|
|
2975
|
+
* Fetch all endpoints, skip cache (always request).
|
|
2976
|
+
*/
|
|
2977
|
+
save(attrs, done) {
|
|
2978
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
2979
|
+
return this;
|
|
2980
|
+
}
|
|
2981
|
+
/**
|
|
2982
|
+
* Enqueue a task for sequential execution.
|
|
2983
|
+
*/
|
|
2984
|
+
enqueue(callback) {
|
|
2985
|
+
if (!this.destroyed) {
|
|
2986
|
+
this.taskQueue.push(callback);
|
|
2987
|
+
this.dequeue(...this.prevArgs);
|
|
2988
|
+
}
|
|
2989
|
+
return this;
|
|
2990
|
+
}
|
|
2991
|
+
/**
|
|
2992
|
+
* Dequeue and execute the next task in queue.
|
|
2993
|
+
*/
|
|
2994
|
+
dequeue(...args) {
|
|
2995
|
+
if (!this.busy && !this.destroyed) {
|
|
2996
|
+
this.busy = 1;
|
|
2997
|
+
setTimeout(() => {
|
|
2998
|
+
this.busy = 0;
|
|
2999
|
+
if (!this.destroyed) {
|
|
3000
|
+
const task2 = this.taskQueue.shift();
|
|
3001
|
+
if (task2) {
|
|
3002
|
+
this.prevArgs = args;
|
|
3003
|
+
funcWithTry(task2, args, this, noop);
|
|
2939
3004
|
}
|
|
2940
|
-
return cached;
|
|
2941
3005
|
}
|
|
3006
|
+
}, 0);
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
/**
|
|
3010
|
+
* Destroy the service instance.
|
|
3011
|
+
* After destruction, no new requests can be sent.
|
|
3012
|
+
*/
|
|
3013
|
+
destroy() {
|
|
3014
|
+
this.destroyed = 1;
|
|
3015
|
+
this.taskQueue = [];
|
|
3016
|
+
}
|
|
3017
|
+
// Instance event methods (delegate to instance emitter)
|
|
3018
|
+
on(event, handler) {
|
|
3019
|
+
this._emitter.on(event, handler);
|
|
3020
|
+
return this;
|
|
3021
|
+
}
|
|
3022
|
+
off(event, handler) {
|
|
3023
|
+
this._emitter.off(event, handler);
|
|
3024
|
+
return this;
|
|
3025
|
+
}
|
|
3026
|
+
fire(event, data) {
|
|
3027
|
+
this._emitter.fire(event, data);
|
|
3028
|
+
return this;
|
|
3029
|
+
}
|
|
3030
|
+
// ============================================================
|
|
3031
|
+
// Per-type static state
|
|
3032
|
+
// ============================================================
|
|
3033
|
+
/** Per-type metadata registry */
|
|
3034
|
+
static _metaList = {};
|
|
3035
|
+
/** Per-type payload cache (LFU with frequency eviction) */
|
|
3036
|
+
static _payloadCache = new Cache({
|
|
3037
|
+
maxSize: 20,
|
|
3038
|
+
bufferSize: 5
|
|
3039
|
+
});
|
|
3040
|
+
/** Per-type pending cache keys for deduplication */
|
|
3041
|
+
static _pendingCacheKeys = {};
|
|
3042
|
+
/** Per-type sync function */
|
|
3043
|
+
static _syncFn = noop;
|
|
3044
|
+
/** Per-type static event emitter */
|
|
3045
|
+
static _staticEmitter = new EventEmitter();
|
|
3046
|
+
/** Per-type cache max size */
|
|
3047
|
+
static _cacheMax = 20;
|
|
3048
|
+
/** Per-type cache buffer size */
|
|
3049
|
+
static _cacheBuffer = 5;
|
|
3050
|
+
// ============================================================
|
|
3051
|
+
// Static methods (operate on per-type state via `this`)
|
|
3052
|
+
// ============================================================
|
|
3053
|
+
/**
|
|
3054
|
+
* Register API endpoint metadata.
|
|
3055
|
+
*/
|
|
3056
|
+
static add(attrs) {
|
|
3057
|
+
if (!Array.isArray(attrs)) {
|
|
3058
|
+
attrs = [attrs];
|
|
3059
|
+
}
|
|
3060
|
+
for (const payload of attrs) {
|
|
3061
|
+
if (payload) {
|
|
3062
|
+
const name = payload.name;
|
|
3063
|
+
const cache = payload.cache;
|
|
3064
|
+
payload.cache = cache ? cache | 0 : 0;
|
|
3065
|
+
this._metaList[name] = payload;
|
|
2942
3066
|
}
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
/**
|
|
3070
|
+
* Get metadata for an API endpoint.
|
|
3071
|
+
*/
|
|
3072
|
+
static meta(attrs) {
|
|
3073
|
+
const name = typeof attrs === "string" ? attrs : attrs["name"];
|
|
3074
|
+
return this._metaList[name] || attrs;
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Create a Payload for an API request.
|
|
3078
|
+
*/
|
|
3079
|
+
static create(attrs) {
|
|
3080
|
+
const meta = this.meta(attrs);
|
|
3081
|
+
const cache = attrs["cache"] | 0 || meta.cache || 0;
|
|
3082
|
+
const entity = new Payload();
|
|
3083
|
+
entity.set(meta);
|
|
3084
|
+
entity.cacheInfo = {
|
|
3085
|
+
name: meta.name,
|
|
3086
|
+
after: meta.after,
|
|
3087
|
+
cleans: meta.cleanKeys,
|
|
3088
|
+
key: cache ? defaultCacheKey(meta, attrs) : "",
|
|
3089
|
+
time: 0
|
|
3090
|
+
};
|
|
3091
|
+
if (typeof attrs === "object" && attrs !== null) {
|
|
3092
|
+
entity.set(attrs);
|
|
3093
|
+
}
|
|
3094
|
+
const before = meta.before;
|
|
3095
|
+
if (before) {
|
|
3096
|
+
funcWithTry(before, [entity], entity, noop);
|
|
3097
|
+
}
|
|
3098
|
+
this._staticEmitter.fire("begin", { payload: entity });
|
|
3099
|
+
return entity;
|
|
3100
|
+
}
|
|
3101
|
+
/**
|
|
3102
|
+
* Get or create a Payload for an API request.
|
|
3103
|
+
*/
|
|
3104
|
+
static get(attrs, createNew) {
|
|
3105
|
+
let entity;
|
|
3106
|
+
let needsUpdate = false;
|
|
3107
|
+
if (!createNew) {
|
|
3108
|
+
entity = this.cached(attrs);
|
|
3109
|
+
}
|
|
3110
|
+
if (!entity) {
|
|
3111
|
+
entity = this.create(attrs);
|
|
3112
|
+
needsUpdate = true;
|
|
3113
|
+
}
|
|
3114
|
+
return { entity, needsUpdate };
|
|
3115
|
+
}
|
|
3116
|
+
/**
|
|
3117
|
+
* Get cached Payload if available and not expired.
|
|
3118
|
+
*/
|
|
3119
|
+
static cached(attrs) {
|
|
3120
|
+
const meta = this.meta(attrs);
|
|
3121
|
+
const cache = attrs["cache"] | 0 || meta.cache || 0;
|
|
3122
|
+
let cacheKey = "";
|
|
3123
|
+
if (cache) {
|
|
3124
|
+
cacheKey = defaultCacheKey(meta, attrs);
|
|
3125
|
+
}
|
|
3126
|
+
if (cacheKey) {
|
|
3127
|
+
const info = this._pendingCacheKeys[cacheKey];
|
|
3128
|
+
if (info) {
|
|
3129
|
+
return info.entity;
|
|
2950
3130
|
}
|
|
2951
|
-
const
|
|
2952
|
-
|
|
2953
|
-
if (
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
}
|
|
3131
|
+
const cached = this._payloadCache.get(cacheKey);
|
|
3132
|
+
if (cached && cached.cacheInfo) {
|
|
3133
|
+
if (now() - cached.cacheInfo.time > cache) {
|
|
3134
|
+
this._payloadCache.del(cacheKey);
|
|
3135
|
+
return void 0;
|
|
2957
3136
|
}
|
|
2958
|
-
|
|
2959
|
-
for (const key of keysToDelete) {
|
|
2960
|
-
bagCache.del(key);
|
|
3137
|
+
return cached;
|
|
2961
3138
|
}
|
|
2962
|
-
},
|
|
2963
|
-
on(event, handler) {
|
|
2964
|
-
staticEmitter2.on(event, handler);
|
|
2965
|
-
},
|
|
2966
|
-
off(event, handler) {
|
|
2967
|
-
staticEmitter2.off(event, handler);
|
|
2968
|
-
},
|
|
2969
|
-
fire(event, data) {
|
|
2970
|
-
staticEmitter2.fire(event, data);
|
|
2971
|
-
},
|
|
2972
|
-
extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
2973
|
-
return createServiceType(
|
|
2974
|
-
newSyncFn,
|
|
2975
|
-
newCacheMax || cacheMax,
|
|
2976
|
-
newCacheBuffer || cacheBuffer
|
|
2977
|
-
);
|
|
2978
3139
|
}
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
this
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
}
|
|
2997
|
-
ServiceInstance.prototype = {
|
|
2998
|
-
all(attrs, done) {
|
|
2999
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
3000
|
-
return this;
|
|
3001
|
-
},
|
|
3002
|
-
one(attrs, done) {
|
|
3003
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
3004
|
-
return this;
|
|
3005
|
-
},
|
|
3006
|
-
save(attrs, done) {
|
|
3007
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
3008
|
-
return this;
|
|
3009
|
-
},
|
|
3010
|
-
enqueue(callback) {
|
|
3011
|
-
if (!this["$d"]) {
|
|
3012
|
-
this["$g"].push(callback);
|
|
3013
|
-
this.dequeue(...this["$h"]);
|
|
3014
|
-
}
|
|
3015
|
-
return this;
|
|
3016
|
-
},
|
|
3017
|
-
dequeue(...args) {
|
|
3018
|
-
if (!this["$e"] && !this["$d"]) {
|
|
3019
|
-
this["$e"] = 1;
|
|
3020
|
-
setTimeout(() => {
|
|
3021
|
-
this["$e"] = 0;
|
|
3022
|
-
if (!this["$d"]) {
|
|
3023
|
-
const task2 = this["$g"].shift();
|
|
3024
|
-
if (task2) {
|
|
3025
|
-
this["$h"] = args;
|
|
3026
|
-
funcWithTry(task2, args, this, noop);
|
|
3027
|
-
}
|
|
3028
|
-
}
|
|
3029
|
-
}, 0);
|
|
3140
|
+
return void 0;
|
|
3141
|
+
}
|
|
3142
|
+
/**
|
|
3143
|
+
* Clear cached payloads by endpoint name.
|
|
3144
|
+
*/
|
|
3145
|
+
static clear(names) {
|
|
3146
|
+
const nameList = (typeof names === "string" ? names : names.join(",")).split(",");
|
|
3147
|
+
const nameSet = {};
|
|
3148
|
+
for (const n of nameList) {
|
|
3149
|
+
nameSet[n] = 1;
|
|
3150
|
+
}
|
|
3151
|
+
const keysToDelete = [];
|
|
3152
|
+
this._payloadCache.forEach((payload) => {
|
|
3153
|
+
if (payload?.cacheInfo && nameSet[payload.cacheInfo.name]) {
|
|
3154
|
+
if (payload.cacheInfo.key) {
|
|
3155
|
+
keysToDelete.push(payload.cacheInfo.key);
|
|
3156
|
+
}
|
|
3030
3157
|
}
|
|
3031
|
-
}
|
|
3032
|
-
|
|
3033
|
-
this
|
|
3034
|
-
this["$g"] = [];
|
|
3035
|
-
},
|
|
3036
|
-
on(event, handler) {
|
|
3037
|
-
this._emitter.on(event, handler);
|
|
3038
|
-
return this;
|
|
3039
|
-
},
|
|
3040
|
-
off(event, handler) {
|
|
3041
|
-
this._emitter.off(event, handler);
|
|
3042
|
-
return this;
|
|
3043
|
-
},
|
|
3044
|
-
fire(event, data) {
|
|
3045
|
-
this._emitter.fire(event, data);
|
|
3046
|
-
return this;
|
|
3158
|
+
});
|
|
3159
|
+
for (const key of keysToDelete) {
|
|
3160
|
+
this._payloadCache.del(key);
|
|
3047
3161
|
}
|
|
3048
|
-
}
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
}
|
|
3068
|
-
|
|
3162
|
+
}
|
|
3163
|
+
// Static event methods (operate on per-type emitter)
|
|
3164
|
+
static on(event, handler) {
|
|
3165
|
+
this._staticEmitter.on(event, handler);
|
|
3166
|
+
}
|
|
3167
|
+
static off(event, handler) {
|
|
3168
|
+
this._staticEmitter.off(event, handler);
|
|
3169
|
+
}
|
|
3170
|
+
static fire(event, data) {
|
|
3171
|
+
this._staticEmitter.fire(event, data);
|
|
3172
|
+
}
|
|
3173
|
+
/**
|
|
3174
|
+
* Create a new Service subclass with a custom sync function.
|
|
3175
|
+
* Each subclass gets its own per-type state (metaList, cache, etc.)
|
|
3176
|
+
* to ensure isolation between different Service types.
|
|
3177
|
+
*/
|
|
3178
|
+
static extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
3179
|
+
const ParentService = this;
|
|
3180
|
+
class ChildService extends ParentService {
|
|
3181
|
+
static _metaList = {};
|
|
3182
|
+
static _payloadCache = new Cache({
|
|
3183
|
+
maxSize: newCacheMax || ParentService._cacheMax,
|
|
3184
|
+
bufferSize: newCacheBuffer || ParentService._cacheBuffer
|
|
3185
|
+
});
|
|
3186
|
+
static _pendingCacheKeys = {};
|
|
3187
|
+
static _syncFn = newSyncFn;
|
|
3188
|
+
static _staticEmitter = new EventEmitter();
|
|
3189
|
+
static _cacheMax = newCacheMax || ParentService._cacheMax;
|
|
3190
|
+
static _cacheBuffer = newCacheBuffer || ParentService._cacheBuffer;
|
|
3191
|
+
}
|
|
3192
|
+
return ChildService;
|
|
3193
|
+
}
|
|
3194
|
+
};
|
|
3069
3195
|
function defaultCacheKey(meta, attrs) {
|
|
3070
3196
|
return JSON.stringify(attrs) + SPLITTER + JSON.stringify(meta);
|
|
3071
3197
|
}
|
|
3072
3198
|
function serviceSend(service, attrs, done, flag, save) {
|
|
3073
|
-
if (service["
|
|
3074
|
-
if (service["
|
|
3199
|
+
if (service["destroyed"]) return;
|
|
3200
|
+
if (service["busy"]) {
|
|
3075
3201
|
service.enqueue(
|
|
3076
3202
|
serviceSend.bind(null, service, attrs, done, flag, save)
|
|
3077
3203
|
);
|
|
3078
3204
|
return;
|
|
3079
3205
|
}
|
|
3080
|
-
service["
|
|
3206
|
+
service["busy"] = 1;
|
|
3081
3207
|
let attrList;
|
|
3082
3208
|
if (typeof attrs === "string") {
|
|
3083
3209
|
attrList = [{ name: attrs }];
|
|
3084
|
-
} else if (isArray(attrs)) {
|
|
3210
|
+
} else if (Array.isArray(attrs)) {
|
|
3085
3211
|
attrList = attrs;
|
|
3086
3212
|
} else {
|
|
3087
3213
|
attrList = [attrs];
|
|
3088
3214
|
}
|
|
3089
|
-
const internals = service.
|
|
3215
|
+
const internals = service.internals;
|
|
3090
3216
|
const { syncFn, pendingCacheKeys, staticEmitter: staticEmitter2 } = internals;
|
|
3091
3217
|
let requestCount = 0;
|
|
3092
3218
|
const total = attrList.length;
|
|
3093
3219
|
const doneArr = new Array(total + 1);
|
|
3094
3220
|
const errorArgs = [];
|
|
3095
3221
|
const remoteComplete = (idx, error) => {
|
|
3096
|
-
const
|
|
3097
|
-
let
|
|
3222
|
+
const payload = doneArr[idx + 1];
|
|
3223
|
+
let newPayload = false;
|
|
3098
3224
|
if (error) {
|
|
3099
3225
|
errorArgs[idx] = error;
|
|
3100
|
-
staticEmitter2.fire("fail", {
|
|
3226
|
+
staticEmitter2.fire("fail", { payload, error });
|
|
3101
3227
|
} else {
|
|
3102
|
-
|
|
3103
|
-
staticEmitter2.fire("done", {
|
|
3228
|
+
newPayload = true;
|
|
3229
|
+
staticEmitter2.fire("done", { payload });
|
|
3104
3230
|
}
|
|
3105
|
-
if (!service["
|
|
3231
|
+
if (!service["destroyed"]) {
|
|
3106
3232
|
const finish = requestCount === total;
|
|
3107
3233
|
if (finish) {
|
|
3108
|
-
service["
|
|
3234
|
+
service["busy"] = 0;
|
|
3109
3235
|
if (flag === FETCH_FLAGS_ALL) {
|
|
3110
3236
|
doneArr[0] = errorArgs;
|
|
3111
3237
|
funcWithTry(done, doneArr, service, noop);
|
|
3112
3238
|
}
|
|
3113
3239
|
}
|
|
3114
3240
|
if (flag === FETCH_FLAGS_ONE) {
|
|
3115
|
-
funcWithTry(done, [error || null,
|
|
3241
|
+
funcWithTry(done, [error || null, payload, finish, idx], service, noop);
|
|
3116
3242
|
}
|
|
3117
3243
|
}
|
|
3118
|
-
if (
|
|
3119
|
-
staticEmitter2.fire("end", {
|
|
3244
|
+
if (newPayload) {
|
|
3245
|
+
staticEmitter2.fire("end", { payload, error });
|
|
3120
3246
|
}
|
|
3121
3247
|
};
|
|
3122
3248
|
for (const attr of attrList) {
|
|
3123
3249
|
if (!attr) continue;
|
|
3124
3250
|
const attrObj = typeof attr === "string" ? { name: attr } : attr;
|
|
3125
|
-
const
|
|
3126
|
-
|
|
3127
|
-
|
|
3251
|
+
const payloadInfo = service.type.get(
|
|
3252
|
+
attrObj,
|
|
3253
|
+
save
|
|
3254
|
+
);
|
|
3255
|
+
const payloadEntity = payloadInfo.entity;
|
|
3256
|
+
const cacheKey = payloadEntity.cacheInfo?.key || "";
|
|
3128
3257
|
const complete = remoteComplete.bind(null, requestCount++);
|
|
3129
3258
|
if (cacheKey && pendingCacheKeys[cacheKey]) {
|
|
3130
3259
|
pendingCacheKeys[cacheKey].push(complete);
|
|
3131
|
-
} else if (
|
|
3260
|
+
} else if (payloadInfo.needsUpdate) {
|
|
3132
3261
|
if (cacheKey) {
|
|
3133
3262
|
const cacheList = [complete];
|
|
3134
|
-
cacheList.
|
|
3263
|
+
cacheList.entity = payloadEntity;
|
|
3135
3264
|
pendingCacheKeys[cacheKey] = cacheList;
|
|
3136
3265
|
const cacheComplete = () => {
|
|
3137
3266
|
const list = pendingCacheKeys[cacheKey];
|
|
3138
|
-
const entity = list.
|
|
3267
|
+
const entity = list.entity;
|
|
3139
3268
|
if (entity.cacheInfo) {
|
|
3140
3269
|
entity.cacheInfo.time = now();
|
|
3141
3270
|
}
|
|
3142
|
-
internals.
|
|
3271
|
+
internals.payloadCache.set(cacheKey, entity);
|
|
3143
3272
|
Reflect.deleteProperty(pendingCacheKeys, cacheKey);
|
|
3144
3273
|
for (const cb of list) {
|
|
3145
3274
|
if (typeof cb === "function") {
|
|
@@ -3147,9 +3276,9 @@ function serviceSend(service, attrs, done, flag, save) {
|
|
|
3147
3276
|
}
|
|
3148
3277
|
}
|
|
3149
3278
|
};
|
|
3150
|
-
syncFn(
|
|
3279
|
+
syncFn(payloadEntity, cacheComplete);
|
|
3151
3280
|
} else {
|
|
3152
|
-
syncFn(
|
|
3281
|
+
syncFn(payloadEntity, complete);
|
|
3153
3282
|
}
|
|
3154
3283
|
} else {
|
|
3155
3284
|
complete();
|
|
@@ -3157,9 +3286,117 @@ function serviceSend(service, attrs, done, flag, save) {
|
|
|
3157
3286
|
}
|
|
3158
3287
|
}
|
|
3159
3288
|
|
|
3289
|
+
// src/frame-visualizer.ts
|
|
3290
|
+
var MSG_PING = "LARK_VISUALIZER_PING";
|
|
3291
|
+
var MSG_PONG = "LARK_VISUALIZER_PONG";
|
|
3292
|
+
var MSG_REQUEST_TREE = "LARK_VISUALIZER_REQUEST_TREE";
|
|
3293
|
+
var MSG_TREE = "LARK_VISUALIZER_TREE";
|
|
3294
|
+
var MSG_TREE_DELTA = "LARK_VISUALIZER_TREE_DELTA";
|
|
3295
|
+
function serializeView(view) {
|
|
3296
|
+
return {
|
|
3297
|
+
id: view.id,
|
|
3298
|
+
rendered: !!view.rendered,
|
|
3299
|
+
signature: view.signature,
|
|
3300
|
+
observedStateKeys: view.observedStateKeys ?? null,
|
|
3301
|
+
locationObserved: {
|
|
3302
|
+
flag: view.locationObserved.flag,
|
|
3303
|
+
keys: view.locationObserved.keys,
|
|
3304
|
+
observePath: view.locationObserved.observePath
|
|
3305
|
+
},
|
|
3306
|
+
hasTemplate: !!view.template
|
|
3307
|
+
};
|
|
3308
|
+
}
|
|
3309
|
+
function serializeFrame(frameId) {
|
|
3310
|
+
const frame = Frame.get(frameId);
|
|
3311
|
+
if (!frame) return null;
|
|
3312
|
+
const view = frame.view;
|
|
3313
|
+
const children = [];
|
|
3314
|
+
for (const childId of frame.children()) {
|
|
3315
|
+
const childNode = serializeFrame(childId);
|
|
3316
|
+
if (childNode) {
|
|
3317
|
+
children.push(childNode);
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
return {
|
|
3321
|
+
id: frame.id,
|
|
3322
|
+
parentId: frame.parentId ?? null,
|
|
3323
|
+
viewPath: frame.viewPath ?? null,
|
|
3324
|
+
childrenCount: frame.childrenCount,
|
|
3325
|
+
readyCount: frame.readyCount,
|
|
3326
|
+
childrenCreated: frame.childrenCreated,
|
|
3327
|
+
childrenAlter: frame.childrenAlter,
|
|
3328
|
+
destroyed: frame.destroyed,
|
|
3329
|
+
view: view ? serializeView(view) : null,
|
|
3330
|
+
children
|
|
3331
|
+
};
|
|
3332
|
+
}
|
|
3333
|
+
function serializeFrameTree() {
|
|
3334
|
+
const root = Frame.root();
|
|
3335
|
+
const rootNode = serializeFrame(root.id);
|
|
3336
|
+
let totalFrames = 0;
|
|
3337
|
+
const countFrames = (node) => {
|
|
3338
|
+
if (!node) return;
|
|
3339
|
+
totalFrames++;
|
|
3340
|
+
for (const child of node.children) {
|
|
3341
|
+
countFrames(child);
|
|
3342
|
+
}
|
|
3343
|
+
};
|
|
3344
|
+
countFrames(rootNode);
|
|
3345
|
+
return {
|
|
3346
|
+
root: rootNode,
|
|
3347
|
+
totalFrames,
|
|
3348
|
+
timestamp: Date.now(),
|
|
3349
|
+
rootId: root.id
|
|
3350
|
+
};
|
|
3351
|
+
}
|
|
3352
|
+
var bridgeInstalled = false;
|
|
3353
|
+
var lastTreeJson = "";
|
|
3354
|
+
function installFrameVisualizerBridge() {
|
|
3355
|
+
if (bridgeInstalled) return;
|
|
3356
|
+
if (typeof window === "undefined") return;
|
|
3357
|
+
bridgeInstalled = true;
|
|
3358
|
+
window.addEventListener("message", (event) => {
|
|
3359
|
+
const data = event.data;
|
|
3360
|
+
if (!data || typeof data !== "object") return;
|
|
3361
|
+
const type = data.type;
|
|
3362
|
+
if (type === MSG_PING) {
|
|
3363
|
+
const source = event.source;
|
|
3364
|
+
if (source) {
|
|
3365
|
+
source.postMessage({ type: MSG_PONG }, { targetOrigin: "*" });
|
|
3366
|
+
}
|
|
3367
|
+
return;
|
|
3368
|
+
}
|
|
3369
|
+
if (type === MSG_REQUEST_TREE) {
|
|
3370
|
+
const tree = serializeFrameTree();
|
|
3371
|
+
const source = event.source;
|
|
3372
|
+
if (source) {
|
|
3373
|
+
source.postMessage(
|
|
3374
|
+
{ type: MSG_TREE, data: tree },
|
|
3375
|
+
{ targetOrigin: "*" }
|
|
3376
|
+
);
|
|
3377
|
+
}
|
|
3378
|
+
}
|
|
3379
|
+
});
|
|
3380
|
+
Frame.on("add", () => {
|
|
3381
|
+
pushTreeUpdate();
|
|
3382
|
+
});
|
|
3383
|
+
Frame.on("remove", () => {
|
|
3384
|
+
pushTreeUpdate();
|
|
3385
|
+
});
|
|
3386
|
+
}
|
|
3387
|
+
function pushTreeUpdate() {
|
|
3388
|
+
if (window === window.parent) return;
|
|
3389
|
+
const tree = serializeFrameTree();
|
|
3390
|
+
const treeJson = JSON.stringify(tree);
|
|
3391
|
+
if (treeJson !== lastTreeJson) {
|
|
3392
|
+
lastTreeJson = treeJson;
|
|
3393
|
+
window.parent.postMessage({ type: MSG_TREE_DELTA, data: tree }, "*");
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3160
3397
|
// src/framework.ts
|
|
3161
3398
|
var config = {
|
|
3162
|
-
rootId: "
|
|
3399
|
+
rootId: "root",
|
|
3163
3400
|
hashbang: "#!",
|
|
3164
3401
|
error: (error) => {
|
|
3165
3402
|
throw error;
|
|
@@ -3252,7 +3489,12 @@ function dispatcherUpdate(frame, stateKeys) {
|
|
|
3252
3489
|
const isChanged = stateKeys ? stateIsObserveChanged(view, stateKeys) : viewIsObserveChanged(view);
|
|
3253
3490
|
let renderPromise;
|
|
3254
3491
|
if (isChanged) {
|
|
3255
|
-
const renderResult = funcWithTry(
|
|
3492
|
+
const renderResult = funcWithTry(
|
|
3493
|
+
view.renderMethod ?? view.render,
|
|
3494
|
+
[],
|
|
3495
|
+
view,
|
|
3496
|
+
noop
|
|
3497
|
+
);
|
|
3256
3498
|
if (renderResult && typeof renderResult.then === "function") {
|
|
3257
3499
|
renderPromise = renderResult;
|
|
3258
3500
|
}
|
|
@@ -3274,13 +3516,13 @@ function dispatcherUpdate(frame, stateKeys) {
|
|
|
3274
3516
|
}
|
|
3275
3517
|
function dispatcherNotifyChange(e) {
|
|
3276
3518
|
const rootFrame2 = Frame.root();
|
|
3277
|
-
const view = e
|
|
3519
|
+
const view = e.view;
|
|
3278
3520
|
if (view) {
|
|
3279
3521
|
const viewPath = typeof view === "object" && view !== null ? String(view.to || "") : String(view);
|
|
3280
3522
|
rootFrame2.mountView(viewPath);
|
|
3281
3523
|
} else {
|
|
3282
3524
|
dispatcherUpdateTag++;
|
|
3283
|
-
dispatcherUpdate(rootFrame2, e
|
|
3525
|
+
dispatcherUpdate(rootFrame2, e.keys);
|
|
3284
3526
|
}
|
|
3285
3527
|
}
|
|
3286
3528
|
function dispatchEvent(target, eventType, eventInit) {
|
|
@@ -3291,8 +3533,6 @@ function dispatchEvent(target, eventType, eventInit) {
|
|
|
3291
3533
|
});
|
|
3292
3534
|
target.dispatchEvent(event);
|
|
3293
3535
|
}
|
|
3294
|
-
var Base = class extends EventEmitter {
|
|
3295
|
-
};
|
|
3296
3536
|
function use(names, callback) {
|
|
3297
3537
|
if (!config.require) {
|
|
3298
3538
|
if (callback) callback();
|
|
@@ -3307,7 +3547,7 @@ function use(names, callback) {
|
|
|
3307
3547
|
}
|
|
3308
3548
|
}
|
|
3309
3549
|
var WAIT_OK = 1;
|
|
3310
|
-
var
|
|
3550
|
+
var WAIT_TIMEOUT_OR_NOT_FOUND = 0;
|
|
3311
3551
|
function waitZoneViewsRendered(viewId, timeout) {
|
|
3312
3552
|
if (timeout == null) {
|
|
3313
3553
|
timeout = 30 * 1e3;
|
|
@@ -3318,7 +3558,7 @@ function waitZoneViewsRendered(viewId, timeout) {
|
|
|
3318
3558
|
const check = () => {
|
|
3319
3559
|
const currentTime = now();
|
|
3320
3560
|
if (currentTime > endTime || !checkFrame) {
|
|
3321
|
-
resolve(
|
|
3561
|
+
resolve(WAIT_TIMEOUT_OR_NOT_FOUND);
|
|
3322
3562
|
} else if (checkFrame.childrenCount === checkFrame.readyCount) {
|
|
3323
3563
|
resolve(WAIT_OK);
|
|
3324
3564
|
} else {
|
|
@@ -3355,14 +3595,15 @@ var Framework = {
|
|
|
3355
3595
|
Router._setConfig(config);
|
|
3356
3596
|
EventDelegator.setFrameGetter((id) => Frame.get(id));
|
|
3357
3597
|
Router.on(ROUTER_EVENTS.CHANGED, (data) => {
|
|
3358
|
-
dispatcherNotifyChange(data);
|
|
3598
|
+
if (data) dispatcherNotifyChange(data);
|
|
3359
3599
|
});
|
|
3360
3600
|
State.on(ROUTER_EVENTS.CHANGED, (data) => {
|
|
3361
|
-
dispatcherNotifyChange(data);
|
|
3601
|
+
if (data) dispatcherNotifyChange(data);
|
|
3362
3602
|
});
|
|
3363
3603
|
booted3 = true;
|
|
3364
3604
|
markBooted();
|
|
3365
3605
|
markRouterBooted();
|
|
3606
|
+
installFrameVisualizerBridge();
|
|
3366
3607
|
const rootFrame2 = Frame.root(config.rootId);
|
|
3367
3608
|
Router._bind();
|
|
3368
3609
|
const defaultView = config.defaultView || "";
|
|
@@ -3394,7 +3635,7 @@ var Framework = {
|
|
|
3394
3635
|
/** Wait for zone views to be rendered */
|
|
3395
3636
|
waitZoneViewsRendered,
|
|
3396
3637
|
WAIT_OK,
|
|
3397
|
-
|
|
3638
|
+
WAIT_TIMEOUT_OR_NOT_FOUND,
|
|
3398
3639
|
/**
|
|
3399
3640
|
* Convert array to hash map.
|
|
3400
3641
|
*/
|
|
@@ -3459,7 +3700,7 @@ var Framework = {
|
|
|
3459
3700
|
/**
|
|
3460
3701
|
* Base class with EventEmitter.
|
|
3461
3702
|
*/
|
|
3462
|
-
Base,
|
|
3703
|
+
Base: EventEmitter,
|
|
3463
3704
|
// ============================================================
|
|
3464
3705
|
// Module access
|
|
3465
3706
|
// ============================================================
|
|
@@ -3477,10 +3718,11 @@ if (typeof window !== "undefined") {
|
|
|
3477
3718
|
window.__lark_State = State;
|
|
3478
3719
|
window.__lark_Router = Router;
|
|
3479
3720
|
window.__lark_Frame = Frame;
|
|
3721
|
+
window.__lark_View = View;
|
|
3480
3722
|
}
|
|
3481
3723
|
|
|
3482
3724
|
// src/store.ts
|
|
3483
|
-
var LARK_GLOBAL = "
|
|
3725
|
+
var LARK_GLOBAL = "lark-global";
|
|
3484
3726
|
var Platform = /* @__PURE__ */ ((Platform2) => {
|
|
3485
3727
|
Platform2["Lark"] = "lark";
|
|
3486
3728
|
Platform2["React"] = "react";
|
|
@@ -3523,8 +3765,10 @@ var Queue = class {
|
|
|
3523
3765
|
const flushTickTask = () => {
|
|
3524
3766
|
while (queue.length > 0) {
|
|
3525
3767
|
const task2 = queue.shift();
|
|
3526
|
-
|
|
3527
|
-
|
|
3768
|
+
if (task2) {
|
|
3769
|
+
pendingTasks.delete(task2);
|
|
3770
|
+
runTask(task2);
|
|
3771
|
+
}
|
|
3528
3772
|
}
|
|
3529
3773
|
};
|
|
3530
3774
|
Promise.resolve().then(flushTickTask);
|
|
@@ -3623,9 +3867,11 @@ var setStateConfig = (target, config2) => {
|
|
|
3623
3867
|
if (target && isObject(config2)) StateConfigMap.set(target, config2);
|
|
3624
3868
|
};
|
|
3625
3869
|
var getStateConfig = (target, key) => {
|
|
3626
|
-
if (!StateConfigMap.has(target))
|
|
3870
|
+
if (!StateConfigMap.has(target)) {
|
|
3871
|
+
return void 0;
|
|
3872
|
+
}
|
|
3627
3873
|
const config2 = StateConfigMap.get(target);
|
|
3628
|
-
return key ? config2[key] : config2;
|
|
3874
|
+
return key ? config2?.[key] : config2;
|
|
3629
3875
|
};
|
|
3630
3876
|
var isState = (target) => isObject(target) && StateConfigMap.has(target);
|
|
3631
3877
|
var createLinkKeys = (target, property) => {
|
|
@@ -3795,20 +4041,20 @@ function createState(initialData, config2) {
|
|
|
3795
4041
|
lazySet(state, initialData);
|
|
3796
4042
|
return state;
|
|
3797
4043
|
}
|
|
3798
|
-
var
|
|
4044
|
+
var curLazySetKey = null;
|
|
3799
4045
|
function lazySet(target, data) {
|
|
3800
4046
|
if (isObject(data)) {
|
|
3801
4047
|
Reflect.ownKeys(data).forEach((key) => {
|
|
3802
4048
|
const strKey = key;
|
|
3803
|
-
if (
|
|
3804
|
-
|
|
4049
|
+
if (curLazySetKey) throw new Error("[lark-store] lazy set key conflict");
|
|
4050
|
+
curLazySetKey = strKey;
|
|
3805
4051
|
target[strKey] = data[strKey];
|
|
3806
4052
|
});
|
|
3807
4053
|
}
|
|
3808
4054
|
}
|
|
3809
4055
|
function isLazySet(property) {
|
|
3810
|
-
if (
|
|
3811
|
-
|
|
4056
|
+
if (curLazySetKey === property) {
|
|
4057
|
+
curLazySetKey = "";
|
|
3812
4058
|
return true;
|
|
3813
4059
|
}
|
|
3814
4060
|
return false;
|
|
@@ -4192,14 +4438,11 @@ function defineStore(name, creator, config2) {
|
|
|
4192
4438
|
const useStore = adapter.useStore;
|
|
4193
4439
|
const store = new StoreClass(name, config2);
|
|
4194
4440
|
store[_storeCreate](
|
|
4195
|
-
creator(
|
|
4196
|
-
store[_innerStore](),
|
|
4197
|
-
extendApis
|
|
4198
|
-
)
|
|
4441
|
+
creator(store[_innerStore](), extendApis)
|
|
4199
4442
|
);
|
|
4200
4443
|
Object.defineProperties(useStore, {
|
|
4201
4444
|
$storeName: { value: name, configurable: true },
|
|
4202
|
-
$
|
|
4445
|
+
$destroyFn: { value: () => store[_storeDestroy](), configurable: true }
|
|
4203
4446
|
});
|
|
4204
4447
|
if (!StoreCache.has(name)) {
|
|
4205
4448
|
StoreCache.set(name, { store, creator, config: config2, useStore });
|
|
@@ -4264,7 +4507,7 @@ function observeCell(state, cb, immediate = true) {
|
|
|
4264
4507
|
}
|
|
4265
4508
|
function multi(useStore) {
|
|
4266
4509
|
const storeName = useStore["$storeName"];
|
|
4267
|
-
const flagSym = `
|
|
4510
|
+
const flagSym = `lark-comp-${storeName}`;
|
|
4268
4511
|
const map = /* @__PURE__ */ new Map();
|
|
4269
4512
|
let rootViewPath;
|
|
4270
4513
|
const getFlag = (viewContext) => {
|
|
@@ -4273,7 +4516,7 @@ function multi(useStore) {
|
|
|
4273
4516
|
const viewId = owner?.["id"] || "";
|
|
4274
4517
|
let flag;
|
|
4275
4518
|
if (viewPath === rootViewPath) {
|
|
4276
|
-
flag = `${flagSym}
|
|
4519
|
+
flag = `${flagSym}-${viewId}`;
|
|
4277
4520
|
} else {
|
|
4278
4521
|
flag = owner?.["viewInitParams"]?.[flagSym];
|
|
4279
4522
|
}
|
|
@@ -4290,19 +4533,18 @@ function multi(useStore) {
|
|
|
4290
4533
|
};
|
|
4291
4534
|
const useFn = ((view) => {
|
|
4292
4535
|
if (!view)
|
|
4293
|
-
throw new Error(
|
|
4536
|
+
throw new Error(
|
|
4537
|
+
"[@lark.js/mvc error] multi: cannot find the view instance"
|
|
4538
|
+
);
|
|
4294
4539
|
const viewCtx = view;
|
|
4295
4540
|
const flag = viewCtx[flagSym];
|
|
4296
4541
|
if (map.has(flag)) return map.get(flag);
|
|
4297
|
-
const newFn = cloneStore(
|
|
4298
|
-
flag,
|
|
4299
|
-
useStore
|
|
4300
|
-
);
|
|
4542
|
+
const newFn = cloneStore(flag, useStore);
|
|
4301
4543
|
map.set(flag, newFn);
|
|
4302
4544
|
return useFn(view);
|
|
4303
4545
|
});
|
|
4304
4546
|
const mixinObj = {
|
|
4305
|
-
|
|
4547
|
+
make() {
|
|
4306
4548
|
if (!rootViewPath) {
|
|
4307
4549
|
const owner = this["owner"];
|
|
4308
4550
|
rootViewPath = owner?.["path"] || "";
|
|
@@ -4352,17 +4594,17 @@ function restoreComments(source, comments) {
|
|
|
4352
4594
|
}
|
|
4353
4595
|
function processViewEvents(source) {
|
|
4354
4596
|
return source.replace(
|
|
4355
|
-
|
|
4597
|
+
/@(\w+)="([^"]+)"/g,
|
|
4356
4598
|
(fullAttr, eventName, attrValue) => {
|
|
4357
4599
|
const eventMatch = attrValue.match(/^(\w+)\((.*)\)$/s);
|
|
4358
4600
|
if (!eventMatch) return fullAttr;
|
|
4359
4601
|
const handlerName = eventMatch[1];
|
|
4360
4602
|
const paramsStr = eventMatch[2].trim();
|
|
4361
4603
|
if (!paramsStr) {
|
|
4362
|
-
return
|
|
4604
|
+
return `@${eventName}="${VIEW_ID_PLACEHOLDER}${SPLITTER2}${handlerName}()"`;
|
|
4363
4605
|
}
|
|
4364
4606
|
const urlParams = jsObjectToUrlParams(paramsStr);
|
|
4365
|
-
return
|
|
4607
|
+
return `@${eventName}="${VIEW_ID_PLACEHOLDER}${SPLITTER2}${handlerName}(${urlParams})"`;
|
|
4366
4608
|
}
|
|
4367
4609
|
);
|
|
4368
4610
|
}
|
|
@@ -4435,7 +4677,7 @@ function convertArtSyntax(source, debug) {
|
|
|
4435
4677
|
}
|
|
4436
4678
|
if (blockStack.length > 0) {
|
|
4437
4679
|
const unclosed = blockStack.map((b) => `"${b.ctrl}" at line ${b.line}`).join(", ");
|
|
4438
|
-
throw new Error(`[@lark/mvc error] unclosed block(s): ${unclosed}`);
|
|
4680
|
+
throw new Error(`[@lark.js/mvc error] unclosed block(s): ${unclosed}`);
|
|
4439
4681
|
}
|
|
4440
4682
|
return result.join("");
|
|
4441
4683
|
}
|
|
@@ -4529,12 +4771,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4529
4771
|
}
|
|
4530
4772
|
return `${debugPrefix}<%}else{%>`;
|
|
4531
4773
|
}
|
|
4532
|
-
case "
|
|
4533
|
-
blockStack.push({ ctrl: "
|
|
4774
|
+
case "forOf": {
|
|
4775
|
+
blockStack.push({ ctrl: "forOf", line: lineNo });
|
|
4534
4776
|
const object = tokens[0];
|
|
4535
4777
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4536
4778
|
throw new Error(
|
|
4537
|
-
`[@lark/mvc error] bad
|
|
4779
|
+
`[@lark.js/mvc error] bad forOf syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{forOf list as item [index]}}`
|
|
4538
4780
|
);
|
|
4539
4781
|
}
|
|
4540
4782
|
const restTokens = tokens.slice(2);
|
|
@@ -4556,12 +4798,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4556
4798
|
}
|
|
4557
4799
|
return `${debugPrefix}<%for(let ${index}=0${refExpr},${refObjCount}=${refObj}.length${lastCount};${index}<${refObjCount};${index}++){${firstAndLast}${valueDecl}%>`;
|
|
4558
4800
|
}
|
|
4559
|
-
case "
|
|
4560
|
-
blockStack.push({ ctrl: "
|
|
4801
|
+
case "forIn": {
|
|
4802
|
+
blockStack.push({ ctrl: "forIn", line: lineNo });
|
|
4561
4803
|
const object = tokens[0];
|
|
4562
4804
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4563
4805
|
throw new Error(
|
|
4564
|
-
`[@lark/mvc error] bad
|
|
4806
|
+
`[@lark.js/mvc error] bad forIn syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{for-in obj as val [key]}}`
|
|
4565
4807
|
);
|
|
4566
4808
|
}
|
|
4567
4809
|
const restTokens2 = tokens.slice(2);
|
|
@@ -4581,19 +4823,19 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4581
4823
|
case "set":
|
|
4582
4824
|
return `${debugPrefix}<%let ${tokens.join(" ")};%>`;
|
|
4583
4825
|
case "/if":
|
|
4584
|
-
case "/
|
|
4585
|
-
case "/
|
|
4826
|
+
case "/forOf":
|
|
4827
|
+
case "/forIn":
|
|
4586
4828
|
case "/for": {
|
|
4587
4829
|
const expectedCtrl = keyword.substring(1);
|
|
4588
4830
|
const last = blockStack.pop();
|
|
4589
4831
|
if (!last) {
|
|
4590
4832
|
throw new Error(
|
|
4591
|
-
`[@lark/mvc error
|
|
4833
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: no matching open block`
|
|
4592
4834
|
);
|
|
4593
4835
|
}
|
|
4594
4836
|
if (last.ctrl !== expectedCtrl) {
|
|
4595
4837
|
throw new Error(
|
|
4596
|
-
`[@lark/mvc error
|
|
4838
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: expected {{/${last.ctrl}}} to close block opened at line ${last.line}`
|
|
4597
4839
|
);
|
|
4598
4840
|
}
|
|
4599
4841
|
return `${debugPrefix}<%}%>`;
|
|
@@ -4657,7 +4899,7 @@ function parseAsExpr(expr) {
|
|
|
4657
4899
|
function compileToFunction(source, debug, file) {
|
|
4658
4900
|
const matcher = /<%([@=!:])?([\s\S]*?)%>|$/g;
|
|
4659
4901
|
let index = 0;
|
|
4660
|
-
let funcSource = `$
|
|
4902
|
+
let funcSource = `$out+='`;
|
|
4661
4903
|
let hasAtRule = false;
|
|
4662
4904
|
const escapeSlashRegExp = /\\|'/g;
|
|
4663
4905
|
const escapeBreakReturnRegExp = /\r|\n/g;
|
|
@@ -4683,17 +4925,17 @@ function compileToFunction(source, debug, file) {
|
|
|
4683
4925
|
}
|
|
4684
4926
|
if (operate === "@") {
|
|
4685
4927
|
hasAtRule = true;
|
|
4686
|
-
funcSource += `'+($
|
|
4928
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$refFn($refAlt,${content}))+'`;
|
|
4687
4929
|
} else if (operate === "=" || operate === ":") {
|
|
4688
|
-
funcSource += `'+($
|
|
4930
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$encHtml(${content}))+'`;
|
|
4689
4931
|
} else if (operate === "!") {
|
|
4690
|
-
if (!content.startsWith("$
|
|
4691
|
-
content = `$
|
|
4932
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
4933
|
+
content = `$strSafe(${content})`;
|
|
4692
4934
|
}
|
|
4693
|
-
funcSource += `'+($
|
|
4935
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',${content})+'`;
|
|
4694
4936
|
} else if (content) {
|
|
4695
4937
|
if (line > -1) {
|
|
4696
|
-
funcSource += `';$
|
|
4938
|
+
funcSource += `';$dbgLine=${line};$dbgArt='${art}';`;
|
|
4697
4939
|
content = "";
|
|
4698
4940
|
} else {
|
|
4699
4941
|
funcSource += `';`;
|
|
@@ -4702,19 +4944,19 @@ function compileToFunction(source, debug, file) {
|
|
|
4702
4944
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4703
4945
|
}
|
|
4704
4946
|
if (expr) {
|
|
4705
|
-
funcSource += `$
|
|
4947
|
+
funcSource += `$dbgExpr='<%${expr}%>';`;
|
|
4706
4948
|
}
|
|
4707
|
-
funcSource += content + `;$
|
|
4949
|
+
funcSource += content + `;$out+='`;
|
|
4708
4950
|
}
|
|
4709
4951
|
} else {
|
|
4710
4952
|
if (operate === "@") {
|
|
4711
4953
|
hasAtRule = true;
|
|
4712
|
-
funcSource += `'+$
|
|
4954
|
+
funcSource += `'+$refFn($refAlt,${content})+'`;
|
|
4713
4955
|
} else if (operate === "=" || operate === ":") {
|
|
4714
|
-
funcSource += `'+$
|
|
4956
|
+
funcSource += `'+$encHtml(${content})+'`;
|
|
4715
4957
|
} else if (operate === "!") {
|
|
4716
|
-
if (!content.startsWith("$
|
|
4717
|
-
content = `$
|
|
4958
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
4959
|
+
content = `$strSafe(${content})`;
|
|
4718
4960
|
}
|
|
4719
4961
|
funcSource += `'+${content}+'`;
|
|
4720
4962
|
} else if (content) {
|
|
@@ -4722,28 +4964,28 @@ function compileToFunction(source, debug, file) {
|
|
|
4722
4964
|
if (funcSource.endsWith(`+'';`)) {
|
|
4723
4965
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4724
4966
|
}
|
|
4725
|
-
funcSource += `${content};$
|
|
4967
|
+
funcSource += `${content};$out+='`;
|
|
4726
4968
|
}
|
|
4727
4969
|
}
|
|
4728
4970
|
return match;
|
|
4729
4971
|
});
|
|
4730
4972
|
funcSource += `';`;
|
|
4731
|
-
funcSource = funcSource.replace(/\$
|
|
4732
|
-
funcSource = funcSource.replace(/\$
|
|
4973
|
+
funcSource = funcSource.replace(/\$out\+='';/g, "");
|
|
4974
|
+
funcSource = funcSource.replace(/\$out\+=''\+/g, "$out+=");
|
|
4733
4975
|
if (debug) {
|
|
4734
4976
|
const filePart = file ? `\\r\\n\\tat file:${file}` : "";
|
|
4735
|
-
funcSource = `let $
|
|
4977
|
+
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;}`;
|
|
4736
4978
|
}
|
|
4737
4979
|
const viewIdRegExp = new RegExp(String.fromCharCode(31), "g");
|
|
4738
4980
|
funcSource = funcSource.replace(viewIdRegExp, `'+$viewId+'`);
|
|
4739
|
-
const atRule = hasAtRule ? `if(!$
|
|
4740
|
-
const encode = `if(!$
|
|
4741
|
-
const encodeURIMore = `if(!$
|
|
4742
|
-
const encodeQuote = `if(!$
|
|
4743
|
-
const refFallback = "if(
|
|
4981
|
+
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;}}` : "";
|
|
4982
|
+
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)}`;
|
|
4983
|
+
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)}`;
|
|
4984
|
+
const encodeQuote = `if(!$encQuote){let $qReg=/['"\\\\]/g;$encQuote=v=>$strSafe(v).replace($qReg,'\\\\$&')}`;
|
|
4985
|
+
const refFallback = "if(!$refAlt)$refAlt=$data;";
|
|
4744
4986
|
const fns = `${refFallback}${encode}${encodeURIMore}${encodeQuote}${atRule};`;
|
|
4745
|
-
const fullSource = `${fns}let $
|
|
4746
|
-
return `(
|
|
4987
|
+
const fullSource = `${fns}let $splitter='\\x1e',$tmp,$out=''{{VARS}};${funcSource}return $out`;
|
|
4988
|
+
return `($data,$viewId,$refAlt,$encHtml,$strSafe,$encUri,$refFn,$encQuote)=>{${fullSource}}`;
|
|
4747
4989
|
}
|
|
4748
4990
|
function compileTemplate(source, options = {}) {
|
|
4749
4991
|
const { debug = false, globalVars = [], file } = options;
|
|
@@ -4752,17 +4994,17 @@ function compileTemplate(source, options = {}) {
|
|
|
4752
4994
|
const viewEventProcessed = processViewEvents(converted);
|
|
4753
4995
|
const finalSource = restoreComments(viewEventProcessed, comments);
|
|
4754
4996
|
const funcBody = compileToFunction(finalSource, debug, file);
|
|
4755
|
-
const varDeclarations = globalVars.map((key) => `,${key}
|
|
4997
|
+
const varDeclarations = globalVars.map((key) => `,${key}=$data.${key}`).join("");
|
|
4756
4998
|
const funcWithVars = funcBody.replace("{{VARS}}", () => varDeclarations);
|
|
4757
4999
|
return `export default function(data, selfId, refData) {
|
|
4758
|
-
let
|
|
5000
|
+
let $data = data || {},
|
|
4759
5001
|
$viewId = selfId || '';
|
|
4760
|
-
return (${funcWithVars})(
|
|
4761
|
-
/* $
|
|
4762
|
-
/* $
|
|
4763
|
-
/* $
|
|
4764
|
-
/* $
|
|
4765
|
-
/* $
|
|
5002
|
+
return (${funcWithVars})($data, $viewId, refData,
|
|
5003
|
+
/* $encHtml */ v => String(v == null ? '' : v).replace(/[&<>"'\`]/g, m => '&' + ({'&':'amp','<':'lt','>':'gt','"':'#34',"'":'#39','\`':'#96'})[m] + ';'),
|
|
5004
|
+
/* $strSafe */ v => String(v == null ? '' : v),
|
|
5005
|
+
/* $encUri */ null,
|
|
5006
|
+
/* $refFn */ null,
|
|
5007
|
+
/* $encQuote */ null
|
|
4766
5008
|
);
|
|
4767
5009
|
}`;
|
|
4768
5010
|
}
|
|
@@ -4871,7 +5113,7 @@ function fallbackExtractVariables(source) {
|
|
|
4871
5113
|
while ((m = outputRegExp.exec(source)) !== null) {
|
|
4872
5114
|
vars.add(m[1]);
|
|
4873
5115
|
}
|
|
4874
|
-
const eachRegExp = /\{\{
|
|
5116
|
+
const eachRegExp = /\{\{forOf\s+([a-zA-Z_$][\w$]*)\s+as/g;
|
|
4875
5117
|
while ((m = eachRegExp.exec(source)) !== null) {
|
|
4876
5118
|
vars.add(m[1]);
|
|
4877
5119
|
}
|
|
@@ -4917,77 +5159,88 @@ var BUILTIN_GLOBALS = {
|
|
|
4917
5159
|
//
|
|
4918
5160
|
// These variables appear in the generated template function signature
|
|
4919
5161
|
// or body. They must be excluded from extractGlobalVars() so that
|
|
4920
|
-
// they are not mistaken for user data variables and destructured from
|
|
5162
|
+
// they are not mistaken for user data variables and destructured from $data.
|
|
4921
5163
|
// SPLITTER character constant (same as \x1e), used as namespace separator
|
|
4922
5164
|
// for refData keys, event attribute encoding, and internal data structures.
|
|
4923
|
-
// Declared as: let $
|
|
4924
|
-
$
|
|
4925
|
-
//
|
|
4926
|
-
// User variables are destructured from
|
|
4927
|
-
// let {name, age} =
|
|
5165
|
+
// Declared as: let $splitter='\x1e'
|
|
5166
|
+
$splitter: 1,
|
|
5167
|
+
// Data — the data object passed from Updater to the template function.
|
|
5168
|
+
// User variables are destructured from $data at the top of the function:
|
|
5169
|
+
// let {name, age} = $data;
|
|
4928
5170
|
// This is the first parameter of the generated arrow function.
|
|
4929
|
-
|
|
5171
|
+
$data: 1,
|
|
4930
5172
|
// Null-safe toString: v => '' + (v == null ? '' : v)
|
|
4931
5173
|
// Converts null/undefined to empty string, otherwise calls toString().
|
|
4932
5174
|
// Wraps every {{!raw}} output to prevent "null" / "undefined" rendering.
|
|
4933
|
-
$
|
|
4934
|
-
// HTML entity encoder: v => $
|
|
5175
|
+
$strSafe: 1,
|
|
5176
|
+
// HTML entity encoder: v => $strSafe(v).replace(/[&<>"'`]/g, entityMap)
|
|
4935
5177
|
// Encodes &, <, >, ", ', ` to HTML entities (& < etc.)
|
|
4936
5178
|
// Applied to all {{=escaped}} and {{:binding}} outputs.
|
|
4937
|
-
$
|
|
4938
|
-
// HTML entity map — internal object used by $
|
|
5179
|
+
$encHtml: 1,
|
|
5180
|
+
// HTML entity map — internal object used by $encHtml:
|
|
4939
5181
|
// {'&':'amp','<':'gt','>':'gt','"':'#34','\'':'#39','`':'#96'}
|
|
4940
|
-
// Not a standalone function; referenced inside $
|
|
4941
|
-
$
|
|
4942
|
-
// HTML entity RegExp — internal regexp used by $
|
|
5182
|
+
// Not a standalone function; referenced inside $encHtml's closure.
|
|
5183
|
+
$entMap: 1,
|
|
5184
|
+
// HTML entity RegExp — internal regexp used by $encHtml:
|
|
4943
5185
|
// /[&<>"'`]/g
|
|
4944
|
-
$
|
|
4945
|
-
// HTML entity replacer function — internal helper used by $
|
|
4946
|
-
// m => '&' + $
|
|
4947
|
-
// Maps
|
|
4948
|
-
$
|
|
5186
|
+
$entReg: 1,
|
|
5187
|
+
// HTML entity replacer function — internal helper used by $encHtml:
|
|
5188
|
+
// m => '&' + $entMap[m] + ';'
|
|
5189
|
+
// Maps matched character to its entity string.
|
|
5190
|
+
$entFn: 1,
|
|
4949
5191
|
// Output buffer — the string accumulator for rendered HTML.
|
|
4950
|
-
// All template output is appended via $
|
|
4951
|
-
// Declared as: let $
|
|
4952
|
-
$
|
|
5192
|
+
// All template output is appended via $out += '...'.
|
|
5193
|
+
// Declared as: let $out = ''
|
|
5194
|
+
$out: 1,
|
|
4953
5195
|
// Reference lookup: (refData, value) => key
|
|
4954
5196
|
// Finds or allocates a SPLITTER-prefixed key in refData for a given
|
|
4955
5197
|
// object reference. Used by {{@ref}} operator for passing object
|
|
4956
|
-
// references to child views via lark
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
// URI encoder: v => encodeURIComponent($n(v)).replace(/[!')(*]/g, extraMap)
|
|
5198
|
+
// references to child views via v-lark attributes.
|
|
5199
|
+
$refFn: 1,
|
|
5200
|
+
// URI encoder: v => encodeURIComponent($strSafe(v)).replace(/[!')(*]/g, extraMap)
|
|
4960
5201
|
// Extends encodeURIComponent with encoding of ! ' ( ) *.
|
|
4961
|
-
// Applied to values in
|
|
4962
|
-
$
|
|
4963
|
-
//
|
|
5202
|
+
// Applied to values in @event URL parameters and {{!uri}} contexts.
|
|
5203
|
+
$encUri: 1,
|
|
5204
|
+
// URI encode map — internal object used by $encUri:
|
|
5205
|
+
// {'!':'%21','\'':'%27','(':'%28',')':'%29','*':'%2A'}
|
|
5206
|
+
$uriMap: 1,
|
|
5207
|
+
// URI encode replacer — internal helper used by $encUri:
|
|
5208
|
+
// m => $uriMap[m]
|
|
5209
|
+
$uriFn: 1,
|
|
5210
|
+
// URI encode regexp — internal regexp used by $encUri:
|
|
5211
|
+
// /[!')(*]/g
|
|
5212
|
+
$uriReg: 1,
|
|
5213
|
+
// Quote encoder: v => $strSafe(v).replace(/['"\\]/g, '\\$&')
|
|
4964
5214
|
// Escapes quotes and backslashes for safe embedding in HTML attribute
|
|
4965
5215
|
// values (e.g. data-json='...').
|
|
4966
|
-
$
|
|
5216
|
+
$encQuote: 1,
|
|
5217
|
+
// Quote encode regexp — internal regexp used by $encQuote:
|
|
5218
|
+
// /['"\\]/g
|
|
5219
|
+
$qReg: 1,
|
|
4967
5220
|
// View ID — the unique identifier of the owning View instance.
|
|
4968
|
-
// Injected into
|
|
5221
|
+
// Injected into @event attribute values at render time so that
|
|
4969
5222
|
// EventDelegator can dispatch events to the correct View handler.
|
|
4970
5223
|
// The \x1f placeholder in compiled output is replaced with '+$viewId+'.
|
|
4971
5224
|
$viewId: 1,
|
|
4972
5225
|
// Debug: current expression text — stores the template expression being
|
|
4973
5226
|
// evaluated, for error reporting. Only present in debug mode.
|
|
4974
|
-
// e.g. $
|
|
4975
|
-
$
|
|
5227
|
+
// e.g. $dbgExpr='<%=user.name%>'
|
|
5228
|
+
$dbgExpr: 1,
|
|
4976
5229
|
// Debug: original art syntax — stores the {{}} template syntax before
|
|
4977
5230
|
// conversion, for error reporting. Only present in debug mode.
|
|
4978
|
-
// e.g. $
|
|
4979
|
-
$
|
|
5231
|
+
// e.g. $dbgArt='{{=user.name}}'
|
|
5232
|
+
$dbgArt: 1,
|
|
4980
5233
|
// Debug: source line number — tracks the current line in the template
|
|
4981
5234
|
// source, for error reporting. Only present in debug mode.
|
|
4982
|
-
$
|
|
4983
|
-
//
|
|
4984
|
-
// Defaults to
|
|
4985
|
-
// Ensures $
|
|
4986
|
-
|
|
5235
|
+
$dbgLine: 1,
|
|
5236
|
+
// RefData alias — fallback reference lookup table.
|
|
5237
|
+
// Defaults to $data when no explicit $refAlt is provided.
|
|
5238
|
+
// Ensures $refFn() does not crash when @ operator is used without refData.
|
|
5239
|
+
$refAlt: 1,
|
|
4987
5240
|
// Temporary variable — used by the compiler for intermediate
|
|
4988
5241
|
// expression results in generated code (e.g. loop variables,
|
|
4989
|
-
// conditional branches). Declared as: let $
|
|
4990
|
-
$
|
|
5242
|
+
// conditional branches). Declared as: let $tmp
|
|
5243
|
+
$tmp: 1,
|
|
4991
5244
|
// JS literals
|
|
4992
5245
|
undefined: 1,
|
|
4993
5246
|
null: 1,
|
|
@@ -5053,7 +5306,6 @@ var BUILTIN_GLOBALS = {
|
|
|
5053
5306
|
var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
5054
5307
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5055
5308
|
0 && (module.exports = {
|
|
5056
|
-
Bag,
|
|
5057
5309
|
CALL_BREAK_TIME,
|
|
5058
5310
|
Cache,
|
|
5059
5311
|
EVENT_METHOD_REGEXP,
|
|
@@ -5062,16 +5314,14 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5062
5314
|
Frame,
|
|
5063
5315
|
Framework,
|
|
5064
5316
|
LARK_VIEW,
|
|
5317
|
+
Payload,
|
|
5065
5318
|
Platform,
|
|
5066
5319
|
ROUTER_EVENTS,
|
|
5067
5320
|
Router,
|
|
5068
5321
|
SPLITTER,
|
|
5069
5322
|
Service,
|
|
5070
5323
|
State,
|
|
5071
|
-
TAG_ATTR_KEY,
|
|
5072
|
-
TAG_KEY,
|
|
5073
5324
|
TAG_NAME_REGEXP,
|
|
5074
|
-
TAG_VIEW_KEY,
|
|
5075
5325
|
Updater,
|
|
5076
5326
|
VIEW_EVENT_METHOD_REGEXP,
|
|
5077
5327
|
View,
|
|
@@ -5102,7 +5352,7 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5102
5352
|
getStore,
|
|
5103
5353
|
getUseStore,
|
|
5104
5354
|
has,
|
|
5105
|
-
|
|
5355
|
+
installFrameVisualizerBridge,
|
|
5106
5356
|
isPlainObject,
|
|
5107
5357
|
isPrimitive,
|
|
5108
5358
|
isPrimitiveOrFunc,
|
|
@@ -5122,6 +5372,7 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5122
5372
|
parseUri,
|
|
5123
5373
|
registerViewClass,
|
|
5124
5374
|
safeguard,
|
|
5375
|
+
serializeFrameTree,
|
|
5125
5376
|
setData,
|
|
5126
5377
|
shallowSet,
|
|
5127
5378
|
storeMark,
|