@lark.js/mvc 0.0.3 → 0.0.5
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 +872 -727
- package/dist/{chunk-Y72BUONO.js → chunk-IIIY575B.js} +108 -97
- package/dist/index.cjs +1718 -1115
- package/dist/index.d.cts +1857 -731
- package/dist/index.d.ts +1857 -731
- package/dist/index.js +1708 -1111
- package/dist/runtime.cjs +70 -0
- package/dist/runtime.d.cts +29 -0
- package/dist/runtime.d.ts +29 -0
- package/dist/runtime.js +41 -0
- package/dist/vite.cjs +108 -97
- package/dist/vite.d.cts +3 -3
- package/dist/vite.d.ts +3 -3
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +108 -97
- package/dist/webpack.js +1 -1
- package/package.json +21 -8
- package/src/client.d.ts +80 -0
package/dist/index.cjs
CHANGED
|
@@ -20,17 +20,19 @@ 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,
|
|
25
|
+
CrossSite: () => cross_site_default,
|
|
26
26
|
EVENT_METHOD_REGEXP: () => EVENT_METHOD_REGEXP,
|
|
27
27
|
EventDelegator: () => EventDelegator,
|
|
28
28
|
EventEmitter: () => EventEmitter,
|
|
29
29
|
Frame: () => Frame,
|
|
30
|
+
FrameVisualBridge: () => FrameVisualBridge,
|
|
30
31
|
Framework: () => Framework,
|
|
31
32
|
LARK_VIEW: () => LARK_VIEW,
|
|
33
|
+
Payload: () => Payload,
|
|
32
34
|
Platform: () => Platform,
|
|
33
|
-
ROUTER_EVENTS: () =>
|
|
35
|
+
ROUTER_EVENTS: () => RouterEvents,
|
|
34
36
|
Router: () => Router,
|
|
35
37
|
SPLITTER: () => SPLITTER,
|
|
36
38
|
Service: () => Service,
|
|
@@ -44,13 +46,14 @@ __export(index_exports, {
|
|
|
44
46
|
applyVdomOps: () => applyVdomOps,
|
|
45
47
|
assign: () => assign,
|
|
46
48
|
cell: () => cell,
|
|
47
|
-
classExtend: () => classExtend,
|
|
48
49
|
cloneData: () => cloneData,
|
|
49
50
|
cloneStore: () => cloneStore,
|
|
50
51
|
compileTemplate: () => compileTemplate,
|
|
52
|
+
computed: () => computed,
|
|
51
53
|
createState: () => createState,
|
|
52
54
|
createVdomRef: () => createVdomRef,
|
|
53
55
|
defineStore: () => defineStore,
|
|
56
|
+
defineView: () => defineView,
|
|
54
57
|
delStore: () => delStore,
|
|
55
58
|
encodeHTML: () => encodeHTML,
|
|
56
59
|
encodeQ: () => encodeQ,
|
|
@@ -58,6 +61,7 @@ __export(index_exports, {
|
|
|
58
61
|
encodeURIExtra: () => encodeURIExtra,
|
|
59
62
|
ensureElementId: () => ensureElementId,
|
|
60
63
|
extractGlobalVars: () => extractGlobalVars,
|
|
64
|
+
frameworkConfig: () => config,
|
|
61
65
|
funcWithTry: () => funcWithTry,
|
|
62
66
|
generateId: () => generateId,
|
|
63
67
|
getAttribute: () => getAttribute,
|
|
@@ -65,9 +69,9 @@ __export(index_exports, {
|
|
|
65
69
|
getPlatform: () => getPlatform,
|
|
66
70
|
getStore: () => getStore,
|
|
67
71
|
getUseStore: () => getUseStore,
|
|
68
|
-
|
|
72
|
+
hasOwnProperty: () => hasOwnProperty,
|
|
69
73
|
installFrameVisualizerBridge: () => installFrameVisualizerBridge,
|
|
70
|
-
|
|
74
|
+
invalidateViewClass: () => invalidateViewClass,
|
|
71
75
|
isPlainObject: () => isPlainObject,
|
|
72
76
|
isPrimitive: () => isPrimitive,
|
|
73
77
|
isPrimitiveOrFunc: () => isPrimitiveOrFunc,
|
|
@@ -86,6 +90,7 @@ __export(index_exports, {
|
|
|
86
90
|
observeCell: () => observeCell,
|
|
87
91
|
parseUri: () => parseUri,
|
|
88
92
|
registerViewClass: () => registerViewClass,
|
|
93
|
+
resetProjectsMap: () => resetProjectsMap,
|
|
89
94
|
safeguard: () => safeguard,
|
|
90
95
|
serializeFrameTree: () => serializeFrameTree,
|
|
91
96
|
setData: () => setData,
|
|
@@ -97,6 +102,7 @@ __export(index_exports, {
|
|
|
97
102
|
toUri: () => toUri,
|
|
98
103
|
translateData: () => translateData,
|
|
99
104
|
unmark: () => unmark,
|
|
105
|
+
use: () => use,
|
|
100
106
|
vdomGetCompareKey: () => vdomGetCompareKey,
|
|
101
107
|
vdomGetNode: () => vdomGetNode,
|
|
102
108
|
vdomSetAttributes: () => vdomSetAttributes,
|
|
@@ -110,12 +116,12 @@ module.exports = __toCommonJS(index_exports);
|
|
|
110
116
|
// src/constants.ts
|
|
111
117
|
var globalCounter = 0;
|
|
112
118
|
var SPLITTER = "";
|
|
113
|
-
var
|
|
119
|
+
var RouterEvents = {
|
|
114
120
|
CHANGE: "change",
|
|
115
121
|
CHANGED: "changed",
|
|
116
122
|
PAGE_UNLOAD: "page_unload"
|
|
117
123
|
};
|
|
118
|
-
var
|
|
124
|
+
var LarkInnerKeys = {
|
|
119
125
|
/** Attribute name: ldk (static key for skipping VDOM diff) */
|
|
120
126
|
DIFF_KEY: "ldk",
|
|
121
127
|
/** Attribute name: lak (static attribute key) */
|
|
@@ -147,7 +153,6 @@ function isPlainObject(value) {
|
|
|
147
153
|
if (proto === null) return true;
|
|
148
154
|
return proto === Object.prototype || proto === null;
|
|
149
155
|
}
|
|
150
|
-
var isArray = Array.isArray;
|
|
151
156
|
function isPrimitiveOrFunc(value) {
|
|
152
157
|
return !value || typeof value !== "object" && typeof value !== "function";
|
|
153
158
|
}
|
|
@@ -163,13 +168,13 @@ function syncCounter(val) {
|
|
|
163
168
|
}
|
|
164
169
|
function noop() {
|
|
165
170
|
}
|
|
166
|
-
function
|
|
171
|
+
function hasOwnProperty(owner, prop) {
|
|
167
172
|
return owner != null && Object.prototype.hasOwnProperty.call(owner, prop);
|
|
168
173
|
}
|
|
169
174
|
function keys(obj) {
|
|
170
175
|
const result = [];
|
|
171
176
|
for (const p in obj) {
|
|
172
|
-
if (
|
|
177
|
+
if (hasOwnProperty(obj, p)) {
|
|
173
178
|
result.push(p);
|
|
174
179
|
}
|
|
175
180
|
}
|
|
@@ -179,7 +184,7 @@ function assign(target, ...sources) {
|
|
|
179
184
|
for (const source of sources) {
|
|
180
185
|
if (source) {
|
|
181
186
|
for (const p in source) {
|
|
182
|
-
if (
|
|
187
|
+
if (hasOwnProperty(source, p)) {
|
|
183
188
|
target[p] = source[p];
|
|
184
189
|
}
|
|
185
190
|
}
|
|
@@ -188,25 +193,26 @@ function assign(target, ...sources) {
|
|
|
188
193
|
return target;
|
|
189
194
|
}
|
|
190
195
|
function funcWithTry(fns, args, context, configError) {
|
|
191
|
-
const fnArray = isArray(fns) ? fns : [fns];
|
|
196
|
+
const fnArray = Array.isArray(fns) ? fns : [fns];
|
|
192
197
|
let ret;
|
|
193
198
|
for (const fn of fnArray) {
|
|
194
199
|
try {
|
|
195
|
-
ret =
|
|
200
|
+
ret = fn.apply(context, args);
|
|
196
201
|
} catch (e) {
|
|
197
|
-
configError(e);
|
|
202
|
+
configError?.(e);
|
|
198
203
|
}
|
|
199
204
|
}
|
|
200
205
|
return ret;
|
|
201
206
|
}
|
|
207
|
+
var EMPTY_STRING_SET = /* @__PURE__ */ new Set();
|
|
202
208
|
function setData(newData, oldData, changedKeys2, excludes) {
|
|
203
209
|
let changed = false;
|
|
204
210
|
for (const p in newData) {
|
|
205
|
-
if (
|
|
211
|
+
if (hasOwnProperty(newData, p)) {
|
|
206
212
|
const now2 = newData[p];
|
|
207
213
|
const old = oldData[p];
|
|
208
214
|
if ((!isPrimitiveOrFunc(now2) || old !== now2) && !excludes.has(p)) {
|
|
209
|
-
changedKeys2
|
|
215
|
+
changedKeys2.add(p);
|
|
210
216
|
changed = true;
|
|
211
217
|
}
|
|
212
218
|
oldData[p] = now2;
|
|
@@ -214,17 +220,25 @@ function setData(newData, oldData, changedKeys2, excludes) {
|
|
|
214
220
|
}
|
|
215
221
|
return changed;
|
|
216
222
|
}
|
|
223
|
+
function isRefToken(s) {
|
|
224
|
+
if (s.length < 2 || s[0] !== SPLITTER) return false;
|
|
225
|
+
for (let i = 1; i < s.length; i++) {
|
|
226
|
+
const c = s.charCodeAt(i);
|
|
227
|
+
if (c < 48 || c > 57) return false;
|
|
228
|
+
}
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
217
231
|
function translateData(data, value) {
|
|
218
232
|
if (isPrimitive(value)) {
|
|
219
233
|
const prop = String(value);
|
|
220
|
-
if (prop
|
|
234
|
+
if (isRefToken(prop) && hasOwnProperty(data, prop)) {
|
|
221
235
|
return data[prop];
|
|
222
236
|
}
|
|
223
237
|
return value;
|
|
224
238
|
}
|
|
225
|
-
if (isPlainObject(value) || isArray(value)) {
|
|
239
|
+
if (isPlainObject(value) || Array.isArray(value)) {
|
|
226
240
|
for (const p in value) {
|
|
227
|
-
if (
|
|
241
|
+
if (hasOwnProperty(value, p)) {
|
|
228
242
|
const val = value[p];
|
|
229
243
|
const newVal = translateData(data, val);
|
|
230
244
|
value[p] = newVal;
|
|
@@ -261,38 +275,33 @@ function nodeInside(a, b) {
|
|
|
261
275
|
return false;
|
|
262
276
|
}
|
|
263
277
|
}
|
|
264
|
-
var paramsTemp = {};
|
|
265
|
-
function paramsReplacer(_match, name, value) {
|
|
266
|
-
try {
|
|
267
|
-
paramsTemp[name] = decodeURIComponent(value || "");
|
|
268
|
-
} catch {
|
|
269
|
-
paramsTemp[name] = value || "";
|
|
270
|
-
}
|
|
271
|
-
return "";
|
|
272
|
-
}
|
|
273
278
|
function parseUri(uri) {
|
|
274
|
-
|
|
279
|
+
const params = {};
|
|
275
280
|
const path = uri.replace(URL_QUERY_HASH_REGEXP, "");
|
|
276
281
|
const pathname = path;
|
|
277
282
|
const actualPath = uri === pathname && IS_URL_PARAMS.test(pathname) ? "" : pathname;
|
|
278
|
-
uri.replace(actualPath, "").replace(URL_PARAM_REGEXP,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
uri.replace(actualPath, "").replace(URL_PARAM_REGEXP, (_match, name, value) => {
|
|
284
|
+
try {
|
|
285
|
+
params[name] = decodeURIComponent(value || "");
|
|
286
|
+
} catch {
|
|
287
|
+
params[name] = value || "";
|
|
288
|
+
}
|
|
289
|
+
return "";
|
|
290
|
+
});
|
|
291
|
+
return { path: actualPath, params };
|
|
283
292
|
}
|
|
284
293
|
var IS_URL_PARAMS = {
|
|
285
294
|
test(s) {
|
|
286
295
|
return /(?!^)=|&/.test(s);
|
|
287
296
|
}
|
|
288
297
|
};
|
|
289
|
-
function toUri(path, params,
|
|
298
|
+
function toUri(path, params, keepEmpty) {
|
|
290
299
|
const pairs = [];
|
|
291
300
|
let hasParams = false;
|
|
292
301
|
for (const p in params) {
|
|
293
|
-
if (
|
|
302
|
+
if (hasOwnProperty(params, p)) {
|
|
294
303
|
const v = String(params[p] ?? "");
|
|
295
|
-
if (!
|
|
304
|
+
if (!keepEmpty || v || keepEmpty.has(p)) {
|
|
296
305
|
pairs.push(`${p}=${encodeURIComponent(v)}`);
|
|
297
306
|
hasParams = true;
|
|
298
307
|
}
|
|
@@ -315,14 +324,6 @@ function toMap(list, key) {
|
|
|
315
324
|
function now() {
|
|
316
325
|
return Date.now ? Date.now() : (/* @__PURE__ */ new Date()).getTime();
|
|
317
326
|
}
|
|
318
|
-
function classExtend(make, base, props, statics) {
|
|
319
|
-
const baseProto = base["prototype"] ?? {};
|
|
320
|
-
const cProto = Object.create(baseProto);
|
|
321
|
-
assign(cProto, props);
|
|
322
|
-
Object.assign(make, statics);
|
|
323
|
-
cProto.constructor = make;
|
|
324
|
-
make["prototype"] = cProto;
|
|
325
|
-
}
|
|
326
327
|
|
|
327
328
|
// src/apply-style.ts
|
|
328
329
|
var injectedStyleIds = /* @__PURE__ */ new Set();
|
|
@@ -362,32 +363,40 @@ function applyStyle(styleIdOrPairs, css) {
|
|
|
362
363
|
}
|
|
363
364
|
|
|
364
365
|
// src/mark.ts
|
|
365
|
-
var
|
|
366
|
-
|
|
366
|
+
var hostStore = /* @__PURE__ */ new WeakMap();
|
|
367
|
+
function getOrCreate(host) {
|
|
368
|
+
let record = hostStore.get(host);
|
|
369
|
+
if (!record) {
|
|
370
|
+
record = { signs: /* @__PURE__ */ new Map(), deleted: false };
|
|
371
|
+
hostStore.set(host, record);
|
|
372
|
+
}
|
|
373
|
+
return record;
|
|
374
|
+
}
|
|
367
375
|
function mark(host, key) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const markHost = hostRecord[MARK_OBJECT_KEY] || (hostRecord[MARK_OBJECT_KEY] = {});
|
|
372
|
-
if (!Object.prototype.hasOwnProperty.call(markHost, key)) {
|
|
373
|
-
markHost[key] = 0;
|
|
374
|
-
}
|
|
375
|
-
sign = ++markHost[key];
|
|
376
|
+
const record = getOrCreate(host);
|
|
377
|
+
if (record.deleted) {
|
|
378
|
+
return () => false;
|
|
376
379
|
}
|
|
380
|
+
const sign = (record.signs.get(key) ?? 0) + 1;
|
|
381
|
+
record.signs.set(key, sign);
|
|
377
382
|
return () => {
|
|
378
|
-
const
|
|
379
|
-
return !!
|
|
383
|
+
const current = hostStore.get(host);
|
|
384
|
+
return !!current && !current.deleted && current.signs.get(key) === sign;
|
|
380
385
|
};
|
|
381
386
|
}
|
|
382
387
|
function unmark(host) {
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
388
|
+
const record = hostStore.get(host);
|
|
389
|
+
if (record) {
|
|
390
|
+
record.deleted = true;
|
|
391
|
+
record.signs.clear();
|
|
392
|
+
} else {
|
|
393
|
+
hostStore.set(host, { signs: /* @__PURE__ */ new Map(), deleted: true });
|
|
394
|
+
}
|
|
386
395
|
}
|
|
387
396
|
|
|
388
397
|
// src/safeguard.ts
|
|
389
398
|
var proxiesPool = /* @__PURE__ */ new Map();
|
|
390
|
-
var SAFEGUARD_SENTINEL = "
|
|
399
|
+
var SAFEGUARD_SENTINEL = "_safe_";
|
|
391
400
|
function safeguard(data, getter, setter, isRoot) {
|
|
392
401
|
if (typeof window.__lark_Debug === "undefined" || !window.__lark_Debug) {
|
|
393
402
|
return data;
|
|
@@ -428,7 +437,7 @@ function safeguard(data, getter, setter, isRoot) {
|
|
|
428
437
|
if (!prefix && getter) {
|
|
429
438
|
getter(property);
|
|
430
439
|
}
|
|
431
|
-
if (!isRoot &&
|
|
440
|
+
if (!isRoot && hasOwnProperty(target, property) && (Array.isArray(out) || isPlainObject(out))) {
|
|
432
441
|
return build(prefix + property + ".", out);
|
|
433
442
|
}
|
|
434
443
|
return out;
|
|
@@ -517,15 +526,17 @@ var Cache = class {
|
|
|
517
526
|
this.lookup.set(prefixedKey, entry);
|
|
518
527
|
}
|
|
519
528
|
/**
|
|
520
|
-
* Delete a cached entry.
|
|
529
|
+
* Delete a cached entry. Removes it immediately from both the lookup map
|
|
530
|
+
* and the entries array so the GC can reclaim the value without waiting
|
|
531
|
+
* for the next eviction sweep.
|
|
521
532
|
*/
|
|
522
533
|
del(key) {
|
|
523
534
|
const prefixedKey = this.prefixKey(key);
|
|
524
535
|
const entry = this.lookup.get(prefixedKey);
|
|
525
536
|
if (!entry) return;
|
|
526
|
-
entry.frequency = -1;
|
|
527
|
-
entry.value = void 0;
|
|
528
537
|
this.lookup.delete(prefixedKey);
|
|
538
|
+
const idx = this.entries.indexOf(entry);
|
|
539
|
+
if (idx !== -1) this.entries.splice(idx, 1);
|
|
529
540
|
if (this.onRemove) {
|
|
530
541
|
this.onRemove(key);
|
|
531
542
|
}
|
|
@@ -550,20 +561,46 @@ var Cache = class {
|
|
|
550
561
|
this.entries = [];
|
|
551
562
|
this.lookup.clear();
|
|
552
563
|
}
|
|
553
|
-
/**
|
|
564
|
+
/**
|
|
565
|
+
* Evict the `bufferSize` worst entries from the cache.
|
|
566
|
+
*
|
|
567
|
+
* Uses single-pass partial selection (O(n·k)) instead of sorting the entire
|
|
568
|
+
* `entries` array (O(n log n)). For the typical `bufferSize = 5` this is
|
|
569
|
+
* effectively a linear scan with at most 5 in-bucket comparisons per
|
|
570
|
+
* iteration — and it avoids mutating the rest of `entries`.
|
|
571
|
+
*/
|
|
554
572
|
evictEntries() {
|
|
555
|
-
this.entries
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
this.lookup.delete(this.prefixKey(
|
|
561
|
-
if (this.onRemove)
|
|
562
|
-
|
|
563
|
-
|
|
573
|
+
const entries = this.entries;
|
|
574
|
+
const k = this.bufferSize;
|
|
575
|
+
if (k <= 0 || entries.length === 0) return;
|
|
576
|
+
if (entries.length <= k) {
|
|
577
|
+
for (const e of entries) {
|
|
578
|
+
this.lookup.delete(this.prefixKey(e.originalKey));
|
|
579
|
+
if (this.onRemove) this.onRemove(e.originalKey);
|
|
580
|
+
}
|
|
581
|
+
this.entries = [];
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const cmp = this.comparator;
|
|
585
|
+
const worst = [];
|
|
586
|
+
for (const entry of entries) {
|
|
587
|
+
if (worst.length < k) {
|
|
588
|
+
let i = worst.length;
|
|
589
|
+
while (i > 0 && cmp(entry, worst[i - 1]) > 0) i--;
|
|
590
|
+
worst.splice(i, 0, entry);
|
|
591
|
+
} else if (cmp(entry, worst[k - 1]) > 0) {
|
|
592
|
+
worst.pop();
|
|
593
|
+
let i = worst.length;
|
|
594
|
+
while (i > 0 && cmp(entry, worst[i - 1]) > 0) i--;
|
|
595
|
+
worst.splice(i, 0, entry);
|
|
564
596
|
}
|
|
565
597
|
}
|
|
566
|
-
|
|
598
|
+
const evictSet = new Set(worst);
|
|
599
|
+
for (const e of worst) {
|
|
600
|
+
this.lookup.delete(this.prefixKey(e.originalKey));
|
|
601
|
+
if (this.onRemove) this.onRemove(e.originalKey);
|
|
602
|
+
}
|
|
603
|
+
this.entries = entries.filter((e) => !evictSet.has(e));
|
|
567
604
|
}
|
|
568
605
|
};
|
|
569
606
|
|
|
@@ -571,6 +608,10 @@ var Cache = class {
|
|
|
571
608
|
var EventEmitter = class {
|
|
572
609
|
/** Event listeners: prefixed key -> listener array */
|
|
573
610
|
listeners = /* @__PURE__ */ new Map();
|
|
611
|
+
/** Number of `fire()` calls currently on the stack (re-entrancy depth). */
|
|
612
|
+
firingDepth = 0;
|
|
613
|
+
/** Keys whose listener list needs compaction after firing settles. */
|
|
614
|
+
pendingCompaction;
|
|
574
615
|
/**
|
|
575
616
|
* Bind event listener.
|
|
576
617
|
*/
|
|
@@ -593,24 +634,37 @@ var EventEmitter = class {
|
|
|
593
634
|
const key = SPLITTER + event;
|
|
594
635
|
if (handler) {
|
|
595
636
|
const list = this.listeners.get(key);
|
|
596
|
-
if (list)
|
|
637
|
+
if (!list) return this;
|
|
638
|
+
if (this.firingDepth > 0) {
|
|
597
639
|
for (const listener of list) {
|
|
598
640
|
if (listener.handler === handler) {
|
|
599
641
|
listener.handler = noop;
|
|
642
|
+
(this.pendingCompaction ??= /* @__PURE__ */ new Set()).add(key);
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
} else {
|
|
647
|
+
for (let i = 0; i < list.length; i++) {
|
|
648
|
+
if (list[i].handler === handler) {
|
|
649
|
+
list.splice(i, 1);
|
|
600
650
|
break;
|
|
601
651
|
}
|
|
602
652
|
}
|
|
653
|
+
if (list.length === 0) this.listeners.delete(key);
|
|
603
654
|
}
|
|
604
655
|
} else {
|
|
605
656
|
this.listeners.delete(key);
|
|
606
|
-
Reflect.deleteProperty(
|
|
657
|
+
Reflect.deleteProperty(
|
|
658
|
+
this,
|
|
659
|
+
`on${event[0].toUpperCase() + event.slice(1)}`
|
|
660
|
+
);
|
|
607
661
|
}
|
|
608
662
|
return this;
|
|
609
663
|
}
|
|
610
664
|
/**
|
|
611
|
-
* Fire event, execute all bound handlers.
|
|
612
|
-
*
|
|
613
|
-
*
|
|
665
|
+
* Fire event, execute all bound handlers. Safe for re-entrant `off()` calls
|
|
666
|
+
* during dispatch: removed handlers are replaced with noop and compacted
|
|
667
|
+
* after the outermost fire returns.
|
|
614
668
|
*
|
|
615
669
|
* @param event - Event name
|
|
616
670
|
* @param data - Event data (type property added automatically)
|
|
@@ -624,38 +678,41 @@ var EventEmitter = class {
|
|
|
624
678
|
data = {};
|
|
625
679
|
}
|
|
626
680
|
data["type"] = event;
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
681
|
+
this.firingDepth++;
|
|
682
|
+
try {
|
|
683
|
+
if (list) {
|
|
684
|
+
const len = list.length;
|
|
685
|
+
for (let i = 0; i < len; i++) {
|
|
686
|
+
const idx = lastToFirst ? len - 1 - i : i;
|
|
687
|
+
const listener = list[idx];
|
|
688
|
+
if (!listener) continue;
|
|
689
|
+
if (listener.handler === noop) continue;
|
|
634
690
|
listener.executing = 1;
|
|
635
|
-
funcWithTry(
|
|
636
|
-
[listener.handler],
|
|
637
|
-
[data],
|
|
638
|
-
this,
|
|
639
|
-
noop
|
|
640
|
-
);
|
|
691
|
+
funcWithTry([listener.handler], [data], this, noop);
|
|
641
692
|
listener.executing = "";
|
|
642
|
-
} else if (!listener.executing) {
|
|
643
|
-
list.splice(idx, 1);
|
|
644
693
|
}
|
|
645
694
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
695
|
+
const onMethodName = `on${event[0].toUpperCase() + event.slice(1)}`;
|
|
696
|
+
const onMethod = this[onMethodName];
|
|
697
|
+
if (typeof onMethod === "function") {
|
|
698
|
+
funcWithTry([onMethod], [data], this, noop);
|
|
699
|
+
}
|
|
700
|
+
if (remove) {
|
|
701
|
+
this.off(event);
|
|
702
|
+
}
|
|
703
|
+
} finally {
|
|
704
|
+
this.firingDepth--;
|
|
705
|
+
if (this.firingDepth === 0 && this.pendingCompaction) {
|
|
706
|
+
for (const k of this.pendingCompaction) {
|
|
707
|
+
const l = this.listeners.get(k);
|
|
708
|
+
if (!l) continue;
|
|
709
|
+
for (let i = l.length - 1; i >= 0; i--) {
|
|
710
|
+
if (l[i].handler === noop) l.splice(i, 1);
|
|
711
|
+
}
|
|
712
|
+
if (l.length === 0) this.listeners.delete(k);
|
|
713
|
+
}
|
|
714
|
+
this.pendingCompaction = void 0;
|
|
715
|
+
}
|
|
659
716
|
}
|
|
660
717
|
return this;
|
|
661
718
|
}
|
|
@@ -664,8 +721,8 @@ var EventEmitter = class {
|
|
|
664
721
|
// src/state.ts
|
|
665
722
|
var appData = {};
|
|
666
723
|
var keyRefCounts = {};
|
|
667
|
-
var changedKeys =
|
|
668
|
-
var stashedChangedKeys =
|
|
724
|
+
var changedKeys = /* @__PURE__ */ new Set();
|
|
725
|
+
var stashedChangedKeys = EMPTY_STRING_SET;
|
|
669
726
|
var dataIsChanged = false;
|
|
670
727
|
var dataWhereSet = {};
|
|
671
728
|
var emitter = new EventEmitter();
|
|
@@ -676,7 +733,7 @@ function markBooted() {
|
|
|
676
733
|
function setupKeysRef(keys2) {
|
|
677
734
|
const keyList = keys2.split(",");
|
|
678
735
|
for (const key of keyList) {
|
|
679
|
-
if (
|
|
736
|
+
if (hasOwnProperty(keyRefCounts, key)) {
|
|
680
737
|
keyRefCounts[key]++;
|
|
681
738
|
} else {
|
|
682
739
|
keyRefCounts[key] = 1;
|
|
@@ -686,7 +743,7 @@ function setupKeysRef(keys2) {
|
|
|
686
743
|
}
|
|
687
744
|
function teardownKeysRef(keyList) {
|
|
688
745
|
for (const key of keyList) {
|
|
689
|
-
if (
|
|
746
|
+
if (hasOwnProperty(keyRefCounts, key)) {
|
|
690
747
|
const count = --keyRefCounts[key];
|
|
691
748
|
if (count <= 0) {
|
|
692
749
|
Reflect.deleteProperty(keyRefCounts, key);
|
|
@@ -698,35 +755,14 @@ function teardownKeysRef(keyList) {
|
|
|
698
755
|
}
|
|
699
756
|
}
|
|
700
757
|
}
|
|
701
|
-
var
|
|
702
|
-
var notifyList = [];
|
|
703
|
-
var notifyTimer;
|
|
758
|
+
var warnedKeys = /* @__PURE__ */ new Set();
|
|
704
759
|
function clearNotify(key) {
|
|
705
|
-
|
|
706
|
-
if (notifyList[i]?.key === key) {
|
|
707
|
-
notifyList.splice(i, 1);
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
function doNotify() {
|
|
712
|
-
const locker = {};
|
|
713
|
-
for (const n of notifyList) {
|
|
714
|
-
if (!locker[n.key]) {
|
|
715
|
-
console.warn(n.message);
|
|
716
|
-
locker[n.key] = 1;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
notifyList.length = 0;
|
|
720
|
-
notifyStarted = 0;
|
|
760
|
+
warnedKeys.delete(key);
|
|
721
761
|
}
|
|
722
762
|
function delayNotify(key, message) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
if (!notifyStarted) {
|
|
727
|
-
notifyStarted = 1;
|
|
728
|
-
notifyTimer = setTimeout(doNotify, 500);
|
|
729
|
-
}
|
|
763
|
+
if (warnedKeys.has(key)) return;
|
|
764
|
+
warnedKeys.add(key);
|
|
765
|
+
console.warn(message);
|
|
730
766
|
}
|
|
731
767
|
var State = {
|
|
732
768
|
/**
|
|
@@ -738,7 +774,7 @@ var State = {
|
|
|
738
774
|
return safeguard(
|
|
739
775
|
result,
|
|
740
776
|
(dataKey) => {
|
|
741
|
-
if (booted &&
|
|
777
|
+
if (booted && hasOwnProperty(dataWhereSet, dataKey) && dataWhereSet[dataKey] !== window.location.pathname) {
|
|
742
778
|
console.warn(
|
|
743
779
|
`beware! You get state:"{State}.${dataKey}" where it set by page:${dataWhereSet[dataKey]}`
|
|
744
780
|
);
|
|
@@ -759,7 +795,7 @@ var State = {
|
|
|
759
795
|
* Set data to state.
|
|
760
796
|
*/
|
|
761
797
|
set(data, excludes) {
|
|
762
|
-
dataIsChanged = setData(data, appData, changedKeys, excludes ||
|
|
798
|
+
dataIsChanged = setData(data, appData, changedKeys, excludes || EMPTY_STRING_SET) || dataIsChanged;
|
|
763
799
|
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && booted) {
|
|
764
800
|
for (const p in data) {
|
|
765
801
|
dataWhereSet[p] = window.location.pathname;
|
|
@@ -776,26 +812,19 @@ var State = {
|
|
|
776
812
|
}
|
|
777
813
|
if (dataIsChanged) {
|
|
778
814
|
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
779
|
-
for (const p
|
|
780
|
-
|
|
781
|
-
clearNotify(p);
|
|
782
|
-
}
|
|
815
|
+
for (const p of changedKeys) {
|
|
816
|
+
clearNotify(p);
|
|
783
817
|
}
|
|
784
818
|
}
|
|
785
819
|
dataIsChanged = false;
|
|
786
|
-
const keys2 =
|
|
787
|
-
for (const k in changedKeys) {
|
|
788
|
-
if (has(changedKeys, k)) {
|
|
789
|
-
keys2[k] = 1;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
820
|
+
const keys2 = changedKeys;
|
|
792
821
|
stashedChangedKeys = keys2;
|
|
793
|
-
changedKeys =
|
|
794
|
-
emitter.fire(
|
|
822
|
+
changedKeys = /* @__PURE__ */ new Set();
|
|
823
|
+
emitter.fire(RouterEvents.CHANGED, { keys: keys2 });
|
|
795
824
|
}
|
|
796
825
|
},
|
|
797
826
|
/**
|
|
798
|
-
* Get
|
|
827
|
+
* Get the set of keys changed in the most recent digest.
|
|
799
828
|
*/
|
|
800
829
|
diff() {
|
|
801
830
|
return stashedChangedKeys;
|
|
@@ -835,6 +864,7 @@ var State = {
|
|
|
835
864
|
emitter.fire(event, data, remove);
|
|
836
865
|
return State;
|
|
837
866
|
}
|
|
867
|
+
// onChanged: noop,
|
|
838
868
|
};
|
|
839
869
|
|
|
840
870
|
// src/router.ts
|
|
@@ -852,6 +882,7 @@ var cachedDefaultPath;
|
|
|
852
882
|
var cachedRewrite;
|
|
853
883
|
var defaultTitle;
|
|
854
884
|
var frameworkConfig;
|
|
885
|
+
var beforeEachGuards = [];
|
|
855
886
|
function createEmptyLocation() {
|
|
856
887
|
return {
|
|
857
888
|
href: "",
|
|
@@ -1006,7 +1037,7 @@ var Router = {
|
|
|
1006
1037
|
document.title = defaultTitle || document.title;
|
|
1007
1038
|
}
|
|
1008
1039
|
emitter2.fire(
|
|
1009
|
-
|
|
1040
|
+
RouterEvents.CHANGED,
|
|
1010
1041
|
lastChanged
|
|
1011
1042
|
);
|
|
1012
1043
|
}
|
|
@@ -1039,16 +1070,16 @@ var Router = {
|
|
|
1039
1070
|
}
|
|
1040
1071
|
const lPath = lastLocation["path"] || "";
|
|
1041
1072
|
const lParams = lastLocation["params"];
|
|
1042
|
-
const lQuery =
|
|
1073
|
+
const lQuery = /* @__PURE__ */ new Set();
|
|
1043
1074
|
for (const k in lastLocation.query["params"]) {
|
|
1044
|
-
if (
|
|
1045
|
-
lQuery
|
|
1075
|
+
if (hasOwnProperty(lastLocation.query["params"], k)) {
|
|
1076
|
+
lQuery.add(k);
|
|
1046
1077
|
}
|
|
1047
1078
|
}
|
|
1048
1079
|
if (tPath) {
|
|
1049
|
-
if (!
|
|
1050
|
-
for (const qKey
|
|
1051
|
-
if (
|
|
1080
|
+
if (!hasOwnProperty(window, "history")) {
|
|
1081
|
+
for (const qKey of lQuery) {
|
|
1082
|
+
if (!hasOwnProperty(tParams, qKey)) {
|
|
1052
1083
|
tParams[qKey] = "";
|
|
1053
1084
|
}
|
|
1054
1085
|
}
|
|
@@ -1057,14 +1088,17 @@ var Router = {
|
|
|
1057
1088
|
tPath = lPath;
|
|
1058
1089
|
tParams = assign({}, lParams, tParams);
|
|
1059
1090
|
}
|
|
1060
|
-
updateUrl(
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
)
|
|
1091
|
+
updateUrl(tPath, tParams, lastLocation, replace, silentFlag, lQuery);
|
|
1092
|
+
},
|
|
1093
|
+
/**
|
|
1094
|
+
* Register an async-friendly navigation guard. See `RouterInterface.beforeEach`.
|
|
1095
|
+
*/
|
|
1096
|
+
beforeEach(guard) {
|
|
1097
|
+
beforeEachGuards.push(guard);
|
|
1098
|
+
return () => {
|
|
1099
|
+
const idx = beforeEachGuards.indexOf(guard);
|
|
1100
|
+
if (idx !== -1) beforeEachGuards.splice(idx, 1);
|
|
1101
|
+
};
|
|
1068
1102
|
},
|
|
1069
1103
|
/**
|
|
1070
1104
|
* Join multiple path segments into a single path.
|
|
@@ -1128,21 +1162,48 @@ var Router = {
|
|
|
1128
1162
|
}
|
|
1129
1163
|
};
|
|
1130
1164
|
Router.fire(
|
|
1131
|
-
|
|
1165
|
+
RouterEvents.CHANGE,
|
|
1132
1166
|
changeEvent
|
|
1133
1167
|
);
|
|
1134
|
-
if (
|
|
1168
|
+
if (suspend || changeEvent.p) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
if (beforeEachGuards.length === 0) {
|
|
1135
1172
|
changeEvent.resolve();
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
const from = lastLocation;
|
|
1176
|
+
const to = loc;
|
|
1177
|
+
const guards = beforeEachGuards.slice();
|
|
1178
|
+
let chain = Promise.resolve(true);
|
|
1179
|
+
for (const guard of guards) {
|
|
1180
|
+
chain = chain.then((prev) => {
|
|
1181
|
+
if (prev === false) return false;
|
|
1182
|
+
return guard(to, from);
|
|
1183
|
+
});
|
|
1136
1184
|
}
|
|
1185
|
+
chain.then(
|
|
1186
|
+
(result) => {
|
|
1187
|
+
if (changeEvent.p) return;
|
|
1188
|
+
if (result === false) {
|
|
1189
|
+
changeEvent.reject();
|
|
1190
|
+
} else {
|
|
1191
|
+
changeEvent.resolve();
|
|
1192
|
+
}
|
|
1193
|
+
},
|
|
1194
|
+
() => {
|
|
1195
|
+
if (!changeEvent.p) changeEvent.reject();
|
|
1196
|
+
}
|
|
1197
|
+
);
|
|
1137
1198
|
}
|
|
1138
1199
|
};
|
|
1139
1200
|
Router.notify = watchChange;
|
|
1140
1201
|
window.addEventListener("hashchange", watchChange);
|
|
1141
1202
|
window.addEventListener("popstate", watchChange);
|
|
1142
1203
|
window.addEventListener("beforeunload", (domEvent) => {
|
|
1143
|
-
const
|
|
1144
|
-
Router.fire(
|
|
1145
|
-
const msg =
|
|
1204
|
+
const data = {};
|
|
1205
|
+
Router.fire(RouterEvents.PAGE_UNLOAD, data);
|
|
1206
|
+
const msg = data["msg"];
|
|
1146
1207
|
if (msg) {
|
|
1147
1208
|
domEvent.returnValue = msg;
|
|
1148
1209
|
}
|
|
@@ -1174,26 +1235,30 @@ var frameGetter;
|
|
|
1174
1235
|
function parseEventInfo(eventInfo) {
|
|
1175
1236
|
const cached = eventInfoCache.get(eventInfo);
|
|
1176
1237
|
if (cached) {
|
|
1177
|
-
return assign({}, cached, {
|
|
1238
|
+
return assign({}, cached, { value: eventInfo });
|
|
1178
1239
|
}
|
|
1179
1240
|
const match = eventInfo.match(EVENT_METHOD_REGEXP) || [];
|
|
1180
1241
|
const result = {
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1242
|
+
id: match[1] || "",
|
|
1243
|
+
name: match[2] || "",
|
|
1244
|
+
params: match[3] || ""
|
|
1184
1245
|
};
|
|
1185
1246
|
eventInfoCache.set(eventInfo, result);
|
|
1186
|
-
return assign({}, result, {
|
|
1247
|
+
return assign({}, result, { value: eventInfo });
|
|
1187
1248
|
}
|
|
1188
1249
|
function findFrameInfo(current, eventType) {
|
|
1189
1250
|
const eventInfos = [];
|
|
1190
|
-
let begin = current;
|
|
1191
1251
|
const info = current.getAttribute(`@${eventType}`);
|
|
1252
|
+
const hasSelectorEvents = !!selectorEvents[eventType];
|
|
1253
|
+
if (!info && !hasSelectorEvents) {
|
|
1254
|
+
return eventInfos;
|
|
1255
|
+
}
|
|
1256
|
+
let begin = current;
|
|
1192
1257
|
let match;
|
|
1193
1258
|
if (info) {
|
|
1194
1259
|
match = parseEventInfo(info);
|
|
1195
1260
|
}
|
|
1196
|
-
if (match && !match.
|
|
1261
|
+
if (match && !match.id || hasSelectorEvents) {
|
|
1197
1262
|
let selectorFrameId = "#";
|
|
1198
1263
|
let backtrace = 0;
|
|
1199
1264
|
while (begin && begin !== document.body) {
|
|
@@ -1219,10 +1284,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1219
1284
|
if (selectorEntry) {
|
|
1220
1285
|
for (const selectorName of selectorEntry.selectors) {
|
|
1221
1286
|
const entry = {
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1287
|
+
value: selectorName,
|
|
1288
|
+
id: frameId,
|
|
1289
|
+
name: selectorName,
|
|
1290
|
+
params: ""
|
|
1226
1291
|
};
|
|
1227
1292
|
if (selectorName) {
|
|
1228
1293
|
if (!backtrace && elementMatchesSelector(current, selectorName)) {
|
|
@@ -1234,8 +1299,8 @@ function findFrameInfo(current, eventType) {
|
|
|
1234
1299
|
}
|
|
1235
1300
|
}
|
|
1236
1301
|
if (view.template && !backtrace) {
|
|
1237
|
-
if (match && !match.
|
|
1238
|
-
match.
|
|
1302
|
+
if (match && !match.id) {
|
|
1303
|
+
match.id = frameId;
|
|
1239
1304
|
}
|
|
1240
1305
|
break;
|
|
1241
1306
|
}
|
|
@@ -1251,10 +1316,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1251
1316
|
}
|
|
1252
1317
|
if (match) {
|
|
1253
1318
|
eventInfos.push({
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1319
|
+
id: match.id,
|
|
1320
|
+
value: match.value,
|
|
1321
|
+
name: match.name,
|
|
1322
|
+
params: match.params
|
|
1258
1323
|
});
|
|
1259
1324
|
}
|
|
1260
1325
|
return eventInfos;
|
|
@@ -1275,7 +1340,7 @@ function domEventProcessor(domEvent) {
|
|
|
1275
1340
|
const eventInfos = findFrameInfo(current, eventType);
|
|
1276
1341
|
if (eventInfos.length) {
|
|
1277
1342
|
for (const info of eventInfos) {
|
|
1278
|
-
const {
|
|
1343
|
+
const { id: frameId, name: handlerName, params } = info;
|
|
1279
1344
|
if (lastFrameId !== frameId) {
|
|
1280
1345
|
if (lastFrameId && domEvent.isPropagationStopped?.()) {
|
|
1281
1346
|
break;
|
|
@@ -1366,7 +1431,7 @@ var EventDelegator = {
|
|
|
1366
1431
|
};
|
|
1367
1432
|
|
|
1368
1433
|
// src/vdom.ts
|
|
1369
|
-
var
|
|
1434
|
+
var wrapMeta = {
|
|
1370
1435
|
option: [1, "<select multiple>"],
|
|
1371
1436
|
thead: [1, "<table>"],
|
|
1372
1437
|
col: [2, "<table><colgroup>"],
|
|
@@ -1374,13 +1439,13 @@ var WrapMeta = {
|
|
|
1374
1439
|
td: [3, "<table><tbody><tr>"],
|
|
1375
1440
|
area: [1, "<map>"],
|
|
1376
1441
|
param: [1, "<object>"],
|
|
1377
|
-
|
|
1378
|
-
|
|
1442
|
+
svg: [1, '<svg xmlns="' + SVG_NS + '">'],
|
|
1443
|
+
math: [1, '<math xmlns="' + MATH_NS + '">'],
|
|
1379
1444
|
_: [0, ""]
|
|
1380
1445
|
};
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1446
|
+
wrapMeta["optgroup"] = wrapMeta["option"];
|
|
1447
|
+
wrapMeta["tbody"] = wrapMeta["tfoot"] = wrapMeta["colgroup"] = wrapMeta["caption"] = wrapMeta["thead"];
|
|
1448
|
+
wrapMeta["th"] = wrapMeta["td"];
|
|
1384
1449
|
var VDoc = document.implementation.createHTMLDocument("");
|
|
1385
1450
|
var VBase = VDoc.createElement("base");
|
|
1386
1451
|
VBase.href = document.location.href;
|
|
@@ -1391,16 +1456,12 @@ var VDomSpecials = {
|
|
|
1391
1456
|
OPTION: ["selected"]
|
|
1392
1457
|
};
|
|
1393
1458
|
function vdomUnmountFrames(frame, node) {
|
|
1394
|
-
if (node
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
if (children.includes(id)) {
|
|
1401
|
-
frame.unmountFrame(id);
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1459
|
+
if (!(node instanceof Element)) return;
|
|
1460
|
+
const id = node.getAttribute("id");
|
|
1461
|
+
if (!id) return;
|
|
1462
|
+
frame.unmountZone(id);
|
|
1463
|
+
if (frame.children().includes(id)) {
|
|
1464
|
+
frame.unmountFrame(id);
|
|
1404
1465
|
}
|
|
1405
1466
|
}
|
|
1406
1467
|
function vdomGetNode(html, refNode) {
|
|
@@ -1408,14 +1469,14 @@ function vdomGetNode(html, refNode) {
|
|
|
1408
1469
|
const ns = refNode.namespaceURI;
|
|
1409
1470
|
let tag;
|
|
1410
1471
|
if (ns === SVG_NS) {
|
|
1411
|
-
tag = "
|
|
1472
|
+
tag = "svg";
|
|
1412
1473
|
} else if (ns === MATH_NS) {
|
|
1413
|
-
tag = "
|
|
1474
|
+
tag = "math";
|
|
1414
1475
|
} else {
|
|
1415
1476
|
const match = TAG_NAME_REGEXP.exec(html);
|
|
1416
1477
|
tag = match ? match[1] : "";
|
|
1417
1478
|
}
|
|
1418
|
-
const wrap =
|
|
1479
|
+
const wrap = wrapMeta[tag] || wrapMeta["_"];
|
|
1419
1480
|
tmp.innerHTML = wrap[1] + html;
|
|
1420
1481
|
let j = wrap[0];
|
|
1421
1482
|
while (j--) {
|
|
@@ -1432,7 +1493,7 @@ function vdomGetCompareKey(node) {
|
|
|
1432
1493
|
}
|
|
1433
1494
|
let key = el.autoId ? "" : el.getAttribute("id") || void 0;
|
|
1434
1495
|
if (!key) {
|
|
1435
|
-
key = el.getAttribute(
|
|
1496
|
+
key = el.getAttribute(LarkInnerKeys.DIFF_KEY) || void 0;
|
|
1436
1497
|
}
|
|
1437
1498
|
if (!key) {
|
|
1438
1499
|
const larkView = el.getAttribute(LARK_VIEW);
|
|
@@ -1445,8 +1506,7 @@ function vdomGetCompareKey(node) {
|
|
|
1445
1506
|
return key;
|
|
1446
1507
|
}
|
|
1447
1508
|
function vdomSpecialDiff(oldNode, newNode) {
|
|
1448
|
-
const
|
|
1449
|
-
const specials = VDomSpecials[nodeName];
|
|
1509
|
+
const specials = VDomSpecials[oldNode.nodeName];
|
|
1450
1510
|
if (!specials) return 0;
|
|
1451
1511
|
const oldEl = oldNode;
|
|
1452
1512
|
const newEl = newNode;
|
|
@@ -1495,13 +1555,17 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1495
1555
|
let oldNode = oldParent.lastChild;
|
|
1496
1556
|
let newNode = newParent.firstChild;
|
|
1497
1557
|
let extra = 0;
|
|
1498
|
-
const keyedNodes =
|
|
1499
|
-
const newKeyedNodes =
|
|
1558
|
+
const keyedNodes = /* @__PURE__ */ new Map();
|
|
1559
|
+
const newKeyedNodes = /* @__PURE__ */ new Map();
|
|
1500
1560
|
while (oldNode) {
|
|
1501
1561
|
extra++;
|
|
1502
1562
|
const nodeKey = vdomGetCompareKey(oldNode);
|
|
1503
1563
|
if (nodeKey) {
|
|
1504
|
-
|
|
1564
|
+
let bucket = keyedNodes.get(nodeKey);
|
|
1565
|
+
if (!bucket) {
|
|
1566
|
+
bucket = [];
|
|
1567
|
+
keyedNodes.set(nodeKey, bucket);
|
|
1568
|
+
}
|
|
1505
1569
|
bucket.push(oldNode);
|
|
1506
1570
|
}
|
|
1507
1571
|
oldNode = oldNode.previousSibling;
|
|
@@ -1509,7 +1573,7 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1509
1573
|
while (newNode) {
|
|
1510
1574
|
const nodeKey = vdomGetCompareKey(newNode);
|
|
1511
1575
|
if (nodeKey) {
|
|
1512
|
-
newKeyedNodes
|
|
1576
|
+
newKeyedNodes.set(nodeKey, (newKeyedNodes.get(nodeKey) ?? 0) + 1);
|
|
1513
1577
|
}
|
|
1514
1578
|
newNode = newNode.nextSibling;
|
|
1515
1579
|
}
|
|
@@ -1520,23 +1584,25 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1520
1584
|
const tempNew = newNode;
|
|
1521
1585
|
newNode = newNode.nextSibling;
|
|
1522
1586
|
const nodeKey = vdomGetCompareKey(tempNew);
|
|
1523
|
-
let foundNode = nodeKey ? keyedNodes
|
|
1587
|
+
let foundNode = nodeKey ? keyedNodes.get(nodeKey) : void 0;
|
|
1524
1588
|
if (foundNode && (foundNode = foundNode.slice()) && foundNode.length) {
|
|
1525
1589
|
const matched = foundNode.pop();
|
|
1526
1590
|
while (matched !== oldNode) {
|
|
1527
|
-
|
|
1591
|
+
if (!oldNode) break;
|
|
1592
|
+
const next = oldNode.nextSibling;
|
|
1528
1593
|
oldParent.appendChild(oldNode);
|
|
1529
1594
|
oldNode = next;
|
|
1530
1595
|
}
|
|
1531
1596
|
oldNode = matched.nextSibling;
|
|
1532
|
-
if (nodeKey
|
|
1533
|
-
newKeyedNodes
|
|
1597
|
+
if (nodeKey) {
|
|
1598
|
+
const c = newKeyedNodes.get(nodeKey);
|
|
1599
|
+
if (c) newKeyedNodes.set(nodeKey, c - 1);
|
|
1534
1600
|
}
|
|
1535
1601
|
vdomSetNode(matched, tempNew, oldParent, ref, frame, keys_);
|
|
1536
1602
|
} else if (oldNode) {
|
|
1537
1603
|
const tempOld2 = oldNode;
|
|
1538
1604
|
const oldKey = vdomGetCompareKey(tempOld2);
|
|
1539
|
-
if (oldKey && keyedNodes
|
|
1605
|
+
if (oldKey && keyedNodes.has(oldKey) && newKeyedNodes.get(oldKey)) {
|
|
1540
1606
|
extra++;
|
|
1541
1607
|
ref.hasChanged = 1;
|
|
1542
1608
|
ref.domOps.push([8, oldParent, tempNew, tempOld2]);
|
|
@@ -1560,17 +1626,21 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1560
1626
|
}
|
|
1561
1627
|
}
|
|
1562
1628
|
function vdomSetNode(oldNode, newNode, oldParent, ref, frame, keys_) {
|
|
1563
|
-
|
|
1629
|
+
const oldAsEl = oldNode instanceof Element ? oldNode : null;
|
|
1630
|
+
const newAsEl = newNode instanceof Element ? newNode : null;
|
|
1631
|
+
const hasViewKey = !!oldAsEl?.hasAttribute(LarkInnerKeys.VIEW_KEY);
|
|
1632
|
+
const equalAsNodes = oldAsEl !== null && newAsEl !== null && oldAsEl.isEqualNode && oldAsEl.isEqualNode(newAsEl);
|
|
1633
|
+
if (vdomSpecialDiff(oldNode, newNode) || hasViewKey || !equalAsNodes) {
|
|
1564
1634
|
if (oldNode.nodeType === newNode.nodeType && oldNode.nodeName === newNode.nodeName) {
|
|
1565
|
-
if (
|
|
1566
|
-
const oldEl =
|
|
1567
|
-
const newEl =
|
|
1568
|
-
const staticKey = newEl.getAttribute(
|
|
1569
|
-
if (staticKey && staticKey === oldEl.getAttribute(
|
|
1635
|
+
if (oldAsEl !== null && newAsEl !== null) {
|
|
1636
|
+
const oldEl = oldAsEl;
|
|
1637
|
+
const newEl = newAsEl;
|
|
1638
|
+
const staticKey = newEl.getAttribute(LarkInnerKeys.DIFF_KEY);
|
|
1639
|
+
if (staticKey && staticKey === oldEl.getAttribute(LarkInnerKeys.DIFF_KEY)) {
|
|
1570
1640
|
return;
|
|
1571
1641
|
}
|
|
1572
1642
|
const newLarkView = newEl.getAttribute(LARK_VIEW);
|
|
1573
|
-
const updateAttribute = !newEl.getAttribute(
|
|
1643
|
+
const updateAttribute = !newEl.getAttribute(LarkInnerKeys.ATTR_KEY) || newEl.getAttribute(LarkInnerKeys.ATTR_KEY) !== oldEl.getAttribute(LarkInnerKeys.ATTR_KEY);
|
|
1574
1644
|
let updateChildren = true;
|
|
1575
1645
|
if (newLarkView) {
|
|
1576
1646
|
const oldFrameId = oldEl.getAttribute("id") || "";
|
|
@@ -1671,7 +1741,8 @@ function encodeQ(v) {
|
|
|
1671
1741
|
}
|
|
1672
1742
|
|
|
1673
1743
|
// src/updater.ts
|
|
1674
|
-
function updaterRef(
|
|
1744
|
+
function updaterRef(refDataIn, value, key) {
|
|
1745
|
+
const refData = refDataIn;
|
|
1675
1746
|
const counter = refData[SPLITTER];
|
|
1676
1747
|
for (let i = counter; --i; ) {
|
|
1677
1748
|
key = SPLITTER + i;
|
|
@@ -1691,13 +1762,19 @@ var Updater = class {
|
|
|
1691
1762
|
/** Ref data for template rendering */
|
|
1692
1763
|
refData;
|
|
1693
1764
|
/** Changed keys in current digest cycle */
|
|
1694
|
-
changedKeys =
|
|
1765
|
+
changedKeys = /* @__PURE__ */ new Set();
|
|
1695
1766
|
/** Whether data has changed since last digest */
|
|
1696
1767
|
hasChangedFlag = 0;
|
|
1697
|
-
/**
|
|
1768
|
+
/**
|
|
1769
|
+
* Digesting queue: supports re-digest during digest.
|
|
1770
|
+
* Holds pending callbacks; `null` is used as a sentinel marking the start
|
|
1771
|
+
* of an active digest cycle, so `runDigest` can detect re-entrant calls.
|
|
1772
|
+
*/
|
|
1698
1773
|
digestingQueue = [];
|
|
1699
|
-
/**
|
|
1700
|
-
|
|
1774
|
+
/** Monotonically increasing version, bumped each time data actually changes. */
|
|
1775
|
+
version = 0;
|
|
1776
|
+
/** Snapshot of `version` taken by `snapshot()`, used by `altered()`. */
|
|
1777
|
+
snapshotVersion;
|
|
1701
1778
|
constructor(viewId) {
|
|
1702
1779
|
this.viewId = viewId;
|
|
1703
1780
|
this.data = { vId: viewId };
|
|
@@ -1725,7 +1802,16 @@ var Updater = class {
|
|
|
1725
1802
|
* Returns this for chaining.
|
|
1726
1803
|
*/
|
|
1727
1804
|
set(data, excludes) {
|
|
1728
|
-
|
|
1805
|
+
const changed = setData(
|
|
1806
|
+
data,
|
|
1807
|
+
this.data,
|
|
1808
|
+
this.changedKeys,
|
|
1809
|
+
excludes || EMPTY_STRING_SET
|
|
1810
|
+
);
|
|
1811
|
+
if (changed) {
|
|
1812
|
+
this.version++;
|
|
1813
|
+
this.hasChangedFlag = 1;
|
|
1814
|
+
}
|
|
1729
1815
|
return this;
|
|
1730
1816
|
}
|
|
1731
1817
|
/**
|
|
@@ -1761,13 +1847,13 @@ var Updater = class {
|
|
|
1761
1847
|
const keys2 = this.changedKeys;
|
|
1762
1848
|
const changed = this.hasChangedFlag;
|
|
1763
1849
|
this.hasChangedFlag = 0;
|
|
1764
|
-
this.changedKeys =
|
|
1850
|
+
this.changedKeys = /* @__PURE__ */ new Set();
|
|
1765
1851
|
const frame = Frame.get(this.viewId);
|
|
1766
1852
|
const view = frame?.view;
|
|
1767
1853
|
const node = getById(this.viewId);
|
|
1768
|
-
if (changed && view && node && view.signature > 0) {
|
|
1854
|
+
if (changed && view && node && view.signature > 0 && frame) {
|
|
1769
1855
|
const template = view.template;
|
|
1770
|
-
if (
|
|
1856
|
+
if (typeof template === "function") {
|
|
1771
1857
|
const html = template(
|
|
1772
1858
|
this.data,
|
|
1773
1859
|
this.viewId,
|
|
@@ -1804,43 +1890,65 @@ var Updater = class {
|
|
|
1804
1890
|
}
|
|
1805
1891
|
}
|
|
1806
1892
|
/**
|
|
1807
|
-
* Save a snapshot of current data for altered() detection.
|
|
1893
|
+
* Save a snapshot of the current data version for `altered()` detection.
|
|
1894
|
+
* Cheap O(1) — records the current monotonic version, no serialization.
|
|
1808
1895
|
*/
|
|
1809
1896
|
snapshot() {
|
|
1810
|
-
this.
|
|
1897
|
+
this.snapshotVersion = this.version;
|
|
1811
1898
|
return this;
|
|
1812
1899
|
}
|
|
1813
1900
|
/**
|
|
1814
|
-
* Check
|
|
1901
|
+
* Check whether data has changed since the last snapshot.
|
|
1902
|
+
* Returns undefined when no snapshot has been taken yet.
|
|
1815
1903
|
*/
|
|
1816
1904
|
altered() {
|
|
1817
|
-
if (this.
|
|
1818
|
-
|
|
1819
|
-
}
|
|
1820
|
-
return void 0;
|
|
1905
|
+
if (this.snapshotVersion === void 0) return void 0;
|
|
1906
|
+
return this.version !== this.snapshotVersion;
|
|
1821
1907
|
}
|
|
1822
1908
|
/**
|
|
1823
|
-
* Translate
|
|
1909
|
+
* Translate a refData reference back to its original value.
|
|
1910
|
+
*
|
|
1911
|
+
* The ref protocol is `SPLITTER` + ascii decimal digits — the exact format
|
|
1912
|
+
* emitted by `updaterRef`. We require that exact shape so a user-supplied
|
|
1913
|
+
* string that merely begins with SPLITTER is never accidentally resolved
|
|
1914
|
+
* (or mishandled as a "missing ref").
|
|
1824
1915
|
*/
|
|
1825
1916
|
translate(data) {
|
|
1826
|
-
if (typeof data
|
|
1827
|
-
|
|
1917
|
+
if (typeof data !== "string") return data;
|
|
1918
|
+
if (data.length < 2 || data[0] !== SPLITTER) return data;
|
|
1919
|
+
for (let i = 1; i < data.length; i++) {
|
|
1920
|
+
const c = data.charCodeAt(i);
|
|
1921
|
+
if (c < 48 || c > 57) return data;
|
|
1828
1922
|
}
|
|
1829
|
-
return data;
|
|
1923
|
+
return hasOwnProperty(this.refData, data) ? this.refData[data] : data;
|
|
1830
1924
|
}
|
|
1831
1925
|
/**
|
|
1832
|
-
*
|
|
1926
|
+
* Resolve a dotted property path against refData.
|
|
1927
|
+
*
|
|
1928
|
+
* Only safe property-path syntax is supported: `a`, `a.b`, `a.b.c`.
|
|
1929
|
+
* Numeric literals (e.g. `1`, `1.5`) are returned as numbers. Anything else
|
|
1930
|
+
* returns `undefined` — we no longer evaluate arbitrary JavaScript via
|
|
1931
|
+
* `new Function`, so the method is CSP-safe and cannot be used as an
|
|
1932
|
+
* injection vector.
|
|
1833
1933
|
*/
|
|
1834
1934
|
parse(expr) {
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1935
|
+
const trimmed = expr.trim();
|
|
1936
|
+
if (!trimmed) return void 0;
|
|
1937
|
+
if (/^-?\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
1938
|
+
return Number(trimmed);
|
|
1939
|
+
}
|
|
1940
|
+
if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(trimmed)) {
|
|
1839
1941
|
return void 0;
|
|
1840
1942
|
}
|
|
1943
|
+
let cur = this.refData;
|
|
1944
|
+
for (const segment of trimmed.split(".")) {
|
|
1945
|
+
if (cur == null || typeof cur !== "object") return void 0;
|
|
1946
|
+
cur = cur[segment];
|
|
1947
|
+
}
|
|
1948
|
+
return cur;
|
|
1841
1949
|
}
|
|
1842
1950
|
/**
|
|
1843
|
-
* Get
|
|
1951
|
+
* Get the set of keys changed since the last digest (for external inspection).
|
|
1844
1952
|
*/
|
|
1845
1953
|
getChangedKeys() {
|
|
1846
1954
|
return this.changedKeys;
|
|
@@ -1855,221 +1963,6 @@ if (typeof window !== "undefined") {
|
|
|
1855
1963
|
if (typeof document !== "undefined") {
|
|
1856
1964
|
VIEW_GLOBALS["document"] = document;
|
|
1857
1965
|
}
|
|
1858
|
-
function viewPrepare(oView) {
|
|
1859
|
-
if (oView.ctors) {
|
|
1860
|
-
return oView.ctors;
|
|
1861
|
-
}
|
|
1862
|
-
const ctors = [];
|
|
1863
|
-
oView.ctors = ctors;
|
|
1864
|
-
const proto = oView.prototype;
|
|
1865
|
-
const eventsObject = {};
|
|
1866
|
-
const eventsList = [];
|
|
1867
|
-
const selectorObject = {};
|
|
1868
|
-
const mixins = proto["mixins"];
|
|
1869
|
-
if (mixins && Array.isArray(mixins)) {
|
|
1870
|
-
viewMergeMixins(mixins, oView, ctors);
|
|
1871
|
-
}
|
|
1872
|
-
for (const p in proto) {
|
|
1873
|
-
if (!has(proto, p)) continue;
|
|
1874
|
-
const currentFn = proto[p];
|
|
1875
|
-
if (typeof currentFn !== "function") continue;
|
|
1876
|
-
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
1877
|
-
if (!matches) continue;
|
|
1878
|
-
const isSelector = matches[1];
|
|
1879
|
-
const selectorOrCallback = matches[2];
|
|
1880
|
-
const events = matches[3];
|
|
1881
|
-
const modifiers = matches[4];
|
|
1882
|
-
const mod = {};
|
|
1883
|
-
if (modifiers) {
|
|
1884
|
-
for (const item of modifiers.split(",")) {
|
|
1885
|
-
mod[item] = true;
|
|
1886
|
-
}
|
|
1887
|
-
}
|
|
1888
|
-
const eventTypes = events.split(",");
|
|
1889
|
-
for (const item of eventTypes) {
|
|
1890
|
-
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
1891
|
-
let mask = 1;
|
|
1892
|
-
if (isSelector) {
|
|
1893
|
-
if (globalNode) {
|
|
1894
|
-
eventsList.push({
|
|
1895
|
-
handler: currentFn,
|
|
1896
|
-
element: globalNode,
|
|
1897
|
-
eventName: item,
|
|
1898
|
-
modifiers: mod
|
|
1899
|
-
});
|
|
1900
|
-
continue;
|
|
1901
|
-
}
|
|
1902
|
-
mask = 2;
|
|
1903
|
-
let selectorEntry = selectorObject[item];
|
|
1904
|
-
if (!selectorEntry) {
|
|
1905
|
-
selectorEntry = selectorObject[item] = {
|
|
1906
|
-
selectors: []
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
if (!selectorEntry[selectorOrCallback]) {
|
|
1910
|
-
selectorEntry[selectorOrCallback] = 1;
|
|
1911
|
-
selectorEntry.selectors.push(selectorOrCallback);
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
1915
|
-
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
1916
|
-
const existingFn = proto[combinedKey];
|
|
1917
|
-
if (!existingFn) {
|
|
1918
|
-
proto[combinedKey] = currentFn;
|
|
1919
|
-
} else {
|
|
1920
|
-
const mixinFn = currentFn;
|
|
1921
|
-
const existingMixin = existingFn;
|
|
1922
|
-
if (existingMixin.b) {
|
|
1923
|
-
if (mixinFn.b) {
|
|
1924
|
-
proto[combinedKey] = processMixinsSameEvent(
|
|
1925
|
-
currentFn,
|
|
1926
|
-
existingFn
|
|
1927
|
-
);
|
|
1928
|
-
} else if (has(proto, p)) {
|
|
1929
|
-
proto[combinedKey] = currentFn;
|
|
1930
|
-
}
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
viewWrapMethod(proto, "render", "$b");
|
|
1936
|
-
proto["$eo"] = eventsObject;
|
|
1937
|
-
proto["$el"] = eventsList;
|
|
1938
|
-
proto["$so"] = selectorObject;
|
|
1939
|
-
proto["$f"] = proto["assign"];
|
|
1940
|
-
return ctors;
|
|
1941
|
-
}
|
|
1942
|
-
function viewWrapMethod(proto, fnName, shortKey) {
|
|
1943
|
-
const originalFn = proto[fnName];
|
|
1944
|
-
if (typeof originalFn !== "function") return;
|
|
1945
|
-
const wrapped = function(...args) {
|
|
1946
|
-
if (this.signature > 0) {
|
|
1947
|
-
this.signature++;
|
|
1948
|
-
this.fire("rendercall");
|
|
1949
|
-
destroyAllResources(this, false);
|
|
1950
|
-
const instanceFn = typeof this[fnName] === "function" ? this[fnName] : originalFn;
|
|
1951
|
-
const fnToCall = instanceFn === wrapped ? originalFn : instanceFn;
|
|
1952
|
-
return funcWithTry(fnToCall, args, this, noop);
|
|
1953
|
-
}
|
|
1954
|
-
return void 0;
|
|
1955
|
-
};
|
|
1956
|
-
proto[fnName] = wrapped;
|
|
1957
|
-
proto[shortKey] = wrapped;
|
|
1958
|
-
}
|
|
1959
|
-
function processMixinsSameEvent(additional, exist) {
|
|
1960
|
-
let temp;
|
|
1961
|
-
const existMixin = exist;
|
|
1962
|
-
if (existMixin.a) {
|
|
1963
|
-
temp = existMixin;
|
|
1964
|
-
} else {
|
|
1965
|
-
temp = function(...e) {
|
|
1966
|
-
funcWithTry(temp.a ?? [], e, this, noop);
|
|
1967
|
-
};
|
|
1968
|
-
temp.a = [exist];
|
|
1969
|
-
temp.b = 1;
|
|
1970
|
-
}
|
|
1971
|
-
const additionalMixin = additional;
|
|
1972
|
-
temp.a = (temp.a ?? []).concat(additionalMixin.a ?? [additional]);
|
|
1973
|
-
return temp;
|
|
1974
|
-
}
|
|
1975
|
-
function viewMergeMixins(mixins, viewClass, ctors) {
|
|
1976
|
-
const proto = viewClass.prototype;
|
|
1977
|
-
const temp = {};
|
|
1978
|
-
for (const node of mixins) {
|
|
1979
|
-
for (const p in node) {
|
|
1980
|
-
if (!has(node, p)) continue;
|
|
1981
|
-
const fn = node[p];
|
|
1982
|
-
const exist = temp[p];
|
|
1983
|
-
if (p === "make") {
|
|
1984
|
-
ctors.push(fn);
|
|
1985
|
-
continue;
|
|
1986
|
-
}
|
|
1987
|
-
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
1988
|
-
if (exist) {
|
|
1989
|
-
temp[p] = processMixinsSameEvent(fn, exist);
|
|
1990
|
-
} else {
|
|
1991
|
-
fn.b = 1;
|
|
1992
|
-
temp[p] = fn;
|
|
1993
|
-
}
|
|
1994
|
-
} else {
|
|
1995
|
-
if (!exist) {
|
|
1996
|
-
temp[p] = fn;
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
for (const p in temp) {
|
|
2002
|
-
if (!has(proto, p)) {
|
|
2003
|
-
proto[p] = temp[p];
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
}
|
|
2007
|
-
function viewDelegateEvents(view, destroy = false) {
|
|
2008
|
-
const proto = Object.getPrototypeOf(view) ?? {};
|
|
2009
|
-
const eventsObject = proto["$eo"] || view.eventObjectMap;
|
|
2010
|
-
const selectorObject = proto["$so"] || view.eventSelectorMap;
|
|
2011
|
-
const eventsList = proto["$el"] || view.globalEventList;
|
|
2012
|
-
for (const e in eventsObject) {
|
|
2013
|
-
if (has(eventsObject, e)) {
|
|
2014
|
-
if (destroy) {
|
|
2015
|
-
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
2016
|
-
} else {
|
|
2017
|
-
EventDelegator.bind(e, !!selectorObject[e]);
|
|
2018
|
-
}
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
for (const entry of eventsList) {
|
|
2022
|
-
if (destroy) {
|
|
2023
|
-
entry.element.removeEventListener(
|
|
2024
|
-
entry.eventName,
|
|
2025
|
-
entry.boundHandler
|
|
2026
|
-
);
|
|
2027
|
-
} else {
|
|
2028
|
-
const handler = entry.handler;
|
|
2029
|
-
const element = entry.element;
|
|
2030
|
-
const modifiers = entry.modifiers;
|
|
2031
|
-
entry.boundHandler = function(domEvent) {
|
|
2032
|
-
const extendedEvent = domEvent;
|
|
2033
|
-
extendedEvent.eventTarget = element;
|
|
2034
|
-
if (modifiers) {
|
|
2035
|
-
const kbEvent = domEvent;
|
|
2036
|
-
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
2037
|
-
return;
|
|
2038
|
-
}
|
|
2039
|
-
}
|
|
2040
|
-
funcWithTry(handler, [domEvent], view, noop);
|
|
2041
|
-
};
|
|
2042
|
-
entry.element.addEventListener(
|
|
2043
|
-
entry.eventName,
|
|
2044
|
-
entry.boundHandler
|
|
2045
|
-
);
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
function destroyAllResources(view, lastly) {
|
|
2050
|
-
const cache = view.resources;
|
|
2051
|
-
for (const p in cache) {
|
|
2052
|
-
if (has(cache, p)) {
|
|
2053
|
-
const entry = cache[p];
|
|
2054
|
-
if (lastly || entry.destroyOnRender) {
|
|
2055
|
-
destroyResource(cache, p, true);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
function destroyResource(cache, key, callDestroy, oldEntity) {
|
|
2061
|
-
const entry = cache[key];
|
|
2062
|
-
if (!entry || entry.entity === oldEntity) return void 0;
|
|
2063
|
-
const entity = entry.entity;
|
|
2064
|
-
if (entity && typeof entity === "object") {
|
|
2065
|
-
const destroyFn = entity["destroy"];
|
|
2066
|
-
if (typeof destroyFn === "function" && callDestroy) {
|
|
2067
|
-
funcWithTry(destroyFn, [], entity, noop);
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
Reflect.deleteProperty(cache, key);
|
|
2071
|
-
return entity;
|
|
2072
|
-
}
|
|
2073
1966
|
var View = class _View {
|
|
2074
1967
|
/** View ID (same as owner frame ID) */
|
|
2075
1968
|
id = "";
|
|
@@ -2093,18 +1986,44 @@ var View = class _View {
|
|
|
2093
1986
|
observedStateKeys;
|
|
2094
1987
|
/** Resource map */
|
|
2095
1988
|
resources = {};
|
|
2096
|
-
/** Selector event map: eventType -> handler name list */
|
|
2097
|
-
eventSelectorMap = {};
|
|
2098
|
-
/** Event object map: eventType -> bitmask */
|
|
2099
|
-
eventObjectMap = {};
|
|
2100
|
-
/** Global event list */
|
|
2101
|
-
globalEventList = [];
|
|
2102
1989
|
/** Assign method reference */
|
|
2103
1990
|
assignMethod;
|
|
2104
1991
|
/** Whether endUpdate pending */
|
|
2105
1992
|
endUpdatePending;
|
|
2106
1993
|
/** Internal event storage */
|
|
2107
1994
|
_events = new EventEmitter();
|
|
1995
|
+
// ============================================================
|
|
1996
|
+
// Getters for prototype-stored event maps
|
|
1997
|
+
// ============================================================
|
|
1998
|
+
/** Prototype-stored event maps shape (set by View.prepare). */
|
|
1999
|
+
get protoEventState() {
|
|
2000
|
+
return Object.getPrototypeOf(this);
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Event bitmask map: eventType -> bitmask (1=root, 2=selector).
|
|
2004
|
+
* Read from prototype ($evtObjMap) set by View.prepare.
|
|
2005
|
+
* Using a getter avoids ES6 class field shadowing the prototype value.
|
|
2006
|
+
*/
|
|
2007
|
+
get eventObjectMap() {
|
|
2008
|
+
return this.protoEventState.$evtObjMap ?? {};
|
|
2009
|
+
}
|
|
2010
|
+
/**
|
|
2011
|
+
* Selector event map: eventType -> selector list.
|
|
2012
|
+
* Read from prototype ($selMap) set by View.prepare.
|
|
2013
|
+
*/
|
|
2014
|
+
get eventSelectorMap() {
|
|
2015
|
+
return this.protoEventState.$selMap ?? {};
|
|
2016
|
+
}
|
|
2017
|
+
/**
|
|
2018
|
+
* Global event list: [{handler, element, eventName, modifiers}].
|
|
2019
|
+
* Read from prototype ($globalEvtList) set by View.prepare.
|
|
2020
|
+
*/
|
|
2021
|
+
get globalEventList() {
|
|
2022
|
+
return this.protoEventState.$globalEvtList ?? [];
|
|
2023
|
+
}
|
|
2024
|
+
// ============================================================
|
|
2025
|
+
// Instance lifecycle methods
|
|
2026
|
+
// ============================================================
|
|
2108
2027
|
/**
|
|
2109
2028
|
* Initialize view (called by Frame when mounting).
|
|
2110
2029
|
*/
|
|
@@ -2112,14 +2031,7 @@ var View = class _View {
|
|
|
2112
2031
|
}
|
|
2113
2032
|
/**
|
|
2114
2033
|
* Render view template (called by Frame after init).
|
|
2115
|
-
* Wrapped by
|
|
2116
|
-
*
|
|
2117
|
-
* Default implementation calls updater.digest() which:
|
|
2118
|
-
* 1. Executes the template function with current data
|
|
2119
|
-
* 2. Runs VDOM diff against previous DOM
|
|
2120
|
-
* 3. Applies DOM operations
|
|
2121
|
-
* 4. Calls endUpdate to mount child frames
|
|
2122
|
-
*
|
|
2034
|
+
* Wrapped by View.wrapMethod to manage signature + resources.
|
|
2123
2035
|
*/
|
|
2124
2036
|
render() {
|
|
2125
2037
|
this.updater.digest();
|
|
@@ -2142,13 +2054,17 @@ var View = class _View {
|
|
|
2142
2054
|
// ============================================================
|
|
2143
2055
|
// Update methods
|
|
2144
2056
|
// ============================================================
|
|
2057
|
+
/** Get the owning frame, asserting it has been bound. */
|
|
2058
|
+
get ownerFrame() {
|
|
2059
|
+
return this.owner;
|
|
2060
|
+
}
|
|
2145
2061
|
/**
|
|
2146
2062
|
* Notify view that HTML update is about to begin.
|
|
2147
2063
|
* Unmounts child frames in the update zone.
|
|
2148
2064
|
*/
|
|
2149
2065
|
beginUpdate(id) {
|
|
2150
2066
|
if (this.signature > 0 && this.endUpdatePending !== void 0) {
|
|
2151
|
-
this.
|
|
2067
|
+
this.ownerFrame.unmountZone(id, true);
|
|
2152
2068
|
}
|
|
2153
2069
|
}
|
|
2154
2070
|
/**
|
|
@@ -2166,12 +2082,12 @@ var View = class _View {
|
|
|
2166
2082
|
this.endUpdatePending = 1;
|
|
2167
2083
|
this.rendered = true;
|
|
2168
2084
|
}
|
|
2169
|
-
const ownerFrame = this.
|
|
2085
|
+
const ownerFrame = this.ownerFrame;
|
|
2170
2086
|
ownerFrame.mountZone(updateId, inner);
|
|
2171
2087
|
if (!flag) {
|
|
2172
2088
|
setTimeout(
|
|
2173
2089
|
this.wrapAsync(() => {
|
|
2174
|
-
runInvokes(ownerFrame);
|
|
2090
|
+
_View.runInvokes(ownerFrame);
|
|
2175
2091
|
}),
|
|
2176
2092
|
0
|
|
2177
2093
|
);
|
|
@@ -2205,11 +2121,12 @@ var View = class _View {
|
|
|
2205
2121
|
const loc = this.locationObserved;
|
|
2206
2122
|
loc.flag = 1;
|
|
2207
2123
|
if (typeof params === "object" && !Array.isArray(params)) {
|
|
2208
|
-
|
|
2124
|
+
const opts = params;
|
|
2125
|
+
if (opts["path"]) {
|
|
2209
2126
|
observePath = true;
|
|
2210
2127
|
}
|
|
2211
|
-
const paramKeys =
|
|
2212
|
-
if (paramKeys) {
|
|
2128
|
+
const paramKeys = opts["params"];
|
|
2129
|
+
if (typeof paramKeys === "string" || Array.isArray(paramKeys)) {
|
|
2213
2130
|
params = paramKeys;
|
|
2214
2131
|
}
|
|
2215
2132
|
}
|
|
@@ -2247,7 +2164,7 @@ var View = class _View {
|
|
|
2247
2164
|
capture(key, resource, destroyOnRender = false) {
|
|
2248
2165
|
const cache = this.resources;
|
|
2249
2166
|
if (resource) {
|
|
2250
|
-
destroyResource(cache, key, true, resource);
|
|
2167
|
+
_View.destroyResource(cache, key, true, resource);
|
|
2251
2168
|
cache[key] = {
|
|
2252
2169
|
entity: resource,
|
|
2253
2170
|
destroyOnRender
|
|
@@ -2263,7 +2180,7 @@ var View = class _View {
|
|
|
2263
2180
|
* If destroy=true, calls the resource's destroy() method.
|
|
2264
2181
|
*/
|
|
2265
2182
|
release(key, destroy = true) {
|
|
2266
|
-
return destroyResource(this.resources, key, destroy);
|
|
2183
|
+
return _View.destroyResource(this.resources, key, destroy);
|
|
2267
2184
|
}
|
|
2268
2185
|
// ============================================================
|
|
2269
2186
|
// Leave tip
|
|
@@ -2273,24 +2190,16 @@ var View = class _View {
|
|
|
2273
2190
|
*/
|
|
2274
2191
|
leaveTip(message, condition) {
|
|
2275
2192
|
const changeListener = function(e) {
|
|
2276
|
-
const isRouterChange = e.type ===
|
|
2193
|
+
const isRouterChange = e.type === RouterEvents.CHANGE;
|
|
2277
2194
|
const aKey = isRouterChange ? "a" : "b";
|
|
2278
2195
|
const bKey = isRouterChange ? "b" : "a";
|
|
2279
2196
|
if (changeListener[aKey]) {
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
}
|
|
2283
|
-
if (typeof e.reject === "function") {
|
|
2284
|
-
e.reject();
|
|
2285
|
-
}
|
|
2197
|
+
e.prevent?.();
|
|
2198
|
+
e.reject?.();
|
|
2286
2199
|
} else if (condition()) {
|
|
2287
|
-
|
|
2288
|
-
e.prevent();
|
|
2289
|
-
}
|
|
2200
|
+
e.prevent?.();
|
|
2290
2201
|
changeListener[bKey] = 1;
|
|
2291
|
-
|
|
2292
|
-
e.resolve();
|
|
2293
|
-
}
|
|
2202
|
+
e.resolve?.();
|
|
2294
2203
|
}
|
|
2295
2204
|
};
|
|
2296
2205
|
const unloadListener = (e) => {
|
|
@@ -2298,21 +2207,284 @@ var View = class _View {
|
|
|
2298
2207
|
e["msg"] = message;
|
|
2299
2208
|
}
|
|
2300
2209
|
};
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
Router.on(ROUTER_EVENTS.PAGE_UNLOAD, unloadFn);
|
|
2305
|
-
this.on("unload", changeFn);
|
|
2210
|
+
Router.on(RouterEvents.CHANGE, changeListener);
|
|
2211
|
+
Router.on(RouterEvents.PAGE_UNLOAD, unloadListener);
|
|
2212
|
+
this.on("unload", changeListener);
|
|
2306
2213
|
this.on("destroy", () => {
|
|
2307
|
-
Router.off(
|
|
2308
|
-
Router.off(
|
|
2214
|
+
Router.off(RouterEvents.CHANGE, changeListener);
|
|
2215
|
+
Router.off(RouterEvents.PAGE_UNLOAD, unloadListener);
|
|
2309
2216
|
});
|
|
2310
2217
|
}
|
|
2311
2218
|
// ============================================================
|
|
2312
|
-
// Static
|
|
2219
|
+
// Static public methods
|
|
2313
2220
|
// ============================================================
|
|
2314
2221
|
/** Collected ctors from mixins */
|
|
2315
2222
|
static ctors;
|
|
2223
|
+
/**
|
|
2224
|
+
* Prepare a View subclass by scanning its prototype for event method patterns.
|
|
2225
|
+
* Pattern: `$?name<eventType1,eventType2>(&modifiers)`
|
|
2226
|
+
*
|
|
2227
|
+
* Only runs once per View subclass (guarded by ctors marker).
|
|
2228
|
+
* Called from Frame.mountView before creating the view instance.
|
|
2229
|
+
*/
|
|
2230
|
+
static prepare(oView) {
|
|
2231
|
+
if (oView.ctors) {
|
|
2232
|
+
return oView.ctors;
|
|
2233
|
+
}
|
|
2234
|
+
const ctors = [];
|
|
2235
|
+
oView.ctors = ctors;
|
|
2236
|
+
const proto = oView.prototype;
|
|
2237
|
+
const eventsObject = {};
|
|
2238
|
+
const eventsList = [];
|
|
2239
|
+
const selectorObject = {};
|
|
2240
|
+
const mixins = proto["mixins"];
|
|
2241
|
+
if (mixins && Array.isArray(mixins)) {
|
|
2242
|
+
_View.mergeMixins(mixins, oView, ctors);
|
|
2243
|
+
}
|
|
2244
|
+
for (const p in proto) {
|
|
2245
|
+
if (!hasOwnProperty(proto, p)) continue;
|
|
2246
|
+
const currentFn = proto[p];
|
|
2247
|
+
if (typeof currentFn !== "function") continue;
|
|
2248
|
+
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
2249
|
+
if (!matches) continue;
|
|
2250
|
+
const isSelector = matches[1];
|
|
2251
|
+
const selectorOrCallback = matches[2];
|
|
2252
|
+
const events = matches[3];
|
|
2253
|
+
const modifiers = matches[4];
|
|
2254
|
+
const mod = {};
|
|
2255
|
+
if (modifiers) {
|
|
2256
|
+
for (const item of modifiers.split(",")) {
|
|
2257
|
+
mod[item] = true;
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
const eventTypes = events.split(",");
|
|
2261
|
+
for (const item of eventTypes) {
|
|
2262
|
+
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
2263
|
+
let mask = 1;
|
|
2264
|
+
if (isSelector) {
|
|
2265
|
+
if (globalNode) {
|
|
2266
|
+
eventsList.push({
|
|
2267
|
+
handler: currentFn,
|
|
2268
|
+
element: globalNode,
|
|
2269
|
+
eventName: item,
|
|
2270
|
+
modifiers: mod
|
|
2271
|
+
});
|
|
2272
|
+
continue;
|
|
2273
|
+
}
|
|
2274
|
+
mask = 2;
|
|
2275
|
+
let selectorEntry = selectorObject[item];
|
|
2276
|
+
if (!selectorEntry) {
|
|
2277
|
+
selectorEntry = selectorObject[item] = {
|
|
2278
|
+
selectors: []
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
if (!selectorEntry[selectorOrCallback]) {
|
|
2282
|
+
selectorEntry[selectorOrCallback] = 1;
|
|
2283
|
+
selectorEntry.selectors.push(selectorOrCallback);
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
2287
|
+
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
2288
|
+
const existingFn = proto[combinedKey];
|
|
2289
|
+
if (!existingFn) {
|
|
2290
|
+
proto[combinedKey] = currentFn;
|
|
2291
|
+
} else if (typeof existingFn === "function") {
|
|
2292
|
+
const mixinFn = currentFn;
|
|
2293
|
+
const existingMixin = existingFn;
|
|
2294
|
+
if (existingMixin.marker) {
|
|
2295
|
+
if (mixinFn.marker) {
|
|
2296
|
+
proto[combinedKey] = _View.processMixinsSameEvent(
|
|
2297
|
+
mixinFn,
|
|
2298
|
+
existingMixin
|
|
2299
|
+
);
|
|
2300
|
+
} else if (hasOwnProperty(proto, p)) {
|
|
2301
|
+
proto[combinedKey] = currentFn;
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
_View.wrapMethod(proto, "render", "$renderWrap");
|
|
2308
|
+
proto["$evtObjMap"] = eventsObject;
|
|
2309
|
+
proto["$globalEvtList"] = eventsList;
|
|
2310
|
+
proto["$selMap"] = selectorObject;
|
|
2311
|
+
proto["$assignFn"] = proto["assign"];
|
|
2312
|
+
return ctors;
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* Bind or unbind event delegation for a view instance.
|
|
2316
|
+
* Called from Frame during mount/unmount.
|
|
2317
|
+
*/
|
|
2318
|
+
static delegateEvents(view, destroy = false) {
|
|
2319
|
+
const eventsObject = view.eventObjectMap;
|
|
2320
|
+
const selectorObject = view.eventSelectorMap;
|
|
2321
|
+
const eventsList = view.globalEventList;
|
|
2322
|
+
for (const e in eventsObject) {
|
|
2323
|
+
if (hasOwnProperty(eventsObject, e)) {
|
|
2324
|
+
if (destroy) {
|
|
2325
|
+
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
2326
|
+
} else {
|
|
2327
|
+
EventDelegator.bind(e, !!selectorObject[e]);
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
for (const entry of eventsList) {
|
|
2332
|
+
if (destroy) {
|
|
2333
|
+
entry.element.removeEventListener(
|
|
2334
|
+
entry.eventName,
|
|
2335
|
+
entry.boundHandler
|
|
2336
|
+
);
|
|
2337
|
+
} else {
|
|
2338
|
+
const handler = entry.handler;
|
|
2339
|
+
const element = entry.element;
|
|
2340
|
+
const modifiers = entry.modifiers;
|
|
2341
|
+
entry.boundHandler = function(domEvent) {
|
|
2342
|
+
const extendedEvent = domEvent;
|
|
2343
|
+
extendedEvent.eventTarget = element;
|
|
2344
|
+
if (modifiers) {
|
|
2345
|
+
const kbEvent = domEvent;
|
|
2346
|
+
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
2347
|
+
return;
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
funcWithTry(handler, [domEvent], view, noop);
|
|
2351
|
+
};
|
|
2352
|
+
entry.element.addEventListener(
|
|
2353
|
+
entry.eventName,
|
|
2354
|
+
entry.boundHandler
|
|
2355
|
+
);
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
/**
|
|
2360
|
+
* Destroy all resources managed by a view.
|
|
2361
|
+
* If lastly=true, destroy ALL resources; otherwise only destroyOnRender ones.
|
|
2362
|
+
*/
|
|
2363
|
+
static destroyAllResources(view, lastly) {
|
|
2364
|
+
const cache = view.resources;
|
|
2365
|
+
for (const p in cache) {
|
|
2366
|
+
if (hasOwnProperty(cache, p)) {
|
|
2367
|
+
const entry = cache[p];
|
|
2368
|
+
if (lastly || entry.destroyOnRender) {
|
|
2369
|
+
_View.destroyResource(cache, p, true);
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
/**
|
|
2375
|
+
* Process deferred invoke calls on a frame.
|
|
2376
|
+
*/
|
|
2377
|
+
static runInvokes(frame) {
|
|
2378
|
+
const list = frame.invokeList;
|
|
2379
|
+
if (!list) return;
|
|
2380
|
+
while (list.length) {
|
|
2381
|
+
const entry = list.shift();
|
|
2382
|
+
if (entry && !entry.removed) {
|
|
2383
|
+
frame.invoke(entry.name, entry.args);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
// ============================================================
|
|
2388
|
+
// Static private methods
|
|
2389
|
+
// ============================================================
|
|
2390
|
+
/**
|
|
2391
|
+
* Wrap a method on the prototype to add signature checking and resource cleanup.
|
|
2392
|
+
*/
|
|
2393
|
+
static wrapMethod(proto, fnName, shortKey) {
|
|
2394
|
+
const originalFn = proto[fnName];
|
|
2395
|
+
if (typeof originalFn !== "function") return;
|
|
2396
|
+
const originalAsFn = originalFn;
|
|
2397
|
+
const wrapped = function(...args) {
|
|
2398
|
+
if (this.signature > 0) {
|
|
2399
|
+
this.signature++;
|
|
2400
|
+
this.fire("render");
|
|
2401
|
+
_View.destroyAllResources(this, false);
|
|
2402
|
+
const lookup = this;
|
|
2403
|
+
const candidate = lookup[fnName];
|
|
2404
|
+
const instanceFn = typeof candidate === "function" ? candidate : originalAsFn;
|
|
2405
|
+
const fnToCall = instanceFn === wrapped ? originalAsFn : instanceFn;
|
|
2406
|
+
return funcWithTry(fnToCall, args, this, noop);
|
|
2407
|
+
}
|
|
2408
|
+
return void 0;
|
|
2409
|
+
};
|
|
2410
|
+
proto[fnName] = wrapped;
|
|
2411
|
+
proto[shortKey] = wrapped;
|
|
2412
|
+
}
|
|
2413
|
+
/**
|
|
2414
|
+
* When two mixins define the same event method, merge them into
|
|
2415
|
+
* a single function that calls both in sequence.
|
|
2416
|
+
*/
|
|
2417
|
+
static processMixinsSameEvent(additional, exist) {
|
|
2418
|
+
let temp;
|
|
2419
|
+
if (exist.handlerList) {
|
|
2420
|
+
temp = exist;
|
|
2421
|
+
} else {
|
|
2422
|
+
const merged = function(...e) {
|
|
2423
|
+
funcWithTry(merged.handlerList ?? [], e, this, noop);
|
|
2424
|
+
};
|
|
2425
|
+
merged.handlerList = [exist];
|
|
2426
|
+
merged.marker = 1;
|
|
2427
|
+
temp = merged;
|
|
2428
|
+
}
|
|
2429
|
+
temp.handlerList = (temp.handlerList ?? []).concat(
|
|
2430
|
+
additional.handlerList ?? [additional]
|
|
2431
|
+
);
|
|
2432
|
+
return temp;
|
|
2433
|
+
}
|
|
2434
|
+
/**
|
|
2435
|
+
* Merge an array of mixin objects into the view prototype.
|
|
2436
|
+
*/
|
|
2437
|
+
static mergeMixins(mixins, viewClass, ctors) {
|
|
2438
|
+
const proto = viewClass.prototype;
|
|
2439
|
+
const temp = {};
|
|
2440
|
+
for (const node of mixins) {
|
|
2441
|
+
for (const p in node) {
|
|
2442
|
+
if (!hasOwnProperty(node, p)) continue;
|
|
2443
|
+
const fn = node[p];
|
|
2444
|
+
if (typeof fn !== "function") continue;
|
|
2445
|
+
const mixinFn = fn;
|
|
2446
|
+
const exist = temp[p];
|
|
2447
|
+
if (p === "make") {
|
|
2448
|
+
ctors.push(mixinFn);
|
|
2449
|
+
continue;
|
|
2450
|
+
}
|
|
2451
|
+
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
2452
|
+
if (exist) {
|
|
2453
|
+
temp[p] = _View.processMixinsSameEvent(mixinFn, exist);
|
|
2454
|
+
} else {
|
|
2455
|
+
mixinFn.marker = 1;
|
|
2456
|
+
temp[p] = mixinFn;
|
|
2457
|
+
}
|
|
2458
|
+
} else if (!exist) {
|
|
2459
|
+
temp[p] = mixinFn;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
for (const p in temp) {
|
|
2464
|
+
if (!hasOwnProperty(proto, p)) {
|
|
2465
|
+
proto[p] = temp[p];
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
/**
|
|
2470
|
+
* Destroy a single resource entry.
|
|
2471
|
+
*/
|
|
2472
|
+
static destroyResource(cache, key, callDestroy, oldEntity) {
|
|
2473
|
+
const entry = cache[key];
|
|
2474
|
+
if (!entry || entry.entity === oldEntity) return void 0;
|
|
2475
|
+
const entity = entry.entity;
|
|
2476
|
+
if (entity && typeof entity === "object") {
|
|
2477
|
+
const destroyFn = entity["destroy"];
|
|
2478
|
+
if (typeof destroyFn === "function" && callDestroy) {
|
|
2479
|
+
funcWithTry(destroyFn, [], entity, noop);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
Reflect.deleteProperty(cache, key);
|
|
2483
|
+
return entity;
|
|
2484
|
+
}
|
|
2485
|
+
// ============================================================
|
|
2486
|
+
// Static: extend and merge
|
|
2487
|
+
// ============================================================
|
|
2316
2488
|
/**
|
|
2317
2489
|
* Extend View to create a new View subclass.
|
|
2318
2490
|
*
|
|
@@ -2322,19 +2494,20 @@ var View = class _View {
|
|
|
2322
2494
|
* - Event method patterns: `'name<click>'` etc.
|
|
2323
2495
|
*/
|
|
2324
2496
|
static extend(props, statics) {
|
|
2325
|
-
|
|
2326
|
-
const make =
|
|
2497
|
+
const definedProps = props ?? {};
|
|
2498
|
+
const make = definedProps["make"];
|
|
2327
2499
|
const ctors = [];
|
|
2328
|
-
if (make) {
|
|
2500
|
+
if (typeof make === "function") {
|
|
2329
2501
|
ctors.push(make);
|
|
2330
2502
|
}
|
|
2331
2503
|
const ParentView = this;
|
|
2332
2504
|
const ChildView = class extends ParentView {
|
|
2333
2505
|
constructor(nodeId, ownerFrame, initParams, node, mixinCtors) {
|
|
2334
2506
|
super(nodeId, ownerFrame, initParams, node, []);
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2507
|
+
const instanceProps = this;
|
|
2508
|
+
for (const key in definedProps) {
|
|
2509
|
+
if (hasOwnProperty(definedProps, key) && key !== "make" && key !== "render") {
|
|
2510
|
+
instanceProps[key] = definedProps[key];
|
|
2338
2511
|
}
|
|
2339
2512
|
}
|
|
2340
2513
|
this.id = nodeId;
|
|
@@ -2354,56 +2527,110 @@ var View = class _View {
|
|
|
2354
2527
|
}
|
|
2355
2528
|
};
|
|
2356
2529
|
const proto = ChildView.prototype;
|
|
2357
|
-
for (const key in
|
|
2358
|
-
if (
|
|
2359
|
-
proto[key] =
|
|
2530
|
+
for (const key in definedProps) {
|
|
2531
|
+
if (hasOwnProperty(definedProps, key) && key !== "make") {
|
|
2532
|
+
proto[key] = definedProps[key];
|
|
2360
2533
|
}
|
|
2361
2534
|
}
|
|
2362
2535
|
if (statics) {
|
|
2536
|
+
const staticTarget = ChildView;
|
|
2363
2537
|
for (const key in statics) {
|
|
2364
|
-
if (
|
|
2365
|
-
|
|
2538
|
+
if (hasOwnProperty(statics, key)) {
|
|
2539
|
+
staticTarget[key] = statics[key];
|
|
2366
2540
|
}
|
|
2367
2541
|
}
|
|
2368
2542
|
}
|
|
2369
|
-
ChildView.merge = viewMerge;
|
|
2370
|
-
ChildView.extend = _View.extend;
|
|
2371
2543
|
return ChildView;
|
|
2372
2544
|
}
|
|
2373
2545
|
/**
|
|
2374
2546
|
* Merge mixins into View prototype.
|
|
2375
2547
|
*/
|
|
2376
2548
|
static merge(...mixins) {
|
|
2377
|
-
const
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
return self;
|
|
2549
|
+
const existingCtors = this.ctors || [];
|
|
2550
|
+
_View.mergeMixins(mixins, this, existingCtors);
|
|
2551
|
+
return this;
|
|
2381
2552
|
}
|
|
2382
2553
|
};
|
|
2383
|
-
function
|
|
2384
|
-
|
|
2385
|
-
const existingCtors = self.ctors || [];
|
|
2386
|
-
viewMergeMixins(mixins, self, existingCtors);
|
|
2387
|
-
return self;
|
|
2554
|
+
function defineView(props, statics) {
|
|
2555
|
+
return View.extend(props, statics);
|
|
2388
2556
|
}
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
}
|
|
2557
|
+
|
|
2558
|
+
// src/module-loader.ts
|
|
2559
|
+
var config = {
|
|
2560
|
+
rootId: "root",
|
|
2561
|
+
hashbang: "#!",
|
|
2562
|
+
error: (error) => {
|
|
2563
|
+
throw error;
|
|
2397
2564
|
}
|
|
2565
|
+
};
|
|
2566
|
+
function use(names, callback) {
|
|
2567
|
+
const nameList = typeof names === "string" ? [names] : names;
|
|
2568
|
+
const loadPromise = (() => {
|
|
2569
|
+
if (config.require) {
|
|
2570
|
+
const result = config.require(nameList);
|
|
2571
|
+
if (result && typeof result.then === "function") {
|
|
2572
|
+
return result;
|
|
2573
|
+
}
|
|
2574
|
+
return Promise.resolve([]);
|
|
2575
|
+
}
|
|
2576
|
+
return Promise.all(
|
|
2577
|
+
nameList.map((name) => {
|
|
2578
|
+
const importPath = name.startsWith(".") || name.startsWith("/") ? name : `./${name}`;
|
|
2579
|
+
return import(
|
|
2580
|
+
/* @vite-ignore */
|
|
2581
|
+
/* webpackIgnore: true */
|
|
2582
|
+
importPath
|
|
2583
|
+
).then((mod) => {
|
|
2584
|
+
return mod && (mod["__esModule"] || // For Webpack
|
|
2585
|
+
typeof mod["default"] === "function") ? mod["default"] : mod;
|
|
2586
|
+
}).catch((err) => {
|
|
2587
|
+
const errorHandler = config.error;
|
|
2588
|
+
if (errorHandler) {
|
|
2589
|
+
errorHandler(err instanceof Error ? err : new Error(String(err)));
|
|
2590
|
+
}
|
|
2591
|
+
return void 0;
|
|
2592
|
+
});
|
|
2593
|
+
})
|
|
2594
|
+
);
|
|
2595
|
+
})();
|
|
2596
|
+
if (callback) {
|
|
2597
|
+
loadPromise.then((modules) => {
|
|
2598
|
+
callback(...modules);
|
|
2599
|
+
});
|
|
2600
|
+
}
|
|
2601
|
+
return loadPromise;
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
// src/view-registry.ts
|
|
2605
|
+
var viewClassRegistry = {};
|
|
2606
|
+
function getViewClass(path) {
|
|
2607
|
+
return viewClassRegistry[path];
|
|
2608
|
+
}
|
|
2609
|
+
function registerViewClass(viewPath, ViewClass) {
|
|
2610
|
+
const parsed = parseUri(viewPath);
|
|
2611
|
+
const path = parsed.path;
|
|
2612
|
+
if (path) {
|
|
2613
|
+
viewClassRegistry[path] = ViewClass;
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
function invalidateViewClass(viewPath) {
|
|
2617
|
+
const parsed = parseUri(viewPath);
|
|
2618
|
+
const path = parsed.path;
|
|
2619
|
+
if (path) {
|
|
2620
|
+
Reflect.deleteProperty(viewClassRegistry, path);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
function getViewClassRegistry() {
|
|
2624
|
+
return viewClassRegistry;
|
|
2398
2625
|
}
|
|
2399
2626
|
|
|
2400
2627
|
// src/frame.ts
|
|
2401
2628
|
var frameRegistry = /* @__PURE__ */ new Map();
|
|
2402
2629
|
var rootFrame;
|
|
2403
2630
|
var globalAlter;
|
|
2631
|
+
var MAX_FRAME_POOL = 64;
|
|
2404
2632
|
var frameCache = [];
|
|
2405
2633
|
var staticEmitter = new EventEmitter();
|
|
2406
|
-
var viewClassRegistry = {};
|
|
2407
2634
|
var Frame = class _Frame extends EventEmitter {
|
|
2408
2635
|
/** Frame ID (same as owner DOM element ID) */
|
|
2409
2636
|
id;
|
|
@@ -2418,8 +2645,8 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2418
2645
|
childrenCount = 0;
|
|
2419
2646
|
/** Ready count (children that have fired 'created') */
|
|
2420
2647
|
readyCount = 0;
|
|
2421
|
-
/**
|
|
2422
|
-
readyMap =
|
|
2648
|
+
/** Set of child frame IDs that have fired 'created' */
|
|
2649
|
+
readyMap = /* @__PURE__ */ new Set();
|
|
2423
2650
|
/** View instance */
|
|
2424
2651
|
viewInstance;
|
|
2425
2652
|
/** Get view instance (read-only) */
|
|
@@ -2490,31 +2717,42 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2490
2717
|
this.viewPath = viewPath;
|
|
2491
2718
|
const params = parsed["params"];
|
|
2492
2719
|
translateQuery(pId || this.id, viewPath, params);
|
|
2720
|
+
const initParams = { ...params };
|
|
2493
2721
|
if (viewInitParams) {
|
|
2494
|
-
assign(
|
|
2722
|
+
assign(initParams, viewInitParams);
|
|
2495
2723
|
}
|
|
2496
2724
|
const sign = this.signature;
|
|
2497
|
-
|
|
2498
|
-
|
|
2725
|
+
const registered = getViewClass(viewClassName);
|
|
2726
|
+
if (registered) {
|
|
2727
|
+
this.doMountView(registered, initParams, node, sign);
|
|
2728
|
+
return;
|
|
2499
2729
|
}
|
|
2730
|
+
use(viewClassName, (ViewClass) => {
|
|
2731
|
+
if (sign !== this.signature) return;
|
|
2732
|
+
if (typeof ViewClass === "function") {
|
|
2733
|
+
const ViewClassTyped = ViewClass;
|
|
2734
|
+
registerViewClass(viewClassName, ViewClassTyped);
|
|
2735
|
+
this.doMountView(ViewClassTyped, initParams, node, sign);
|
|
2736
|
+
} else {
|
|
2737
|
+
const error = new Error(`Cannot load view: ${viewClassName}`);
|
|
2738
|
+
const errorHandler = config.error;
|
|
2739
|
+
if (errorHandler) {
|
|
2740
|
+
errorHandler(error);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
});
|
|
2500
2744
|
}
|
|
2501
2745
|
/**
|
|
2502
2746
|
* Internal: actually mount the view after class is loaded.
|
|
2503
2747
|
*/
|
|
2504
2748
|
doMountView(ViewClass, params, node, sign) {
|
|
2505
2749
|
if (sign !== this.signature) return;
|
|
2506
|
-
const mixinCtors =
|
|
2507
|
-
const
|
|
2508
|
-
const view = new
|
|
2509
|
-
this.id,
|
|
2510
|
-
this,
|
|
2511
|
-
params,
|
|
2512
|
-
node,
|
|
2513
|
-
mixinCtors
|
|
2514
|
-
);
|
|
2750
|
+
const mixinCtors = View.prepare(ViewClass);
|
|
2751
|
+
const Ctor = ViewClass;
|
|
2752
|
+
const view = new Ctor(this.id, this, params, node, mixinCtors);
|
|
2515
2753
|
this.viewInstance = view;
|
|
2516
2754
|
view.signature = 1;
|
|
2517
|
-
|
|
2755
|
+
View.delegateEvents(view);
|
|
2518
2756
|
const initResult = funcWithTry(
|
|
2519
2757
|
view.init,
|
|
2520
2758
|
[params, { node, deep: !view.template }],
|
|
@@ -2525,13 +2763,10 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2525
2763
|
Promise.resolve(initResult).then(() => {
|
|
2526
2764
|
if (nextSign !== this.signature) return;
|
|
2527
2765
|
if (view.template) {
|
|
2528
|
-
|
|
2529
|
-
if (renderFn) {
|
|
2530
|
-
renderFn.call(view);
|
|
2531
|
-
}
|
|
2766
|
+
view.render();
|
|
2532
2767
|
} else {
|
|
2533
2768
|
this.hasAltered = 0;
|
|
2534
|
-
if (!view
|
|
2769
|
+
if (!view.endUpdatePendingFlag) {
|
|
2535
2770
|
view.endUpdate();
|
|
2536
2771
|
}
|
|
2537
2772
|
}
|
|
@@ -2595,7 +2830,9 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2595
2830
|
frame.unmountView();
|
|
2596
2831
|
removeFrame(targetId, wasCreated);
|
|
2597
2832
|
reInitFrameForCache(frame);
|
|
2598
|
-
frameCache.
|
|
2833
|
+
if (frameCache.length < MAX_FRAME_POOL) {
|
|
2834
|
+
frameCache.push(frame);
|
|
2835
|
+
}
|
|
2599
2836
|
const parent = frameRegistry.get(pId || "");
|
|
2600
2837
|
if (parent && parent.childrenMap[targetId]) {
|
|
2601
2838
|
Reflect.deleteProperty(parent.childrenMap, targetId);
|
|
@@ -2614,13 +2851,12 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2614
2851
|
const viewElements = rootEl.querySelectorAll(`[${LARK_VIEW}]`);
|
|
2615
2852
|
const frames = [];
|
|
2616
2853
|
viewElements.forEach((el) => {
|
|
2617
|
-
|
|
2618
|
-
if (
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
}
|
|
2854
|
+
if (!(el instanceof HTMLElement)) return;
|
|
2855
|
+
if (htmlElIsBound(el)) return;
|
|
2856
|
+
const elId = ensureElementId2(el);
|
|
2857
|
+
el.frameBound = 1;
|
|
2858
|
+
const viewPath = getAttribute(el, LARK_VIEW);
|
|
2859
|
+
frames.push([elId, viewPath]);
|
|
2624
2860
|
});
|
|
2625
2861
|
for (const [frameId, viewPath] of frames) {
|
|
2626
2862
|
this.mountFrame(frameId, viewPath);
|
|
@@ -2633,7 +2869,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2633
2869
|
*/
|
|
2634
2870
|
unmountZone(zoneId, _inner) {
|
|
2635
2871
|
for (const childId in this.childrenMap) {
|
|
2636
|
-
if (
|
|
2872
|
+
if (hasOwnProperty(this.childrenMap, childId)) {
|
|
2637
2873
|
if (!zoneId || childId !== zoneId) {
|
|
2638
2874
|
this.unmountFrame(childId);
|
|
2639
2875
|
}
|
|
@@ -2647,7 +2883,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2647
2883
|
children() {
|
|
2648
2884
|
const result = [];
|
|
2649
2885
|
for (const id in this.childrenMap) {
|
|
2650
|
-
if (
|
|
2886
|
+
if (hasOwnProperty(this.childrenMap, id)) {
|
|
2651
2887
|
result.push(id);
|
|
2652
2888
|
}
|
|
2653
2889
|
}
|
|
@@ -2674,14 +2910,10 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2674
2910
|
let result;
|
|
2675
2911
|
const view = this.view;
|
|
2676
2912
|
if (view && view.rendered) {
|
|
2677
|
-
const
|
|
2913
|
+
const lookup = view;
|
|
2914
|
+
const fn = lookup[name];
|
|
2678
2915
|
if (typeof fn === "function") {
|
|
2679
|
-
result = funcWithTry(
|
|
2680
|
-
fn,
|
|
2681
|
-
args || [],
|
|
2682
|
-
view,
|
|
2683
|
-
noop
|
|
2684
|
-
);
|
|
2916
|
+
result = funcWithTry(fn, args || [], view, noop);
|
|
2685
2917
|
}
|
|
2686
2918
|
} else {
|
|
2687
2919
|
const key = SPLITTER + name;
|
|
@@ -2704,6 +2936,25 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2704
2936
|
}
|
|
2705
2937
|
return result;
|
|
2706
2938
|
}
|
|
2939
|
+
/**
|
|
2940
|
+
* Type-safe variant of `invoke`.
|
|
2941
|
+
*
|
|
2942
|
+
* `invoke()` accepts any string and any args, which silently hides
|
|
2943
|
+
* mismatched call sites when a method gets renamed. `invokeTyped` carries
|
|
2944
|
+
* the view's method signature through TypeScript so the compiler catches
|
|
2945
|
+
* those mistakes:
|
|
2946
|
+
*
|
|
2947
|
+
* ```ts
|
|
2948
|
+
* type Home = View & { loadData(id: string): Promise<void> };
|
|
2949
|
+
* frame.invokeTyped<Home, "loadData">("loadData", ["user-1"]);
|
|
2950
|
+
* ```
|
|
2951
|
+
*
|
|
2952
|
+
* Behavior is identical to `invoke` at runtime — same defer / direct-call
|
|
2953
|
+
* paths — so it's a drop-in safer overload.
|
|
2954
|
+
*/
|
|
2955
|
+
invokeTyped(name, args) {
|
|
2956
|
+
return this.invoke(name, args);
|
|
2957
|
+
}
|
|
2707
2958
|
// ============================================================
|
|
2708
2959
|
// Static methods
|
|
2709
2960
|
// ============================================================
|
|
@@ -2715,10 +2966,27 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2715
2966
|
static getAll() {
|
|
2716
2967
|
return frameRegistry;
|
|
2717
2968
|
}
|
|
2718
|
-
/**
|
|
2719
|
-
|
|
2969
|
+
/**
|
|
2970
|
+
* Returns the existing root frame, or `undefined` if none has been created.
|
|
2971
|
+
* Pure getter — never creates a Frame, never touches the DOM.
|
|
2972
|
+
*
|
|
2973
|
+
* Use `Frame.createRoot(id)` to create the root explicitly during framework
|
|
2974
|
+
* boot. For Micro-Frontend hosts that own multiple independent containers,
|
|
2975
|
+
* use `new Frame(containerId)` directly so each MF mount has its own root.
|
|
2976
|
+
*/
|
|
2977
|
+
static getRoot() {
|
|
2978
|
+
return rootFrame;
|
|
2979
|
+
}
|
|
2980
|
+
/**
|
|
2981
|
+
* Create (or return) the singleton root frame for this app.
|
|
2982
|
+
*
|
|
2983
|
+
* Idempotent: subsequent calls always return the original root regardless
|
|
2984
|
+
* of `rootId` — so passing a different id later is silently ignored.
|
|
2985
|
+
* `Framework.boot()` is the canonical caller; user code rarely needs this.
|
|
2986
|
+
*/
|
|
2987
|
+
static createRoot(rootId) {
|
|
2720
2988
|
if (!rootFrame) {
|
|
2721
|
-
rootId = rootId || "
|
|
2989
|
+
rootId = rootId || "root";
|
|
2722
2990
|
let rootElement = document.getElementById(rootId);
|
|
2723
2991
|
if (!rootElement) {
|
|
2724
2992
|
rootElement = document.body;
|
|
@@ -2728,6 +2996,17 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2728
2996
|
}
|
|
2729
2997
|
return rootFrame;
|
|
2730
2998
|
}
|
|
2999
|
+
/**
|
|
3000
|
+
* @deprecated Use `Frame.getRoot()` for read-only access or
|
|
3001
|
+
* `Frame.createRoot(id)` to create the root explicitly. The single-method
|
|
3002
|
+
* `root()` blurred the distinction and was a common source of bugs in
|
|
3003
|
+
* Micro-Frontend hosts.
|
|
3004
|
+
*
|
|
3005
|
+
* Kept for backward compatibility — behavior unchanged.
|
|
3006
|
+
*/
|
|
3007
|
+
static root(rootId) {
|
|
3008
|
+
return _Frame.createRoot(rootId);
|
|
3009
|
+
}
|
|
2731
3010
|
/** Bind event listener (static) */
|
|
2732
3011
|
static on(event, handler) {
|
|
2733
3012
|
staticEmitter.on(event, handler);
|
|
@@ -2743,6 +3022,9 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2743
3022
|
staticEmitter.fire(event, data);
|
|
2744
3023
|
}
|
|
2745
3024
|
};
|
|
3025
|
+
function htmlElIsBound(element) {
|
|
3026
|
+
return !!element.frameBound;
|
|
3027
|
+
}
|
|
2746
3028
|
function ensureElementId2(element) {
|
|
2747
3029
|
const id = element.getAttribute("id");
|
|
2748
3030
|
if (id) return id;
|
|
@@ -2772,8 +3054,8 @@ function notifyCreated(frameInstance) {
|
|
|
2772
3054
|
const pId = frameInstance.parentId;
|
|
2773
3055
|
if (pId) {
|
|
2774
3056
|
const parent = frameRegistry.get(pId);
|
|
2775
|
-
if (parent && !parent.readyMap
|
|
2776
|
-
parent.readyMap
|
|
3057
|
+
if (parent && !parent.readyMap.has(frameInstance.id)) {
|
|
3058
|
+
parent.readyMap.add(frameInstance.id);
|
|
2777
3059
|
parent.readyCount++;
|
|
2778
3060
|
notifyCreated(parent);
|
|
2779
3061
|
}
|
|
@@ -2788,9 +3070,9 @@ function notifyAlter(frameInstance, data) {
|
|
|
2788
3070
|
const pId = frameInstance.parentId;
|
|
2789
3071
|
if (pId) {
|
|
2790
3072
|
const parent = frameRegistry.get(pId);
|
|
2791
|
-
if (parent && parent.readyMap
|
|
3073
|
+
if (parent && parent.readyMap.has(frameInstance.id)) {
|
|
2792
3074
|
parent.readyCount--;
|
|
2793
|
-
|
|
3075
|
+
parent.readyMap.delete(frameInstance.id);
|
|
2794
3076
|
notifyAlter(parent, data);
|
|
2795
3077
|
}
|
|
2796
3078
|
}
|
|
@@ -2803,7 +3085,7 @@ function reInitFrame(frame, id, parentId) {
|
|
|
2803
3085
|
frame["childrenCount"] = 0;
|
|
2804
3086
|
frame["readyCount"] = 0;
|
|
2805
3087
|
frame["signature"] = 1;
|
|
2806
|
-
frame["readyMap"] =
|
|
3088
|
+
frame["readyMap"] = /* @__PURE__ */ new Set();
|
|
2807
3089
|
frame["invokeList"] = [];
|
|
2808
3090
|
frameRegistry.set(id, frame);
|
|
2809
3091
|
}
|
|
@@ -2811,7 +3093,7 @@ function reInitFrameForCache(frame) {
|
|
|
2811
3093
|
Reflect.set(frame, "id", "");
|
|
2812
3094
|
frame["_parentId"] = void 0;
|
|
2813
3095
|
frame["childrenMap"] = {};
|
|
2814
|
-
frame["readyMap"] =
|
|
3096
|
+
frame["readyMap"] = /* @__PURE__ */ new Set();
|
|
2815
3097
|
}
|
|
2816
3098
|
function translateQuery(pId, src, params) {
|
|
2817
3099
|
const parentFrame = frameRegistry.get(pId);
|
|
@@ -2821,37 +3103,153 @@ function translateQuery(pId, src, params) {
|
|
|
2821
3103
|
if (!parentRefData) return;
|
|
2822
3104
|
if (src.indexOf(SPLITTER) > 0) {
|
|
2823
3105
|
translateData(parentRefData, params);
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
);
|
|
3106
|
+
const paramsRec = params;
|
|
3107
|
+
const splitterValue = paramsRec[SPLITTER];
|
|
3108
|
+
if (splitterValue && typeof splitterValue === "object") {
|
|
3109
|
+
assign(params, splitterValue);
|
|
2829
3110
|
Reflect.deleteProperty(params, SPLITTER);
|
|
2830
3111
|
}
|
|
2831
3112
|
}
|
|
2832
3113
|
}
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
3114
|
+
|
|
3115
|
+
// src/cross-site.ts
|
|
3116
|
+
var preparePromises = {};
|
|
3117
|
+
var projectsMap = null;
|
|
3118
|
+
function loadRemoteView(viewPath, bizCode) {
|
|
3119
|
+
const crossConfigs = config.crossConfigs || window.crossConfigs;
|
|
3120
|
+
const currentName = config.projectName || "";
|
|
3121
|
+
const slashIndex = viewPath.indexOf("/");
|
|
3122
|
+
const projectName = slashIndex > -1 ? viewPath.substring(0, slashIndex) : viewPath;
|
|
3123
|
+
if (projectName === currentName) return Promise.resolve();
|
|
3124
|
+
if (!preparePromises[projectName]) {
|
|
3125
|
+
if (!projectsMap) {
|
|
3126
|
+
const map = toMap(crossConfigs || [], "projectName");
|
|
3127
|
+
projectsMap = map;
|
|
3128
|
+
}
|
|
3129
|
+
const info = projectsMap[projectName];
|
|
3130
|
+
if (!info) {
|
|
3131
|
+
return Promise.reject(
|
|
3132
|
+
new Error(`Cannot find ${projectName} from crossConfigs`)
|
|
3133
|
+
);
|
|
3134
|
+
}
|
|
3135
|
+
preparePromises[projectName] = use(`${projectName}/prepare`).then((modules) => {
|
|
3136
|
+
let mod = modules[0];
|
|
3137
|
+
if (mod && typeof mod === "object" && mod !== null) {
|
|
3138
|
+
const rec = mod;
|
|
3139
|
+
if (rec["__esModule"]) {
|
|
3140
|
+
mod = rec["default"];
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
if (typeof mod === "function") {
|
|
3144
|
+
return mod({ bizCode });
|
|
3145
|
+
}
|
|
3146
|
+
return void 0;
|
|
3147
|
+
}).catch((err) => {
|
|
3148
|
+
Reflect.deleteProperty(preparePromises, projectName);
|
|
3149
|
+
throw err;
|
|
3150
|
+
});
|
|
2838
3151
|
}
|
|
3152
|
+
return preparePromises[projectName];
|
|
3153
|
+
}
|
|
3154
|
+
function resetProjectsMap() {
|
|
3155
|
+
projectsMap = null;
|
|
2839
3156
|
}
|
|
3157
|
+
var skeletonTemplate = (data, viewId) => {
|
|
3158
|
+
let skeletonHtml = "<div>Loading...</div>";
|
|
3159
|
+
if (data && typeof data === "object") {
|
|
3160
|
+
const candidate = data.skeleton;
|
|
3161
|
+
if (typeof candidate === "string") skeletonHtml = candidate;
|
|
3162
|
+
}
|
|
3163
|
+
return `<div id="mf_${viewId}">${skeletonHtml}</div>`;
|
|
3164
|
+
};
|
|
3165
|
+
var CrossSite = View.extend({
|
|
3166
|
+
/** Skeleton template renders loading state + child container */
|
|
3167
|
+
template: skeletonTemplate,
|
|
3168
|
+
init(params) {
|
|
3169
|
+
this.$sign = 0;
|
|
3170
|
+
this.on("destroy", () => {
|
|
3171
|
+
this.$sign = -1;
|
|
3172
|
+
});
|
|
3173
|
+
this.assign?.(params);
|
|
3174
|
+
},
|
|
3175
|
+
assign(data) {
|
|
3176
|
+
this.$view = typeof data["view"] === "string" ? data["view"] : "";
|
|
3177
|
+
const nested = data["params"];
|
|
3178
|
+
const nestedParams = nested && typeof nested === "object" ? nested : {};
|
|
3179
|
+
this.$params = { ...data, ...nestedParams };
|
|
3180
|
+
this.updater.set({
|
|
3181
|
+
skeleton: data["skeleton"],
|
|
3182
|
+
skeletonParams: data["skeletonParams"] || {},
|
|
3183
|
+
bizCode: data["bizCode"]
|
|
3184
|
+
});
|
|
3185
|
+
if (this.$sign > 0) {
|
|
3186
|
+
this.updateView();
|
|
3187
|
+
}
|
|
3188
|
+
return false;
|
|
3189
|
+
},
|
|
3190
|
+
async updateView() {
|
|
3191
|
+
const sign = ++this.$sign;
|
|
3192
|
+
const stored = this.updater.get();
|
|
3193
|
+
const bizCode = stored.bizCode;
|
|
3194
|
+
try {
|
|
3195
|
+
await loadRemoteView(this.$view, bizCode);
|
|
3196
|
+
} catch (ex) {
|
|
3197
|
+
const node = document.getElementById("mf_" + this.id);
|
|
3198
|
+
if (node) {
|
|
3199
|
+
const err = ex instanceof Error ? ex : new Error(String(ex));
|
|
3200
|
+
node.innerHTML = err.message || String(err);
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
if (this.$sign !== sign) return;
|
|
3204
|
+
const mf = Frame.get("mf_" + this.id);
|
|
3205
|
+
const parsedNew = parseUri(this.$view);
|
|
3206
|
+
const newPath = parsedNew.path;
|
|
3207
|
+
const oldPath = mf?.viewPath ? parseUri(mf.viewPath).path : "";
|
|
3208
|
+
const view = mf?.view;
|
|
3209
|
+
if (newPath === oldPath && view && typeof view.assign === "function") {
|
|
3210
|
+
const result = funcWithTry(view.assign, [this.$params], view, noop);
|
|
3211
|
+
if (result) {
|
|
3212
|
+
view.render();
|
|
3213
|
+
}
|
|
3214
|
+
return;
|
|
3215
|
+
}
|
|
3216
|
+
const owner = this.owner;
|
|
3217
|
+
if (owner && typeof owner !== "number") {
|
|
3218
|
+
owner.mountFrame("mf_" + this.id, this.$view, this.$params);
|
|
3219
|
+
}
|
|
3220
|
+
},
|
|
3221
|
+
render() {
|
|
3222
|
+
const params = this.$params;
|
|
3223
|
+
this.updater.digest({
|
|
3224
|
+
skeleton: params?.["skeleton"]
|
|
3225
|
+
});
|
|
3226
|
+
this.updateView();
|
|
3227
|
+
},
|
|
3228
|
+
/**
|
|
3229
|
+
* Invoke a method on the remote view.
|
|
3230
|
+
* Usage: mf.invoke('callView', methodName, ...args)
|
|
3231
|
+
*/
|
|
3232
|
+
callView(name, ...args) {
|
|
3233
|
+
const mf = Frame.get("mf_" + this.id);
|
|
3234
|
+
return mf?.invoke(name, args);
|
|
3235
|
+
}
|
|
3236
|
+
});
|
|
3237
|
+
var cross_site_default = CrossSite;
|
|
2840
3238
|
|
|
2841
3239
|
// src/service.ts
|
|
2842
|
-
var
|
|
2843
|
-
/**
|
|
3240
|
+
var Payload = class {
|
|
3241
|
+
/** Payload data */
|
|
2844
3242
|
data;
|
|
2845
3243
|
/** Internal cache info */
|
|
2846
3244
|
cacheInfo;
|
|
2847
3245
|
constructor(data = {}) {
|
|
2848
3246
|
this.data = data;
|
|
2849
3247
|
}
|
|
2850
|
-
/** Get a value from
|
|
3248
|
+
/** Get a value from payload data */
|
|
2851
3249
|
get(key) {
|
|
2852
3250
|
return this.data[key];
|
|
2853
3251
|
}
|
|
2854
|
-
/** Set a value in
|
|
3252
|
+
/** Set a value in payload data */
|
|
2855
3253
|
set(keyOrData, value) {
|
|
2856
3254
|
if (typeof keyOrData === "string") {
|
|
2857
3255
|
this.data[keyOrData] = value;
|
|
@@ -2863,297 +3261,398 @@ var Bag = class {
|
|
|
2863
3261
|
};
|
|
2864
3262
|
var FETCH_FLAGS_ALL = 1;
|
|
2865
3263
|
var FETCH_FLAGS_ONE = 2;
|
|
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
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
3264
|
+
var Service = class {
|
|
3265
|
+
/** Service instance ID */
|
|
3266
|
+
id = "";
|
|
3267
|
+
/** Whether service is busy (1 = busy) */
|
|
3268
|
+
busy = 0;
|
|
3269
|
+
/** Whether service is destroyed (1 = destroyed) */
|
|
3270
|
+
destroyed = 0;
|
|
3271
|
+
/** Task queue for sequential operations */
|
|
3272
|
+
taskQueue = [];
|
|
3273
|
+
/** Previous dequeue arguments */
|
|
3274
|
+
prevArgs = [];
|
|
3275
|
+
/** Instance event emitter */
|
|
3276
|
+
_emitter = new EventEmitter();
|
|
3277
|
+
constructor() {
|
|
3278
|
+
this.id = generateId("service");
|
|
3279
|
+
}
|
|
3280
|
+
// ============================================================
|
|
3281
|
+
// Instance accessors for type-level data
|
|
3282
|
+
// ============================================================
|
|
3283
|
+
/** Instance event emitter (public accessor) */
|
|
3284
|
+
get emitter() {
|
|
3285
|
+
return this._emitter;
|
|
3286
|
+
}
|
|
3287
|
+
/**
|
|
3288
|
+
* Get internals object for serviceSend compatibility.
|
|
3289
|
+
* References per-type static state from the current class.
|
|
3290
|
+
*/
|
|
3291
|
+
get internals() {
|
|
3292
|
+
const ctor = this.constructor;
|
|
3293
|
+
return {
|
|
3294
|
+
metaList: ctor._metaList,
|
|
3295
|
+
payloadCache: ctor._payloadCache,
|
|
3296
|
+
pendingCacheKeys: ctor._pendingCacheKeys,
|
|
3297
|
+
syncFn: ctor._syncFn,
|
|
3298
|
+
staticEmitter: ctor._staticEmitter
|
|
3299
|
+
};
|
|
3300
|
+
}
|
|
3301
|
+
/**
|
|
3302
|
+
* Get type reference (the constructor) for serviceSend compatibility.
|
|
3303
|
+
* Static methods like get/create are accessible via the constructor.
|
|
3304
|
+
*/
|
|
3305
|
+
get type() {
|
|
3306
|
+
return this.constructor;
|
|
3307
|
+
}
|
|
3308
|
+
// ============================================================
|
|
3309
|
+
// Instance methods
|
|
3310
|
+
// ============================================================
|
|
3311
|
+
/**
|
|
3312
|
+
* Fetch all endpoints, callback when all complete.
|
|
3313
|
+
* Uses cache when available.
|
|
3314
|
+
*/
|
|
3315
|
+
all(attrs, done) {
|
|
3316
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
3317
|
+
return this;
|
|
3318
|
+
}
|
|
3319
|
+
/**
|
|
3320
|
+
* Fetch all endpoints, callback on each completion.
|
|
3321
|
+
*/
|
|
3322
|
+
one(attrs, done) {
|
|
3323
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
3324
|
+
return this;
|
|
3325
|
+
}
|
|
3326
|
+
/**
|
|
3327
|
+
* Fetch all endpoints, skip cache (always request).
|
|
3328
|
+
*/
|
|
3329
|
+
save(attrs, done) {
|
|
3330
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
3331
|
+
return this;
|
|
3332
|
+
}
|
|
3333
|
+
/**
|
|
3334
|
+
* Enqueue a task for sequential execution.
|
|
3335
|
+
*/
|
|
3336
|
+
enqueue(callback) {
|
|
3337
|
+
if (!this.destroyed) {
|
|
3338
|
+
this.taskQueue.push(callback);
|
|
3339
|
+
this.dequeue(...this.prevArgs);
|
|
3340
|
+
}
|
|
3341
|
+
return this;
|
|
3342
|
+
}
|
|
3343
|
+
/**
|
|
3344
|
+
* Dequeue and execute the next task in queue.
|
|
3345
|
+
*/
|
|
3346
|
+
dequeue(...args) {
|
|
3347
|
+
if (!this.busy && !this.destroyed) {
|
|
3348
|
+
this.busy = 1;
|
|
3349
|
+
setTimeout(() => {
|
|
3350
|
+
this.busy = 0;
|
|
3351
|
+
if (!this.destroyed) {
|
|
3352
|
+
const task2 = this.taskQueue.shift();
|
|
3353
|
+
if (task2) {
|
|
3354
|
+
this.prevArgs = args;
|
|
3355
|
+
funcWithTry(task2, args, this, noop);
|
|
2943
3356
|
}
|
|
2944
|
-
return cached;
|
|
2945
3357
|
}
|
|
3358
|
+
}, 0);
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
/**
|
|
3362
|
+
* Destroy the service instance.
|
|
3363
|
+
* After destruction, no new requests can be sent.
|
|
3364
|
+
*/
|
|
3365
|
+
destroy() {
|
|
3366
|
+
this.destroyed = 1;
|
|
3367
|
+
this.taskQueue = [];
|
|
3368
|
+
}
|
|
3369
|
+
// Instance event methods (delegate to instance emitter)
|
|
3370
|
+
on(event, handler) {
|
|
3371
|
+
this._emitter.on(event, handler);
|
|
3372
|
+
return this;
|
|
3373
|
+
}
|
|
3374
|
+
off(event, handler) {
|
|
3375
|
+
this._emitter.off(event, handler);
|
|
3376
|
+
return this;
|
|
3377
|
+
}
|
|
3378
|
+
fire(event, data) {
|
|
3379
|
+
this._emitter.fire(event, data);
|
|
3380
|
+
return this;
|
|
3381
|
+
}
|
|
3382
|
+
// ============================================================
|
|
3383
|
+
// Per-type static state
|
|
3384
|
+
// ============================================================
|
|
3385
|
+
/** Per-type metadata registry */
|
|
3386
|
+
static _metaList = {};
|
|
3387
|
+
/** Per-type payload cache (LFU with frequency eviction) */
|
|
3388
|
+
static _payloadCache = new Cache({
|
|
3389
|
+
maxSize: 20,
|
|
3390
|
+
bufferSize: 5
|
|
3391
|
+
});
|
|
3392
|
+
/** Per-type pending cache keys for deduplication */
|
|
3393
|
+
static _pendingCacheKeys = {};
|
|
3394
|
+
/** Per-type sync function */
|
|
3395
|
+
static _syncFn = noop;
|
|
3396
|
+
/** Per-type static event emitter */
|
|
3397
|
+
static _staticEmitter = new EventEmitter();
|
|
3398
|
+
/** Per-type cache max size */
|
|
3399
|
+
static _cacheMax = 20;
|
|
3400
|
+
/** Per-type cache buffer size */
|
|
3401
|
+
static _cacheBuffer = 5;
|
|
3402
|
+
// ============================================================
|
|
3403
|
+
// Static methods (operate on per-type state via `this`)
|
|
3404
|
+
// ============================================================
|
|
3405
|
+
/**
|
|
3406
|
+
* Register API endpoint metadata.
|
|
3407
|
+
*/
|
|
3408
|
+
static add(attrs) {
|
|
3409
|
+
if (!Array.isArray(attrs)) {
|
|
3410
|
+
attrs = [attrs];
|
|
3411
|
+
}
|
|
3412
|
+
for (const payload of attrs) {
|
|
3413
|
+
if (payload) {
|
|
3414
|
+
const name = payload.name;
|
|
3415
|
+
const cache = payload.cache;
|
|
3416
|
+
payload.cache = cache ? cache | 0 : 0;
|
|
3417
|
+
this._metaList[name] = payload;
|
|
2946
3418
|
}
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
/**
|
|
3422
|
+
* Get metadata for an API endpoint.
|
|
3423
|
+
*/
|
|
3424
|
+
static meta(attrs) {
|
|
3425
|
+
const name = typeof attrs === "string" ? attrs : String(attrs["name"] ?? "");
|
|
3426
|
+
const known = this._metaList[name];
|
|
3427
|
+
if (known) return known;
|
|
3428
|
+
return attrs;
|
|
3429
|
+
}
|
|
3430
|
+
/**
|
|
3431
|
+
* Create a Payload for an API request.
|
|
3432
|
+
*/
|
|
3433
|
+
static create(attrs) {
|
|
3434
|
+
const meta = this.meta(attrs);
|
|
3435
|
+
const cache = toCacheValue(attrs["cache"]) || meta.cache || 0;
|
|
3436
|
+
const entity = new Payload();
|
|
3437
|
+
entity.set(meta);
|
|
3438
|
+
entity.cacheInfo = {
|
|
3439
|
+
name: meta.name,
|
|
3440
|
+
after: typeof meta.after === "function" ? meta.after : void 0,
|
|
3441
|
+
cleans: typeof meta.cleanKeys === "string" ? meta.cleanKeys : void 0,
|
|
3442
|
+
key: cache ? defaultCacheKey(meta, attrs) : "",
|
|
3443
|
+
time: 0
|
|
3444
|
+
};
|
|
3445
|
+
if (attrs !== null) {
|
|
3446
|
+
entity.set(attrs);
|
|
3447
|
+
}
|
|
3448
|
+
const before = meta.before;
|
|
3449
|
+
if (typeof before === "function") {
|
|
3450
|
+
funcWithTry(before, [entity], entity, noop);
|
|
3451
|
+
}
|
|
3452
|
+
this._staticEmitter.fire("begin", { payload: entity });
|
|
3453
|
+
return entity;
|
|
3454
|
+
}
|
|
3455
|
+
/**
|
|
3456
|
+
* Get or create a Payload for an API request.
|
|
3457
|
+
*/
|
|
3458
|
+
static get(attrs, createNew) {
|
|
3459
|
+
let entity;
|
|
3460
|
+
let needsUpdate = false;
|
|
3461
|
+
if (!createNew) {
|
|
3462
|
+
entity = this.cached(attrs);
|
|
3463
|
+
}
|
|
3464
|
+
if (!entity) {
|
|
3465
|
+
entity = this.create(attrs);
|
|
3466
|
+
needsUpdate = true;
|
|
3467
|
+
}
|
|
3468
|
+
return { entity, needsUpdate };
|
|
3469
|
+
}
|
|
3470
|
+
/**
|
|
3471
|
+
* Get cached Payload if available and not expired.
|
|
3472
|
+
*/
|
|
3473
|
+
static cached(attrs) {
|
|
3474
|
+
const meta = this.meta(attrs);
|
|
3475
|
+
const cache = toCacheValue(attrs["cache"]) || meta.cache || 0;
|
|
3476
|
+
let cacheKey = "";
|
|
3477
|
+
if (cache) {
|
|
3478
|
+
cacheKey = defaultCacheKey(meta, attrs);
|
|
3479
|
+
}
|
|
3480
|
+
if (cacheKey) {
|
|
3481
|
+
const info = this._pendingCacheKeys[cacheKey];
|
|
3482
|
+
if (info) {
|
|
3483
|
+
const entity = info.entity;
|
|
3484
|
+
return entity instanceof Payload ? entity : void 0;
|
|
3485
|
+
}
|
|
3486
|
+
const cached = this._payloadCache.get(cacheKey);
|
|
3487
|
+
if (cached && cached.cacheInfo) {
|
|
3488
|
+
if (now() - cached.cacheInfo.time > cache) {
|
|
3489
|
+
this._payloadCache.del(cacheKey);
|
|
3490
|
+
return void 0;
|
|
2961
3491
|
}
|
|
2962
|
-
|
|
2963
|
-
for (const key of keysToDelete) {
|
|
2964
|
-
bagCache.del(key);
|
|
3492
|
+
return cached;
|
|
2965
3493
|
}
|
|
2966
|
-
},
|
|
2967
|
-
on(event, handler) {
|
|
2968
|
-
staticEmitter2.on(event, handler);
|
|
2969
|
-
},
|
|
2970
|
-
off(event, handler) {
|
|
2971
|
-
staticEmitter2.off(event, handler);
|
|
2972
|
-
},
|
|
2973
|
-
fire(event, data) {
|
|
2974
|
-
staticEmitter2.fire(event, data);
|
|
2975
|
-
},
|
|
2976
|
-
extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
2977
|
-
return createServiceType(
|
|
2978
|
-
newSyncFn,
|
|
2979
|
-
newCacheMax || cacheMax,
|
|
2980
|
-
newCacheBuffer || cacheBuffer
|
|
2981
|
-
);
|
|
2982
3494
|
}
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
this
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
this._emitter = new EventEmitter();
|
|
2998
|
-
this._internals = internals;
|
|
2999
|
-
this._type = serviceType;
|
|
3000
|
-
}
|
|
3001
|
-
ServiceInstance.prototype = {
|
|
3002
|
-
all(attrs, done) {
|
|
3003
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
3004
|
-
return this;
|
|
3005
|
-
},
|
|
3006
|
-
one(attrs, done) {
|
|
3007
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
3008
|
-
return this;
|
|
3009
|
-
},
|
|
3010
|
-
save(attrs, done) {
|
|
3011
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
3012
|
-
return this;
|
|
3013
|
-
},
|
|
3014
|
-
enqueue(callback) {
|
|
3015
|
-
if (!this["$d"]) {
|
|
3016
|
-
this["$g"].push(callback);
|
|
3017
|
-
this.dequeue(...this["$h"]);
|
|
3018
|
-
}
|
|
3019
|
-
return this;
|
|
3020
|
-
},
|
|
3021
|
-
dequeue(...args) {
|
|
3022
|
-
if (!this["$e"] && !this["$d"]) {
|
|
3023
|
-
this["$e"] = 1;
|
|
3024
|
-
setTimeout(() => {
|
|
3025
|
-
this["$e"] = 0;
|
|
3026
|
-
if (!this["$d"]) {
|
|
3027
|
-
const task2 = this["$g"].shift();
|
|
3028
|
-
if (task2) {
|
|
3029
|
-
this["$h"] = args;
|
|
3030
|
-
funcWithTry(task2, args, this, noop);
|
|
3031
|
-
}
|
|
3032
|
-
}
|
|
3033
|
-
}, 0);
|
|
3495
|
+
return void 0;
|
|
3496
|
+
}
|
|
3497
|
+
/**
|
|
3498
|
+
* Clear cached payloads by endpoint name.
|
|
3499
|
+
*/
|
|
3500
|
+
static clear(names) {
|
|
3501
|
+
const nameSet = new Set(
|
|
3502
|
+
(typeof names === "string" ? names : names.join(",")).split(",")
|
|
3503
|
+
);
|
|
3504
|
+
const keysToDelete = [];
|
|
3505
|
+
this._payloadCache.forEach((payload) => {
|
|
3506
|
+
const info = payload?.cacheInfo;
|
|
3507
|
+
if (info && info.key && nameSet.has(info.name)) {
|
|
3508
|
+
keysToDelete.push(info.key);
|
|
3034
3509
|
}
|
|
3035
|
-
}
|
|
3036
|
-
|
|
3037
|
-
this
|
|
3038
|
-
this["$g"] = [];
|
|
3039
|
-
},
|
|
3040
|
-
on(event, handler) {
|
|
3041
|
-
this._emitter.on(event, handler);
|
|
3042
|
-
return this;
|
|
3043
|
-
},
|
|
3044
|
-
off(event, handler) {
|
|
3045
|
-
this._emitter.off(event, handler);
|
|
3046
|
-
return this;
|
|
3047
|
-
},
|
|
3048
|
-
fire(event, data) {
|
|
3049
|
-
this._emitter.fire(event, data);
|
|
3050
|
-
return this;
|
|
3510
|
+
});
|
|
3511
|
+
for (const key of keysToDelete) {
|
|
3512
|
+
this._payloadCache.del(key);
|
|
3051
3513
|
}
|
|
3052
|
-
}
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3514
|
+
}
|
|
3515
|
+
// Static event methods (operate on per-type emitter)
|
|
3516
|
+
static on(event, handler) {
|
|
3517
|
+
this._staticEmitter.on(event, handler);
|
|
3518
|
+
}
|
|
3519
|
+
static off(event, handler) {
|
|
3520
|
+
this._staticEmitter.off(event, handler);
|
|
3521
|
+
}
|
|
3522
|
+
static fire(event, data) {
|
|
3523
|
+
this._staticEmitter.fire(event, data);
|
|
3524
|
+
}
|
|
3525
|
+
/**
|
|
3526
|
+
* Create a new Service subclass with a custom sync function.
|
|
3527
|
+
*
|
|
3528
|
+
* Each subclass gets its OWN copies of every per-type static field
|
|
3529
|
+
* (`_metaList`, `_payloadCache`, `_pendingCacheKeys`, `_syncFn`,
|
|
3530
|
+
* `_staticEmitter`, `_cacheMax`, `_cacheBuffer`) via `static override`.
|
|
3531
|
+
* This is intentional: it ensures that endpoint metadata, cache state,
|
|
3532
|
+
* in-flight dedup keys, and event subscribers are fully isolated between
|
|
3533
|
+
* different Service types, even when one extends another.
|
|
3534
|
+
*
|
|
3535
|
+
* **Do not refactor these `static override` declarations away** — sharing
|
|
3536
|
+
* them through prototype inheritance would let endpoints registered on one
|
|
3537
|
+
* subclass leak into another, and the LFU cache evictions of one type
|
|
3538
|
+
* would race with those of another.
|
|
3539
|
+
*/
|
|
3540
|
+
static extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
3541
|
+
const ParentService = this;
|
|
3542
|
+
class ChildService extends ParentService {
|
|
3543
|
+
// Intentionally per-subclass — see Service.extend doc.
|
|
3544
|
+
static _metaList = {};
|
|
3545
|
+
static _payloadCache = new Cache({
|
|
3546
|
+
maxSize: newCacheMax || ParentService._cacheMax,
|
|
3547
|
+
bufferSize: newCacheBuffer || ParentService._cacheBuffer
|
|
3548
|
+
});
|
|
3549
|
+
static _pendingCacheKeys = {};
|
|
3550
|
+
static _syncFn = newSyncFn;
|
|
3551
|
+
static _staticEmitter = new EventEmitter();
|
|
3552
|
+
static _cacheMax = newCacheMax || ParentService._cacheMax;
|
|
3553
|
+
static _cacheBuffer = newCacheBuffer || ParentService._cacheBuffer;
|
|
3554
|
+
}
|
|
3555
|
+
return ChildService;
|
|
3556
|
+
}
|
|
3557
|
+
};
|
|
3558
|
+
var metaJsonCache = /* @__PURE__ */ new WeakMap();
|
|
3559
|
+
function getMetaJson(meta) {
|
|
3560
|
+
let cached = metaJsonCache.get(meta);
|
|
3561
|
+
if (cached === void 0) {
|
|
3562
|
+
cached = JSON.stringify(meta);
|
|
3563
|
+
metaJsonCache.set(meta, cached);
|
|
3564
|
+
}
|
|
3565
|
+
return cached;
|
|
3071
3566
|
}
|
|
3072
|
-
var Service = createServiceType(noop);
|
|
3073
3567
|
function defaultCacheKey(meta, attrs) {
|
|
3074
|
-
return JSON.stringify(attrs) + SPLITTER +
|
|
3568
|
+
return JSON.stringify(attrs) + SPLITTER + getMetaJson(meta);
|
|
3569
|
+
}
|
|
3570
|
+
function toCacheValue(v) {
|
|
3571
|
+
if (typeof v === "number") return v | 0;
|
|
3572
|
+
if (typeof v === "string") {
|
|
3573
|
+
const n = Number(v);
|
|
3574
|
+
return Number.isFinite(n) ? n | 0 : 0;
|
|
3575
|
+
}
|
|
3576
|
+
return 0;
|
|
3075
3577
|
}
|
|
3076
3578
|
function serviceSend(service, attrs, done, flag, save) {
|
|
3077
|
-
if (service
|
|
3078
|
-
if (service
|
|
3079
|
-
service
|
|
3080
|
-
|
|
3081
|
-
);
|
|
3579
|
+
if (service.destroyed) return;
|
|
3580
|
+
if (service.busy) {
|
|
3581
|
+
const queued = () => serviceSend(service, attrs, done, flag, save);
|
|
3582
|
+
service.enqueue(queued);
|
|
3082
3583
|
return;
|
|
3083
3584
|
}
|
|
3084
|
-
service
|
|
3585
|
+
service.busy = 1;
|
|
3085
3586
|
let attrList;
|
|
3086
3587
|
if (typeof attrs === "string") {
|
|
3087
3588
|
attrList = [{ name: attrs }];
|
|
3088
|
-
} else if (isArray(attrs)) {
|
|
3589
|
+
} else if (Array.isArray(attrs)) {
|
|
3089
3590
|
attrList = attrs;
|
|
3090
3591
|
} else {
|
|
3091
3592
|
attrList = [attrs];
|
|
3092
3593
|
}
|
|
3093
|
-
const internals = service.
|
|
3594
|
+
const internals = service.internals;
|
|
3094
3595
|
const { syncFn, pendingCacheKeys, staticEmitter: staticEmitter2 } = internals;
|
|
3095
3596
|
let requestCount = 0;
|
|
3096
3597
|
const total = attrList.length;
|
|
3097
3598
|
const doneArr = new Array(total + 1);
|
|
3098
3599
|
const errorArgs = [];
|
|
3099
3600
|
const remoteComplete = (idx, error) => {
|
|
3100
|
-
const
|
|
3101
|
-
let
|
|
3601
|
+
const payload = doneArr[idx + 1];
|
|
3602
|
+
let newPayload = false;
|
|
3102
3603
|
if (error) {
|
|
3103
3604
|
errorArgs[idx] = error;
|
|
3104
|
-
staticEmitter2.fire("fail", {
|
|
3605
|
+
staticEmitter2.fire("fail", { payload, error });
|
|
3105
3606
|
} else {
|
|
3106
|
-
|
|
3107
|
-
staticEmitter2.fire("done", {
|
|
3607
|
+
newPayload = true;
|
|
3608
|
+
staticEmitter2.fire("done", { payload });
|
|
3108
3609
|
}
|
|
3109
|
-
if (!service
|
|
3610
|
+
if (!service.destroyed) {
|
|
3110
3611
|
const finish = requestCount === total;
|
|
3111
3612
|
if (finish) {
|
|
3112
|
-
service
|
|
3613
|
+
service.busy = 0;
|
|
3113
3614
|
if (flag === FETCH_FLAGS_ALL) {
|
|
3114
3615
|
doneArr[0] = errorArgs;
|
|
3115
3616
|
funcWithTry(done, doneArr, service, noop);
|
|
3116
3617
|
}
|
|
3117
3618
|
}
|
|
3118
3619
|
if (flag === FETCH_FLAGS_ONE) {
|
|
3119
|
-
funcWithTry(done, [error || null,
|
|
3620
|
+
funcWithTry(done, [error || null, payload, finish, idx], service, noop);
|
|
3120
3621
|
}
|
|
3121
3622
|
}
|
|
3122
|
-
if (
|
|
3123
|
-
staticEmitter2.fire("end", {
|
|
3623
|
+
if (newPayload) {
|
|
3624
|
+
staticEmitter2.fire("end", { payload, error });
|
|
3124
3625
|
}
|
|
3125
3626
|
};
|
|
3126
3627
|
for (const attr of attrList) {
|
|
3127
3628
|
if (!attr) continue;
|
|
3128
3629
|
const attrObj = typeof attr === "string" ? { name: attr } : attr;
|
|
3129
|
-
const
|
|
3130
|
-
const
|
|
3131
|
-
const cacheKey =
|
|
3630
|
+
const payloadInfo = service.type.get(attrObj, save);
|
|
3631
|
+
const payloadEntity = payloadInfo.entity;
|
|
3632
|
+
const cacheKey = payloadEntity.cacheInfo?.key || "";
|
|
3132
3633
|
const complete = remoteComplete.bind(null, requestCount++);
|
|
3133
3634
|
if (cacheKey && pendingCacheKeys[cacheKey]) {
|
|
3134
3635
|
pendingCacheKeys[cacheKey].push(complete);
|
|
3135
|
-
} else if (
|
|
3636
|
+
} else if (payloadInfo.needsUpdate) {
|
|
3136
3637
|
if (cacheKey) {
|
|
3137
3638
|
const cacheList = [complete];
|
|
3138
|
-
cacheList.
|
|
3639
|
+
cacheList.entity = payloadEntity;
|
|
3139
3640
|
pendingCacheKeys[cacheKey] = cacheList;
|
|
3140
3641
|
const cacheComplete = () => {
|
|
3141
3642
|
const list = pendingCacheKeys[cacheKey];
|
|
3142
|
-
const entity = list.
|
|
3143
|
-
if (entity.cacheInfo) {
|
|
3643
|
+
const entity = list.entity;
|
|
3644
|
+
if (entity instanceof Payload && entity.cacheInfo) {
|
|
3144
3645
|
entity.cacheInfo.time = now();
|
|
3646
|
+
internals.payloadCache.set(cacheKey, entity);
|
|
3145
3647
|
}
|
|
3146
|
-
internals.bagCache.set(cacheKey, entity);
|
|
3147
3648
|
Reflect.deleteProperty(pendingCacheKeys, cacheKey);
|
|
3148
3649
|
for (const cb of list) {
|
|
3149
|
-
if (typeof cb === "function")
|
|
3150
|
-
cb();
|
|
3151
|
-
}
|
|
3650
|
+
if (typeof cb === "function") cb();
|
|
3152
3651
|
}
|
|
3153
3652
|
};
|
|
3154
|
-
syncFn(
|
|
3653
|
+
syncFn(payloadEntity, cacheComplete);
|
|
3155
3654
|
} else {
|
|
3156
|
-
syncFn(
|
|
3655
|
+
syncFn(payloadEntity, complete);
|
|
3157
3656
|
}
|
|
3158
3657
|
} else {
|
|
3159
3658
|
complete();
|
|
@@ -3161,12 +3660,14 @@ function serviceSend(service, attrs, done, flag, save) {
|
|
|
3161
3660
|
}
|
|
3162
3661
|
}
|
|
3163
3662
|
|
|
3164
|
-
// src/frame-
|
|
3165
|
-
var
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3663
|
+
// src/frame-visual.ts
|
|
3664
|
+
var FrameVisualBridge = {
|
|
3665
|
+
MSG_PING: "LARK_VIS_PING",
|
|
3666
|
+
MSG_PONG: "LARK_VIS_PONG",
|
|
3667
|
+
MSG_REQUEST_TREE: "LARK_VIS_REQUEST_TREE",
|
|
3668
|
+
MSG_TREE: "LARK_VIS_TREE",
|
|
3669
|
+
MSG_TREE_DELTA: "LARK_VIS_TREE_DELTA"
|
|
3670
|
+
};
|
|
3170
3671
|
function serializeView(view) {
|
|
3171
3672
|
return {
|
|
3172
3673
|
id: view.id,
|
|
@@ -3206,7 +3707,10 @@ function serializeFrame(frameId) {
|
|
|
3206
3707
|
};
|
|
3207
3708
|
}
|
|
3208
3709
|
function serializeFrameTree() {
|
|
3209
|
-
const root = Frame.
|
|
3710
|
+
const root = Frame.getRoot();
|
|
3711
|
+
if (!root) {
|
|
3712
|
+
return { root: null, totalFrames: 0, timestamp: Date.now(), rootId: "" };
|
|
3713
|
+
}
|
|
3210
3714
|
const rootNode = serializeFrame(root.id);
|
|
3211
3715
|
let totalFrames = 0;
|
|
3212
3716
|
const countFrames = (node) => {
|
|
@@ -3234,19 +3738,22 @@ function installFrameVisualizerBridge() {
|
|
|
3234
3738
|
const data = event.data;
|
|
3235
3739
|
if (!data || typeof data !== "object") return;
|
|
3236
3740
|
const type = data.type;
|
|
3237
|
-
if (type === MSG_PING) {
|
|
3741
|
+
if (type === FrameVisualBridge.MSG_PING) {
|
|
3238
3742
|
const source = event.source;
|
|
3239
3743
|
if (source) {
|
|
3240
|
-
source.postMessage(
|
|
3744
|
+
source.postMessage(
|
|
3745
|
+
{ type: FrameVisualBridge.MSG_PONG },
|
|
3746
|
+
{ targetOrigin: "*" }
|
|
3747
|
+
);
|
|
3241
3748
|
}
|
|
3242
3749
|
return;
|
|
3243
3750
|
}
|
|
3244
|
-
if (type === MSG_REQUEST_TREE) {
|
|
3751
|
+
if (type === FrameVisualBridge.MSG_REQUEST_TREE) {
|
|
3245
3752
|
const tree = serializeFrameTree();
|
|
3246
3753
|
const source = event.source;
|
|
3247
3754
|
if (source) {
|
|
3248
3755
|
source.postMessage(
|
|
3249
|
-
{ type: MSG_TREE, data: tree },
|
|
3756
|
+
{ type: FrameVisualBridge.MSG_TREE, data: tree },
|
|
3250
3757
|
{ targetOrigin: "*" }
|
|
3251
3758
|
);
|
|
3252
3759
|
}
|
|
@@ -3265,18 +3772,14 @@ function pushTreeUpdate() {
|
|
|
3265
3772
|
const treeJson = JSON.stringify(tree);
|
|
3266
3773
|
if (treeJson !== lastTreeJson) {
|
|
3267
3774
|
lastTreeJson = treeJson;
|
|
3268
|
-
window.parent.postMessage(
|
|
3775
|
+
window.parent.postMessage(
|
|
3776
|
+
{ type: FrameVisualBridge.MSG_TREE_DELTA, data: tree },
|
|
3777
|
+
"*"
|
|
3778
|
+
);
|
|
3269
3779
|
}
|
|
3270
3780
|
}
|
|
3271
3781
|
|
|
3272
3782
|
// src/framework.ts
|
|
3273
|
-
var config = {
|
|
3274
|
-
rootId: "lark-root",
|
|
3275
|
-
hashbang: "#!",
|
|
3276
|
-
error: (error) => {
|
|
3277
|
-
throw error;
|
|
3278
|
-
}
|
|
3279
|
-
};
|
|
3280
3783
|
var booted3 = false;
|
|
3281
3784
|
var taskList = [];
|
|
3282
3785
|
var taskIndex = 0;
|
|
@@ -3325,6 +3828,9 @@ function task(fn, args, context) {
|
|
|
3325
3828
|
}
|
|
3326
3829
|
}
|
|
3327
3830
|
var dispatcherUpdateTag = 0;
|
|
3831
|
+
function isThenable(value) {
|
|
3832
|
+
return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
3833
|
+
}
|
|
3328
3834
|
function viewIsObserveChanged(view) {
|
|
3329
3835
|
const loc = view.locationObserved;
|
|
3330
3836
|
let result = false;
|
|
@@ -3338,7 +3844,7 @@ function viewIsObserveChanged(view) {
|
|
|
3338
3844
|
const changedParams = lastChanged2?.params;
|
|
3339
3845
|
if (changedParams) {
|
|
3340
3846
|
for (const key of loc.keys) {
|
|
3341
|
-
result =
|
|
3847
|
+
result = hasOwnProperty(changedParams, key);
|
|
3342
3848
|
if (result) break;
|
|
3343
3849
|
}
|
|
3344
3850
|
}
|
|
@@ -3350,49 +3856,65 @@ function stateIsObserveChanged(view, stateKeys) {
|
|
|
3350
3856
|
const observedKeys = view.observedStateKeys;
|
|
3351
3857
|
if (!observedKeys) return false;
|
|
3352
3858
|
for (const key of observedKeys) {
|
|
3353
|
-
if (has(
|
|
3859
|
+
if (stateKeys.has(key)) return true;
|
|
3354
3860
|
}
|
|
3355
3861
|
return false;
|
|
3356
3862
|
}
|
|
3357
3863
|
function dispatcherUpdate(frame, stateKeys) {
|
|
3358
|
-
const
|
|
3359
|
-
const
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
renderPromise
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3864
|
+
const stack = [frame];
|
|
3865
|
+
const drain = (s) => {
|
|
3866
|
+
while (s.length > 0) {
|
|
3867
|
+
const current = s.pop();
|
|
3868
|
+
const tagged = current;
|
|
3869
|
+
const view = current.view;
|
|
3870
|
+
if (!view || tagged.dispatcherUpdateTag === dispatcherUpdateTag || view.signature <= 1) {
|
|
3871
|
+
continue;
|
|
3872
|
+
}
|
|
3873
|
+
tagged.dispatcherUpdateTag = dispatcherUpdateTag;
|
|
3874
|
+
const isChanged = stateKeys ? stateIsObserveChanged(view, stateKeys) : viewIsObserveChanged(view);
|
|
3875
|
+
let renderPromise;
|
|
3876
|
+
if (isChanged) {
|
|
3877
|
+
const renderResult = funcWithTry(
|
|
3878
|
+
view.renderMethod ?? view.render,
|
|
3879
|
+
[],
|
|
3880
|
+
view,
|
|
3881
|
+
noop
|
|
3882
|
+
);
|
|
3883
|
+
if (isThenable(renderResult)) {
|
|
3884
|
+
renderPromise = renderResult;
|
|
3885
|
+
}
|
|
3886
|
+
}
|
|
3887
|
+
const children = current.children();
|
|
3888
|
+
if (renderPromise) {
|
|
3889
|
+
renderPromise.then(() => {
|
|
3890
|
+
const subStack = [];
|
|
3891
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
3892
|
+
const child = Frame.get(children[i]);
|
|
3893
|
+
if (child) subStack.push(child);
|
|
3894
|
+
}
|
|
3895
|
+
drain(subStack);
|
|
3896
|
+
});
|
|
3897
|
+
} else {
|
|
3898
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
3899
|
+
const child = Frame.get(children[i]);
|
|
3900
|
+
if (child) s.push(child);
|
|
3901
|
+
}
|
|
3378
3902
|
}
|
|
3379
3903
|
}
|
|
3380
3904
|
};
|
|
3381
|
-
|
|
3382
|
-
renderPromise.then(recurse);
|
|
3383
|
-
} else {
|
|
3384
|
-
recurse();
|
|
3385
|
-
}
|
|
3905
|
+
drain(stack);
|
|
3386
3906
|
}
|
|
3387
3907
|
function dispatcherNotifyChange(e) {
|
|
3388
|
-
const rootFrame2 = Frame.
|
|
3389
|
-
|
|
3908
|
+
const rootFrame2 = Frame.getRoot();
|
|
3909
|
+
if (!rootFrame2) return;
|
|
3910
|
+
const routeEvent = e;
|
|
3911
|
+
const view = routeEvent.view;
|
|
3390
3912
|
if (view) {
|
|
3391
3913
|
const viewPath = typeof view === "object" && view !== null ? String(view.to || "") : String(view);
|
|
3392
3914
|
rootFrame2.mountView(viewPath);
|
|
3393
3915
|
} else {
|
|
3394
3916
|
dispatcherUpdateTag++;
|
|
3395
|
-
dispatcherUpdate(rootFrame2, e
|
|
3917
|
+
dispatcherUpdate(rootFrame2, e.keys);
|
|
3396
3918
|
}
|
|
3397
3919
|
}
|
|
3398
3920
|
function dispatchEvent(target, eventType, eventInit) {
|
|
@@ -3403,23 +3925,8 @@ function dispatchEvent(target, eventType, eventInit) {
|
|
|
3403
3925
|
});
|
|
3404
3926
|
target.dispatchEvent(event);
|
|
3405
3927
|
}
|
|
3406
|
-
var Base = class extends EventEmitter {
|
|
3407
|
-
};
|
|
3408
|
-
function use(names, callback) {
|
|
3409
|
-
if (!config.require) {
|
|
3410
|
-
if (callback) callback();
|
|
3411
|
-
return;
|
|
3412
|
-
}
|
|
3413
|
-
const nameList = typeof names === "string" ? [names] : names;
|
|
3414
|
-
const result = config.require(nameList);
|
|
3415
|
-
if (result && typeof result.then === "function") {
|
|
3416
|
-
result.then((modules) => {
|
|
3417
|
-
if (callback) callback(modules);
|
|
3418
|
-
});
|
|
3419
|
-
}
|
|
3420
|
-
}
|
|
3421
3928
|
var WAIT_OK = 1;
|
|
3422
|
-
var
|
|
3929
|
+
var WAIT_TIMEOUT_OR_NOT_FOUND = 0;
|
|
3423
3930
|
function waitZoneViewsRendered(viewId, timeout) {
|
|
3424
3931
|
if (timeout == null) {
|
|
3425
3932
|
timeout = 30 * 1e3;
|
|
@@ -3430,7 +3937,7 @@ function waitZoneViewsRendered(viewId, timeout) {
|
|
|
3430
3937
|
const check = () => {
|
|
3431
3938
|
const currentTime = now();
|
|
3432
3939
|
if (currentTime > endTime || !checkFrame) {
|
|
3433
|
-
resolve(
|
|
3940
|
+
resolve(WAIT_TIMEOUT_OR_NOT_FOUND);
|
|
3434
3941
|
} else if (checkFrame.childrenCount === checkFrame.readyCount) {
|
|
3435
3942
|
resolve(WAIT_OK);
|
|
3436
3943
|
} else {
|
|
@@ -3440,12 +3947,27 @@ function waitZoneViewsRendered(viewId, timeout) {
|
|
|
3440
3947
|
setTimeout(check, 9);
|
|
3441
3948
|
});
|
|
3442
3949
|
}
|
|
3950
|
+
function getConfigImpl(key) {
|
|
3951
|
+
if (key === void 0) return config;
|
|
3952
|
+
return config[key];
|
|
3953
|
+
}
|
|
3443
3954
|
var Framework = {
|
|
3444
3955
|
// ============================================================
|
|
3445
3956
|
// Lifecycle
|
|
3446
3957
|
// ============================================================
|
|
3958
|
+
/** Read framework configuration. See `FrameworkInterface.getConfig`. */
|
|
3959
|
+
getConfig: getConfigImpl,
|
|
3960
|
+
/**
|
|
3961
|
+
* Merge a patch into framework configuration. See `FrameworkInterface.setConfig`.
|
|
3962
|
+
*/
|
|
3963
|
+
setConfig(patch) {
|
|
3964
|
+
if (patch && typeof patch === "object") {
|
|
3965
|
+
assign(config, patch);
|
|
3966
|
+
}
|
|
3967
|
+
return config;
|
|
3968
|
+
},
|
|
3447
3969
|
/**
|
|
3448
|
-
*
|
|
3970
|
+
* @deprecated Use `getConfig()` / `setConfig()`. Behavior unchanged.
|
|
3449
3971
|
*/
|
|
3450
3972
|
config(cfg) {
|
|
3451
3973
|
if (!cfg) {
|
|
@@ -3466,17 +3988,17 @@ var Framework = {
|
|
|
3466
3988
|
}
|
|
3467
3989
|
Router._setConfig(config);
|
|
3468
3990
|
EventDelegator.setFrameGetter((id) => Frame.get(id));
|
|
3469
|
-
Router.on(
|
|
3470
|
-
dispatcherNotifyChange(data);
|
|
3991
|
+
Router.on(RouterEvents.CHANGED, (data) => {
|
|
3992
|
+
if (data) dispatcherNotifyChange(data);
|
|
3471
3993
|
});
|
|
3472
|
-
State.on(
|
|
3473
|
-
dispatcherNotifyChange(data);
|
|
3994
|
+
State.on(RouterEvents.CHANGED, (data) => {
|
|
3995
|
+
if (data) dispatcherNotifyChange(data);
|
|
3474
3996
|
});
|
|
3475
3997
|
booted3 = true;
|
|
3476
3998
|
markBooted();
|
|
3477
3999
|
markRouterBooted();
|
|
3478
4000
|
installFrameVisualizerBridge();
|
|
3479
|
-
const rootFrame2 = Frame.
|
|
4001
|
+
const rootFrame2 = Frame.createRoot(config.rootId);
|
|
3480
4002
|
Router._bind();
|
|
3481
4003
|
const defaultView = config.defaultView || "";
|
|
3482
4004
|
if (defaultView && !rootFrame2.view) {
|
|
@@ -3507,7 +4029,7 @@ var Framework = {
|
|
|
3507
4029
|
/** Wait for zone views to be rendered */
|
|
3508
4030
|
waitZoneViewsRendered,
|
|
3509
4031
|
WAIT_OK,
|
|
3510
|
-
|
|
4032
|
+
WAIT_TIMEOUT_OR_NOT_FOUND,
|
|
3511
4033
|
/**
|
|
3512
4034
|
* Convert array to hash map.
|
|
3513
4035
|
*/
|
|
@@ -3531,7 +4053,7 @@ var Framework = {
|
|
|
3531
4053
|
/**
|
|
3532
4054
|
* Check if object has own property.
|
|
3533
4055
|
*/
|
|
3534
|
-
has,
|
|
4056
|
+
has: hasOwnProperty,
|
|
3535
4057
|
/**
|
|
3536
4058
|
* Get object keys.
|
|
3537
4059
|
*/
|
|
@@ -3572,7 +4094,7 @@ var Framework = {
|
|
|
3572
4094
|
/**
|
|
3573
4095
|
* Base class with EventEmitter.
|
|
3574
4096
|
*/
|
|
3575
|
-
Base,
|
|
4097
|
+
Base: EventEmitter,
|
|
3576
4098
|
// ============================================================
|
|
3577
4099
|
// Module access
|
|
3578
4100
|
// ============================================================
|
|
@@ -3590,10 +4112,14 @@ if (typeof window !== "undefined") {
|
|
|
3590
4112
|
window.__lark_State = State;
|
|
3591
4113
|
window.__lark_Router = Router;
|
|
3592
4114
|
window.__lark_Frame = Frame;
|
|
4115
|
+
window.__lark_View = View;
|
|
4116
|
+
window.__lark_invalidateViewClass = invalidateViewClass;
|
|
4117
|
+
window.__lark_getViewClassRegistry = getViewClassRegistry;
|
|
4118
|
+
window.__lark_registerViewClass = registerViewClass;
|
|
3593
4119
|
}
|
|
3594
4120
|
|
|
3595
4121
|
// src/store.ts
|
|
3596
|
-
var LARK_GLOBAL = "
|
|
4122
|
+
var LARK_GLOBAL = "lark-global";
|
|
3597
4123
|
var Platform = /* @__PURE__ */ ((Platform2) => {
|
|
3598
4124
|
Platform2["Lark"] = "lark";
|
|
3599
4125
|
Platform2["React"] = "react";
|
|
@@ -3603,28 +4129,38 @@ var Platform = /* @__PURE__ */ ((Platform2) => {
|
|
|
3603
4129
|
var isFunction = (val) => typeof val === "function";
|
|
3604
4130
|
var isObject = (val) => val !== null && typeof val === "object";
|
|
3605
4131
|
var isPromise = (val) => isObject(val) && isFunction(val["then"]);
|
|
3606
|
-
var
|
|
3607
|
-
var
|
|
4132
|
+
var hasOwnProperty2 = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
|
|
4133
|
+
var hasStructuredClone = typeof globalThis !== "undefined" && typeof globalThis.structuredClone === "function";
|
|
4134
|
+
var deepCloneFallback = (obj) => {
|
|
3608
4135
|
if (!obj || !isObject(obj)) return {};
|
|
3609
|
-
const newData = Array.isArray(obj) ? [] :
|
|
4136
|
+
const newData = Array.isArray(obj) ? [] : {};
|
|
3610
4137
|
for (const key in obj) {
|
|
3611
|
-
if (
|
|
4138
|
+
if (hasOwnProperty2(obj, key)) {
|
|
3612
4139
|
const value = obj[key];
|
|
3613
|
-
newData[key] = isObject(value) ?
|
|
4140
|
+
newData[key] = isObject(value) ? deepCloneFallback(value) : value;
|
|
3614
4141
|
}
|
|
3615
4142
|
}
|
|
3616
4143
|
return newData;
|
|
3617
4144
|
};
|
|
4145
|
+
var deepClone = (obj) => {
|
|
4146
|
+
if (hasStructuredClone) {
|
|
4147
|
+
try {
|
|
4148
|
+
return structuredClone(obj);
|
|
4149
|
+
} catch {
|
|
4150
|
+
return deepCloneFallback(obj);
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
return deepCloneFallback(obj);
|
|
4154
|
+
};
|
|
3618
4155
|
var cloneData = (data) => isObject(data) ? deepClone(data) : data;
|
|
3619
4156
|
var getDataByKey = (target, key) => {
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
data = rec?.[key];
|
|
4157
|
+
if (!key.includes(".")) {
|
|
4158
|
+
return target[key];
|
|
4159
|
+
}
|
|
4160
|
+
let data = target;
|
|
4161
|
+
for (const k of key.split(".")) {
|
|
4162
|
+
if (!isObject(data)) return void 0;
|
|
4163
|
+
data = data[k];
|
|
3628
4164
|
}
|
|
3629
4165
|
return data;
|
|
3630
4166
|
};
|
|
@@ -3636,8 +4172,10 @@ var Queue = class {
|
|
|
3636
4172
|
const flushTickTask = () => {
|
|
3637
4173
|
while (queue.length > 0) {
|
|
3638
4174
|
const task2 = queue.shift();
|
|
3639
|
-
|
|
3640
|
-
|
|
4175
|
+
if (task2) {
|
|
4176
|
+
pendingTasks.delete(task2);
|
|
4177
|
+
runTask(task2);
|
|
4178
|
+
}
|
|
3641
4179
|
}
|
|
3642
4180
|
};
|
|
3643
4181
|
Promise.resolve().then(flushTickTask);
|
|
@@ -3670,17 +4208,18 @@ var Queue = class {
|
|
|
3670
4208
|
};
|
|
3671
4209
|
var addParams2Callback = (cb, params) => {
|
|
3672
4210
|
if (!cb || !params) return;
|
|
3673
|
-
const
|
|
3674
|
-
|
|
3675
|
-
|
|
4211
|
+
const tagged = cb;
|
|
4212
|
+
const existing = tagged.params;
|
|
4213
|
+
if (isObject(existing)) {
|
|
4214
|
+
Object.assign(existing, params);
|
|
3676
4215
|
} else {
|
|
3677
|
-
|
|
4216
|
+
tagged.params = params;
|
|
3678
4217
|
}
|
|
3679
4218
|
};
|
|
3680
4219
|
var runTask = (cb) => {
|
|
3681
|
-
const
|
|
3682
|
-
const params =
|
|
3683
|
-
delete
|
|
4220
|
+
const tagged = cb;
|
|
4221
|
+
const params = tagged.params;
|
|
4222
|
+
delete tagged.params;
|
|
3684
4223
|
try {
|
|
3685
4224
|
cb(params);
|
|
3686
4225
|
} catch {
|
|
@@ -3706,7 +4245,9 @@ var ArrMethods = {};
|
|
|
3706
4245
|
if (res === -1 || res === false) {
|
|
3707
4246
|
res = rawMethod.apply(
|
|
3708
4247
|
this,
|
|
3709
|
-
args.map(
|
|
4248
|
+
args.map(
|
|
4249
|
+
(item) => isObject(item) ? ProxyCache.get(item) ?? item : item
|
|
4250
|
+
)
|
|
3710
4251
|
);
|
|
3711
4252
|
}
|
|
3712
4253
|
return res;
|
|
@@ -3724,6 +4265,7 @@ var inArrUpdate = false;
|
|
|
3724
4265
|
});
|
|
3725
4266
|
function needKeepArrItem(target, newVal, key) {
|
|
3726
4267
|
if (!Array.isArray(target) || !inArrUpdate) return false;
|
|
4268
|
+
if (!isObject(newVal)) return false;
|
|
3727
4269
|
return getLinkKeys(newVal) === createLinkKeys(target, key);
|
|
3728
4270
|
}
|
|
3729
4271
|
var defStateConfig = {
|
|
@@ -3735,11 +4277,13 @@ var StateConfigMap = /* @__PURE__ */ new WeakMap();
|
|
|
3735
4277
|
var setStateConfig = (target, config2) => {
|
|
3736
4278
|
if (target && isObject(config2)) StateConfigMap.set(target, config2);
|
|
3737
4279
|
};
|
|
3738
|
-
|
|
3739
|
-
if (!StateConfigMap.has(target))
|
|
4280
|
+
function getStateConfig(target, key) {
|
|
4281
|
+
if (!StateConfigMap.has(target)) {
|
|
4282
|
+
return void 0;
|
|
4283
|
+
}
|
|
3740
4284
|
const config2 = StateConfigMap.get(target);
|
|
3741
|
-
return key ? config2[key] : config2;
|
|
3742
|
-
}
|
|
4285
|
+
return key ? config2?.[key] : config2;
|
|
4286
|
+
}
|
|
3743
4287
|
var isState = (target) => isObject(target) && StateConfigMap.has(target);
|
|
3744
4288
|
var createLinkKeys = (target, property) => {
|
|
3745
4289
|
if (!hasLinkKeys(target)) return property;
|
|
@@ -3777,7 +4321,7 @@ var needKeep = (key) => {
|
|
|
3777
4321
|
};
|
|
3778
4322
|
var canSetNewVal = (params) => {
|
|
3779
4323
|
const { property, newVal, oldVal } = params;
|
|
3780
|
-
if (
|
|
4324
|
+
if (hasOwnProperty2(params.target, property) && newVal === oldVal)
|
|
3781
4325
|
return false;
|
|
3782
4326
|
return true;
|
|
3783
4327
|
};
|
|
@@ -3789,16 +4333,13 @@ var getNewVal = (params) => {
|
|
|
3789
4333
|
if (config2?.shallow) return newVal;
|
|
3790
4334
|
if (needKeepVal) return newVal;
|
|
3791
4335
|
const linkKeys = createLinkKeys(target, property);
|
|
3792
|
-
const newState = createState(newVal, {
|
|
3793
|
-
...config2,
|
|
3794
|
-
linkKeys
|
|
3795
|
-
});
|
|
4336
|
+
const newState = createState(newVal, { ...config2, linkKeys });
|
|
3796
4337
|
if (isPromise(newVal)) handlePromise(newVal, target, property);
|
|
3797
4338
|
return newState;
|
|
3798
4339
|
};
|
|
3799
4340
|
var genPayload = (params) => {
|
|
3800
4341
|
const { target, property, newVal, oldVal } = params;
|
|
3801
|
-
const config2 = getStateConfig(target)
|
|
4342
|
+
const config2 = getStateConfig(target) ?? defStateConfig;
|
|
3802
4343
|
return {
|
|
3803
4344
|
belong: config2.belong || LARK_GLOBAL,
|
|
3804
4345
|
target,
|
|
@@ -3808,11 +4349,12 @@ var genPayload = (params) => {
|
|
|
3808
4349
|
};
|
|
3809
4350
|
};
|
|
3810
4351
|
var handlePromise = (child, parent, key) => {
|
|
4352
|
+
const childObj = child;
|
|
3811
4353
|
child.then((res) => {
|
|
3812
4354
|
const parentProxy = ProxyCache.get(parent);
|
|
3813
4355
|
if (parentProxy) {
|
|
3814
4356
|
const oldVal = parentProxy[key];
|
|
3815
|
-
if (ProxyCache.get(
|
|
4357
|
+
if (ProxyCache.get(childObj) === oldVal) {
|
|
3816
4358
|
parentProxy[key] = res;
|
|
3817
4359
|
}
|
|
3818
4360
|
}
|
|
@@ -3820,7 +4362,7 @@ var handlePromise = (child, parent, key) => {
|
|
|
3820
4362
|
const parentProxy = ProxyCache.get(parent);
|
|
3821
4363
|
if (parentProxy) {
|
|
3822
4364
|
const oldVal = parentProxy[key];
|
|
3823
|
-
if (ProxyCache.get(
|
|
4365
|
+
if (ProxyCache.get(childObj) === oldVal) {
|
|
3824
4366
|
parentProxy[key] = err;
|
|
3825
4367
|
}
|
|
3826
4368
|
}
|
|
@@ -3832,7 +4374,7 @@ var mark2 = (host, key) => {
|
|
|
3832
4374
|
let sign;
|
|
3833
4375
|
if (!host[_deleteKey]) {
|
|
3834
4376
|
const markHost = host[_markObjKey] || (host[_markObjKey] = {});
|
|
3835
|
-
if (!
|
|
4377
|
+
if (!hasOwnProperty2(markHost, key)) {
|
|
3836
4378
|
markHost[key] = 0;
|
|
3837
4379
|
}
|
|
3838
4380
|
sign = ++markHost[key];
|
|
@@ -3869,7 +4411,7 @@ function createState(initialData, config2) {
|
|
|
3869
4411
|
oldVal
|
|
3870
4412
|
});
|
|
3871
4413
|
if (!canSet) return true;
|
|
3872
|
-
const proxyTarget = receiver
|
|
4414
|
+
const proxyTarget = isObject(receiver) && receiver !== null ? receiver : state;
|
|
3873
4415
|
newVal = getNewVal({
|
|
3874
4416
|
target: proxyTarget,
|
|
3875
4417
|
property: strProp,
|
|
@@ -3889,7 +4431,7 @@ function createState(initialData, config2) {
|
|
|
3889
4431
|
},
|
|
3890
4432
|
deleteProperty(target, property) {
|
|
3891
4433
|
const strProp = property;
|
|
3892
|
-
if (!
|
|
4434
|
+
if (!hasOwnProperty2(target, strProp)) return true;
|
|
3893
4435
|
const oldVal = Reflect.get(target, property);
|
|
3894
4436
|
Reflect.deleteProperty(target, property);
|
|
3895
4437
|
const payload = genPayload({
|
|
@@ -3933,11 +4475,8 @@ function shallowSet(target, key, data) {
|
|
|
3933
4475
|
keep(key);
|
|
3934
4476
|
const config2 = getStateConfig(target);
|
|
3935
4477
|
const linkKeys = createLinkKeys(target, key);
|
|
3936
|
-
target[key] = createState(data, {
|
|
3937
|
-
|
|
3938
|
-
linkKeys,
|
|
3939
|
-
shallow: true
|
|
3940
|
-
});
|
|
4478
|
+
target[key] = createState(data, { ...config2, linkKeys, shallow: true });
|
|
4479
|
+
return target[key];
|
|
3941
4480
|
}
|
|
3942
4481
|
var GlobalDeps = /* @__PURE__ */ new Map();
|
|
3943
4482
|
function track(payload) {
|
|
@@ -4018,8 +4557,22 @@ var _stateKeys = /* @__PURE__ */ Symbol("state-keys");
|
|
|
4018
4557
|
var _storeState = /* @__PURE__ */ Symbol("store-state");
|
|
4019
4558
|
var _storeDefScheduler = /* @__PURE__ */ Symbol("store-def-scheduler");
|
|
4020
4559
|
var _storeProxy = /* @__PURE__ */ Symbol("fn:store-proxy");
|
|
4560
|
+
var _computedKeys = /* @__PURE__ */ Symbol("store-computed-keys");
|
|
4561
|
+
var COMPUTED_BRAND = /* @__PURE__ */ Symbol("store-computed-brand");
|
|
4562
|
+
function computed(deps, fn) {
|
|
4563
|
+
const marker = {
|
|
4564
|
+
[COMPUTED_BRAND]: true,
|
|
4565
|
+
deps,
|
|
4566
|
+
fn
|
|
4567
|
+
};
|
|
4568
|
+
return marker;
|
|
4569
|
+
}
|
|
4570
|
+
function isComputedMarker(val) {
|
|
4571
|
+
return isObject(val) && val[COMPUTED_BRAND] === true;
|
|
4572
|
+
}
|
|
4021
4573
|
var BaseStore = class {
|
|
4022
4574
|
[_storeStatus] = 0 /* BEFORE_CREATE */;
|
|
4575
|
+
[_computedKeys] = /* @__PURE__ */ new Set();
|
|
4023
4576
|
[_storeDefScheduler] = getDefScheduler;
|
|
4024
4577
|
[_storeBoot]() {
|
|
4025
4578
|
this[_storeStatus] = 2 /* ACTIVE */;
|
|
@@ -4042,10 +4595,16 @@ var BaseStore = class {
|
|
|
4042
4595
|
if (isObject(body)) {
|
|
4043
4596
|
const state = {};
|
|
4044
4597
|
const handlers = {};
|
|
4598
|
+
const computedDefs = {};
|
|
4599
|
+
const computedKeys = this[_computedKeys];
|
|
4045
4600
|
Reflect.ownKeys(body).forEach((key) => {
|
|
4046
4601
|
const strKey = key;
|
|
4047
4602
|
const val = body[strKey];
|
|
4048
|
-
if (
|
|
4603
|
+
if (isComputedMarker(val)) {
|
|
4604
|
+
computedDefs[strKey] = val;
|
|
4605
|
+
state[strKey] = void 0;
|
|
4606
|
+
computedKeys.add(strKey);
|
|
4607
|
+
} else if (isFunction(val)) {
|
|
4049
4608
|
if (!excludeFns.includes(strKey)) handlers[strKey] = val;
|
|
4050
4609
|
} else {
|
|
4051
4610
|
state[strKey] = val;
|
|
@@ -4055,6 +4614,22 @@ var BaseStore = class {
|
|
|
4055
4614
|
this[_originState] = cloneData(state);
|
|
4056
4615
|
this[_stateKeys] = Object.keys(state);
|
|
4057
4616
|
this[_storeState] = createState(state, { belong: this[_storeName] });
|
|
4617
|
+
if (Object.keys(computedDefs).length > 0) {
|
|
4618
|
+
const belong = this[_storeName];
|
|
4619
|
+
const storeState = this[_storeState];
|
|
4620
|
+
for (const key of Object.keys(computedDefs)) {
|
|
4621
|
+
const def = computedDefs[key];
|
|
4622
|
+
const recompute = () => {
|
|
4623
|
+
storeState[key] = def.fn();
|
|
4624
|
+
};
|
|
4625
|
+
recompute();
|
|
4626
|
+
const trackList = def.deps.map((depKey) => ({
|
|
4627
|
+
key: depKey,
|
|
4628
|
+
cb: recompute
|
|
4629
|
+
}));
|
|
4630
|
+
if (trackList.length > 0) track({ belong, trackList });
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4058
4633
|
}
|
|
4059
4634
|
}
|
|
4060
4635
|
constructor(name, config2) {
|
|
@@ -4076,18 +4651,21 @@ var BaseStore = class {
|
|
|
4076
4651
|
}
|
|
4077
4652
|
[_storeProxy](toOut = false) {
|
|
4078
4653
|
const self = this;
|
|
4079
|
-
|
|
4654
|
+
const proxy = new Proxy(self, {
|
|
4080
4655
|
get(target, property) {
|
|
4081
|
-
|
|
4082
|
-
|
|
4656
|
+
const strProp = property;
|
|
4657
|
+
if (self[_stateKeys].includes(strProp)) {
|
|
4658
|
+
const val = self[_storeState][strProp];
|
|
4083
4659
|
return toOut ? cloneData(val) : val;
|
|
4084
4660
|
}
|
|
4085
4661
|
return Reflect.get(target, property);
|
|
4086
4662
|
},
|
|
4087
4663
|
set(_target, property, val) {
|
|
4088
4664
|
if (toOut) return true;
|
|
4089
|
-
|
|
4090
|
-
|
|
4665
|
+
const strProp = property;
|
|
4666
|
+
if (self[_computedKeys].has(strProp)) return true;
|
|
4667
|
+
if (self[_stateKeys].includes(strProp)) {
|
|
4668
|
+
self[_storeState][strProp] = val;
|
|
4091
4669
|
}
|
|
4092
4670
|
return true;
|
|
4093
4671
|
},
|
|
@@ -4095,11 +4673,14 @@ var BaseStore = class {
|
|
|
4095
4673
|
return Reflect.has(target, property) || self[_stateKeys].includes(property);
|
|
4096
4674
|
}
|
|
4097
4675
|
});
|
|
4676
|
+
return proxy;
|
|
4098
4677
|
}
|
|
4099
4678
|
};
|
|
4100
4679
|
var LarkUtils = {
|
|
4101
4680
|
isLarkView(instance) {
|
|
4102
|
-
|
|
4681
|
+
if (!isObject(instance)) return false;
|
|
4682
|
+
const updater = instance["updater"];
|
|
4683
|
+
return isObject(updater) && isFunction(updater["set"]) && isFunction(updater["digest"]);
|
|
4103
4684
|
},
|
|
4104
4685
|
getRender(view) {
|
|
4105
4686
|
return view.updater.digest.bind(view.updater);
|
|
@@ -4115,41 +4696,45 @@ var getLarkAdapter = (storeName) => ({
|
|
|
4115
4696
|
Store: LarkStore,
|
|
4116
4697
|
useStore: ((view) => {
|
|
4117
4698
|
const store = getStore(storeName);
|
|
4699
|
+
if (!(store instanceof LarkStore)) return {};
|
|
4118
4700
|
return store[_storeBoot](view);
|
|
4119
4701
|
})
|
|
4120
4702
|
});
|
|
4121
|
-
var
|
|
4122
|
-
var
|
|
4703
|
+
var _innerObserveFlags = /* @__PURE__ */ Symbol("store-inner-observe-flags");
|
|
4704
|
+
var _boundViews = /* @__PURE__ */ Symbol("store-bound-views");
|
|
4123
4705
|
var LarkStore = class extends BaseStore {
|
|
4124
|
-
[
|
|
4125
|
-
[
|
|
4706
|
+
[_boundViews] = /* @__PURE__ */ new Set();
|
|
4707
|
+
[_innerObserveFlags] = /* @__PURE__ */ new Set();
|
|
4126
4708
|
[_storeBoot](view) {
|
|
4127
|
-
if (view && LarkUtils.isLarkView(view) && !this[
|
|
4128
|
-
this[
|
|
4709
|
+
if (view && LarkUtils.isLarkView(view) && !this[_boundViews].has(view)) {
|
|
4710
|
+
this[_boundViews].add(view);
|
|
4129
4711
|
LarkUtils.onDestroy(view, () => {
|
|
4130
|
-
this[
|
|
4712
|
+
this[_boundViews].delete(view);
|
|
4131
4713
|
});
|
|
4132
4714
|
}
|
|
4133
4715
|
return super[_storeBoot]();
|
|
4134
4716
|
}
|
|
4135
4717
|
[_storeDestroy]() {
|
|
4136
|
-
this[
|
|
4137
|
-
this[
|
|
4718
|
+
this[_boundViews].clear();
|
|
4719
|
+
this[_innerObserveFlags].clear();
|
|
4138
4720
|
super[_storeDestroy]();
|
|
4139
4721
|
}
|
|
4140
4722
|
observe(view, keys2, defCallback) {
|
|
4141
4723
|
if (this[_storeStatus] !== 2 /* ACTIVE */) return noop;
|
|
4142
|
-
let observeKeys = keys2;
|
|
4724
|
+
let observeKeys = Array.isArray(keys2) ? keys2 : [];
|
|
4143
4725
|
const _view = view;
|
|
4144
4726
|
const renderFn = _view ? LarkUtils.getRender(_view) : noop;
|
|
4145
4727
|
const dateSetterFn = _view ? LarkUtils.getDataSetter(_view) : noop;
|
|
4146
4728
|
const isInnerObserve = !view;
|
|
4147
4729
|
const innerFlags = /* @__PURE__ */ new Set();
|
|
4148
|
-
const storeInnerObserveFlags = this[
|
|
4730
|
+
const storeInnerObserveFlags = this[_innerObserveFlags];
|
|
4149
4731
|
if (isFunction(keys2)) {
|
|
4150
4732
|
const res = keys2();
|
|
4151
4733
|
if (Array.isArray(res)) observeKeys = res;
|
|
4152
4734
|
}
|
|
4735
|
+
if (keys2 === void 0 && _view && observeKeys.length === 0 && Array.isArray(this[_stateKeys])) {
|
|
4736
|
+
observeKeys = this[_stateKeys].slice();
|
|
4737
|
+
}
|
|
4153
4738
|
const defSetter = (immediate, key, alias, transform) => () => {
|
|
4154
4739
|
const stateVal = getDataByKey(this, key);
|
|
4155
4740
|
let data = { [alias || key]: stateVal };
|
|
@@ -4204,11 +4789,12 @@ var getReactAdapter = (storeName) => ({
|
|
|
4204
4789
|
Store: ReactStore,
|
|
4205
4790
|
useStore: (() => {
|
|
4206
4791
|
const store = getStore(storeName);
|
|
4792
|
+
if (!(store instanceof ReactStore)) return {};
|
|
4207
4793
|
return store[_storeBoot]();
|
|
4208
4794
|
})
|
|
4209
4795
|
});
|
|
4210
|
-
var
|
|
4211
|
-
var
|
|
4796
|
+
var _observe = /* @__PURE__ */ Symbol("store-observe");
|
|
4797
|
+
var _getLastState = /* @__PURE__ */ Symbol("store-get-last-state");
|
|
4212
4798
|
var ReactStore = class extends BaseStore {
|
|
4213
4799
|
stateChangeCount = 0;
|
|
4214
4800
|
lastCount = 0;
|
|
@@ -4222,7 +4808,7 @@ var ReactStore = class extends BaseStore {
|
|
|
4222
4808
|
}
|
|
4223
4809
|
[_storeCreate](body) {
|
|
4224
4810
|
super[_storeCreate](body);
|
|
4225
|
-
this[
|
|
4811
|
+
this[_observe](() => {
|
|
4226
4812
|
this.stateChangeCount += 1;
|
|
4227
4813
|
});
|
|
4228
4814
|
}
|
|
@@ -4232,7 +4818,7 @@ var ReactStore = class extends BaseStore {
|
|
|
4232
4818
|
this.lastCount = currCount;
|
|
4233
4819
|
return changed;
|
|
4234
4820
|
}
|
|
4235
|
-
[
|
|
4821
|
+
[_getLastState](handlers) {
|
|
4236
4822
|
if (this.isStateChanged() || !this.lastState) {
|
|
4237
4823
|
const state = this[_storeState];
|
|
4238
4824
|
const immutableState = freezeData(state);
|
|
@@ -4240,7 +4826,7 @@ var ReactStore = class extends BaseStore {
|
|
|
4240
4826
|
}
|
|
4241
4827
|
return this.lastState;
|
|
4242
4828
|
}
|
|
4243
|
-
[
|
|
4829
|
+
[_observe](cb) {
|
|
4244
4830
|
const tasks = this[_stateKeys].map((key) => ({ key, cb }));
|
|
4245
4831
|
track({ belong: this[_storeName], trackList: tasks });
|
|
4246
4832
|
return () => clear({ belong: this[_storeName], clearList: tasks });
|
|
@@ -4267,6 +4853,7 @@ var getNodeAdapter = (storeName) => ({
|
|
|
4267
4853
|
Store: NodeStore,
|
|
4268
4854
|
useStore: (() => {
|
|
4269
4855
|
const store = getStore(storeName);
|
|
4856
|
+
if (!(store instanceof NodeStore)) return {};
|
|
4270
4857
|
return store[_storeBoot]();
|
|
4271
4858
|
})
|
|
4272
4859
|
});
|
|
@@ -4293,7 +4880,7 @@ var getPlatform = (comp) => {
|
|
|
4293
4880
|
if (LarkUtils.isLarkView(comp)) return "lark" /* Lark */;
|
|
4294
4881
|
return void 0;
|
|
4295
4882
|
};
|
|
4296
|
-
var extendApis = { lazySet, shallowSet };
|
|
4883
|
+
var extendApis = { lazySet, shallowSet, computed };
|
|
4297
4884
|
var StoreCache = /* @__PURE__ */ new Map();
|
|
4298
4885
|
function defineStore(name, creator, config2) {
|
|
4299
4886
|
if (StoreCache.has(name)) {
|
|
@@ -4304,18 +4891,20 @@ function defineStore(name, creator, config2) {
|
|
|
4304
4891
|
const StoreClass = adapter.Store;
|
|
4305
4892
|
const useStore = adapter.useStore;
|
|
4306
4893
|
const store = new StoreClass(name, config2);
|
|
4307
|
-
store[
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
extendApis
|
|
4311
|
-
)
|
|
4312
|
-
);
|
|
4894
|
+
const innerProxy = store[_innerStore]();
|
|
4895
|
+
const body = creator(innerProxy, extendApis);
|
|
4896
|
+
store[_storeCreate](body);
|
|
4313
4897
|
Object.defineProperties(useStore, {
|
|
4314
4898
|
$storeName: { value: name, configurable: true },
|
|
4315
|
-
$
|
|
4899
|
+
$destroyFn: { value: () => store[_storeDestroy](), configurable: true }
|
|
4316
4900
|
});
|
|
4317
4901
|
if (!StoreCache.has(name)) {
|
|
4318
|
-
StoreCache.set(name, {
|
|
4902
|
+
StoreCache.set(name, {
|
|
4903
|
+
store,
|
|
4904
|
+
creator,
|
|
4905
|
+
config: config2,
|
|
4906
|
+
useStore
|
|
4907
|
+
});
|
|
4319
4908
|
}
|
|
4320
4909
|
return useStore;
|
|
4321
4910
|
}
|
|
@@ -4337,7 +4926,7 @@ function getUseStore(name) {
|
|
|
4337
4926
|
return void 0;
|
|
4338
4927
|
}
|
|
4339
4928
|
function cloneStore(name, useStore, config2) {
|
|
4340
|
-
const oldStoreName = useStore
|
|
4929
|
+
const oldStoreName = useStore.$storeName ?? "";
|
|
4341
4930
|
const cached = StoreCache.get(oldStoreName);
|
|
4342
4931
|
const oldStoreCreator = cached?.creator;
|
|
4343
4932
|
const oldConfig = cached?.config || {};
|
|
@@ -4358,16 +4947,12 @@ function isStoreActive(name) {
|
|
|
4358
4947
|
}
|
|
4359
4948
|
var cellCount = 0;
|
|
4360
4949
|
function cell(data) {
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
linkKeys: `${LARK_GLOBAL}_${cellCount++}`
|
|
4364
|
-
});
|
|
4950
|
+
const linkKeys = `${LARK_GLOBAL}_${cellCount++}`;
|
|
4951
|
+
return createState(data, { belong: LARK_GLOBAL, linkKeys });
|
|
4365
4952
|
}
|
|
4366
4953
|
function observeCell(state, cb, immediate = true) {
|
|
4367
4954
|
const linkKeys = getLinkKeys(state);
|
|
4368
|
-
if (!linkKeys)
|
|
4369
|
-
return () => {
|
|
4370
|
-
};
|
|
4955
|
+
if (!linkKeys) return noop;
|
|
4371
4956
|
const keys2 = linkKeys.split(".");
|
|
4372
4957
|
const key = keys2[keys2.length - 1];
|
|
4373
4958
|
const list = [{ key, cb }];
|
|
@@ -4376,49 +4961,50 @@ function observeCell(state, cb, immediate = true) {
|
|
|
4376
4961
|
return () => clear({ belong: LARK_GLOBAL, clearList: list });
|
|
4377
4962
|
}
|
|
4378
4963
|
function multi(useStore) {
|
|
4379
|
-
const storeName = useStore
|
|
4380
|
-
const flagSym = `
|
|
4964
|
+
const storeName = useStore.$storeName ?? "";
|
|
4965
|
+
const flagSym = `lark-comp-${storeName}`;
|
|
4381
4966
|
const map = /* @__PURE__ */ new Map();
|
|
4382
4967
|
let rootViewPath;
|
|
4383
4968
|
const getFlag = (viewContext) => {
|
|
4384
|
-
const owner = viewContext
|
|
4385
|
-
const viewPath = owner?.
|
|
4386
|
-
const viewId = owner?.
|
|
4969
|
+
const owner = viewContext.owner;
|
|
4970
|
+
const viewPath = owner?.path ?? "";
|
|
4971
|
+
const viewId = owner?.id ?? "";
|
|
4387
4972
|
let flag;
|
|
4388
4973
|
if (viewPath === rootViewPath) {
|
|
4389
|
-
flag = `${flagSym}
|
|
4974
|
+
flag = `${flagSym}-${viewId}`;
|
|
4390
4975
|
} else {
|
|
4391
|
-
|
|
4976
|
+
const initParams = owner?.viewInitParams;
|
|
4977
|
+
const candidate = initParams?.[flagSym];
|
|
4978
|
+
flag = typeof candidate === "string" ? candidate : void 0;
|
|
4392
4979
|
}
|
|
4393
|
-
if (owner && isFunction(owner
|
|
4394
|
-
const rawMountFrame = owner
|
|
4395
|
-
owner
|
|
4980
|
+
if (owner && isFunction(owner.mountFrame)) {
|
|
4981
|
+
const rawMountFrame = owner.mountFrame;
|
|
4982
|
+
owner.mountFrame = (frameId, viewPath2, viewInitParams = {}) => rawMountFrame.call(
|
|
4396
4983
|
owner,
|
|
4397
|
-
|
|
4984
|
+
frameId,
|
|
4398
4985
|
viewPath2,
|
|
4399
4986
|
Object.assign(viewInitParams, { [flagSym]: flag })
|
|
4400
4987
|
);
|
|
4401
4988
|
}
|
|
4402
|
-
return flag;
|
|
4989
|
+
return flag ?? "";
|
|
4403
4990
|
};
|
|
4404
4991
|
const useFn = ((view) => {
|
|
4405
4992
|
if (!view)
|
|
4406
|
-
throw new Error(
|
|
4993
|
+
throw new Error(
|
|
4994
|
+
"[@lark.js/mvc error] multi: cannot find the view instance"
|
|
4995
|
+
);
|
|
4407
4996
|
const viewCtx = view;
|
|
4408
|
-
const
|
|
4997
|
+
const tag = viewCtx[flagSym];
|
|
4998
|
+
const flag = typeof tag === "string" ? tag : "";
|
|
4409
4999
|
if (map.has(flag)) return map.get(flag);
|
|
4410
|
-
const newFn = cloneStore(
|
|
4411
|
-
flag,
|
|
4412
|
-
useStore
|
|
4413
|
-
);
|
|
5000
|
+
const newFn = cloneStore(flag, useStore);
|
|
4414
5001
|
map.set(flag, newFn);
|
|
4415
5002
|
return useFn(view);
|
|
4416
5003
|
});
|
|
4417
5004
|
const mixinObj = {
|
|
4418
5005
|
make() {
|
|
4419
5006
|
if (!rootViewPath) {
|
|
4420
|
-
|
|
4421
|
-
rootViewPath = owner?.["path"] || "";
|
|
5007
|
+
rootViewPath = this.owner?.path ?? "";
|
|
4422
5008
|
}
|
|
4423
5009
|
this[flagSym] = getFlag(this);
|
|
4424
5010
|
}
|
|
@@ -4548,7 +5134,7 @@ function convertArtSyntax(source, debug) {
|
|
|
4548
5134
|
}
|
|
4549
5135
|
if (blockStack.length > 0) {
|
|
4550
5136
|
const unclosed = blockStack.map((b) => `"${b.ctrl}" at line ${b.line}`).join(", ");
|
|
4551
|
-
throw new Error(`[@lark/mvc error] unclosed block(s): ${unclosed}`);
|
|
5137
|
+
throw new Error(`[@lark.js/mvc error] unclosed block(s): ${unclosed}`);
|
|
4552
5138
|
}
|
|
4553
5139
|
return result.join("");
|
|
4554
5140
|
}
|
|
@@ -4625,7 +5211,7 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4625
5211
|
return `${debugPrefix}<%for(${forExpr}){%>`;
|
|
4626
5212
|
}
|
|
4627
5213
|
const tokens = code.split(/\s+/);
|
|
4628
|
-
const keyword = tokens.shift();
|
|
5214
|
+
const keyword = tokens.shift() ?? "";
|
|
4629
5215
|
switch (keyword) {
|
|
4630
5216
|
case "if": {
|
|
4631
5217
|
blockStack.push({ ctrl: "if", line: lineNo });
|
|
@@ -4642,12 +5228,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4642
5228
|
}
|
|
4643
5229
|
return `${debugPrefix}<%}else{%>`;
|
|
4644
5230
|
}
|
|
4645
|
-
case "
|
|
4646
|
-
blockStack.push({ ctrl: "
|
|
5231
|
+
case "forOf": {
|
|
5232
|
+
blockStack.push({ ctrl: "forOf", line: lineNo });
|
|
4647
5233
|
const object = tokens[0];
|
|
4648
5234
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4649
5235
|
throw new Error(
|
|
4650
|
-
`[@lark/mvc error] bad
|
|
5236
|
+
`[@lark.js/mvc error] bad forOf syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{forOf list as item [index]}}`
|
|
4651
5237
|
);
|
|
4652
5238
|
}
|
|
4653
5239
|
const restTokens = tokens.slice(2);
|
|
@@ -4669,12 +5255,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4669
5255
|
}
|
|
4670
5256
|
return `${debugPrefix}<%for(let ${index}=0${refExpr},${refObjCount}=${refObj}.length${lastCount};${index}<${refObjCount};${index}++){${firstAndLast}${valueDecl}%>`;
|
|
4671
5257
|
}
|
|
4672
|
-
case "
|
|
4673
|
-
blockStack.push({ ctrl: "
|
|
5258
|
+
case "forIn": {
|
|
5259
|
+
blockStack.push({ ctrl: "forIn", line: lineNo });
|
|
4674
5260
|
const object = tokens[0];
|
|
4675
5261
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4676
5262
|
throw new Error(
|
|
4677
|
-
`[@lark/mvc error] bad
|
|
5263
|
+
`[@lark.js/mvc error] bad forIn syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{for-in obj as val [key]}}`
|
|
4678
5264
|
);
|
|
4679
5265
|
}
|
|
4680
5266
|
const restTokens2 = tokens.slice(2);
|
|
@@ -4694,19 +5280,19 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4694
5280
|
case "set":
|
|
4695
5281
|
return `${debugPrefix}<%let ${tokens.join(" ")};%>`;
|
|
4696
5282
|
case "/if":
|
|
4697
|
-
case "/
|
|
4698
|
-
case "/
|
|
5283
|
+
case "/forOf":
|
|
5284
|
+
case "/forIn":
|
|
4699
5285
|
case "/for": {
|
|
4700
5286
|
const expectedCtrl = keyword.substring(1);
|
|
4701
5287
|
const last = blockStack.pop();
|
|
4702
5288
|
if (!last) {
|
|
4703
5289
|
throw new Error(
|
|
4704
|
-
`[@lark/mvc error] unexpected {{${code}}}: no matching open block`
|
|
5290
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: no matching open block`
|
|
4705
5291
|
);
|
|
4706
5292
|
}
|
|
4707
5293
|
if (last.ctrl !== expectedCtrl) {
|
|
4708
5294
|
throw new Error(
|
|
4709
|
-
`[@lark/mvc error] unexpected {{${code}}}: expected {{/${last.ctrl}}} to close block opened at line ${last.line}`
|
|
5295
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: expected {{/${last.ctrl}}} to close block opened at line ${last.line}`
|
|
4710
5296
|
);
|
|
4711
5297
|
}
|
|
4712
5298
|
return `${debugPrefix}<%}%>`;
|
|
@@ -4770,7 +5356,7 @@ function parseAsExpr(expr) {
|
|
|
4770
5356
|
function compileToFunction(source, debug, file) {
|
|
4771
5357
|
const matcher = /<%([@=!:])?([\s\S]*?)%>|$/g;
|
|
4772
5358
|
let index = 0;
|
|
4773
|
-
let funcSource = `$
|
|
5359
|
+
let funcSource = `$out+='`;
|
|
4774
5360
|
let hasAtRule = false;
|
|
4775
5361
|
const escapeSlashRegExp = /\\|'/g;
|
|
4776
5362
|
const escapeBreakReturnRegExp = /\r|\n/g;
|
|
@@ -4796,17 +5382,17 @@ function compileToFunction(source, debug, file) {
|
|
|
4796
5382
|
}
|
|
4797
5383
|
if (operate === "@") {
|
|
4798
5384
|
hasAtRule = true;
|
|
4799
|
-
funcSource += `'+($
|
|
5385
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$refFn($refAlt,${content}))+'`;
|
|
4800
5386
|
} else if (operate === "=" || operate === ":") {
|
|
4801
|
-
funcSource += `'+($
|
|
5387
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$encHtml(${content}))+'`;
|
|
4802
5388
|
} else if (operate === "!") {
|
|
4803
|
-
if (!content.startsWith("$
|
|
4804
|
-
content = `$
|
|
5389
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
5390
|
+
content = `$strSafe(${content})`;
|
|
4805
5391
|
}
|
|
4806
|
-
funcSource += `'+($
|
|
5392
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',${content})+'`;
|
|
4807
5393
|
} else if (content) {
|
|
4808
5394
|
if (line > -1) {
|
|
4809
|
-
funcSource += `';$
|
|
5395
|
+
funcSource += `';$dbgLine=${line};$dbgArt='${art}';`;
|
|
4810
5396
|
content = "";
|
|
4811
5397
|
} else {
|
|
4812
5398
|
funcSource += `';`;
|
|
@@ -4815,19 +5401,19 @@ function compileToFunction(source, debug, file) {
|
|
|
4815
5401
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4816
5402
|
}
|
|
4817
5403
|
if (expr) {
|
|
4818
|
-
funcSource += `$
|
|
5404
|
+
funcSource += `$dbgExpr='<%${expr}%>';`;
|
|
4819
5405
|
}
|
|
4820
|
-
funcSource += content + `;$
|
|
5406
|
+
funcSource += content + `;$out+='`;
|
|
4821
5407
|
}
|
|
4822
5408
|
} else {
|
|
4823
5409
|
if (operate === "@") {
|
|
4824
5410
|
hasAtRule = true;
|
|
4825
|
-
funcSource += `'+$
|
|
5411
|
+
funcSource += `'+$refFn($refAlt,${content})+'`;
|
|
4826
5412
|
} else if (operate === "=" || operate === ":") {
|
|
4827
|
-
funcSource += `'+$
|
|
5413
|
+
funcSource += `'+$encHtml(${content})+'`;
|
|
4828
5414
|
} else if (operate === "!") {
|
|
4829
|
-
if (!content.startsWith("$
|
|
4830
|
-
content = `$
|
|
5415
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
5416
|
+
content = `$strSafe(${content})`;
|
|
4831
5417
|
}
|
|
4832
5418
|
funcSource += `'+${content}+'`;
|
|
4833
5419
|
} else if (content) {
|
|
@@ -4835,28 +5421,24 @@ function compileToFunction(source, debug, file) {
|
|
|
4835
5421
|
if (funcSource.endsWith(`+'';`)) {
|
|
4836
5422
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4837
5423
|
}
|
|
4838
|
-
funcSource += `${content};$
|
|
5424
|
+
funcSource += `${content};$out+='`;
|
|
4839
5425
|
}
|
|
4840
5426
|
}
|
|
4841
5427
|
return match;
|
|
4842
5428
|
});
|
|
4843
5429
|
funcSource += `';`;
|
|
4844
|
-
funcSource = funcSource.replace(/\$
|
|
4845
|
-
funcSource = funcSource.replace(/\$
|
|
5430
|
+
funcSource = funcSource.replace(/\$out\+='';/g, "");
|
|
5431
|
+
funcSource = funcSource.replace(/\$out\+=''\+/g, "$out+=");
|
|
4846
5432
|
if (debug) {
|
|
4847
5433
|
const filePart = file ? `\\r\\n\\tat file:${file}` : "";
|
|
4848
|
-
funcSource = `let $
|
|
5434
|
+
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;}`;
|
|
4849
5435
|
}
|
|
4850
5436
|
const viewIdRegExp = new RegExp(String.fromCharCode(31), "g");
|
|
4851
5437
|
funcSource = funcSource.replace(viewIdRegExp, `'+$viewId+'`);
|
|
4852
|
-
|
|
4853
|
-
const
|
|
4854
|
-
const
|
|
4855
|
-
|
|
4856
|
-
const refFallback = "if(!$$ref)$$ref=$$;";
|
|
4857
|
-
const fns = `${refFallback}${encode}${encodeURIMore}${encodeQuote}${atRule};`;
|
|
4858
|
-
const fullSource = `${fns}let $g='\\x1e',$_temp,$p=''{{VARS}};${funcSource}return $p`;
|
|
4859
|
-
return `($$,$viewId,$$ref,$e,$n,$eu,$i,$eq)=>{${fullSource}}`;
|
|
5438
|
+
void hasAtRule;
|
|
5439
|
+
const refFallback = "if(!$refAlt)$refAlt=$data;";
|
|
5440
|
+
const fullSource = `${refFallback}let $splitter='\\x1e',$tmp,$out=''{{VARS}};${funcSource}return $out`;
|
|
5441
|
+
return `($data,$viewId,$refAlt,$encHtml,$strSafe,$encUri,$refFn,$encQuote)=>{${fullSource}}`;
|
|
4860
5442
|
}
|
|
4861
5443
|
function compileTemplate(source, options = {}) {
|
|
4862
5444
|
const { debug = false, globalVars = [], file } = options;
|
|
@@ -4865,17 +5447,14 @@ function compileTemplate(source, options = {}) {
|
|
|
4865
5447
|
const viewEventProcessed = processViewEvents(converted);
|
|
4866
5448
|
const finalSource = restoreComments(viewEventProcessed, comments);
|
|
4867
5449
|
const funcBody = compileToFunction(finalSource, debug, file);
|
|
4868
|
-
const varDeclarations = globalVars.map((key) => `,${key}
|
|
5450
|
+
const varDeclarations = globalVars.map((key) => `,${key}=$data.${key}`).join("");
|
|
4869
5451
|
const funcWithVars = funcBody.replace("{{VARS}}", () => varDeclarations);
|
|
4870
|
-
return `
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
/* $eu */ null,
|
|
4877
|
-
/* $i */ null,
|
|
4878
|
-
/* $eq */ null
|
|
5452
|
+
return `import { encHtml as __larkEncHtml, strSafe as __larkStrSafe, encUri as __larkEncUri, encQuote as __larkEncQuote, refFn as __larkRefFn } from "@lark.js/mvc/runtime";
|
|
5453
|
+
export default function(data, viewId, refData) {
|
|
5454
|
+
let $data = data || {},
|
|
5455
|
+
$viewId = viewId || '';
|
|
5456
|
+
return (${funcWithVars})($data, $viewId, refData,
|
|
5457
|
+
__larkEncHtml, __larkStrSafe, __larkEncUri, __larkRefFn, __larkEncQuote
|
|
4879
5458
|
);
|
|
4880
5459
|
}`;
|
|
4881
5460
|
}
|
|
@@ -4984,7 +5563,7 @@ function fallbackExtractVariables(source) {
|
|
|
4984
5563
|
while ((m = outputRegExp.exec(source)) !== null) {
|
|
4985
5564
|
vars.add(m[1]);
|
|
4986
5565
|
}
|
|
4987
|
-
const eachRegExp = /\{\{
|
|
5566
|
+
const eachRegExp = /\{\{forOf\s+([a-zA-Z_$][\w$]*)\s+as/g;
|
|
4988
5567
|
while ((m = eachRegExp.exec(source)) !== null) {
|
|
4989
5568
|
vars.add(m[1]);
|
|
4990
5569
|
}
|
|
@@ -5000,82 +5579,100 @@ function walkAst(ast, visitors) {
|
|
|
5000
5579
|
if (visitors[type]) {
|
|
5001
5580
|
visitors[type](node);
|
|
5002
5581
|
}
|
|
5582
|
+
const bag = node;
|
|
5003
5583
|
for (const key of Object.keys(node)) {
|
|
5004
5584
|
if (key === "type" || key === "start" || key === "end" || key === "loc" || key === "range")
|
|
5005
5585
|
continue;
|
|
5006
|
-
if (type === "MemberExpression" && key === "property"
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
continue;
|
|
5586
|
+
if (type === "MemberExpression" && key === "property") {
|
|
5587
|
+
const me = node;
|
|
5588
|
+
if (!me.computed) continue;
|
|
5010
5589
|
}
|
|
5011
|
-
if (type === "
|
|
5012
|
-
|
|
5590
|
+
if (type === "ObjectProperty" && key === "key") {
|
|
5591
|
+
const op = node;
|
|
5592
|
+
if (!op.computed) continue;
|
|
5013
5593
|
}
|
|
5014
|
-
|
|
5594
|
+
if (type === "ObjectMethod" && key === "key") {
|
|
5595
|
+
const om = node;
|
|
5596
|
+
if (!om.computed) continue;
|
|
5597
|
+
}
|
|
5598
|
+
const child = bag[key];
|
|
5015
5599
|
if (Array.isArray(child)) {
|
|
5016
5600
|
for (const item of child) {
|
|
5017
|
-
if (item
|
|
5018
|
-
visit(item);
|
|
5019
|
-
}
|
|
5601
|
+
if (isAstNode(item)) visit(item);
|
|
5020
5602
|
}
|
|
5021
|
-
} else if (child
|
|
5603
|
+
} else if (isAstNode(child)) {
|
|
5022
5604
|
visit(child);
|
|
5023
5605
|
}
|
|
5024
5606
|
}
|
|
5025
5607
|
}
|
|
5026
5608
|
visit(ast);
|
|
5027
5609
|
}
|
|
5610
|
+
function isAstNode(v) {
|
|
5611
|
+
return !!v && typeof v === "object" && typeof v.type === "string";
|
|
5612
|
+
}
|
|
5028
5613
|
var BUILTIN_GLOBALS = {
|
|
5029
5614
|
// ─── Template runtime helpers (injected by compileToFunction) ───────
|
|
5030
5615
|
//
|
|
5031
5616
|
// These variables appear in the generated template function signature
|
|
5032
5617
|
// or body. They must be excluded from extractGlobalVars() so that
|
|
5033
|
-
// they are not mistaken for user data variables and destructured from
|
|
5618
|
+
// they are not mistaken for user data variables and destructured from $data.
|
|
5034
5619
|
// SPLITTER character constant (same as \x1e), used as namespace separator
|
|
5035
5620
|
// for refData keys, event attribute encoding, and internal data structures.
|
|
5036
|
-
// Declared as: let $
|
|
5037
|
-
$
|
|
5038
|
-
//
|
|
5039
|
-
// User variables are destructured from
|
|
5040
|
-
// let {name, age} =
|
|
5621
|
+
// Declared as: let $splitter='\x1e'
|
|
5622
|
+
$splitter: 1,
|
|
5623
|
+
// Data — the data object passed from Updater to the template function.
|
|
5624
|
+
// User variables are destructured from $data at the top of the function:
|
|
5625
|
+
// let {name, age} = $data;
|
|
5041
5626
|
// This is the first parameter of the generated arrow function.
|
|
5042
|
-
|
|
5627
|
+
$data: 1,
|
|
5043
5628
|
// Null-safe toString: v => '' + (v == null ? '' : v)
|
|
5044
5629
|
// Converts null/undefined to empty string, otherwise calls toString().
|
|
5045
5630
|
// Wraps every {{!raw}} output to prevent "null" / "undefined" rendering.
|
|
5046
|
-
$
|
|
5047
|
-
// HTML entity encoder: v => $
|
|
5631
|
+
$strSafe: 1,
|
|
5632
|
+
// HTML entity encoder: v => $strSafe(v).replace(/[&<>"'`]/g, entityMap)
|
|
5048
5633
|
// Encodes &, <, >, ", ', ` to HTML entities (& < etc.)
|
|
5049
5634
|
// Applied to all {{=escaped}} and {{:binding}} outputs.
|
|
5050
|
-
$
|
|
5051
|
-
// HTML entity map — internal object used by $
|
|
5635
|
+
$encHtml: 1,
|
|
5636
|
+
// HTML entity map — internal object used by $encHtml:
|
|
5052
5637
|
// {'&':'amp','<':'gt','>':'gt','"':'#34','\'':'#39','`':'#96'}
|
|
5053
|
-
// Not a standalone function; referenced inside $
|
|
5054
|
-
$
|
|
5055
|
-
// HTML entity RegExp — internal regexp used by $
|
|
5638
|
+
// Not a standalone function; referenced inside $encHtml's closure.
|
|
5639
|
+
$entMap: 1,
|
|
5640
|
+
// HTML entity RegExp — internal regexp used by $encHtml:
|
|
5056
5641
|
// /[&<>"'`]/g
|
|
5057
|
-
$
|
|
5058
|
-
// HTML entity replacer function — internal helper used by $
|
|
5059
|
-
// m => '&' + $
|
|
5060
|
-
// Maps
|
|
5061
|
-
$
|
|
5642
|
+
$entReg: 1,
|
|
5643
|
+
// HTML entity replacer function — internal helper used by $encHtml:
|
|
5644
|
+
// m => '&' + $entMap[m] + ';'
|
|
5645
|
+
// Maps matched character to its entity string.
|
|
5646
|
+
$entFn: 1,
|
|
5062
5647
|
// Output buffer — the string accumulator for rendered HTML.
|
|
5063
|
-
// All template output is appended via $
|
|
5064
|
-
// Declared as: let $
|
|
5065
|
-
$
|
|
5648
|
+
// All template output is appended via $out += '...'.
|
|
5649
|
+
// Declared as: let $out = ''
|
|
5650
|
+
$out: 1,
|
|
5066
5651
|
// Reference lookup: (refData, value) => key
|
|
5067
5652
|
// Finds or allocates a SPLITTER-prefixed key in refData for a given
|
|
5068
5653
|
// object reference. Used by {{@ref}} operator for passing object
|
|
5069
5654
|
// references to child views via v-lark attributes.
|
|
5070
|
-
$
|
|
5071
|
-
// URI encoder: v => encodeURIComponent($
|
|
5655
|
+
$refFn: 1,
|
|
5656
|
+
// URI encoder: v => encodeURIComponent($strSafe(v)).replace(/[!')(*]/g, extraMap)
|
|
5072
5657
|
// Extends encodeURIComponent with encoding of ! ' ( ) *.
|
|
5073
5658
|
// Applied to values in @event URL parameters and {{!uri}} contexts.
|
|
5074
|
-
$
|
|
5075
|
-
//
|
|
5659
|
+
$encUri: 1,
|
|
5660
|
+
// URI encode map — internal object used by $encUri:
|
|
5661
|
+
// {'!':'%21','\'':'%27','(':'%28',')':'%29','*':'%2A'}
|
|
5662
|
+
$uriMap: 1,
|
|
5663
|
+
// URI encode replacer — internal helper used by $encUri:
|
|
5664
|
+
// m => $uriMap[m]
|
|
5665
|
+
$uriFn: 1,
|
|
5666
|
+
// URI encode regexp — internal regexp used by $encUri:
|
|
5667
|
+
// /[!')(*]/g
|
|
5668
|
+
$uriReg: 1,
|
|
5669
|
+
// Quote encoder: v => $strSafe(v).replace(/['"\\]/g, '\\$&')
|
|
5076
5670
|
// Escapes quotes and backslashes for safe embedding in HTML attribute
|
|
5077
5671
|
// values (e.g. data-json='...').
|
|
5078
|
-
$
|
|
5672
|
+
$encQuote: 1,
|
|
5673
|
+
// Quote encode regexp — internal regexp used by $encQuote:
|
|
5674
|
+
// /['"\\]/g
|
|
5675
|
+
$qReg: 1,
|
|
5079
5676
|
// View ID — the unique identifier of the owning View instance.
|
|
5080
5677
|
// Injected into @event attribute values at render time so that
|
|
5081
5678
|
// EventDelegator can dispatch events to the correct View handler.
|
|
@@ -5083,23 +5680,23 @@ var BUILTIN_GLOBALS = {
|
|
|
5083
5680
|
$viewId: 1,
|
|
5084
5681
|
// Debug: current expression text — stores the template expression being
|
|
5085
5682
|
// evaluated, for error reporting. Only present in debug mode.
|
|
5086
|
-
// e.g. $
|
|
5087
|
-
$
|
|
5683
|
+
// e.g. $dbgExpr='<%=user.name%>'
|
|
5684
|
+
$dbgExpr: 1,
|
|
5088
5685
|
// Debug: original art syntax — stores the {{}} template syntax before
|
|
5089
5686
|
// conversion, for error reporting. Only present in debug mode.
|
|
5090
|
-
// e.g. $
|
|
5091
|
-
$
|
|
5687
|
+
// e.g. $dbgArt='{{=user.name}}'
|
|
5688
|
+
$dbgArt: 1,
|
|
5092
5689
|
// Debug: source line number — tracks the current line in the template
|
|
5093
5690
|
// source, for error reporting. Only present in debug mode.
|
|
5094
|
-
$
|
|
5095
|
-
//
|
|
5096
|
-
// Defaults to
|
|
5097
|
-
// Ensures $
|
|
5098
|
-
|
|
5691
|
+
$dbgLine: 1,
|
|
5692
|
+
// RefData alias — fallback reference lookup table.
|
|
5693
|
+
// Defaults to $data when no explicit $refAlt is provided.
|
|
5694
|
+
// Ensures $refFn() does not crash when @ operator is used without refData.
|
|
5695
|
+
$refAlt: 1,
|
|
5099
5696
|
// Temporary variable — used by the compiler for intermediate
|
|
5100
5697
|
// expression results in generated code (e.g. loop variables,
|
|
5101
|
-
// conditional branches). Declared as: let $
|
|
5102
|
-
$
|
|
5698
|
+
// conditional branches). Declared as: let $tmp
|
|
5699
|
+
$tmp: 1,
|
|
5103
5700
|
// JS literals
|
|
5104
5701
|
undefined: 1,
|
|
5105
5702
|
null: 1,
|
|
@@ -5165,15 +5762,17 @@ var BUILTIN_GLOBALS = {
|
|
|
5165
5762
|
var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
5166
5763
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5167
5764
|
0 && (module.exports = {
|
|
5168
|
-
Bag,
|
|
5169
5765
|
CALL_BREAK_TIME,
|
|
5170
5766
|
Cache,
|
|
5767
|
+
CrossSite,
|
|
5171
5768
|
EVENT_METHOD_REGEXP,
|
|
5172
5769
|
EventDelegator,
|
|
5173
5770
|
EventEmitter,
|
|
5174
5771
|
Frame,
|
|
5772
|
+
FrameVisualBridge,
|
|
5175
5773
|
Framework,
|
|
5176
5774
|
LARK_VIEW,
|
|
5775
|
+
Payload,
|
|
5177
5776
|
Platform,
|
|
5178
5777
|
ROUTER_EVENTS,
|
|
5179
5778
|
Router,
|
|
@@ -5189,13 +5788,14 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5189
5788
|
applyVdomOps,
|
|
5190
5789
|
assign,
|
|
5191
5790
|
cell,
|
|
5192
|
-
classExtend,
|
|
5193
5791
|
cloneData,
|
|
5194
5792
|
cloneStore,
|
|
5195
5793
|
compileTemplate,
|
|
5794
|
+
computed,
|
|
5196
5795
|
createState,
|
|
5197
5796
|
createVdomRef,
|
|
5198
5797
|
defineStore,
|
|
5798
|
+
defineView,
|
|
5199
5799
|
delStore,
|
|
5200
5800
|
encodeHTML,
|
|
5201
5801
|
encodeQ,
|
|
@@ -5203,6 +5803,7 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5203
5803
|
encodeURIExtra,
|
|
5204
5804
|
ensureElementId,
|
|
5205
5805
|
extractGlobalVars,
|
|
5806
|
+
frameworkConfig,
|
|
5206
5807
|
funcWithTry,
|
|
5207
5808
|
generateId,
|
|
5208
5809
|
getAttribute,
|
|
@@ -5210,9 +5811,9 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5210
5811
|
getPlatform,
|
|
5211
5812
|
getStore,
|
|
5212
5813
|
getUseStore,
|
|
5213
|
-
|
|
5814
|
+
hasOwnProperty,
|
|
5214
5815
|
installFrameVisualizerBridge,
|
|
5215
|
-
|
|
5816
|
+
invalidateViewClass,
|
|
5216
5817
|
isPlainObject,
|
|
5217
5818
|
isPrimitive,
|
|
5218
5819
|
isPrimitiveOrFunc,
|
|
@@ -5231,6 +5832,7 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5231
5832
|
observeCell,
|
|
5232
5833
|
parseUri,
|
|
5233
5834
|
registerViewClass,
|
|
5835
|
+
resetProjectsMap,
|
|
5234
5836
|
safeguard,
|
|
5235
5837
|
serializeFrameTree,
|
|
5236
5838
|
setData,
|
|
@@ -5242,6 +5844,7 @@ var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
|
5242
5844
|
toUri,
|
|
5243
5845
|
translateData,
|
|
5244
5846
|
unmark,
|
|
5847
|
+
use,
|
|
5245
5848
|
vdomGetCompareKey,
|
|
5246
5849
|
vdomGetNode,
|
|
5247
5850
|
vdomSetAttributes,
|