@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.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
2
|
var globalCounter = 0;
|
|
3
3
|
var SPLITTER = "";
|
|
4
|
-
var
|
|
4
|
+
var RouterEvents = {
|
|
5
5
|
CHANGE: "change",
|
|
6
6
|
CHANGED: "changed",
|
|
7
7
|
PAGE_UNLOAD: "page_unload"
|
|
8
8
|
};
|
|
9
|
-
var
|
|
9
|
+
var LarkInnerKeys = {
|
|
10
10
|
/** Attribute name: ldk (static key for skipping VDOM diff) */
|
|
11
11
|
DIFF_KEY: "ldk",
|
|
12
12
|
/** Attribute name: lak (static attribute key) */
|
|
@@ -38,7 +38,6 @@ function isPlainObject(value) {
|
|
|
38
38
|
if (proto === null) return true;
|
|
39
39
|
return proto === Object.prototype || proto === null;
|
|
40
40
|
}
|
|
41
|
-
var isArray = Array.isArray;
|
|
42
41
|
function isPrimitiveOrFunc(value) {
|
|
43
42
|
return !value || typeof value !== "object" && typeof value !== "function";
|
|
44
43
|
}
|
|
@@ -54,13 +53,13 @@ function syncCounter(val) {
|
|
|
54
53
|
}
|
|
55
54
|
function noop() {
|
|
56
55
|
}
|
|
57
|
-
function
|
|
56
|
+
function hasOwnProperty(owner, prop) {
|
|
58
57
|
return owner != null && Object.prototype.hasOwnProperty.call(owner, prop);
|
|
59
58
|
}
|
|
60
59
|
function keys(obj) {
|
|
61
60
|
const result = [];
|
|
62
61
|
for (const p in obj) {
|
|
63
|
-
if (
|
|
62
|
+
if (hasOwnProperty(obj, p)) {
|
|
64
63
|
result.push(p);
|
|
65
64
|
}
|
|
66
65
|
}
|
|
@@ -70,7 +69,7 @@ function assign(target, ...sources) {
|
|
|
70
69
|
for (const source of sources) {
|
|
71
70
|
if (source) {
|
|
72
71
|
for (const p in source) {
|
|
73
|
-
if (
|
|
72
|
+
if (hasOwnProperty(source, p)) {
|
|
74
73
|
target[p] = source[p];
|
|
75
74
|
}
|
|
76
75
|
}
|
|
@@ -79,25 +78,26 @@ function assign(target, ...sources) {
|
|
|
79
78
|
return target;
|
|
80
79
|
}
|
|
81
80
|
function funcWithTry(fns, args, context, configError) {
|
|
82
|
-
const fnArray = isArray(fns) ? fns : [fns];
|
|
81
|
+
const fnArray = Array.isArray(fns) ? fns : [fns];
|
|
83
82
|
let ret;
|
|
84
83
|
for (const fn of fnArray) {
|
|
85
84
|
try {
|
|
86
|
-
ret =
|
|
85
|
+
ret = fn.apply(context, args);
|
|
87
86
|
} catch (e) {
|
|
88
|
-
configError(e);
|
|
87
|
+
configError?.(e);
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
return ret;
|
|
92
91
|
}
|
|
92
|
+
var EMPTY_STRING_SET = /* @__PURE__ */ new Set();
|
|
93
93
|
function setData(newData, oldData, changedKeys2, excludes) {
|
|
94
94
|
let changed = false;
|
|
95
95
|
for (const p in newData) {
|
|
96
|
-
if (
|
|
96
|
+
if (hasOwnProperty(newData, p)) {
|
|
97
97
|
const now2 = newData[p];
|
|
98
98
|
const old = oldData[p];
|
|
99
99
|
if ((!isPrimitiveOrFunc(now2) || old !== now2) && !excludes.has(p)) {
|
|
100
|
-
changedKeys2
|
|
100
|
+
changedKeys2.add(p);
|
|
101
101
|
changed = true;
|
|
102
102
|
}
|
|
103
103
|
oldData[p] = now2;
|
|
@@ -105,17 +105,25 @@ function setData(newData, oldData, changedKeys2, excludes) {
|
|
|
105
105
|
}
|
|
106
106
|
return changed;
|
|
107
107
|
}
|
|
108
|
+
function isRefToken(s) {
|
|
109
|
+
if (s.length < 2 || s[0] !== SPLITTER) return false;
|
|
110
|
+
for (let i = 1; i < s.length; i++) {
|
|
111
|
+
const c = s.charCodeAt(i);
|
|
112
|
+
if (c < 48 || c > 57) return false;
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
108
116
|
function translateData(data, value) {
|
|
109
117
|
if (isPrimitive(value)) {
|
|
110
118
|
const prop = String(value);
|
|
111
|
-
if (prop
|
|
119
|
+
if (isRefToken(prop) && hasOwnProperty(data, prop)) {
|
|
112
120
|
return data[prop];
|
|
113
121
|
}
|
|
114
122
|
return value;
|
|
115
123
|
}
|
|
116
|
-
if (isPlainObject(value) || isArray(value)) {
|
|
124
|
+
if (isPlainObject(value) || Array.isArray(value)) {
|
|
117
125
|
for (const p in value) {
|
|
118
|
-
if (
|
|
126
|
+
if (hasOwnProperty(value, p)) {
|
|
119
127
|
const val = value[p];
|
|
120
128
|
const newVal = translateData(data, val);
|
|
121
129
|
value[p] = newVal;
|
|
@@ -152,38 +160,33 @@ function nodeInside(a, b) {
|
|
|
152
160
|
return false;
|
|
153
161
|
}
|
|
154
162
|
}
|
|
155
|
-
var paramsTemp = {};
|
|
156
|
-
function paramsReplacer(_match, name, value) {
|
|
157
|
-
try {
|
|
158
|
-
paramsTemp[name] = decodeURIComponent(value || "");
|
|
159
|
-
} catch {
|
|
160
|
-
paramsTemp[name] = value || "";
|
|
161
|
-
}
|
|
162
|
-
return "";
|
|
163
|
-
}
|
|
164
163
|
function parseUri(uri) {
|
|
165
|
-
|
|
164
|
+
const params = {};
|
|
166
165
|
const path = uri.replace(URL_QUERY_HASH_REGEXP, "");
|
|
167
166
|
const pathname = path;
|
|
168
167
|
const actualPath = uri === pathname && IS_URL_PARAMS.test(pathname) ? "" : pathname;
|
|
169
|
-
uri.replace(actualPath, "").replace(URL_PARAM_REGEXP,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
168
|
+
uri.replace(actualPath, "").replace(URL_PARAM_REGEXP, (_match, name, value) => {
|
|
169
|
+
try {
|
|
170
|
+
params[name] = decodeURIComponent(value || "");
|
|
171
|
+
} catch {
|
|
172
|
+
params[name] = value || "";
|
|
173
|
+
}
|
|
174
|
+
return "";
|
|
175
|
+
});
|
|
176
|
+
return { path: actualPath, params };
|
|
174
177
|
}
|
|
175
178
|
var IS_URL_PARAMS = {
|
|
176
179
|
test(s) {
|
|
177
180
|
return /(?!^)=|&/.test(s);
|
|
178
181
|
}
|
|
179
182
|
};
|
|
180
|
-
function toUri(path, params,
|
|
183
|
+
function toUri(path, params, keepEmpty) {
|
|
181
184
|
const pairs = [];
|
|
182
185
|
let hasParams = false;
|
|
183
186
|
for (const p in params) {
|
|
184
|
-
if (
|
|
187
|
+
if (hasOwnProperty(params, p)) {
|
|
185
188
|
const v = String(params[p] ?? "");
|
|
186
|
-
if (!
|
|
189
|
+
if (!keepEmpty || v || keepEmpty.has(p)) {
|
|
187
190
|
pairs.push(`${p}=${encodeURIComponent(v)}`);
|
|
188
191
|
hasParams = true;
|
|
189
192
|
}
|
|
@@ -206,14 +209,6 @@ function toMap(list, key) {
|
|
|
206
209
|
function now() {
|
|
207
210
|
return Date.now ? Date.now() : (/* @__PURE__ */ new Date()).getTime();
|
|
208
211
|
}
|
|
209
|
-
function classExtend(make, base, props, statics) {
|
|
210
|
-
const baseProto = base["prototype"] ?? {};
|
|
211
|
-
const cProto = Object.create(baseProto);
|
|
212
|
-
assign(cProto, props);
|
|
213
|
-
Object.assign(make, statics);
|
|
214
|
-
cProto.constructor = make;
|
|
215
|
-
make["prototype"] = cProto;
|
|
216
|
-
}
|
|
217
212
|
|
|
218
213
|
// src/apply-style.ts
|
|
219
214
|
var injectedStyleIds = /* @__PURE__ */ new Set();
|
|
@@ -253,32 +248,40 @@ function applyStyle(styleIdOrPairs, css) {
|
|
|
253
248
|
}
|
|
254
249
|
|
|
255
250
|
// src/mark.ts
|
|
256
|
-
var
|
|
257
|
-
|
|
251
|
+
var hostStore = /* @__PURE__ */ new WeakMap();
|
|
252
|
+
function getOrCreate(host) {
|
|
253
|
+
let record = hostStore.get(host);
|
|
254
|
+
if (!record) {
|
|
255
|
+
record = { signs: /* @__PURE__ */ new Map(), deleted: false };
|
|
256
|
+
hostStore.set(host, record);
|
|
257
|
+
}
|
|
258
|
+
return record;
|
|
259
|
+
}
|
|
258
260
|
function mark(host, key) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const markHost = hostRecord[MARK_OBJECT_KEY] || (hostRecord[MARK_OBJECT_KEY] = {});
|
|
263
|
-
if (!Object.prototype.hasOwnProperty.call(markHost, key)) {
|
|
264
|
-
markHost[key] = 0;
|
|
265
|
-
}
|
|
266
|
-
sign = ++markHost[key];
|
|
261
|
+
const record = getOrCreate(host);
|
|
262
|
+
if (record.deleted) {
|
|
263
|
+
return () => false;
|
|
267
264
|
}
|
|
265
|
+
const sign = (record.signs.get(key) ?? 0) + 1;
|
|
266
|
+
record.signs.set(key, sign);
|
|
268
267
|
return () => {
|
|
269
|
-
const
|
|
270
|
-
return !!
|
|
268
|
+
const current = hostStore.get(host);
|
|
269
|
+
return !!current && !current.deleted && current.signs.get(key) === sign;
|
|
271
270
|
};
|
|
272
271
|
}
|
|
273
272
|
function unmark(host) {
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
273
|
+
const record = hostStore.get(host);
|
|
274
|
+
if (record) {
|
|
275
|
+
record.deleted = true;
|
|
276
|
+
record.signs.clear();
|
|
277
|
+
} else {
|
|
278
|
+
hostStore.set(host, { signs: /* @__PURE__ */ new Map(), deleted: true });
|
|
279
|
+
}
|
|
277
280
|
}
|
|
278
281
|
|
|
279
282
|
// src/safeguard.ts
|
|
280
283
|
var proxiesPool = /* @__PURE__ */ new Map();
|
|
281
|
-
var SAFEGUARD_SENTINEL = "
|
|
284
|
+
var SAFEGUARD_SENTINEL = "_safe_";
|
|
282
285
|
function safeguard(data, getter, setter, isRoot) {
|
|
283
286
|
if (typeof window.__lark_Debug === "undefined" || !window.__lark_Debug) {
|
|
284
287
|
return data;
|
|
@@ -319,7 +322,7 @@ function safeguard(data, getter, setter, isRoot) {
|
|
|
319
322
|
if (!prefix && getter) {
|
|
320
323
|
getter(property);
|
|
321
324
|
}
|
|
322
|
-
if (!isRoot &&
|
|
325
|
+
if (!isRoot && hasOwnProperty(target, property) && (Array.isArray(out) || isPlainObject(out))) {
|
|
323
326
|
return build(prefix + property + ".", out);
|
|
324
327
|
}
|
|
325
328
|
return out;
|
|
@@ -408,15 +411,17 @@ var Cache = class {
|
|
|
408
411
|
this.lookup.set(prefixedKey, entry);
|
|
409
412
|
}
|
|
410
413
|
/**
|
|
411
|
-
* Delete a cached entry.
|
|
414
|
+
* Delete a cached entry. Removes it immediately from both the lookup map
|
|
415
|
+
* and the entries array so the GC can reclaim the value without waiting
|
|
416
|
+
* for the next eviction sweep.
|
|
412
417
|
*/
|
|
413
418
|
del(key) {
|
|
414
419
|
const prefixedKey = this.prefixKey(key);
|
|
415
420
|
const entry = this.lookup.get(prefixedKey);
|
|
416
421
|
if (!entry) return;
|
|
417
|
-
entry.frequency = -1;
|
|
418
|
-
entry.value = void 0;
|
|
419
422
|
this.lookup.delete(prefixedKey);
|
|
423
|
+
const idx = this.entries.indexOf(entry);
|
|
424
|
+
if (idx !== -1) this.entries.splice(idx, 1);
|
|
420
425
|
if (this.onRemove) {
|
|
421
426
|
this.onRemove(key);
|
|
422
427
|
}
|
|
@@ -441,20 +446,46 @@ var Cache = class {
|
|
|
441
446
|
this.entries = [];
|
|
442
447
|
this.lookup.clear();
|
|
443
448
|
}
|
|
444
|
-
/**
|
|
449
|
+
/**
|
|
450
|
+
* Evict the `bufferSize` worst entries from the cache.
|
|
451
|
+
*
|
|
452
|
+
* Uses single-pass partial selection (O(n·k)) instead of sorting the entire
|
|
453
|
+
* `entries` array (O(n log n)). For the typical `bufferSize = 5` this is
|
|
454
|
+
* effectively a linear scan with at most 5 in-bucket comparisons per
|
|
455
|
+
* iteration — and it avoids mutating the rest of `entries`.
|
|
456
|
+
*/
|
|
445
457
|
evictEntries() {
|
|
446
|
-
this.entries
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
this.lookup.delete(this.prefixKey(
|
|
452
|
-
if (this.onRemove)
|
|
453
|
-
|
|
454
|
-
|
|
458
|
+
const entries = this.entries;
|
|
459
|
+
const k = this.bufferSize;
|
|
460
|
+
if (k <= 0 || entries.length === 0) return;
|
|
461
|
+
if (entries.length <= k) {
|
|
462
|
+
for (const e of entries) {
|
|
463
|
+
this.lookup.delete(this.prefixKey(e.originalKey));
|
|
464
|
+
if (this.onRemove) this.onRemove(e.originalKey);
|
|
465
|
+
}
|
|
466
|
+
this.entries = [];
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const cmp = this.comparator;
|
|
470
|
+
const worst = [];
|
|
471
|
+
for (const entry of entries) {
|
|
472
|
+
if (worst.length < k) {
|
|
473
|
+
let i = worst.length;
|
|
474
|
+
while (i > 0 && cmp(entry, worst[i - 1]) > 0) i--;
|
|
475
|
+
worst.splice(i, 0, entry);
|
|
476
|
+
} else if (cmp(entry, worst[k - 1]) > 0) {
|
|
477
|
+
worst.pop();
|
|
478
|
+
let i = worst.length;
|
|
479
|
+
while (i > 0 && cmp(entry, worst[i - 1]) > 0) i--;
|
|
480
|
+
worst.splice(i, 0, entry);
|
|
455
481
|
}
|
|
456
482
|
}
|
|
457
|
-
|
|
483
|
+
const evictSet = new Set(worst);
|
|
484
|
+
for (const e of worst) {
|
|
485
|
+
this.lookup.delete(this.prefixKey(e.originalKey));
|
|
486
|
+
if (this.onRemove) this.onRemove(e.originalKey);
|
|
487
|
+
}
|
|
488
|
+
this.entries = entries.filter((e) => !evictSet.has(e));
|
|
458
489
|
}
|
|
459
490
|
};
|
|
460
491
|
|
|
@@ -462,6 +493,10 @@ var Cache = class {
|
|
|
462
493
|
var EventEmitter = class {
|
|
463
494
|
/** Event listeners: prefixed key -> listener array */
|
|
464
495
|
listeners = /* @__PURE__ */ new Map();
|
|
496
|
+
/** Number of `fire()` calls currently on the stack (re-entrancy depth). */
|
|
497
|
+
firingDepth = 0;
|
|
498
|
+
/** Keys whose listener list needs compaction after firing settles. */
|
|
499
|
+
pendingCompaction;
|
|
465
500
|
/**
|
|
466
501
|
* Bind event listener.
|
|
467
502
|
*/
|
|
@@ -484,24 +519,37 @@ var EventEmitter = class {
|
|
|
484
519
|
const key = SPLITTER + event;
|
|
485
520
|
if (handler) {
|
|
486
521
|
const list = this.listeners.get(key);
|
|
487
|
-
if (list)
|
|
522
|
+
if (!list) return this;
|
|
523
|
+
if (this.firingDepth > 0) {
|
|
488
524
|
for (const listener of list) {
|
|
489
525
|
if (listener.handler === handler) {
|
|
490
526
|
listener.handler = noop;
|
|
527
|
+
(this.pendingCompaction ??= /* @__PURE__ */ new Set()).add(key);
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
} else {
|
|
532
|
+
for (let i = 0; i < list.length; i++) {
|
|
533
|
+
if (list[i].handler === handler) {
|
|
534
|
+
list.splice(i, 1);
|
|
491
535
|
break;
|
|
492
536
|
}
|
|
493
537
|
}
|
|
538
|
+
if (list.length === 0) this.listeners.delete(key);
|
|
494
539
|
}
|
|
495
540
|
} else {
|
|
496
541
|
this.listeners.delete(key);
|
|
497
|
-
Reflect.deleteProperty(
|
|
542
|
+
Reflect.deleteProperty(
|
|
543
|
+
this,
|
|
544
|
+
`on${event[0].toUpperCase() + event.slice(1)}`
|
|
545
|
+
);
|
|
498
546
|
}
|
|
499
547
|
return this;
|
|
500
548
|
}
|
|
501
549
|
/**
|
|
502
|
-
* Fire event, execute all bound handlers.
|
|
503
|
-
*
|
|
504
|
-
*
|
|
550
|
+
* Fire event, execute all bound handlers. Safe for re-entrant `off()` calls
|
|
551
|
+
* during dispatch: removed handlers are replaced with noop and compacted
|
|
552
|
+
* after the outermost fire returns.
|
|
505
553
|
*
|
|
506
554
|
* @param event - Event name
|
|
507
555
|
* @param data - Event data (type property added automatically)
|
|
@@ -515,38 +563,41 @@ var EventEmitter = class {
|
|
|
515
563
|
data = {};
|
|
516
564
|
}
|
|
517
565
|
data["type"] = event;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
566
|
+
this.firingDepth++;
|
|
567
|
+
try {
|
|
568
|
+
if (list) {
|
|
569
|
+
const len = list.length;
|
|
570
|
+
for (let i = 0; i < len; i++) {
|
|
571
|
+
const idx = lastToFirst ? len - 1 - i : i;
|
|
572
|
+
const listener = list[idx];
|
|
573
|
+
if (!listener) continue;
|
|
574
|
+
if (listener.handler === noop) continue;
|
|
525
575
|
listener.executing = 1;
|
|
526
|
-
funcWithTry(
|
|
527
|
-
[listener.handler],
|
|
528
|
-
[data],
|
|
529
|
-
this,
|
|
530
|
-
noop
|
|
531
|
-
);
|
|
576
|
+
funcWithTry([listener.handler], [data], this, noop);
|
|
532
577
|
listener.executing = "";
|
|
533
|
-
} else if (!listener.executing) {
|
|
534
|
-
list.splice(idx, 1);
|
|
535
578
|
}
|
|
536
579
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
580
|
+
const onMethodName = `on${event[0].toUpperCase() + event.slice(1)}`;
|
|
581
|
+
const onMethod = this[onMethodName];
|
|
582
|
+
if (typeof onMethod === "function") {
|
|
583
|
+
funcWithTry([onMethod], [data], this, noop);
|
|
584
|
+
}
|
|
585
|
+
if (remove) {
|
|
586
|
+
this.off(event);
|
|
587
|
+
}
|
|
588
|
+
} finally {
|
|
589
|
+
this.firingDepth--;
|
|
590
|
+
if (this.firingDepth === 0 && this.pendingCompaction) {
|
|
591
|
+
for (const k of this.pendingCompaction) {
|
|
592
|
+
const l = this.listeners.get(k);
|
|
593
|
+
if (!l) continue;
|
|
594
|
+
for (let i = l.length - 1; i >= 0; i--) {
|
|
595
|
+
if (l[i].handler === noop) l.splice(i, 1);
|
|
596
|
+
}
|
|
597
|
+
if (l.length === 0) this.listeners.delete(k);
|
|
598
|
+
}
|
|
599
|
+
this.pendingCompaction = void 0;
|
|
600
|
+
}
|
|
550
601
|
}
|
|
551
602
|
return this;
|
|
552
603
|
}
|
|
@@ -555,8 +606,8 @@ var EventEmitter = class {
|
|
|
555
606
|
// src/state.ts
|
|
556
607
|
var appData = {};
|
|
557
608
|
var keyRefCounts = {};
|
|
558
|
-
var changedKeys =
|
|
559
|
-
var stashedChangedKeys =
|
|
609
|
+
var changedKeys = /* @__PURE__ */ new Set();
|
|
610
|
+
var stashedChangedKeys = EMPTY_STRING_SET;
|
|
560
611
|
var dataIsChanged = false;
|
|
561
612
|
var dataWhereSet = {};
|
|
562
613
|
var emitter = new EventEmitter();
|
|
@@ -567,7 +618,7 @@ function markBooted() {
|
|
|
567
618
|
function setupKeysRef(keys2) {
|
|
568
619
|
const keyList = keys2.split(",");
|
|
569
620
|
for (const key of keyList) {
|
|
570
|
-
if (
|
|
621
|
+
if (hasOwnProperty(keyRefCounts, key)) {
|
|
571
622
|
keyRefCounts[key]++;
|
|
572
623
|
} else {
|
|
573
624
|
keyRefCounts[key] = 1;
|
|
@@ -577,7 +628,7 @@ function setupKeysRef(keys2) {
|
|
|
577
628
|
}
|
|
578
629
|
function teardownKeysRef(keyList) {
|
|
579
630
|
for (const key of keyList) {
|
|
580
|
-
if (
|
|
631
|
+
if (hasOwnProperty(keyRefCounts, key)) {
|
|
581
632
|
const count = --keyRefCounts[key];
|
|
582
633
|
if (count <= 0) {
|
|
583
634
|
Reflect.deleteProperty(keyRefCounts, key);
|
|
@@ -589,35 +640,14 @@ function teardownKeysRef(keyList) {
|
|
|
589
640
|
}
|
|
590
641
|
}
|
|
591
642
|
}
|
|
592
|
-
var
|
|
593
|
-
var notifyList = [];
|
|
594
|
-
var notifyTimer;
|
|
643
|
+
var warnedKeys = /* @__PURE__ */ new Set();
|
|
595
644
|
function clearNotify(key) {
|
|
596
|
-
|
|
597
|
-
if (notifyList[i]?.key === key) {
|
|
598
|
-
notifyList.splice(i, 1);
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
function doNotify() {
|
|
603
|
-
const locker = {};
|
|
604
|
-
for (const n of notifyList) {
|
|
605
|
-
if (!locker[n.key]) {
|
|
606
|
-
console.warn(n.message);
|
|
607
|
-
locker[n.key] = 1;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
notifyList.length = 0;
|
|
611
|
-
notifyStarted = 0;
|
|
645
|
+
warnedKeys.delete(key);
|
|
612
646
|
}
|
|
613
647
|
function delayNotify(key, message) {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
if (!notifyStarted) {
|
|
618
|
-
notifyStarted = 1;
|
|
619
|
-
notifyTimer = setTimeout(doNotify, 500);
|
|
620
|
-
}
|
|
648
|
+
if (warnedKeys.has(key)) return;
|
|
649
|
+
warnedKeys.add(key);
|
|
650
|
+
console.warn(message);
|
|
621
651
|
}
|
|
622
652
|
var State = {
|
|
623
653
|
/**
|
|
@@ -629,7 +659,7 @@ var State = {
|
|
|
629
659
|
return safeguard(
|
|
630
660
|
result,
|
|
631
661
|
(dataKey) => {
|
|
632
|
-
if (booted &&
|
|
662
|
+
if (booted && hasOwnProperty(dataWhereSet, dataKey) && dataWhereSet[dataKey] !== window.location.pathname) {
|
|
633
663
|
console.warn(
|
|
634
664
|
`beware! You get state:"{State}.${dataKey}" where it set by page:${dataWhereSet[dataKey]}`
|
|
635
665
|
);
|
|
@@ -650,7 +680,7 @@ var State = {
|
|
|
650
680
|
* Set data to state.
|
|
651
681
|
*/
|
|
652
682
|
set(data, excludes) {
|
|
653
|
-
dataIsChanged = setData(data, appData, changedKeys, excludes ||
|
|
683
|
+
dataIsChanged = setData(data, appData, changedKeys, excludes || EMPTY_STRING_SET) || dataIsChanged;
|
|
654
684
|
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && booted) {
|
|
655
685
|
for (const p in data) {
|
|
656
686
|
dataWhereSet[p] = window.location.pathname;
|
|
@@ -667,26 +697,19 @@ var State = {
|
|
|
667
697
|
}
|
|
668
698
|
if (dataIsChanged) {
|
|
669
699
|
if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
|
|
670
|
-
for (const p
|
|
671
|
-
|
|
672
|
-
clearNotify(p);
|
|
673
|
-
}
|
|
700
|
+
for (const p of changedKeys) {
|
|
701
|
+
clearNotify(p);
|
|
674
702
|
}
|
|
675
703
|
}
|
|
676
704
|
dataIsChanged = false;
|
|
677
|
-
const keys2 =
|
|
678
|
-
for (const k in changedKeys) {
|
|
679
|
-
if (has(changedKeys, k)) {
|
|
680
|
-
keys2[k] = 1;
|
|
681
|
-
}
|
|
682
|
-
}
|
|
705
|
+
const keys2 = changedKeys;
|
|
683
706
|
stashedChangedKeys = keys2;
|
|
684
|
-
changedKeys =
|
|
685
|
-
emitter.fire(
|
|
707
|
+
changedKeys = /* @__PURE__ */ new Set();
|
|
708
|
+
emitter.fire(RouterEvents.CHANGED, { keys: keys2 });
|
|
686
709
|
}
|
|
687
710
|
},
|
|
688
711
|
/**
|
|
689
|
-
* Get
|
|
712
|
+
* Get the set of keys changed in the most recent digest.
|
|
690
713
|
*/
|
|
691
714
|
diff() {
|
|
692
715
|
return stashedChangedKeys;
|
|
@@ -726,6 +749,7 @@ var State = {
|
|
|
726
749
|
emitter.fire(event, data, remove);
|
|
727
750
|
return State;
|
|
728
751
|
}
|
|
752
|
+
// onChanged: noop,
|
|
729
753
|
};
|
|
730
754
|
|
|
731
755
|
// src/router.ts
|
|
@@ -743,6 +767,7 @@ var cachedDefaultPath;
|
|
|
743
767
|
var cachedRewrite;
|
|
744
768
|
var defaultTitle;
|
|
745
769
|
var frameworkConfig;
|
|
770
|
+
var beforeEachGuards = [];
|
|
746
771
|
function createEmptyLocation() {
|
|
747
772
|
return {
|
|
748
773
|
href: "",
|
|
@@ -897,7 +922,7 @@ var Router = {
|
|
|
897
922
|
document.title = defaultTitle || document.title;
|
|
898
923
|
}
|
|
899
924
|
emitter2.fire(
|
|
900
|
-
|
|
925
|
+
RouterEvents.CHANGED,
|
|
901
926
|
lastChanged
|
|
902
927
|
);
|
|
903
928
|
}
|
|
@@ -930,16 +955,16 @@ var Router = {
|
|
|
930
955
|
}
|
|
931
956
|
const lPath = lastLocation["path"] || "";
|
|
932
957
|
const lParams = lastLocation["params"];
|
|
933
|
-
const lQuery =
|
|
958
|
+
const lQuery = /* @__PURE__ */ new Set();
|
|
934
959
|
for (const k in lastLocation.query["params"]) {
|
|
935
|
-
if (
|
|
936
|
-
lQuery
|
|
960
|
+
if (hasOwnProperty(lastLocation.query["params"], k)) {
|
|
961
|
+
lQuery.add(k);
|
|
937
962
|
}
|
|
938
963
|
}
|
|
939
964
|
if (tPath) {
|
|
940
|
-
if (!
|
|
941
|
-
for (const qKey
|
|
942
|
-
if (
|
|
965
|
+
if (!hasOwnProperty(window, "history")) {
|
|
966
|
+
for (const qKey of lQuery) {
|
|
967
|
+
if (!hasOwnProperty(tParams, qKey)) {
|
|
943
968
|
tParams[qKey] = "";
|
|
944
969
|
}
|
|
945
970
|
}
|
|
@@ -948,14 +973,17 @@ var Router = {
|
|
|
948
973
|
tPath = lPath;
|
|
949
974
|
tParams = assign({}, lParams, tParams);
|
|
950
975
|
}
|
|
951
|
-
updateUrl(
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
)
|
|
976
|
+
updateUrl(tPath, tParams, lastLocation, replace, silentFlag, lQuery);
|
|
977
|
+
},
|
|
978
|
+
/**
|
|
979
|
+
* Register an async-friendly navigation guard. See `RouterInterface.beforeEach`.
|
|
980
|
+
*/
|
|
981
|
+
beforeEach(guard) {
|
|
982
|
+
beforeEachGuards.push(guard);
|
|
983
|
+
return () => {
|
|
984
|
+
const idx = beforeEachGuards.indexOf(guard);
|
|
985
|
+
if (idx !== -1) beforeEachGuards.splice(idx, 1);
|
|
986
|
+
};
|
|
959
987
|
},
|
|
960
988
|
/**
|
|
961
989
|
* Join multiple path segments into a single path.
|
|
@@ -1019,21 +1047,48 @@ var Router = {
|
|
|
1019
1047
|
}
|
|
1020
1048
|
};
|
|
1021
1049
|
Router.fire(
|
|
1022
|
-
|
|
1050
|
+
RouterEvents.CHANGE,
|
|
1023
1051
|
changeEvent
|
|
1024
1052
|
);
|
|
1025
|
-
if (
|
|
1053
|
+
if (suspend || changeEvent.p) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
if (beforeEachGuards.length === 0) {
|
|
1026
1057
|
changeEvent.resolve();
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
const from = lastLocation;
|
|
1061
|
+
const to = loc;
|
|
1062
|
+
const guards = beforeEachGuards.slice();
|
|
1063
|
+
let chain = Promise.resolve(true);
|
|
1064
|
+
for (const guard of guards) {
|
|
1065
|
+
chain = chain.then((prev) => {
|
|
1066
|
+
if (prev === false) return false;
|
|
1067
|
+
return guard(to, from);
|
|
1068
|
+
});
|
|
1027
1069
|
}
|
|
1070
|
+
chain.then(
|
|
1071
|
+
(result) => {
|
|
1072
|
+
if (changeEvent.p) return;
|
|
1073
|
+
if (result === false) {
|
|
1074
|
+
changeEvent.reject();
|
|
1075
|
+
} else {
|
|
1076
|
+
changeEvent.resolve();
|
|
1077
|
+
}
|
|
1078
|
+
},
|
|
1079
|
+
() => {
|
|
1080
|
+
if (!changeEvent.p) changeEvent.reject();
|
|
1081
|
+
}
|
|
1082
|
+
);
|
|
1028
1083
|
}
|
|
1029
1084
|
};
|
|
1030
1085
|
Router.notify = watchChange;
|
|
1031
1086
|
window.addEventListener("hashchange", watchChange);
|
|
1032
1087
|
window.addEventListener("popstate", watchChange);
|
|
1033
1088
|
window.addEventListener("beforeunload", (domEvent) => {
|
|
1034
|
-
const
|
|
1035
|
-
Router.fire(
|
|
1036
|
-
const msg =
|
|
1089
|
+
const data = {};
|
|
1090
|
+
Router.fire(RouterEvents.PAGE_UNLOAD, data);
|
|
1091
|
+
const msg = data["msg"];
|
|
1037
1092
|
if (msg) {
|
|
1038
1093
|
domEvent.returnValue = msg;
|
|
1039
1094
|
}
|
|
@@ -1065,26 +1120,30 @@ var frameGetter;
|
|
|
1065
1120
|
function parseEventInfo(eventInfo) {
|
|
1066
1121
|
const cached = eventInfoCache.get(eventInfo);
|
|
1067
1122
|
if (cached) {
|
|
1068
|
-
return assign({}, cached, {
|
|
1123
|
+
return assign({}, cached, { value: eventInfo });
|
|
1069
1124
|
}
|
|
1070
1125
|
const match = eventInfo.match(EVENT_METHOD_REGEXP) || [];
|
|
1071
1126
|
const result = {
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1127
|
+
id: match[1] || "",
|
|
1128
|
+
name: match[2] || "",
|
|
1129
|
+
params: match[3] || ""
|
|
1075
1130
|
};
|
|
1076
1131
|
eventInfoCache.set(eventInfo, result);
|
|
1077
|
-
return assign({}, result, {
|
|
1132
|
+
return assign({}, result, { value: eventInfo });
|
|
1078
1133
|
}
|
|
1079
1134
|
function findFrameInfo(current, eventType) {
|
|
1080
1135
|
const eventInfos = [];
|
|
1081
|
-
let begin = current;
|
|
1082
1136
|
const info = current.getAttribute(`@${eventType}`);
|
|
1137
|
+
const hasSelectorEvents = !!selectorEvents[eventType];
|
|
1138
|
+
if (!info && !hasSelectorEvents) {
|
|
1139
|
+
return eventInfos;
|
|
1140
|
+
}
|
|
1141
|
+
let begin = current;
|
|
1083
1142
|
let match;
|
|
1084
1143
|
if (info) {
|
|
1085
1144
|
match = parseEventInfo(info);
|
|
1086
1145
|
}
|
|
1087
|
-
if (match && !match.
|
|
1146
|
+
if (match && !match.id || hasSelectorEvents) {
|
|
1088
1147
|
let selectorFrameId = "#";
|
|
1089
1148
|
let backtrace = 0;
|
|
1090
1149
|
while (begin && begin !== document.body) {
|
|
@@ -1110,10 +1169,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1110
1169
|
if (selectorEntry) {
|
|
1111
1170
|
for (const selectorName of selectorEntry.selectors) {
|
|
1112
1171
|
const entry = {
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1172
|
+
value: selectorName,
|
|
1173
|
+
id: frameId,
|
|
1174
|
+
name: selectorName,
|
|
1175
|
+
params: ""
|
|
1117
1176
|
};
|
|
1118
1177
|
if (selectorName) {
|
|
1119
1178
|
if (!backtrace && elementMatchesSelector(current, selectorName)) {
|
|
@@ -1125,8 +1184,8 @@ function findFrameInfo(current, eventType) {
|
|
|
1125
1184
|
}
|
|
1126
1185
|
}
|
|
1127
1186
|
if (view.template && !backtrace) {
|
|
1128
|
-
if (match && !match.
|
|
1129
|
-
match.
|
|
1187
|
+
if (match && !match.id) {
|
|
1188
|
+
match.id = frameId;
|
|
1130
1189
|
}
|
|
1131
1190
|
break;
|
|
1132
1191
|
}
|
|
@@ -1142,10 +1201,10 @@ function findFrameInfo(current, eventType) {
|
|
|
1142
1201
|
}
|
|
1143
1202
|
if (match) {
|
|
1144
1203
|
eventInfos.push({
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1204
|
+
id: match.id,
|
|
1205
|
+
value: match.value,
|
|
1206
|
+
name: match.name,
|
|
1207
|
+
params: match.params
|
|
1149
1208
|
});
|
|
1150
1209
|
}
|
|
1151
1210
|
return eventInfos;
|
|
@@ -1166,7 +1225,7 @@ function domEventProcessor(domEvent) {
|
|
|
1166
1225
|
const eventInfos = findFrameInfo(current, eventType);
|
|
1167
1226
|
if (eventInfos.length) {
|
|
1168
1227
|
for (const info of eventInfos) {
|
|
1169
|
-
const {
|
|
1228
|
+
const { id: frameId, name: handlerName, params } = info;
|
|
1170
1229
|
if (lastFrameId !== frameId) {
|
|
1171
1230
|
if (lastFrameId && domEvent.isPropagationStopped?.()) {
|
|
1172
1231
|
break;
|
|
@@ -1257,7 +1316,7 @@ var EventDelegator = {
|
|
|
1257
1316
|
};
|
|
1258
1317
|
|
|
1259
1318
|
// src/vdom.ts
|
|
1260
|
-
var
|
|
1319
|
+
var wrapMeta = {
|
|
1261
1320
|
option: [1, "<select multiple>"],
|
|
1262
1321
|
thead: [1, "<table>"],
|
|
1263
1322
|
col: [2, "<table><colgroup>"],
|
|
@@ -1265,13 +1324,13 @@ var WrapMeta = {
|
|
|
1265
1324
|
td: [3, "<table><tbody><tr>"],
|
|
1266
1325
|
area: [1, "<map>"],
|
|
1267
1326
|
param: [1, "<object>"],
|
|
1268
|
-
|
|
1269
|
-
|
|
1327
|
+
svg: [1, '<svg xmlns="' + SVG_NS + '">'],
|
|
1328
|
+
math: [1, '<math xmlns="' + MATH_NS + '">'],
|
|
1270
1329
|
_: [0, ""]
|
|
1271
1330
|
};
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1331
|
+
wrapMeta["optgroup"] = wrapMeta["option"];
|
|
1332
|
+
wrapMeta["tbody"] = wrapMeta["tfoot"] = wrapMeta["colgroup"] = wrapMeta["caption"] = wrapMeta["thead"];
|
|
1333
|
+
wrapMeta["th"] = wrapMeta["td"];
|
|
1275
1334
|
var VDoc = document.implementation.createHTMLDocument("");
|
|
1276
1335
|
var VBase = VDoc.createElement("base");
|
|
1277
1336
|
VBase.href = document.location.href;
|
|
@@ -1282,16 +1341,12 @@ var VDomSpecials = {
|
|
|
1282
1341
|
OPTION: ["selected"]
|
|
1283
1342
|
};
|
|
1284
1343
|
function vdomUnmountFrames(frame, node) {
|
|
1285
|
-
if (node
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
if (children.includes(id)) {
|
|
1292
|
-
frame.unmountFrame(id);
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1344
|
+
if (!(node instanceof Element)) return;
|
|
1345
|
+
const id = node.getAttribute("id");
|
|
1346
|
+
if (!id) return;
|
|
1347
|
+
frame.unmountZone(id);
|
|
1348
|
+
if (frame.children().includes(id)) {
|
|
1349
|
+
frame.unmountFrame(id);
|
|
1295
1350
|
}
|
|
1296
1351
|
}
|
|
1297
1352
|
function vdomGetNode(html, refNode) {
|
|
@@ -1299,14 +1354,14 @@ function vdomGetNode(html, refNode) {
|
|
|
1299
1354
|
const ns = refNode.namespaceURI;
|
|
1300
1355
|
let tag;
|
|
1301
1356
|
if (ns === SVG_NS) {
|
|
1302
|
-
tag = "
|
|
1357
|
+
tag = "svg";
|
|
1303
1358
|
} else if (ns === MATH_NS) {
|
|
1304
|
-
tag = "
|
|
1359
|
+
tag = "math";
|
|
1305
1360
|
} else {
|
|
1306
1361
|
const match = TAG_NAME_REGEXP.exec(html);
|
|
1307
1362
|
tag = match ? match[1] : "";
|
|
1308
1363
|
}
|
|
1309
|
-
const wrap =
|
|
1364
|
+
const wrap = wrapMeta[tag] || wrapMeta["_"];
|
|
1310
1365
|
tmp.innerHTML = wrap[1] + html;
|
|
1311
1366
|
let j = wrap[0];
|
|
1312
1367
|
while (j--) {
|
|
@@ -1323,7 +1378,7 @@ function vdomGetCompareKey(node) {
|
|
|
1323
1378
|
}
|
|
1324
1379
|
let key = el.autoId ? "" : el.getAttribute("id") || void 0;
|
|
1325
1380
|
if (!key) {
|
|
1326
|
-
key = el.getAttribute(
|
|
1381
|
+
key = el.getAttribute(LarkInnerKeys.DIFF_KEY) || void 0;
|
|
1327
1382
|
}
|
|
1328
1383
|
if (!key) {
|
|
1329
1384
|
const larkView = el.getAttribute(LARK_VIEW);
|
|
@@ -1336,8 +1391,7 @@ function vdomGetCompareKey(node) {
|
|
|
1336
1391
|
return key;
|
|
1337
1392
|
}
|
|
1338
1393
|
function vdomSpecialDiff(oldNode, newNode) {
|
|
1339
|
-
const
|
|
1340
|
-
const specials = VDomSpecials[nodeName];
|
|
1394
|
+
const specials = VDomSpecials[oldNode.nodeName];
|
|
1341
1395
|
if (!specials) return 0;
|
|
1342
1396
|
const oldEl = oldNode;
|
|
1343
1397
|
const newEl = newNode;
|
|
@@ -1386,13 +1440,17 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1386
1440
|
let oldNode = oldParent.lastChild;
|
|
1387
1441
|
let newNode = newParent.firstChild;
|
|
1388
1442
|
let extra = 0;
|
|
1389
|
-
const keyedNodes =
|
|
1390
|
-
const newKeyedNodes =
|
|
1443
|
+
const keyedNodes = /* @__PURE__ */ new Map();
|
|
1444
|
+
const newKeyedNodes = /* @__PURE__ */ new Map();
|
|
1391
1445
|
while (oldNode) {
|
|
1392
1446
|
extra++;
|
|
1393
1447
|
const nodeKey = vdomGetCompareKey(oldNode);
|
|
1394
1448
|
if (nodeKey) {
|
|
1395
|
-
|
|
1449
|
+
let bucket = keyedNodes.get(nodeKey);
|
|
1450
|
+
if (!bucket) {
|
|
1451
|
+
bucket = [];
|
|
1452
|
+
keyedNodes.set(nodeKey, bucket);
|
|
1453
|
+
}
|
|
1396
1454
|
bucket.push(oldNode);
|
|
1397
1455
|
}
|
|
1398
1456
|
oldNode = oldNode.previousSibling;
|
|
@@ -1400,7 +1458,7 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1400
1458
|
while (newNode) {
|
|
1401
1459
|
const nodeKey = vdomGetCompareKey(newNode);
|
|
1402
1460
|
if (nodeKey) {
|
|
1403
|
-
newKeyedNodes
|
|
1461
|
+
newKeyedNodes.set(nodeKey, (newKeyedNodes.get(nodeKey) ?? 0) + 1);
|
|
1404
1462
|
}
|
|
1405
1463
|
newNode = newNode.nextSibling;
|
|
1406
1464
|
}
|
|
@@ -1411,23 +1469,25 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1411
1469
|
const tempNew = newNode;
|
|
1412
1470
|
newNode = newNode.nextSibling;
|
|
1413
1471
|
const nodeKey = vdomGetCompareKey(tempNew);
|
|
1414
|
-
let foundNode = nodeKey ? keyedNodes
|
|
1472
|
+
let foundNode = nodeKey ? keyedNodes.get(nodeKey) : void 0;
|
|
1415
1473
|
if (foundNode && (foundNode = foundNode.slice()) && foundNode.length) {
|
|
1416
1474
|
const matched = foundNode.pop();
|
|
1417
1475
|
while (matched !== oldNode) {
|
|
1418
|
-
|
|
1476
|
+
if (!oldNode) break;
|
|
1477
|
+
const next = oldNode.nextSibling;
|
|
1419
1478
|
oldParent.appendChild(oldNode);
|
|
1420
1479
|
oldNode = next;
|
|
1421
1480
|
}
|
|
1422
1481
|
oldNode = matched.nextSibling;
|
|
1423
|
-
if (nodeKey
|
|
1424
|
-
newKeyedNodes
|
|
1482
|
+
if (nodeKey) {
|
|
1483
|
+
const c = newKeyedNodes.get(nodeKey);
|
|
1484
|
+
if (c) newKeyedNodes.set(nodeKey, c - 1);
|
|
1425
1485
|
}
|
|
1426
1486
|
vdomSetNode(matched, tempNew, oldParent, ref, frame, keys_);
|
|
1427
1487
|
} else if (oldNode) {
|
|
1428
1488
|
const tempOld2 = oldNode;
|
|
1429
1489
|
const oldKey = vdomGetCompareKey(tempOld2);
|
|
1430
|
-
if (oldKey && keyedNodes
|
|
1490
|
+
if (oldKey && keyedNodes.has(oldKey) && newKeyedNodes.get(oldKey)) {
|
|
1431
1491
|
extra++;
|
|
1432
1492
|
ref.hasChanged = 1;
|
|
1433
1493
|
ref.domOps.push([8, oldParent, tempNew, tempOld2]);
|
|
@@ -1451,17 +1511,21 @@ function vdomSetChildNodes(oldParent, newParent, ref, frame, keys_) {
|
|
|
1451
1511
|
}
|
|
1452
1512
|
}
|
|
1453
1513
|
function vdomSetNode(oldNode, newNode, oldParent, ref, frame, keys_) {
|
|
1454
|
-
|
|
1514
|
+
const oldAsEl = oldNode instanceof Element ? oldNode : null;
|
|
1515
|
+
const newAsEl = newNode instanceof Element ? newNode : null;
|
|
1516
|
+
const hasViewKey = !!oldAsEl?.hasAttribute(LarkInnerKeys.VIEW_KEY);
|
|
1517
|
+
const equalAsNodes = oldAsEl !== null && newAsEl !== null && oldAsEl.isEqualNode && oldAsEl.isEqualNode(newAsEl);
|
|
1518
|
+
if (vdomSpecialDiff(oldNode, newNode) || hasViewKey || !equalAsNodes) {
|
|
1455
1519
|
if (oldNode.nodeType === newNode.nodeType && oldNode.nodeName === newNode.nodeName) {
|
|
1456
|
-
if (
|
|
1457
|
-
const oldEl =
|
|
1458
|
-
const newEl =
|
|
1459
|
-
const staticKey = newEl.getAttribute(
|
|
1460
|
-
if (staticKey && staticKey === oldEl.getAttribute(
|
|
1520
|
+
if (oldAsEl !== null && newAsEl !== null) {
|
|
1521
|
+
const oldEl = oldAsEl;
|
|
1522
|
+
const newEl = newAsEl;
|
|
1523
|
+
const staticKey = newEl.getAttribute(LarkInnerKeys.DIFF_KEY);
|
|
1524
|
+
if (staticKey && staticKey === oldEl.getAttribute(LarkInnerKeys.DIFF_KEY)) {
|
|
1461
1525
|
return;
|
|
1462
1526
|
}
|
|
1463
1527
|
const newLarkView = newEl.getAttribute(LARK_VIEW);
|
|
1464
|
-
const updateAttribute = !newEl.getAttribute(
|
|
1528
|
+
const updateAttribute = !newEl.getAttribute(LarkInnerKeys.ATTR_KEY) || newEl.getAttribute(LarkInnerKeys.ATTR_KEY) !== oldEl.getAttribute(LarkInnerKeys.ATTR_KEY);
|
|
1465
1529
|
let updateChildren = true;
|
|
1466
1530
|
if (newLarkView) {
|
|
1467
1531
|
const oldFrameId = oldEl.getAttribute("id") || "";
|
|
@@ -1562,7 +1626,8 @@ function encodeQ(v) {
|
|
|
1562
1626
|
}
|
|
1563
1627
|
|
|
1564
1628
|
// src/updater.ts
|
|
1565
|
-
function updaterRef(
|
|
1629
|
+
function updaterRef(refDataIn, value, key) {
|
|
1630
|
+
const refData = refDataIn;
|
|
1566
1631
|
const counter = refData[SPLITTER];
|
|
1567
1632
|
for (let i = counter; --i; ) {
|
|
1568
1633
|
key = SPLITTER + i;
|
|
@@ -1582,13 +1647,19 @@ var Updater = class {
|
|
|
1582
1647
|
/** Ref data for template rendering */
|
|
1583
1648
|
refData;
|
|
1584
1649
|
/** Changed keys in current digest cycle */
|
|
1585
|
-
changedKeys =
|
|
1650
|
+
changedKeys = /* @__PURE__ */ new Set();
|
|
1586
1651
|
/** Whether data has changed since last digest */
|
|
1587
1652
|
hasChangedFlag = 0;
|
|
1588
|
-
/**
|
|
1653
|
+
/**
|
|
1654
|
+
* Digesting queue: supports re-digest during digest.
|
|
1655
|
+
* Holds pending callbacks; `null` is used as a sentinel marking the start
|
|
1656
|
+
* of an active digest cycle, so `runDigest` can detect re-entrant calls.
|
|
1657
|
+
*/
|
|
1589
1658
|
digestingQueue = [];
|
|
1590
|
-
/**
|
|
1591
|
-
|
|
1659
|
+
/** Monotonically increasing version, bumped each time data actually changes. */
|
|
1660
|
+
version = 0;
|
|
1661
|
+
/** Snapshot of `version` taken by `snapshot()`, used by `altered()`. */
|
|
1662
|
+
snapshotVersion;
|
|
1592
1663
|
constructor(viewId) {
|
|
1593
1664
|
this.viewId = viewId;
|
|
1594
1665
|
this.data = { vId: viewId };
|
|
@@ -1616,7 +1687,16 @@ var Updater = class {
|
|
|
1616
1687
|
* Returns this for chaining.
|
|
1617
1688
|
*/
|
|
1618
1689
|
set(data, excludes) {
|
|
1619
|
-
|
|
1690
|
+
const changed = setData(
|
|
1691
|
+
data,
|
|
1692
|
+
this.data,
|
|
1693
|
+
this.changedKeys,
|
|
1694
|
+
excludes || EMPTY_STRING_SET
|
|
1695
|
+
);
|
|
1696
|
+
if (changed) {
|
|
1697
|
+
this.version++;
|
|
1698
|
+
this.hasChangedFlag = 1;
|
|
1699
|
+
}
|
|
1620
1700
|
return this;
|
|
1621
1701
|
}
|
|
1622
1702
|
/**
|
|
@@ -1652,13 +1732,13 @@ var Updater = class {
|
|
|
1652
1732
|
const keys2 = this.changedKeys;
|
|
1653
1733
|
const changed = this.hasChangedFlag;
|
|
1654
1734
|
this.hasChangedFlag = 0;
|
|
1655
|
-
this.changedKeys =
|
|
1735
|
+
this.changedKeys = /* @__PURE__ */ new Set();
|
|
1656
1736
|
const frame = Frame.get(this.viewId);
|
|
1657
1737
|
const view = frame?.view;
|
|
1658
1738
|
const node = getById(this.viewId);
|
|
1659
|
-
if (changed && view && node && view.signature > 0) {
|
|
1739
|
+
if (changed && view && node && view.signature > 0 && frame) {
|
|
1660
1740
|
const template = view.template;
|
|
1661
|
-
if (
|
|
1741
|
+
if (typeof template === "function") {
|
|
1662
1742
|
const html = template(
|
|
1663
1743
|
this.data,
|
|
1664
1744
|
this.viewId,
|
|
@@ -1695,43 +1775,65 @@ var Updater = class {
|
|
|
1695
1775
|
}
|
|
1696
1776
|
}
|
|
1697
1777
|
/**
|
|
1698
|
-
* Save a snapshot of current data for altered() detection.
|
|
1778
|
+
* Save a snapshot of the current data version for `altered()` detection.
|
|
1779
|
+
* Cheap O(1) — records the current monotonic version, no serialization.
|
|
1699
1780
|
*/
|
|
1700
1781
|
snapshot() {
|
|
1701
|
-
this.
|
|
1782
|
+
this.snapshotVersion = this.version;
|
|
1702
1783
|
return this;
|
|
1703
1784
|
}
|
|
1704
1785
|
/**
|
|
1705
|
-
* Check
|
|
1786
|
+
* Check whether data has changed since the last snapshot.
|
|
1787
|
+
* Returns undefined when no snapshot has been taken yet.
|
|
1706
1788
|
*/
|
|
1707
1789
|
altered() {
|
|
1708
|
-
if (this.
|
|
1709
|
-
|
|
1710
|
-
}
|
|
1711
|
-
return void 0;
|
|
1790
|
+
if (this.snapshotVersion === void 0) return void 0;
|
|
1791
|
+
return this.version !== this.snapshotVersion;
|
|
1712
1792
|
}
|
|
1713
1793
|
/**
|
|
1714
|
-
* Translate
|
|
1794
|
+
* Translate a refData reference back to its original value.
|
|
1795
|
+
*
|
|
1796
|
+
* The ref protocol is `SPLITTER` + ascii decimal digits — the exact format
|
|
1797
|
+
* emitted by `updaterRef`. We require that exact shape so a user-supplied
|
|
1798
|
+
* string that merely begins with SPLITTER is never accidentally resolved
|
|
1799
|
+
* (or mishandled as a "missing ref").
|
|
1715
1800
|
*/
|
|
1716
1801
|
translate(data) {
|
|
1717
|
-
if (typeof data
|
|
1718
|
-
|
|
1802
|
+
if (typeof data !== "string") return data;
|
|
1803
|
+
if (data.length < 2 || data[0] !== SPLITTER) return data;
|
|
1804
|
+
for (let i = 1; i < data.length; i++) {
|
|
1805
|
+
const c = data.charCodeAt(i);
|
|
1806
|
+
if (c < 48 || c > 57) return data;
|
|
1719
1807
|
}
|
|
1720
|
-
return data;
|
|
1808
|
+
return hasOwnProperty(this.refData, data) ? this.refData[data] : data;
|
|
1721
1809
|
}
|
|
1722
1810
|
/**
|
|
1723
|
-
*
|
|
1811
|
+
* Resolve a dotted property path against refData.
|
|
1812
|
+
*
|
|
1813
|
+
* Only safe property-path syntax is supported: `a`, `a.b`, `a.b.c`.
|
|
1814
|
+
* Numeric literals (e.g. `1`, `1.5`) are returned as numbers. Anything else
|
|
1815
|
+
* returns `undefined` — we no longer evaluate arbitrary JavaScript via
|
|
1816
|
+
* `new Function`, so the method is CSP-safe and cannot be used as an
|
|
1817
|
+
* injection vector.
|
|
1724
1818
|
*/
|
|
1725
1819
|
parse(expr) {
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1820
|
+
const trimmed = expr.trim();
|
|
1821
|
+
if (!trimmed) return void 0;
|
|
1822
|
+
if (/^-?\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
1823
|
+
return Number(trimmed);
|
|
1824
|
+
}
|
|
1825
|
+
if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(trimmed)) {
|
|
1730
1826
|
return void 0;
|
|
1731
1827
|
}
|
|
1828
|
+
let cur = this.refData;
|
|
1829
|
+
for (const segment of trimmed.split(".")) {
|
|
1830
|
+
if (cur == null || typeof cur !== "object") return void 0;
|
|
1831
|
+
cur = cur[segment];
|
|
1832
|
+
}
|
|
1833
|
+
return cur;
|
|
1732
1834
|
}
|
|
1733
1835
|
/**
|
|
1734
|
-
* Get
|
|
1836
|
+
* Get the set of keys changed since the last digest (for external inspection).
|
|
1735
1837
|
*/
|
|
1736
1838
|
getChangedKeys() {
|
|
1737
1839
|
return this.changedKeys;
|
|
@@ -1746,221 +1848,6 @@ if (typeof window !== "undefined") {
|
|
|
1746
1848
|
if (typeof document !== "undefined") {
|
|
1747
1849
|
VIEW_GLOBALS["document"] = document;
|
|
1748
1850
|
}
|
|
1749
|
-
function viewPrepare(oView) {
|
|
1750
|
-
if (oView.ctors) {
|
|
1751
|
-
return oView.ctors;
|
|
1752
|
-
}
|
|
1753
|
-
const ctors = [];
|
|
1754
|
-
oView.ctors = ctors;
|
|
1755
|
-
const proto = oView.prototype;
|
|
1756
|
-
const eventsObject = {};
|
|
1757
|
-
const eventsList = [];
|
|
1758
|
-
const selectorObject = {};
|
|
1759
|
-
const mixins = proto["mixins"];
|
|
1760
|
-
if (mixins && Array.isArray(mixins)) {
|
|
1761
|
-
viewMergeMixins(mixins, oView, ctors);
|
|
1762
|
-
}
|
|
1763
|
-
for (const p in proto) {
|
|
1764
|
-
if (!has(proto, p)) continue;
|
|
1765
|
-
const currentFn = proto[p];
|
|
1766
|
-
if (typeof currentFn !== "function") continue;
|
|
1767
|
-
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
1768
|
-
if (!matches) continue;
|
|
1769
|
-
const isSelector = matches[1];
|
|
1770
|
-
const selectorOrCallback = matches[2];
|
|
1771
|
-
const events = matches[3];
|
|
1772
|
-
const modifiers = matches[4];
|
|
1773
|
-
const mod = {};
|
|
1774
|
-
if (modifiers) {
|
|
1775
|
-
for (const item of modifiers.split(",")) {
|
|
1776
|
-
mod[item] = true;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
const eventTypes = events.split(",");
|
|
1780
|
-
for (const item of eventTypes) {
|
|
1781
|
-
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
1782
|
-
let mask = 1;
|
|
1783
|
-
if (isSelector) {
|
|
1784
|
-
if (globalNode) {
|
|
1785
|
-
eventsList.push({
|
|
1786
|
-
handler: currentFn,
|
|
1787
|
-
element: globalNode,
|
|
1788
|
-
eventName: item,
|
|
1789
|
-
modifiers: mod
|
|
1790
|
-
});
|
|
1791
|
-
continue;
|
|
1792
|
-
}
|
|
1793
|
-
mask = 2;
|
|
1794
|
-
let selectorEntry = selectorObject[item];
|
|
1795
|
-
if (!selectorEntry) {
|
|
1796
|
-
selectorEntry = selectorObject[item] = {
|
|
1797
|
-
selectors: []
|
|
1798
|
-
};
|
|
1799
|
-
}
|
|
1800
|
-
if (!selectorEntry[selectorOrCallback]) {
|
|
1801
|
-
selectorEntry[selectorOrCallback] = 1;
|
|
1802
|
-
selectorEntry.selectors.push(selectorOrCallback);
|
|
1803
|
-
}
|
|
1804
|
-
}
|
|
1805
|
-
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
1806
|
-
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
1807
|
-
const existingFn = proto[combinedKey];
|
|
1808
|
-
if (!existingFn) {
|
|
1809
|
-
proto[combinedKey] = currentFn;
|
|
1810
|
-
} else {
|
|
1811
|
-
const mixinFn = currentFn;
|
|
1812
|
-
const existingMixin = existingFn;
|
|
1813
|
-
if (existingMixin.b) {
|
|
1814
|
-
if (mixinFn.b) {
|
|
1815
|
-
proto[combinedKey] = processMixinsSameEvent(
|
|
1816
|
-
currentFn,
|
|
1817
|
-
existingFn
|
|
1818
|
-
);
|
|
1819
|
-
} else if (has(proto, p)) {
|
|
1820
|
-
proto[combinedKey] = currentFn;
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
viewWrapMethod(proto, "render", "$b");
|
|
1827
|
-
proto["$eo"] = eventsObject;
|
|
1828
|
-
proto["$el"] = eventsList;
|
|
1829
|
-
proto["$so"] = selectorObject;
|
|
1830
|
-
proto["$f"] = proto["assign"];
|
|
1831
|
-
return ctors;
|
|
1832
|
-
}
|
|
1833
|
-
function viewWrapMethod(proto, fnName, shortKey) {
|
|
1834
|
-
const originalFn = proto[fnName];
|
|
1835
|
-
if (typeof originalFn !== "function") return;
|
|
1836
|
-
const wrapped = function(...args) {
|
|
1837
|
-
if (this.signature > 0) {
|
|
1838
|
-
this.signature++;
|
|
1839
|
-
this.fire("rendercall");
|
|
1840
|
-
destroyAllResources(this, false);
|
|
1841
|
-
const instanceFn = typeof this[fnName] === "function" ? this[fnName] : originalFn;
|
|
1842
|
-
const fnToCall = instanceFn === wrapped ? originalFn : instanceFn;
|
|
1843
|
-
return funcWithTry(fnToCall, args, this, noop);
|
|
1844
|
-
}
|
|
1845
|
-
return void 0;
|
|
1846
|
-
};
|
|
1847
|
-
proto[fnName] = wrapped;
|
|
1848
|
-
proto[shortKey] = wrapped;
|
|
1849
|
-
}
|
|
1850
|
-
function processMixinsSameEvent(additional, exist) {
|
|
1851
|
-
let temp;
|
|
1852
|
-
const existMixin = exist;
|
|
1853
|
-
if (existMixin.a) {
|
|
1854
|
-
temp = existMixin;
|
|
1855
|
-
} else {
|
|
1856
|
-
temp = function(...e) {
|
|
1857
|
-
funcWithTry(temp.a ?? [], e, this, noop);
|
|
1858
|
-
};
|
|
1859
|
-
temp.a = [exist];
|
|
1860
|
-
temp.b = 1;
|
|
1861
|
-
}
|
|
1862
|
-
const additionalMixin = additional;
|
|
1863
|
-
temp.a = (temp.a ?? []).concat(additionalMixin.a ?? [additional]);
|
|
1864
|
-
return temp;
|
|
1865
|
-
}
|
|
1866
|
-
function viewMergeMixins(mixins, viewClass, ctors) {
|
|
1867
|
-
const proto = viewClass.prototype;
|
|
1868
|
-
const temp = {};
|
|
1869
|
-
for (const node of mixins) {
|
|
1870
|
-
for (const p in node) {
|
|
1871
|
-
if (!has(node, p)) continue;
|
|
1872
|
-
const fn = node[p];
|
|
1873
|
-
const exist = temp[p];
|
|
1874
|
-
if (p === "make") {
|
|
1875
|
-
ctors.push(fn);
|
|
1876
|
-
continue;
|
|
1877
|
-
}
|
|
1878
|
-
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
1879
|
-
if (exist) {
|
|
1880
|
-
temp[p] = processMixinsSameEvent(fn, exist);
|
|
1881
|
-
} else {
|
|
1882
|
-
fn.b = 1;
|
|
1883
|
-
temp[p] = fn;
|
|
1884
|
-
}
|
|
1885
|
-
} else {
|
|
1886
|
-
if (!exist) {
|
|
1887
|
-
temp[p] = fn;
|
|
1888
|
-
}
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
for (const p in temp) {
|
|
1893
|
-
if (!has(proto, p)) {
|
|
1894
|
-
proto[p] = temp[p];
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
function viewDelegateEvents(view, destroy = false) {
|
|
1899
|
-
const proto = Object.getPrototypeOf(view) ?? {};
|
|
1900
|
-
const eventsObject = proto["$eo"] || view.eventObjectMap;
|
|
1901
|
-
const selectorObject = proto["$so"] || view.eventSelectorMap;
|
|
1902
|
-
const eventsList = proto["$el"] || view.globalEventList;
|
|
1903
|
-
for (const e in eventsObject) {
|
|
1904
|
-
if (has(eventsObject, e)) {
|
|
1905
|
-
if (destroy) {
|
|
1906
|
-
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
1907
|
-
} else {
|
|
1908
|
-
EventDelegator.bind(e, !!selectorObject[e]);
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
for (const entry of eventsList) {
|
|
1913
|
-
if (destroy) {
|
|
1914
|
-
entry.element.removeEventListener(
|
|
1915
|
-
entry.eventName,
|
|
1916
|
-
entry.boundHandler
|
|
1917
|
-
);
|
|
1918
|
-
} else {
|
|
1919
|
-
const handler = entry.handler;
|
|
1920
|
-
const element = entry.element;
|
|
1921
|
-
const modifiers = entry.modifiers;
|
|
1922
|
-
entry.boundHandler = function(domEvent) {
|
|
1923
|
-
const extendedEvent = domEvent;
|
|
1924
|
-
extendedEvent.eventTarget = element;
|
|
1925
|
-
if (modifiers) {
|
|
1926
|
-
const kbEvent = domEvent;
|
|
1927
|
-
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
1928
|
-
return;
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1931
|
-
funcWithTry(handler, [domEvent], view, noop);
|
|
1932
|
-
};
|
|
1933
|
-
entry.element.addEventListener(
|
|
1934
|
-
entry.eventName,
|
|
1935
|
-
entry.boundHandler
|
|
1936
|
-
);
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
}
|
|
1940
|
-
function destroyAllResources(view, lastly) {
|
|
1941
|
-
const cache = view.resources;
|
|
1942
|
-
for (const p in cache) {
|
|
1943
|
-
if (has(cache, p)) {
|
|
1944
|
-
const entry = cache[p];
|
|
1945
|
-
if (lastly || entry.destroyOnRender) {
|
|
1946
|
-
destroyResource(cache, p, true);
|
|
1947
|
-
}
|
|
1948
|
-
}
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
1951
|
-
function destroyResource(cache, key, callDestroy, oldEntity) {
|
|
1952
|
-
const entry = cache[key];
|
|
1953
|
-
if (!entry || entry.entity === oldEntity) return void 0;
|
|
1954
|
-
const entity = entry.entity;
|
|
1955
|
-
if (entity && typeof entity === "object") {
|
|
1956
|
-
const destroyFn = entity["destroy"];
|
|
1957
|
-
if (typeof destroyFn === "function" && callDestroy) {
|
|
1958
|
-
funcWithTry(destroyFn, [], entity, noop);
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
Reflect.deleteProperty(cache, key);
|
|
1962
|
-
return entity;
|
|
1963
|
-
}
|
|
1964
1851
|
var View = class _View {
|
|
1965
1852
|
/** View ID (same as owner frame ID) */
|
|
1966
1853
|
id = "";
|
|
@@ -1984,18 +1871,44 @@ var View = class _View {
|
|
|
1984
1871
|
observedStateKeys;
|
|
1985
1872
|
/** Resource map */
|
|
1986
1873
|
resources = {};
|
|
1987
|
-
/** Selector event map: eventType -> handler name list */
|
|
1988
|
-
eventSelectorMap = {};
|
|
1989
|
-
/** Event object map: eventType -> bitmask */
|
|
1990
|
-
eventObjectMap = {};
|
|
1991
|
-
/** Global event list */
|
|
1992
|
-
globalEventList = [];
|
|
1993
1874
|
/** Assign method reference */
|
|
1994
1875
|
assignMethod;
|
|
1995
1876
|
/** Whether endUpdate pending */
|
|
1996
1877
|
endUpdatePending;
|
|
1997
1878
|
/** Internal event storage */
|
|
1998
1879
|
_events = new EventEmitter();
|
|
1880
|
+
// ============================================================
|
|
1881
|
+
// Getters for prototype-stored event maps
|
|
1882
|
+
// ============================================================
|
|
1883
|
+
/** Prototype-stored event maps shape (set by View.prepare). */
|
|
1884
|
+
get protoEventState() {
|
|
1885
|
+
return Object.getPrototypeOf(this);
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Event bitmask map: eventType -> bitmask (1=root, 2=selector).
|
|
1889
|
+
* Read from prototype ($evtObjMap) set by View.prepare.
|
|
1890
|
+
* Using a getter avoids ES6 class field shadowing the prototype value.
|
|
1891
|
+
*/
|
|
1892
|
+
get eventObjectMap() {
|
|
1893
|
+
return this.protoEventState.$evtObjMap ?? {};
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* Selector event map: eventType -> selector list.
|
|
1897
|
+
* Read from prototype ($selMap) set by View.prepare.
|
|
1898
|
+
*/
|
|
1899
|
+
get eventSelectorMap() {
|
|
1900
|
+
return this.protoEventState.$selMap ?? {};
|
|
1901
|
+
}
|
|
1902
|
+
/**
|
|
1903
|
+
* Global event list: [{handler, element, eventName, modifiers}].
|
|
1904
|
+
* Read from prototype ($globalEvtList) set by View.prepare.
|
|
1905
|
+
*/
|
|
1906
|
+
get globalEventList() {
|
|
1907
|
+
return this.protoEventState.$globalEvtList ?? [];
|
|
1908
|
+
}
|
|
1909
|
+
// ============================================================
|
|
1910
|
+
// Instance lifecycle methods
|
|
1911
|
+
// ============================================================
|
|
1999
1912
|
/**
|
|
2000
1913
|
* Initialize view (called by Frame when mounting).
|
|
2001
1914
|
*/
|
|
@@ -2003,14 +1916,7 @@ var View = class _View {
|
|
|
2003
1916
|
}
|
|
2004
1917
|
/**
|
|
2005
1918
|
* Render view template (called by Frame after init).
|
|
2006
|
-
* Wrapped by
|
|
2007
|
-
*
|
|
2008
|
-
* Default implementation calls updater.digest() which:
|
|
2009
|
-
* 1. Executes the template function with current data
|
|
2010
|
-
* 2. Runs VDOM diff against previous DOM
|
|
2011
|
-
* 3. Applies DOM operations
|
|
2012
|
-
* 4. Calls endUpdate to mount child frames
|
|
2013
|
-
*
|
|
1919
|
+
* Wrapped by View.wrapMethod to manage signature + resources.
|
|
2014
1920
|
*/
|
|
2015
1921
|
render() {
|
|
2016
1922
|
this.updater.digest();
|
|
@@ -2033,13 +1939,17 @@ var View = class _View {
|
|
|
2033
1939
|
// ============================================================
|
|
2034
1940
|
// Update methods
|
|
2035
1941
|
// ============================================================
|
|
1942
|
+
/** Get the owning frame, asserting it has been bound. */
|
|
1943
|
+
get ownerFrame() {
|
|
1944
|
+
return this.owner;
|
|
1945
|
+
}
|
|
2036
1946
|
/**
|
|
2037
1947
|
* Notify view that HTML update is about to begin.
|
|
2038
1948
|
* Unmounts child frames in the update zone.
|
|
2039
1949
|
*/
|
|
2040
1950
|
beginUpdate(id) {
|
|
2041
1951
|
if (this.signature > 0 && this.endUpdatePending !== void 0) {
|
|
2042
|
-
this.
|
|
1952
|
+
this.ownerFrame.unmountZone(id, true);
|
|
2043
1953
|
}
|
|
2044
1954
|
}
|
|
2045
1955
|
/**
|
|
@@ -2057,12 +1967,12 @@ var View = class _View {
|
|
|
2057
1967
|
this.endUpdatePending = 1;
|
|
2058
1968
|
this.rendered = true;
|
|
2059
1969
|
}
|
|
2060
|
-
const ownerFrame = this.
|
|
1970
|
+
const ownerFrame = this.ownerFrame;
|
|
2061
1971
|
ownerFrame.mountZone(updateId, inner);
|
|
2062
1972
|
if (!flag) {
|
|
2063
1973
|
setTimeout(
|
|
2064
1974
|
this.wrapAsync(() => {
|
|
2065
|
-
runInvokes(ownerFrame);
|
|
1975
|
+
_View.runInvokes(ownerFrame);
|
|
2066
1976
|
}),
|
|
2067
1977
|
0
|
|
2068
1978
|
);
|
|
@@ -2096,11 +2006,12 @@ var View = class _View {
|
|
|
2096
2006
|
const loc = this.locationObserved;
|
|
2097
2007
|
loc.flag = 1;
|
|
2098
2008
|
if (typeof params === "object" && !Array.isArray(params)) {
|
|
2099
|
-
|
|
2009
|
+
const opts = params;
|
|
2010
|
+
if (opts["path"]) {
|
|
2100
2011
|
observePath = true;
|
|
2101
2012
|
}
|
|
2102
|
-
const paramKeys =
|
|
2103
|
-
if (paramKeys) {
|
|
2013
|
+
const paramKeys = opts["params"];
|
|
2014
|
+
if (typeof paramKeys === "string" || Array.isArray(paramKeys)) {
|
|
2104
2015
|
params = paramKeys;
|
|
2105
2016
|
}
|
|
2106
2017
|
}
|
|
@@ -2138,7 +2049,7 @@ var View = class _View {
|
|
|
2138
2049
|
capture(key, resource, destroyOnRender = false) {
|
|
2139
2050
|
const cache = this.resources;
|
|
2140
2051
|
if (resource) {
|
|
2141
|
-
destroyResource(cache, key, true, resource);
|
|
2052
|
+
_View.destroyResource(cache, key, true, resource);
|
|
2142
2053
|
cache[key] = {
|
|
2143
2054
|
entity: resource,
|
|
2144
2055
|
destroyOnRender
|
|
@@ -2154,7 +2065,7 @@ var View = class _View {
|
|
|
2154
2065
|
* If destroy=true, calls the resource's destroy() method.
|
|
2155
2066
|
*/
|
|
2156
2067
|
release(key, destroy = true) {
|
|
2157
|
-
return destroyResource(this.resources, key, destroy);
|
|
2068
|
+
return _View.destroyResource(this.resources, key, destroy);
|
|
2158
2069
|
}
|
|
2159
2070
|
// ============================================================
|
|
2160
2071
|
// Leave tip
|
|
@@ -2164,24 +2075,16 @@ var View = class _View {
|
|
|
2164
2075
|
*/
|
|
2165
2076
|
leaveTip(message, condition) {
|
|
2166
2077
|
const changeListener = function(e) {
|
|
2167
|
-
const isRouterChange = e.type ===
|
|
2078
|
+
const isRouterChange = e.type === RouterEvents.CHANGE;
|
|
2168
2079
|
const aKey = isRouterChange ? "a" : "b";
|
|
2169
2080
|
const bKey = isRouterChange ? "b" : "a";
|
|
2170
2081
|
if (changeListener[aKey]) {
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
}
|
|
2174
|
-
if (typeof e.reject === "function") {
|
|
2175
|
-
e.reject();
|
|
2176
|
-
}
|
|
2082
|
+
e.prevent?.();
|
|
2083
|
+
e.reject?.();
|
|
2177
2084
|
} else if (condition()) {
|
|
2178
|
-
|
|
2179
|
-
e.prevent();
|
|
2180
|
-
}
|
|
2085
|
+
e.prevent?.();
|
|
2181
2086
|
changeListener[bKey] = 1;
|
|
2182
|
-
|
|
2183
|
-
e.resolve();
|
|
2184
|
-
}
|
|
2087
|
+
e.resolve?.();
|
|
2185
2088
|
}
|
|
2186
2089
|
};
|
|
2187
2090
|
const unloadListener = (e) => {
|
|
@@ -2189,21 +2092,284 @@ var View = class _View {
|
|
|
2189
2092
|
e["msg"] = message;
|
|
2190
2093
|
}
|
|
2191
2094
|
};
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
Router.on(ROUTER_EVENTS.PAGE_UNLOAD, unloadFn);
|
|
2196
|
-
this.on("unload", changeFn);
|
|
2095
|
+
Router.on(RouterEvents.CHANGE, changeListener);
|
|
2096
|
+
Router.on(RouterEvents.PAGE_UNLOAD, unloadListener);
|
|
2097
|
+
this.on("unload", changeListener);
|
|
2197
2098
|
this.on("destroy", () => {
|
|
2198
|
-
Router.off(
|
|
2199
|
-
Router.off(
|
|
2099
|
+
Router.off(RouterEvents.CHANGE, changeListener);
|
|
2100
|
+
Router.off(RouterEvents.PAGE_UNLOAD, unloadListener);
|
|
2200
2101
|
});
|
|
2201
2102
|
}
|
|
2202
2103
|
// ============================================================
|
|
2203
|
-
// Static
|
|
2104
|
+
// Static public methods
|
|
2204
2105
|
// ============================================================
|
|
2205
2106
|
/** Collected ctors from mixins */
|
|
2206
2107
|
static ctors;
|
|
2108
|
+
/**
|
|
2109
|
+
* Prepare a View subclass by scanning its prototype for event method patterns.
|
|
2110
|
+
* Pattern: `$?name<eventType1,eventType2>(&modifiers)`
|
|
2111
|
+
*
|
|
2112
|
+
* Only runs once per View subclass (guarded by ctors marker).
|
|
2113
|
+
* Called from Frame.mountView before creating the view instance.
|
|
2114
|
+
*/
|
|
2115
|
+
static prepare(oView) {
|
|
2116
|
+
if (oView.ctors) {
|
|
2117
|
+
return oView.ctors;
|
|
2118
|
+
}
|
|
2119
|
+
const ctors = [];
|
|
2120
|
+
oView.ctors = ctors;
|
|
2121
|
+
const proto = oView.prototype;
|
|
2122
|
+
const eventsObject = {};
|
|
2123
|
+
const eventsList = [];
|
|
2124
|
+
const selectorObject = {};
|
|
2125
|
+
const mixins = proto["mixins"];
|
|
2126
|
+
if (mixins && Array.isArray(mixins)) {
|
|
2127
|
+
_View.mergeMixins(mixins, oView, ctors);
|
|
2128
|
+
}
|
|
2129
|
+
for (const p in proto) {
|
|
2130
|
+
if (!hasOwnProperty(proto, p)) continue;
|
|
2131
|
+
const currentFn = proto[p];
|
|
2132
|
+
if (typeof currentFn !== "function") continue;
|
|
2133
|
+
const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
|
|
2134
|
+
if (!matches) continue;
|
|
2135
|
+
const isSelector = matches[1];
|
|
2136
|
+
const selectorOrCallback = matches[2];
|
|
2137
|
+
const events = matches[3];
|
|
2138
|
+
const modifiers = matches[4];
|
|
2139
|
+
const mod = {};
|
|
2140
|
+
if (modifiers) {
|
|
2141
|
+
for (const item of modifiers.split(",")) {
|
|
2142
|
+
mod[item] = true;
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
const eventTypes = events.split(",");
|
|
2146
|
+
for (const item of eventTypes) {
|
|
2147
|
+
const globalNode = VIEW_GLOBALS[selectorOrCallback];
|
|
2148
|
+
let mask = 1;
|
|
2149
|
+
if (isSelector) {
|
|
2150
|
+
if (globalNode) {
|
|
2151
|
+
eventsList.push({
|
|
2152
|
+
handler: currentFn,
|
|
2153
|
+
element: globalNode,
|
|
2154
|
+
eventName: item,
|
|
2155
|
+
modifiers: mod
|
|
2156
|
+
});
|
|
2157
|
+
continue;
|
|
2158
|
+
}
|
|
2159
|
+
mask = 2;
|
|
2160
|
+
let selectorEntry = selectorObject[item];
|
|
2161
|
+
if (!selectorEntry) {
|
|
2162
|
+
selectorEntry = selectorObject[item] = {
|
|
2163
|
+
selectors: []
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
if (!selectorEntry[selectorOrCallback]) {
|
|
2167
|
+
selectorEntry[selectorOrCallback] = 1;
|
|
2168
|
+
selectorEntry.selectors.push(selectorOrCallback);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
eventsObject[item] = (eventsObject[item] || 0) | mask;
|
|
2172
|
+
const combinedKey = selectorOrCallback + SPLITTER + item;
|
|
2173
|
+
const existingFn = proto[combinedKey];
|
|
2174
|
+
if (!existingFn) {
|
|
2175
|
+
proto[combinedKey] = currentFn;
|
|
2176
|
+
} else if (typeof existingFn === "function") {
|
|
2177
|
+
const mixinFn = currentFn;
|
|
2178
|
+
const existingMixin = existingFn;
|
|
2179
|
+
if (existingMixin.marker) {
|
|
2180
|
+
if (mixinFn.marker) {
|
|
2181
|
+
proto[combinedKey] = _View.processMixinsSameEvent(
|
|
2182
|
+
mixinFn,
|
|
2183
|
+
existingMixin
|
|
2184
|
+
);
|
|
2185
|
+
} else if (hasOwnProperty(proto, p)) {
|
|
2186
|
+
proto[combinedKey] = currentFn;
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
_View.wrapMethod(proto, "render", "$renderWrap");
|
|
2193
|
+
proto["$evtObjMap"] = eventsObject;
|
|
2194
|
+
proto["$globalEvtList"] = eventsList;
|
|
2195
|
+
proto["$selMap"] = selectorObject;
|
|
2196
|
+
proto["$assignFn"] = proto["assign"];
|
|
2197
|
+
return ctors;
|
|
2198
|
+
}
|
|
2199
|
+
/**
|
|
2200
|
+
* Bind or unbind event delegation for a view instance.
|
|
2201
|
+
* Called from Frame during mount/unmount.
|
|
2202
|
+
*/
|
|
2203
|
+
static delegateEvents(view, destroy = false) {
|
|
2204
|
+
const eventsObject = view.eventObjectMap;
|
|
2205
|
+
const selectorObject = view.eventSelectorMap;
|
|
2206
|
+
const eventsList = view.globalEventList;
|
|
2207
|
+
for (const e in eventsObject) {
|
|
2208
|
+
if (hasOwnProperty(eventsObject, e)) {
|
|
2209
|
+
if (destroy) {
|
|
2210
|
+
EventDelegator.unbind(e, !!selectorObject[e]);
|
|
2211
|
+
} else {
|
|
2212
|
+
EventDelegator.bind(e, !!selectorObject[e]);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
for (const entry of eventsList) {
|
|
2217
|
+
if (destroy) {
|
|
2218
|
+
entry.element.removeEventListener(
|
|
2219
|
+
entry.eventName,
|
|
2220
|
+
entry.boundHandler
|
|
2221
|
+
);
|
|
2222
|
+
} else {
|
|
2223
|
+
const handler = entry.handler;
|
|
2224
|
+
const element = entry.element;
|
|
2225
|
+
const modifiers = entry.modifiers;
|
|
2226
|
+
entry.boundHandler = function(domEvent) {
|
|
2227
|
+
const extendedEvent = domEvent;
|
|
2228
|
+
extendedEvent.eventTarget = element;
|
|
2229
|
+
if (modifiers) {
|
|
2230
|
+
const kbEvent = domEvent;
|
|
2231
|
+
if (modifiers["ctrl"] && !kbEvent.ctrlKey || modifiers["shift"] && !kbEvent.shiftKey || modifiers["alt"] && !kbEvent.altKey || modifiers["meta"] && !kbEvent.metaKey) {
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
funcWithTry(handler, [domEvent], view, noop);
|
|
2236
|
+
};
|
|
2237
|
+
entry.element.addEventListener(
|
|
2238
|
+
entry.eventName,
|
|
2239
|
+
entry.boundHandler
|
|
2240
|
+
);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* Destroy all resources managed by a view.
|
|
2246
|
+
* If lastly=true, destroy ALL resources; otherwise only destroyOnRender ones.
|
|
2247
|
+
*/
|
|
2248
|
+
static destroyAllResources(view, lastly) {
|
|
2249
|
+
const cache = view.resources;
|
|
2250
|
+
for (const p in cache) {
|
|
2251
|
+
if (hasOwnProperty(cache, p)) {
|
|
2252
|
+
const entry = cache[p];
|
|
2253
|
+
if (lastly || entry.destroyOnRender) {
|
|
2254
|
+
_View.destroyResource(cache, p, true);
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
/**
|
|
2260
|
+
* Process deferred invoke calls on a frame.
|
|
2261
|
+
*/
|
|
2262
|
+
static runInvokes(frame) {
|
|
2263
|
+
const list = frame.invokeList;
|
|
2264
|
+
if (!list) return;
|
|
2265
|
+
while (list.length) {
|
|
2266
|
+
const entry = list.shift();
|
|
2267
|
+
if (entry && !entry.removed) {
|
|
2268
|
+
frame.invoke(entry.name, entry.args);
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
// ============================================================
|
|
2273
|
+
// Static private methods
|
|
2274
|
+
// ============================================================
|
|
2275
|
+
/**
|
|
2276
|
+
* Wrap a method on the prototype to add signature checking and resource cleanup.
|
|
2277
|
+
*/
|
|
2278
|
+
static wrapMethod(proto, fnName, shortKey) {
|
|
2279
|
+
const originalFn = proto[fnName];
|
|
2280
|
+
if (typeof originalFn !== "function") return;
|
|
2281
|
+
const originalAsFn = originalFn;
|
|
2282
|
+
const wrapped = function(...args) {
|
|
2283
|
+
if (this.signature > 0) {
|
|
2284
|
+
this.signature++;
|
|
2285
|
+
this.fire("render");
|
|
2286
|
+
_View.destroyAllResources(this, false);
|
|
2287
|
+
const lookup = this;
|
|
2288
|
+
const candidate = lookup[fnName];
|
|
2289
|
+
const instanceFn = typeof candidate === "function" ? candidate : originalAsFn;
|
|
2290
|
+
const fnToCall = instanceFn === wrapped ? originalAsFn : instanceFn;
|
|
2291
|
+
return funcWithTry(fnToCall, args, this, noop);
|
|
2292
|
+
}
|
|
2293
|
+
return void 0;
|
|
2294
|
+
};
|
|
2295
|
+
proto[fnName] = wrapped;
|
|
2296
|
+
proto[shortKey] = wrapped;
|
|
2297
|
+
}
|
|
2298
|
+
/**
|
|
2299
|
+
* When two mixins define the same event method, merge them into
|
|
2300
|
+
* a single function that calls both in sequence.
|
|
2301
|
+
*/
|
|
2302
|
+
static processMixinsSameEvent(additional, exist) {
|
|
2303
|
+
let temp;
|
|
2304
|
+
if (exist.handlerList) {
|
|
2305
|
+
temp = exist;
|
|
2306
|
+
} else {
|
|
2307
|
+
const merged = function(...e) {
|
|
2308
|
+
funcWithTry(merged.handlerList ?? [], e, this, noop);
|
|
2309
|
+
};
|
|
2310
|
+
merged.handlerList = [exist];
|
|
2311
|
+
merged.marker = 1;
|
|
2312
|
+
temp = merged;
|
|
2313
|
+
}
|
|
2314
|
+
temp.handlerList = (temp.handlerList ?? []).concat(
|
|
2315
|
+
additional.handlerList ?? [additional]
|
|
2316
|
+
);
|
|
2317
|
+
return temp;
|
|
2318
|
+
}
|
|
2319
|
+
/**
|
|
2320
|
+
* Merge an array of mixin objects into the view prototype.
|
|
2321
|
+
*/
|
|
2322
|
+
static mergeMixins(mixins, viewClass, ctors) {
|
|
2323
|
+
const proto = viewClass.prototype;
|
|
2324
|
+
const temp = {};
|
|
2325
|
+
for (const node of mixins) {
|
|
2326
|
+
for (const p in node) {
|
|
2327
|
+
if (!hasOwnProperty(node, p)) continue;
|
|
2328
|
+
const fn = node[p];
|
|
2329
|
+
if (typeof fn !== "function") continue;
|
|
2330
|
+
const mixinFn = fn;
|
|
2331
|
+
const exist = temp[p];
|
|
2332
|
+
if (p === "make") {
|
|
2333
|
+
ctors.push(mixinFn);
|
|
2334
|
+
continue;
|
|
2335
|
+
}
|
|
2336
|
+
if (VIEW_EVENT_METHOD_REGEXP.test(p)) {
|
|
2337
|
+
if (exist) {
|
|
2338
|
+
temp[p] = _View.processMixinsSameEvent(mixinFn, exist);
|
|
2339
|
+
} else {
|
|
2340
|
+
mixinFn.marker = 1;
|
|
2341
|
+
temp[p] = mixinFn;
|
|
2342
|
+
}
|
|
2343
|
+
} else if (!exist) {
|
|
2344
|
+
temp[p] = mixinFn;
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
for (const p in temp) {
|
|
2349
|
+
if (!hasOwnProperty(proto, p)) {
|
|
2350
|
+
proto[p] = temp[p];
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Destroy a single resource entry.
|
|
2356
|
+
*/
|
|
2357
|
+
static destroyResource(cache, key, callDestroy, oldEntity) {
|
|
2358
|
+
const entry = cache[key];
|
|
2359
|
+
if (!entry || entry.entity === oldEntity) return void 0;
|
|
2360
|
+
const entity = entry.entity;
|
|
2361
|
+
if (entity && typeof entity === "object") {
|
|
2362
|
+
const destroyFn = entity["destroy"];
|
|
2363
|
+
if (typeof destroyFn === "function" && callDestroy) {
|
|
2364
|
+
funcWithTry(destroyFn, [], entity, noop);
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
Reflect.deleteProperty(cache, key);
|
|
2368
|
+
return entity;
|
|
2369
|
+
}
|
|
2370
|
+
// ============================================================
|
|
2371
|
+
// Static: extend and merge
|
|
2372
|
+
// ============================================================
|
|
2207
2373
|
/**
|
|
2208
2374
|
* Extend View to create a new View subclass.
|
|
2209
2375
|
*
|
|
@@ -2213,19 +2379,20 @@ var View = class _View {
|
|
|
2213
2379
|
* - Event method patterns: `'name<click>'` etc.
|
|
2214
2380
|
*/
|
|
2215
2381
|
static extend(props, statics) {
|
|
2216
|
-
|
|
2217
|
-
const make =
|
|
2382
|
+
const definedProps = props ?? {};
|
|
2383
|
+
const make = definedProps["make"];
|
|
2218
2384
|
const ctors = [];
|
|
2219
|
-
if (make) {
|
|
2385
|
+
if (typeof make === "function") {
|
|
2220
2386
|
ctors.push(make);
|
|
2221
2387
|
}
|
|
2222
2388
|
const ParentView = this;
|
|
2223
2389
|
const ChildView = class extends ParentView {
|
|
2224
2390
|
constructor(nodeId, ownerFrame, initParams, node, mixinCtors) {
|
|
2225
2391
|
super(nodeId, ownerFrame, initParams, node, []);
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2392
|
+
const instanceProps = this;
|
|
2393
|
+
for (const key in definedProps) {
|
|
2394
|
+
if (hasOwnProperty(definedProps, key) && key !== "make" && key !== "render") {
|
|
2395
|
+
instanceProps[key] = definedProps[key];
|
|
2229
2396
|
}
|
|
2230
2397
|
}
|
|
2231
2398
|
this.id = nodeId;
|
|
@@ -2245,56 +2412,110 @@ var View = class _View {
|
|
|
2245
2412
|
}
|
|
2246
2413
|
};
|
|
2247
2414
|
const proto = ChildView.prototype;
|
|
2248
|
-
for (const key in
|
|
2249
|
-
if (
|
|
2250
|
-
proto[key] =
|
|
2415
|
+
for (const key in definedProps) {
|
|
2416
|
+
if (hasOwnProperty(definedProps, key) && key !== "make") {
|
|
2417
|
+
proto[key] = definedProps[key];
|
|
2251
2418
|
}
|
|
2252
2419
|
}
|
|
2253
2420
|
if (statics) {
|
|
2421
|
+
const staticTarget = ChildView;
|
|
2254
2422
|
for (const key in statics) {
|
|
2255
|
-
if (
|
|
2256
|
-
|
|
2423
|
+
if (hasOwnProperty(statics, key)) {
|
|
2424
|
+
staticTarget[key] = statics[key];
|
|
2257
2425
|
}
|
|
2258
2426
|
}
|
|
2259
2427
|
}
|
|
2260
|
-
ChildView.merge = viewMerge;
|
|
2261
|
-
ChildView.extend = _View.extend;
|
|
2262
2428
|
return ChildView;
|
|
2263
2429
|
}
|
|
2264
2430
|
/**
|
|
2265
2431
|
* Merge mixins into View prototype.
|
|
2266
2432
|
*/
|
|
2267
2433
|
static merge(...mixins) {
|
|
2268
|
-
const
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
return self;
|
|
2434
|
+
const existingCtors = this.ctors || [];
|
|
2435
|
+
_View.mergeMixins(mixins, this, existingCtors);
|
|
2436
|
+
return this;
|
|
2272
2437
|
}
|
|
2273
2438
|
};
|
|
2274
|
-
function
|
|
2275
|
-
|
|
2276
|
-
const existingCtors = self.ctors || [];
|
|
2277
|
-
viewMergeMixins(mixins, self, existingCtors);
|
|
2278
|
-
return self;
|
|
2439
|
+
function defineView(props, statics) {
|
|
2440
|
+
return View.extend(props, statics);
|
|
2279
2441
|
}
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
}
|
|
2442
|
+
|
|
2443
|
+
// src/module-loader.ts
|
|
2444
|
+
var config = {
|
|
2445
|
+
rootId: "root",
|
|
2446
|
+
hashbang: "#!",
|
|
2447
|
+
error: (error) => {
|
|
2448
|
+
throw error;
|
|
2288
2449
|
}
|
|
2450
|
+
};
|
|
2451
|
+
function use(names, callback) {
|
|
2452
|
+
const nameList = typeof names === "string" ? [names] : names;
|
|
2453
|
+
const loadPromise = (() => {
|
|
2454
|
+
if (config.require) {
|
|
2455
|
+
const result = config.require(nameList);
|
|
2456
|
+
if (result && typeof result.then === "function") {
|
|
2457
|
+
return result;
|
|
2458
|
+
}
|
|
2459
|
+
return Promise.resolve([]);
|
|
2460
|
+
}
|
|
2461
|
+
return Promise.all(
|
|
2462
|
+
nameList.map((name) => {
|
|
2463
|
+
const importPath = name.startsWith(".") || name.startsWith("/") ? name : `./${name}`;
|
|
2464
|
+
return import(
|
|
2465
|
+
/* @vite-ignore */
|
|
2466
|
+
/* webpackIgnore: true */
|
|
2467
|
+
importPath
|
|
2468
|
+
).then((mod) => {
|
|
2469
|
+
return mod && (mod["__esModule"] || // For Webpack
|
|
2470
|
+
typeof mod["default"] === "function") ? mod["default"] : mod;
|
|
2471
|
+
}).catch((err) => {
|
|
2472
|
+
const errorHandler = config.error;
|
|
2473
|
+
if (errorHandler) {
|
|
2474
|
+
errorHandler(err instanceof Error ? err : new Error(String(err)));
|
|
2475
|
+
}
|
|
2476
|
+
return void 0;
|
|
2477
|
+
});
|
|
2478
|
+
})
|
|
2479
|
+
);
|
|
2480
|
+
})();
|
|
2481
|
+
if (callback) {
|
|
2482
|
+
loadPromise.then((modules) => {
|
|
2483
|
+
callback(...modules);
|
|
2484
|
+
});
|
|
2485
|
+
}
|
|
2486
|
+
return loadPromise;
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
// src/view-registry.ts
|
|
2490
|
+
var viewClassRegistry = {};
|
|
2491
|
+
function getViewClass(path) {
|
|
2492
|
+
return viewClassRegistry[path];
|
|
2493
|
+
}
|
|
2494
|
+
function registerViewClass(viewPath, ViewClass) {
|
|
2495
|
+
const parsed = parseUri(viewPath);
|
|
2496
|
+
const path = parsed.path;
|
|
2497
|
+
if (path) {
|
|
2498
|
+
viewClassRegistry[path] = ViewClass;
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
function invalidateViewClass(viewPath) {
|
|
2502
|
+
const parsed = parseUri(viewPath);
|
|
2503
|
+
const path = parsed.path;
|
|
2504
|
+
if (path) {
|
|
2505
|
+
Reflect.deleteProperty(viewClassRegistry, path);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
function getViewClassRegistry() {
|
|
2509
|
+
return viewClassRegistry;
|
|
2289
2510
|
}
|
|
2290
2511
|
|
|
2291
2512
|
// src/frame.ts
|
|
2292
2513
|
var frameRegistry = /* @__PURE__ */ new Map();
|
|
2293
2514
|
var rootFrame;
|
|
2294
2515
|
var globalAlter;
|
|
2516
|
+
var MAX_FRAME_POOL = 64;
|
|
2295
2517
|
var frameCache = [];
|
|
2296
2518
|
var staticEmitter = new EventEmitter();
|
|
2297
|
-
var viewClassRegistry = {};
|
|
2298
2519
|
var Frame = class _Frame extends EventEmitter {
|
|
2299
2520
|
/** Frame ID (same as owner DOM element ID) */
|
|
2300
2521
|
id;
|
|
@@ -2309,8 +2530,8 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2309
2530
|
childrenCount = 0;
|
|
2310
2531
|
/** Ready count (children that have fired 'created') */
|
|
2311
2532
|
readyCount = 0;
|
|
2312
|
-
/**
|
|
2313
|
-
readyMap =
|
|
2533
|
+
/** Set of child frame IDs that have fired 'created' */
|
|
2534
|
+
readyMap = /* @__PURE__ */ new Set();
|
|
2314
2535
|
/** View instance */
|
|
2315
2536
|
viewInstance;
|
|
2316
2537
|
/** Get view instance (read-only) */
|
|
@@ -2381,31 +2602,42 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2381
2602
|
this.viewPath = viewPath;
|
|
2382
2603
|
const params = parsed["params"];
|
|
2383
2604
|
translateQuery(pId || this.id, viewPath, params);
|
|
2605
|
+
const initParams = { ...params };
|
|
2384
2606
|
if (viewInitParams) {
|
|
2385
|
-
assign(
|
|
2607
|
+
assign(initParams, viewInitParams);
|
|
2386
2608
|
}
|
|
2387
2609
|
const sign = this.signature;
|
|
2388
|
-
|
|
2389
|
-
|
|
2610
|
+
const registered = getViewClass(viewClassName);
|
|
2611
|
+
if (registered) {
|
|
2612
|
+
this.doMountView(registered, initParams, node, sign);
|
|
2613
|
+
return;
|
|
2390
2614
|
}
|
|
2615
|
+
use(viewClassName, (ViewClass) => {
|
|
2616
|
+
if (sign !== this.signature) return;
|
|
2617
|
+
if (typeof ViewClass === "function") {
|
|
2618
|
+
const ViewClassTyped = ViewClass;
|
|
2619
|
+
registerViewClass(viewClassName, ViewClassTyped);
|
|
2620
|
+
this.doMountView(ViewClassTyped, initParams, node, sign);
|
|
2621
|
+
} else {
|
|
2622
|
+
const error = new Error(`Cannot load view: ${viewClassName}`);
|
|
2623
|
+
const errorHandler = config.error;
|
|
2624
|
+
if (errorHandler) {
|
|
2625
|
+
errorHandler(error);
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
});
|
|
2391
2629
|
}
|
|
2392
2630
|
/**
|
|
2393
2631
|
* Internal: actually mount the view after class is loaded.
|
|
2394
2632
|
*/
|
|
2395
2633
|
doMountView(ViewClass, params, node, sign) {
|
|
2396
2634
|
if (sign !== this.signature) return;
|
|
2397
|
-
const mixinCtors =
|
|
2398
|
-
const
|
|
2399
|
-
const view = new
|
|
2400
|
-
this.id,
|
|
2401
|
-
this,
|
|
2402
|
-
params,
|
|
2403
|
-
node,
|
|
2404
|
-
mixinCtors
|
|
2405
|
-
);
|
|
2635
|
+
const mixinCtors = View.prepare(ViewClass);
|
|
2636
|
+
const Ctor = ViewClass;
|
|
2637
|
+
const view = new Ctor(this.id, this, params, node, mixinCtors);
|
|
2406
2638
|
this.viewInstance = view;
|
|
2407
2639
|
view.signature = 1;
|
|
2408
|
-
|
|
2640
|
+
View.delegateEvents(view);
|
|
2409
2641
|
const initResult = funcWithTry(
|
|
2410
2642
|
view.init,
|
|
2411
2643
|
[params, { node, deep: !view.template }],
|
|
@@ -2416,13 +2648,10 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2416
2648
|
Promise.resolve(initResult).then(() => {
|
|
2417
2649
|
if (nextSign !== this.signature) return;
|
|
2418
2650
|
if (view.template) {
|
|
2419
|
-
|
|
2420
|
-
if (renderFn) {
|
|
2421
|
-
renderFn.call(view);
|
|
2422
|
-
}
|
|
2651
|
+
view.render();
|
|
2423
2652
|
} else {
|
|
2424
2653
|
this.hasAltered = 0;
|
|
2425
|
-
if (!view
|
|
2654
|
+
if (!view.endUpdatePendingFlag) {
|
|
2426
2655
|
view.endUpdate();
|
|
2427
2656
|
}
|
|
2428
2657
|
}
|
|
@@ -2486,7 +2715,9 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2486
2715
|
frame.unmountView();
|
|
2487
2716
|
removeFrame(targetId, wasCreated);
|
|
2488
2717
|
reInitFrameForCache(frame);
|
|
2489
|
-
frameCache.
|
|
2718
|
+
if (frameCache.length < MAX_FRAME_POOL) {
|
|
2719
|
+
frameCache.push(frame);
|
|
2720
|
+
}
|
|
2490
2721
|
const parent = frameRegistry.get(pId || "");
|
|
2491
2722
|
if (parent && parent.childrenMap[targetId]) {
|
|
2492
2723
|
Reflect.deleteProperty(parent.childrenMap, targetId);
|
|
@@ -2505,13 +2736,12 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2505
2736
|
const viewElements = rootEl.querySelectorAll(`[${LARK_VIEW}]`);
|
|
2506
2737
|
const frames = [];
|
|
2507
2738
|
viewElements.forEach((el) => {
|
|
2508
|
-
|
|
2509
|
-
if (
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
}
|
|
2739
|
+
if (!(el instanceof HTMLElement)) return;
|
|
2740
|
+
if (htmlElIsBound(el)) return;
|
|
2741
|
+
const elId = ensureElementId2(el);
|
|
2742
|
+
el.frameBound = 1;
|
|
2743
|
+
const viewPath = getAttribute(el, LARK_VIEW);
|
|
2744
|
+
frames.push([elId, viewPath]);
|
|
2515
2745
|
});
|
|
2516
2746
|
for (const [frameId, viewPath] of frames) {
|
|
2517
2747
|
this.mountFrame(frameId, viewPath);
|
|
@@ -2524,7 +2754,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2524
2754
|
*/
|
|
2525
2755
|
unmountZone(zoneId, _inner) {
|
|
2526
2756
|
for (const childId in this.childrenMap) {
|
|
2527
|
-
if (
|
|
2757
|
+
if (hasOwnProperty(this.childrenMap, childId)) {
|
|
2528
2758
|
if (!zoneId || childId !== zoneId) {
|
|
2529
2759
|
this.unmountFrame(childId);
|
|
2530
2760
|
}
|
|
@@ -2538,7 +2768,7 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2538
2768
|
children() {
|
|
2539
2769
|
const result = [];
|
|
2540
2770
|
for (const id in this.childrenMap) {
|
|
2541
|
-
if (
|
|
2771
|
+
if (hasOwnProperty(this.childrenMap, id)) {
|
|
2542
2772
|
result.push(id);
|
|
2543
2773
|
}
|
|
2544
2774
|
}
|
|
@@ -2565,14 +2795,10 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2565
2795
|
let result;
|
|
2566
2796
|
const view = this.view;
|
|
2567
2797
|
if (view && view.rendered) {
|
|
2568
|
-
const
|
|
2798
|
+
const lookup = view;
|
|
2799
|
+
const fn = lookup[name];
|
|
2569
2800
|
if (typeof fn === "function") {
|
|
2570
|
-
result = funcWithTry(
|
|
2571
|
-
fn,
|
|
2572
|
-
args || [],
|
|
2573
|
-
view,
|
|
2574
|
-
noop
|
|
2575
|
-
);
|
|
2801
|
+
result = funcWithTry(fn, args || [], view, noop);
|
|
2576
2802
|
}
|
|
2577
2803
|
} else {
|
|
2578
2804
|
const key = SPLITTER + name;
|
|
@@ -2595,6 +2821,25 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2595
2821
|
}
|
|
2596
2822
|
return result;
|
|
2597
2823
|
}
|
|
2824
|
+
/**
|
|
2825
|
+
* Type-safe variant of `invoke`.
|
|
2826
|
+
*
|
|
2827
|
+
* `invoke()` accepts any string and any args, which silently hides
|
|
2828
|
+
* mismatched call sites when a method gets renamed. `invokeTyped` carries
|
|
2829
|
+
* the view's method signature through TypeScript so the compiler catches
|
|
2830
|
+
* those mistakes:
|
|
2831
|
+
*
|
|
2832
|
+
* ```ts
|
|
2833
|
+
* type Home = View & { loadData(id: string): Promise<void> };
|
|
2834
|
+
* frame.invokeTyped<Home, "loadData">("loadData", ["user-1"]);
|
|
2835
|
+
* ```
|
|
2836
|
+
*
|
|
2837
|
+
* Behavior is identical to `invoke` at runtime — same defer / direct-call
|
|
2838
|
+
* paths — so it's a drop-in safer overload.
|
|
2839
|
+
*/
|
|
2840
|
+
invokeTyped(name, args) {
|
|
2841
|
+
return this.invoke(name, args);
|
|
2842
|
+
}
|
|
2598
2843
|
// ============================================================
|
|
2599
2844
|
// Static methods
|
|
2600
2845
|
// ============================================================
|
|
@@ -2606,10 +2851,27 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2606
2851
|
static getAll() {
|
|
2607
2852
|
return frameRegistry;
|
|
2608
2853
|
}
|
|
2609
|
-
/**
|
|
2610
|
-
|
|
2854
|
+
/**
|
|
2855
|
+
* Returns the existing root frame, or `undefined` if none has been created.
|
|
2856
|
+
* Pure getter — never creates a Frame, never touches the DOM.
|
|
2857
|
+
*
|
|
2858
|
+
* Use `Frame.createRoot(id)` to create the root explicitly during framework
|
|
2859
|
+
* boot. For Micro-Frontend hosts that own multiple independent containers,
|
|
2860
|
+
* use `new Frame(containerId)` directly so each MF mount has its own root.
|
|
2861
|
+
*/
|
|
2862
|
+
static getRoot() {
|
|
2863
|
+
return rootFrame;
|
|
2864
|
+
}
|
|
2865
|
+
/**
|
|
2866
|
+
* Create (or return) the singleton root frame for this app.
|
|
2867
|
+
*
|
|
2868
|
+
* Idempotent: subsequent calls always return the original root regardless
|
|
2869
|
+
* of `rootId` — so passing a different id later is silently ignored.
|
|
2870
|
+
* `Framework.boot()` is the canonical caller; user code rarely needs this.
|
|
2871
|
+
*/
|
|
2872
|
+
static createRoot(rootId) {
|
|
2611
2873
|
if (!rootFrame) {
|
|
2612
|
-
rootId = rootId || "
|
|
2874
|
+
rootId = rootId || "root";
|
|
2613
2875
|
let rootElement = document.getElementById(rootId);
|
|
2614
2876
|
if (!rootElement) {
|
|
2615
2877
|
rootElement = document.body;
|
|
@@ -2619,6 +2881,17 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2619
2881
|
}
|
|
2620
2882
|
return rootFrame;
|
|
2621
2883
|
}
|
|
2884
|
+
/**
|
|
2885
|
+
* @deprecated Use `Frame.getRoot()` for read-only access or
|
|
2886
|
+
* `Frame.createRoot(id)` to create the root explicitly. The single-method
|
|
2887
|
+
* `root()` blurred the distinction and was a common source of bugs in
|
|
2888
|
+
* Micro-Frontend hosts.
|
|
2889
|
+
*
|
|
2890
|
+
* Kept for backward compatibility — behavior unchanged.
|
|
2891
|
+
*/
|
|
2892
|
+
static root(rootId) {
|
|
2893
|
+
return _Frame.createRoot(rootId);
|
|
2894
|
+
}
|
|
2622
2895
|
/** Bind event listener (static) */
|
|
2623
2896
|
static on(event, handler) {
|
|
2624
2897
|
staticEmitter.on(event, handler);
|
|
@@ -2634,6 +2907,9 @@ var Frame = class _Frame extends EventEmitter {
|
|
|
2634
2907
|
staticEmitter.fire(event, data);
|
|
2635
2908
|
}
|
|
2636
2909
|
};
|
|
2910
|
+
function htmlElIsBound(element) {
|
|
2911
|
+
return !!element.frameBound;
|
|
2912
|
+
}
|
|
2637
2913
|
function ensureElementId2(element) {
|
|
2638
2914
|
const id = element.getAttribute("id");
|
|
2639
2915
|
if (id) return id;
|
|
@@ -2663,8 +2939,8 @@ function notifyCreated(frameInstance) {
|
|
|
2663
2939
|
const pId = frameInstance.parentId;
|
|
2664
2940
|
if (pId) {
|
|
2665
2941
|
const parent = frameRegistry.get(pId);
|
|
2666
|
-
if (parent && !parent.readyMap
|
|
2667
|
-
parent.readyMap
|
|
2942
|
+
if (parent && !parent.readyMap.has(frameInstance.id)) {
|
|
2943
|
+
parent.readyMap.add(frameInstance.id);
|
|
2668
2944
|
parent.readyCount++;
|
|
2669
2945
|
notifyCreated(parent);
|
|
2670
2946
|
}
|
|
@@ -2679,9 +2955,9 @@ function notifyAlter(frameInstance, data) {
|
|
|
2679
2955
|
const pId = frameInstance.parentId;
|
|
2680
2956
|
if (pId) {
|
|
2681
2957
|
const parent = frameRegistry.get(pId);
|
|
2682
|
-
if (parent && parent.readyMap
|
|
2958
|
+
if (parent && parent.readyMap.has(frameInstance.id)) {
|
|
2683
2959
|
parent.readyCount--;
|
|
2684
|
-
|
|
2960
|
+
parent.readyMap.delete(frameInstance.id);
|
|
2685
2961
|
notifyAlter(parent, data);
|
|
2686
2962
|
}
|
|
2687
2963
|
}
|
|
@@ -2694,7 +2970,7 @@ function reInitFrame(frame, id, parentId) {
|
|
|
2694
2970
|
frame["childrenCount"] = 0;
|
|
2695
2971
|
frame["readyCount"] = 0;
|
|
2696
2972
|
frame["signature"] = 1;
|
|
2697
|
-
frame["readyMap"] =
|
|
2973
|
+
frame["readyMap"] = /* @__PURE__ */ new Set();
|
|
2698
2974
|
frame["invokeList"] = [];
|
|
2699
2975
|
frameRegistry.set(id, frame);
|
|
2700
2976
|
}
|
|
@@ -2702,7 +2978,7 @@ function reInitFrameForCache(frame) {
|
|
|
2702
2978
|
Reflect.set(frame, "id", "");
|
|
2703
2979
|
frame["_parentId"] = void 0;
|
|
2704
2980
|
frame["childrenMap"] = {};
|
|
2705
|
-
frame["readyMap"] =
|
|
2981
|
+
frame["readyMap"] = /* @__PURE__ */ new Set();
|
|
2706
2982
|
}
|
|
2707
2983
|
function translateQuery(pId, src, params) {
|
|
2708
2984
|
const parentFrame = frameRegistry.get(pId);
|
|
@@ -2712,37 +2988,153 @@ function translateQuery(pId, src, params) {
|
|
|
2712
2988
|
if (!parentRefData) return;
|
|
2713
2989
|
if (src.indexOf(SPLITTER) > 0) {
|
|
2714
2990
|
translateData(parentRefData, params);
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
);
|
|
2991
|
+
const paramsRec = params;
|
|
2992
|
+
const splitterValue = paramsRec[SPLITTER];
|
|
2993
|
+
if (splitterValue && typeof splitterValue === "object") {
|
|
2994
|
+
assign(params, splitterValue);
|
|
2720
2995
|
Reflect.deleteProperty(params, SPLITTER);
|
|
2721
2996
|
}
|
|
2722
2997
|
}
|
|
2723
2998
|
}
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2999
|
+
|
|
3000
|
+
// src/cross-site.ts
|
|
3001
|
+
var preparePromises = {};
|
|
3002
|
+
var projectsMap = null;
|
|
3003
|
+
function loadRemoteView(viewPath, bizCode) {
|
|
3004
|
+
const crossConfigs = config.crossConfigs || window.crossConfigs;
|
|
3005
|
+
const currentName = config.projectName || "";
|
|
3006
|
+
const slashIndex = viewPath.indexOf("/");
|
|
3007
|
+
const projectName = slashIndex > -1 ? viewPath.substring(0, slashIndex) : viewPath;
|
|
3008
|
+
if (projectName === currentName) return Promise.resolve();
|
|
3009
|
+
if (!preparePromises[projectName]) {
|
|
3010
|
+
if (!projectsMap) {
|
|
3011
|
+
const map = toMap(crossConfigs || [], "projectName");
|
|
3012
|
+
projectsMap = map;
|
|
3013
|
+
}
|
|
3014
|
+
const info = projectsMap[projectName];
|
|
3015
|
+
if (!info) {
|
|
3016
|
+
return Promise.reject(
|
|
3017
|
+
new Error(`Cannot find ${projectName} from crossConfigs`)
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
3020
|
+
preparePromises[projectName] = use(`${projectName}/prepare`).then((modules) => {
|
|
3021
|
+
let mod = modules[0];
|
|
3022
|
+
if (mod && typeof mod === "object" && mod !== null) {
|
|
3023
|
+
const rec = mod;
|
|
3024
|
+
if (rec["__esModule"]) {
|
|
3025
|
+
mod = rec["default"];
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
if (typeof mod === "function") {
|
|
3029
|
+
return mod({ bizCode });
|
|
3030
|
+
}
|
|
3031
|
+
return void 0;
|
|
3032
|
+
}).catch((err) => {
|
|
3033
|
+
Reflect.deleteProperty(preparePromises, projectName);
|
|
3034
|
+
throw err;
|
|
3035
|
+
});
|
|
2729
3036
|
}
|
|
3037
|
+
return preparePromises[projectName];
|
|
3038
|
+
}
|
|
3039
|
+
function resetProjectsMap() {
|
|
3040
|
+
projectsMap = null;
|
|
2730
3041
|
}
|
|
3042
|
+
var skeletonTemplate = (data, viewId) => {
|
|
3043
|
+
let skeletonHtml = "<div>Loading...</div>";
|
|
3044
|
+
if (data && typeof data === "object") {
|
|
3045
|
+
const candidate = data.skeleton;
|
|
3046
|
+
if (typeof candidate === "string") skeletonHtml = candidate;
|
|
3047
|
+
}
|
|
3048
|
+
return `<div id="mf_${viewId}">${skeletonHtml}</div>`;
|
|
3049
|
+
};
|
|
3050
|
+
var CrossSite = View.extend({
|
|
3051
|
+
/** Skeleton template renders loading state + child container */
|
|
3052
|
+
template: skeletonTemplate,
|
|
3053
|
+
init(params) {
|
|
3054
|
+
this.$sign = 0;
|
|
3055
|
+
this.on("destroy", () => {
|
|
3056
|
+
this.$sign = -1;
|
|
3057
|
+
});
|
|
3058
|
+
this.assign?.(params);
|
|
3059
|
+
},
|
|
3060
|
+
assign(data) {
|
|
3061
|
+
this.$view = typeof data["view"] === "string" ? data["view"] : "";
|
|
3062
|
+
const nested = data["params"];
|
|
3063
|
+
const nestedParams = nested && typeof nested === "object" ? nested : {};
|
|
3064
|
+
this.$params = { ...data, ...nestedParams };
|
|
3065
|
+
this.updater.set({
|
|
3066
|
+
skeleton: data["skeleton"],
|
|
3067
|
+
skeletonParams: data["skeletonParams"] || {},
|
|
3068
|
+
bizCode: data["bizCode"]
|
|
3069
|
+
});
|
|
3070
|
+
if (this.$sign > 0) {
|
|
3071
|
+
this.updateView();
|
|
3072
|
+
}
|
|
3073
|
+
return false;
|
|
3074
|
+
},
|
|
3075
|
+
async updateView() {
|
|
3076
|
+
const sign = ++this.$sign;
|
|
3077
|
+
const stored = this.updater.get();
|
|
3078
|
+
const bizCode = stored.bizCode;
|
|
3079
|
+
try {
|
|
3080
|
+
await loadRemoteView(this.$view, bizCode);
|
|
3081
|
+
} catch (ex) {
|
|
3082
|
+
const node = document.getElementById("mf_" + this.id);
|
|
3083
|
+
if (node) {
|
|
3084
|
+
const err = ex instanceof Error ? ex : new Error(String(ex));
|
|
3085
|
+
node.innerHTML = err.message || String(err);
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
if (this.$sign !== sign) return;
|
|
3089
|
+
const mf = Frame.get("mf_" + this.id);
|
|
3090
|
+
const parsedNew = parseUri(this.$view);
|
|
3091
|
+
const newPath = parsedNew.path;
|
|
3092
|
+
const oldPath = mf?.viewPath ? parseUri(mf.viewPath).path : "";
|
|
3093
|
+
const view = mf?.view;
|
|
3094
|
+
if (newPath === oldPath && view && typeof view.assign === "function") {
|
|
3095
|
+
const result = funcWithTry(view.assign, [this.$params], view, noop);
|
|
3096
|
+
if (result) {
|
|
3097
|
+
view.render();
|
|
3098
|
+
}
|
|
3099
|
+
return;
|
|
3100
|
+
}
|
|
3101
|
+
const owner = this.owner;
|
|
3102
|
+
if (owner && typeof owner !== "number") {
|
|
3103
|
+
owner.mountFrame("mf_" + this.id, this.$view, this.$params);
|
|
3104
|
+
}
|
|
3105
|
+
},
|
|
3106
|
+
render() {
|
|
3107
|
+
const params = this.$params;
|
|
3108
|
+
this.updater.digest({
|
|
3109
|
+
skeleton: params?.["skeleton"]
|
|
3110
|
+
});
|
|
3111
|
+
this.updateView();
|
|
3112
|
+
},
|
|
3113
|
+
/**
|
|
3114
|
+
* Invoke a method on the remote view.
|
|
3115
|
+
* Usage: mf.invoke('callView', methodName, ...args)
|
|
3116
|
+
*/
|
|
3117
|
+
callView(name, ...args) {
|
|
3118
|
+
const mf = Frame.get("mf_" + this.id);
|
|
3119
|
+
return mf?.invoke(name, args);
|
|
3120
|
+
}
|
|
3121
|
+
});
|
|
3122
|
+
var cross_site_default = CrossSite;
|
|
2731
3123
|
|
|
2732
3124
|
// src/service.ts
|
|
2733
|
-
var
|
|
2734
|
-
/**
|
|
3125
|
+
var Payload = class {
|
|
3126
|
+
/** Payload data */
|
|
2735
3127
|
data;
|
|
2736
3128
|
/** Internal cache info */
|
|
2737
3129
|
cacheInfo;
|
|
2738
3130
|
constructor(data = {}) {
|
|
2739
3131
|
this.data = data;
|
|
2740
3132
|
}
|
|
2741
|
-
/** Get a value from
|
|
3133
|
+
/** Get a value from payload data */
|
|
2742
3134
|
get(key) {
|
|
2743
3135
|
return this.data[key];
|
|
2744
3136
|
}
|
|
2745
|
-
/** Set a value in
|
|
3137
|
+
/** Set a value in payload data */
|
|
2746
3138
|
set(keyOrData, value) {
|
|
2747
3139
|
if (typeof keyOrData === "string") {
|
|
2748
3140
|
this.data[keyOrData] = value;
|
|
@@ -2754,297 +3146,398 @@ var Bag = class {
|
|
|
2754
3146
|
};
|
|
2755
3147
|
var FETCH_FLAGS_ALL = 1;
|
|
2756
3148
|
var FETCH_FLAGS_ONE = 2;
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
3149
|
+
var Service = class {
|
|
3150
|
+
/** Service instance ID */
|
|
3151
|
+
id = "";
|
|
3152
|
+
/** Whether service is busy (1 = busy) */
|
|
3153
|
+
busy = 0;
|
|
3154
|
+
/** Whether service is destroyed (1 = destroyed) */
|
|
3155
|
+
destroyed = 0;
|
|
3156
|
+
/** Task queue for sequential operations */
|
|
3157
|
+
taskQueue = [];
|
|
3158
|
+
/** Previous dequeue arguments */
|
|
3159
|
+
prevArgs = [];
|
|
3160
|
+
/** Instance event emitter */
|
|
3161
|
+
_emitter = new EventEmitter();
|
|
3162
|
+
constructor() {
|
|
3163
|
+
this.id = generateId("service");
|
|
3164
|
+
}
|
|
3165
|
+
// ============================================================
|
|
3166
|
+
// Instance accessors for type-level data
|
|
3167
|
+
// ============================================================
|
|
3168
|
+
/** Instance event emitter (public accessor) */
|
|
3169
|
+
get emitter() {
|
|
3170
|
+
return this._emitter;
|
|
3171
|
+
}
|
|
3172
|
+
/**
|
|
3173
|
+
* Get internals object for serviceSend compatibility.
|
|
3174
|
+
* References per-type static state from the current class.
|
|
3175
|
+
*/
|
|
3176
|
+
get internals() {
|
|
3177
|
+
const ctor = this.constructor;
|
|
3178
|
+
return {
|
|
3179
|
+
metaList: ctor._metaList,
|
|
3180
|
+
payloadCache: ctor._payloadCache,
|
|
3181
|
+
pendingCacheKeys: ctor._pendingCacheKeys,
|
|
3182
|
+
syncFn: ctor._syncFn,
|
|
3183
|
+
staticEmitter: ctor._staticEmitter
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
/**
|
|
3187
|
+
* Get type reference (the constructor) for serviceSend compatibility.
|
|
3188
|
+
* Static methods like get/create are accessible via the constructor.
|
|
3189
|
+
*/
|
|
3190
|
+
get type() {
|
|
3191
|
+
return this.constructor;
|
|
3192
|
+
}
|
|
3193
|
+
// ============================================================
|
|
3194
|
+
// Instance methods
|
|
3195
|
+
// ============================================================
|
|
3196
|
+
/**
|
|
3197
|
+
* Fetch all endpoints, callback when all complete.
|
|
3198
|
+
* Uses cache when available.
|
|
3199
|
+
*/
|
|
3200
|
+
all(attrs, done) {
|
|
3201
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
3202
|
+
return this;
|
|
3203
|
+
}
|
|
3204
|
+
/**
|
|
3205
|
+
* Fetch all endpoints, callback on each completion.
|
|
3206
|
+
*/
|
|
3207
|
+
one(attrs, done) {
|
|
3208
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
3209
|
+
return this;
|
|
3210
|
+
}
|
|
3211
|
+
/**
|
|
3212
|
+
* Fetch all endpoints, skip cache (always request).
|
|
3213
|
+
*/
|
|
3214
|
+
save(attrs, done) {
|
|
3215
|
+
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
3216
|
+
return this;
|
|
3217
|
+
}
|
|
3218
|
+
/**
|
|
3219
|
+
* Enqueue a task for sequential execution.
|
|
3220
|
+
*/
|
|
3221
|
+
enqueue(callback) {
|
|
3222
|
+
if (!this.destroyed) {
|
|
3223
|
+
this.taskQueue.push(callback);
|
|
3224
|
+
this.dequeue(...this.prevArgs);
|
|
3225
|
+
}
|
|
3226
|
+
return this;
|
|
3227
|
+
}
|
|
3228
|
+
/**
|
|
3229
|
+
* Dequeue and execute the next task in queue.
|
|
3230
|
+
*/
|
|
3231
|
+
dequeue(...args) {
|
|
3232
|
+
if (!this.busy && !this.destroyed) {
|
|
3233
|
+
this.busy = 1;
|
|
3234
|
+
setTimeout(() => {
|
|
3235
|
+
this.busy = 0;
|
|
3236
|
+
if (!this.destroyed) {
|
|
3237
|
+
const task2 = this.taskQueue.shift();
|
|
3238
|
+
if (task2) {
|
|
3239
|
+
this.prevArgs = args;
|
|
3240
|
+
funcWithTry(task2, args, this, noop);
|
|
2834
3241
|
}
|
|
2835
|
-
return cached;
|
|
2836
3242
|
}
|
|
3243
|
+
}, 0);
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
/**
|
|
3247
|
+
* Destroy the service instance.
|
|
3248
|
+
* After destruction, no new requests can be sent.
|
|
3249
|
+
*/
|
|
3250
|
+
destroy() {
|
|
3251
|
+
this.destroyed = 1;
|
|
3252
|
+
this.taskQueue = [];
|
|
3253
|
+
}
|
|
3254
|
+
// Instance event methods (delegate to instance emitter)
|
|
3255
|
+
on(event, handler) {
|
|
3256
|
+
this._emitter.on(event, handler);
|
|
3257
|
+
return this;
|
|
3258
|
+
}
|
|
3259
|
+
off(event, handler) {
|
|
3260
|
+
this._emitter.off(event, handler);
|
|
3261
|
+
return this;
|
|
3262
|
+
}
|
|
3263
|
+
fire(event, data) {
|
|
3264
|
+
this._emitter.fire(event, data);
|
|
3265
|
+
return this;
|
|
3266
|
+
}
|
|
3267
|
+
// ============================================================
|
|
3268
|
+
// Per-type static state
|
|
3269
|
+
// ============================================================
|
|
3270
|
+
/** Per-type metadata registry */
|
|
3271
|
+
static _metaList = {};
|
|
3272
|
+
/** Per-type payload cache (LFU with frequency eviction) */
|
|
3273
|
+
static _payloadCache = new Cache({
|
|
3274
|
+
maxSize: 20,
|
|
3275
|
+
bufferSize: 5
|
|
3276
|
+
});
|
|
3277
|
+
/** Per-type pending cache keys for deduplication */
|
|
3278
|
+
static _pendingCacheKeys = {};
|
|
3279
|
+
/** Per-type sync function */
|
|
3280
|
+
static _syncFn = noop;
|
|
3281
|
+
/** Per-type static event emitter */
|
|
3282
|
+
static _staticEmitter = new EventEmitter();
|
|
3283
|
+
/** Per-type cache max size */
|
|
3284
|
+
static _cacheMax = 20;
|
|
3285
|
+
/** Per-type cache buffer size */
|
|
3286
|
+
static _cacheBuffer = 5;
|
|
3287
|
+
// ============================================================
|
|
3288
|
+
// Static methods (operate on per-type state via `this`)
|
|
3289
|
+
// ============================================================
|
|
3290
|
+
/**
|
|
3291
|
+
* Register API endpoint metadata.
|
|
3292
|
+
*/
|
|
3293
|
+
static add(attrs) {
|
|
3294
|
+
if (!Array.isArray(attrs)) {
|
|
3295
|
+
attrs = [attrs];
|
|
3296
|
+
}
|
|
3297
|
+
for (const payload of attrs) {
|
|
3298
|
+
if (payload) {
|
|
3299
|
+
const name = payload.name;
|
|
3300
|
+
const cache = payload.cache;
|
|
3301
|
+
payload.cache = cache ? cache | 0 : 0;
|
|
3302
|
+
this._metaList[name] = payload;
|
|
2837
3303
|
}
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3306
|
+
/**
|
|
3307
|
+
* Get metadata for an API endpoint.
|
|
3308
|
+
*/
|
|
3309
|
+
static meta(attrs) {
|
|
3310
|
+
const name = typeof attrs === "string" ? attrs : String(attrs["name"] ?? "");
|
|
3311
|
+
const known = this._metaList[name];
|
|
3312
|
+
if (known) return known;
|
|
3313
|
+
return attrs;
|
|
3314
|
+
}
|
|
3315
|
+
/**
|
|
3316
|
+
* Create a Payload for an API request.
|
|
3317
|
+
*/
|
|
3318
|
+
static create(attrs) {
|
|
3319
|
+
const meta = this.meta(attrs);
|
|
3320
|
+
const cache = toCacheValue(attrs["cache"]) || meta.cache || 0;
|
|
3321
|
+
const entity = new Payload();
|
|
3322
|
+
entity.set(meta);
|
|
3323
|
+
entity.cacheInfo = {
|
|
3324
|
+
name: meta.name,
|
|
3325
|
+
after: typeof meta.after === "function" ? meta.after : void 0,
|
|
3326
|
+
cleans: typeof meta.cleanKeys === "string" ? meta.cleanKeys : void 0,
|
|
3327
|
+
key: cache ? defaultCacheKey(meta, attrs) : "",
|
|
3328
|
+
time: 0
|
|
3329
|
+
};
|
|
3330
|
+
if (attrs !== null) {
|
|
3331
|
+
entity.set(attrs);
|
|
3332
|
+
}
|
|
3333
|
+
const before = meta.before;
|
|
3334
|
+
if (typeof before === "function") {
|
|
3335
|
+
funcWithTry(before, [entity], entity, noop);
|
|
3336
|
+
}
|
|
3337
|
+
this._staticEmitter.fire("begin", { payload: entity });
|
|
3338
|
+
return entity;
|
|
3339
|
+
}
|
|
3340
|
+
/**
|
|
3341
|
+
* Get or create a Payload for an API request.
|
|
3342
|
+
*/
|
|
3343
|
+
static get(attrs, createNew) {
|
|
3344
|
+
let entity;
|
|
3345
|
+
let needsUpdate = false;
|
|
3346
|
+
if (!createNew) {
|
|
3347
|
+
entity = this.cached(attrs);
|
|
3348
|
+
}
|
|
3349
|
+
if (!entity) {
|
|
3350
|
+
entity = this.create(attrs);
|
|
3351
|
+
needsUpdate = true;
|
|
3352
|
+
}
|
|
3353
|
+
return { entity, needsUpdate };
|
|
3354
|
+
}
|
|
3355
|
+
/**
|
|
3356
|
+
* Get cached Payload if available and not expired.
|
|
3357
|
+
*/
|
|
3358
|
+
static cached(attrs) {
|
|
3359
|
+
const meta = this.meta(attrs);
|
|
3360
|
+
const cache = toCacheValue(attrs["cache"]) || meta.cache || 0;
|
|
3361
|
+
let cacheKey = "";
|
|
3362
|
+
if (cache) {
|
|
3363
|
+
cacheKey = defaultCacheKey(meta, attrs);
|
|
3364
|
+
}
|
|
3365
|
+
if (cacheKey) {
|
|
3366
|
+
const info = this._pendingCacheKeys[cacheKey];
|
|
3367
|
+
if (info) {
|
|
3368
|
+
const entity = info.entity;
|
|
3369
|
+
return entity instanceof Payload ? entity : void 0;
|
|
3370
|
+
}
|
|
3371
|
+
const cached = this._payloadCache.get(cacheKey);
|
|
3372
|
+
if (cached && cached.cacheInfo) {
|
|
3373
|
+
if (now() - cached.cacheInfo.time > cache) {
|
|
3374
|
+
this._payloadCache.del(cacheKey);
|
|
3375
|
+
return void 0;
|
|
2852
3376
|
}
|
|
2853
|
-
|
|
2854
|
-
for (const key of keysToDelete) {
|
|
2855
|
-
bagCache.del(key);
|
|
3377
|
+
return cached;
|
|
2856
3378
|
}
|
|
2857
|
-
},
|
|
2858
|
-
on(event, handler) {
|
|
2859
|
-
staticEmitter2.on(event, handler);
|
|
2860
|
-
},
|
|
2861
|
-
off(event, handler) {
|
|
2862
|
-
staticEmitter2.off(event, handler);
|
|
2863
|
-
},
|
|
2864
|
-
fire(event, data) {
|
|
2865
|
-
staticEmitter2.fire(event, data);
|
|
2866
|
-
},
|
|
2867
|
-
extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
2868
|
-
return createServiceType(
|
|
2869
|
-
newSyncFn,
|
|
2870
|
-
newCacheMax || cacheMax,
|
|
2871
|
-
newCacheBuffer || cacheBuffer
|
|
2872
|
-
);
|
|
2873
3379
|
}
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
this
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
this._emitter = new EventEmitter();
|
|
2889
|
-
this._internals = internals;
|
|
2890
|
-
this._type = serviceType;
|
|
2891
|
-
}
|
|
2892
|
-
ServiceInstance.prototype = {
|
|
2893
|
-
all(attrs, done) {
|
|
2894
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, false);
|
|
2895
|
-
return this;
|
|
2896
|
-
},
|
|
2897
|
-
one(attrs, done) {
|
|
2898
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ONE, false);
|
|
2899
|
-
return this;
|
|
2900
|
-
},
|
|
2901
|
-
save(attrs, done) {
|
|
2902
|
-
serviceSend(this, attrs, done, FETCH_FLAGS_ALL, true);
|
|
2903
|
-
return this;
|
|
2904
|
-
},
|
|
2905
|
-
enqueue(callback) {
|
|
2906
|
-
if (!this["$d"]) {
|
|
2907
|
-
this["$g"].push(callback);
|
|
2908
|
-
this.dequeue(...this["$h"]);
|
|
2909
|
-
}
|
|
2910
|
-
return this;
|
|
2911
|
-
},
|
|
2912
|
-
dequeue(...args) {
|
|
2913
|
-
if (!this["$e"] && !this["$d"]) {
|
|
2914
|
-
this["$e"] = 1;
|
|
2915
|
-
setTimeout(() => {
|
|
2916
|
-
this["$e"] = 0;
|
|
2917
|
-
if (!this["$d"]) {
|
|
2918
|
-
const task2 = this["$g"].shift();
|
|
2919
|
-
if (task2) {
|
|
2920
|
-
this["$h"] = args;
|
|
2921
|
-
funcWithTry(task2, args, this, noop);
|
|
2922
|
-
}
|
|
2923
|
-
}
|
|
2924
|
-
}, 0);
|
|
3380
|
+
return void 0;
|
|
3381
|
+
}
|
|
3382
|
+
/**
|
|
3383
|
+
* Clear cached payloads by endpoint name.
|
|
3384
|
+
*/
|
|
3385
|
+
static clear(names) {
|
|
3386
|
+
const nameSet = new Set(
|
|
3387
|
+
(typeof names === "string" ? names : names.join(",")).split(",")
|
|
3388
|
+
);
|
|
3389
|
+
const keysToDelete = [];
|
|
3390
|
+
this._payloadCache.forEach((payload) => {
|
|
3391
|
+
const info = payload?.cacheInfo;
|
|
3392
|
+
if (info && info.key && nameSet.has(info.name)) {
|
|
3393
|
+
keysToDelete.push(info.key);
|
|
2925
3394
|
}
|
|
2926
|
-
}
|
|
2927
|
-
|
|
2928
|
-
this
|
|
2929
|
-
this["$g"] = [];
|
|
2930
|
-
},
|
|
2931
|
-
on(event, handler) {
|
|
2932
|
-
this._emitter.on(event, handler);
|
|
2933
|
-
return this;
|
|
2934
|
-
},
|
|
2935
|
-
off(event, handler) {
|
|
2936
|
-
this._emitter.off(event, handler);
|
|
2937
|
-
return this;
|
|
2938
|
-
},
|
|
2939
|
-
fire(event, data) {
|
|
2940
|
-
this._emitter.fire(event, data);
|
|
2941
|
-
return this;
|
|
3395
|
+
});
|
|
3396
|
+
for (const key of keysToDelete) {
|
|
3397
|
+
this._payloadCache.del(key);
|
|
2942
3398
|
}
|
|
2943
|
-
}
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
3399
|
+
}
|
|
3400
|
+
// Static event methods (operate on per-type emitter)
|
|
3401
|
+
static on(event, handler) {
|
|
3402
|
+
this._staticEmitter.on(event, handler);
|
|
3403
|
+
}
|
|
3404
|
+
static off(event, handler) {
|
|
3405
|
+
this._staticEmitter.off(event, handler);
|
|
3406
|
+
}
|
|
3407
|
+
static fire(event, data) {
|
|
3408
|
+
this._staticEmitter.fire(event, data);
|
|
3409
|
+
}
|
|
3410
|
+
/**
|
|
3411
|
+
* Create a new Service subclass with a custom sync function.
|
|
3412
|
+
*
|
|
3413
|
+
* Each subclass gets its OWN copies of every per-type static field
|
|
3414
|
+
* (`_metaList`, `_payloadCache`, `_pendingCacheKeys`, `_syncFn`,
|
|
3415
|
+
* `_staticEmitter`, `_cacheMax`, `_cacheBuffer`) via `static override`.
|
|
3416
|
+
* This is intentional: it ensures that endpoint metadata, cache state,
|
|
3417
|
+
* in-flight dedup keys, and event subscribers are fully isolated between
|
|
3418
|
+
* different Service types, even when one extends another.
|
|
3419
|
+
*
|
|
3420
|
+
* **Do not refactor these `static override` declarations away** — sharing
|
|
3421
|
+
* them through prototype inheritance would let endpoints registered on one
|
|
3422
|
+
* subclass leak into another, and the LFU cache evictions of one type
|
|
3423
|
+
* would race with those of another.
|
|
3424
|
+
*/
|
|
3425
|
+
static extend(newSyncFn, newCacheMax, newCacheBuffer) {
|
|
3426
|
+
const ParentService = this;
|
|
3427
|
+
class ChildService extends ParentService {
|
|
3428
|
+
// Intentionally per-subclass — see Service.extend doc.
|
|
3429
|
+
static _metaList = {};
|
|
3430
|
+
static _payloadCache = new Cache({
|
|
3431
|
+
maxSize: newCacheMax || ParentService._cacheMax,
|
|
3432
|
+
bufferSize: newCacheBuffer || ParentService._cacheBuffer
|
|
3433
|
+
});
|
|
3434
|
+
static _pendingCacheKeys = {};
|
|
3435
|
+
static _syncFn = newSyncFn;
|
|
3436
|
+
static _staticEmitter = new EventEmitter();
|
|
3437
|
+
static _cacheMax = newCacheMax || ParentService._cacheMax;
|
|
3438
|
+
static _cacheBuffer = newCacheBuffer || ParentService._cacheBuffer;
|
|
3439
|
+
}
|
|
3440
|
+
return ChildService;
|
|
3441
|
+
}
|
|
3442
|
+
};
|
|
3443
|
+
var metaJsonCache = /* @__PURE__ */ new WeakMap();
|
|
3444
|
+
function getMetaJson(meta) {
|
|
3445
|
+
let cached = metaJsonCache.get(meta);
|
|
3446
|
+
if (cached === void 0) {
|
|
3447
|
+
cached = JSON.stringify(meta);
|
|
3448
|
+
metaJsonCache.set(meta, cached);
|
|
3449
|
+
}
|
|
3450
|
+
return cached;
|
|
2962
3451
|
}
|
|
2963
|
-
var Service = createServiceType(noop);
|
|
2964
3452
|
function defaultCacheKey(meta, attrs) {
|
|
2965
|
-
return JSON.stringify(attrs) + SPLITTER +
|
|
3453
|
+
return JSON.stringify(attrs) + SPLITTER + getMetaJson(meta);
|
|
3454
|
+
}
|
|
3455
|
+
function toCacheValue(v) {
|
|
3456
|
+
if (typeof v === "number") return v | 0;
|
|
3457
|
+
if (typeof v === "string") {
|
|
3458
|
+
const n = Number(v);
|
|
3459
|
+
return Number.isFinite(n) ? n | 0 : 0;
|
|
3460
|
+
}
|
|
3461
|
+
return 0;
|
|
2966
3462
|
}
|
|
2967
3463
|
function serviceSend(service, attrs, done, flag, save) {
|
|
2968
|
-
if (service
|
|
2969
|
-
if (service
|
|
2970
|
-
service
|
|
2971
|
-
|
|
2972
|
-
);
|
|
3464
|
+
if (service.destroyed) return;
|
|
3465
|
+
if (service.busy) {
|
|
3466
|
+
const queued = () => serviceSend(service, attrs, done, flag, save);
|
|
3467
|
+
service.enqueue(queued);
|
|
2973
3468
|
return;
|
|
2974
3469
|
}
|
|
2975
|
-
service
|
|
3470
|
+
service.busy = 1;
|
|
2976
3471
|
let attrList;
|
|
2977
3472
|
if (typeof attrs === "string") {
|
|
2978
3473
|
attrList = [{ name: attrs }];
|
|
2979
|
-
} else if (isArray(attrs)) {
|
|
3474
|
+
} else if (Array.isArray(attrs)) {
|
|
2980
3475
|
attrList = attrs;
|
|
2981
3476
|
} else {
|
|
2982
3477
|
attrList = [attrs];
|
|
2983
3478
|
}
|
|
2984
|
-
const internals = service.
|
|
3479
|
+
const internals = service.internals;
|
|
2985
3480
|
const { syncFn, pendingCacheKeys, staticEmitter: staticEmitter2 } = internals;
|
|
2986
3481
|
let requestCount = 0;
|
|
2987
3482
|
const total = attrList.length;
|
|
2988
3483
|
const doneArr = new Array(total + 1);
|
|
2989
3484
|
const errorArgs = [];
|
|
2990
3485
|
const remoteComplete = (idx, error) => {
|
|
2991
|
-
const
|
|
2992
|
-
let
|
|
3486
|
+
const payload = doneArr[idx + 1];
|
|
3487
|
+
let newPayload = false;
|
|
2993
3488
|
if (error) {
|
|
2994
3489
|
errorArgs[idx] = error;
|
|
2995
|
-
staticEmitter2.fire("fail", {
|
|
3490
|
+
staticEmitter2.fire("fail", { payload, error });
|
|
2996
3491
|
} else {
|
|
2997
|
-
|
|
2998
|
-
staticEmitter2.fire("done", {
|
|
3492
|
+
newPayload = true;
|
|
3493
|
+
staticEmitter2.fire("done", { payload });
|
|
2999
3494
|
}
|
|
3000
|
-
if (!service
|
|
3495
|
+
if (!service.destroyed) {
|
|
3001
3496
|
const finish = requestCount === total;
|
|
3002
3497
|
if (finish) {
|
|
3003
|
-
service
|
|
3498
|
+
service.busy = 0;
|
|
3004
3499
|
if (flag === FETCH_FLAGS_ALL) {
|
|
3005
3500
|
doneArr[0] = errorArgs;
|
|
3006
3501
|
funcWithTry(done, doneArr, service, noop);
|
|
3007
3502
|
}
|
|
3008
3503
|
}
|
|
3009
3504
|
if (flag === FETCH_FLAGS_ONE) {
|
|
3010
|
-
funcWithTry(done, [error || null,
|
|
3505
|
+
funcWithTry(done, [error || null, payload, finish, idx], service, noop);
|
|
3011
3506
|
}
|
|
3012
3507
|
}
|
|
3013
|
-
if (
|
|
3014
|
-
staticEmitter2.fire("end", {
|
|
3508
|
+
if (newPayload) {
|
|
3509
|
+
staticEmitter2.fire("end", { payload, error });
|
|
3015
3510
|
}
|
|
3016
3511
|
};
|
|
3017
3512
|
for (const attr of attrList) {
|
|
3018
3513
|
if (!attr) continue;
|
|
3019
3514
|
const attrObj = typeof attr === "string" ? { name: attr } : attr;
|
|
3020
|
-
const
|
|
3021
|
-
const
|
|
3022
|
-
const cacheKey =
|
|
3515
|
+
const payloadInfo = service.type.get(attrObj, save);
|
|
3516
|
+
const payloadEntity = payloadInfo.entity;
|
|
3517
|
+
const cacheKey = payloadEntity.cacheInfo?.key || "";
|
|
3023
3518
|
const complete = remoteComplete.bind(null, requestCount++);
|
|
3024
3519
|
if (cacheKey && pendingCacheKeys[cacheKey]) {
|
|
3025
3520
|
pendingCacheKeys[cacheKey].push(complete);
|
|
3026
|
-
} else if (
|
|
3521
|
+
} else if (payloadInfo.needsUpdate) {
|
|
3027
3522
|
if (cacheKey) {
|
|
3028
3523
|
const cacheList = [complete];
|
|
3029
|
-
cacheList.
|
|
3524
|
+
cacheList.entity = payloadEntity;
|
|
3030
3525
|
pendingCacheKeys[cacheKey] = cacheList;
|
|
3031
3526
|
const cacheComplete = () => {
|
|
3032
3527
|
const list = pendingCacheKeys[cacheKey];
|
|
3033
|
-
const entity = list.
|
|
3034
|
-
if (entity.cacheInfo) {
|
|
3528
|
+
const entity = list.entity;
|
|
3529
|
+
if (entity instanceof Payload && entity.cacheInfo) {
|
|
3035
3530
|
entity.cacheInfo.time = now();
|
|
3531
|
+
internals.payloadCache.set(cacheKey, entity);
|
|
3036
3532
|
}
|
|
3037
|
-
internals.bagCache.set(cacheKey, entity);
|
|
3038
3533
|
Reflect.deleteProperty(pendingCacheKeys, cacheKey);
|
|
3039
3534
|
for (const cb of list) {
|
|
3040
|
-
if (typeof cb === "function")
|
|
3041
|
-
cb();
|
|
3042
|
-
}
|
|
3535
|
+
if (typeof cb === "function") cb();
|
|
3043
3536
|
}
|
|
3044
3537
|
};
|
|
3045
|
-
syncFn(
|
|
3538
|
+
syncFn(payloadEntity, cacheComplete);
|
|
3046
3539
|
} else {
|
|
3047
|
-
syncFn(
|
|
3540
|
+
syncFn(payloadEntity, complete);
|
|
3048
3541
|
}
|
|
3049
3542
|
} else {
|
|
3050
3543
|
complete();
|
|
@@ -3052,12 +3545,14 @@ function serviceSend(service, attrs, done, flag, save) {
|
|
|
3052
3545
|
}
|
|
3053
3546
|
}
|
|
3054
3547
|
|
|
3055
|
-
// src/frame-
|
|
3056
|
-
var
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3548
|
+
// src/frame-visual.ts
|
|
3549
|
+
var FrameVisualBridge = {
|
|
3550
|
+
MSG_PING: "LARK_VIS_PING",
|
|
3551
|
+
MSG_PONG: "LARK_VIS_PONG",
|
|
3552
|
+
MSG_REQUEST_TREE: "LARK_VIS_REQUEST_TREE",
|
|
3553
|
+
MSG_TREE: "LARK_VIS_TREE",
|
|
3554
|
+
MSG_TREE_DELTA: "LARK_VIS_TREE_DELTA"
|
|
3555
|
+
};
|
|
3061
3556
|
function serializeView(view) {
|
|
3062
3557
|
return {
|
|
3063
3558
|
id: view.id,
|
|
@@ -3097,7 +3592,10 @@ function serializeFrame(frameId) {
|
|
|
3097
3592
|
};
|
|
3098
3593
|
}
|
|
3099
3594
|
function serializeFrameTree() {
|
|
3100
|
-
const root = Frame.
|
|
3595
|
+
const root = Frame.getRoot();
|
|
3596
|
+
if (!root) {
|
|
3597
|
+
return { root: null, totalFrames: 0, timestamp: Date.now(), rootId: "" };
|
|
3598
|
+
}
|
|
3101
3599
|
const rootNode = serializeFrame(root.id);
|
|
3102
3600
|
let totalFrames = 0;
|
|
3103
3601
|
const countFrames = (node) => {
|
|
@@ -3125,19 +3623,22 @@ function installFrameVisualizerBridge() {
|
|
|
3125
3623
|
const data = event.data;
|
|
3126
3624
|
if (!data || typeof data !== "object") return;
|
|
3127
3625
|
const type = data.type;
|
|
3128
|
-
if (type === MSG_PING) {
|
|
3626
|
+
if (type === FrameVisualBridge.MSG_PING) {
|
|
3129
3627
|
const source = event.source;
|
|
3130
3628
|
if (source) {
|
|
3131
|
-
source.postMessage(
|
|
3629
|
+
source.postMessage(
|
|
3630
|
+
{ type: FrameVisualBridge.MSG_PONG },
|
|
3631
|
+
{ targetOrigin: "*" }
|
|
3632
|
+
);
|
|
3132
3633
|
}
|
|
3133
3634
|
return;
|
|
3134
3635
|
}
|
|
3135
|
-
if (type === MSG_REQUEST_TREE) {
|
|
3636
|
+
if (type === FrameVisualBridge.MSG_REQUEST_TREE) {
|
|
3136
3637
|
const tree = serializeFrameTree();
|
|
3137
3638
|
const source = event.source;
|
|
3138
3639
|
if (source) {
|
|
3139
3640
|
source.postMessage(
|
|
3140
|
-
{ type: MSG_TREE, data: tree },
|
|
3641
|
+
{ type: FrameVisualBridge.MSG_TREE, data: tree },
|
|
3141
3642
|
{ targetOrigin: "*" }
|
|
3142
3643
|
);
|
|
3143
3644
|
}
|
|
@@ -3156,18 +3657,14 @@ function pushTreeUpdate() {
|
|
|
3156
3657
|
const treeJson = JSON.stringify(tree);
|
|
3157
3658
|
if (treeJson !== lastTreeJson) {
|
|
3158
3659
|
lastTreeJson = treeJson;
|
|
3159
|
-
window.parent.postMessage(
|
|
3660
|
+
window.parent.postMessage(
|
|
3661
|
+
{ type: FrameVisualBridge.MSG_TREE_DELTA, data: tree },
|
|
3662
|
+
"*"
|
|
3663
|
+
);
|
|
3160
3664
|
}
|
|
3161
3665
|
}
|
|
3162
3666
|
|
|
3163
3667
|
// src/framework.ts
|
|
3164
|
-
var config = {
|
|
3165
|
-
rootId: "lark-root",
|
|
3166
|
-
hashbang: "#!",
|
|
3167
|
-
error: (error) => {
|
|
3168
|
-
throw error;
|
|
3169
|
-
}
|
|
3170
|
-
};
|
|
3171
3668
|
var booted3 = false;
|
|
3172
3669
|
var taskList = [];
|
|
3173
3670
|
var taskIndex = 0;
|
|
@@ -3216,6 +3713,9 @@ function task(fn, args, context) {
|
|
|
3216
3713
|
}
|
|
3217
3714
|
}
|
|
3218
3715
|
var dispatcherUpdateTag = 0;
|
|
3716
|
+
function isThenable(value) {
|
|
3717
|
+
return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
3718
|
+
}
|
|
3219
3719
|
function viewIsObserveChanged(view) {
|
|
3220
3720
|
const loc = view.locationObserved;
|
|
3221
3721
|
let result = false;
|
|
@@ -3229,7 +3729,7 @@ function viewIsObserveChanged(view) {
|
|
|
3229
3729
|
const changedParams = lastChanged2?.params;
|
|
3230
3730
|
if (changedParams) {
|
|
3231
3731
|
for (const key of loc.keys) {
|
|
3232
|
-
result =
|
|
3732
|
+
result = hasOwnProperty(changedParams, key);
|
|
3233
3733
|
if (result) break;
|
|
3234
3734
|
}
|
|
3235
3735
|
}
|
|
@@ -3241,49 +3741,65 @@ function stateIsObserveChanged(view, stateKeys) {
|
|
|
3241
3741
|
const observedKeys = view.observedStateKeys;
|
|
3242
3742
|
if (!observedKeys) return false;
|
|
3243
3743
|
for (const key of observedKeys) {
|
|
3244
|
-
if (has(
|
|
3744
|
+
if (stateKeys.has(key)) return true;
|
|
3245
3745
|
}
|
|
3246
3746
|
return false;
|
|
3247
3747
|
}
|
|
3248
3748
|
function dispatcherUpdate(frame, stateKeys) {
|
|
3249
|
-
const
|
|
3250
|
-
const
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
renderPromise
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3749
|
+
const stack = [frame];
|
|
3750
|
+
const drain = (s) => {
|
|
3751
|
+
while (s.length > 0) {
|
|
3752
|
+
const current = s.pop();
|
|
3753
|
+
const tagged = current;
|
|
3754
|
+
const view = current.view;
|
|
3755
|
+
if (!view || tagged.dispatcherUpdateTag === dispatcherUpdateTag || view.signature <= 1) {
|
|
3756
|
+
continue;
|
|
3757
|
+
}
|
|
3758
|
+
tagged.dispatcherUpdateTag = dispatcherUpdateTag;
|
|
3759
|
+
const isChanged = stateKeys ? stateIsObserveChanged(view, stateKeys) : viewIsObserveChanged(view);
|
|
3760
|
+
let renderPromise;
|
|
3761
|
+
if (isChanged) {
|
|
3762
|
+
const renderResult = funcWithTry(
|
|
3763
|
+
view.renderMethod ?? view.render,
|
|
3764
|
+
[],
|
|
3765
|
+
view,
|
|
3766
|
+
noop
|
|
3767
|
+
);
|
|
3768
|
+
if (isThenable(renderResult)) {
|
|
3769
|
+
renderPromise = renderResult;
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
const children = current.children();
|
|
3773
|
+
if (renderPromise) {
|
|
3774
|
+
renderPromise.then(() => {
|
|
3775
|
+
const subStack = [];
|
|
3776
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
3777
|
+
const child = Frame.get(children[i]);
|
|
3778
|
+
if (child) subStack.push(child);
|
|
3779
|
+
}
|
|
3780
|
+
drain(subStack);
|
|
3781
|
+
});
|
|
3782
|
+
} else {
|
|
3783
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
3784
|
+
const child = Frame.get(children[i]);
|
|
3785
|
+
if (child) s.push(child);
|
|
3786
|
+
}
|
|
3269
3787
|
}
|
|
3270
3788
|
}
|
|
3271
3789
|
};
|
|
3272
|
-
|
|
3273
|
-
renderPromise.then(recurse);
|
|
3274
|
-
} else {
|
|
3275
|
-
recurse();
|
|
3276
|
-
}
|
|
3790
|
+
drain(stack);
|
|
3277
3791
|
}
|
|
3278
3792
|
function dispatcherNotifyChange(e) {
|
|
3279
|
-
const rootFrame2 = Frame.
|
|
3280
|
-
|
|
3793
|
+
const rootFrame2 = Frame.getRoot();
|
|
3794
|
+
if (!rootFrame2) return;
|
|
3795
|
+
const routeEvent = e;
|
|
3796
|
+
const view = routeEvent.view;
|
|
3281
3797
|
if (view) {
|
|
3282
3798
|
const viewPath = typeof view === "object" && view !== null ? String(view.to || "") : String(view);
|
|
3283
3799
|
rootFrame2.mountView(viewPath);
|
|
3284
3800
|
} else {
|
|
3285
3801
|
dispatcherUpdateTag++;
|
|
3286
|
-
dispatcherUpdate(rootFrame2, e
|
|
3802
|
+
dispatcherUpdate(rootFrame2, e.keys);
|
|
3287
3803
|
}
|
|
3288
3804
|
}
|
|
3289
3805
|
function dispatchEvent(target, eventType, eventInit) {
|
|
@@ -3294,23 +3810,8 @@ function dispatchEvent(target, eventType, eventInit) {
|
|
|
3294
3810
|
});
|
|
3295
3811
|
target.dispatchEvent(event);
|
|
3296
3812
|
}
|
|
3297
|
-
var Base = class extends EventEmitter {
|
|
3298
|
-
};
|
|
3299
|
-
function use(names, callback) {
|
|
3300
|
-
if (!config.require) {
|
|
3301
|
-
if (callback) callback();
|
|
3302
|
-
return;
|
|
3303
|
-
}
|
|
3304
|
-
const nameList = typeof names === "string" ? [names] : names;
|
|
3305
|
-
const result = config.require(nameList);
|
|
3306
|
-
if (result && typeof result.then === "function") {
|
|
3307
|
-
result.then((modules) => {
|
|
3308
|
-
if (callback) callback(modules);
|
|
3309
|
-
});
|
|
3310
|
-
}
|
|
3311
|
-
}
|
|
3312
3813
|
var WAIT_OK = 1;
|
|
3313
|
-
var
|
|
3814
|
+
var WAIT_TIMEOUT_OR_NOT_FOUND = 0;
|
|
3314
3815
|
function waitZoneViewsRendered(viewId, timeout) {
|
|
3315
3816
|
if (timeout == null) {
|
|
3316
3817
|
timeout = 30 * 1e3;
|
|
@@ -3321,7 +3822,7 @@ function waitZoneViewsRendered(viewId, timeout) {
|
|
|
3321
3822
|
const check = () => {
|
|
3322
3823
|
const currentTime = now();
|
|
3323
3824
|
if (currentTime > endTime || !checkFrame) {
|
|
3324
|
-
resolve(
|
|
3825
|
+
resolve(WAIT_TIMEOUT_OR_NOT_FOUND);
|
|
3325
3826
|
} else if (checkFrame.childrenCount === checkFrame.readyCount) {
|
|
3326
3827
|
resolve(WAIT_OK);
|
|
3327
3828
|
} else {
|
|
@@ -3331,12 +3832,27 @@ function waitZoneViewsRendered(viewId, timeout) {
|
|
|
3331
3832
|
setTimeout(check, 9);
|
|
3332
3833
|
});
|
|
3333
3834
|
}
|
|
3835
|
+
function getConfigImpl(key) {
|
|
3836
|
+
if (key === void 0) return config;
|
|
3837
|
+
return config[key];
|
|
3838
|
+
}
|
|
3334
3839
|
var Framework = {
|
|
3335
3840
|
// ============================================================
|
|
3336
3841
|
// Lifecycle
|
|
3337
3842
|
// ============================================================
|
|
3843
|
+
/** Read framework configuration. See `FrameworkInterface.getConfig`. */
|
|
3844
|
+
getConfig: getConfigImpl,
|
|
3845
|
+
/**
|
|
3846
|
+
* Merge a patch into framework configuration. See `FrameworkInterface.setConfig`.
|
|
3847
|
+
*/
|
|
3848
|
+
setConfig(patch) {
|
|
3849
|
+
if (patch && typeof patch === "object") {
|
|
3850
|
+
assign(config, patch);
|
|
3851
|
+
}
|
|
3852
|
+
return config;
|
|
3853
|
+
},
|
|
3338
3854
|
/**
|
|
3339
|
-
*
|
|
3855
|
+
* @deprecated Use `getConfig()` / `setConfig()`. Behavior unchanged.
|
|
3340
3856
|
*/
|
|
3341
3857
|
config(cfg) {
|
|
3342
3858
|
if (!cfg) {
|
|
@@ -3357,17 +3873,17 @@ var Framework = {
|
|
|
3357
3873
|
}
|
|
3358
3874
|
Router._setConfig(config);
|
|
3359
3875
|
EventDelegator.setFrameGetter((id) => Frame.get(id));
|
|
3360
|
-
Router.on(
|
|
3361
|
-
dispatcherNotifyChange(data);
|
|
3876
|
+
Router.on(RouterEvents.CHANGED, (data) => {
|
|
3877
|
+
if (data) dispatcherNotifyChange(data);
|
|
3362
3878
|
});
|
|
3363
|
-
State.on(
|
|
3364
|
-
dispatcherNotifyChange(data);
|
|
3879
|
+
State.on(RouterEvents.CHANGED, (data) => {
|
|
3880
|
+
if (data) dispatcherNotifyChange(data);
|
|
3365
3881
|
});
|
|
3366
3882
|
booted3 = true;
|
|
3367
3883
|
markBooted();
|
|
3368
3884
|
markRouterBooted();
|
|
3369
3885
|
installFrameVisualizerBridge();
|
|
3370
|
-
const rootFrame2 = Frame.
|
|
3886
|
+
const rootFrame2 = Frame.createRoot(config.rootId);
|
|
3371
3887
|
Router._bind();
|
|
3372
3888
|
const defaultView = config.defaultView || "";
|
|
3373
3889
|
if (defaultView && !rootFrame2.view) {
|
|
@@ -3398,7 +3914,7 @@ var Framework = {
|
|
|
3398
3914
|
/** Wait for zone views to be rendered */
|
|
3399
3915
|
waitZoneViewsRendered,
|
|
3400
3916
|
WAIT_OK,
|
|
3401
|
-
|
|
3917
|
+
WAIT_TIMEOUT_OR_NOT_FOUND,
|
|
3402
3918
|
/**
|
|
3403
3919
|
* Convert array to hash map.
|
|
3404
3920
|
*/
|
|
@@ -3422,7 +3938,7 @@ var Framework = {
|
|
|
3422
3938
|
/**
|
|
3423
3939
|
* Check if object has own property.
|
|
3424
3940
|
*/
|
|
3425
|
-
has,
|
|
3941
|
+
has: hasOwnProperty,
|
|
3426
3942
|
/**
|
|
3427
3943
|
* Get object keys.
|
|
3428
3944
|
*/
|
|
@@ -3463,7 +3979,7 @@ var Framework = {
|
|
|
3463
3979
|
/**
|
|
3464
3980
|
* Base class with EventEmitter.
|
|
3465
3981
|
*/
|
|
3466
|
-
Base,
|
|
3982
|
+
Base: EventEmitter,
|
|
3467
3983
|
// ============================================================
|
|
3468
3984
|
// Module access
|
|
3469
3985
|
// ============================================================
|
|
@@ -3481,10 +3997,14 @@ if (typeof window !== "undefined") {
|
|
|
3481
3997
|
window.__lark_State = State;
|
|
3482
3998
|
window.__lark_Router = Router;
|
|
3483
3999
|
window.__lark_Frame = Frame;
|
|
4000
|
+
window.__lark_View = View;
|
|
4001
|
+
window.__lark_invalidateViewClass = invalidateViewClass;
|
|
4002
|
+
window.__lark_getViewClassRegistry = getViewClassRegistry;
|
|
4003
|
+
window.__lark_registerViewClass = registerViewClass;
|
|
3484
4004
|
}
|
|
3485
4005
|
|
|
3486
4006
|
// src/store.ts
|
|
3487
|
-
var LARK_GLOBAL = "
|
|
4007
|
+
var LARK_GLOBAL = "lark-global";
|
|
3488
4008
|
var Platform = /* @__PURE__ */ ((Platform2) => {
|
|
3489
4009
|
Platform2["Lark"] = "lark";
|
|
3490
4010
|
Platform2["React"] = "react";
|
|
@@ -3494,28 +4014,38 @@ var Platform = /* @__PURE__ */ ((Platform2) => {
|
|
|
3494
4014
|
var isFunction = (val) => typeof val === "function";
|
|
3495
4015
|
var isObject = (val) => val !== null && typeof val === "object";
|
|
3496
4016
|
var isPromise = (val) => isObject(val) && isFunction(val["then"]);
|
|
3497
|
-
var
|
|
3498
|
-
var
|
|
4017
|
+
var hasOwnProperty2 = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
|
|
4018
|
+
var hasStructuredClone = typeof globalThis !== "undefined" && typeof globalThis.structuredClone === "function";
|
|
4019
|
+
var deepCloneFallback = (obj) => {
|
|
3499
4020
|
if (!obj || !isObject(obj)) return {};
|
|
3500
|
-
const newData = Array.isArray(obj) ? [] :
|
|
4021
|
+
const newData = Array.isArray(obj) ? [] : {};
|
|
3501
4022
|
for (const key in obj) {
|
|
3502
|
-
if (
|
|
4023
|
+
if (hasOwnProperty2(obj, key)) {
|
|
3503
4024
|
const value = obj[key];
|
|
3504
|
-
newData[key] = isObject(value) ?
|
|
4025
|
+
newData[key] = isObject(value) ? deepCloneFallback(value) : value;
|
|
3505
4026
|
}
|
|
3506
4027
|
}
|
|
3507
4028
|
return newData;
|
|
3508
4029
|
};
|
|
4030
|
+
var deepClone = (obj) => {
|
|
4031
|
+
if (hasStructuredClone) {
|
|
4032
|
+
try {
|
|
4033
|
+
return structuredClone(obj);
|
|
4034
|
+
} catch {
|
|
4035
|
+
return deepCloneFallback(obj);
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
return deepCloneFallback(obj);
|
|
4039
|
+
};
|
|
3509
4040
|
var cloneData = (data) => isObject(data) ? deepClone(data) : data;
|
|
3510
4041
|
var getDataByKey = (target, key) => {
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
data = rec?.[key];
|
|
4042
|
+
if (!key.includes(".")) {
|
|
4043
|
+
return target[key];
|
|
4044
|
+
}
|
|
4045
|
+
let data = target;
|
|
4046
|
+
for (const k of key.split(".")) {
|
|
4047
|
+
if (!isObject(data)) return void 0;
|
|
4048
|
+
data = data[k];
|
|
3519
4049
|
}
|
|
3520
4050
|
return data;
|
|
3521
4051
|
};
|
|
@@ -3527,8 +4057,10 @@ var Queue = class {
|
|
|
3527
4057
|
const flushTickTask = () => {
|
|
3528
4058
|
while (queue.length > 0) {
|
|
3529
4059
|
const task2 = queue.shift();
|
|
3530
|
-
|
|
3531
|
-
|
|
4060
|
+
if (task2) {
|
|
4061
|
+
pendingTasks.delete(task2);
|
|
4062
|
+
runTask(task2);
|
|
4063
|
+
}
|
|
3532
4064
|
}
|
|
3533
4065
|
};
|
|
3534
4066
|
Promise.resolve().then(flushTickTask);
|
|
@@ -3561,17 +4093,18 @@ var Queue = class {
|
|
|
3561
4093
|
};
|
|
3562
4094
|
var addParams2Callback = (cb, params) => {
|
|
3563
4095
|
if (!cb || !params) return;
|
|
3564
|
-
const
|
|
3565
|
-
|
|
3566
|
-
|
|
4096
|
+
const tagged = cb;
|
|
4097
|
+
const existing = tagged.params;
|
|
4098
|
+
if (isObject(existing)) {
|
|
4099
|
+
Object.assign(existing, params);
|
|
3567
4100
|
} else {
|
|
3568
|
-
|
|
4101
|
+
tagged.params = params;
|
|
3569
4102
|
}
|
|
3570
4103
|
};
|
|
3571
4104
|
var runTask = (cb) => {
|
|
3572
|
-
const
|
|
3573
|
-
const params =
|
|
3574
|
-
delete
|
|
4105
|
+
const tagged = cb;
|
|
4106
|
+
const params = tagged.params;
|
|
4107
|
+
delete tagged.params;
|
|
3575
4108
|
try {
|
|
3576
4109
|
cb(params);
|
|
3577
4110
|
} catch {
|
|
@@ -3597,7 +4130,9 @@ var ArrMethods = {};
|
|
|
3597
4130
|
if (res === -1 || res === false) {
|
|
3598
4131
|
res = rawMethod.apply(
|
|
3599
4132
|
this,
|
|
3600
|
-
args.map(
|
|
4133
|
+
args.map(
|
|
4134
|
+
(item) => isObject(item) ? ProxyCache.get(item) ?? item : item
|
|
4135
|
+
)
|
|
3601
4136
|
);
|
|
3602
4137
|
}
|
|
3603
4138
|
return res;
|
|
@@ -3615,6 +4150,7 @@ var inArrUpdate = false;
|
|
|
3615
4150
|
});
|
|
3616
4151
|
function needKeepArrItem(target, newVal, key) {
|
|
3617
4152
|
if (!Array.isArray(target) || !inArrUpdate) return false;
|
|
4153
|
+
if (!isObject(newVal)) return false;
|
|
3618
4154
|
return getLinkKeys(newVal) === createLinkKeys(target, key);
|
|
3619
4155
|
}
|
|
3620
4156
|
var defStateConfig = {
|
|
@@ -3626,11 +4162,13 @@ var StateConfigMap = /* @__PURE__ */ new WeakMap();
|
|
|
3626
4162
|
var setStateConfig = (target, config2) => {
|
|
3627
4163
|
if (target && isObject(config2)) StateConfigMap.set(target, config2);
|
|
3628
4164
|
};
|
|
3629
|
-
|
|
3630
|
-
if (!StateConfigMap.has(target))
|
|
4165
|
+
function getStateConfig(target, key) {
|
|
4166
|
+
if (!StateConfigMap.has(target)) {
|
|
4167
|
+
return void 0;
|
|
4168
|
+
}
|
|
3631
4169
|
const config2 = StateConfigMap.get(target);
|
|
3632
|
-
return key ? config2[key] : config2;
|
|
3633
|
-
}
|
|
4170
|
+
return key ? config2?.[key] : config2;
|
|
4171
|
+
}
|
|
3634
4172
|
var isState = (target) => isObject(target) && StateConfigMap.has(target);
|
|
3635
4173
|
var createLinkKeys = (target, property) => {
|
|
3636
4174
|
if (!hasLinkKeys(target)) return property;
|
|
@@ -3668,7 +4206,7 @@ var needKeep = (key) => {
|
|
|
3668
4206
|
};
|
|
3669
4207
|
var canSetNewVal = (params) => {
|
|
3670
4208
|
const { property, newVal, oldVal } = params;
|
|
3671
|
-
if (
|
|
4209
|
+
if (hasOwnProperty2(params.target, property) && newVal === oldVal)
|
|
3672
4210
|
return false;
|
|
3673
4211
|
return true;
|
|
3674
4212
|
};
|
|
@@ -3680,16 +4218,13 @@ var getNewVal = (params) => {
|
|
|
3680
4218
|
if (config2?.shallow) return newVal;
|
|
3681
4219
|
if (needKeepVal) return newVal;
|
|
3682
4220
|
const linkKeys = createLinkKeys(target, property);
|
|
3683
|
-
const newState = createState(newVal, {
|
|
3684
|
-
...config2,
|
|
3685
|
-
linkKeys
|
|
3686
|
-
});
|
|
4221
|
+
const newState = createState(newVal, { ...config2, linkKeys });
|
|
3687
4222
|
if (isPromise(newVal)) handlePromise(newVal, target, property);
|
|
3688
4223
|
return newState;
|
|
3689
4224
|
};
|
|
3690
4225
|
var genPayload = (params) => {
|
|
3691
4226
|
const { target, property, newVal, oldVal } = params;
|
|
3692
|
-
const config2 = getStateConfig(target)
|
|
4227
|
+
const config2 = getStateConfig(target) ?? defStateConfig;
|
|
3693
4228
|
return {
|
|
3694
4229
|
belong: config2.belong || LARK_GLOBAL,
|
|
3695
4230
|
target,
|
|
@@ -3699,11 +4234,12 @@ var genPayload = (params) => {
|
|
|
3699
4234
|
};
|
|
3700
4235
|
};
|
|
3701
4236
|
var handlePromise = (child, parent, key) => {
|
|
4237
|
+
const childObj = child;
|
|
3702
4238
|
child.then((res) => {
|
|
3703
4239
|
const parentProxy = ProxyCache.get(parent);
|
|
3704
4240
|
if (parentProxy) {
|
|
3705
4241
|
const oldVal = parentProxy[key];
|
|
3706
|
-
if (ProxyCache.get(
|
|
4242
|
+
if (ProxyCache.get(childObj) === oldVal) {
|
|
3707
4243
|
parentProxy[key] = res;
|
|
3708
4244
|
}
|
|
3709
4245
|
}
|
|
@@ -3711,7 +4247,7 @@ var handlePromise = (child, parent, key) => {
|
|
|
3711
4247
|
const parentProxy = ProxyCache.get(parent);
|
|
3712
4248
|
if (parentProxy) {
|
|
3713
4249
|
const oldVal = parentProxy[key];
|
|
3714
|
-
if (ProxyCache.get(
|
|
4250
|
+
if (ProxyCache.get(childObj) === oldVal) {
|
|
3715
4251
|
parentProxy[key] = err;
|
|
3716
4252
|
}
|
|
3717
4253
|
}
|
|
@@ -3723,7 +4259,7 @@ var mark2 = (host, key) => {
|
|
|
3723
4259
|
let sign;
|
|
3724
4260
|
if (!host[_deleteKey]) {
|
|
3725
4261
|
const markHost = host[_markObjKey] || (host[_markObjKey] = {});
|
|
3726
|
-
if (!
|
|
4262
|
+
if (!hasOwnProperty2(markHost, key)) {
|
|
3727
4263
|
markHost[key] = 0;
|
|
3728
4264
|
}
|
|
3729
4265
|
sign = ++markHost[key];
|
|
@@ -3760,7 +4296,7 @@ function createState(initialData, config2) {
|
|
|
3760
4296
|
oldVal
|
|
3761
4297
|
});
|
|
3762
4298
|
if (!canSet) return true;
|
|
3763
|
-
const proxyTarget = receiver
|
|
4299
|
+
const proxyTarget = isObject(receiver) && receiver !== null ? receiver : state;
|
|
3764
4300
|
newVal = getNewVal({
|
|
3765
4301
|
target: proxyTarget,
|
|
3766
4302
|
property: strProp,
|
|
@@ -3780,7 +4316,7 @@ function createState(initialData, config2) {
|
|
|
3780
4316
|
},
|
|
3781
4317
|
deleteProperty(target, property) {
|
|
3782
4318
|
const strProp = property;
|
|
3783
|
-
if (!
|
|
4319
|
+
if (!hasOwnProperty2(target, strProp)) return true;
|
|
3784
4320
|
const oldVal = Reflect.get(target, property);
|
|
3785
4321
|
Reflect.deleteProperty(target, property);
|
|
3786
4322
|
const payload = genPayload({
|
|
@@ -3824,11 +4360,8 @@ function shallowSet(target, key, data) {
|
|
|
3824
4360
|
keep(key);
|
|
3825
4361
|
const config2 = getStateConfig(target);
|
|
3826
4362
|
const linkKeys = createLinkKeys(target, key);
|
|
3827
|
-
target[key] = createState(data, {
|
|
3828
|
-
|
|
3829
|
-
linkKeys,
|
|
3830
|
-
shallow: true
|
|
3831
|
-
});
|
|
4363
|
+
target[key] = createState(data, { ...config2, linkKeys, shallow: true });
|
|
4364
|
+
return target[key];
|
|
3832
4365
|
}
|
|
3833
4366
|
var GlobalDeps = /* @__PURE__ */ new Map();
|
|
3834
4367
|
function track(payload) {
|
|
@@ -3909,8 +4442,22 @@ var _stateKeys = /* @__PURE__ */ Symbol("state-keys");
|
|
|
3909
4442
|
var _storeState = /* @__PURE__ */ Symbol("store-state");
|
|
3910
4443
|
var _storeDefScheduler = /* @__PURE__ */ Symbol("store-def-scheduler");
|
|
3911
4444
|
var _storeProxy = /* @__PURE__ */ Symbol("fn:store-proxy");
|
|
4445
|
+
var _computedKeys = /* @__PURE__ */ Symbol("store-computed-keys");
|
|
4446
|
+
var COMPUTED_BRAND = /* @__PURE__ */ Symbol("store-computed-brand");
|
|
4447
|
+
function computed(deps, fn) {
|
|
4448
|
+
const marker = {
|
|
4449
|
+
[COMPUTED_BRAND]: true,
|
|
4450
|
+
deps,
|
|
4451
|
+
fn
|
|
4452
|
+
};
|
|
4453
|
+
return marker;
|
|
4454
|
+
}
|
|
4455
|
+
function isComputedMarker(val) {
|
|
4456
|
+
return isObject(val) && val[COMPUTED_BRAND] === true;
|
|
4457
|
+
}
|
|
3912
4458
|
var BaseStore = class {
|
|
3913
4459
|
[_storeStatus] = 0 /* BEFORE_CREATE */;
|
|
4460
|
+
[_computedKeys] = /* @__PURE__ */ new Set();
|
|
3914
4461
|
[_storeDefScheduler] = getDefScheduler;
|
|
3915
4462
|
[_storeBoot]() {
|
|
3916
4463
|
this[_storeStatus] = 2 /* ACTIVE */;
|
|
@@ -3933,10 +4480,16 @@ var BaseStore = class {
|
|
|
3933
4480
|
if (isObject(body)) {
|
|
3934
4481
|
const state = {};
|
|
3935
4482
|
const handlers = {};
|
|
4483
|
+
const computedDefs = {};
|
|
4484
|
+
const computedKeys = this[_computedKeys];
|
|
3936
4485
|
Reflect.ownKeys(body).forEach((key) => {
|
|
3937
4486
|
const strKey = key;
|
|
3938
4487
|
const val = body[strKey];
|
|
3939
|
-
if (
|
|
4488
|
+
if (isComputedMarker(val)) {
|
|
4489
|
+
computedDefs[strKey] = val;
|
|
4490
|
+
state[strKey] = void 0;
|
|
4491
|
+
computedKeys.add(strKey);
|
|
4492
|
+
} else if (isFunction(val)) {
|
|
3940
4493
|
if (!excludeFns.includes(strKey)) handlers[strKey] = val;
|
|
3941
4494
|
} else {
|
|
3942
4495
|
state[strKey] = val;
|
|
@@ -3946,6 +4499,22 @@ var BaseStore = class {
|
|
|
3946
4499
|
this[_originState] = cloneData(state);
|
|
3947
4500
|
this[_stateKeys] = Object.keys(state);
|
|
3948
4501
|
this[_storeState] = createState(state, { belong: this[_storeName] });
|
|
4502
|
+
if (Object.keys(computedDefs).length > 0) {
|
|
4503
|
+
const belong = this[_storeName];
|
|
4504
|
+
const storeState = this[_storeState];
|
|
4505
|
+
for (const key of Object.keys(computedDefs)) {
|
|
4506
|
+
const def = computedDefs[key];
|
|
4507
|
+
const recompute = () => {
|
|
4508
|
+
storeState[key] = def.fn();
|
|
4509
|
+
};
|
|
4510
|
+
recompute();
|
|
4511
|
+
const trackList = def.deps.map((depKey) => ({
|
|
4512
|
+
key: depKey,
|
|
4513
|
+
cb: recompute
|
|
4514
|
+
}));
|
|
4515
|
+
if (trackList.length > 0) track({ belong, trackList });
|
|
4516
|
+
}
|
|
4517
|
+
}
|
|
3949
4518
|
}
|
|
3950
4519
|
}
|
|
3951
4520
|
constructor(name, config2) {
|
|
@@ -3967,18 +4536,21 @@ var BaseStore = class {
|
|
|
3967
4536
|
}
|
|
3968
4537
|
[_storeProxy](toOut = false) {
|
|
3969
4538
|
const self = this;
|
|
3970
|
-
|
|
4539
|
+
const proxy = new Proxy(self, {
|
|
3971
4540
|
get(target, property) {
|
|
3972
|
-
|
|
3973
|
-
|
|
4541
|
+
const strProp = property;
|
|
4542
|
+
if (self[_stateKeys].includes(strProp)) {
|
|
4543
|
+
const val = self[_storeState][strProp];
|
|
3974
4544
|
return toOut ? cloneData(val) : val;
|
|
3975
4545
|
}
|
|
3976
4546
|
return Reflect.get(target, property);
|
|
3977
4547
|
},
|
|
3978
4548
|
set(_target, property, val) {
|
|
3979
4549
|
if (toOut) return true;
|
|
3980
|
-
|
|
3981
|
-
|
|
4550
|
+
const strProp = property;
|
|
4551
|
+
if (self[_computedKeys].has(strProp)) return true;
|
|
4552
|
+
if (self[_stateKeys].includes(strProp)) {
|
|
4553
|
+
self[_storeState][strProp] = val;
|
|
3982
4554
|
}
|
|
3983
4555
|
return true;
|
|
3984
4556
|
},
|
|
@@ -3986,11 +4558,14 @@ var BaseStore = class {
|
|
|
3986
4558
|
return Reflect.has(target, property) || self[_stateKeys].includes(property);
|
|
3987
4559
|
}
|
|
3988
4560
|
});
|
|
4561
|
+
return proxy;
|
|
3989
4562
|
}
|
|
3990
4563
|
};
|
|
3991
4564
|
var LarkUtils = {
|
|
3992
4565
|
isLarkView(instance) {
|
|
3993
|
-
|
|
4566
|
+
if (!isObject(instance)) return false;
|
|
4567
|
+
const updater = instance["updater"];
|
|
4568
|
+
return isObject(updater) && isFunction(updater["set"]) && isFunction(updater["digest"]);
|
|
3994
4569
|
},
|
|
3995
4570
|
getRender(view) {
|
|
3996
4571
|
return view.updater.digest.bind(view.updater);
|
|
@@ -4006,41 +4581,45 @@ var getLarkAdapter = (storeName) => ({
|
|
|
4006
4581
|
Store: LarkStore,
|
|
4007
4582
|
useStore: ((view) => {
|
|
4008
4583
|
const store = getStore(storeName);
|
|
4584
|
+
if (!(store instanceof LarkStore)) return {};
|
|
4009
4585
|
return store[_storeBoot](view);
|
|
4010
4586
|
})
|
|
4011
4587
|
});
|
|
4012
|
-
var
|
|
4013
|
-
var
|
|
4588
|
+
var _innerObserveFlags = /* @__PURE__ */ Symbol("store-inner-observe-flags");
|
|
4589
|
+
var _boundViews = /* @__PURE__ */ Symbol("store-bound-views");
|
|
4014
4590
|
var LarkStore = class extends BaseStore {
|
|
4015
|
-
[
|
|
4016
|
-
[
|
|
4591
|
+
[_boundViews] = /* @__PURE__ */ new Set();
|
|
4592
|
+
[_innerObserveFlags] = /* @__PURE__ */ new Set();
|
|
4017
4593
|
[_storeBoot](view) {
|
|
4018
|
-
if (view && LarkUtils.isLarkView(view) && !this[
|
|
4019
|
-
this[
|
|
4594
|
+
if (view && LarkUtils.isLarkView(view) && !this[_boundViews].has(view)) {
|
|
4595
|
+
this[_boundViews].add(view);
|
|
4020
4596
|
LarkUtils.onDestroy(view, () => {
|
|
4021
|
-
this[
|
|
4597
|
+
this[_boundViews].delete(view);
|
|
4022
4598
|
});
|
|
4023
4599
|
}
|
|
4024
4600
|
return super[_storeBoot]();
|
|
4025
4601
|
}
|
|
4026
4602
|
[_storeDestroy]() {
|
|
4027
|
-
this[
|
|
4028
|
-
this[
|
|
4603
|
+
this[_boundViews].clear();
|
|
4604
|
+
this[_innerObserveFlags].clear();
|
|
4029
4605
|
super[_storeDestroy]();
|
|
4030
4606
|
}
|
|
4031
4607
|
observe(view, keys2, defCallback) {
|
|
4032
4608
|
if (this[_storeStatus] !== 2 /* ACTIVE */) return noop;
|
|
4033
|
-
let observeKeys = keys2;
|
|
4609
|
+
let observeKeys = Array.isArray(keys2) ? keys2 : [];
|
|
4034
4610
|
const _view = view;
|
|
4035
4611
|
const renderFn = _view ? LarkUtils.getRender(_view) : noop;
|
|
4036
4612
|
const dateSetterFn = _view ? LarkUtils.getDataSetter(_view) : noop;
|
|
4037
4613
|
const isInnerObserve = !view;
|
|
4038
4614
|
const innerFlags = /* @__PURE__ */ new Set();
|
|
4039
|
-
const storeInnerObserveFlags = this[
|
|
4615
|
+
const storeInnerObserveFlags = this[_innerObserveFlags];
|
|
4040
4616
|
if (isFunction(keys2)) {
|
|
4041
4617
|
const res = keys2();
|
|
4042
4618
|
if (Array.isArray(res)) observeKeys = res;
|
|
4043
4619
|
}
|
|
4620
|
+
if (keys2 === void 0 && _view && observeKeys.length === 0 && Array.isArray(this[_stateKeys])) {
|
|
4621
|
+
observeKeys = this[_stateKeys].slice();
|
|
4622
|
+
}
|
|
4044
4623
|
const defSetter = (immediate, key, alias, transform) => () => {
|
|
4045
4624
|
const stateVal = getDataByKey(this, key);
|
|
4046
4625
|
let data = { [alias || key]: stateVal };
|
|
@@ -4095,11 +4674,12 @@ var getReactAdapter = (storeName) => ({
|
|
|
4095
4674
|
Store: ReactStore,
|
|
4096
4675
|
useStore: (() => {
|
|
4097
4676
|
const store = getStore(storeName);
|
|
4677
|
+
if (!(store instanceof ReactStore)) return {};
|
|
4098
4678
|
return store[_storeBoot]();
|
|
4099
4679
|
})
|
|
4100
4680
|
});
|
|
4101
|
-
var
|
|
4102
|
-
var
|
|
4681
|
+
var _observe = /* @__PURE__ */ Symbol("store-observe");
|
|
4682
|
+
var _getLastState = /* @__PURE__ */ Symbol("store-get-last-state");
|
|
4103
4683
|
var ReactStore = class extends BaseStore {
|
|
4104
4684
|
stateChangeCount = 0;
|
|
4105
4685
|
lastCount = 0;
|
|
@@ -4113,7 +4693,7 @@ var ReactStore = class extends BaseStore {
|
|
|
4113
4693
|
}
|
|
4114
4694
|
[_storeCreate](body) {
|
|
4115
4695
|
super[_storeCreate](body);
|
|
4116
|
-
this[
|
|
4696
|
+
this[_observe](() => {
|
|
4117
4697
|
this.stateChangeCount += 1;
|
|
4118
4698
|
});
|
|
4119
4699
|
}
|
|
@@ -4123,7 +4703,7 @@ var ReactStore = class extends BaseStore {
|
|
|
4123
4703
|
this.lastCount = currCount;
|
|
4124
4704
|
return changed;
|
|
4125
4705
|
}
|
|
4126
|
-
[
|
|
4706
|
+
[_getLastState](handlers) {
|
|
4127
4707
|
if (this.isStateChanged() || !this.lastState) {
|
|
4128
4708
|
const state = this[_storeState];
|
|
4129
4709
|
const immutableState = freezeData(state);
|
|
@@ -4131,7 +4711,7 @@ var ReactStore = class extends BaseStore {
|
|
|
4131
4711
|
}
|
|
4132
4712
|
return this.lastState;
|
|
4133
4713
|
}
|
|
4134
|
-
[
|
|
4714
|
+
[_observe](cb) {
|
|
4135
4715
|
const tasks = this[_stateKeys].map((key) => ({ key, cb }));
|
|
4136
4716
|
track({ belong: this[_storeName], trackList: tasks });
|
|
4137
4717
|
return () => clear({ belong: this[_storeName], clearList: tasks });
|
|
@@ -4158,6 +4738,7 @@ var getNodeAdapter = (storeName) => ({
|
|
|
4158
4738
|
Store: NodeStore,
|
|
4159
4739
|
useStore: (() => {
|
|
4160
4740
|
const store = getStore(storeName);
|
|
4741
|
+
if (!(store instanceof NodeStore)) return {};
|
|
4161
4742
|
return store[_storeBoot]();
|
|
4162
4743
|
})
|
|
4163
4744
|
});
|
|
@@ -4184,7 +4765,7 @@ var getPlatform = (comp) => {
|
|
|
4184
4765
|
if (LarkUtils.isLarkView(comp)) return "lark" /* Lark */;
|
|
4185
4766
|
return void 0;
|
|
4186
4767
|
};
|
|
4187
|
-
var extendApis = { lazySet, shallowSet };
|
|
4768
|
+
var extendApis = { lazySet, shallowSet, computed };
|
|
4188
4769
|
var StoreCache = /* @__PURE__ */ new Map();
|
|
4189
4770
|
function defineStore(name, creator, config2) {
|
|
4190
4771
|
if (StoreCache.has(name)) {
|
|
@@ -4195,18 +4776,20 @@ function defineStore(name, creator, config2) {
|
|
|
4195
4776
|
const StoreClass = adapter.Store;
|
|
4196
4777
|
const useStore = adapter.useStore;
|
|
4197
4778
|
const store = new StoreClass(name, config2);
|
|
4198
|
-
store[
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
extendApis
|
|
4202
|
-
)
|
|
4203
|
-
);
|
|
4779
|
+
const innerProxy = store[_innerStore]();
|
|
4780
|
+
const body = creator(innerProxy, extendApis);
|
|
4781
|
+
store[_storeCreate](body);
|
|
4204
4782
|
Object.defineProperties(useStore, {
|
|
4205
4783
|
$storeName: { value: name, configurable: true },
|
|
4206
|
-
$
|
|
4784
|
+
$destroyFn: { value: () => store[_storeDestroy](), configurable: true }
|
|
4207
4785
|
});
|
|
4208
4786
|
if (!StoreCache.has(name)) {
|
|
4209
|
-
StoreCache.set(name, {
|
|
4787
|
+
StoreCache.set(name, {
|
|
4788
|
+
store,
|
|
4789
|
+
creator,
|
|
4790
|
+
config: config2,
|
|
4791
|
+
useStore
|
|
4792
|
+
});
|
|
4210
4793
|
}
|
|
4211
4794
|
return useStore;
|
|
4212
4795
|
}
|
|
@@ -4228,7 +4811,7 @@ function getUseStore(name) {
|
|
|
4228
4811
|
return void 0;
|
|
4229
4812
|
}
|
|
4230
4813
|
function cloneStore(name, useStore, config2) {
|
|
4231
|
-
const oldStoreName = useStore
|
|
4814
|
+
const oldStoreName = useStore.$storeName ?? "";
|
|
4232
4815
|
const cached = StoreCache.get(oldStoreName);
|
|
4233
4816
|
const oldStoreCreator = cached?.creator;
|
|
4234
4817
|
const oldConfig = cached?.config || {};
|
|
@@ -4249,16 +4832,12 @@ function isStoreActive(name) {
|
|
|
4249
4832
|
}
|
|
4250
4833
|
var cellCount = 0;
|
|
4251
4834
|
function cell(data) {
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
linkKeys: `${LARK_GLOBAL}_${cellCount++}`
|
|
4255
|
-
});
|
|
4835
|
+
const linkKeys = `${LARK_GLOBAL}_${cellCount++}`;
|
|
4836
|
+
return createState(data, { belong: LARK_GLOBAL, linkKeys });
|
|
4256
4837
|
}
|
|
4257
4838
|
function observeCell(state, cb, immediate = true) {
|
|
4258
4839
|
const linkKeys = getLinkKeys(state);
|
|
4259
|
-
if (!linkKeys)
|
|
4260
|
-
return () => {
|
|
4261
|
-
};
|
|
4840
|
+
if (!linkKeys) return noop;
|
|
4262
4841
|
const keys2 = linkKeys.split(".");
|
|
4263
4842
|
const key = keys2[keys2.length - 1];
|
|
4264
4843
|
const list = [{ key, cb }];
|
|
@@ -4267,49 +4846,50 @@ function observeCell(state, cb, immediate = true) {
|
|
|
4267
4846
|
return () => clear({ belong: LARK_GLOBAL, clearList: list });
|
|
4268
4847
|
}
|
|
4269
4848
|
function multi(useStore) {
|
|
4270
|
-
const storeName = useStore
|
|
4271
|
-
const flagSym = `
|
|
4849
|
+
const storeName = useStore.$storeName ?? "";
|
|
4850
|
+
const flagSym = `lark-comp-${storeName}`;
|
|
4272
4851
|
const map = /* @__PURE__ */ new Map();
|
|
4273
4852
|
let rootViewPath;
|
|
4274
4853
|
const getFlag = (viewContext) => {
|
|
4275
|
-
const owner = viewContext
|
|
4276
|
-
const viewPath = owner?.
|
|
4277
|
-
const viewId = owner?.
|
|
4854
|
+
const owner = viewContext.owner;
|
|
4855
|
+
const viewPath = owner?.path ?? "";
|
|
4856
|
+
const viewId = owner?.id ?? "";
|
|
4278
4857
|
let flag;
|
|
4279
4858
|
if (viewPath === rootViewPath) {
|
|
4280
|
-
flag = `${flagSym}
|
|
4859
|
+
flag = `${flagSym}-${viewId}`;
|
|
4281
4860
|
} else {
|
|
4282
|
-
|
|
4861
|
+
const initParams = owner?.viewInitParams;
|
|
4862
|
+
const candidate = initParams?.[flagSym];
|
|
4863
|
+
flag = typeof candidate === "string" ? candidate : void 0;
|
|
4283
4864
|
}
|
|
4284
|
-
if (owner && isFunction(owner
|
|
4285
|
-
const rawMountFrame = owner
|
|
4286
|
-
owner
|
|
4865
|
+
if (owner && isFunction(owner.mountFrame)) {
|
|
4866
|
+
const rawMountFrame = owner.mountFrame;
|
|
4867
|
+
owner.mountFrame = (frameId, viewPath2, viewInitParams = {}) => rawMountFrame.call(
|
|
4287
4868
|
owner,
|
|
4288
|
-
|
|
4869
|
+
frameId,
|
|
4289
4870
|
viewPath2,
|
|
4290
4871
|
Object.assign(viewInitParams, { [flagSym]: flag })
|
|
4291
4872
|
);
|
|
4292
4873
|
}
|
|
4293
|
-
return flag;
|
|
4874
|
+
return flag ?? "";
|
|
4294
4875
|
};
|
|
4295
4876
|
const useFn = ((view) => {
|
|
4296
4877
|
if (!view)
|
|
4297
|
-
throw new Error(
|
|
4878
|
+
throw new Error(
|
|
4879
|
+
"[@lark.js/mvc error] multi: cannot find the view instance"
|
|
4880
|
+
);
|
|
4298
4881
|
const viewCtx = view;
|
|
4299
|
-
const
|
|
4882
|
+
const tag = viewCtx[flagSym];
|
|
4883
|
+
const flag = typeof tag === "string" ? tag : "";
|
|
4300
4884
|
if (map.has(flag)) return map.get(flag);
|
|
4301
|
-
const newFn = cloneStore(
|
|
4302
|
-
flag,
|
|
4303
|
-
useStore
|
|
4304
|
-
);
|
|
4885
|
+
const newFn = cloneStore(flag, useStore);
|
|
4305
4886
|
map.set(flag, newFn);
|
|
4306
4887
|
return useFn(view);
|
|
4307
4888
|
});
|
|
4308
4889
|
const mixinObj = {
|
|
4309
4890
|
make() {
|
|
4310
4891
|
if (!rootViewPath) {
|
|
4311
|
-
|
|
4312
|
-
rootViewPath = owner?.["path"] || "";
|
|
4892
|
+
rootViewPath = this.owner?.path ?? "";
|
|
4313
4893
|
}
|
|
4314
4894
|
this[flagSym] = getFlag(this);
|
|
4315
4895
|
}
|
|
@@ -4439,7 +5019,7 @@ function convertArtSyntax(source, debug) {
|
|
|
4439
5019
|
}
|
|
4440
5020
|
if (blockStack.length > 0) {
|
|
4441
5021
|
const unclosed = blockStack.map((b) => `"${b.ctrl}" at line ${b.line}`).join(", ");
|
|
4442
|
-
throw new Error(`[@lark/mvc error] unclosed block(s): ${unclosed}`);
|
|
5022
|
+
throw new Error(`[@lark.js/mvc error] unclosed block(s): ${unclosed}`);
|
|
4443
5023
|
}
|
|
4444
5024
|
return result.join("");
|
|
4445
5025
|
}
|
|
@@ -4516,7 +5096,7 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4516
5096
|
return `${debugPrefix}<%for(${forExpr}){%>`;
|
|
4517
5097
|
}
|
|
4518
5098
|
const tokens = code.split(/\s+/);
|
|
4519
|
-
const keyword = tokens.shift();
|
|
5099
|
+
const keyword = tokens.shift() ?? "";
|
|
4520
5100
|
switch (keyword) {
|
|
4521
5101
|
case "if": {
|
|
4522
5102
|
blockStack.push({ ctrl: "if", line: lineNo });
|
|
@@ -4533,12 +5113,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4533
5113
|
}
|
|
4534
5114
|
return `${debugPrefix}<%}else{%>`;
|
|
4535
5115
|
}
|
|
4536
|
-
case "
|
|
4537
|
-
blockStack.push({ ctrl: "
|
|
5116
|
+
case "forOf": {
|
|
5117
|
+
blockStack.push({ ctrl: "forOf", line: lineNo });
|
|
4538
5118
|
const object = tokens[0];
|
|
4539
5119
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4540
5120
|
throw new Error(
|
|
4541
|
-
`[@lark/mvc error] bad
|
|
5121
|
+
`[@lark.js/mvc error] bad forOf syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{forOf list as item [index]}}`
|
|
4542
5122
|
);
|
|
4543
5123
|
}
|
|
4544
5124
|
const restTokens = tokens.slice(2);
|
|
@@ -4560,12 +5140,12 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4560
5140
|
}
|
|
4561
5141
|
return `${debugPrefix}<%for(let ${index}=0${refExpr},${refObjCount}=${refObj}.length${lastCount};${index}<${refObjCount};${index}++){${firstAndLast}${valueDecl}%>`;
|
|
4562
5142
|
}
|
|
4563
|
-
case "
|
|
4564
|
-
blockStack.push({ ctrl: "
|
|
5143
|
+
case "forIn": {
|
|
5144
|
+
blockStack.push({ ctrl: "forIn", line: lineNo });
|
|
4565
5145
|
const object = tokens[0];
|
|
4566
5146
|
if (tokens.length > 1 && tokens[1] !== "as") {
|
|
4567
5147
|
throw new Error(
|
|
4568
|
-
`[@lark/mvc error] bad
|
|
5148
|
+
`[@lark.js/mvc error] bad forIn syntax: {{${code}}}. Expected "as" keyword, got "${tokens[1]}". Usage: {{for-in obj as val [key]}}`
|
|
4569
5149
|
);
|
|
4570
5150
|
}
|
|
4571
5151
|
const restTokens2 = tokens.slice(2);
|
|
@@ -4585,19 +5165,19 @@ function convertArtExpression(code, debug, lineNo, blockStack = []) {
|
|
|
4585
5165
|
case "set":
|
|
4586
5166
|
return `${debugPrefix}<%let ${tokens.join(" ")};%>`;
|
|
4587
5167
|
case "/if":
|
|
4588
|
-
case "/
|
|
4589
|
-
case "/
|
|
5168
|
+
case "/forOf":
|
|
5169
|
+
case "/forIn":
|
|
4590
5170
|
case "/for": {
|
|
4591
5171
|
const expectedCtrl = keyword.substring(1);
|
|
4592
5172
|
const last = blockStack.pop();
|
|
4593
5173
|
if (!last) {
|
|
4594
5174
|
throw new Error(
|
|
4595
|
-
`[@lark/mvc error] unexpected {{${code}}}: no matching open block`
|
|
5175
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: no matching open block`
|
|
4596
5176
|
);
|
|
4597
5177
|
}
|
|
4598
5178
|
if (last.ctrl !== expectedCtrl) {
|
|
4599
5179
|
throw new Error(
|
|
4600
|
-
`[@lark/mvc error] unexpected {{${code}}}: expected {{/${last.ctrl}}} to close block opened at line ${last.line}`
|
|
5180
|
+
`[@lark.js/mvc error] unexpected {{${code}}}: expected {{/${last.ctrl}}} to close block opened at line ${last.line}`
|
|
4601
5181
|
);
|
|
4602
5182
|
}
|
|
4603
5183
|
return `${debugPrefix}<%}%>`;
|
|
@@ -4661,7 +5241,7 @@ function parseAsExpr(expr) {
|
|
|
4661
5241
|
function compileToFunction(source, debug, file) {
|
|
4662
5242
|
const matcher = /<%([@=!:])?([\s\S]*?)%>|$/g;
|
|
4663
5243
|
let index = 0;
|
|
4664
|
-
let funcSource = `$
|
|
5244
|
+
let funcSource = `$out+='`;
|
|
4665
5245
|
let hasAtRule = false;
|
|
4666
5246
|
const escapeSlashRegExp = /\\|'/g;
|
|
4667
5247
|
const escapeBreakReturnRegExp = /\r|\n/g;
|
|
@@ -4687,17 +5267,17 @@ function compileToFunction(source, debug, file) {
|
|
|
4687
5267
|
}
|
|
4688
5268
|
if (operate === "@") {
|
|
4689
5269
|
hasAtRule = true;
|
|
4690
|
-
funcSource += `'+($
|
|
5270
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$refFn($refAlt,${content}))+'`;
|
|
4691
5271
|
} else if (operate === "=" || operate === ":") {
|
|
4692
|
-
funcSource += `'+($
|
|
5272
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',$encHtml(${content}))+'`;
|
|
4693
5273
|
} else if (operate === "!") {
|
|
4694
|
-
if (!content.startsWith("$
|
|
4695
|
-
content = `$
|
|
5274
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
5275
|
+
content = `$strSafe(${content})`;
|
|
4696
5276
|
}
|
|
4697
|
-
funcSource += `'+($
|
|
5277
|
+
funcSource += `'+($dbgExpr='<%${operate + expr}%>',${content})+'`;
|
|
4698
5278
|
} else if (content) {
|
|
4699
5279
|
if (line > -1) {
|
|
4700
|
-
funcSource += `';$
|
|
5280
|
+
funcSource += `';$dbgLine=${line};$dbgArt='${art}';`;
|
|
4701
5281
|
content = "";
|
|
4702
5282
|
} else {
|
|
4703
5283
|
funcSource += `';`;
|
|
@@ -4706,19 +5286,19 @@ function compileToFunction(source, debug, file) {
|
|
|
4706
5286
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4707
5287
|
}
|
|
4708
5288
|
if (expr) {
|
|
4709
|
-
funcSource += `$
|
|
5289
|
+
funcSource += `$dbgExpr='<%${expr}%>';`;
|
|
4710
5290
|
}
|
|
4711
|
-
funcSource += content + `;$
|
|
5291
|
+
funcSource += content + `;$out+='`;
|
|
4712
5292
|
}
|
|
4713
5293
|
} else {
|
|
4714
5294
|
if (operate === "@") {
|
|
4715
5295
|
hasAtRule = true;
|
|
4716
|
-
funcSource += `'+$
|
|
5296
|
+
funcSource += `'+$refFn($refAlt,${content})+'`;
|
|
4717
5297
|
} else if (operate === "=" || operate === ":") {
|
|
4718
|
-
funcSource += `'+$
|
|
5298
|
+
funcSource += `'+$encHtml(${content})+'`;
|
|
4719
5299
|
} else if (operate === "!") {
|
|
4720
|
-
if (!content.startsWith("$
|
|
4721
|
-
content = `$
|
|
5300
|
+
if (!content.startsWith("$encUri(") || !content.endsWith(")")) {
|
|
5301
|
+
content = `$strSafe(${content})`;
|
|
4722
5302
|
}
|
|
4723
5303
|
funcSource += `'+${content}+'`;
|
|
4724
5304
|
} else if (content) {
|
|
@@ -4726,28 +5306,24 @@ function compileToFunction(source, debug, file) {
|
|
|
4726
5306
|
if (funcSource.endsWith(`+'';`)) {
|
|
4727
5307
|
funcSource = funcSource.substring(0, funcSource.length - 4) + ";";
|
|
4728
5308
|
}
|
|
4729
|
-
funcSource += `${content};$
|
|
5309
|
+
funcSource += `${content};$out+='`;
|
|
4730
5310
|
}
|
|
4731
5311
|
}
|
|
4732
5312
|
return match;
|
|
4733
5313
|
});
|
|
4734
5314
|
funcSource += `';`;
|
|
4735
|
-
funcSource = funcSource.replace(/\$
|
|
4736
|
-
funcSource = funcSource.replace(/\$
|
|
5315
|
+
funcSource = funcSource.replace(/\$out\+='';/g, "");
|
|
5316
|
+
funcSource = funcSource.replace(/\$out\+=''\+/g, "$out+=");
|
|
4737
5317
|
if (debug) {
|
|
4738
5318
|
const filePart = file ? `\\r\\n\\tat file:${file}` : "";
|
|
4739
|
-
funcSource = `let $
|
|
5319
|
+
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;}`;
|
|
4740
5320
|
}
|
|
4741
5321
|
const viewIdRegExp = new RegExp(String.fromCharCode(31), "g");
|
|
4742
5322
|
funcSource = funcSource.replace(viewIdRegExp, `'+$viewId+'`);
|
|
4743
|
-
|
|
4744
|
-
const
|
|
4745
|
-
const
|
|
4746
|
-
|
|
4747
|
-
const refFallback = "if(!$$ref)$$ref=$$;";
|
|
4748
|
-
const fns = `${refFallback}${encode}${encodeURIMore}${encodeQuote}${atRule};`;
|
|
4749
|
-
const fullSource = `${fns}let $g='\\x1e',$_temp,$p=''{{VARS}};${funcSource}return $p`;
|
|
4750
|
-
return `($$,$viewId,$$ref,$e,$n,$eu,$i,$eq)=>{${fullSource}}`;
|
|
5323
|
+
void hasAtRule;
|
|
5324
|
+
const refFallback = "if(!$refAlt)$refAlt=$data;";
|
|
5325
|
+
const fullSource = `${refFallback}let $splitter='\\x1e',$tmp,$out=''{{VARS}};${funcSource}return $out`;
|
|
5326
|
+
return `($data,$viewId,$refAlt,$encHtml,$strSafe,$encUri,$refFn,$encQuote)=>{${fullSource}}`;
|
|
4751
5327
|
}
|
|
4752
5328
|
function compileTemplate(source, options = {}) {
|
|
4753
5329
|
const { debug = false, globalVars = [], file } = options;
|
|
@@ -4756,17 +5332,14 @@ function compileTemplate(source, options = {}) {
|
|
|
4756
5332
|
const viewEventProcessed = processViewEvents(converted);
|
|
4757
5333
|
const finalSource = restoreComments(viewEventProcessed, comments);
|
|
4758
5334
|
const funcBody = compileToFunction(finalSource, debug, file);
|
|
4759
|
-
const varDeclarations = globalVars.map((key) => `,${key}
|
|
5335
|
+
const varDeclarations = globalVars.map((key) => `,${key}=$data.${key}`).join("");
|
|
4760
5336
|
const funcWithVars = funcBody.replace("{{VARS}}", () => varDeclarations);
|
|
4761
|
-
return `
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
/* $eu */ null,
|
|
4768
|
-
/* $i */ null,
|
|
4769
|
-
/* $eq */ null
|
|
5337
|
+
return `import { encHtml as __larkEncHtml, strSafe as __larkStrSafe, encUri as __larkEncUri, encQuote as __larkEncQuote, refFn as __larkRefFn } from "@lark.js/mvc/runtime";
|
|
5338
|
+
export default function(data, viewId, refData) {
|
|
5339
|
+
let $data = data || {},
|
|
5340
|
+
$viewId = viewId || '';
|
|
5341
|
+
return (${funcWithVars})($data, $viewId, refData,
|
|
5342
|
+
__larkEncHtml, __larkStrSafe, __larkEncUri, __larkRefFn, __larkEncQuote
|
|
4770
5343
|
);
|
|
4771
5344
|
}`;
|
|
4772
5345
|
}
|
|
@@ -4875,7 +5448,7 @@ function fallbackExtractVariables(source) {
|
|
|
4875
5448
|
while ((m = outputRegExp.exec(source)) !== null) {
|
|
4876
5449
|
vars.add(m[1]);
|
|
4877
5450
|
}
|
|
4878
|
-
const eachRegExp = /\{\{
|
|
5451
|
+
const eachRegExp = /\{\{forOf\s+([a-zA-Z_$][\w$]*)\s+as/g;
|
|
4879
5452
|
while ((m = eachRegExp.exec(source)) !== null) {
|
|
4880
5453
|
vars.add(m[1]);
|
|
4881
5454
|
}
|
|
@@ -4891,82 +5464,100 @@ function walkAst(ast, visitors) {
|
|
|
4891
5464
|
if (visitors[type]) {
|
|
4892
5465
|
visitors[type](node);
|
|
4893
5466
|
}
|
|
5467
|
+
const bag = node;
|
|
4894
5468
|
for (const key of Object.keys(node)) {
|
|
4895
5469
|
if (key === "type" || key === "start" || key === "end" || key === "loc" || key === "range")
|
|
4896
5470
|
continue;
|
|
4897
|
-
if (type === "MemberExpression" && key === "property"
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
continue;
|
|
5471
|
+
if (type === "MemberExpression" && key === "property") {
|
|
5472
|
+
const me = node;
|
|
5473
|
+
if (!me.computed) continue;
|
|
4901
5474
|
}
|
|
4902
|
-
if (type === "
|
|
4903
|
-
|
|
5475
|
+
if (type === "ObjectProperty" && key === "key") {
|
|
5476
|
+
const op = node;
|
|
5477
|
+
if (!op.computed) continue;
|
|
4904
5478
|
}
|
|
4905
|
-
|
|
5479
|
+
if (type === "ObjectMethod" && key === "key") {
|
|
5480
|
+
const om = node;
|
|
5481
|
+
if (!om.computed) continue;
|
|
5482
|
+
}
|
|
5483
|
+
const child = bag[key];
|
|
4906
5484
|
if (Array.isArray(child)) {
|
|
4907
5485
|
for (const item of child) {
|
|
4908
|
-
if (item
|
|
4909
|
-
visit(item);
|
|
4910
|
-
}
|
|
5486
|
+
if (isAstNode(item)) visit(item);
|
|
4911
5487
|
}
|
|
4912
|
-
} else if (child
|
|
5488
|
+
} else if (isAstNode(child)) {
|
|
4913
5489
|
visit(child);
|
|
4914
5490
|
}
|
|
4915
5491
|
}
|
|
4916
5492
|
}
|
|
4917
5493
|
visit(ast);
|
|
4918
5494
|
}
|
|
5495
|
+
function isAstNode(v) {
|
|
5496
|
+
return !!v && typeof v === "object" && typeof v.type === "string";
|
|
5497
|
+
}
|
|
4919
5498
|
var BUILTIN_GLOBALS = {
|
|
4920
5499
|
// ─── Template runtime helpers (injected by compileToFunction) ───────
|
|
4921
5500
|
//
|
|
4922
5501
|
// These variables appear in the generated template function signature
|
|
4923
5502
|
// or body. They must be excluded from extractGlobalVars() so that
|
|
4924
|
-
// they are not mistaken for user data variables and destructured from
|
|
5503
|
+
// they are not mistaken for user data variables and destructured from $data.
|
|
4925
5504
|
// SPLITTER character constant (same as \x1e), used as namespace separator
|
|
4926
5505
|
// for refData keys, event attribute encoding, and internal data structures.
|
|
4927
|
-
// Declared as: let $
|
|
4928
|
-
$
|
|
4929
|
-
//
|
|
4930
|
-
// User variables are destructured from
|
|
4931
|
-
// let {name, age} =
|
|
5506
|
+
// Declared as: let $splitter='\x1e'
|
|
5507
|
+
$splitter: 1,
|
|
5508
|
+
// Data — the data object passed from Updater to the template function.
|
|
5509
|
+
// User variables are destructured from $data at the top of the function:
|
|
5510
|
+
// let {name, age} = $data;
|
|
4932
5511
|
// This is the first parameter of the generated arrow function.
|
|
4933
|
-
|
|
5512
|
+
$data: 1,
|
|
4934
5513
|
// Null-safe toString: v => '' + (v == null ? '' : v)
|
|
4935
5514
|
// Converts null/undefined to empty string, otherwise calls toString().
|
|
4936
5515
|
// Wraps every {{!raw}} output to prevent "null" / "undefined" rendering.
|
|
4937
|
-
$
|
|
4938
|
-
// HTML entity encoder: v => $
|
|
5516
|
+
$strSafe: 1,
|
|
5517
|
+
// HTML entity encoder: v => $strSafe(v).replace(/[&<>"'`]/g, entityMap)
|
|
4939
5518
|
// Encodes &, <, >, ", ', ` to HTML entities (& < etc.)
|
|
4940
5519
|
// Applied to all {{=escaped}} and {{:binding}} outputs.
|
|
4941
|
-
$
|
|
4942
|
-
// HTML entity map — internal object used by $
|
|
5520
|
+
$encHtml: 1,
|
|
5521
|
+
// HTML entity map — internal object used by $encHtml:
|
|
4943
5522
|
// {'&':'amp','<':'gt','>':'gt','"':'#34','\'':'#39','`':'#96'}
|
|
4944
|
-
// Not a standalone function; referenced inside $
|
|
4945
|
-
$
|
|
4946
|
-
// HTML entity RegExp — internal regexp used by $
|
|
5523
|
+
// Not a standalone function; referenced inside $encHtml's closure.
|
|
5524
|
+
$entMap: 1,
|
|
5525
|
+
// HTML entity RegExp — internal regexp used by $encHtml:
|
|
4947
5526
|
// /[&<>"'`]/g
|
|
4948
|
-
$
|
|
4949
|
-
// HTML entity replacer function — internal helper used by $
|
|
4950
|
-
// m => '&' + $
|
|
4951
|
-
// Maps
|
|
4952
|
-
$
|
|
5527
|
+
$entReg: 1,
|
|
5528
|
+
// HTML entity replacer function — internal helper used by $encHtml:
|
|
5529
|
+
// m => '&' + $entMap[m] + ';'
|
|
5530
|
+
// Maps matched character to its entity string.
|
|
5531
|
+
$entFn: 1,
|
|
4953
5532
|
// Output buffer — the string accumulator for rendered HTML.
|
|
4954
|
-
// All template output is appended via $
|
|
4955
|
-
// Declared as: let $
|
|
4956
|
-
$
|
|
5533
|
+
// All template output is appended via $out += '...'.
|
|
5534
|
+
// Declared as: let $out = ''
|
|
5535
|
+
$out: 1,
|
|
4957
5536
|
// Reference lookup: (refData, value) => key
|
|
4958
5537
|
// Finds or allocates a SPLITTER-prefixed key in refData for a given
|
|
4959
5538
|
// object reference. Used by {{@ref}} operator for passing object
|
|
4960
5539
|
// references to child views via v-lark attributes.
|
|
4961
|
-
$
|
|
4962
|
-
// URI encoder: v => encodeURIComponent($
|
|
5540
|
+
$refFn: 1,
|
|
5541
|
+
// URI encoder: v => encodeURIComponent($strSafe(v)).replace(/[!')(*]/g, extraMap)
|
|
4963
5542
|
// Extends encodeURIComponent with encoding of ! ' ( ) *.
|
|
4964
5543
|
// Applied to values in @event URL parameters and {{!uri}} contexts.
|
|
4965
|
-
$
|
|
4966
|
-
//
|
|
5544
|
+
$encUri: 1,
|
|
5545
|
+
// URI encode map — internal object used by $encUri:
|
|
5546
|
+
// {'!':'%21','\'':'%27','(':'%28',')':'%29','*':'%2A'}
|
|
5547
|
+
$uriMap: 1,
|
|
5548
|
+
// URI encode replacer — internal helper used by $encUri:
|
|
5549
|
+
// m => $uriMap[m]
|
|
5550
|
+
$uriFn: 1,
|
|
5551
|
+
// URI encode regexp — internal regexp used by $encUri:
|
|
5552
|
+
// /[!')(*]/g
|
|
5553
|
+
$uriReg: 1,
|
|
5554
|
+
// Quote encoder: v => $strSafe(v).replace(/['"\\]/g, '\\$&')
|
|
4967
5555
|
// Escapes quotes and backslashes for safe embedding in HTML attribute
|
|
4968
5556
|
// values (e.g. data-json='...').
|
|
4969
|
-
$
|
|
5557
|
+
$encQuote: 1,
|
|
5558
|
+
// Quote encode regexp — internal regexp used by $encQuote:
|
|
5559
|
+
// /['"\\]/g
|
|
5560
|
+
$qReg: 1,
|
|
4970
5561
|
// View ID — the unique identifier of the owning View instance.
|
|
4971
5562
|
// Injected into @event attribute values at render time so that
|
|
4972
5563
|
// EventDelegator can dispatch events to the correct View handler.
|
|
@@ -4974,23 +5565,23 @@ var BUILTIN_GLOBALS = {
|
|
|
4974
5565
|
$viewId: 1,
|
|
4975
5566
|
// Debug: current expression text — stores the template expression being
|
|
4976
5567
|
// evaluated, for error reporting. Only present in debug mode.
|
|
4977
|
-
// e.g. $
|
|
4978
|
-
$
|
|
5568
|
+
// e.g. $dbgExpr='<%=user.name%>'
|
|
5569
|
+
$dbgExpr: 1,
|
|
4979
5570
|
// Debug: original art syntax — stores the {{}} template syntax before
|
|
4980
5571
|
// conversion, for error reporting. Only present in debug mode.
|
|
4981
|
-
// e.g. $
|
|
4982
|
-
$
|
|
5572
|
+
// e.g. $dbgArt='{{=user.name}}'
|
|
5573
|
+
$dbgArt: 1,
|
|
4983
5574
|
// Debug: source line number — tracks the current line in the template
|
|
4984
5575
|
// source, for error reporting. Only present in debug mode.
|
|
4985
|
-
$
|
|
4986
|
-
//
|
|
4987
|
-
// Defaults to
|
|
4988
|
-
// Ensures $
|
|
4989
|
-
|
|
5576
|
+
$dbgLine: 1,
|
|
5577
|
+
// RefData alias — fallback reference lookup table.
|
|
5578
|
+
// Defaults to $data when no explicit $refAlt is provided.
|
|
5579
|
+
// Ensures $refFn() does not crash when @ operator is used without refData.
|
|
5580
|
+
$refAlt: 1,
|
|
4990
5581
|
// Temporary variable — used by the compiler for intermediate
|
|
4991
5582
|
// expression results in generated code (e.g. loop variables,
|
|
4992
|
-
// conditional branches). Declared as: let $
|
|
4993
|
-
$
|
|
5583
|
+
// conditional branches). Declared as: let $tmp
|
|
5584
|
+
$tmp: 1,
|
|
4994
5585
|
// JS literals
|
|
4995
5586
|
undefined: 1,
|
|
4996
5587
|
null: 1,
|
|
@@ -5055,17 +5646,19 @@ var BUILTIN_GLOBALS = {
|
|
|
5055
5646
|
};
|
|
5056
5647
|
var BUILTIN_GLOBAL_SET = new Set(Object.keys(BUILTIN_GLOBALS));
|
|
5057
5648
|
export {
|
|
5058
|
-
Bag,
|
|
5059
5649
|
CALL_BREAK_TIME,
|
|
5060
5650
|
Cache,
|
|
5651
|
+
cross_site_default as CrossSite,
|
|
5061
5652
|
EVENT_METHOD_REGEXP,
|
|
5062
5653
|
EventDelegator,
|
|
5063
5654
|
EventEmitter,
|
|
5064
5655
|
Frame,
|
|
5656
|
+
FrameVisualBridge,
|
|
5065
5657
|
Framework,
|
|
5066
5658
|
LARK_VIEW,
|
|
5659
|
+
Payload,
|
|
5067
5660
|
Platform,
|
|
5068
|
-
ROUTER_EVENTS,
|
|
5661
|
+
RouterEvents as ROUTER_EVENTS,
|
|
5069
5662
|
Router,
|
|
5070
5663
|
SPLITTER,
|
|
5071
5664
|
Service,
|
|
@@ -5079,13 +5672,14 @@ export {
|
|
|
5079
5672
|
applyVdomOps,
|
|
5080
5673
|
assign,
|
|
5081
5674
|
cell,
|
|
5082
|
-
classExtend,
|
|
5083
5675
|
cloneData,
|
|
5084
5676
|
cloneStore,
|
|
5085
5677
|
compileTemplate,
|
|
5678
|
+
computed,
|
|
5086
5679
|
createState,
|
|
5087
5680
|
createVdomRef,
|
|
5088
5681
|
defineStore,
|
|
5682
|
+
defineView,
|
|
5089
5683
|
delStore,
|
|
5090
5684
|
encodeHTML,
|
|
5091
5685
|
encodeQ,
|
|
@@ -5093,6 +5687,7 @@ export {
|
|
|
5093
5687
|
encodeURIExtra,
|
|
5094
5688
|
ensureElementId,
|
|
5095
5689
|
extractGlobalVars,
|
|
5690
|
+
config as frameworkConfig,
|
|
5096
5691
|
funcWithTry,
|
|
5097
5692
|
generateId,
|
|
5098
5693
|
getAttribute,
|
|
@@ -5100,9 +5695,9 @@ export {
|
|
|
5100
5695
|
getPlatform,
|
|
5101
5696
|
getStore,
|
|
5102
5697
|
getUseStore,
|
|
5103
|
-
|
|
5698
|
+
hasOwnProperty,
|
|
5104
5699
|
installFrameVisualizerBridge,
|
|
5105
|
-
|
|
5700
|
+
invalidateViewClass,
|
|
5106
5701
|
isPlainObject,
|
|
5107
5702
|
isPrimitive,
|
|
5108
5703
|
isPrimitiveOrFunc,
|
|
@@ -5121,6 +5716,7 @@ export {
|
|
|
5121
5716
|
observeCell,
|
|
5122
5717
|
parseUri,
|
|
5123
5718
|
registerViewClass,
|
|
5719
|
+
resetProjectsMap,
|
|
5124
5720
|
safeguard,
|
|
5125
5721
|
serializeFrameTree,
|
|
5126
5722
|
setData,
|
|
@@ -5132,6 +5728,7 @@ export {
|
|
|
5132
5728
|
toUri,
|
|
5133
5729
|
translateData,
|
|
5134
5730
|
unmark,
|
|
5731
|
+
use,
|
|
5135
5732
|
vdomGetCompareKey,
|
|
5136
5733
|
vdomGetNode,
|
|
5137
5734
|
vdomSetAttributes,
|