@askrjs/askr 0.0.2 → 0.0.3
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/{chunk-MIPES65F.js → chunk-2ONGHQ7Z.js} +1575 -1483
- package/dist/chunk-2ONGHQ7Z.js.map +1 -0
- package/dist/{chunk-RJWOOUYV.js → chunk-H3NSVHA7.js} +2 -6
- package/dist/{chunk-RJWOOUYV.js.map → chunk-H3NSVHA7.js.map} +1 -1
- package/dist/chunk-JHOGWTAW.js +16 -0
- package/dist/{chunk-QECQ2TF6.js.map → chunk-JHOGWTAW.js.map} +1 -1
- package/dist/{chunk-PFOLLB6A.js → chunk-OFW6DFBM.js} +330 -138
- package/dist/chunk-OFW6DFBM.js.map +1 -0
- package/dist/chunk-SALJX5PZ.js +26 -0
- package/dist/{chunk-KR6HG7HF.js.map → chunk-SALJX5PZ.js.map} +1 -1
- package/dist/index.cjs +1869 -1199
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -8
- package/dist/index.d.ts +51 -8
- package/dist/index.js +251 -79
- package/dist/index.js.map +1 -1
- package/dist/jsx/jsx-dev-runtime.js +2 -5
- package/dist/jsx/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx/jsx-runtime.js +2 -4
- package/dist/{navigate-SDZNA2ZE.js → navigate-CZEUXFPM.js} +5 -5
- package/dist/{route-P5YQBT4T.js → route-USEXGOBT.js} +4 -4
- package/dist/{ssr-65K3IJ6B.js → ssr-QJ5NTQR6.js} +5 -5
- package/package.json +4 -3
- package/dist/chunk-KR6HG7HF.js +0 -38
- package/dist/chunk-MIPES65F.js.map +0 -1
- package/dist/chunk-PFOLLB6A.js.map +0 -1
- package/dist/chunk-QECQ2TF6.js +0 -28
- /package/dist/{navigate-SDZNA2ZE.js.map → navigate-CZEUXFPM.js.map} +0 -0
- /package/dist/{route-P5YQBT4T.js.map → route-USEXGOBT.js.map} +0 -0
- /package/dist/{ssr-65K3IJ6B.js.map → ssr-QJ5NTQR6.js.map} +0 -0
|
@@ -1,11 +1,60 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Fragment
|
|
3
|
-
|
|
4
|
-
} from "./chunk-KR6HG7HF.js";
|
|
2
|
+
Fragment as Fragment2
|
|
3
|
+
} from "./chunk-SALJX5PZ.js";
|
|
5
4
|
import {
|
|
6
|
-
|
|
5
|
+
Fragment,
|
|
7
6
|
__export
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JHOGWTAW.js";
|
|
8
|
+
|
|
9
|
+
// src/router/route.ts
|
|
10
|
+
var route_exports = {};
|
|
11
|
+
__export(route_exports, {
|
|
12
|
+
_lockRouteRegistrationForTests: () => _lockRouteRegistrationForTests,
|
|
13
|
+
_unlockRouteRegistrationForTests: () => _unlockRouteRegistrationForTests,
|
|
14
|
+
clearRoutes: () => clearRoutes,
|
|
15
|
+
getLoadedNamespaces: () => getLoadedNamespaces,
|
|
16
|
+
getNamespaceRoutes: () => getNamespaceRoutes,
|
|
17
|
+
getRoutes: () => getRoutes,
|
|
18
|
+
lockRouteRegistration: () => lockRouteRegistration,
|
|
19
|
+
registerRoute: () => registerRoute,
|
|
20
|
+
resolveRoute: () => resolveRoute,
|
|
21
|
+
route: () => route,
|
|
22
|
+
setServerLocation: () => setServerLocation,
|
|
23
|
+
unloadNamespace: () => unloadNamespace
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// src/router/match.ts
|
|
27
|
+
function match(path, pattern) {
|
|
28
|
+
const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
29
|
+
const normalizedPattern = pattern.endsWith("/") && pattern !== "/" ? pattern.slice(0, -1) : pattern;
|
|
30
|
+
const pathSegments = normalizedPath.split("/").filter(Boolean);
|
|
31
|
+
const patternSegments = normalizedPattern.split("/").filter(Boolean);
|
|
32
|
+
if (patternSegments.length === 1 && patternSegments[0] === "*") {
|
|
33
|
+
return {
|
|
34
|
+
matched: true,
|
|
35
|
+
params: {
|
|
36
|
+
"*": pathSegments.length > 1 ? normalizedPath : pathSegments[0]
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (pathSegments.length !== patternSegments.length) {
|
|
41
|
+
return { matched: false, params: {} };
|
|
42
|
+
}
|
|
43
|
+
const params = {};
|
|
44
|
+
for (let i = 0; i < patternSegments.length; i++) {
|
|
45
|
+
const patternSegment = patternSegments[i];
|
|
46
|
+
const pathSegment = pathSegments[i];
|
|
47
|
+
if (patternSegment.startsWith("{") && patternSegment.endsWith("}")) {
|
|
48
|
+
const paramName = patternSegment.slice(1, -1);
|
|
49
|
+
params[paramName] = decodeURIComponent(pathSegment);
|
|
50
|
+
} else if (patternSegment === "*") {
|
|
51
|
+
params["*"] = pathSegment;
|
|
52
|
+
} else if (patternSegment !== pathSegment) {
|
|
53
|
+
return { matched: false, params: {} };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { matched: true, params };
|
|
57
|
+
}
|
|
9
58
|
|
|
10
59
|
// src/dev/invariant.ts
|
|
11
60
|
function invariant(condition, message, context) {
|
|
@@ -17,11 +66,6 @@ function invariant(condition, message, context) {
|
|
|
17
66
|
function assertSchedulingPrecondition(condition, violationMessage) {
|
|
18
67
|
invariant(condition, `[Scheduler Precondition] ${violationMessage}`);
|
|
19
68
|
}
|
|
20
|
-
var init_invariant = __esm({
|
|
21
|
-
"src/dev/invariant.ts"() {
|
|
22
|
-
"use strict";
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
69
|
|
|
26
70
|
// src/dev/logger.ts
|
|
27
71
|
function callConsole(method, args) {
|
|
@@ -35,31 +79,26 @@ function callConsole(method, args) {
|
|
|
35
79
|
}
|
|
36
80
|
}
|
|
37
81
|
}
|
|
38
|
-
var logger
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
callConsole("warn", args);
|
|
54
|
-
},
|
|
55
|
-
error: (...args) => {
|
|
56
|
-
callConsole("error", args);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
82
|
+
var logger = {
|
|
83
|
+
debug: (...args) => {
|
|
84
|
+
if (process.env.NODE_ENV === "production") return;
|
|
85
|
+
callConsole("debug", args);
|
|
86
|
+
},
|
|
87
|
+
info: (...args) => {
|
|
88
|
+
if (process.env.NODE_ENV === "production") return;
|
|
89
|
+
callConsole("info", args);
|
|
90
|
+
},
|
|
91
|
+
warn: (...args) => {
|
|
92
|
+
if (process.env.NODE_ENV === "production") return;
|
|
93
|
+
callConsole("warn", args);
|
|
94
|
+
},
|
|
95
|
+
error: (...args) => {
|
|
96
|
+
callConsole("error", args);
|
|
59
97
|
}
|
|
60
|
-
}
|
|
98
|
+
};
|
|
61
99
|
|
|
62
100
|
// src/runtime/scheduler.ts
|
|
101
|
+
var MAX_FLUSH_DEPTH = 50;
|
|
63
102
|
function isBulkCommitActive() {
|
|
64
103
|
try {
|
|
65
104
|
const fb = globalThis.__ASKR_FASTLANE;
|
|
@@ -69,6 +108,250 @@ function isBulkCommitActive() {
|
|
|
69
108
|
return false;
|
|
70
109
|
}
|
|
71
110
|
}
|
|
111
|
+
var Scheduler = class {
|
|
112
|
+
constructor() {
|
|
113
|
+
this.q = [];
|
|
114
|
+
this.head = 0;
|
|
115
|
+
this.running = false;
|
|
116
|
+
this.inHandler = false;
|
|
117
|
+
this.depth = 0;
|
|
118
|
+
this.executionDepth = 0;
|
|
119
|
+
// for compat with existing diagnostics
|
|
120
|
+
// Monotonic flush version increments at end of each flush
|
|
121
|
+
this.flushVersion = 0;
|
|
122
|
+
// Best-effort microtask kick scheduling
|
|
123
|
+
this.kickScheduled = false;
|
|
124
|
+
// Escape hatch flag for runWithSyncProgress
|
|
125
|
+
this.allowSyncProgress = false;
|
|
126
|
+
// Waiters waiting for flushVersion >= target
|
|
127
|
+
this.waiters = [];
|
|
128
|
+
// Keep a lightweight taskCount for compatibility/diagnostics
|
|
129
|
+
this.taskCount = 0;
|
|
130
|
+
}
|
|
131
|
+
enqueue(task) {
|
|
132
|
+
assertSchedulingPrecondition(
|
|
133
|
+
typeof task === "function",
|
|
134
|
+
"enqueue() requires a function"
|
|
135
|
+
);
|
|
136
|
+
if (isBulkCommitActive() && !this.allowSyncProgress) {
|
|
137
|
+
if (process.env.NODE_ENV !== "production") {
|
|
138
|
+
throw new Error(
|
|
139
|
+
"[Scheduler] enqueue() during bulk commit (not allowed)"
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
this.q.push(task);
|
|
145
|
+
this.taskCount++;
|
|
146
|
+
if (!this.running && !this.kickScheduled && !this.inHandler && !isBulkCommitActive()) {
|
|
147
|
+
this.kickScheduled = true;
|
|
148
|
+
queueMicrotask(() => {
|
|
149
|
+
this.kickScheduled = false;
|
|
150
|
+
if (this.running) return;
|
|
151
|
+
if (isBulkCommitActive()) return;
|
|
152
|
+
try {
|
|
153
|
+
this.flush();
|
|
154
|
+
} catch (err) {
|
|
155
|
+
setTimeout(() => {
|
|
156
|
+
throw err;
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
flush() {
|
|
163
|
+
invariant(
|
|
164
|
+
!this.running,
|
|
165
|
+
"[Scheduler] flush() called while already running"
|
|
166
|
+
);
|
|
167
|
+
if (process.env.NODE_ENV !== "production") {
|
|
168
|
+
if (isBulkCommitActive() && !this.allowSyncProgress) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
"[Scheduler] flush() started during bulk commit (not allowed)"
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
this.running = true;
|
|
175
|
+
this.depth = 0;
|
|
176
|
+
let fatal = null;
|
|
177
|
+
try {
|
|
178
|
+
while (this.head < this.q.length) {
|
|
179
|
+
this.depth++;
|
|
180
|
+
if (process.env.NODE_ENV !== "production" && this.depth > MAX_FLUSH_DEPTH) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`[Scheduler] exceeded MAX_FLUSH_DEPTH (${MAX_FLUSH_DEPTH}). Likely infinite update loop.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
const task = this.q[this.head++];
|
|
186
|
+
try {
|
|
187
|
+
this.executionDepth++;
|
|
188
|
+
task();
|
|
189
|
+
this.executionDepth--;
|
|
190
|
+
} catch (err) {
|
|
191
|
+
if (this.executionDepth > 0) this.executionDepth = 0;
|
|
192
|
+
fatal = err;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
if (this.taskCount > 0) this.taskCount--;
|
|
196
|
+
}
|
|
197
|
+
} finally {
|
|
198
|
+
this.running = false;
|
|
199
|
+
this.depth = 0;
|
|
200
|
+
this.executionDepth = 0;
|
|
201
|
+
if (this.head >= this.q.length) {
|
|
202
|
+
this.q.length = 0;
|
|
203
|
+
this.head = 0;
|
|
204
|
+
} else if (this.head > 0) {
|
|
205
|
+
const remaining = this.q.length - this.head;
|
|
206
|
+
if (this.head > 1024 || this.head > remaining) {
|
|
207
|
+
this.q = this.q.slice(this.head);
|
|
208
|
+
} else {
|
|
209
|
+
for (let i = 0; i < remaining; i++) {
|
|
210
|
+
this.q[i] = this.q[this.head + i];
|
|
211
|
+
}
|
|
212
|
+
this.q.length = remaining;
|
|
213
|
+
}
|
|
214
|
+
this.head = 0;
|
|
215
|
+
}
|
|
216
|
+
this.flushVersion++;
|
|
217
|
+
this.resolveWaiters();
|
|
218
|
+
}
|
|
219
|
+
if (fatal) throw fatal;
|
|
220
|
+
}
|
|
221
|
+
runWithSyncProgress(fn) {
|
|
222
|
+
const prev = this.allowSyncProgress;
|
|
223
|
+
this.allowSyncProgress = true;
|
|
224
|
+
const g = globalThis;
|
|
225
|
+
const origQueueMicrotask = g.queueMicrotask;
|
|
226
|
+
const origSetTimeout = g.setTimeout;
|
|
227
|
+
if (process.env.NODE_ENV !== "production") {
|
|
228
|
+
g.queueMicrotask = () => {
|
|
229
|
+
throw new Error(
|
|
230
|
+
"[Scheduler] queueMicrotask not allowed during runWithSyncProgress"
|
|
231
|
+
);
|
|
232
|
+
};
|
|
233
|
+
g.setTimeout = () => {
|
|
234
|
+
throw new Error(
|
|
235
|
+
"[Scheduler] setTimeout not allowed during runWithSyncProgress"
|
|
236
|
+
);
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const startVersion = this.flushVersion;
|
|
240
|
+
try {
|
|
241
|
+
const res = fn();
|
|
242
|
+
if (!this.running && this.q.length - this.head > 0) {
|
|
243
|
+
this.flush();
|
|
244
|
+
}
|
|
245
|
+
if (process.env.NODE_ENV !== "production") {
|
|
246
|
+
if (this.q.length - this.head > 0) {
|
|
247
|
+
throw new Error(
|
|
248
|
+
"[Scheduler] tasks remain after runWithSyncProgress flush"
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return res;
|
|
253
|
+
} finally {
|
|
254
|
+
if (process.env.NODE_ENV !== "production") {
|
|
255
|
+
g.queueMicrotask = origQueueMicrotask;
|
|
256
|
+
g.setTimeout = origSetTimeout;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
if (this.flushVersion === startVersion) {
|
|
260
|
+
this.flushVersion++;
|
|
261
|
+
this.resolveWaiters();
|
|
262
|
+
}
|
|
263
|
+
} catch (e) {
|
|
264
|
+
void e;
|
|
265
|
+
}
|
|
266
|
+
this.allowSyncProgress = prev;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
waitForFlush(targetVersion, timeoutMs = 2e3) {
|
|
270
|
+
const target = typeof targetVersion === "number" ? targetVersion : this.flushVersion + 1;
|
|
271
|
+
if (this.flushVersion >= target) return Promise.resolve();
|
|
272
|
+
return new Promise((resolve, reject) => {
|
|
273
|
+
const timer = setTimeout(() => {
|
|
274
|
+
const ns = globalThis.__ASKR__ || {};
|
|
275
|
+
const diag = {
|
|
276
|
+
flushVersion: this.flushVersion,
|
|
277
|
+
queueLen: this.q.length - this.head,
|
|
278
|
+
running: this.running,
|
|
279
|
+
inHandler: this.inHandler,
|
|
280
|
+
bulk: isBulkCommitActive(),
|
|
281
|
+
namespace: ns
|
|
282
|
+
};
|
|
283
|
+
reject(
|
|
284
|
+
new Error(
|
|
285
|
+
`waitForFlush timeout ${timeoutMs}ms: ${JSON.stringify(diag)}`
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
}, timeoutMs);
|
|
289
|
+
this.waiters.push({ target, resolve, reject, timer });
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
getState() {
|
|
293
|
+
return {
|
|
294
|
+
queueLength: this.q.length - this.head,
|
|
295
|
+
running: this.running,
|
|
296
|
+
depth: this.depth,
|
|
297
|
+
executionDepth: this.executionDepth,
|
|
298
|
+
taskCount: this.taskCount,
|
|
299
|
+
flushVersion: this.flushVersion,
|
|
300
|
+
// New fields for optional inspection
|
|
301
|
+
inHandler: this.inHandler,
|
|
302
|
+
allowSyncProgress: this.allowSyncProgress
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
setInHandler(v) {
|
|
306
|
+
this.inHandler = v;
|
|
307
|
+
}
|
|
308
|
+
isInHandler() {
|
|
309
|
+
return this.inHandler;
|
|
310
|
+
}
|
|
311
|
+
isExecuting() {
|
|
312
|
+
return this.running || this.executionDepth > 0;
|
|
313
|
+
}
|
|
314
|
+
// Clear pending synchronous tasks (used by fastlane enter/exit)
|
|
315
|
+
clearPendingSyncTasks() {
|
|
316
|
+
const remaining = this.q.length - this.head;
|
|
317
|
+
if (remaining <= 0) return 0;
|
|
318
|
+
if (this.running) {
|
|
319
|
+
this.q.length = this.head;
|
|
320
|
+
this.taskCount = Math.max(0, this.taskCount - remaining);
|
|
321
|
+
queueMicrotask(() => {
|
|
322
|
+
try {
|
|
323
|
+
this.flushVersion++;
|
|
324
|
+
this.resolveWaiters();
|
|
325
|
+
} catch (e) {
|
|
326
|
+
void e;
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
return remaining;
|
|
330
|
+
}
|
|
331
|
+
this.q.length = 0;
|
|
332
|
+
this.head = 0;
|
|
333
|
+
this.taskCount = Math.max(0, this.taskCount - remaining);
|
|
334
|
+
this.flushVersion++;
|
|
335
|
+
this.resolveWaiters();
|
|
336
|
+
return remaining;
|
|
337
|
+
}
|
|
338
|
+
resolveWaiters() {
|
|
339
|
+
if (this.waiters.length === 0) return;
|
|
340
|
+
const ready = [];
|
|
341
|
+
const remaining = [];
|
|
342
|
+
for (const w of this.waiters) {
|
|
343
|
+
if (this.flushVersion >= w.target) {
|
|
344
|
+
if (w.timer) clearTimeout(w.timer);
|
|
345
|
+
ready.push(w.resolve);
|
|
346
|
+
} else {
|
|
347
|
+
remaining.push(w);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
this.waiters = remaining;
|
|
351
|
+
for (const r of ready) r();
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
var globalScheduler = new Scheduler();
|
|
72
355
|
function isSchedulerExecuting() {
|
|
73
356
|
return globalScheduler.isExecuting();
|
|
74
357
|
}
|
|
@@ -96,261 +379,11 @@ function scheduleEventHandler(handler) {
|
|
|
96
379
|
}
|
|
97
380
|
};
|
|
98
381
|
}
|
|
99
|
-
var MAX_FLUSH_DEPTH, Scheduler, globalScheduler;
|
|
100
|
-
var init_scheduler = __esm({
|
|
101
|
-
"src/runtime/scheduler.ts"() {
|
|
102
|
-
"use strict";
|
|
103
|
-
init_invariant();
|
|
104
|
-
init_logger();
|
|
105
|
-
MAX_FLUSH_DEPTH = 50;
|
|
106
|
-
Scheduler = class {
|
|
107
|
-
constructor() {
|
|
108
|
-
this.q = [];
|
|
109
|
-
this.head = 0;
|
|
110
|
-
this.running = false;
|
|
111
|
-
this.inHandler = false;
|
|
112
|
-
this.depth = 0;
|
|
113
|
-
this.executionDepth = 0;
|
|
114
|
-
// for compat with existing diagnostics
|
|
115
|
-
// Monotonic flush version increments at end of each flush
|
|
116
|
-
this.flushVersion = 0;
|
|
117
|
-
// Best-effort microtask kick scheduling
|
|
118
|
-
this.kickScheduled = false;
|
|
119
|
-
// Escape hatch flag for runWithSyncProgress
|
|
120
|
-
this.allowSyncProgress = false;
|
|
121
|
-
// Waiters waiting for flushVersion >= target
|
|
122
|
-
this.waiters = [];
|
|
123
|
-
// Keep a lightweight taskCount for compatibility/diagnostics
|
|
124
|
-
this.taskCount = 0;
|
|
125
|
-
}
|
|
126
|
-
enqueue(task) {
|
|
127
|
-
assertSchedulingPrecondition(
|
|
128
|
-
typeof task === "function",
|
|
129
|
-
"enqueue() requires a function"
|
|
130
|
-
);
|
|
131
|
-
if (isBulkCommitActive() && !this.allowSyncProgress) {
|
|
132
|
-
if (process.env.NODE_ENV !== "production") {
|
|
133
|
-
throw new Error(
|
|
134
|
-
"[Scheduler] enqueue() during bulk commit (not allowed)"
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
this.q.push(task);
|
|
140
|
-
this.taskCount++;
|
|
141
|
-
if (!this.running && !this.kickScheduled && !this.inHandler && !isBulkCommitActive()) {
|
|
142
|
-
this.kickScheduled = true;
|
|
143
|
-
queueMicrotask(() => {
|
|
144
|
-
this.kickScheduled = false;
|
|
145
|
-
if (this.running) return;
|
|
146
|
-
if (isBulkCommitActive()) return;
|
|
147
|
-
try {
|
|
148
|
-
this.flush();
|
|
149
|
-
} catch (err) {
|
|
150
|
-
setTimeout(() => {
|
|
151
|
-
throw err;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
flush() {
|
|
158
|
-
invariant(
|
|
159
|
-
!this.running,
|
|
160
|
-
"[Scheduler] flush() called while already running"
|
|
161
|
-
);
|
|
162
|
-
if (process.env.NODE_ENV !== "production") {
|
|
163
|
-
if (isBulkCommitActive() && !this.allowSyncProgress) {
|
|
164
|
-
throw new Error(
|
|
165
|
-
"[Scheduler] flush() started during bulk commit (not allowed)"
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
this.running = true;
|
|
170
|
-
this.depth = 0;
|
|
171
|
-
let fatal = null;
|
|
172
|
-
try {
|
|
173
|
-
while (this.head < this.q.length) {
|
|
174
|
-
this.depth++;
|
|
175
|
-
if (process.env.NODE_ENV !== "production" && this.depth > MAX_FLUSH_DEPTH) {
|
|
176
|
-
throw new Error(
|
|
177
|
-
`[Scheduler] exceeded MAX_FLUSH_DEPTH (${MAX_FLUSH_DEPTH}). Likely infinite update loop.`
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
const task = this.q[this.head++];
|
|
181
|
-
try {
|
|
182
|
-
this.executionDepth++;
|
|
183
|
-
task();
|
|
184
|
-
this.executionDepth--;
|
|
185
|
-
} catch (err) {
|
|
186
|
-
if (this.executionDepth > 0) this.executionDepth = 0;
|
|
187
|
-
fatal = err;
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
if (this.taskCount > 0) this.taskCount--;
|
|
191
|
-
}
|
|
192
|
-
} finally {
|
|
193
|
-
this.running = false;
|
|
194
|
-
this.depth = 0;
|
|
195
|
-
this.executionDepth = 0;
|
|
196
|
-
if (this.head >= this.q.length) {
|
|
197
|
-
this.q.length = 0;
|
|
198
|
-
this.head = 0;
|
|
199
|
-
} else if (this.head > 0) {
|
|
200
|
-
const remaining = this.q.length - this.head;
|
|
201
|
-
if (this.head > 1024 || this.head > remaining) {
|
|
202
|
-
this.q = this.q.slice(this.head);
|
|
203
|
-
} else {
|
|
204
|
-
for (let i = 0; i < remaining; i++) {
|
|
205
|
-
this.q[i] = this.q[this.head + i];
|
|
206
|
-
}
|
|
207
|
-
this.q.length = remaining;
|
|
208
|
-
}
|
|
209
|
-
this.head = 0;
|
|
210
|
-
}
|
|
211
|
-
this.flushVersion++;
|
|
212
|
-
this.resolveWaiters();
|
|
213
|
-
}
|
|
214
|
-
if (fatal) throw fatal;
|
|
215
|
-
}
|
|
216
|
-
runWithSyncProgress(fn) {
|
|
217
|
-
const prev = this.allowSyncProgress;
|
|
218
|
-
this.allowSyncProgress = true;
|
|
219
|
-
const g = globalThis;
|
|
220
|
-
const origQueueMicrotask = g.queueMicrotask;
|
|
221
|
-
const origSetTimeout = g.setTimeout;
|
|
222
|
-
if (process.env.NODE_ENV !== "production") {
|
|
223
|
-
g.queueMicrotask = () => {
|
|
224
|
-
throw new Error(
|
|
225
|
-
"[Scheduler] queueMicrotask not allowed during runWithSyncProgress"
|
|
226
|
-
);
|
|
227
|
-
};
|
|
228
|
-
g.setTimeout = () => {
|
|
229
|
-
throw new Error(
|
|
230
|
-
"[Scheduler] setTimeout not allowed during runWithSyncProgress"
|
|
231
|
-
);
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
const startVersion = this.flushVersion;
|
|
235
|
-
try {
|
|
236
|
-
const res = fn();
|
|
237
|
-
if (!this.running && this.q.length - this.head > 0) {
|
|
238
|
-
this.flush();
|
|
239
|
-
}
|
|
240
|
-
if (process.env.NODE_ENV !== "production") {
|
|
241
|
-
if (this.q.length - this.head > 0) {
|
|
242
|
-
throw new Error(
|
|
243
|
-
"[Scheduler] tasks remain after runWithSyncProgress flush"
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return res;
|
|
248
|
-
} finally {
|
|
249
|
-
if (process.env.NODE_ENV !== "production") {
|
|
250
|
-
g.queueMicrotask = origQueueMicrotask;
|
|
251
|
-
g.setTimeout = origSetTimeout;
|
|
252
|
-
}
|
|
253
|
-
try {
|
|
254
|
-
if (this.flushVersion === startVersion) {
|
|
255
|
-
this.flushVersion++;
|
|
256
|
-
this.resolveWaiters();
|
|
257
|
-
}
|
|
258
|
-
} catch (e) {
|
|
259
|
-
void e;
|
|
260
|
-
}
|
|
261
|
-
this.allowSyncProgress = prev;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
waitForFlush(targetVersion, timeoutMs = 2e3) {
|
|
265
|
-
const target = typeof targetVersion === "number" ? targetVersion : this.flushVersion + 1;
|
|
266
|
-
if (this.flushVersion >= target) return Promise.resolve();
|
|
267
|
-
return new Promise((resolve, reject) => {
|
|
268
|
-
const timer = setTimeout(() => {
|
|
269
|
-
const ns = globalThis.__ASKR__ || {};
|
|
270
|
-
const diag = {
|
|
271
|
-
flushVersion: this.flushVersion,
|
|
272
|
-
queueLen: this.q.length - this.head,
|
|
273
|
-
running: this.running,
|
|
274
|
-
inHandler: this.inHandler,
|
|
275
|
-
bulk: isBulkCommitActive(),
|
|
276
|
-
namespace: ns
|
|
277
|
-
};
|
|
278
|
-
reject(
|
|
279
|
-
new Error(
|
|
280
|
-
`waitForFlush timeout ${timeoutMs}ms: ${JSON.stringify(diag)}`
|
|
281
|
-
)
|
|
282
|
-
);
|
|
283
|
-
}, timeoutMs);
|
|
284
|
-
this.waiters.push({ target, resolve, reject, timer });
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
getState() {
|
|
288
|
-
return {
|
|
289
|
-
queueLength: this.q.length - this.head,
|
|
290
|
-
running: this.running,
|
|
291
|
-
depth: this.depth,
|
|
292
|
-
executionDepth: this.executionDepth,
|
|
293
|
-
taskCount: this.taskCount,
|
|
294
|
-
flushVersion: this.flushVersion,
|
|
295
|
-
// New fields for optional inspection
|
|
296
|
-
inHandler: this.inHandler,
|
|
297
|
-
allowSyncProgress: this.allowSyncProgress
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
setInHandler(v) {
|
|
301
|
-
this.inHandler = v;
|
|
302
|
-
}
|
|
303
|
-
isInHandler() {
|
|
304
|
-
return this.inHandler;
|
|
305
|
-
}
|
|
306
|
-
isExecuting() {
|
|
307
|
-
return this.running || this.executionDepth > 0;
|
|
308
|
-
}
|
|
309
|
-
// Clear pending synchronous tasks (used by fastlane enter/exit)
|
|
310
|
-
clearPendingSyncTasks() {
|
|
311
|
-
const remaining = this.q.length - this.head;
|
|
312
|
-
if (remaining <= 0) return 0;
|
|
313
|
-
if (this.running) {
|
|
314
|
-
this.q.length = this.head;
|
|
315
|
-
this.taskCount = Math.max(0, this.taskCount - remaining);
|
|
316
|
-
queueMicrotask(() => {
|
|
317
|
-
try {
|
|
318
|
-
this.flushVersion++;
|
|
319
|
-
this.resolveWaiters();
|
|
320
|
-
} catch (e) {
|
|
321
|
-
void e;
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
return remaining;
|
|
325
|
-
}
|
|
326
|
-
this.q.length = 0;
|
|
327
|
-
this.head = 0;
|
|
328
|
-
this.taskCount = Math.max(0, this.taskCount - remaining);
|
|
329
|
-
this.flushVersion++;
|
|
330
|
-
this.resolveWaiters();
|
|
331
|
-
return remaining;
|
|
332
|
-
}
|
|
333
|
-
resolveWaiters() {
|
|
334
|
-
if (this.waiters.length === 0) return;
|
|
335
|
-
const ready = [];
|
|
336
|
-
const remaining = [];
|
|
337
|
-
for (const w of this.waiters) {
|
|
338
|
-
if (this.flushVersion >= w.target) {
|
|
339
|
-
if (w.timer) clearTimeout(w.timer);
|
|
340
|
-
ready.push(w.resolve);
|
|
341
|
-
} else {
|
|
342
|
-
remaining.push(w);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
this.waiters = remaining;
|
|
346
|
-
for (const r of ready) r();
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
globalScheduler = new Scheduler();
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
382
|
|
|
353
383
|
// src/runtime/context.ts
|
|
384
|
+
var CONTEXT_FRAME_SYMBOL = /* @__PURE__ */ Symbol("__tempoContextFrame__");
|
|
385
|
+
var currentContextFrame = null;
|
|
386
|
+
var currentAsyncResourceFrame = null;
|
|
354
387
|
function withContext(frame, fn) {
|
|
355
388
|
const oldFrame = currentContextFrame;
|
|
356
389
|
currentContextFrame = frame;
|
|
@@ -469,16 +502,6 @@ function ContextFunctionChildInvoker(props) {
|
|
|
469
502
|
function getCurrentContextFrame() {
|
|
470
503
|
return currentContextFrame;
|
|
471
504
|
}
|
|
472
|
-
var CONTEXT_FRAME_SYMBOL, currentContextFrame, currentAsyncResourceFrame;
|
|
473
|
-
var init_context = __esm({
|
|
474
|
-
"src/runtime/context.ts"() {
|
|
475
|
-
"use strict";
|
|
476
|
-
init_component();
|
|
477
|
-
CONTEXT_FRAME_SYMBOL = /* @__PURE__ */ Symbol("__tempoContextFrame__");
|
|
478
|
-
currentContextFrame = null;
|
|
479
|
-
currentAsyncResourceFrame = null;
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
505
|
|
|
483
506
|
// src/renderer/diag/index.ts
|
|
484
507
|
function getDiagMap() {
|
|
@@ -536,13 +559,51 @@ function __ASKR_incCounter(key) {
|
|
|
536
559
|
void e;
|
|
537
560
|
}
|
|
538
561
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
562
|
+
|
|
563
|
+
// src/runtime/dev-namespace.ts
|
|
564
|
+
function getDevNamespace() {
|
|
565
|
+
if (process.env.NODE_ENV === "production") return {};
|
|
566
|
+
try {
|
|
567
|
+
const g = globalThis;
|
|
568
|
+
if (!g.__ASKR__) g.__ASKR__ = {};
|
|
569
|
+
return g.__ASKR__;
|
|
570
|
+
} catch {
|
|
571
|
+
return {};
|
|
542
572
|
}
|
|
543
|
-
}
|
|
573
|
+
}
|
|
574
|
+
function setDevValue(key, value) {
|
|
575
|
+
if (process.env.NODE_ENV === "production") return;
|
|
576
|
+
try {
|
|
577
|
+
getDevNamespace()[key] = value;
|
|
578
|
+
} catch {
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
function getDevValue(key) {
|
|
582
|
+
if (process.env.NODE_ENV === "production") return void 0;
|
|
583
|
+
try {
|
|
584
|
+
return getDevNamespace()[key];
|
|
585
|
+
} catch {
|
|
586
|
+
return void 0;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
544
589
|
|
|
545
590
|
// src/runtime/fastlane-shared.ts
|
|
591
|
+
var _bulkCommitActive = false;
|
|
592
|
+
var _appliedParents = null;
|
|
593
|
+
function enterBulkCommit() {
|
|
594
|
+
_bulkCommitActive = true;
|
|
595
|
+
_appliedParents = /* @__PURE__ */ new WeakSet();
|
|
596
|
+
try {
|
|
597
|
+
const cleared = globalScheduler.clearPendingSyncTasks?.() ?? 0;
|
|
598
|
+
setDevValue("__ASKR_FASTLANE_CLEARED_TASKS", cleared);
|
|
599
|
+
} catch (err) {
|
|
600
|
+
if (process.env.NODE_ENV !== "production") throw err;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
function exitBulkCommit() {
|
|
604
|
+
_bulkCommitActive = false;
|
|
605
|
+
_appliedParents = null;
|
|
606
|
+
}
|
|
546
607
|
function isBulkCommitActive2() {
|
|
547
608
|
return _bulkCommitActive;
|
|
548
609
|
}
|
|
@@ -554,95 +615,62 @@ function markFastPathApplied(parent) {
|
|
|
554
615
|
void e;
|
|
555
616
|
}
|
|
556
617
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
"use strict";
|
|
561
|
-
_bulkCommitActive = false;
|
|
562
|
-
_appliedParents = null;
|
|
563
|
-
}
|
|
564
|
-
});
|
|
618
|
+
function isFastPathApplied(parent) {
|
|
619
|
+
return !!(_appliedParents && _appliedParents.has(parent));
|
|
620
|
+
}
|
|
565
621
|
|
|
566
622
|
// src/renderer/types.ts
|
|
567
623
|
function _isDOMElement(node) {
|
|
568
624
|
return typeof node === "object" && node !== null && "type" in node;
|
|
569
625
|
}
|
|
570
|
-
var init_types = __esm({
|
|
571
|
-
"src/renderer/types.ts"() {
|
|
572
|
-
"use strict";
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
626
|
|
|
576
627
|
// src/renderer/cleanup.ts
|
|
577
|
-
function
|
|
578
|
-
|
|
579
|
-
if (!
|
|
580
|
-
const errors = [];
|
|
628
|
+
function cleanupSingleInstance(node, errors, strict) {
|
|
629
|
+
const inst = node.__ASKR_INSTANCE;
|
|
630
|
+
if (!inst) return;
|
|
581
631
|
try {
|
|
582
|
-
|
|
583
|
-
if (inst) {
|
|
584
|
-
try {
|
|
585
|
-
cleanupComponent(inst);
|
|
586
|
-
} catch (err) {
|
|
587
|
-
if (opts?.strict) errors.push(err);
|
|
588
|
-
else if (process.env.NODE_ENV !== "production")
|
|
589
|
-
logger.warn("[Askr] cleanupComponent failed:", err);
|
|
590
|
-
}
|
|
591
|
-
try {
|
|
592
|
-
delete node.__ASKR_INSTANCE;
|
|
593
|
-
} catch (e) {
|
|
594
|
-
if (opts?.strict) errors.push(e);
|
|
595
|
-
else void e;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
632
|
+
cleanupComponent(inst);
|
|
598
633
|
} catch (err) {
|
|
599
|
-
if (
|
|
600
|
-
else
|
|
601
|
-
|
|
602
|
-
|
|
634
|
+
if (strict) errors.push(err);
|
|
635
|
+
else logger.warn("[Askr] cleanupComponent failed:", err);
|
|
636
|
+
}
|
|
637
|
+
try {
|
|
638
|
+
delete node.__ASKR_INSTANCE;
|
|
639
|
+
} catch (e) {
|
|
640
|
+
if (strict) errors.push(e);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
function cleanupInstanceIfPresent(node, opts) {
|
|
644
|
+
if (!node || !(node instanceof Element)) return;
|
|
645
|
+
const errors = [];
|
|
646
|
+
const strict = opts?.strict ?? false;
|
|
647
|
+
try {
|
|
648
|
+
cleanupSingleInstance(node, errors, strict);
|
|
649
|
+
} catch (err) {
|
|
650
|
+
if (strict) errors.push(err);
|
|
651
|
+
else logger.warn("[Askr] cleanupInstanceIfPresent failed:", err);
|
|
603
652
|
}
|
|
604
653
|
try {
|
|
605
654
|
const descendants = node.querySelectorAll("*");
|
|
606
655
|
for (const d of Array.from(descendants)) {
|
|
607
656
|
try {
|
|
608
|
-
|
|
609
|
-
if (inst) {
|
|
610
|
-
try {
|
|
611
|
-
cleanupComponent(inst);
|
|
612
|
-
} catch (err) {
|
|
613
|
-
if (opts?.strict) errors.push(err);
|
|
614
|
-
else if (process.env.NODE_ENV !== "production") {
|
|
615
|
-
logger.warn(
|
|
616
|
-
"[Askr] cleanupInstanceIfPresent descendant cleanup failed:",
|
|
617
|
-
err
|
|
618
|
-
);
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
try {
|
|
622
|
-
delete d.__ASKR_INSTANCE;
|
|
623
|
-
} catch (e) {
|
|
624
|
-
if (opts?.strict) errors.push(e);
|
|
625
|
-
else void e;
|
|
626
|
-
}
|
|
627
|
-
}
|
|
657
|
+
cleanupSingleInstance(d, errors, strict);
|
|
628
658
|
} catch (err) {
|
|
629
|
-
if (
|
|
630
|
-
else
|
|
659
|
+
if (strict) errors.push(err);
|
|
660
|
+
else
|
|
631
661
|
logger.warn(
|
|
632
662
|
"[Askr] cleanupInstanceIfPresent descendant cleanup failed:",
|
|
633
663
|
err
|
|
634
664
|
);
|
|
635
|
-
}
|
|
636
665
|
}
|
|
637
666
|
}
|
|
638
667
|
} catch (err) {
|
|
639
|
-
if (
|
|
640
|
-
else
|
|
668
|
+
if (strict) errors.push(err);
|
|
669
|
+
else
|
|
641
670
|
logger.warn(
|
|
642
671
|
"[Askr] cleanupInstanceIfPresent descendant query failed:",
|
|
643
672
|
err
|
|
644
673
|
);
|
|
645
|
-
}
|
|
646
674
|
}
|
|
647
675
|
if (errors.length > 0) {
|
|
648
676
|
throw new AggregateError(errors, "cleanupInstanceIfPresent failed");
|
|
@@ -651,6 +679,7 @@ function cleanupInstanceIfPresent(node, opts) {
|
|
|
651
679
|
function cleanupInstancesUnder(node, opts) {
|
|
652
680
|
cleanupInstanceIfPresent(node, opts);
|
|
653
681
|
}
|
|
682
|
+
var elementListeners = /* @__PURE__ */ new WeakMap();
|
|
654
683
|
function removeElementListeners(element) {
|
|
655
684
|
const map = elementListeners.get(element);
|
|
656
685
|
if (map) {
|
|
@@ -670,34 +699,217 @@ function removeAllListeners(root) {
|
|
|
670
699
|
removeElementListeners(children[i]);
|
|
671
700
|
}
|
|
672
701
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
702
|
+
|
|
703
|
+
// src/renderer/utils.ts
|
|
704
|
+
function parseEventName(propName) {
|
|
705
|
+
if (!propName.startsWith("on") || propName.length <= 2) return null;
|
|
706
|
+
return propName.slice(2).charAt(0).toLowerCase() + propName.slice(3).toLowerCase();
|
|
707
|
+
}
|
|
708
|
+
function getPassiveOptions(eventName) {
|
|
709
|
+
if (eventName === "wheel" || eventName === "scroll" || eventName.startsWith("touch")) {
|
|
710
|
+
return { passive: true };
|
|
680
711
|
}
|
|
681
|
-
|
|
712
|
+
return void 0;
|
|
713
|
+
}
|
|
714
|
+
function createWrappedHandler(handler, flushAfter = false) {
|
|
715
|
+
return (event) => {
|
|
716
|
+
globalScheduler.setInHandler(true);
|
|
717
|
+
try {
|
|
718
|
+
handler(event);
|
|
719
|
+
} catch (error) {
|
|
720
|
+
logger.error("[Askr] Event handler error:", error);
|
|
721
|
+
} finally {
|
|
722
|
+
globalScheduler.setInHandler(false);
|
|
723
|
+
if (flushAfter) {
|
|
724
|
+
const state = globalScheduler.getState();
|
|
725
|
+
if ((state.queueLength ?? 0) > 0 && !state.running) {
|
|
726
|
+
queueMicrotask(() => {
|
|
727
|
+
try {
|
|
728
|
+
if (!globalScheduler.isExecuting()) globalScheduler.flush();
|
|
729
|
+
} catch (err) {
|
|
730
|
+
queueMicrotask(() => {
|
|
731
|
+
throw err;
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
function isSkippedProp(key) {
|
|
741
|
+
return key === "children" || key === "key";
|
|
742
|
+
}
|
|
743
|
+
function isIgnoredForPropChanges(key) {
|
|
744
|
+
if (key === "children" || key === "key") return true;
|
|
745
|
+
if (key.startsWith("on") && key.length > 2) return true;
|
|
746
|
+
if (key.startsWith("data-")) return true;
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
function hasPropChanged(el, key, value) {
|
|
750
|
+
try {
|
|
751
|
+
if (key === "class" || key === "className") {
|
|
752
|
+
return el.className !== String(value);
|
|
753
|
+
}
|
|
754
|
+
if (key === "value" || key === "checked") {
|
|
755
|
+
return el[key] !== value;
|
|
756
|
+
}
|
|
757
|
+
const attr = el.getAttribute(key);
|
|
758
|
+
if (value === void 0 || value === null || value === false) {
|
|
759
|
+
return attr !== null;
|
|
760
|
+
}
|
|
761
|
+
return String(value) !== attr;
|
|
762
|
+
} catch {
|
|
763
|
+
return true;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
function hasNonTrivialProps(props) {
|
|
767
|
+
for (const k of Object.keys(props)) {
|
|
768
|
+
if (isIgnoredForPropChanges(k)) continue;
|
|
769
|
+
return true;
|
|
770
|
+
}
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
function checkPropChanges(el, props) {
|
|
774
|
+
for (const k of Object.keys(props)) {
|
|
775
|
+
if (isIgnoredForPropChanges(k)) continue;
|
|
776
|
+
if (hasPropChanged(el, k, props[k])) {
|
|
777
|
+
return true;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
return false;
|
|
781
|
+
}
|
|
782
|
+
function extractKey(vnode) {
|
|
783
|
+
if (typeof vnode !== "object" || vnode === null) return void 0;
|
|
784
|
+
const obj = vnode;
|
|
785
|
+
const rawKey = obj.key ?? obj.props?.key;
|
|
786
|
+
if (rawKey === void 0) return void 0;
|
|
787
|
+
return typeof rawKey === "symbol" ? String(rawKey) : rawKey;
|
|
788
|
+
}
|
|
789
|
+
function buildKeyMapFromChildren(parent) {
|
|
790
|
+
const map = /* @__PURE__ */ new Map();
|
|
791
|
+
const children = Array.from(parent.children);
|
|
792
|
+
for (const ch of children) {
|
|
793
|
+
const k = ch.getAttribute("data-key");
|
|
794
|
+
if (k !== null) {
|
|
795
|
+
map.set(k, ch);
|
|
796
|
+
const n = Number(k);
|
|
797
|
+
if (!Number.isNaN(n)) map.set(n, ch);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return map;
|
|
801
|
+
}
|
|
802
|
+
function recordDOMReplace(source) {
|
|
803
|
+
try {
|
|
804
|
+
__ASKR_incCounter("__DOM_REPLACE_COUNT");
|
|
805
|
+
__ASKR_set(`__LAST_DOM_REPLACE_STACK_${source}`, new Error().stack);
|
|
806
|
+
} catch {
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
function recordFastPathStats(stats, counterName) {
|
|
810
|
+
try {
|
|
811
|
+
__ASKR_set("__LAST_FASTPATH_STATS", stats);
|
|
812
|
+
__ASKR_set("__LAST_FASTPATH_COMMIT_COUNT", 1);
|
|
813
|
+
if (counterName) {
|
|
814
|
+
__ASKR_incCounter(counterName);
|
|
815
|
+
}
|
|
816
|
+
} catch {
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
function logFastPathDebug(message, indexOrData, data) {
|
|
820
|
+
if (process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true") {
|
|
821
|
+
if (data !== void 0) {
|
|
822
|
+
logger.warn(`[Askr][FASTPATH] ${message}`, indexOrData, data);
|
|
823
|
+
} else if (indexOrData !== void 0) {
|
|
824
|
+
logger.warn(`[Askr][FASTPATH] ${message}`, indexOrData);
|
|
825
|
+
} else {
|
|
826
|
+
logger.warn(`[Askr][FASTPATH] ${message}`);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
function now() {
|
|
831
|
+
return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
832
|
+
}
|
|
682
833
|
|
|
683
834
|
// src/renderer/keyed.ts
|
|
835
|
+
var keyedElements = /* @__PURE__ */ new WeakMap();
|
|
684
836
|
function getKeyMapForElement(el) {
|
|
685
837
|
return keyedElements.get(el);
|
|
686
838
|
}
|
|
687
|
-
function
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
if (
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
839
|
+
function populateKeyMapForElement(parent) {
|
|
840
|
+
try {
|
|
841
|
+
if (keyedElements.has(parent)) return;
|
|
842
|
+
let domMap = buildKeyMapFromChildren(parent);
|
|
843
|
+
if (domMap.size === 0) {
|
|
844
|
+
domMap = /* @__PURE__ */ new Map();
|
|
845
|
+
const children = Array.from(parent.children);
|
|
846
|
+
for (const ch of children) {
|
|
847
|
+
const text = (ch.textContent || "").trim();
|
|
848
|
+
if (text) {
|
|
849
|
+
domMap.set(text, ch);
|
|
850
|
+
const n = Number(text);
|
|
851
|
+
if (!Number.isNaN(n)) domMap.set(n, ch);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
if (domMap.size > 0) keyedElements.set(parent, domMap);
|
|
856
|
+
} catch {
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
var _reconcilerRecordedParents = /* @__PURE__ */ new WeakSet();
|
|
860
|
+
function extractKeyedVnodes(newChildren) {
|
|
861
|
+
const result = [];
|
|
862
|
+
for (const child of newChildren) {
|
|
863
|
+
const key = extractKey(child);
|
|
864
|
+
if (key !== void 0) {
|
|
865
|
+
result.push({ key, vnode: child });
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
return result;
|
|
869
|
+
}
|
|
870
|
+
function computeLISLength(positions) {
|
|
871
|
+
const tails = [];
|
|
872
|
+
for (const pos of positions) {
|
|
873
|
+
if (pos === -1) continue;
|
|
874
|
+
let lo = 0;
|
|
875
|
+
let hi = tails.length;
|
|
876
|
+
while (lo < hi) {
|
|
877
|
+
const mid = lo + hi >> 1;
|
|
878
|
+
if (tails[mid] < pos) lo = mid + 1;
|
|
879
|
+
else hi = mid;
|
|
880
|
+
}
|
|
881
|
+
if (lo === tails.length) tails.push(pos);
|
|
882
|
+
else tails[lo] = pos;
|
|
883
|
+
}
|
|
884
|
+
return tails.length;
|
|
885
|
+
}
|
|
886
|
+
function checkVnodesHaveProps(keyedVnodes) {
|
|
887
|
+
for (const { vnode } of keyedVnodes) {
|
|
888
|
+
if (typeof vnode !== "object" || vnode === null) continue;
|
|
889
|
+
const vnodeObj = vnode;
|
|
890
|
+
if (vnodeObj.props && hasNonTrivialProps(vnodeObj.props)) {
|
|
891
|
+
return true;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
896
|
+
function checkVnodePropChanges(keyedVnodes, oldKeyMap) {
|
|
897
|
+
for (const { key, vnode } of keyedVnodes) {
|
|
898
|
+
const el = oldKeyMap?.get(key);
|
|
899
|
+
if (!el || typeof vnode !== "object" || vnode === null) continue;
|
|
900
|
+
const vnodeObj = vnode;
|
|
901
|
+
const props = vnodeObj.props || {};
|
|
902
|
+
for (const k of Object.keys(props)) {
|
|
903
|
+
if (isIgnoredForPropChanges(k)) continue;
|
|
904
|
+
if (hasPropChanged(el, k, props[k])) {
|
|
905
|
+
return true;
|
|
698
906
|
}
|
|
699
907
|
}
|
|
700
908
|
}
|
|
909
|
+
return false;
|
|
910
|
+
}
|
|
911
|
+
function isKeyedReorderFastPathEligible(parent, newChildren, oldKeyMap) {
|
|
912
|
+
const keyedVnodes = extractKeyedVnodes(newChildren);
|
|
701
913
|
const totalKeyed = keyedVnodes.length;
|
|
702
914
|
const newKeyOrder = keyedVnodes.map((kv) => kv.key);
|
|
703
915
|
const oldKeyOrder = oldKeyMap ? Array.from(oldKeyMap.keys()) : [];
|
|
@@ -718,89 +930,15 @@ function isKeyedReorderFastPathEligible(parent, newChildren, oldKeyMap) {
|
|
|
718
930
|
let lisLen = 0;
|
|
719
931
|
if (totalKeyed >= 128) {
|
|
720
932
|
const parentChildren = Array.from(parent.children);
|
|
721
|
-
const positions =
|
|
722
|
-
for (let i = 0; i < keyedVnodes.length; i++) {
|
|
723
|
-
const key = keyedVnodes[i].key;
|
|
933
|
+
const positions = keyedVnodes.map(({ key }) => {
|
|
724
934
|
const el = oldKeyMap?.get(key);
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
729
|
-
const tails = [];
|
|
730
|
-
for (let i = 0; i < positions.length; i++) {
|
|
731
|
-
const pos = positions[i];
|
|
732
|
-
if (pos === -1) continue;
|
|
733
|
-
let lo = 0;
|
|
734
|
-
let hi = tails.length;
|
|
735
|
-
while (lo < hi) {
|
|
736
|
-
const mid = lo + hi >> 1;
|
|
737
|
-
if (tails[mid] < pos) lo = mid + 1;
|
|
738
|
-
else hi = mid;
|
|
739
|
-
}
|
|
740
|
-
if (lo === tails.length) tails.push(pos);
|
|
741
|
-
else tails[lo] = pos;
|
|
742
|
-
}
|
|
743
|
-
lisLen = tails.length;
|
|
935
|
+
return el?.parentElement === parent ? parentChildren.indexOf(el) : -1;
|
|
936
|
+
});
|
|
937
|
+
lisLen = computeLISLength(positions);
|
|
744
938
|
lisTrigger = lisLen < Math.floor(totalKeyed * 0.5);
|
|
745
939
|
}
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
const vnode = keyedVnodes[i].vnode;
|
|
749
|
-
if (typeof vnode !== "object" || vnode === null) continue;
|
|
750
|
-
const vnodeObj = vnode;
|
|
751
|
-
const props = vnodeObj.props || {};
|
|
752
|
-
for (const k of Object.keys(props)) {
|
|
753
|
-
if (k === "children" || k === "key") continue;
|
|
754
|
-
if (k.startsWith("on") && k.length > 2) continue;
|
|
755
|
-
if (k.startsWith("data-")) continue;
|
|
756
|
-
hasPropsPresent = true;
|
|
757
|
-
break;
|
|
758
|
-
}
|
|
759
|
-
if (hasPropsPresent) break;
|
|
760
|
-
}
|
|
761
|
-
let hasPropChanges = false;
|
|
762
|
-
for (let i = 0; i < keyedVnodes.length; i++) {
|
|
763
|
-
const { key, vnode } = keyedVnodes[i];
|
|
764
|
-
const el = oldKeyMap?.get(key);
|
|
765
|
-
if (!el || typeof vnode !== "object" || vnode === null) continue;
|
|
766
|
-
const vnodeObj = vnode;
|
|
767
|
-
const props = vnodeObj.props || {};
|
|
768
|
-
for (const k of Object.keys(props)) {
|
|
769
|
-
if (k === "children" || k === "key") continue;
|
|
770
|
-
if (k.startsWith("on") && k.length > 2) continue;
|
|
771
|
-
if (k.startsWith("data-")) continue;
|
|
772
|
-
const v = props[k];
|
|
773
|
-
try {
|
|
774
|
-
if (k === "class" || k === "className") {
|
|
775
|
-
if (el.className !== String(v)) {
|
|
776
|
-
hasPropChanges = true;
|
|
777
|
-
break;
|
|
778
|
-
}
|
|
779
|
-
} else if (k === "value" || k === "checked") {
|
|
780
|
-
if (el[k] !== v) {
|
|
781
|
-
hasPropChanges = true;
|
|
782
|
-
break;
|
|
783
|
-
}
|
|
784
|
-
} else {
|
|
785
|
-
const attr = el.getAttribute(k);
|
|
786
|
-
if (v === void 0 || v === null || v === false) {
|
|
787
|
-
if (attr !== null) {
|
|
788
|
-
hasPropChanges = true;
|
|
789
|
-
break;
|
|
790
|
-
}
|
|
791
|
-
} else if (String(v) !== attr) {
|
|
792
|
-
hasPropChanges = true;
|
|
793
|
-
break;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
} catch (e) {
|
|
797
|
-
hasPropChanges = true;
|
|
798
|
-
void e;
|
|
799
|
-
break;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
if (hasPropChanges) break;
|
|
803
|
-
}
|
|
940
|
+
const hasPropsPresent = checkVnodesHaveProps(keyedVnodes);
|
|
941
|
+
const hasPropChanges = checkVnodePropChanges(keyedVnodes, oldKeyMap);
|
|
804
942
|
const useFastPath = (cheapMoveTrigger || lisTrigger) && !hasPropChanges && !hasPropsPresent;
|
|
805
943
|
return {
|
|
806
944
|
useFastPath,
|
|
@@ -810,23 +948,103 @@ function isKeyedReorderFastPathEligible(parent, newChildren, oldKeyMap) {
|
|
|
810
948
|
hasPropChanges
|
|
811
949
|
};
|
|
812
950
|
}
|
|
813
|
-
var keyedElements, _reconcilerRecordedParents;
|
|
814
|
-
var init_keyed = __esm({
|
|
815
|
-
"src/renderer/keyed.ts"() {
|
|
816
|
-
"use strict";
|
|
817
|
-
keyedElements = /* @__PURE__ */ new WeakMap();
|
|
818
|
-
_reconcilerRecordedParents = /* @__PURE__ */ new WeakSet();
|
|
819
|
-
}
|
|
820
|
-
});
|
|
821
951
|
|
|
822
952
|
// src/renderer/dom.ts
|
|
953
|
+
var IS_DOM_AVAILABLE = typeof document !== "undefined";
|
|
954
|
+
function addTrackedListener(el, eventName, handler) {
|
|
955
|
+
const wrappedHandler = createWrappedHandler(handler, true);
|
|
956
|
+
const options = getPassiveOptions(eventName);
|
|
957
|
+
if (options !== void 0) {
|
|
958
|
+
el.addEventListener(eventName, wrappedHandler, options);
|
|
959
|
+
} else {
|
|
960
|
+
el.addEventListener(eventName, wrappedHandler);
|
|
961
|
+
}
|
|
962
|
+
if (!elementListeners.has(el)) {
|
|
963
|
+
elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
964
|
+
}
|
|
965
|
+
elementListeners.get(el).set(eventName, {
|
|
966
|
+
handler: wrappedHandler,
|
|
967
|
+
original: handler,
|
|
968
|
+
options
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
function applyPropsToElement(el, props, tagName) {
|
|
972
|
+
for (const key in props) {
|
|
973
|
+
const value = props[key];
|
|
974
|
+
if (isSkippedProp(key)) continue;
|
|
975
|
+
if (value === void 0 || value === null || value === false) continue;
|
|
976
|
+
const eventName = parseEventName(key);
|
|
977
|
+
if (eventName) {
|
|
978
|
+
addTrackedListener(el, eventName, value);
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
if (key === "class" || key === "className") {
|
|
982
|
+
el.className = String(value);
|
|
983
|
+
} else if (key === "value" || key === "checked") {
|
|
984
|
+
applyFormControlProp(el, key, value, tagName);
|
|
985
|
+
} else {
|
|
986
|
+
el.setAttribute(key, String(value));
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function applyFormControlProp(el, key, value, tagName) {
|
|
991
|
+
const tag = tagName.toLowerCase();
|
|
992
|
+
if (key === "value") {
|
|
993
|
+
if (tag === "input" || tag === "textarea" || tag === "select") {
|
|
994
|
+
el.value = String(value);
|
|
995
|
+
el.setAttribute("value", String(value));
|
|
996
|
+
} else {
|
|
997
|
+
el.setAttribute("value", String(value));
|
|
998
|
+
}
|
|
999
|
+
} else if (key === "checked") {
|
|
1000
|
+
if (tag === "input") {
|
|
1001
|
+
el.checked = Boolean(value);
|
|
1002
|
+
el.setAttribute("checked", String(Boolean(value)));
|
|
1003
|
+
} else {
|
|
1004
|
+
el.setAttribute("checked", String(Boolean(value)));
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
function materializeKey(el, vnode, props) {
|
|
1009
|
+
const vnodeKey = vnode.key ?? props?.key;
|
|
1010
|
+
if (vnodeKey !== void 0) {
|
|
1011
|
+
el.setAttribute("data-key", String(vnodeKey));
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
function warnMissingKeys(children) {
|
|
1015
|
+
if (process.env.NODE_ENV === "production") return;
|
|
1016
|
+
let hasElements = false;
|
|
1017
|
+
let hasKeys = false;
|
|
1018
|
+
for (const item of children) {
|
|
1019
|
+
if (typeof item === "object" && item !== null && "type" in item) {
|
|
1020
|
+
hasElements = true;
|
|
1021
|
+
const rawKey = item.key ?? item.props?.key;
|
|
1022
|
+
if (rawKey !== void 0) {
|
|
1023
|
+
hasKeys = true;
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
if (hasElements && !hasKeys) {
|
|
1029
|
+
try {
|
|
1030
|
+
const inst = getCurrentInstance();
|
|
1031
|
+
const name = inst?.fn?.name || "<anonymous>";
|
|
1032
|
+
logger.warn(
|
|
1033
|
+
`Missing keys on dynamic lists in ${name}. Each child in a list should have a unique "key" prop.`
|
|
1034
|
+
);
|
|
1035
|
+
} catch {
|
|
1036
|
+
logger.warn(
|
|
1037
|
+
'Missing keys on dynamic lists. Each child in a list should have a unique "key" prop.'
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
823
1042
|
function createDOMNode(node) {
|
|
824
1043
|
if (!IS_DOM_AVAILABLE) {
|
|
825
1044
|
if (process.env.NODE_ENV !== "production") {
|
|
826
1045
|
try {
|
|
827
1046
|
logger.warn("[Askr] createDOMNode called in non-DOM environment");
|
|
828
|
-
} catch
|
|
829
|
-
void e;
|
|
1047
|
+
} catch {
|
|
830
1048
|
}
|
|
831
1049
|
}
|
|
832
1050
|
return null;
|
|
@@ -842,8 +1060,8 @@ function createDOMNode(node) {
|
|
|
842
1060
|
}
|
|
843
1061
|
if (Array.isArray(node)) {
|
|
844
1062
|
const fragment = document.createDocumentFragment();
|
|
845
|
-
for (
|
|
846
|
-
const dom = createDOMNode(
|
|
1063
|
+
for (const child of node) {
|
|
1064
|
+
const dom = createDOMNode(child);
|
|
847
1065
|
if (dom) fragment.appendChild(dom);
|
|
848
1066
|
}
|
|
849
1067
|
return fragment;
|
|
@@ -852,212 +1070,124 @@ function createDOMNode(node) {
|
|
|
852
1070
|
const type = node.type;
|
|
853
1071
|
const props = node.props || {};
|
|
854
1072
|
if (typeof type === "string") {
|
|
855
|
-
|
|
856
|
-
for (const key in props) {
|
|
857
|
-
const value = props[key];
|
|
858
|
-
if (key === "children" || key === "key") continue;
|
|
859
|
-
if (value === void 0 || value === null || value === false) continue;
|
|
860
|
-
if (key.startsWith("on") && key.length > 2) {
|
|
861
|
-
const eventName = key.slice(2).charAt(0).toLowerCase() + key.slice(3).toLowerCase();
|
|
862
|
-
const wrappedHandler = (event) => {
|
|
863
|
-
globalScheduler.setInHandler(true);
|
|
864
|
-
try {
|
|
865
|
-
value(event);
|
|
866
|
-
} catch (error) {
|
|
867
|
-
logger.error("[Askr] Event handler error:", error);
|
|
868
|
-
} finally {
|
|
869
|
-
globalScheduler.setInHandler(false);
|
|
870
|
-
const state = globalScheduler.getState();
|
|
871
|
-
if ((state.queueLength ?? 0) > 0 && !state.running) {
|
|
872
|
-
queueMicrotask(() => {
|
|
873
|
-
try {
|
|
874
|
-
if (!globalScheduler.isExecuting()) globalScheduler.flush();
|
|
875
|
-
} catch (err) {
|
|
876
|
-
queueMicrotask(() => {
|
|
877
|
-
throw err;
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
});
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
};
|
|
884
|
-
const options = eventName === "wheel" || eventName === "scroll" || eventName.startsWith("touch") ? { passive: true } : void 0;
|
|
885
|
-
if (options !== void 0)
|
|
886
|
-
el.addEventListener(eventName, wrappedHandler, options);
|
|
887
|
-
else el.addEventListener(eventName, wrappedHandler);
|
|
888
|
-
if (!elementListeners.has(el)) {
|
|
889
|
-
elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
890
|
-
}
|
|
891
|
-
elementListeners.get(el).set(eventName, {
|
|
892
|
-
handler: wrappedHandler,
|
|
893
|
-
original: value,
|
|
894
|
-
options
|
|
895
|
-
});
|
|
896
|
-
} else if (key === "class" || key === "className") {
|
|
897
|
-
el.className = String(value);
|
|
898
|
-
} else if (key === "value" || key === "checked") {
|
|
899
|
-
const tag = type.toLowerCase();
|
|
900
|
-
if (key === "value") {
|
|
901
|
-
if (tag === "input" || tag === "textarea" || tag === "select") {
|
|
902
|
-
el.value = String(value);
|
|
903
|
-
el.setAttribute("value", String(value));
|
|
904
|
-
} else {
|
|
905
|
-
el.setAttribute("value", String(value));
|
|
906
|
-
}
|
|
907
|
-
} else {
|
|
908
|
-
if (tag === "input") {
|
|
909
|
-
el.checked = Boolean(value);
|
|
910
|
-
el.setAttribute("checked", String(Boolean(value)));
|
|
911
|
-
} else {
|
|
912
|
-
el.setAttribute("checked", String(Boolean(value)));
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
} else {
|
|
916
|
-
el.setAttribute(key, String(value));
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
const vnodeKey = node.key ?? props?.key;
|
|
920
|
-
if (vnodeKey !== void 0) {
|
|
921
|
-
el.setAttribute("data-key", String(vnodeKey));
|
|
922
|
-
}
|
|
923
|
-
const children = props.children || node.children;
|
|
924
|
-
if (children) {
|
|
925
|
-
if (Array.isArray(children)) {
|
|
926
|
-
if (process.env.NODE_ENV !== "production") {
|
|
927
|
-
let hasElements = false;
|
|
928
|
-
let hasKeys = false;
|
|
929
|
-
for (let i = 0; i < children.length; i++) {
|
|
930
|
-
const item = children[i];
|
|
931
|
-
if (typeof item === "object" && item !== null && "type" in item) {
|
|
932
|
-
hasElements = true;
|
|
933
|
-
const itemProps = item.props || {};
|
|
934
|
-
if ("key" in itemProps) {
|
|
935
|
-
hasKeys = true;
|
|
936
|
-
break;
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
if (hasElements && !hasKeys) {
|
|
941
|
-
if (typeof console !== "undefined") {
|
|
942
|
-
try {
|
|
943
|
-
const inst = getCurrentInstance();
|
|
944
|
-
const name = inst?.fn?.name || "<anonymous>";
|
|
945
|
-
logger.warn(
|
|
946
|
-
`Missing keys on dynamic lists in ${name}. Each child in a list should have a unique "key" prop.`
|
|
947
|
-
);
|
|
948
|
-
} catch (e) {
|
|
949
|
-
logger.warn(
|
|
950
|
-
'Missing keys on dynamic lists. Each child in a list should have a unique "key" prop.'
|
|
951
|
-
);
|
|
952
|
-
void e;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
for (let i = 0; i < children.length; i++) {
|
|
958
|
-
const dom = createDOMNode(children[i]);
|
|
959
|
-
if (dom) el.appendChild(dom);
|
|
960
|
-
}
|
|
961
|
-
} else {
|
|
962
|
-
const dom = createDOMNode(children);
|
|
963
|
-
if (dom) el.appendChild(dom);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
return el;
|
|
1073
|
+
return createIntrinsicElement(node, type, props);
|
|
967
1074
|
}
|
|
968
1075
|
if (typeof type === "function") {
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
);
|
|
987
|
-
|
|
988
|
-
}
|
|
989
|
-
if (snapshot) {
|
|
990
|
-
childInstance.ownerFrame = snapshot;
|
|
991
|
-
}
|
|
992
|
-
const result = withContext(
|
|
993
|
-
snapshot,
|
|
994
|
-
() => renderComponentInline(childInstance)
|
|
995
|
-
);
|
|
996
|
-
if (result instanceof Promise) {
|
|
997
|
-
throw new Error(
|
|
998
|
-
"Async components are not supported. Components must return synchronously."
|
|
999
|
-
);
|
|
1076
|
+
return createComponentElement(node, type, props);
|
|
1077
|
+
}
|
|
1078
|
+
if (typeof type === "symbol" && (type === Fragment2 || String(type) === "Symbol(Fragment)")) {
|
|
1079
|
+
return createFragmentElement(node, props);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
return null;
|
|
1083
|
+
}
|
|
1084
|
+
function createIntrinsicElement(node, type, props) {
|
|
1085
|
+
const el = document.createElement(type);
|
|
1086
|
+
materializeKey(el, node, props);
|
|
1087
|
+
applyPropsToElement(el, props, type);
|
|
1088
|
+
const children = props.children || node.children;
|
|
1089
|
+
if (children) {
|
|
1090
|
+
if (Array.isArray(children)) {
|
|
1091
|
+
warnMissingKeys(children);
|
|
1092
|
+
for (const child of children) {
|
|
1093
|
+
const dom = createDOMNode(child);
|
|
1094
|
+
if (dom) el.appendChild(dom);
|
|
1000
1095
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1096
|
+
} else {
|
|
1097
|
+
const dom = createDOMNode(children);
|
|
1098
|
+
if (dom) el.appendChild(dom);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
return el;
|
|
1102
|
+
}
|
|
1103
|
+
function createComponentElement(node, type, props) {
|
|
1104
|
+
const frame = node[CONTEXT_FRAME_SYMBOL];
|
|
1105
|
+
const snapshot = frame || getCurrentContextFrame();
|
|
1106
|
+
const componentFn = type;
|
|
1107
|
+
const isAsync = componentFn.constructor.name === "AsyncFunction";
|
|
1108
|
+
if (isAsync) {
|
|
1109
|
+
throw new Error(
|
|
1110
|
+
"Async components are not supported. Use resource() for async work."
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
let childInstance = node.__instance;
|
|
1114
|
+
if (!childInstance) {
|
|
1115
|
+
childInstance = createComponentInstance(
|
|
1116
|
+
`comp-${Math.random().toString(36).slice(2, 7)}`,
|
|
1117
|
+
componentFn,
|
|
1118
|
+
props || {},
|
|
1119
|
+
null
|
|
1120
|
+
);
|
|
1121
|
+
node.__instance = childInstance;
|
|
1122
|
+
}
|
|
1123
|
+
if (snapshot) {
|
|
1124
|
+
childInstance.ownerFrame = snapshot;
|
|
1125
|
+
}
|
|
1126
|
+
const result = withContext(
|
|
1127
|
+
snapshot,
|
|
1128
|
+
() => renderComponentInline(childInstance)
|
|
1129
|
+
);
|
|
1130
|
+
if (result instanceof Promise) {
|
|
1131
|
+
throw new Error(
|
|
1132
|
+
"Async components are not supported. Components must return synchronously."
|
|
1133
|
+
);
|
|
1134
|
+
}
|
|
1135
|
+
const dom = withContext(snapshot, () => createDOMNode(result));
|
|
1136
|
+
if (dom instanceof Element) {
|
|
1137
|
+
mountInstanceInline(childInstance, dom);
|
|
1138
|
+
return dom;
|
|
1139
|
+
}
|
|
1140
|
+
if (!dom) {
|
|
1141
|
+
const placeholder = document.createComment("");
|
|
1142
|
+
childInstance._placeholder = placeholder;
|
|
1143
|
+
childInstance.mounted = true;
|
|
1144
|
+
childInstance.notifyUpdate = childInstance._enqueueRun;
|
|
1145
|
+
return placeholder;
|
|
1146
|
+
}
|
|
1147
|
+
const host = document.createElement("div");
|
|
1148
|
+
host.appendChild(dom);
|
|
1149
|
+
mountInstanceInline(childInstance, host);
|
|
1150
|
+
return host;
|
|
1151
|
+
}
|
|
1152
|
+
function createFragmentElement(node, props) {
|
|
1153
|
+
const fragment = document.createDocumentFragment();
|
|
1154
|
+
const children = props.children || node.children;
|
|
1155
|
+
if (children) {
|
|
1156
|
+
if (Array.isArray(children)) {
|
|
1157
|
+
for (const child of children) {
|
|
1158
|
+
const dom = createDOMNode(child);
|
|
1159
|
+
if (dom) fragment.appendChild(dom);
|
|
1028
1160
|
}
|
|
1029
|
-
|
|
1161
|
+
} else {
|
|
1162
|
+
const dom = createDOMNode(children);
|
|
1163
|
+
if (dom) fragment.appendChild(dom);
|
|
1030
1164
|
}
|
|
1031
1165
|
}
|
|
1032
|
-
return
|
|
1166
|
+
return fragment;
|
|
1033
1167
|
}
|
|
1034
1168
|
function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
1035
1169
|
if (!_isDOMElement(vnode)) {
|
|
1036
1170
|
return;
|
|
1037
1171
|
}
|
|
1038
1172
|
const props = vnode.props || {};
|
|
1039
|
-
|
|
1040
|
-
if (vnodeKey !== void 0) {
|
|
1041
|
-
el.setAttribute("data-key", String(vnodeKey));
|
|
1042
|
-
}
|
|
1173
|
+
materializeKey(el, vnode, props);
|
|
1043
1174
|
const existingListeners = elementListeners.get(el);
|
|
1044
1175
|
const desiredEventNames = /* @__PURE__ */ new Set();
|
|
1045
1176
|
for (const key in props) {
|
|
1046
1177
|
const value = props[key];
|
|
1047
|
-
if (key
|
|
1178
|
+
if (isSkippedProp(key)) continue;
|
|
1179
|
+
const eventName = parseEventName(key);
|
|
1048
1180
|
if (value === void 0 || value === null || value === false) {
|
|
1049
1181
|
if (key === "class" || key === "className") {
|
|
1050
1182
|
el.className = "";
|
|
1051
|
-
} else if (
|
|
1052
|
-
const
|
|
1053
|
-
if (
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
else el.removeEventListener(eventName, entry.handler);
|
|
1058
|
-
existingListeners.delete(eventName);
|
|
1183
|
+
} else if (eventName && existingListeners?.has(eventName)) {
|
|
1184
|
+
const entry = existingListeners.get(eventName);
|
|
1185
|
+
if (entry.options !== void 0) {
|
|
1186
|
+
el.removeEventListener(eventName, entry.handler, entry.options);
|
|
1187
|
+
} else {
|
|
1188
|
+
el.removeEventListener(eventName, entry.handler);
|
|
1059
1189
|
}
|
|
1060
|
-
|
|
1190
|
+
existingListeners.delete(eventName);
|
|
1061
1191
|
} else {
|
|
1062
1192
|
el.removeAttribute(key);
|
|
1063
1193
|
}
|
|
@@ -1067,8 +1197,7 @@ function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
|
1067
1197
|
el.className = String(value);
|
|
1068
1198
|
} else if (key === "value" || key === "checked") {
|
|
1069
1199
|
el[key] = value;
|
|
1070
|
-
} else if (
|
|
1071
|
-
const eventName = key.slice(2).charAt(0).toLowerCase() + key.slice(3).toLowerCase();
|
|
1200
|
+
} else if (eventName) {
|
|
1072
1201
|
desiredEventNames.add(eventName);
|
|
1073
1202
|
const existing = existingListeners?.get(eventName);
|
|
1074
1203
|
if (existing && existing.original === value) {
|
|
@@ -1077,20 +1206,16 @@ function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
|
1077
1206
|
if (existing) {
|
|
1078
1207
|
el.removeEventListener(eventName, existing.handler);
|
|
1079
1208
|
}
|
|
1080
|
-
const wrappedHandler = (
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
} finally {
|
|
1087
|
-
globalScheduler.setInHandler(false);
|
|
1088
|
-
}
|
|
1089
|
-
};
|
|
1090
|
-
const options = eventName === "wheel" || eventName === "scroll" || eventName.startsWith("touch") ? { passive: true } : void 0;
|
|
1091
|
-
if (options !== void 0)
|
|
1209
|
+
const wrappedHandler = createWrappedHandler(
|
|
1210
|
+
value,
|
|
1211
|
+
false
|
|
1212
|
+
);
|
|
1213
|
+
const options = getPassiveOptions(eventName);
|
|
1214
|
+
if (options !== void 0) {
|
|
1092
1215
|
el.addEventListener(eventName, wrappedHandler, options);
|
|
1093
|
-
else
|
|
1216
|
+
} else {
|
|
1217
|
+
el.addEventListener(eventName, wrappedHandler);
|
|
1218
|
+
}
|
|
1094
1219
|
if (!elementListeners.has(el)) {
|
|
1095
1220
|
elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
1096
1221
|
}
|
|
@@ -1105,8 +1230,8 @@ function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
|
1105
1230
|
}
|
|
1106
1231
|
if (existingListeners) {
|
|
1107
1232
|
for (const eventName of existingListeners.keys()) {
|
|
1108
|
-
const entry = existingListeners.get(eventName);
|
|
1109
1233
|
if (!desiredEventNames.has(eventName)) {
|
|
1234
|
+
const entry = existingListeners.get(eventName);
|
|
1110
1235
|
el.removeEventListener(eventName, entry.handler);
|
|
1111
1236
|
existingListeners.delete(eventName);
|
|
1112
1237
|
}
|
|
@@ -1141,6 +1266,14 @@ function updateElementChildren(el, children) {
|
|
|
1141
1266
|
}
|
|
1142
1267
|
function updateUnkeyedChildren(parent, newChildren) {
|
|
1143
1268
|
const existing = Array.from(parent.children);
|
|
1269
|
+
if (newChildren.length === 1 && existing.length === 0 && parent.childNodes.length === 1) {
|
|
1270
|
+
const firstNewChild = newChildren[0];
|
|
1271
|
+
const firstExisting = parent.firstChild;
|
|
1272
|
+
if ((typeof firstNewChild === "string" || typeof firstNewChild === "number") && firstExisting?.nodeType === 3) {
|
|
1273
|
+
firstExisting.data = String(firstNewChild);
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1144
1277
|
if (existing.length === 0 && parent.childNodes.length > 0) {
|
|
1145
1278
|
parent.textContent = "";
|
|
1146
1279
|
}
|
|
@@ -1195,7 +1328,7 @@ function performBulkPositionalKeyedTextUpdate(parent, keyedVnodes) {
|
|
|
1195
1328
|
const total = keyedVnodes.length;
|
|
1196
1329
|
let reused = 0;
|
|
1197
1330
|
let updatedKeys = 0;
|
|
1198
|
-
const t0 =
|
|
1331
|
+
const t0 = now();
|
|
1199
1332
|
for (let i = 0; i < total; i++) {
|
|
1200
1333
|
const { key, vnode } = keyedVnodes[i];
|
|
1201
1334
|
const ch = parent.children[i];
|
|
@@ -1203,202 +1336,209 @@ function performBulkPositionalKeyedTextUpdate(parent, keyedVnodes) {
|
|
|
1203
1336
|
const vnodeType = vnode.type;
|
|
1204
1337
|
if (ch.tagName.toLowerCase() === vnodeType.toLowerCase()) {
|
|
1205
1338
|
const children = vnode.children || vnode.props?.children;
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
}
|
|
1215
|
-
} catch (e) {
|
|
1216
|
-
void e;
|
|
1217
|
-
}
|
|
1218
|
-
if (typeof children === "string" || typeof children === "number") {
|
|
1219
|
-
if (ch.childNodes.length === 1 && ch.firstChild?.nodeType === 3) {
|
|
1220
|
-
ch.firstChild.data = String(children);
|
|
1221
|
-
} else {
|
|
1222
|
-
ch.textContent = String(children);
|
|
1223
|
-
}
|
|
1224
|
-
} else if (Array.isArray(children) && children.length === 1 && (typeof children[0] === "string" || typeof children[0] === "number")) {
|
|
1225
|
-
if (ch.childNodes.length === 1 && ch.firstChild?.nodeType === 3) {
|
|
1226
|
-
ch.firstChild.data = String(children[0]);
|
|
1227
|
-
} else {
|
|
1228
|
-
ch.textContent = String(children[0]);
|
|
1229
|
-
}
|
|
1230
|
-
} else {
|
|
1231
|
-
updateElementFromVnode(ch, vnode);
|
|
1232
|
-
}
|
|
1233
|
-
try {
|
|
1234
|
-
ch.setAttribute("data-key", String(key));
|
|
1235
|
-
updatedKeys++;
|
|
1236
|
-
} catch (e) {
|
|
1237
|
-
void e;
|
|
1238
|
-
}
|
|
1339
|
+
logFastPathDebug("positional idx", i, {
|
|
1340
|
+
chTag: ch.tagName.toLowerCase(),
|
|
1341
|
+
vnodeType,
|
|
1342
|
+
chChildNodes: ch.childNodes.length,
|
|
1343
|
+
childrenType: Array.isArray(children) ? "array" : typeof children
|
|
1344
|
+
});
|
|
1345
|
+
updateTextContent(ch, children);
|
|
1346
|
+
setDataKey(ch, key, () => updatedKeys++);
|
|
1239
1347
|
reused++;
|
|
1240
1348
|
continue;
|
|
1241
1349
|
} else {
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
vnodeType
|
|
1247
|
-
});
|
|
1248
|
-
}
|
|
1249
|
-
} catch (e) {
|
|
1250
|
-
void e;
|
|
1251
|
-
}
|
|
1350
|
+
logFastPathDebug("positional tag mismatch", i, {
|
|
1351
|
+
chTag: ch.tagName.toLowerCase(),
|
|
1352
|
+
vnodeType
|
|
1353
|
+
});
|
|
1252
1354
|
}
|
|
1253
1355
|
} else {
|
|
1254
|
-
|
|
1255
|
-
if (process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true") {
|
|
1256
|
-
logger.warn("[Askr][FASTPATH] positional missing or invalid", i, {
|
|
1257
|
-
ch: !!ch
|
|
1258
|
-
});
|
|
1259
|
-
}
|
|
1260
|
-
} catch (e) {
|
|
1261
|
-
void e;
|
|
1262
|
-
}
|
|
1356
|
+
logFastPathDebug("positional missing or invalid", i, { ch: !!ch });
|
|
1263
1357
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1358
|
+
replaceNodeAtPosition(parent, i, vnode);
|
|
1359
|
+
}
|
|
1360
|
+
const t = now() - t0;
|
|
1361
|
+
updateKeyedElementsMap(parent, keyedVnodes);
|
|
1362
|
+
const stats = { n: total, reused, updatedKeys, t };
|
|
1363
|
+
recordFastPathStats(stats, "bulkKeyedPositionalHits");
|
|
1364
|
+
return stats;
|
|
1365
|
+
}
|
|
1366
|
+
function updateTextContent(el, children) {
|
|
1367
|
+
if (typeof children === "string" || typeof children === "number") {
|
|
1368
|
+
setTextNodeData(el, String(children));
|
|
1369
|
+
} else if (Array.isArray(children) && children.length === 1 && (typeof children[0] === "string" || typeof children[0] === "number")) {
|
|
1370
|
+
setTextNodeData(el, String(children[0]));
|
|
1371
|
+
} else {
|
|
1372
|
+
updateElementFromVnode(el, el);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
function setTextNodeData(el, text) {
|
|
1376
|
+
if (el.childNodes.length === 1 && el.firstChild?.nodeType === 3) {
|
|
1377
|
+
el.firstChild.data = text;
|
|
1378
|
+
} else {
|
|
1379
|
+
el.textContent = text;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
function setDataKey(el, key, onSet) {
|
|
1383
|
+
try {
|
|
1384
|
+
el.setAttribute("data-key", String(key));
|
|
1385
|
+
onSet();
|
|
1386
|
+
} catch {
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
function replaceNodeAtPosition(parent, index, vnode) {
|
|
1390
|
+
const dom = createDOMNode(vnode);
|
|
1391
|
+
if (dom) {
|
|
1392
|
+
const existing = parent.children[index];
|
|
1393
|
+
if (existing) {
|
|
1394
|
+
cleanupInstanceIfPresent(existing);
|
|
1395
|
+
parent.replaceChild(dom, existing);
|
|
1396
|
+
} else {
|
|
1397
|
+
parent.appendChild(dom);
|
|
1271
1398
|
}
|
|
1272
1399
|
}
|
|
1273
|
-
|
|
1400
|
+
}
|
|
1401
|
+
function updateKeyedElementsMap(parent, keyedVnodes) {
|
|
1274
1402
|
try {
|
|
1275
1403
|
const newKeyMap = /* @__PURE__ */ new Map();
|
|
1276
|
-
for (let i = 0; i <
|
|
1404
|
+
for (let i = 0; i < keyedVnodes.length; i++) {
|
|
1277
1405
|
const k = keyedVnodes[i].key;
|
|
1278
1406
|
const ch = parent.children[i];
|
|
1279
1407
|
if (ch) newKeyMap.set(k, ch);
|
|
1280
1408
|
}
|
|
1281
1409
|
keyedElements.set(parent, newKeyMap);
|
|
1282
|
-
} catch
|
|
1283
|
-
void e;
|
|
1284
|
-
}
|
|
1285
|
-
const stats = { n: total, reused, updatedKeys, t };
|
|
1286
|
-
try {
|
|
1287
|
-
if (process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true") {
|
|
1288
|
-
logger.warn("[Askr][FASTPATH] bulk positional stats", stats);
|
|
1289
|
-
}
|
|
1290
|
-
__ASKR_set("__LAST_FASTPATH_STATS", stats);
|
|
1291
|
-
__ASKR_set("__LAST_FASTPATH_COMMIT_COUNT", 1);
|
|
1292
|
-
__ASKR_incCounter("bulkKeyedPositionalHits");
|
|
1293
|
-
} catch (e) {
|
|
1294
|
-
void e;
|
|
1410
|
+
} catch {
|
|
1295
1411
|
}
|
|
1296
|
-
return stats;
|
|
1297
1412
|
}
|
|
1298
1413
|
function performBulkTextReplace(parent, newChildren) {
|
|
1299
|
-
const t0 =
|
|
1414
|
+
const t0 = now();
|
|
1300
1415
|
const existing = Array.from(parent.childNodes);
|
|
1301
1416
|
const finalNodes = [];
|
|
1302
1417
|
let reused = 0;
|
|
1303
1418
|
let created = 0;
|
|
1304
1419
|
for (let i = 0; i < newChildren.length; i++) {
|
|
1305
|
-
const
|
|
1306
|
-
|
|
1307
|
-
if (
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1420
|
+
const result = processChildNode(newChildren[i], existing[i], finalNodes);
|
|
1421
|
+
if (result === "reused") reused++;
|
|
1422
|
+
else if (result === "created") created++;
|
|
1423
|
+
}
|
|
1424
|
+
const tBuild = now() - t0;
|
|
1425
|
+
cleanupRemovedNodes(parent, finalNodes);
|
|
1426
|
+
const tCommit = commitBulkReplace(parent, finalNodes);
|
|
1427
|
+
keyedElements.delete(parent);
|
|
1428
|
+
const stats = {
|
|
1429
|
+
n: newChildren.length,
|
|
1430
|
+
reused,
|
|
1431
|
+
created,
|
|
1432
|
+
tBuild,
|
|
1433
|
+
tCommit
|
|
1434
|
+
};
|
|
1435
|
+
recordBulkTextStats(stats);
|
|
1436
|
+
return stats;
|
|
1437
|
+
}
|
|
1438
|
+
function processChildNode(vnode, existingNode, finalNodes) {
|
|
1439
|
+
if (typeof vnode === "string" || typeof vnode === "number") {
|
|
1440
|
+
return processTextVnode(String(vnode), existingNode, finalNodes);
|
|
1441
|
+
}
|
|
1442
|
+
if (typeof vnode === "object" && vnode !== null && "type" in vnode) {
|
|
1443
|
+
return processElementVnode(vnode, existingNode, finalNodes);
|
|
1444
|
+
}
|
|
1445
|
+
return "skipped";
|
|
1446
|
+
}
|
|
1447
|
+
function processTextVnode(text, existingNode, finalNodes) {
|
|
1448
|
+
if (existingNode && existingNode.nodeType === 3) {
|
|
1449
|
+
existingNode.data = text;
|
|
1450
|
+
finalNodes.push(existingNode);
|
|
1451
|
+
return "reused";
|
|
1452
|
+
}
|
|
1453
|
+
finalNodes.push(document.createTextNode(text));
|
|
1454
|
+
return "created";
|
|
1455
|
+
}
|
|
1456
|
+
function processElementVnode(vnode, existingNode, finalNodes) {
|
|
1457
|
+
const vnodeObj = vnode;
|
|
1458
|
+
if (typeof vnodeObj.type === "string") {
|
|
1459
|
+
const tag = vnodeObj.type;
|
|
1460
|
+
if (existingNode && existingNode.nodeType === 1 && existingNode.tagName.toLowerCase() === tag.toLowerCase()) {
|
|
1461
|
+
updateElementFromVnode(existingNode, vnode);
|
|
1462
|
+
finalNodes.push(existingNode);
|
|
1463
|
+
return "reused";
|
|
1336
1464
|
}
|
|
1337
1465
|
}
|
|
1338
|
-
const
|
|
1466
|
+
const dom = createDOMNode(vnode);
|
|
1467
|
+
if (dom) {
|
|
1468
|
+
finalNodes.push(dom);
|
|
1469
|
+
return "created";
|
|
1470
|
+
}
|
|
1471
|
+
return "skipped";
|
|
1472
|
+
}
|
|
1473
|
+
function cleanupRemovedNodes(parent, keepNodes) {
|
|
1339
1474
|
try {
|
|
1340
1475
|
const toRemove = Array.from(parent.childNodes).filter(
|
|
1341
|
-
(n) => !
|
|
1476
|
+
(n) => !keepNodes.includes(n)
|
|
1342
1477
|
);
|
|
1343
1478
|
for (const n of toRemove) {
|
|
1344
1479
|
if (n instanceof Element) removeAllListeners(n);
|
|
1345
1480
|
cleanupInstanceIfPresent(n);
|
|
1346
1481
|
}
|
|
1347
|
-
} catch
|
|
1348
|
-
void e;
|
|
1482
|
+
} catch {
|
|
1349
1483
|
}
|
|
1484
|
+
}
|
|
1485
|
+
function commitBulkReplace(parent, nodes) {
|
|
1350
1486
|
const fragStart = Date.now();
|
|
1351
1487
|
const fragment = document.createDocumentFragment();
|
|
1352
|
-
for (let i = 0; i <
|
|
1353
|
-
fragment.appendChild(
|
|
1354
|
-
try {
|
|
1355
|
-
__ASKR_incCounter("__DOM_REPLACE_COUNT");
|
|
1356
|
-
__ASKR_set("__LAST_DOM_REPLACE_STACK_DOM", new Error().stack);
|
|
1357
|
-
} catch (e) {
|
|
1358
|
-
void e;
|
|
1488
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1489
|
+
fragment.appendChild(nodes[i]);
|
|
1359
1490
|
}
|
|
1491
|
+
recordDOMReplace("bulk-text-replace");
|
|
1360
1492
|
parent.replaceChildren(fragment);
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
n: newChildren.length,
|
|
1365
|
-
reused,
|
|
1366
|
-
created,
|
|
1367
|
-
tBuild,
|
|
1368
|
-
tCommit
|
|
1369
|
-
};
|
|
1493
|
+
return Date.now() - fragStart;
|
|
1494
|
+
}
|
|
1495
|
+
function recordBulkTextStats(stats) {
|
|
1370
1496
|
try {
|
|
1371
1497
|
__ASKR_set("__LAST_BULK_TEXT_FASTPATH_STATS", stats);
|
|
1372
1498
|
__ASKR_set("__LAST_FASTPATH_STATS", stats);
|
|
1373
1499
|
__ASKR_set("__LAST_FASTPATH_COMMIT_COUNT", 1);
|
|
1374
1500
|
__ASKR_incCounter("bulkTextFastpathHits");
|
|
1375
|
-
} catch
|
|
1376
|
-
void e;
|
|
1501
|
+
} catch {
|
|
1377
1502
|
}
|
|
1378
|
-
return stats;
|
|
1379
1503
|
}
|
|
1380
1504
|
function isBulkTextFastPathEligible(parent, newChildren) {
|
|
1381
1505
|
const threshold = Number(process.env.ASKR_BULK_TEXT_THRESHOLD) || 1024;
|
|
1382
1506
|
const requiredFraction = 0.8;
|
|
1383
1507
|
const total = Array.isArray(newChildren) ? newChildren.length : 0;
|
|
1384
1508
|
if (total < threshold) {
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1509
|
+
recordBulkDiag({
|
|
1510
|
+
phase: "bulk-unkeyed-eligible",
|
|
1511
|
+
reason: "too-small",
|
|
1512
|
+
total,
|
|
1513
|
+
threshold
|
|
1514
|
+
});
|
|
1515
|
+
return false;
|
|
1516
|
+
}
|
|
1517
|
+
const result = countSimpleChildren(newChildren);
|
|
1518
|
+
if (result.componentFound !== void 0) {
|
|
1519
|
+
recordBulkDiag({
|
|
1520
|
+
phase: "bulk-unkeyed-eligible",
|
|
1521
|
+
reason: "component-child",
|
|
1522
|
+
index: result.componentFound
|
|
1523
|
+
});
|
|
1397
1524
|
return false;
|
|
1398
1525
|
}
|
|
1526
|
+
const fraction = result.simple / total;
|
|
1527
|
+
const eligible = fraction >= requiredFraction && parent.childNodes.length >= total;
|
|
1528
|
+
recordBulkDiag({
|
|
1529
|
+
phase: "bulk-unkeyed-eligible",
|
|
1530
|
+
total,
|
|
1531
|
+
simple: result.simple,
|
|
1532
|
+
fraction,
|
|
1533
|
+
requiredFraction,
|
|
1534
|
+
eligible
|
|
1535
|
+
});
|
|
1536
|
+
return eligible;
|
|
1537
|
+
}
|
|
1538
|
+
function countSimpleChildren(children) {
|
|
1399
1539
|
let simple = 0;
|
|
1400
|
-
for (let i = 0; i <
|
|
1401
|
-
const c =
|
|
1540
|
+
for (let i = 0; i < children.length; i++) {
|
|
1541
|
+
const c = children[i];
|
|
1402
1542
|
if (typeof c === "string" || typeof c === "number") {
|
|
1403
1543
|
simple++;
|
|
1404
1544
|
continue;
|
|
@@ -1406,71 +1546,34 @@ function isBulkTextFastPathEligible(parent, newChildren) {
|
|
|
1406
1546
|
if (typeof c === "object" && c !== null && "type" in c) {
|
|
1407
1547
|
const dv = c;
|
|
1408
1548
|
if (typeof dv.type === "function") {
|
|
1409
|
-
|
|
1410
|
-
try {
|
|
1411
|
-
__ASKR_set("__BULK_DIAG", {
|
|
1412
|
-
phase: "bulk-unkeyed-eligible",
|
|
1413
|
-
reason: "component-child",
|
|
1414
|
-
index: i
|
|
1415
|
-
});
|
|
1416
|
-
} catch (e) {
|
|
1417
|
-
void e;
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
return false;
|
|
1549
|
+
return { simple, componentFound: i };
|
|
1421
1550
|
}
|
|
1422
|
-
if (typeof dv.type === "string") {
|
|
1423
|
-
|
|
1424
|
-
if (!children) {
|
|
1425
|
-
simple++;
|
|
1426
|
-
continue;
|
|
1427
|
-
}
|
|
1428
|
-
if (Array.isArray(children)) {
|
|
1429
|
-
if (children.length === 1 && (typeof children[0] === "string" || typeof children[0] === "number")) {
|
|
1430
|
-
simple++;
|
|
1431
|
-
continue;
|
|
1432
|
-
}
|
|
1433
|
-
} else if (typeof children === "string" || typeof children === "number") {
|
|
1434
|
-
simple++;
|
|
1435
|
-
continue;
|
|
1436
|
-
}
|
|
1551
|
+
if (typeof dv.type === "string" && isSimpleElement(dv)) {
|
|
1552
|
+
simple++;
|
|
1437
1553
|
}
|
|
1438
1554
|
}
|
|
1439
1555
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1556
|
+
return { simple };
|
|
1557
|
+
}
|
|
1558
|
+
function isSimpleElement(dv) {
|
|
1559
|
+
const children = dv.children || dv.props?.children;
|
|
1560
|
+
if (!children) return true;
|
|
1561
|
+
if (typeof children === "string" || typeof children === "number") {
|
|
1562
|
+
return true;
|
|
1563
|
+
}
|
|
1564
|
+
if (Array.isArray(children) && children.length === 1 && (typeof children[0] === "string" || typeof children[0] === "number")) {
|
|
1565
|
+
return true;
|
|
1566
|
+
}
|
|
1567
|
+
return false;
|
|
1568
|
+
}
|
|
1569
|
+
function recordBulkDiag(data) {
|
|
1442
1570
|
if (process.env.NODE_ENV !== "production" || process.env.ASKR_FASTPATH_DEBUG === "1") {
|
|
1443
1571
|
try {
|
|
1444
|
-
__ASKR_set("__BULK_DIAG",
|
|
1445
|
-
|
|
1446
|
-
total,
|
|
1447
|
-
simple,
|
|
1448
|
-
fraction,
|
|
1449
|
-
requiredFraction,
|
|
1450
|
-
eligible
|
|
1451
|
-
});
|
|
1452
|
-
} catch (e) {
|
|
1453
|
-
void e;
|
|
1572
|
+
__ASKR_set("__BULK_DIAG", data);
|
|
1573
|
+
} catch {
|
|
1454
1574
|
}
|
|
1455
1575
|
}
|
|
1456
|
-
return eligible;
|
|
1457
1576
|
}
|
|
1458
|
-
var IS_DOM_AVAILABLE;
|
|
1459
|
-
var init_dom = __esm({
|
|
1460
|
-
"src/renderer/dom.ts"() {
|
|
1461
|
-
"use strict";
|
|
1462
|
-
init_scheduler();
|
|
1463
|
-
init_logger();
|
|
1464
|
-
init_jsx_runtime();
|
|
1465
|
-
init_context();
|
|
1466
|
-
init_component();
|
|
1467
|
-
init_cleanup();
|
|
1468
|
-
init_diag();
|
|
1469
|
-
init_types();
|
|
1470
|
-
init_keyed();
|
|
1471
|
-
IS_DOM_AVAILABLE = typeof document !== "undefined";
|
|
1472
|
-
}
|
|
1473
|
-
});
|
|
1474
1577
|
|
|
1475
1578
|
// src/renderer/fastpath.ts
|
|
1476
1579
|
function applyRendererFastPath(parent, keyedVnodes, oldKeyMap, unkeyedVnodes) {
|
|
@@ -1635,320 +1738,571 @@ function applyRendererFastPath(parent, keyedVnodes, oldKeyMap, unkeyedVnodes) {
|
|
|
1635
1738
|
return null;
|
|
1636
1739
|
}
|
|
1637
1740
|
}
|
|
1638
|
-
var init_fastpath = __esm({
|
|
1639
|
-
"src/renderer/fastpath.ts"() {
|
|
1640
|
-
"use strict";
|
|
1641
|
-
init_dom();
|
|
1642
|
-
init_keyed();
|
|
1643
|
-
init_logger();
|
|
1644
|
-
init_cleanup();
|
|
1645
|
-
init_diag();
|
|
1646
|
-
init_scheduler();
|
|
1647
|
-
init_fastlane_shared();
|
|
1648
|
-
}
|
|
1649
|
-
});
|
|
1650
1741
|
|
|
1651
1742
|
// src/renderer/reconcile.ts
|
|
1652
1743
|
function reconcileKeyedChildren(parent, newChildren, oldKeyMap) {
|
|
1653
|
-
|
|
1744
|
+
logReconcileDebug(newChildren);
|
|
1745
|
+
const { keyedVnodes, unkeyedVnodes } = partitionChildren(newChildren);
|
|
1746
|
+
const fastPathResult = tryFastPaths(
|
|
1747
|
+
parent,
|
|
1748
|
+
newChildren,
|
|
1749
|
+
keyedVnodes,
|
|
1750
|
+
unkeyedVnodes,
|
|
1751
|
+
oldKeyMap
|
|
1752
|
+
);
|
|
1753
|
+
if (fastPathResult) return fastPathResult;
|
|
1754
|
+
return performFullReconciliation(parent, newChildren, keyedVnodes, oldKeyMap);
|
|
1755
|
+
}
|
|
1756
|
+
function logReconcileDebug(newChildren) {
|
|
1757
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1758
|
+
try {
|
|
1759
|
+
logger.warn(
|
|
1760
|
+
"[Askr][RECONCILE] reconcileKeyedChildren newChildren sample",
|
|
1761
|
+
{
|
|
1762
|
+
sample: newChildren && newChildren.length && newChildren[0] || null,
|
|
1763
|
+
len: newChildren.length
|
|
1764
|
+
}
|
|
1765
|
+
);
|
|
1766
|
+
} catch {
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
function partitionChildren(newChildren) {
|
|
1654
1771
|
const keyedVnodes = [];
|
|
1655
1772
|
const unkeyedVnodes = [];
|
|
1656
1773
|
for (let i = 0; i < newChildren.length; i++) {
|
|
1657
1774
|
const child = newChildren[i];
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
if (rawKey !== void 0) {
|
|
1662
|
-
const key = typeof rawKey === "symbol" ? String(rawKey) : rawKey;
|
|
1663
|
-
keyedVnodes.push({ key, vnode: child });
|
|
1664
|
-
} else {
|
|
1665
|
-
unkeyedVnodes.push(child);
|
|
1666
|
-
}
|
|
1775
|
+
const key = extractKey(child);
|
|
1776
|
+
if (key !== void 0) {
|
|
1777
|
+
keyedVnodes.push({ key, vnode: child });
|
|
1667
1778
|
} else {
|
|
1668
1779
|
unkeyedVnodes.push(child);
|
|
1669
1780
|
}
|
|
1670
1781
|
}
|
|
1782
|
+
return { keyedVnodes, unkeyedVnodes };
|
|
1783
|
+
}
|
|
1784
|
+
function tryFastPaths(parent, newChildren, keyedVnodes, unkeyedVnodes, oldKeyMap) {
|
|
1671
1785
|
try {
|
|
1672
|
-
const
|
|
1786
|
+
const rendererResult = tryRendererFastPath(
|
|
1673
1787
|
parent,
|
|
1674
1788
|
newChildren,
|
|
1789
|
+
keyedVnodes,
|
|
1790
|
+
unkeyedVnodes,
|
|
1675
1791
|
oldKeyMap
|
|
1676
1792
|
);
|
|
1677
|
-
if (
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1793
|
+
if (rendererResult) return rendererResult;
|
|
1794
|
+
const positionalResult = tryPositionalBulkUpdate(parent, keyedVnodes);
|
|
1795
|
+
if (positionalResult) return positionalResult;
|
|
1796
|
+
} catch {
|
|
1797
|
+
}
|
|
1798
|
+
return null;
|
|
1799
|
+
}
|
|
1800
|
+
function tryRendererFastPath(parent, newChildren, keyedVnodes, unkeyedVnodes, oldKeyMap) {
|
|
1801
|
+
const decision = isKeyedReorderFastPathEligible(
|
|
1802
|
+
parent,
|
|
1803
|
+
newChildren,
|
|
1804
|
+
oldKeyMap
|
|
1805
|
+
);
|
|
1806
|
+
if (decision.useFastPath && keyedVnodes.length >= 128 || isBulkCommitActive2()) {
|
|
1807
|
+
try {
|
|
1808
|
+
const map = applyRendererFastPath(
|
|
1809
|
+
parent,
|
|
1810
|
+
keyedVnodes,
|
|
1811
|
+
oldKeyMap,
|
|
1812
|
+
unkeyedVnodes
|
|
1813
|
+
);
|
|
1814
|
+
if (map) {
|
|
1815
|
+
keyedElements.set(parent, map);
|
|
1816
|
+
return map;
|
|
1817
|
+
}
|
|
1818
|
+
} catch {
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
return null;
|
|
1822
|
+
}
|
|
1823
|
+
function tryPositionalBulkUpdate(parent, keyedVnodes) {
|
|
1824
|
+
const total = keyedVnodes.length;
|
|
1825
|
+
if (total < 10) return null;
|
|
1826
|
+
const matchCount = countPositionalMatches(parent, keyedVnodes);
|
|
1827
|
+
logPositionalCheck(total, matchCount, parent.children.length);
|
|
1828
|
+
if (matchCount / total < 0.9) return null;
|
|
1829
|
+
if (hasPositionalPropChanges(parent, keyedVnodes)) return null;
|
|
1830
|
+
try {
|
|
1831
|
+
const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);
|
|
1832
|
+
recordFastPathStats(stats, "bulkKeyedPositionalHits");
|
|
1833
|
+
rebuildKeyedMap(parent);
|
|
1834
|
+
return keyedElements.get(parent);
|
|
1835
|
+
} catch {
|
|
1836
|
+
return null;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
function countPositionalMatches(parent, keyedVnodes) {
|
|
1840
|
+
let matchCount = 0;
|
|
1841
|
+
try {
|
|
1842
|
+
for (let i = 0; i < keyedVnodes.length; i++) {
|
|
1843
|
+
const vnode = keyedVnodes[i].vnode;
|
|
1844
|
+
if (!vnode || typeof vnode !== "object" || typeof vnode.type !== "string")
|
|
1845
|
+
continue;
|
|
1846
|
+
const el = parent.children[i];
|
|
1847
|
+
if (!el) continue;
|
|
1848
|
+
if (el.tagName.toLowerCase() === String(vnode.type).toLowerCase()) {
|
|
1849
|
+
matchCount++;
|
|
1697
1850
|
}
|
|
1698
1851
|
}
|
|
1852
|
+
} catch {
|
|
1853
|
+
}
|
|
1854
|
+
return matchCount;
|
|
1855
|
+
}
|
|
1856
|
+
function logPositionalCheck(total, matchCount, parentChildren) {
|
|
1857
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1699
1858
|
try {
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
let hasPropChanges = false;
|
|
1718
|
-
try {
|
|
1719
|
-
for (let i = 0; i < total; i++) {
|
|
1720
|
-
const vnode = keyedVnodes[i].vnode;
|
|
1721
|
-
const el = parent.children[i];
|
|
1722
|
-
if (!el || !vnode || typeof vnode !== "object") continue;
|
|
1723
|
-
const props = vnode.props || {};
|
|
1724
|
-
for (const k of Object.keys(props)) {
|
|
1725
|
-
if (k === "children" || k === "key") continue;
|
|
1726
|
-
if (k.startsWith("on") && k.length > 2) continue;
|
|
1727
|
-
if (k.startsWith("data-")) continue;
|
|
1728
|
-
const v = props[k];
|
|
1729
|
-
try {
|
|
1730
|
-
if (k === "class" || k === "className") {
|
|
1731
|
-
if (el.className !== String(v)) {
|
|
1732
|
-
hasPropChanges = true;
|
|
1733
|
-
break;
|
|
1734
|
-
}
|
|
1735
|
-
} else if (k === "value" || k === "checked") {
|
|
1736
|
-
if (el[k] !== v) {
|
|
1737
|
-
hasPropChanges = true;
|
|
1738
|
-
break;
|
|
1739
|
-
}
|
|
1740
|
-
} else {
|
|
1741
|
-
const attr = el.getAttribute(k);
|
|
1742
|
-
if (v === void 0 || v === null || v === false) {
|
|
1743
|
-
if (attr !== null) {
|
|
1744
|
-
hasPropChanges = true;
|
|
1745
|
-
break;
|
|
1746
|
-
}
|
|
1747
|
-
} else if (String(v) !== attr) {
|
|
1748
|
-
hasPropChanges = true;
|
|
1749
|
-
break;
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
} catch (e) {
|
|
1753
|
-
hasPropChanges = true;
|
|
1754
|
-
void e;
|
|
1755
|
-
break;
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
if (hasPropChanges) break;
|
|
1759
|
-
}
|
|
1760
|
-
} catch (e) {
|
|
1761
|
-
void e;
|
|
1762
|
-
}
|
|
1763
|
-
if (hasPropChanges) {
|
|
1764
|
-
} else {
|
|
1765
|
-
try {
|
|
1766
|
-
const stats = performBulkPositionalKeyedTextUpdate(
|
|
1767
|
-
parent,
|
|
1768
|
-
keyedVnodes
|
|
1769
|
-
);
|
|
1770
|
-
if (process.env.NODE_ENV !== "production" || process.env.ASKR_FASTPATH_DEBUG === "1") {
|
|
1771
|
-
try {
|
|
1772
|
-
__ASKR_set("__LAST_FASTPATH_STATS", stats);
|
|
1773
|
-
__ASKR_set("__LAST_FASTPATH_COMMIT_COUNT", 1);
|
|
1774
|
-
__ASKR_incCounter("bulkKeyedPositionalHits");
|
|
1775
|
-
} catch (e) {
|
|
1776
|
-
void e;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
try {
|
|
1780
|
-
const map = /* @__PURE__ */ new Map();
|
|
1781
|
-
const children = Array.from(parent.children);
|
|
1782
|
-
for (let i = 0; i < children.length; i++) {
|
|
1783
|
-
const el = children[i];
|
|
1784
|
-
const k = el.getAttribute("data-key");
|
|
1785
|
-
if (k !== null) {
|
|
1786
|
-
map.set(k, el);
|
|
1787
|
-
const n = Number(k);
|
|
1788
|
-
if (!Number.isNaN(n)) map.set(n, el);
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
keyedElements.set(parent, map);
|
|
1792
|
-
} catch (e) {
|
|
1793
|
-
void e;
|
|
1794
|
-
}
|
|
1795
|
-
return keyedElements.get(parent);
|
|
1796
|
-
} catch (e) {
|
|
1797
|
-
void e;
|
|
1798
|
-
}
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1859
|
+
logger.warn("[Askr][FASTPATH] positional check", {
|
|
1860
|
+
total,
|
|
1861
|
+
matchCount,
|
|
1862
|
+
parentChildren
|
|
1863
|
+
});
|
|
1864
|
+
} catch {
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
function hasPositionalPropChanges(parent, keyedVnodes) {
|
|
1869
|
+
try {
|
|
1870
|
+
for (let i = 0; i < keyedVnodes.length; i++) {
|
|
1871
|
+
const vnode = keyedVnodes[i].vnode;
|
|
1872
|
+
const el = parent.children[i];
|
|
1873
|
+
if (!el || !vnode || typeof vnode !== "object") continue;
|
|
1874
|
+
if (checkPropChanges(el, vnode.props || {})) {
|
|
1875
|
+
return true;
|
|
1801
1876
|
}
|
|
1802
|
-
} catch (e) {
|
|
1803
|
-
void e;
|
|
1804
1877
|
}
|
|
1805
|
-
} catch
|
|
1806
|
-
|
|
1878
|
+
} catch {
|
|
1879
|
+
return true;
|
|
1880
|
+
}
|
|
1881
|
+
return false;
|
|
1882
|
+
}
|
|
1883
|
+
function rebuildKeyedMap(parent) {
|
|
1884
|
+
try {
|
|
1885
|
+
const map = /* @__PURE__ */ new Map();
|
|
1886
|
+
const children = Array.from(parent.children);
|
|
1887
|
+
for (let i = 0; i < children.length; i++) {
|
|
1888
|
+
const el = children[i];
|
|
1889
|
+
const k = el.getAttribute("data-key");
|
|
1890
|
+
if (k !== null) {
|
|
1891
|
+
map.set(k, el);
|
|
1892
|
+
const n = Number(k);
|
|
1893
|
+
if (!Number.isNaN(n)) map.set(n, el);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
keyedElements.set(parent, map);
|
|
1897
|
+
} catch {
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
function performFullReconciliation(parent, newChildren, keyedVnodes, oldKeyMap) {
|
|
1901
|
+
const newKeyMap = /* @__PURE__ */ new Map();
|
|
1902
|
+
const finalNodes = [];
|
|
1903
|
+
const usedOldEls = /* @__PURE__ */ new WeakSet();
|
|
1904
|
+
const resolveOldElOnce = createOldElResolver(parent, oldKeyMap, usedOldEls);
|
|
1905
|
+
for (let i = 0; i < newChildren.length; i++) {
|
|
1906
|
+
const child = newChildren[i];
|
|
1907
|
+
const node = reconcileSingleChild(
|
|
1908
|
+
child,
|
|
1909
|
+
i,
|
|
1910
|
+
parent,
|
|
1911
|
+
resolveOldElOnce,
|
|
1912
|
+
usedOldEls,
|
|
1913
|
+
newKeyMap
|
|
1914
|
+
);
|
|
1915
|
+
if (node) finalNodes.push(node);
|
|
1916
|
+
}
|
|
1917
|
+
if (typeof document === "undefined") return newKeyMap;
|
|
1918
|
+
commitReconciliation(parent, finalNodes);
|
|
1919
|
+
keyedElements.delete(parent);
|
|
1920
|
+
return newKeyMap;
|
|
1921
|
+
}
|
|
1922
|
+
function createOldElResolver(parent, oldKeyMap, usedOldEls) {
|
|
1923
|
+
return (k) => {
|
|
1924
|
+
if (!oldKeyMap) return void 0;
|
|
1925
|
+
const direct = oldKeyMap.get(k);
|
|
1926
|
+
if (direct && !usedOldEls.has(direct)) {
|
|
1927
|
+
usedOldEls.add(direct);
|
|
1928
|
+
return direct;
|
|
1929
|
+
}
|
|
1930
|
+
const s = String(k);
|
|
1931
|
+
const byString = oldKeyMap.get(s);
|
|
1932
|
+
if (byString && !usedOldEls.has(byString)) {
|
|
1933
|
+
usedOldEls.add(byString);
|
|
1934
|
+
return byString;
|
|
1935
|
+
}
|
|
1936
|
+
const n = Number(s);
|
|
1937
|
+
if (!Number.isNaN(n)) {
|
|
1938
|
+
const byNum = oldKeyMap.get(n);
|
|
1939
|
+
if (byNum && !usedOldEls.has(byNum)) {
|
|
1940
|
+
usedOldEls.add(byNum);
|
|
1941
|
+
return byNum;
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
return scanForElementByKey(parent, k, s, usedOldEls);
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
function scanForElementByKey(parent, k, keyStr, usedOldEls) {
|
|
1948
|
+
try {
|
|
1949
|
+
const children = Array.from(parent.children);
|
|
1950
|
+
for (const ch of children) {
|
|
1951
|
+
if (usedOldEls.has(ch)) continue;
|
|
1952
|
+
const attr = ch.getAttribute("data-key");
|
|
1953
|
+
if (attr === keyStr) {
|
|
1954
|
+
usedOldEls.add(ch);
|
|
1955
|
+
return ch;
|
|
1956
|
+
}
|
|
1957
|
+
const numAttr = Number(attr);
|
|
1958
|
+
if (!Number.isNaN(numAttr) && numAttr === k) {
|
|
1959
|
+
usedOldEls.add(ch);
|
|
1960
|
+
return ch;
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
} catch {
|
|
1964
|
+
}
|
|
1965
|
+
return void 0;
|
|
1966
|
+
}
|
|
1967
|
+
function reconcileSingleChild(child, index, parent, resolveOldElOnce, usedOldEls, newKeyMap) {
|
|
1968
|
+
const key = extractKey(child);
|
|
1969
|
+
if (key !== void 0) {
|
|
1970
|
+
return reconcileKeyedChild(child, key, parent, resolveOldElOnce, newKeyMap);
|
|
1971
|
+
}
|
|
1972
|
+
return reconcileUnkeyedChild(child, index, parent, usedOldEls);
|
|
1973
|
+
}
|
|
1974
|
+
function reconcileKeyedChild(child, key, parent, resolveOldElOnce, newKeyMap) {
|
|
1975
|
+
const el = resolveOldElOnce(key);
|
|
1976
|
+
if (el && el.parentElement === parent) {
|
|
1977
|
+
updateElementFromVnode(el, child);
|
|
1978
|
+
newKeyMap.set(key, el);
|
|
1979
|
+
return el;
|
|
1980
|
+
}
|
|
1981
|
+
const dom = createDOMNode(child);
|
|
1982
|
+
if (dom) {
|
|
1983
|
+
if (dom instanceof Element) newKeyMap.set(key, dom);
|
|
1984
|
+
return dom;
|
|
1985
|
+
}
|
|
1986
|
+
return null;
|
|
1987
|
+
}
|
|
1988
|
+
function reconcileUnkeyedChild(child, index, parent, usedOldEls) {
|
|
1989
|
+
try {
|
|
1990
|
+
const existing = parent.children[index];
|
|
1991
|
+
if (existing && (typeof child === "string" || typeof child === "number") && existing.nodeType === 1) {
|
|
1992
|
+
existing.textContent = String(child);
|
|
1993
|
+
usedOldEls.add(existing);
|
|
1994
|
+
return existing;
|
|
1995
|
+
}
|
|
1996
|
+
if (canReuseElement(existing, child)) {
|
|
1997
|
+
updateElementFromVnode(existing, child);
|
|
1998
|
+
usedOldEls.add(existing);
|
|
1999
|
+
return existing;
|
|
2000
|
+
}
|
|
2001
|
+
const avail = findAvailableUnkeyedElement(parent, usedOldEls);
|
|
2002
|
+
if (avail) {
|
|
2003
|
+
const reuseResult = tryReuseElement(avail, child, usedOldEls);
|
|
2004
|
+
if (reuseResult) return reuseResult;
|
|
2005
|
+
}
|
|
2006
|
+
} catch {
|
|
2007
|
+
}
|
|
2008
|
+
const dom = createDOMNode(child);
|
|
2009
|
+
return dom;
|
|
2010
|
+
}
|
|
2011
|
+
function canReuseElement(existing, child) {
|
|
2012
|
+
if (!existing) return false;
|
|
2013
|
+
if (typeof child !== "object" || child === null || !("type" in child))
|
|
2014
|
+
return false;
|
|
2015
|
+
const childObj = child;
|
|
2016
|
+
const hasNoKey = existing.getAttribute("data-key") === null || existing.getAttribute("data-key") === void 0;
|
|
2017
|
+
return hasNoKey && typeof childObj.type === "string" && existing.tagName.toLowerCase() === String(childObj.type).toLowerCase();
|
|
2018
|
+
}
|
|
2019
|
+
function findAvailableUnkeyedElement(parent, usedOldEls) {
|
|
2020
|
+
return Array.from(parent.children).find(
|
|
2021
|
+
(ch) => !usedOldEls.has(ch) && ch.getAttribute("data-key") === null
|
|
2022
|
+
);
|
|
2023
|
+
}
|
|
2024
|
+
function tryReuseElement(avail, child, usedOldEls) {
|
|
2025
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
2026
|
+
avail.textContent = String(child);
|
|
2027
|
+
usedOldEls.add(avail);
|
|
2028
|
+
return avail;
|
|
2029
|
+
}
|
|
2030
|
+
if (typeof child === "object" && child !== null && "type" in child) {
|
|
2031
|
+
const childObj = child;
|
|
2032
|
+
if (typeof childObj.type === "string" && avail.tagName.toLowerCase() === String(childObj.type).toLowerCase()) {
|
|
2033
|
+
updateElementFromVnode(avail, child);
|
|
2034
|
+
usedOldEls.add(avail);
|
|
2035
|
+
return avail;
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
return null;
|
|
2039
|
+
}
|
|
2040
|
+
function commitReconciliation(parent, finalNodes) {
|
|
2041
|
+
const fragment = document.createDocumentFragment();
|
|
2042
|
+
for (let i = 0; i < finalNodes.length; i++) {
|
|
2043
|
+
fragment.appendChild(finalNodes[i]);
|
|
2044
|
+
}
|
|
2045
|
+
try {
|
|
2046
|
+
const existing = Array.from(parent.childNodes);
|
|
2047
|
+
for (const n of existing) {
|
|
2048
|
+
if (n instanceof Element) removeAllListeners(n);
|
|
2049
|
+
cleanupInstanceIfPresent(n);
|
|
2050
|
+
}
|
|
2051
|
+
} catch {
|
|
2052
|
+
}
|
|
2053
|
+
recordDOMReplace("reconcile");
|
|
2054
|
+
parent.replaceChildren(fragment);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
// src/renderer/evaluate.ts
|
|
2058
|
+
var domRanges = /* @__PURE__ */ new WeakMap();
|
|
2059
|
+
function checkSimpleText(vnodeChildren) {
|
|
2060
|
+
if (!Array.isArray(vnodeChildren)) {
|
|
2061
|
+
if (typeof vnodeChildren === "string" || typeof vnodeChildren === "number") {
|
|
2062
|
+
return { isSimple: true, text: String(vnodeChildren) };
|
|
2063
|
+
}
|
|
2064
|
+
} else if (vnodeChildren.length === 1) {
|
|
2065
|
+
const child = vnodeChildren[0];
|
|
2066
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
2067
|
+
return { isSimple: true, text: String(child) };
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
return { isSimple: false };
|
|
2071
|
+
}
|
|
2072
|
+
function tryUpdateTextInPlace(element, text) {
|
|
2073
|
+
if (element.childNodes.length === 1 && element.firstChild?.nodeType === 3) {
|
|
2074
|
+
element.firstChild.data = text;
|
|
2075
|
+
return true;
|
|
2076
|
+
}
|
|
2077
|
+
return false;
|
|
2078
|
+
}
|
|
2079
|
+
function buildKeyMapFromDOM(parent) {
|
|
2080
|
+
const keyMap = /* @__PURE__ */ new Map();
|
|
2081
|
+
const children = Array.from(parent.children);
|
|
2082
|
+
for (const child of children) {
|
|
2083
|
+
const k = child.getAttribute("data-key");
|
|
2084
|
+
if (k !== null) {
|
|
2085
|
+
keyMap.set(k, child);
|
|
2086
|
+
const n = Number(k);
|
|
2087
|
+
if (!Number.isNaN(n)) keyMap.set(n, child);
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
return keyMap;
|
|
2091
|
+
}
|
|
2092
|
+
function getOrBuildKeyMap(parent) {
|
|
2093
|
+
let keyMap = keyedElements.get(parent);
|
|
2094
|
+
if (!keyMap) {
|
|
2095
|
+
keyMap = buildKeyMapFromDOM(parent);
|
|
2096
|
+
if (keyMap.size > 0) {
|
|
2097
|
+
keyedElements.set(parent, keyMap);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
return keyMap.size > 0 ? keyMap : void 0;
|
|
2101
|
+
}
|
|
2102
|
+
function hasKeyedChildren(children) {
|
|
2103
|
+
return children.some(
|
|
2104
|
+
(child) => typeof child === "object" && child !== null && "key" in child
|
|
2105
|
+
);
|
|
2106
|
+
}
|
|
2107
|
+
function trackBulkTextStats(stats) {
|
|
2108
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2109
|
+
try {
|
|
2110
|
+
__ASKR_set("__LAST_BULK_TEXT_FASTPATH_STATS", stats);
|
|
2111
|
+
__ASKR_incCounter("bulkTextHits");
|
|
2112
|
+
} catch {
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
function trackBulkTextMiss() {
|
|
2117
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2118
|
+
try {
|
|
2119
|
+
__ASKR_incCounter("bulkTextMisses");
|
|
2120
|
+
} catch {
|
|
2121
|
+
}
|
|
1807
2122
|
}
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
2123
|
+
}
|
|
2124
|
+
function reconcileKeyed(parent, children, oldKeyMap) {
|
|
2125
|
+
if (process.env.ASKR_FORCE_BULK_POSREUSE === "1") {
|
|
2126
|
+
const result = tryForcedBulkKeyedPath(parent, children);
|
|
2127
|
+
if (result) return;
|
|
2128
|
+
}
|
|
2129
|
+
const newKeyMap = reconcileKeyedChildren(parent, children, oldKeyMap);
|
|
2130
|
+
keyedElements.set(parent, newKeyMap);
|
|
2131
|
+
}
|
|
2132
|
+
function tryForcedBulkKeyedPath(parent, children) {
|
|
2133
|
+
try {
|
|
2134
|
+
const keyedVnodes = [];
|
|
2135
|
+
for (const child of children) {
|
|
2136
|
+
if (_isDOMElement(child) && child.key !== void 0) {
|
|
2137
|
+
keyedVnodes.push({
|
|
2138
|
+
key: child.key,
|
|
2139
|
+
vnode: child
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
1816
2142
|
}
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
if (byString && !usedOldEls.has(byString)) {
|
|
1820
|
-
usedOldEls.add(byString);
|
|
1821
|
-
return byString;
|
|
2143
|
+
if (keyedVnodes.length === 0 || keyedVnodes.length !== children.length) {
|
|
2144
|
+
return false;
|
|
1822
2145
|
}
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
2146
|
+
if (process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true") {
|
|
2147
|
+
logger.warn(
|
|
2148
|
+
"[Askr][FASTPATH] forced positional bulk keyed reuse (evaluate-level)"
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
2151
|
+
const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);
|
|
2152
|
+
if (process.env.NODE_ENV !== "production" || process.env.ASKR_FASTPATH_DEBUG === "1") {
|
|
2153
|
+
try {
|
|
2154
|
+
__ASKR_set("__LAST_FASTPATH_STATS", stats);
|
|
2155
|
+
__ASKR_set("__LAST_FASTPATH_COMMIT_COUNT", 1);
|
|
2156
|
+
__ASKR_incCounter("bulkKeyedPositionalForced");
|
|
2157
|
+
} catch {
|
|
1829
2158
|
}
|
|
1830
2159
|
}
|
|
2160
|
+
const newMap = buildKeyMapFromDOM(parent);
|
|
2161
|
+
keyedElements.set(parent, newMap);
|
|
2162
|
+
return true;
|
|
2163
|
+
} catch (err) {
|
|
2164
|
+
if (process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true") {
|
|
2165
|
+
logger.warn(
|
|
2166
|
+
"[Askr][FASTPATH] forced bulk path failed, falling back",
|
|
2167
|
+
err
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
return false;
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
function reconcileUnkeyed(parent, children) {
|
|
2174
|
+
if (isBulkTextFastPathEligible(parent, children)) {
|
|
2175
|
+
const stats = performBulkTextReplace(parent, children);
|
|
2176
|
+
trackBulkTextStats(stats);
|
|
2177
|
+
} else {
|
|
2178
|
+
trackBulkTextMiss();
|
|
2179
|
+
updateUnkeyedChildren(parent, children);
|
|
2180
|
+
}
|
|
2181
|
+
keyedElements.delete(parent);
|
|
2182
|
+
}
|
|
2183
|
+
function updateElementChildren2(element, vnodeChildren) {
|
|
2184
|
+
if (!vnodeChildren) {
|
|
2185
|
+
element.textContent = "";
|
|
2186
|
+
keyedElements.delete(element);
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
if (!Array.isArray(vnodeChildren)) {
|
|
2190
|
+
element.textContent = "";
|
|
2191
|
+
const dom = createDOMNode(vnodeChildren);
|
|
2192
|
+
if (dom) element.appendChild(dom);
|
|
2193
|
+
keyedElements.delete(element);
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
if (hasKeyedChildren(vnodeChildren)) {
|
|
2197
|
+
const oldKeyMap = getOrBuildKeyMap(element);
|
|
1831
2198
|
try {
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
const numAttr = Number(attr);
|
|
1841
|
-
if (!Number.isNaN(numAttr) && numAttr === k) {
|
|
1842
|
-
usedOldEls.add(ch);
|
|
1843
|
-
return ch;
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
} catch (e) {
|
|
1847
|
-
void e;
|
|
2199
|
+
reconcileKeyed(element, vnodeChildren, oldKeyMap);
|
|
2200
|
+
} catch {
|
|
2201
|
+
const newKeyMap = reconcileKeyedChildren(
|
|
2202
|
+
element,
|
|
2203
|
+
vnodeChildren,
|
|
2204
|
+
oldKeyMap
|
|
2205
|
+
);
|
|
2206
|
+
keyedElements.set(element, newKeyMap);
|
|
1848
2207
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
2208
|
+
} else {
|
|
2209
|
+
reconcileUnkeyed(element, vnodeChildren);
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
function smartUpdateElement(element, vnode) {
|
|
2213
|
+
const vnodeChildren = vnode.children || vnode.props?.children;
|
|
2214
|
+
const textCheck = checkSimpleText(vnodeChildren);
|
|
2215
|
+
if (textCheck.isSimple && tryUpdateTextInPlace(element, textCheck.text)) {
|
|
2216
|
+
} else {
|
|
2217
|
+
updateElementChildren2(element, vnodeChildren);
|
|
2218
|
+
}
|
|
2219
|
+
updateElementFromVnode(element, vnode, false);
|
|
2220
|
+
}
|
|
2221
|
+
function processFragmentChildren(target, childArray) {
|
|
2222
|
+
const existingChildren = Array.from(target.children);
|
|
2223
|
+
for (let i = 0; i < childArray.length; i++) {
|
|
2224
|
+
const childVnode = childArray[i];
|
|
2225
|
+
const existingNode = existingChildren[i];
|
|
2226
|
+
if (existingNode && _isDOMElement(childVnode) && typeof childVnode.type === "string" && existingNode.tagName.toLowerCase() === childVnode.type.toLowerCase()) {
|
|
2227
|
+
smartUpdateElement(existingNode, childVnode);
|
|
2228
|
+
continue;
|
|
2229
|
+
}
|
|
2230
|
+
const newDom = createDOMNode(childVnode);
|
|
2231
|
+
if (newDom) {
|
|
2232
|
+
if (existingNode) {
|
|
2233
|
+
target.replaceChild(newDom, existingNode);
|
|
2234
|
+
} else {
|
|
2235
|
+
target.appendChild(newDom);
|
|
1871
2236
|
}
|
|
1872
2237
|
}
|
|
2238
|
+
}
|
|
2239
|
+
while (target.children.length > childArray.length) {
|
|
2240
|
+
target.removeChild(target.lastChild);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
function createWrappedEventHandler(handler) {
|
|
2244
|
+
return (event) => {
|
|
2245
|
+
globalScheduler.setInHandler(true);
|
|
1873
2246
|
try {
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
2247
|
+
handler(event);
|
|
2248
|
+
} catch (error) {
|
|
2249
|
+
logger.error("[Askr] Event handler error:", error);
|
|
2250
|
+
} finally {
|
|
2251
|
+
globalScheduler.setInHandler(false);
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
function applyPropsToElement2(el, props) {
|
|
2256
|
+
for (const [key, value] of Object.entries(props)) {
|
|
2257
|
+
if (key === "children" || key === "key") continue;
|
|
2258
|
+
if (value === void 0 || value === null || value === false) continue;
|
|
2259
|
+
if (key.startsWith("on") && key.length > 2) {
|
|
2260
|
+
const eventName = key.slice(2).charAt(0).toLowerCase() + key.slice(3).toLowerCase();
|
|
2261
|
+
const wrappedHandler = createWrappedEventHandler(value);
|
|
2262
|
+
const options = eventName === "wheel" || eventName === "scroll" || eventName.startsWith("touch") ? { passive: true } : void 0;
|
|
2263
|
+
if (options !== void 0) {
|
|
2264
|
+
el.addEventListener(eventName, wrappedHandler, options);
|
|
2265
|
+
} else {
|
|
2266
|
+
el.addEventListener(eventName, wrappedHandler);
|
|
1886
2267
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
(ch) => !usedOldEls.has(ch) && ch.getAttribute("data-key") === null
|
|
1890
|
-
);
|
|
1891
|
-
if (avail) {
|
|
1892
|
-
if (typeof child === "string" || typeof child === "number") {
|
|
1893
|
-
avail.textContent = String(child);
|
|
1894
|
-
} else if (typeof child === "object" && child !== null && "type" in child && typeof child.type === "string" && avail.tagName.toLowerCase() === String(child.type).toLowerCase()) {
|
|
1895
|
-
updateElementFromVnode(avail, child);
|
|
1896
|
-
} else {
|
|
1897
|
-
const dom2 = createDOMNode(child);
|
|
1898
|
-
if (dom2) {
|
|
1899
|
-
finalNodes.push(dom2);
|
|
1900
|
-
continue;
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
|
-
usedOldEls.add(avail);
|
|
1904
|
-
finalNodes.push(avail);
|
|
1905
|
-
continue;
|
|
1906
|
-
}
|
|
1907
|
-
} catch (e) {
|
|
1908
|
-
void e;
|
|
2268
|
+
if (!elementListeners.has(el)) {
|
|
2269
|
+
elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
1909
2270
|
}
|
|
1910
|
-
|
|
1911
|
-
|
|
2271
|
+
elementListeners.get(el).set(eventName, {
|
|
2272
|
+
handler: wrappedHandler,
|
|
2273
|
+
original: value,
|
|
2274
|
+
options
|
|
2275
|
+
});
|
|
2276
|
+
continue;
|
|
1912
2277
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
fragment.appendChild(finalNodes[i]);
|
|
1920
|
-
try {
|
|
1921
|
-
const existing = Array.from(parent.childNodes);
|
|
1922
|
-
for (const n of existing) {
|
|
1923
|
-
if (n instanceof Element) removeAllListeners(n);
|
|
1924
|
-
cleanupInstanceIfPresent(n);
|
|
2278
|
+
if (key === "class" || key === "className") {
|
|
2279
|
+
el.className = String(value);
|
|
2280
|
+
} else if (key === "value" || key === "checked") {
|
|
2281
|
+
el[key] = value;
|
|
2282
|
+
} else {
|
|
2283
|
+
el.setAttribute(key, String(value));
|
|
1925
2284
|
}
|
|
1926
|
-
} catch (e) {
|
|
1927
|
-
void e;
|
|
1928
|
-
}
|
|
1929
|
-
try {
|
|
1930
|
-
__ASKR_incCounter("__DOM_REPLACE_COUNT");
|
|
1931
|
-
__ASKR_set("__LAST_DOM_REPLACE_STACK_RECONCILE", new Error().stack);
|
|
1932
|
-
} catch (e) {
|
|
1933
|
-
void e;
|
|
1934
2285
|
}
|
|
1935
|
-
parent.replaceChildren(fragment);
|
|
1936
|
-
keyedElements.delete(parent);
|
|
1937
|
-
return newKeyMap;
|
|
1938
2286
|
}
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
init_keyed();
|
|
1944
|
-
init_cleanup();
|
|
1945
|
-
init_fastlane_shared();
|
|
1946
|
-
init_diag();
|
|
1947
|
-
init_fastpath();
|
|
2287
|
+
function tryFirstRenderKeyedChildren(target, vnode) {
|
|
2288
|
+
const children = vnode.children;
|
|
2289
|
+
if (!Array.isArray(children) || !hasKeyedChildren(children)) {
|
|
2290
|
+
return false;
|
|
1948
2291
|
}
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
2292
|
+
const el = document.createElement(vnode.type);
|
|
2293
|
+
target.appendChild(el);
|
|
2294
|
+
applyPropsToElement2(el, vnode.props || {});
|
|
2295
|
+
const newKeyMap = reconcileKeyedChildren(el, children, void 0);
|
|
2296
|
+
keyedElements.set(el, newKeyMap);
|
|
2297
|
+
return true;
|
|
2298
|
+
}
|
|
2299
|
+
function isFragment(vnode) {
|
|
2300
|
+
return _isDOMElement(vnode) && typeof vnode.type === "symbol" && (vnode.type === Fragment || String(vnode.type) === "Symbol(askr.fragment)");
|
|
2301
|
+
}
|
|
2302
|
+
function getFragmentChildren(vnode) {
|
|
2303
|
+
const fragmentChildren = vnode.props?.children || vnode.children || [];
|
|
2304
|
+
return Array.isArray(fragmentChildren) ? fragmentChildren : [fragmentChildren];
|
|
2305
|
+
}
|
|
1952
2306
|
function evaluate(node, target, context) {
|
|
1953
2307
|
if (!target) return;
|
|
1954
2308
|
if (typeof document === "undefined") {
|
|
@@ -1984,228 +2338,23 @@ function evaluate(node, target, context) {
|
|
|
1984
2338
|
target.insertBefore(dom, end);
|
|
1985
2339
|
}
|
|
1986
2340
|
} else {
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
let textContent;
|
|
1993
|
-
if (!Array.isArray(vnodeChildren)) {
|
|
1994
|
-
if (typeof vnodeChildren === "string" || typeof vnodeChildren === "number") {
|
|
1995
|
-
isSimpleTextVNode = true;
|
|
1996
|
-
textContent = String(vnodeChildren);
|
|
1997
|
-
}
|
|
1998
|
-
} else if (vnodeChildren.length === 1) {
|
|
1999
|
-
const child = vnodeChildren[0];
|
|
2000
|
-
if (typeof child === "string" || typeof child === "number") {
|
|
2001
|
-
isSimpleTextVNode = true;
|
|
2002
|
-
textContent = String(child);
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
if (isSimpleTextVNode && firstChild.childNodes.length === 1 && firstChild.firstChild?.nodeType === 3) {
|
|
2006
|
-
firstChild.firstChild.data = textContent;
|
|
2341
|
+
let vnode = node;
|
|
2342
|
+
if (isFragment(vnode)) {
|
|
2343
|
+
const childArray = getFragmentChildren(vnode);
|
|
2344
|
+
if (childArray.length === 1 && _isDOMElement(childArray[0]) && typeof childArray[0].type === "string") {
|
|
2345
|
+
vnode = childArray[0];
|
|
2007
2346
|
} else {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
const hasKeys = vnodeChildren.some(
|
|
2011
|
-
(child) => typeof child === "object" && child !== null && "key" in child
|
|
2012
|
-
);
|
|
2013
|
-
if (hasKeys) {
|
|
2014
|
-
let oldKeyMap = keyedElements.get(firstChild);
|
|
2015
|
-
if (!oldKeyMap) {
|
|
2016
|
-
oldKeyMap = /* @__PURE__ */ new Map();
|
|
2017
|
-
try {
|
|
2018
|
-
const children = Array.from(firstChild.children);
|
|
2019
|
-
for (let i = 0; i < children.length; i++) {
|
|
2020
|
-
const ch = children[i];
|
|
2021
|
-
const k = ch.getAttribute("data-key");
|
|
2022
|
-
if (k !== null) {
|
|
2023
|
-
oldKeyMap.set(k, ch);
|
|
2024
|
-
const n = Number(k);
|
|
2025
|
-
if (!Number.isNaN(n)) oldKeyMap.set(n, ch);
|
|
2026
|
-
}
|
|
2027
|
-
}
|
|
2028
|
-
if (oldKeyMap.size > 0)
|
|
2029
|
-
keyedElements.set(firstChild, oldKeyMap);
|
|
2030
|
-
} catch (e) {
|
|
2031
|
-
void e;
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
try {
|
|
2035
|
-
if (process.env.ASKR_FORCE_BULK_POSREUSE === "1") {
|
|
2036
|
-
try {
|
|
2037
|
-
const keyedVnodes = [];
|
|
2038
|
-
for (let i = 0; i < vnodeChildren.length; i++) {
|
|
2039
|
-
const c = vnodeChildren[i];
|
|
2040
|
-
if (_isDOMElement(c) && c.key !== void 0) {
|
|
2041
|
-
keyedVnodes.push({
|
|
2042
|
-
key: c.key,
|
|
2043
|
-
vnode: c
|
|
2044
|
-
});
|
|
2045
|
-
}
|
|
2046
|
-
}
|
|
2047
|
-
if (keyedVnodes.length > 0 && keyedVnodes.length === vnodeChildren.length) {
|
|
2048
|
-
if (process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true") {
|
|
2049
|
-
logger.warn(
|
|
2050
|
-
"[Askr][FASTPATH] forced positional bulk keyed reuse (evaluate-level)"
|
|
2051
|
-
);
|
|
2052
|
-
}
|
|
2053
|
-
const stats = performBulkPositionalKeyedTextUpdate(
|
|
2054
|
-
firstChild,
|
|
2055
|
-
keyedVnodes
|
|
2056
|
-
);
|
|
2057
|
-
if (process.env.NODE_ENV !== "production" || process.env.ASKR_FASTPATH_DEBUG === "1") {
|
|
2058
|
-
try {
|
|
2059
|
-
__ASKR_set("__LAST_FASTPATH_STATS", stats);
|
|
2060
|
-
__ASKR_set("__LAST_FASTPATH_COMMIT_COUNT", 1);
|
|
2061
|
-
__ASKR_incCounter("bulkKeyedPositionalForced");
|
|
2062
|
-
} catch (e) {
|
|
2063
|
-
void e;
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
try {
|
|
2067
|
-
const map = /* @__PURE__ */ new Map();
|
|
2068
|
-
const children = Array.from(firstChild.children);
|
|
2069
|
-
for (let i = 0; i < children.length; i++) {
|
|
2070
|
-
const el = children[i];
|
|
2071
|
-
const k = el.getAttribute("data-key");
|
|
2072
|
-
if (k !== null) {
|
|
2073
|
-
map.set(k, el);
|
|
2074
|
-
const n = Number(k);
|
|
2075
|
-
if (!Number.isNaN(n)) map.set(n, el);
|
|
2076
|
-
}
|
|
2077
|
-
}
|
|
2078
|
-
keyedElements.set(firstChild, map);
|
|
2079
|
-
} catch (e) {
|
|
2080
|
-
void e;
|
|
2081
|
-
}
|
|
2082
|
-
} else {
|
|
2083
|
-
const newKeyMap = reconcileKeyedChildren(
|
|
2084
|
-
firstChild,
|
|
2085
|
-
vnodeChildren,
|
|
2086
|
-
oldKeyMap
|
|
2087
|
-
);
|
|
2088
|
-
keyedElements.set(firstChild, newKeyMap);
|
|
2089
|
-
}
|
|
2090
|
-
} catch (err) {
|
|
2091
|
-
if (process.env.ASKR_FASTPATH_DEBUG === "1" || process.env.ASKR_FASTPATH_DEBUG === "true") {
|
|
2092
|
-
logger.warn(
|
|
2093
|
-
"[Askr][FASTPATH] forced bulk path failed, falling back",
|
|
2094
|
-
err
|
|
2095
|
-
);
|
|
2096
|
-
}
|
|
2097
|
-
const newKeyMap = reconcileKeyedChildren(
|
|
2098
|
-
firstChild,
|
|
2099
|
-
vnodeChildren,
|
|
2100
|
-
oldKeyMap
|
|
2101
|
-
);
|
|
2102
|
-
keyedElements.set(firstChild, newKeyMap);
|
|
2103
|
-
}
|
|
2104
|
-
} else {
|
|
2105
|
-
const newKeyMap = reconcileKeyedChildren(
|
|
2106
|
-
firstChild,
|
|
2107
|
-
vnodeChildren,
|
|
2108
|
-
oldKeyMap
|
|
2109
|
-
);
|
|
2110
|
-
keyedElements.set(firstChild, newKeyMap);
|
|
2111
|
-
}
|
|
2112
|
-
} catch (e) {
|
|
2113
|
-
void e;
|
|
2114
|
-
const newKeyMap = reconcileKeyedChildren(
|
|
2115
|
-
firstChild,
|
|
2116
|
-
vnodeChildren,
|
|
2117
|
-
oldKeyMap
|
|
2118
|
-
);
|
|
2119
|
-
keyedElements.set(firstChild, newKeyMap);
|
|
2120
|
-
}
|
|
2121
|
-
} else {
|
|
2122
|
-
if (isBulkTextFastPathEligible(firstChild, vnodeChildren)) {
|
|
2123
|
-
const stats = performBulkTextReplace(firstChild, vnodeChildren);
|
|
2124
|
-
if (process.env.NODE_ENV !== "production") {
|
|
2125
|
-
try {
|
|
2126
|
-
__ASKR_set("__LAST_BULK_TEXT_FASTPATH_STATS", stats);
|
|
2127
|
-
__ASKR_incCounter("bulkTextHits");
|
|
2128
|
-
} catch (e) {
|
|
2129
|
-
void e;
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
} else {
|
|
2133
|
-
if (process.env.NODE_ENV !== "production") {
|
|
2134
|
-
try {
|
|
2135
|
-
__ASKR_incCounter("bulkTextMisses");
|
|
2136
|
-
} catch (e) {
|
|
2137
|
-
void e;
|
|
2138
|
-
}
|
|
2139
|
-
}
|
|
2140
|
-
updateUnkeyedChildren(firstChild, vnodeChildren);
|
|
2141
|
-
keyedElements.delete(firstChild);
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2144
|
-
} else {
|
|
2145
|
-
firstChild.textContent = "";
|
|
2146
|
-
const dom = createDOMNode(vnodeChildren);
|
|
2147
|
-
if (dom) firstChild.appendChild(dom);
|
|
2148
|
-
keyedElements.delete(firstChild);
|
|
2149
|
-
}
|
|
2150
|
-
} else {
|
|
2151
|
-
firstChild.textContent = "";
|
|
2152
|
-
keyedElements.delete(firstChild);
|
|
2153
|
-
}
|
|
2347
|
+
processFragmentChildren(target, childArray);
|
|
2348
|
+
return;
|
|
2154
2349
|
}
|
|
2155
|
-
|
|
2350
|
+
}
|
|
2351
|
+
const firstChild = target.children[0];
|
|
2352
|
+
if (firstChild && _isDOMElement(vnode) && typeof vnode.type === "string" && firstChild.tagName.toLowerCase() === vnode.type.toLowerCase()) {
|
|
2353
|
+
smartUpdateElement(firstChild, vnode);
|
|
2156
2354
|
} else {
|
|
2157
2355
|
target.textContent = "";
|
|
2158
|
-
if (_isDOMElement(vnode) && typeof vnode.type === "string") {
|
|
2159
|
-
|
|
2160
|
-
if (Array.isArray(children) && children.some(
|
|
2161
|
-
(child) => typeof child === "object" && child !== null && "key" in child
|
|
2162
|
-
)) {
|
|
2163
|
-
const el = document.createElement(vnode.type);
|
|
2164
|
-
target.appendChild(el);
|
|
2165
|
-
const props = vnode.props || {};
|
|
2166
|
-
for (const [key, value] of Object.entries(props)) {
|
|
2167
|
-
if (key === "children" || key === "key") continue;
|
|
2168
|
-
if (value === void 0 || value === null || value === false)
|
|
2169
|
-
continue;
|
|
2170
|
-
if (key.startsWith("on") && key.length > 2) {
|
|
2171
|
-
const eventName = key.slice(2).charAt(0).toLowerCase() + key.slice(3).toLowerCase();
|
|
2172
|
-
const wrappedHandler = (event) => {
|
|
2173
|
-
globalScheduler.setInHandler(true);
|
|
2174
|
-
try {
|
|
2175
|
-
value(event);
|
|
2176
|
-
} catch (error) {
|
|
2177
|
-
logger.error("[Askr] Event handler error:", error);
|
|
2178
|
-
} finally {
|
|
2179
|
-
globalScheduler.setInHandler(false);
|
|
2180
|
-
}
|
|
2181
|
-
};
|
|
2182
|
-
const options = eventName === "wheel" || eventName === "scroll" || eventName.startsWith("touch") ? { passive: true } : void 0;
|
|
2183
|
-
if (options !== void 0)
|
|
2184
|
-
el.addEventListener(eventName, wrappedHandler, options);
|
|
2185
|
-
else el.addEventListener(eventName, wrappedHandler);
|
|
2186
|
-
if (!elementListeners.has(el)) {
|
|
2187
|
-
elementListeners.set(el, /* @__PURE__ */ new Map());
|
|
2188
|
-
}
|
|
2189
|
-
elementListeners.get(el).set(eventName, {
|
|
2190
|
-
handler: wrappedHandler,
|
|
2191
|
-
original: value,
|
|
2192
|
-
options
|
|
2193
|
-
});
|
|
2194
|
-
continue;
|
|
2195
|
-
}
|
|
2196
|
-
if (key === "class" || key === "className") {
|
|
2197
|
-
el.className = String(value);
|
|
2198
|
-
} else if (key === "value" || key === "checked") {
|
|
2199
|
-
el[key] = value;
|
|
2200
|
-
} else {
|
|
2201
|
-
el.setAttribute(key, String(value));
|
|
2202
|
-
}
|
|
2203
|
-
}
|
|
2204
|
-
const newKeyMap = reconcileKeyedChildren(el, children, void 0);
|
|
2205
|
-
keyedElements.set(el, newKeyMap);
|
|
2206
|
-
return;
|
|
2207
|
-
return;
|
|
2208
|
-
}
|
|
2356
|
+
if (_isDOMElement(vnode) && typeof vnode.type === "string" && tryFirstRenderKeyedChildren(target, vnode)) {
|
|
2357
|
+
return;
|
|
2209
2358
|
}
|
|
2210
2359
|
const dom = createDOMNode(vnode);
|
|
2211
2360
|
if (dom) {
|
|
@@ -2214,43 +2363,16 @@ function evaluate(node, target, context) {
|
|
|
2214
2363
|
}
|
|
2215
2364
|
}
|
|
2216
2365
|
}
|
|
2217
|
-
var domRanges;
|
|
2218
|
-
var init_evaluate = __esm({
|
|
2219
|
-
"src/renderer/evaluate.ts"() {
|
|
2220
|
-
"use strict";
|
|
2221
|
-
init_scheduler();
|
|
2222
|
-
init_logger();
|
|
2223
|
-
init_cleanup();
|
|
2224
|
-
init_keyed();
|
|
2225
|
-
init_reconcile();
|
|
2226
|
-
init_types();
|
|
2227
|
-
init_dom();
|
|
2228
|
-
init_diag();
|
|
2229
|
-
domRanges = /* @__PURE__ */ new WeakMap();
|
|
2230
|
-
}
|
|
2231
|
-
});
|
|
2232
2366
|
|
|
2233
2367
|
// src/renderer/index.ts
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
init_evaluate();
|
|
2243
|
-
init_keyed();
|
|
2244
|
-
if (typeof globalThis !== "undefined") {
|
|
2245
|
-
const _g = globalThis;
|
|
2246
|
-
_g.__ASKR_RENDERER = {
|
|
2247
|
-
evaluate,
|
|
2248
|
-
isKeyedReorderFastPathEligible,
|
|
2249
|
-
getKeyMapForElement
|
|
2250
|
-
};
|
|
2251
|
-
}
|
|
2252
|
-
}
|
|
2253
|
-
});
|
|
2368
|
+
if (typeof globalThis !== "undefined") {
|
|
2369
|
+
const _g = globalThis;
|
|
2370
|
+
_g.__ASKR_RENDERER = {
|
|
2371
|
+
evaluate,
|
|
2372
|
+
isKeyedReorderFastPathEligible,
|
|
2373
|
+
getKeyMapForElement
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2254
2376
|
|
|
2255
2377
|
// src/runtime/component.ts
|
|
2256
2378
|
function createComponentInstance(id, fn, props, target) {
|
|
@@ -2302,6 +2424,8 @@ function createComponentInstance(id, fn, props, target) {
|
|
|
2302
2424
|
};
|
|
2303
2425
|
return instance;
|
|
2304
2426
|
}
|
|
2427
|
+
var currentInstance = null;
|
|
2428
|
+
var stateIndex = 0;
|
|
2305
2429
|
function getCurrentComponentInstance() {
|
|
2306
2430
|
return currentInstance;
|
|
2307
2431
|
}
|
|
@@ -2353,6 +2477,7 @@ function mountInstanceInline(instance, target) {
|
|
|
2353
2477
|
executeMountOperations(instance);
|
|
2354
2478
|
}
|
|
2355
2479
|
}
|
|
2480
|
+
var _globalRenderCounter = 0;
|
|
2356
2481
|
function runComponent(instance) {
|
|
2357
2482
|
instance.notifyUpdate = instance._enqueueRun;
|
|
2358
2483
|
instance._currentRenderToken = ++_globalRenderCounter;
|
|
@@ -2372,6 +2497,34 @@ function runComponent(instance) {
|
|
|
2372
2497
|
if (process.env.NODE_ENV !== "production") throw err;
|
|
2373
2498
|
}
|
|
2374
2499
|
globalScheduler.enqueue(() => {
|
|
2500
|
+
if (!instance.target && instance._placeholder) {
|
|
2501
|
+
if (result === null || result === void 0) {
|
|
2502
|
+
finalizeReadSubscriptions(instance);
|
|
2503
|
+
return;
|
|
2504
|
+
}
|
|
2505
|
+
const placeholder = instance._placeholder;
|
|
2506
|
+
const parent = placeholder.parentNode;
|
|
2507
|
+
if (!parent) {
|
|
2508
|
+
logger.warn(
|
|
2509
|
+
"[Askr] placeholder no longer in DOM, cannot render component"
|
|
2510
|
+
);
|
|
2511
|
+
return;
|
|
2512
|
+
}
|
|
2513
|
+
const host = document.createElement("div");
|
|
2514
|
+
const oldInstance = currentInstance;
|
|
2515
|
+
currentInstance = instance;
|
|
2516
|
+
try {
|
|
2517
|
+
evaluate(result, host);
|
|
2518
|
+
parent.replaceChild(host, placeholder);
|
|
2519
|
+
instance.target = host;
|
|
2520
|
+
instance._placeholder = void 0;
|
|
2521
|
+
host.__ASKR_INSTANCE = instance;
|
|
2522
|
+
finalizeReadSubscriptions(instance);
|
|
2523
|
+
} finally {
|
|
2524
|
+
currentInstance = oldInstance;
|
|
2525
|
+
}
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2375
2528
|
if (instance.target) {
|
|
2376
2529
|
let oldChildren = [];
|
|
2377
2530
|
try {
|
|
@@ -2454,6 +2607,8 @@ function runComponent(instance) {
|
|
|
2454
2607
|
}
|
|
2455
2608
|
function renderComponentInline(instance) {
|
|
2456
2609
|
const hadToken = instance._currentRenderToken !== void 0;
|
|
2610
|
+
const prevToken = instance._currentRenderToken;
|
|
2611
|
+
const prevPendingReads = instance._pendingReadStates;
|
|
2457
2612
|
if (!hadToken) {
|
|
2458
2613
|
instance._currentRenderToken = ++_globalRenderCounter;
|
|
2459
2614
|
instance._pendingReadStates = /* @__PURE__ */ new Set();
|
|
@@ -2465,10 +2620,8 @@ function renderComponentInline(instance) {
|
|
|
2465
2620
|
}
|
|
2466
2621
|
return result;
|
|
2467
2622
|
} finally {
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
instance._currentRenderToken = void 0;
|
|
2471
|
-
}
|
|
2623
|
+
instance._currentRenderToken = prevToken;
|
|
2624
|
+
instance._pendingReadStates = prevPendingReads ?? /* @__PURE__ */ new Set();
|
|
2472
2625
|
}
|
|
2473
2626
|
}
|
|
2474
2627
|
function executeComponentSync(instance) {
|
|
@@ -2599,75 +2752,11 @@ function cleanupComponent(instance) {
|
|
|
2599
2752
|
instance._lastReadStates = /* @__PURE__ */ new Set();
|
|
2600
2753
|
}
|
|
2601
2754
|
instance.abortController.abort();
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
var init_component = __esm({
|
|
2605
|
-
"src/runtime/component.ts"() {
|
|
2606
|
-
"use strict";
|
|
2607
|
-
init_scheduler();
|
|
2608
|
-
init_context();
|
|
2609
|
-
init_logger();
|
|
2610
|
-
init_diag();
|
|
2611
|
-
init_fastlane_shared();
|
|
2612
|
-
init_renderer();
|
|
2613
|
-
currentInstance = null;
|
|
2614
|
-
stateIndex = 0;
|
|
2615
|
-
_globalRenderCounter = 0;
|
|
2616
|
-
}
|
|
2617
|
-
});
|
|
2618
|
-
|
|
2619
|
-
// src/router/route.ts
|
|
2620
|
-
var route_exports = {};
|
|
2621
|
-
__export(route_exports, {
|
|
2622
|
-
_lockRouteRegistrationForTests: () => _lockRouteRegistrationForTests,
|
|
2623
|
-
_unlockRouteRegistrationForTests: () => _unlockRouteRegistrationForTests,
|
|
2624
|
-
clearRoutes: () => clearRoutes,
|
|
2625
|
-
getLoadedNamespaces: () => getLoadedNamespaces,
|
|
2626
|
-
getNamespaceRoutes: () => getNamespaceRoutes,
|
|
2627
|
-
getRoutes: () => getRoutes,
|
|
2628
|
-
lockRouteRegistration: () => lockRouteRegistration,
|
|
2629
|
-
registerRoute: () => registerRoute,
|
|
2630
|
-
resolveRoute: () => resolveRoute,
|
|
2631
|
-
route: () => route,
|
|
2632
|
-
setServerLocation: () => setServerLocation,
|
|
2633
|
-
unloadNamespace: () => unloadNamespace
|
|
2634
|
-
});
|
|
2635
|
-
|
|
2636
|
-
// src/router/match.ts
|
|
2637
|
-
function match(path, pattern) {
|
|
2638
|
-
const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
2639
|
-
const normalizedPattern = pattern.endsWith("/") && pattern !== "/" ? pattern.slice(0, -1) : pattern;
|
|
2640
|
-
const pathSegments = normalizedPath.split("/").filter(Boolean);
|
|
2641
|
-
const patternSegments = normalizedPattern.split("/").filter(Boolean);
|
|
2642
|
-
if (patternSegments.length === 1 && patternSegments[0] === "*") {
|
|
2643
|
-
return {
|
|
2644
|
-
matched: true,
|
|
2645
|
-
params: {
|
|
2646
|
-
"*": pathSegments.length > 1 ? normalizedPath : pathSegments[0]
|
|
2647
|
-
}
|
|
2648
|
-
};
|
|
2649
|
-
}
|
|
2650
|
-
if (pathSegments.length !== patternSegments.length) {
|
|
2651
|
-
return { matched: false, params: {} };
|
|
2652
|
-
}
|
|
2653
|
-
const params = {};
|
|
2654
|
-
for (let i = 0; i < patternSegments.length; i++) {
|
|
2655
|
-
const patternSegment = patternSegments[i];
|
|
2656
|
-
const pathSegment = pathSegments[i];
|
|
2657
|
-
if (patternSegment.startsWith("{") && patternSegment.endsWith("}")) {
|
|
2658
|
-
const paramName = patternSegment.slice(1, -1);
|
|
2659
|
-
params[paramName] = decodeURIComponent(pathSegment);
|
|
2660
|
-
} else if (patternSegment === "*") {
|
|
2661
|
-
params["*"] = pathSegment;
|
|
2662
|
-
} else if (patternSegment !== pathSegment) {
|
|
2663
|
-
return { matched: false, params: {} };
|
|
2664
|
-
}
|
|
2665
|
-
}
|
|
2666
|
-
return { matched: true, params };
|
|
2755
|
+
instance.notifyUpdate = null;
|
|
2756
|
+
instance.mounted = false;
|
|
2667
2757
|
}
|
|
2668
2758
|
|
|
2669
2759
|
// src/router/route.ts
|
|
2670
|
-
init_component();
|
|
2671
2760
|
var routes = [];
|
|
2672
2761
|
var namespaces = /* @__PURE__ */ new Set();
|
|
2673
2762
|
var routesByDepth = /* @__PURE__ */ new Map();
|
|
@@ -2981,31 +3070,34 @@ function resolveRoute(pathname) {
|
|
|
2981
3070
|
|
|
2982
3071
|
export {
|
|
2983
3072
|
invariant,
|
|
2984
|
-
init_invariant,
|
|
2985
3073
|
logger,
|
|
2986
|
-
init_logger,
|
|
2987
3074
|
globalScheduler,
|
|
2988
3075
|
scheduleEventHandler,
|
|
2989
|
-
init_scheduler,
|
|
2990
3076
|
withAsyncResourceContext,
|
|
2991
3077
|
defineContext,
|
|
2992
3078
|
readContext,
|
|
2993
3079
|
getCurrentContextFrame,
|
|
2994
|
-
|
|
3080
|
+
setDevValue,
|
|
3081
|
+
getDevValue,
|
|
3082
|
+
enterBulkCommit,
|
|
3083
|
+
exitBulkCommit,
|
|
2995
3084
|
isBulkCommitActive2 as isBulkCommitActive,
|
|
2996
|
-
|
|
3085
|
+
markFastPathApplied,
|
|
3086
|
+
isFastPathApplied,
|
|
2997
3087
|
removeAllListeners,
|
|
2998
|
-
|
|
3088
|
+
getKeyMapForElement,
|
|
3089
|
+
populateKeyMapForElement,
|
|
3090
|
+
isKeyedReorderFastPathEligible,
|
|
2999
3091
|
createComponentInstance,
|
|
3000
3092
|
getCurrentComponentInstance,
|
|
3001
3093
|
setCurrentComponentInstance,
|
|
3002
3094
|
registerMountOperation,
|
|
3003
3095
|
getCurrentInstance,
|
|
3004
3096
|
getSignal,
|
|
3097
|
+
finalizeReadSubscriptions,
|
|
3005
3098
|
getNextStateIndex,
|
|
3006
3099
|
mountComponent,
|
|
3007
3100
|
cleanupComponent,
|
|
3008
|
-
init_component,
|
|
3009
3101
|
setServerLocation,
|
|
3010
3102
|
lockRouteRegistration,
|
|
3011
3103
|
_lockRouteRegistrationForTests,
|
|
@@ -3020,4 +3112,4 @@ export {
|
|
|
3020
3112
|
resolveRoute,
|
|
3021
3113
|
route_exports
|
|
3022
3114
|
};
|
|
3023
|
-
//# sourceMappingURL=chunk-
|
|
3115
|
+
//# sourceMappingURL=chunk-2ONGHQ7Z.js.map
|