@lark.js/mvc 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -27,7 +27,6 @@ __export(index_exports, {
27
27
  EventDelegator: () => EventDelegator,
28
28
  EventEmitter: () => EventEmitter,
29
29
  Frame: () => Frame,
30
- FrameVisualBridge: () => FrameVisualBridge,
31
30
  Framework: () => Framework,
32
31
  LARK_VIEW: () => LARK_VIEW,
33
32
  Payload: () => Payload,
@@ -40,65 +39,30 @@ __export(index_exports, {
40
39
  Updater: () => Updater,
41
40
  VIEW_EVENT_METHOD_REGEXP: () => VIEW_EVENT_METHOD_REGEXP,
42
41
  View: () => View,
43
- applyDomOps: () => applyDomOps,
44
- applyIdUpdates: () => applyIdUpdates,
45
42
  applyStyle: () => applyStyle,
46
- assign: () => assign,
47
43
  bindStore: () => bindStore,
48
44
  computed: () => computed,
49
45
  create: () => create,
50
- createDomRef: () => createDomRef,
51
- defineStore: () => defineStore,
46
+ createVDomRef: () => createVDomRef,
52
47
  defineView: () => defineView,
53
- domGetCompareKey: () => domGetCompareKey,
54
- domGetNode: () => domGetNode,
55
- domSetAttributes: () => domSetAttributes,
56
- domSetChildNodes: () => domSetChildNodes,
57
- domSetNode: () => domSetNode,
58
- domSpecialDiff: () => domSpecialDiff,
59
- domUnmountFrames: () => domUnmountFrames,
60
- encodeHTML: () => encodeHTML,
61
- encodeQ: () => encodeQ,
62
- encodeSafe: () => encodeSafe,
63
- encodeURIExtra: () => encodeURIExtra,
64
- ensureElementId: () => ensureElementId,
65
48
  frameworkConfig: () => config,
66
- funcWithTry: () => funcWithTry,
67
- generateId: () => generateId,
68
- getAttribute: () => getAttribute,
69
- getById: () => getById,
70
49
  getRouteMode: () => getRouteMode,
71
- hasOwnProperty: () => hasOwnProperty,
72
- installFrameVisualizerBridge: () => installFrameVisualizerBridge,
73
50
  invalidateViewClass: () => invalidateViewClass,
74
- isPlainObject: () => isPlainObject,
75
- isPrimitive: () => isPrimitive,
76
- isPrimitiveOrFunc: () => isPrimitiveOrFunc,
77
- keys: () => keys,
78
51
  mark: () => mark,
79
52
  markBooted: () => markBooted,
80
53
  markRouterBooted: () => markRouterBooted,
81
54
  nextCounter: () => nextCounter,
82
- nodeInside: () => nodeInside,
83
- noop: () => noop,
84
- now: () => now,
85
- parseUri: () => parseUri,
86
55
  registerViewClass: () => registerViewClass,
87
56
  resetProjectsMap: () => resetProjectsMap,
88
57
  safeguard: () => safeguard,
89
- serializeFrameTree: () => serializeFrameTree,
90
- setData: () => setData,
91
- syncCounter: () => syncCounter,
92
- toMap: () => toMap,
93
- toUri: () => toUri,
94
- translateData: () => translateData,
95
58
  unmark: () => unmark,
96
59
  use: () => use,
97
- useUrlState: () => useUrlState
60
+ useUrlState: () => useUrlState,
61
+ vdomCreate: () => vdomCreate
98
62
  });
99
63
  module.exports = __toCommonJS(index_exports);
100
64
 
101
- // src/constants.ts
65
+ // src/common.ts
102
66
  var globalCounter = 0;
103
67
  var SPLITTER = String.fromCharCode(30);
104
68
  var RouterEvents = {
@@ -114,21 +78,136 @@ var VIEW_EVENT_METHOD_REGEXP = /^(\$?)([\w]*)<(.*?)>(?:<([\w ,]*)>)?$/;
114
78
  var URL_TRIM_HASH_REGEXP = /(?:^.*\/\/[^/]+|#.*$)/gi;
115
79
  var URL_TRIM_QUERY_REGEXP = /^[^#]*#?!?/;
116
80
  var URL_PARAM_REGEXP = /([^=&?/#]+)=?([^&#?]*)/g;
81
+ var IS_URL_PARAMS = /(?!^)=|&/;
117
82
  var URL_QUERY_HASH_REGEXP = /[#?].*$/;
118
83
  var SVG_NS = "http://www.w3.org/2000/svg";
119
84
  var MATH_NS = "http://www.w3.org/1998/Math/MathML";
120
85
  var TAG_NAME_REGEXP = /<([a-z][^/\0>\x20\t\r\n\f]+)/i;
121
86
  var CALL_BREAK_TIME = 48;
87
+ var V_TEXT_NODE = 0;
88
+ var TAG_STATIC_KEY = "_";
89
+ var VDOM_NS_MAP = {
90
+ svg: SVG_NS,
91
+ math: MATH_NS
92
+ };
122
93
  function nextCounter() {
123
94
  return ++globalCounter;
124
95
  }
96
+ var HTML_ENT_MAP = {
97
+ "&": "amp",
98
+ "<": "lt",
99
+ ">": "gt",
100
+ '"': "#34",
101
+ "'": "#39",
102
+ "`": "#96"
103
+ };
104
+ var HTML_ENT_REGEXP = /[&<>"'`]/g;
105
+ function strSafe(v) {
106
+ return String(v == null ? "" : v);
107
+ }
108
+ function encodeHTML(v) {
109
+ return String(v == null ? "" : v).replace(
110
+ HTML_ENT_REGEXP,
111
+ (m) => "&" + HTML_ENT_MAP[m] + ";"
112
+ );
113
+ }
114
+ var URI_ENT_MAP = {
115
+ "!": "%21",
116
+ "'": "%27",
117
+ "(": "%28",
118
+ ")": "%29",
119
+ "*": "%2A"
120
+ };
121
+ var URI_ENT_REGEXP = /[!')(*]/g;
122
+ function encodeURIExtra(v) {
123
+ return encodeURIComponent(strSafe(v)).replace(
124
+ URI_ENT_REGEXP,
125
+ (m) => URI_ENT_MAP[m]
126
+ );
127
+ }
128
+ var QUOTE_ENT_REGEXP = /['"\\]/g;
129
+ function encodeQuote(v) {
130
+ return strSafe(v).replace(QUOTE_ENT_REGEXP, "\\$&");
131
+ }
132
+ function refFn(ref, value, key) {
133
+ const counter = ref[SPLITTER];
134
+ for (let i = counter; --i; ) {
135
+ key = SPLITTER + i;
136
+ if (ref[key] === value) return key;
137
+ }
138
+ key = SPLITTER + ref[SPLITTER]++;
139
+ ref[key] = value;
140
+ return key;
141
+ }
142
+ function isRefToken(s) {
143
+ if (s.length < 2 || s[0] !== SPLITTER) return false;
144
+ for (let i = 1; i < s.length; i++) {
145
+ const c = s.charCodeAt(i);
146
+ if (c < "0".charCodeAt(0) || c > "9".charCodeAt(0)) return false;
147
+ }
148
+ return true;
149
+ }
125
150
 
126
151
  // src/utils.ts
152
+ var CALL_BREAK_TIME2 = 9;
153
+ var callQueue = [];
154
+ var callScheduled = false;
155
+ var schedulerYield = (() => {
156
+ try {
157
+ if (typeof globalThis?.scheduler?.yield === "function") {
158
+ return globalThis.scheduler.yield.bind(globalThis.scheduler);
159
+ }
160
+ } catch {
161
+ }
162
+ return void 0;
163
+ })();
164
+ async function startCall() {
165
+ callScheduled = false;
166
+ const startTime = performance.now();
167
+ while (callQueue.length > 0) {
168
+ const task2 = callQueue.shift();
169
+ try {
170
+ task2();
171
+ } catch (e) {
172
+ console.error("scheduler task error:", e);
173
+ }
174
+ if (callQueue.length > 0 && performance.now() - startTime > CALL_BREAK_TIME2) {
175
+ if (schedulerYield) {
176
+ await schedulerYield();
177
+ } else {
178
+ scheduleNextChunk();
179
+ return;
180
+ }
181
+ }
182
+ }
183
+ }
184
+ function scheduleNextChunk() {
185
+ setTimeout(() => startCall(), 0);
186
+ callScheduled = true;
187
+ }
188
+ function callFunction(fn, args) {
189
+ callQueue.push(() => fn(...args));
190
+ if (!callScheduled) {
191
+ scheduleNextChunk();
192
+ }
193
+ }
127
194
  function isPlainObject(value) {
128
195
  if (typeof value !== "object" || value === null) return false;
129
196
  const proto = Object.getPrototypeOf(value);
130
- if (proto === null) return true;
131
- return proto === Object.prototype || proto === null;
197
+ return proto === null || proto === Object.prototype;
198
+ }
199
+ function isRecord(value) {
200
+ return typeof value === "object" && value !== null;
201
+ }
202
+ function asRecord(value) {
203
+ if (isRecord(value)) {
204
+ return value;
205
+ }
206
+ console.error("fallback to Object.fromEntries, even an empty object {}.");
207
+ if (Array.isArray(value)) {
208
+ return Object.fromEntries(value.entries());
209
+ }
210
+ return {};
132
211
  }
133
212
  function isPrimitiveOrFunc(value) {
134
213
  return !value || typeof value !== "object" && typeof value !== "function";
@@ -140,9 +219,6 @@ var _localCounter = 0;
140
219
  function generateId(prefix) {
141
220
  return (prefix || "lark_") + _localCounter++;
142
221
  }
143
- function syncCounter(val) {
144
- _localCounter = val;
145
- }
146
222
  function noop() {
147
223
  }
148
224
  function hasOwnProperty(owner, prop) {
@@ -186,25 +262,17 @@ function setData(newData, oldData, changedKeys2, excludes) {
186
262
  let changed = false;
187
263
  for (const p in newData) {
188
264
  if (hasOwnProperty(newData, p)) {
189
- const now2 = newData[p];
265
+ const now = newData[p];
190
266
  const old = oldData[p];
191
- if ((!isPrimitiveOrFunc(now2) || old !== now2) && !excludes.has(p)) {
267
+ if ((!isPrimitiveOrFunc(now) || old !== now) && !excludes.has(p)) {
192
268
  changedKeys2.add(p);
193
269
  changed = true;
194
270
  }
195
- oldData[p] = now2;
271
+ oldData[p] = now;
196
272
  }
197
273
  }
198
274
  return changed;
199
275
  }
200
- function isRefToken(s) {
201
- if (s.length < 2 || s[0] !== SPLITTER) return false;
202
- for (let i = 1; i < s.length; i++) {
203
- const c = s.charCodeAt(i);
204
- if (c < 48 || c > 57) return false;
205
- }
206
- return true;
207
- }
208
276
  function translateData(data, value) {
209
277
  if (isPrimitive(value)) {
210
278
  const prop = String(value);
@@ -233,11 +301,11 @@ function getById(id) {
233
301
  function getAttribute(element, attr) {
234
302
  return Element.prototype.getAttribute.call(element, attr) ?? "";
235
303
  }
236
- function ensureElementId(element) {
304
+ function ensureElementId(element, prefix) {
237
305
  const id = element.getAttribute("id");
238
306
  if (id) return id;
239
307
  element.autoId = 1;
240
- const newId = generateId();
308
+ const newId = generateId(prefix);
241
309
  element.id = newId;
242
310
  return newId;
243
311
  }
@@ -267,11 +335,6 @@ function parseUri(uri) {
267
335
  });
268
336
  return { path: actualPath, params };
269
337
  }
270
- var IS_URL_PARAMS = {
271
- test(s) {
272
- return /(?!^)=|&/.test(s);
273
- }
274
- };
275
338
  function toUri(path, params, keepEmpty) {
276
339
  const pairs = [];
277
340
  let hasParams = false;
@@ -298,9 +361,6 @@ function toMap(list, key) {
298
361
  }
299
362
  return map;
300
363
  }
301
- function now() {
302
- return Date.now ? Date.now() : (/* @__PURE__ */ new Date()).getTime();
303
- }
304
364
 
305
365
  // src/apply-style.ts
306
366
  var injectedStyleIds = /* @__PURE__ */ new Set();
@@ -938,14 +998,12 @@ function getChanged(oldLoc, newLoc) {
938
998
  setDiff("path", oldLoc["path"], newLoc["path"]);
939
999
  if (changedParams["path"]) {
940
1000
  result["path"] = changedParams["path"];
941
- hasChanged = true;
942
1001
  result.changed = true;
943
1002
  }
944
1003
  const viewKey = "view";
945
1004
  setDiff(viewKey, oldLoc.view, newLoc.view);
946
1005
  if (changedParams[viewKey]) {
947
1006
  result.view = changedParams[viewKey];
948
- hasChanged = true;
949
1007
  result.changed = true;
950
1008
  }
951
1009
  const finalResult = {
@@ -1054,10 +1112,7 @@ var Router = {
1054
1112
  if (lastChanged["path"]) {
1055
1113
  document.title = defaultTitle || document.title;
1056
1114
  }
1057
- emitter2.fire(
1058
- RouterEvents.CHANGED,
1059
- lastChanged
1060
- );
1115
+ emitter2.fire(RouterEvents.CHANGED, asRecord(lastChanged));
1061
1116
  }
1062
1117
  silent = 0;
1063
1118
  if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && lastChanged) {
@@ -1188,10 +1243,7 @@ var Router = {
1188
1243
  suspend = 1;
1189
1244
  }
1190
1245
  };
1191
- Router.fire(
1192
- RouterEvents.CHANGE,
1193
- changeEvent
1194
- );
1246
+ Router.fire(RouterEvents.CHANGE, changeEvent);
1195
1247
  if (suspend || changeEvent.p) {
1196
1248
  return;
1197
1249
  }
@@ -1465,6 +1517,53 @@ var EventDelegator = {
1465
1517
  }
1466
1518
  };
1467
1519
 
1520
+ // src/module-loader.ts
1521
+ var config = {
1522
+ rootId: "root",
1523
+ routeMode: "history",
1524
+ hashbang: "#!",
1525
+ error: (error) => {
1526
+ throw error;
1527
+ }
1528
+ };
1529
+ function use(names, callback) {
1530
+ const nameList = typeof names === "string" ? [names] : names;
1531
+ const loadPromise = (() => {
1532
+ if (config.require) {
1533
+ const result = config.require(nameList);
1534
+ if (result && typeof result.then === "function") {
1535
+ return result;
1536
+ }
1537
+ return Promise.resolve([]);
1538
+ }
1539
+ return Promise.all(
1540
+ nameList.map((name) => {
1541
+ const importPath = name.startsWith(".") || name.startsWith("/") ? name : `./${name}`;
1542
+ return import(
1543
+ /* @vite-ignore */
1544
+ /* webpackIgnore: true */
1545
+ importPath
1546
+ ).then((mod) => {
1547
+ return mod && (mod["__esModule"] || // For Webpack
1548
+ typeof mod["default"] === "function") ? mod["default"] : mod;
1549
+ }).catch((err) => {
1550
+ const errorHandler = config.error;
1551
+ if (errorHandler) {
1552
+ errorHandler(err instanceof Error ? err : new Error(String(err)));
1553
+ }
1554
+ return void 0;
1555
+ });
1556
+ })
1557
+ );
1558
+ })();
1559
+ if (callback) {
1560
+ loadPromise.then((modules) => {
1561
+ callback(...modules);
1562
+ });
1563
+ }
1564
+ return loadPromise;
1565
+ }
1566
+
1468
1567
  // src/dom.ts
1469
1568
  var wrapMeta = {
1470
1569
  option: [1, "<select multiple>"],
@@ -1540,13 +1639,11 @@ function domGetCompareKey(node) {
1540
1639
  function domSpecialDiff(oldNode, newNode) {
1541
1640
  const specials = DomSpecials[oldNode.nodeName];
1542
1641
  if (!specials) return 0;
1543
- const oldEl = oldNode;
1544
- const newEl = newNode;
1545
1642
  let result = 0;
1546
1643
  for (const prop of specials) {
1547
- if (oldEl[prop] !== newEl[prop]) {
1644
+ if (Reflect.get(oldNode, prop) !== Reflect.get(newNode, prop)) {
1548
1645
  result = 1;
1549
- oldEl[prop] = newEl[prop];
1646
+ Reflect.set(oldNode, prop, Reflect.get(newNode, prop));
1550
1647
  }
1551
1648
  }
1552
1649
  return result;
@@ -1727,57 +1824,530 @@ function applyIdUpdates(updates) {
1727
1824
  }
1728
1825
  }
1729
1826
  }
1730
- var EncoderMap = {
1731
- "&": "amp",
1732
- "<": "lt",
1733
- ">": "gt",
1734
- '"': "#34",
1735
- "'": "#39",
1736
- "`": "#96"
1827
+
1828
+ // src/vdom.ts
1829
+ var DOM_SPECIALS = {
1830
+ INPUT: ["value", "checked"],
1831
+ TEXTAREA: ["value"],
1832
+ OPTION: ["selected"]
1737
1833
  };
1738
- var ENCODE_REGEXP = /[&<>"'`]/g;
1739
- function encodeHTML(v) {
1740
- return String(v == null ? "" : v).replace(
1741
- ENCODE_REGEXP,
1742
- (m) => "&" + EncoderMap[m] + ";"
1743
- );
1834
+ function vdomCreate(tag, props, children, specials) {
1835
+ if (!tag) {
1836
+ return {
1837
+ tag: children ? SPLITTER : V_TEXT_NODE,
1838
+ html: String(props ?? "")
1839
+ };
1840
+ }
1841
+ const propsObj = props || {};
1842
+ const specialsObj = specials || {};
1843
+ const unary = children === 1;
1844
+ let compareKey;
1845
+ let innerHTML = "";
1846
+ let newChildren;
1847
+ let reused;
1848
+ let reusedTotal = 0;
1849
+ let viewList;
1850
+ let isLarkView2;
1851
+ let attrs = `<${tag}`;
1852
+ let hasSpecials;
1853
+ let prevChild;
1854
+ if (children && children !== 1) {
1855
+ for (const c of children) {
1856
+ if (c.attrs !== void 0) {
1857
+ innerHTML += c.attrs + (c.selfClose ? "/>" : `>${c.html}</${c.tag}>`);
1858
+ } else {
1859
+ if (c.tag === V_TEXT_NODE) {
1860
+ innerHTML += encodeHTML(c.html);
1861
+ } else {
1862
+ innerHTML += c.html;
1863
+ }
1864
+ }
1865
+ if (c.tag === V_TEXT_NODE && prevChild && prevChild.tag === V_TEXT_NODE) {
1866
+ prevChild.html += c.html;
1867
+ } else {
1868
+ if (!newChildren) newChildren = [];
1869
+ newChildren.push(c);
1870
+ prevChild = c;
1871
+ }
1872
+ if (c.compareKey) {
1873
+ if (!reused) reused = {};
1874
+ reused[c.compareKey] = (reused[c.compareKey] || 0) + 1;
1875
+ reusedTotal++;
1876
+ }
1877
+ if (c.views) {
1878
+ if (!viewList) viewList = [];
1879
+ viewList.push(...c.views);
1880
+ }
1881
+ }
1882
+ }
1883
+ hasSpecials = specials || void 0;
1884
+ for (const prop in propsObj) {
1885
+ let value = propsObj[prop];
1886
+ if (value === false || value == null) {
1887
+ if (!specialsObj[prop]) {
1888
+ delete propsObj[prop];
1889
+ }
1890
+ continue;
1891
+ } else if (value === true) {
1892
+ propsObj[prop] = value = specialsObj[prop] ? value : "";
1893
+ }
1894
+ if ((prop === "#" || prop === "id" || prop === TAG_STATIC_KEY) && !compareKey) {
1895
+ compareKey = value;
1896
+ if (prop !== "id") {
1897
+ delete propsObj[prop];
1898
+ continue;
1899
+ }
1900
+ }
1901
+ if (prop === LARK_VIEW && value) {
1902
+ const parsed = parseUri(value);
1903
+ isLarkView2 = parsed.path;
1904
+ if (!viewList) viewList = [];
1905
+ viewList.push([
1906
+ isLarkView2,
1907
+ propsObj["lark-owner"],
1908
+ value,
1909
+ parsed.params
1910
+ ]);
1911
+ if (!compareKey) {
1912
+ compareKey = tag + SPLITTER + isLarkView2;
1913
+ }
1914
+ }
1915
+ if (prop === "value" && tag === "textarea") {
1916
+ innerHTML = String(value);
1917
+ delete propsObj[prop];
1918
+ continue;
1919
+ }
1920
+ attrs += ` ${prop}="${value && encodeHTML(value)}"`;
1921
+ }
1922
+ return {
1923
+ tag,
1924
+ html: innerHTML,
1925
+ attrs,
1926
+ attrsMap: propsObj,
1927
+ attrsSpecials: specialsObj,
1928
+ hasSpecials,
1929
+ children: newChildren,
1930
+ compareKey,
1931
+ reused,
1932
+ reusedTotal,
1933
+ views: viewList,
1934
+ selfClose: unary,
1935
+ isLarkView: isLarkView2
1936
+ };
1744
1937
  }
1745
- function encodeSafe(v) {
1746
- return String(v == null ? "" : v);
1938
+ function isSameVDomNode(a, b) {
1939
+ return a.compareKey && b.compareKey === a.compareKey || !a.compareKey && !b.compareKey && a.tag === b.tag || a.tag === SPLITTER || b.tag === SPLITTER;
1747
1940
  }
1748
- var URIMap = {
1749
- "!": "%21",
1750
- "'": "%27",
1751
- "(": "%28",
1752
- ")": "%29",
1753
- "*": "%2A"
1754
- };
1755
- var URI_ENCODE_REGEXP = /[!')(*]/g;
1756
- function encodeURIExtra(v) {
1757
- return encodeURIComponent(encodeSafe(v)).replace(
1758
- URI_ENCODE_REGEXP,
1759
- (m) => URIMap[m]
1760
- );
1941
+ function getKeyNodes(list, nodes, start, end, realEnd) {
1942
+ const keyedNodes = {};
1943
+ for (let i = end, re = realEnd; i >= start; i--, re--) {
1944
+ const oc = list[i];
1945
+ const cKey = oc.compareKey;
1946
+ if (cKey) {
1947
+ const bucket = keyedNodes[cKey] || (keyedNodes[cKey] = []);
1948
+ bucket.push(nodes[re]);
1949
+ }
1950
+ }
1951
+ return keyedNodes;
1761
1952
  }
1762
- var QUOTE_REGEXP = /['"\\]/g;
1763
- function encodeQ(v) {
1764
- return encodeSafe(v).replace(QUOTE_REGEXP, "\\$&");
1953
+ function vdomCreateNode(vnode, owner, ref) {
1954
+ const tag = vnode.tag;
1955
+ if (tag === V_TEXT_NODE) {
1956
+ return document.createTextNode(vnode.html);
1957
+ }
1958
+ const sTag = typeof tag === "string" ? tag : tag.toString();
1959
+ const ns = VDOM_NS_MAP[sTag] || owner.namespaceURI;
1960
+ const el = document.createElementNS(ns, sTag);
1961
+ vdomSetAttributes(el, vnode, ref);
1962
+ el.innerHTML = vnode.html;
1963
+ return el;
1765
1964
  }
1766
-
1767
- // src/updater.ts
1768
- function updaterRef(refDataIn, value, key) {
1769
- const refData = refDataIn;
1770
- const counter = refData[SPLITTER];
1771
- for (let i = counter; --i; ) {
1772
- key = SPLITTER + i;
1773
- if (refData[key] === value) {
1774
- return key;
1965
+ function vdomSetAttributes(realNode, newVDom, ref, lastVDom) {
1966
+ let changed = 0;
1967
+ const nMap = newVDom.attrsMap || {};
1968
+ const nsMap = newVDom.attrsSpecials || {};
1969
+ if (lastVDom) {
1970
+ const oMap = lastVDom.attrsMap || {};
1971
+ const osMap = lastVDom.attrsSpecials || {};
1972
+ for (const key in oMap) {
1973
+ if (!hasOwnProperty(nMap, key)) {
1974
+ changed = 1;
1975
+ const sValue = osMap[key];
1976
+ if (sValue) {
1977
+ if (ref) {
1978
+ ref.nodeProps.push([realNode, sValue, ""]);
1979
+ } else {
1980
+ Reflect.set(realNode, sValue, "");
1981
+ }
1982
+ } else {
1983
+ realNode.removeAttribute(key);
1984
+ }
1985
+ }
1775
1986
  }
1776
1987
  }
1777
- key = SPLITTER + refData[SPLITTER]++;
1778
- refData[key] = value;
1779
- return key;
1988
+ for (const key in nMap) {
1989
+ const value = nMap[key];
1990
+ const sKey = nsMap[key];
1991
+ if (sKey) {
1992
+ if (Reflect.get(realNode, sKey) !== value) {
1993
+ changed = 1;
1994
+ if (ref) {
1995
+ ref.nodeProps.push([realNode, sKey, value]);
1996
+ } else {
1997
+ Reflect.set(realNode, sKey, value);
1998
+ }
1999
+ }
2000
+ } else {
2001
+ const oldMap = lastVDom?.attrsMap;
2002
+ if (!oldMap || oldMap[key] !== value) {
2003
+ changed = 1;
2004
+ realNode.setAttribute(key, String(value ?? ""));
2005
+ }
2006
+ }
2007
+ }
2008
+ return changed;
2009
+ }
2010
+ function vdomSyncFormState(realNode, newVDom) {
2011
+ const specials = DOM_SPECIALS[realNode.nodeName];
2012
+ if (!specials) return 0;
2013
+ const nMap = newVDom.attrsMap || {};
2014
+ let result = 0;
2015
+ for (const prop of specials) {
2016
+ const newVal = nMap[prop];
2017
+ if (newVal !== void 0 && Reflect.get(realNode, prop) !== newVal) {
2018
+ result = 1;
2019
+ Reflect.set(realNode, prop, newVal);
2020
+ }
2021
+ }
2022
+ return result;
2023
+ }
2024
+ function vdomSetNode(realNode, oldParent, lastVDom, newVDom, ref, frame, keys2, rootView, ready) {
2025
+ const lastTag = lastVDom.tag;
2026
+ const newTag = newVDom.tag;
2027
+ if (lastTag === V_TEXT_NODE || newTag === V_TEXT_NODE) {
2028
+ if (lastTag === newTag) {
2029
+ if (lastVDom.html !== newVDom.html) {
2030
+ ref.changed = 1;
2031
+ realNode.nodeValue = newVDom.html;
2032
+ }
2033
+ } else {
2034
+ ref.changed = 1;
2035
+ domUnmountFrames(frame, realNode);
2036
+ oldParent.replaceChild(vdomCreateNode(newVDom, oldParent, ref), realNode);
2037
+ }
2038
+ return;
2039
+ }
2040
+ if (lastTag === newTag) {
2041
+ const lastAMap = lastVDom.attrsMap || {};
2042
+ const newAMap = newVDom.attrsMap || {};
2043
+ if (lastVDom.compareKey && lastVDom.compareKey === newVDom.compareKey && !lastAMap["id"] && !newAMap["id"]) {
2044
+ return;
2045
+ }
2046
+ let attrChanged = 0;
2047
+ if (lastVDom.attrs !== newVDom.attrs || newVDom.hasSpecials) {
2048
+ attrChanged = vdomSetAttributes(
2049
+ realNode,
2050
+ newVDom,
2051
+ ref,
2052
+ lastVDom
2053
+ );
2054
+ if (attrChanged) ref.changed = 1;
2055
+ }
2056
+ let updateChildren = true;
2057
+ if (newVDom.isLarkView) {
2058
+ const oldFrameId = realNode.getAttribute("id") || "";
2059
+ const newViewPath = newVDom.isLarkView;
2060
+ const oldViewPath = lastVDom.isLarkView || "";
2061
+ if (oldFrameId && newViewPath === oldViewPath) {
2062
+ updateChildren = false;
2063
+ }
2064
+ }
2065
+ vdomSyncFormState(realNode, newVDom);
2066
+ if (updateChildren && !newVDom.selfClose) {
2067
+ vdomSetChildNodes(
2068
+ realNode,
2069
+ lastVDom,
2070
+ newVDom,
2071
+ ref,
2072
+ frame,
2073
+ keys2,
2074
+ rootView,
2075
+ ready
2076
+ );
2077
+ }
2078
+ } else {
2079
+ ref.changed = 1;
2080
+ domUnmountFrames(frame, realNode);
2081
+ oldParent.replaceChild(vdomCreateNode(newVDom, oldParent, ref), realNode);
2082
+ }
2083
+ }
2084
+ function vdomSetChildNodes(realNode, lastVDom, newVDom, ref, frame, keys2, view, ready) {
2085
+ if (!lastVDom) {
2086
+ ref.changed = 1;
2087
+ realNode.innerHTML = newVDom.html;
2088
+ return;
2089
+ }
2090
+ if (lastVDom.html === newVDom.html) {
2091
+ return;
2092
+ }
2093
+ const oldChildren = lastVDom.children;
2094
+ const newChildren = newVDom.children;
2095
+ const oldLen = oldChildren?.length || 0;
2096
+ const newLen = newChildren?.length || 0;
2097
+ if (oldLen === 0 && newLen === 0) return;
2098
+ const nodes = realNode.childNodes;
2099
+ let oldStart = 0;
2100
+ let oldEnd = oldLen - 1;
2101
+ let newStart = 0;
2102
+ let newEnd = newLen - 1;
2103
+ let realStart = oldStart;
2104
+ let realEnd = oldEnd;
2105
+ let keyedNodes;
2106
+ const oldReusedTotal = lastVDom.reusedTotal || 0;
2107
+ const newReusedTotal = newVDom.reusedTotal || 0;
2108
+ let oldStartNode = oldChildren?.[oldStart];
2109
+ let oldEndNode = oldChildren?.[oldEnd];
2110
+ let newStartNode = newChildren?.[newStart];
2111
+ let newEndNode = newChildren?.[newEnd];
2112
+ while (oldStart <= oldEnd && newStart <= newEnd) {
2113
+ if (!oldStartNode) {
2114
+ oldStartNode = oldChildren?.[++oldStart];
2115
+ realStart++;
2116
+ continue;
2117
+ }
2118
+ if (!oldEndNode) {
2119
+ oldEndNode = oldChildren?.[--oldEnd];
2120
+ realEnd--;
2121
+ continue;
2122
+ }
2123
+ if (isSameVDomNode(newStartNode, oldStartNode)) {
2124
+ if (newStartNode.tag === SPLITTER || oldStartNode.tag === SPLITTER) {
2125
+ ref.changed = 1;
2126
+ domUnmountFrames(frame, realNode);
2127
+ if (newStartNode.tag === SPLITTER) {
2128
+ realNode.innerHTML = newStartNode.html;
2129
+ } else {
2130
+ realNode.innerHTML = "";
2131
+ realNode.appendChild(vdomCreateNode(newStartNode, realNode, ref));
2132
+ }
2133
+ } else {
2134
+ vdomSetNode(
2135
+ nodes[realStart],
2136
+ realNode,
2137
+ oldStartNode,
2138
+ newStartNode,
2139
+ ref,
2140
+ frame,
2141
+ keys2,
2142
+ view,
2143
+ ready
2144
+ );
2145
+ }
2146
+ reduceCached(keyedNodes, oldStartNode, nodes[realStart]);
2147
+ realStart++;
2148
+ oldStartNode = oldChildren?.[++oldStart];
2149
+ newStartNode = newChildren?.[++newStart];
2150
+ } else if (isSameVDomNode(newEndNode, oldEndNode)) {
2151
+ if (newEndNode.tag === SPLITTER || oldEndNode.tag === SPLITTER) {
2152
+ ref.changed = 1;
2153
+ domUnmountFrames(frame, realNode);
2154
+ realNode.innerHTML = newEndNode.tag === SPLITTER ? newEndNode.html : "";
2155
+ if (newEndNode.tag !== SPLITTER) {
2156
+ realNode.appendChild(vdomCreateNode(newEndNode, realNode, ref));
2157
+ }
2158
+ } else {
2159
+ vdomSetNode(
2160
+ nodes[realEnd],
2161
+ realNode,
2162
+ oldEndNode,
2163
+ newEndNode,
2164
+ ref,
2165
+ frame,
2166
+ keys2,
2167
+ view,
2168
+ ready
2169
+ );
2170
+ }
2171
+ reduceCached(keyedNodes, oldEndNode, nodes[realEnd]);
2172
+ realEnd--;
2173
+ oldEndNode = oldChildren?.[--oldEnd];
2174
+ newEndNode = newChildren?.[--newEnd];
2175
+ } else if (isSameVDomNode(newEndNode, oldStartNode)) {
2176
+ if (newEndNode.tag === SPLITTER || oldStartNode.tag === SPLITTER) {
2177
+ ref.changed = 1;
2178
+ domUnmountFrames(frame, realNode);
2179
+ realNode.innerHTML = newEndNode.tag === SPLITTER ? newEndNode.html : "";
2180
+ if (newEndNode.tag !== SPLITTER) {
2181
+ realNode.appendChild(vdomCreateNode(newEndNode, realNode, ref));
2182
+ }
2183
+ } else {
2184
+ const oi = nodes[realStart];
2185
+ realNode.insertBefore(oi, nodes[realEnd + 1] || null);
2186
+ vdomSetNode(
2187
+ oi,
2188
+ realNode,
2189
+ oldStartNode,
2190
+ newEndNode,
2191
+ ref,
2192
+ frame,
2193
+ keys2,
2194
+ view,
2195
+ ready
2196
+ );
2197
+ }
2198
+ reduceCached(keyedNodes, oldStartNode, nodes[realStart]);
2199
+ realStart++;
2200
+ oldStartNode = oldChildren?.[++oldStart];
2201
+ newEndNode = newChildren?.[--newEnd];
2202
+ } else if (isSameVDomNode(newStartNode, oldEndNode)) {
2203
+ if (newStartNode.tag === SPLITTER || oldEndNode.tag === SPLITTER) {
2204
+ ref.changed = 1;
2205
+ domUnmountFrames(frame, realNode);
2206
+ realNode.innerHTML = newStartNode.tag === SPLITTER ? newStartNode.html : "";
2207
+ if (newStartNode.tag !== SPLITTER) {
2208
+ realNode.appendChild(vdomCreateNode(newStartNode, realNode, ref));
2209
+ }
2210
+ } else {
2211
+ const oi = nodes[realEnd];
2212
+ realNode.insertBefore(oi, nodes[realStart]);
2213
+ vdomSetNode(
2214
+ oi,
2215
+ realNode,
2216
+ oldEndNode,
2217
+ newStartNode,
2218
+ ref,
2219
+ frame,
2220
+ keys2,
2221
+ view,
2222
+ ready
2223
+ );
2224
+ }
2225
+ reduceCached(keyedNodes, oldEndNode, nodes[realEnd]);
2226
+ realEnd--;
2227
+ oldEndNode = oldChildren?.[--oldEnd];
2228
+ newStartNode = newChildren?.[++newStart];
2229
+ } else {
2230
+ if (!keyedNodes && newReusedTotal > 0 && oldReusedTotal > 0) {
2231
+ keyedNodes = getKeyNodes(
2232
+ oldChildren,
2233
+ nodes,
2234
+ oldStart,
2235
+ oldEnd,
2236
+ realEnd
2237
+ );
2238
+ }
2239
+ const cKey = newStartNode.compareKey;
2240
+ let found;
2241
+ let compareKey;
2242
+ if (cKey && keyedNodes) {
2243
+ found = keyedNodes[cKey];
2244
+ compareKey = void 0;
2245
+ while (found && found.length > 0) {
2246
+ compareKey = found.pop();
2247
+ if (compareKey) break;
2248
+ }
2249
+ if (found && found.length === 0) delete keyedNodes[cKey];
2250
+ }
2251
+ if (compareKey) {
2252
+ if (compareKey !== nodes[realStart]) {
2253
+ for (let j = oldStart + 1; j <= oldEnd; j++) {
2254
+ const oc = oldChildren?.[j];
2255
+ if (oc && nodes[realStart + (j - oldStart)] === compareKey) {
2256
+ oldChildren[j] = void 0;
2257
+ break;
2258
+ }
2259
+ }
2260
+ realNode.insertBefore(compareKey, nodes[realStart]);
2261
+ }
2262
+ vdomSetNode(
2263
+ compareKey,
2264
+ realNode,
2265
+ oldStartNode,
2266
+ newStartNode,
2267
+ ref,
2268
+ frame,
2269
+ keys2,
2270
+ view,
2271
+ ready
2272
+ );
2273
+ } else if (oldStartNode.compareKey && lastVDom.reused?.[oldStartNode.compareKey] && newVDom.reused?.[oldStartNode.compareKey] || nodes[realStart]?.id && realNode.querySelectorAll?.(
2274
+ `#${nodes[realStart].id}`
2275
+ )?.length && !newStartNode.isLarkView) {
2276
+ ref.changed = 1;
2277
+ const newNode = vdomCreateNode(newStartNode, realNode, ref);
2278
+ realNode.insertBefore(newNode, nodes[realStart]);
2279
+ realStart--;
2280
+ realEnd++;
2281
+ } else {
2282
+ vdomSetNode(
2283
+ nodes[realStart],
2284
+ realNode,
2285
+ oldStartNode,
2286
+ newStartNode,
2287
+ ref,
2288
+ frame,
2289
+ keys2,
2290
+ view,
2291
+ ready
2292
+ );
2293
+ }
2294
+ realStart++;
2295
+ oldStartNode = oldChildren?.[++oldStart];
2296
+ newStartNode = newChildren?.[++newStart];
2297
+ }
2298
+ }
2299
+ if (newStart <= newEnd) {
2300
+ const refNode = nodes[realEnd + 1] || null;
2301
+ for (let i = newStart; i <= newEnd; i++) {
2302
+ ref.changed = 1;
2303
+ const nc = newChildren[i];
2304
+ if (nc.tag === SPLITTER) {
2305
+ domUnmountFrames(frame, realNode);
2306
+ realNode.innerHTML = nc.html;
2307
+ return;
2308
+ }
2309
+ const newNode = vdomCreateNode(nc, realNode, ref);
2310
+ realNode.insertBefore(newNode, refNode);
2311
+ }
2312
+ }
2313
+ if (oldStart <= oldEnd) {
2314
+ for (let i = realEnd; i >= realStart; i--) {
2315
+ const node = nodes[i];
2316
+ if (node) {
2317
+ domUnmountFrames(frame, node);
2318
+ ref.changed = 1;
2319
+ realNode.removeChild(node);
2320
+ }
2321
+ }
2322
+ }
2323
+ if (ref.asyncCount === 0) {
2324
+ callFunction(ready, []);
2325
+ }
1780
2326
  }
2327
+ function reduceCached(keyedNodes, node, compared) {
2328
+ if (!keyedNodes || !node.compareKey) return;
2329
+ const bucket = keyedNodes[node.compareKey];
2330
+ if (bucket) {
2331
+ for (let i = bucket.length; i--; ) {
2332
+ if (bucket[i] === compared) {
2333
+ bucket[i] = void 0;
2334
+ break;
2335
+ }
2336
+ }
2337
+ }
2338
+ }
2339
+ function createVDomRef(viewId) {
2340
+ return {
2341
+ viewId,
2342
+ viewRenders: [],
2343
+ nodeProps: [],
2344
+ asyncCount: 0,
2345
+ changed: 0,
2346
+ domOps: []
2347
+ };
2348
+ }
2349
+
2350
+ // src/updater.ts
1781
2351
  var Updater = class {
1782
2352
  /** View ID (same as owner frame ID) */
1783
2353
  viewId;
@@ -1799,6 +2369,8 @@ var Updater = class {
1799
2369
  version = 0;
1800
2370
  /** Snapshot of `version` taken by `snapshot()`, used by `altered()`. */
1801
2371
  snapshotVersion;
2372
+ /** Last rendered VDOM tree (only used when virtualDom is enabled) */
2373
+ vdom;
1802
2374
  constructor(viewId) {
1803
2375
  this.viewId = viewId;
1804
2376
  this.data = { vId: viewId };
@@ -1878,28 +2450,61 @@ var Updater = class {
1878
2450
  if (changed && view && node && view.signature > 0 && frame) {
1879
2451
  const template = view.template;
1880
2452
  if (typeof template === "function") {
1881
- const html = template(
1882
- this.data,
1883
- this.viewId,
1884
- this.refData,
1885
- encodeHTML,
1886
- encodeSafe,
1887
- encodeURIExtra,
1888
- updaterRef,
1889
- encodeQ
1890
- );
1891
- const newDom = domGetNode(html, node);
1892
- const ref = createDomRef();
1893
- domSetChildNodes(node, newDom, ref, frame, keys2);
1894
- applyIdUpdates(ref.idUpdates);
1895
- applyDomOps(ref.domOps);
1896
- for (const v of ref.views) {
1897
- if (v.render) {
1898
- funcWithTry(v.render, [], v, noop);
2453
+ if (config.virtualDom) {
2454
+ const vdomTemplate = template;
2455
+ const newVDom = vdomTemplate(this.data, this.viewId, this.refData);
2456
+ const ref = createVDomRef(this.viewId);
2457
+ const ready = () => {
2458
+ this.vdom = newVDom;
2459
+ if (ref.changed || !view.rendered) {
2460
+ view.endUpdate(this.viewId);
2461
+ }
2462
+ for (const [el, prop, val] of ref.nodeProps) {
2463
+ Reflect.set(el, prop, val);
2464
+ }
2465
+ for (const v of ref.viewRenders) {
2466
+ if (v.render) {
2467
+ funcWithTry(v.render, [], v, noop);
2468
+ }
2469
+ }
2470
+ };
2471
+ vdomSetChildNodes(
2472
+ node,
2473
+ this.vdom,
2474
+ newVDom,
2475
+ ref,
2476
+ frame,
2477
+ keys2,
2478
+ view,
2479
+ ready
2480
+ );
2481
+ if (ref.asyncCount === 0) {
2482
+ ready();
2483
+ }
2484
+ } else {
2485
+ const html = template(
2486
+ this.data,
2487
+ this.viewId,
2488
+ this.refData,
2489
+ encodeHTML,
2490
+ strSafe,
2491
+ encodeURIExtra,
2492
+ refFn,
2493
+ encodeQuote
2494
+ );
2495
+ const newDom = domGetNode(html, node);
2496
+ const ref = createDomRef();
2497
+ domSetChildNodes(node, newDom, ref, frame, keys2);
2498
+ applyIdUpdates(ref.idUpdates);
2499
+ applyDomOps(ref.domOps);
2500
+ for (const v of ref.views) {
2501
+ if (v.render) {
2502
+ funcWithTry(v.render, [], v, noop);
2503
+ }
2504
+ }
2505
+ if (ref.hasChanged || !view.rendered) {
2506
+ view.endUpdate(this.viewId);
1899
2507
  }
1900
- }
1901
- if (ref.hasChanged || !view.rendered) {
1902
- view.endUpdate(this.viewId);
1903
2508
  }
1904
2509
  }
1905
2510
  }
@@ -1933,17 +2538,12 @@ var Updater = class {
1933
2538
  * Translate a refData reference back to its original value.
1934
2539
  *
1935
2540
  * The ref protocol is `SPLITTER` + ascii decimal digits — the exact format
1936
- * emitted by `updaterRef`. We require that exact shape so a user-supplied
2541
+ * emitted by `refFn`. We require that exact shape so a user-supplied
1937
2542
  * string that merely begins with SPLITTER is never accidentally resolved
1938
2543
  * (or mishandled as a "missing ref").
1939
2544
  */
1940
2545
  translate(data) {
1941
- if (typeof data !== "string") return data;
1942
- if (data.length < 2 || data[0] !== SPLITTER) return data;
1943
- for (let i = 1; i < data.length; i++) {
1944
- const c = data.charCodeAt(i);
1945
- if (c < 48 || c > 57) return data;
1946
- }
2546
+ if (typeof data !== "string" || !isRefToken(data)) return data;
1947
2547
  return hasOwnProperty(this.refData, data) ? this.refData[data] : data;
1948
2548
  }
1949
2549
  /**
@@ -2010,8 +2610,6 @@ var View = class _View {
2010
2610
  observedStateKeys;
2011
2611
  /** Resource map */
2012
2612
  resources = {};
2013
- /** Assign method reference */
2014
- assignMethod;
2015
2613
  /** Whether endUpdate pending */
2016
2614
  endUpdatePending;
2017
2615
  /** Internal event storage */
@@ -2088,7 +2686,7 @@ var View = class _View {
2088
2686
  */
2089
2687
  beginUpdate(id) {
2090
2688
  if (this.signature > 0 && this.endUpdatePending !== void 0) {
2091
- this.ownerFrame.unmountZone(id, true);
2689
+ this.ownerFrame.unmountZone(id);
2092
2690
  }
2093
2691
  }
2094
2692
  /**
@@ -2107,7 +2705,7 @@ var View = class _View {
2107
2705
  this.rendered = true;
2108
2706
  }
2109
2707
  const ownerFrame = this.ownerFrame;
2110
- ownerFrame.mountZone(updateId, inner);
2708
+ ownerFrame.mountZone(updateId);
2111
2709
  if (!flag) {
2112
2710
  setTimeout(
2113
2711
  this.wrapAsync(() => {
@@ -2257,17 +2855,16 @@ var View = class _View {
2257
2855
  }
2258
2856
  const makes = [];
2259
2857
  oView.makes = makes;
2260
- const proto = oView.prototype;
2261
2858
  const eventsObject = {};
2262
2859
  const eventsList = [];
2263
2860
  const selectorObject = {};
2264
- const mixins = proto["mixins"];
2861
+ const mixins = Reflect.get(oView.prototype, "mixins");
2265
2862
  if (mixins && Array.isArray(mixins)) {
2266
2863
  _View.mergeMixins(mixins, oView, makes);
2267
2864
  }
2268
- for (const p in proto) {
2269
- if (!hasOwnProperty(proto, p)) continue;
2270
- const currentFn = proto[p];
2865
+ for (const p in oView.prototype) {
2866
+ if (!hasOwnProperty(oView.prototype, p)) continue;
2867
+ const currentFn = Reflect.get(oView.prototype, p);
2271
2868
  if (typeof currentFn !== "function") continue;
2272
2869
  const matches = p.match(VIEW_EVENT_METHOD_REGEXP);
2273
2870
  if (!matches) continue;
@@ -2309,30 +2906,30 @@ var View = class _View {
2309
2906
  }
2310
2907
  eventsObject[item] = (eventsObject[item] || 0) | mask;
2311
2908
  const combinedKey = selectorOrCallback + SPLITTER + item;
2312
- const existingFn = proto[combinedKey];
2909
+ const existingFn = Reflect.get(oView.prototype, combinedKey);
2313
2910
  if (!existingFn) {
2314
- proto[combinedKey] = currentFn;
2911
+ Reflect.set(oView.prototype, combinedKey, currentFn);
2315
2912
  } else if (typeof existingFn === "function") {
2316
2913
  const mixinFn = currentFn;
2317
2914
  const existingMixin = existingFn;
2318
2915
  if (existingMixin.marker) {
2319
2916
  if (mixinFn.marker) {
2320
- proto[combinedKey] = _View.processMixinsSameEvent(
2321
- mixinFn,
2322
- existingMixin
2917
+ Reflect.set(
2918
+ oView.prototype,
2919
+ combinedKey,
2920
+ _View.processMixinsSameEvent(mixinFn, existingMixin)
2323
2921
  );
2324
- } else if (hasOwnProperty(proto, p)) {
2325
- proto[combinedKey] = currentFn;
2922
+ } else if (hasOwnProperty(oView.prototype, p)) {
2923
+ Reflect.set(oView.prototype, combinedKey, currentFn);
2326
2924
  }
2327
2925
  }
2328
2926
  }
2329
2927
  }
2330
2928
  }
2331
- _View.wrapMethod(proto, "render", "$renderWrap");
2332
- proto["$evtObjMap"] = eventsObject;
2333
- proto["$globalEvtList"] = eventsList;
2334
- proto["$selMap"] = selectorObject;
2335
- proto["$assignFn"] = proto["assign"];
2929
+ _View.wrapMethod(asRecord(oView.prototype), "render", "$renderWrap");
2930
+ Reflect.set(oView.prototype, "$evtObjMap", eventsObject);
2931
+ Reflect.set(oView.prototype, "$globalEvtList", eventsList);
2932
+ Reflect.set(oView.prototype, "$selMap", selectorObject);
2336
2933
  return makes;
2337
2934
  }
2338
2935
  /**
@@ -2423,7 +3020,7 @@ var View = class _View {
2423
3020
  this.signature++;
2424
3021
  this.fire("render");
2425
3022
  _View.destroyAllResources(this, false);
2426
- const lookup = this;
3023
+ const lookup = asRecord(this);
2427
3024
  const candidate = lookup[fnName];
2428
3025
  const instanceFn = typeof candidate === "function" ? candidate : originalAsFn;
2429
3026
  const fnToCall = instanceFn === wrapped ? originalAsFn : instanceFn;
@@ -2459,7 +3056,7 @@ var View = class _View {
2459
3056
  * Merge an array of mixin objects into the view prototype.
2460
3057
  */
2461
3058
  static mergeMixins(mixins, viewClass, makes) {
2462
- const proto = viewClass.prototype;
3059
+ const proto = asRecord(viewClass.prototype);
2463
3060
  const temp = {};
2464
3061
  for (const node of mixins) {
2465
3062
  for (const p in node) {
@@ -2550,17 +3147,15 @@ var View = class _View {
2550
3147
  }
2551
3148
  }
2552
3149
  };
2553
- const proto = ChildView.prototype;
2554
3150
  for (const key in definedProps) {
2555
3151
  if (hasOwnProperty(definedProps, key) && key !== "make") {
2556
- proto[key] = definedProps[key];
3152
+ Reflect.set(ChildView.prototype, key, definedProps[key]);
2557
3153
  }
2558
3154
  }
2559
3155
  if (statics) {
2560
- const staticTarget = ChildView;
2561
3156
  for (const key in statics) {
2562
3157
  if (hasOwnProperty(statics, key)) {
2563
- staticTarget[key] = statics[key];
3158
+ Reflect.set(ChildView, key, statics[key]);
2564
3159
  }
2565
3160
  }
2566
3161
  }
@@ -2579,53 +3174,6 @@ function defineView(props, statics) {
2579
3174
  return View.extend(props, statics);
2580
3175
  }
2581
3176
 
2582
- // src/module-loader.ts
2583
- var config = {
2584
- rootId: "root",
2585
- routeMode: "history",
2586
- hashbang: "#!",
2587
- error: (error) => {
2588
- throw error;
2589
- }
2590
- };
2591
- function use(names, callback) {
2592
- const nameList = typeof names === "string" ? [names] : names;
2593
- const loadPromise = (() => {
2594
- if (config.require) {
2595
- const result = config.require(nameList);
2596
- if (result && typeof result.then === "function") {
2597
- return result;
2598
- }
2599
- return Promise.resolve([]);
2600
- }
2601
- return Promise.all(
2602
- nameList.map((name) => {
2603
- const importPath = name.startsWith(".") || name.startsWith("/") ? name : `./${name}`;
2604
- return import(
2605
- /* @vite-ignore */
2606
- /* webpackIgnore: true */
2607
- importPath
2608
- ).then((mod) => {
2609
- return mod && (mod["__esModule"] || // For Webpack
2610
- typeof mod["default"] === "function") ? mod["default"] : mod;
2611
- }).catch((err) => {
2612
- const errorHandler = config.error;
2613
- if (errorHandler) {
2614
- errorHandler(err instanceof Error ? err : new Error(String(err)));
2615
- }
2616
- return void 0;
2617
- });
2618
- })
2619
- );
2620
- })();
2621
- if (callback) {
2622
- loadPromise.then((modules) => {
2623
- callback(...modules);
2624
- });
2625
- }
2626
- return loadPromise;
2627
- }
2628
-
2629
3177
  // src/view-registry.ts
2630
3178
  var viewClassRegistry = {};
2631
3179
  function getViewClass(path) {
@@ -2772,9 +3320,15 @@ var Frame = class _Frame extends EventEmitter {
2772
3320
  */
2773
3321
  doMountView(ViewClass, params, node, sign) {
2774
3322
  if (sign !== this.signature) return;
2775
- const mixinCtors = View.prepare(ViewClass);
2776
- const Ctor = ViewClass;
2777
- const view = new Ctor(this.id, this, params, node, mixinCtors);
3323
+ const mixinConstructors = View.prepare(ViewClass);
3324
+ const Constructor = ViewClass;
3325
+ const view = new Constructor(
3326
+ this.id,
3327
+ this,
3328
+ params,
3329
+ node,
3330
+ mixinConstructors
3331
+ );
2778
3332
  this.viewInstance = view;
2779
3333
  view.signature = 1;
2780
3334
  View.delegateEvents(view);
@@ -2846,7 +3400,7 @@ var Frame = class _Frame extends EventEmitter {
2846
3400
  /**
2847
3401
  * Unmount a child frame.
2848
3402
  */
2849
- unmountFrame(id, _inner) {
3403
+ unmountFrame(id) {
2850
3404
  const targetId = id ? this.childrenMap[id] : this.id;
2851
3405
  const frame = frameRegistry.get(targetId);
2852
3406
  if (!frame) return;
@@ -2868,7 +3422,7 @@ var Frame = class _Frame extends EventEmitter {
2868
3422
  /**
2869
3423
  * Mount all views in a zone.
2870
3424
  */
2871
- mountZone(zoneId, _inner) {
3425
+ mountZone(zoneId) {
2872
3426
  const targetZone = zoneId || this.id;
2873
3427
  this.holdFireCreated = 1;
2874
3428
  const rootEl = document.getElementById(targetZone);
@@ -2878,7 +3432,7 @@ var Frame = class _Frame extends EventEmitter {
2878
3432
  viewElements.forEach((el) => {
2879
3433
  if (!(el instanceof HTMLElement)) return;
2880
3434
  if (htmlElIsBound(el)) return;
2881
- const elId = ensureElementId2(el);
3435
+ const elId = ensureElementId(el, "frame_");
2882
3436
  el.frameBound = 1;
2883
3437
  const viewPath = getAttribute(el, LARK_VIEW);
2884
3438
  frames.push([elId, viewPath]);
@@ -2892,7 +3446,7 @@ var Frame = class _Frame extends EventEmitter {
2892
3446
  /**
2893
3447
  * Unmount all views in a zone.
2894
3448
  */
2895
- unmountZone(zoneId, _inner) {
3449
+ unmountZone(zoneId) {
2896
3450
  for (const childId in this.childrenMap) {
2897
3451
  if (hasOwnProperty(this.childrenMap, childId)) {
2898
3452
  if (!zoneId || childId !== zoneId) {
@@ -2935,8 +3489,7 @@ var Frame = class _Frame extends EventEmitter {
2935
3489
  let result;
2936
3490
  const view = this.view;
2937
3491
  if (view && view.rendered) {
2938
- const lookup = view;
2939
- const fn = lookup[name];
3492
+ const fn = Reflect.get(view, name);
2940
3493
  if (typeof fn === "function") {
2941
3494
  result = funcWithTry(fn, args || [], view, noop);
2942
3495
  }
@@ -3021,17 +3574,6 @@ var Frame = class _Frame extends EventEmitter {
3021
3574
  }
3022
3575
  return rootFrame;
3023
3576
  }
3024
- /**
3025
- * @deprecated Use `Frame.getRoot()` for read-only access or
3026
- * `Frame.createRoot(id)` to create the root explicitly. The single-method
3027
- * `root()` blurred the distinction and was a common source of bugs in
3028
- * Micro-Frontend hosts.
3029
- *
3030
- * Kept for backward compatibility — behavior unchanged.
3031
- */
3032
- static root(rootId) {
3033
- return _Frame.createRoot(rootId);
3034
- }
3035
3577
  /** Bind event listener (static) */
3036
3578
  static on(event, handler) {
3037
3579
  staticEmitter.on(event, handler);
@@ -3050,14 +3592,6 @@ var Frame = class _Frame extends EventEmitter {
3050
3592
  function htmlElIsBound(element) {
3051
3593
  return !!element.frameBound;
3052
3594
  }
3053
- function ensureElementId2(element) {
3054
- const id = element.getAttribute("id");
3055
- if (id) return id;
3056
- element.autoId = 1;
3057
- const newId = generateId("frame_");
3058
- element.id = newId;
3059
- return newId;
3060
- }
3061
3595
  function removeFrame(id, wasCreated) {
3062
3596
  const frameInstance = frameRegistry.get(id);
3063
3597
  if (!frameInstance) return;
@@ -3510,7 +4044,7 @@ var Service = class {
3510
4044
  }
3511
4045
  const cached = this._payloadCache.get(cacheKey);
3512
4046
  if (cached && cached.cacheInfo) {
3513
- if (now() - cached.cacheInfo.time > cache) {
4047
+ if (Date.now() - cached.cacheInfo.time > cache) {
3514
4048
  this._payloadCache.del(cacheKey);
3515
4049
  return void 0;
3516
4050
  }
@@ -3668,7 +4202,7 @@ function serviceSend(service, attrs, done, flag, save) {
3668
4202
  const list = pendingCacheKeys[cacheKey];
3669
4203
  const entity = list.entity;
3670
4204
  if (entity instanceof Payload && entity.cacheInfo) {
3671
- entity.cacheInfo.time = now();
4205
+ entity.cacheInfo.time = Date.now();
3672
4206
  internals.payloadCache.set(cacheKey, entity);
3673
4207
  }
3674
4208
  Reflect.deleteProperty(pendingCacheKeys, cacheKey);
@@ -3686,20 +4220,19 @@ function serviceSend(service, attrs, done, flag, save) {
3686
4220
  }
3687
4221
  }
3688
4222
 
3689
- // src/frame-visual.ts
3690
- var FrameVisualBridge = {
3691
- MSG_PING: "LARK_VIS_PING",
3692
- MSG_PONG: "LARK_VIS_PONG",
3693
- MSG_REQUEST_TREE: "LARK_VIS_REQUEST_TREE",
3694
- MSG_TREE: "LARK_VIS_TREE",
3695
- MSG_TREE_DELTA: "LARK_VIS_TREE_DELTA"
4223
+ // src/devtool.ts
4224
+ var FrameDevtoolBridge = {
4225
+ MSG_PING: "LARK_DEVTOOL_PING",
4226
+ MSG_PONG: "LARK_DEVTOOL_PONG",
4227
+ MSG_REQUEST_TREE: "LARK_DEVTOOL_REQUEST_TREE",
4228
+ MSG_TREE: "LARK_DEVTOOL_TREE",
4229
+ MSG_TREE_DELTA: "LARK_DEVTOOL_TREE_DELTA"
3696
4230
  };
3697
4231
  function serializeView(view) {
3698
4232
  const evtMap = view.eventObjectMap;
3699
4233
  const eventMethodKeys = evtMap ? Object.keys(evtMap) : [];
3700
4234
  const resourceKeys = view.resources ? Object.keys(view.resources) : [];
3701
- const lookup = view;
3702
- const hasAssign = typeof lookup["assign"] === "function";
4235
+ const hasAssign = typeof view["assign"] === "function";
3703
4236
  let updaterData = null;
3704
4237
  try {
3705
4238
  const ref = view.updater?.refData;
@@ -3777,7 +4310,7 @@ function serializeFrameTree() {
3777
4310
  }
3778
4311
  var bridgeInstalled = false;
3779
4312
  var lastTreeJson = "";
3780
- function installFrameVisualizerBridge() {
4313
+ function installFrameDevtoolBridge() {
3781
4314
  if (bridgeInstalled) return;
3782
4315
  if (typeof window === "undefined") return;
3783
4316
  bridgeInstalled = true;
@@ -3785,22 +4318,22 @@ function installFrameVisualizerBridge() {
3785
4318
  const data = event.data;
3786
4319
  if (!data || typeof data !== "object") return;
3787
4320
  const type = data.type;
3788
- if (type === FrameVisualBridge.MSG_PING) {
4321
+ if (type === FrameDevtoolBridge.MSG_PING) {
3789
4322
  const source = event.source;
3790
4323
  if (source) {
3791
4324
  source.postMessage(
3792
- { type: FrameVisualBridge.MSG_PONG },
4325
+ { type: FrameDevtoolBridge.MSG_PONG },
3793
4326
  { targetOrigin: "*" }
3794
4327
  );
3795
4328
  }
3796
4329
  return;
3797
4330
  }
3798
- if (type === FrameVisualBridge.MSG_REQUEST_TREE) {
4331
+ if (type === FrameDevtoolBridge.MSG_REQUEST_TREE) {
3799
4332
  const tree = serializeFrameTree();
3800
4333
  const source = event.source;
3801
4334
  if (source) {
3802
4335
  source.postMessage(
3803
- { type: FrameVisualBridge.MSG_TREE, data: tree },
4336
+ { type: FrameDevtoolBridge.MSG_TREE, data: tree },
3804
4337
  { targetOrigin: "*" }
3805
4338
  );
3806
4339
  }
@@ -3820,7 +4353,7 @@ function pushTreeUpdate() {
3820
4353
  if (treeJson !== lastTreeJson) {
3821
4354
  lastTreeJson = treeJson;
3822
4355
  window.parent.postMessage(
3823
- { type: FrameVisualBridge.MSG_TREE_DELTA, data: tree },
4356
+ { type: FrameDevtoolBridge.MSG_TREE_DELTA, data: tree },
3824
4357
  "*"
3825
4358
  );
3826
4359
  }
@@ -3833,7 +4366,7 @@ var taskIndex = 0;
3833
4366
  var taskScheduled = false;
3834
4367
  function executeTaskChunk(deadline) {
3835
4368
  const hasDeadline = !!deadline;
3836
- const startTime = now();
4369
+ const startTime = Date.now();
3837
4370
  while (true) {
3838
4371
  const fn = taskList[taskIndex];
3839
4372
  if (!fn) {
@@ -3847,7 +4380,7 @@ function executeTaskChunk(deadline) {
3847
4380
  scheduleTaskChunk();
3848
4381
  return;
3849
4382
  }
3850
- } else if (now() - startTime > CALL_BREAK_TIME && taskList.length > taskIndex + 3) {
4383
+ } else if (Date.now() - startTime > CALL_BREAK_TIME && taskList.length > taskIndex + 3) {
3851
4384
  scheduleTaskChunk();
3852
4385
  return;
3853
4386
  }
@@ -3979,10 +4512,10 @@ function waitZoneViewsRendered(viewId, timeout) {
3979
4512
  timeout = 30 * 1e3;
3980
4513
  }
3981
4514
  const checkFrame = Frame.get(viewId);
3982
- const endTime = now() + timeout;
4515
+ const endTime = Date.now() + timeout;
3983
4516
  return new Promise((resolve) => {
3984
4517
  const check = () => {
3985
- const currentTime = now();
4518
+ const currentTime = Date.now();
3986
4519
  if (currentTime > endTime || !checkFrame) {
3987
4520
  resolve(WAIT_TIMEOUT_OR_NOT_FOUND);
3988
4521
  } else if (checkFrame.childrenCount === checkFrame.readyCount) {
@@ -4044,7 +4577,7 @@ var Framework = {
4044
4577
  booted3 = true;
4045
4578
  markBooted();
4046
4579
  markRouterBooted();
4047
- installFrameVisualizerBridge();
4580
+ installFrameDevtoolBridge();
4048
4581
  const rootFrame2 = Frame.createRoot(config.rootId);
4049
4582
  Router._bind();
4050
4583
  const defaultView = config.defaultView || "";
@@ -4238,18 +4771,14 @@ function create(name, creator) {
4238
4771
  changedKeys2.add(key);
4239
4772
  }
4240
4773
  }
4241
- let recomputed = false;
4242
4774
  for (const [key, def] of computedDefs) {
4243
4775
  if (def.deps.some((dep) => changedKeys2.has(dep))) {
4244
4776
  const newVal = def.fn();
4245
4777
  if (!Object.is(state[key], newVal)) {
4246
4778
  state[key] = newVal;
4247
- recomputed = true;
4248
4779
  }
4249
4780
  }
4250
4781
  }
4251
- if (recomputed) {
4252
- }
4253
4782
  };
4254
4783
  const subscribe = (listener) => {
4255
4784
  listeners.add(listener);
@@ -4314,7 +4843,6 @@ function bindStore(view, store, selector) {
4314
4843
  view.on("destroy", off);
4315
4844
  return off;
4316
4845
  }
4317
- var defineStore = create;
4318
4846
  // Annotate the CommonJS export names for ESM import in node:
4319
4847
  0 && (module.exports = {
4320
4848
  CALL_BREAK_TIME,
@@ -4324,7 +4852,6 @@ var defineStore = create;
4324
4852
  EventDelegator,
4325
4853
  EventEmitter,
4326
4854
  Frame,
4327
- FrameVisualBridge,
4328
4855
  Framework,
4329
4856
  LARK_VIEW,
4330
4857
  Payload,
@@ -4337,59 +4864,24 @@ var defineStore = create;
4337
4864
  Updater,
4338
4865
  VIEW_EVENT_METHOD_REGEXP,
4339
4866
  View,
4340
- applyDomOps,
4341
- applyIdUpdates,
4342
4867
  applyStyle,
4343
- assign,
4344
4868
  bindStore,
4345
4869
  computed,
4346
4870
  create,
4347
- createDomRef,
4348
- defineStore,
4871
+ createVDomRef,
4349
4872
  defineView,
4350
- domGetCompareKey,
4351
- domGetNode,
4352
- domSetAttributes,
4353
- domSetChildNodes,
4354
- domSetNode,
4355
- domSpecialDiff,
4356
- domUnmountFrames,
4357
- encodeHTML,
4358
- encodeQ,
4359
- encodeSafe,
4360
- encodeURIExtra,
4361
- ensureElementId,
4362
4873
  frameworkConfig,
4363
- funcWithTry,
4364
- generateId,
4365
- getAttribute,
4366
- getById,
4367
4874
  getRouteMode,
4368
- hasOwnProperty,
4369
- installFrameVisualizerBridge,
4370
4875
  invalidateViewClass,
4371
- isPlainObject,
4372
- isPrimitive,
4373
- isPrimitiveOrFunc,
4374
- keys,
4375
4876
  mark,
4376
4877
  markBooted,
4377
4878
  markRouterBooted,
4378
4879
  nextCounter,
4379
- nodeInside,
4380
- noop,
4381
- now,
4382
- parseUri,
4383
4880
  registerViewClass,
4384
4881
  resetProjectsMap,
4385
4882
  safeguard,
4386
- serializeFrameTree,
4387
- setData,
4388
- syncCounter,
4389
- toMap,
4390
- toUri,
4391
- translateData,
4392
4883
  unmark,
4393
4884
  use,
4394
- useUrlState
4885
+ useUrlState,
4886
+ vdomCreate
4395
4887
  });