@skillbuilder/miniapp-simulator 0.0.0-beta-20261023084421 → 0.2.0

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.
Files changed (37) hide show
  1. package/README.md +52 -2
  2. package/dist/sw/miniapp-simulator-service-worker.js +487 -371
  3. package/dist/sw/miniapp-simulator-service-worker.min.js +1 -1
  4. package/docs/external-cli-workbench.md +5 -7
  5. package/docs/npm-integration-verification.md +1 -11
  6. package/docs/remote-architecture.md +3 -2
  7. package/docs/worker-runtime.md +62 -0
  8. package/lib/{client-BZtD2VtP.mjs → client-CO-UjIY3.mjs} +141 -138
  9. package/lib/index-B5oixYXr.mjs +574 -0
  10. package/lib/index.js +1152 -1075
  11. package/lib/remote-client.js +2 -2
  12. package/lib/types/capabilities/constants.d.ts +1 -0
  13. package/lib/types/capabilities/csp-snippet.d.ts +2 -0
  14. package/lib/types/capabilities/security-head-snippet.d.ts +3 -2
  15. package/lib/types/index.d.ts +8 -1
  16. package/lib/types/injection/types.d.ts +2 -0
  17. package/lib/types/remote/protocol.d.ts +7 -2
  18. package/lib/types/renderer/content-host/iframe-content-host.d.ts +1 -0
  19. package/lib/types/sw/protocol.d.ts +3 -1
  20. package/lib/types/sw/served-entry.d.ts +1 -1
  21. package/lib/types/sw/service-worker-host.d.ts +1 -0
  22. package/lib/types/sw/worker/globals.d.ts +1 -0
  23. package/lib/types/sw/worker/mount-store.d.ts +5 -0
  24. package/lib/types/types/options.d.ts +8 -1
  25. package/lib/types/workbench/server/index.d.ts +1 -1
  26. package/lib/types/worker/adapters/csp-policy.d.ts +7 -0
  27. package/lib/types/worker/adapters/host-lifecycle.d.ts +5 -0
  28. package/lib/types/worker/adapters/mount-recovery.d.ts +2 -0
  29. package/lib/types/worker/adapters/package-policy.d.ts +12 -0
  30. package/lib/types/worker/adapters/page-lifecycle.d.ts +1 -0
  31. package/lib/types/worker/adapters/protocol.d.ts +49 -0
  32. package/lib/types/worker/adapters/scripts.d.ts +2 -0
  33. package/lib/types/worker/adapters/service-worker.d.ts +2 -0
  34. package/lib/workbench-server.mjs +1 -1
  35. package/lib/workbench.js +1 -1
  36. package/package.json +1 -1
  37. package/lib/index-BW85h7kT.mjs +0 -505
@@ -0,0 +1,574 @@
1
+ const E = "0.2.0", _ = /* @__PURE__ */ new Set();
2
+ function M(e, n) {
3
+ const t = () => {
4
+ let s = !document.hidden && e.isConnected;
5
+ for (let r = e; s && r; ) {
6
+ const a = getComputedStyle(r);
7
+ s = a.display !== "none" && a.visibility !== "hidden" && a.visibility !== "collapse";
8
+ const c = r.getRootNode();
9
+ r = r.parentElement ?? (c instanceof ShadowRoot ? c.host : null);
10
+ }
11
+ n(s);
12
+ }, i = new MutationObserver(t);
13
+ for (let s = e; s; ) {
14
+ i.observe(s, { attributes: !0, attributeFilter: ["style", "class", "hidden"] });
15
+ const r = s.getRootNode();
16
+ s = s.parentElement ?? (r instanceof ShadowRoot ? r.host : null);
17
+ }
18
+ return document.addEventListener("visibilitychange", t), window.addEventListener("resize", t), window.addEventListener("pageshow", t), t(), () => {
19
+ i.disconnect(), document.removeEventListener("visibilitychange", t), window.removeEventListener("resize", t), window.removeEventListener("pageshow", t);
20
+ };
21
+ }
22
+ function G(e, n) {
23
+ let t = "", i = 0;
24
+ const s = () => {
25
+ if (document.hidden || !e.isConnected) return !1;
26
+ for (let o = e; o; ) {
27
+ const u = getComputedStyle(o);
28
+ if (u.display === "none" || u.visibility === "hidden" || u.visibility === "collapse")
29
+ return !1;
30
+ const d = o.getRootNode();
31
+ o = o.parentElement ?? (d instanceof ShadowRoot ? d.host : null);
32
+ }
33
+ return !0;
34
+ }, r = () => {
35
+ if (t)
36
+ try {
37
+ const o = new URL(n(), location.href).origin;
38
+ e.contentWindow?.postMessage(
39
+ {
40
+ type: "mini-app:worker-state",
41
+ sessionId: t,
42
+ sequence: ++i,
43
+ state: s() ? "visible" : "hidden"
44
+ },
45
+ o
46
+ );
47
+ } catch {
48
+ }
49
+ }, a = (o) => {
50
+ if (!(!o.isTrusted || o.source !== e.contentWindow || o.data?.type !== "mini-app:worker-ready" || typeof o.data.sessionId != "string")) {
51
+ try {
52
+ if (o.origin !== new URL(n(), location.href).origin || e.contentWindow?.__MINITOOL_WORKER_CONTEXT__?.sessionId !== o.data.sessionId)
53
+ return;
54
+ } catch {
55
+ return;
56
+ }
57
+ t = o.data.sessionId, r();
58
+ }
59
+ }, c = new MutationObserver(r);
60
+ for (let o = e; o; ) {
61
+ c.observe(o, { attributes: !0, attributeFilter: ["style", "class", "hidden"] });
62
+ const u = o.getRootNode();
63
+ o = o.parentElement ?? (u instanceof ShadowRoot ? u.host : null);
64
+ }
65
+ return window.addEventListener("message", a), window.addEventListener("resize", r), window.addEventListener("pageshow", r), document.addEventListener("visibilitychange", r), _.add(r), () => {
66
+ _.delete(r), c.disconnect(), window.removeEventListener("message", a), window.removeEventListener("resize", r), window.removeEventListener("pageshow", r), document.removeEventListener("visibilitychange", r);
67
+ };
68
+ }
69
+ var l = /* @__PURE__ */ ((e) => (e[e.INVALID_PARAM = 10001] = "INVALID_PARAM", e[e.API_UNAVAILABLE = 10002] = "API_UNAVAILABLE", e[e.URL_SCHEME_NOT_ALLOWED = 10003] = "URL_SCHEME_NOT_ALLOWED", e[e.REQUEST_TIMEOUT = 10101] = "REQUEST_TIMEOUT", e[e.REQUEST_ABORTED = 10102] = "REQUEST_ABORTED", e[e.REQUEST_FAILED = 15201] = "REQUEST_FAILED", e[e.STORAGE_IO_ERROR = 50101] = "STORAGE_IO_ERROR", e[e.STORAGE_QUOTA_EXCEEDED = 50201] = "STORAGE_QUOTA_EXCEEDED", e[e.FILE_NOT_FOUND = 50202] = "FILE_NOT_FOUND", e[e.PATH_INVALID = 50203] = "PATH_INVALID", e[e.FILE_ALREADY_EXISTS = 50204] = "FILE_ALREADY_EXISTS", e[e.NOT_A_FILE = 50205] = "NOT_A_FILE", e[e.NOT_A_DIRECTORY = 50206] = "NOT_A_DIRECTORY", e))(l || {});
70
+ function f(e, n) {
71
+ return Object.assign(new Error(n), { code: e });
72
+ }
73
+ class k {
74
+ constructor() {
75
+ this.buffer = "";
76
+ }
77
+ push(n) {
78
+ return n && (this.buffer += n), this.drain(!1);
79
+ }
80
+ /** SSE 末尾没有空行时属于未完成帧,不向调用方发送。 */
81
+ finish() {
82
+ const n = this.drain(!0);
83
+ return this.buffer = "", n;
84
+ }
85
+ drain(n) {
86
+ const t = [];
87
+ let i = 0, s = 0, r = 0;
88
+ for (; r < this.buffer.length; ) {
89
+ const a = this.buffer[r];
90
+ if (a !== "\r" && a !== `
91
+ `) {
92
+ r += 1;
93
+ continue;
94
+ }
95
+ let c = r + 1;
96
+ if (a === "\r") {
97
+ if (c === this.buffer.length && !n) break;
98
+ this.buffer[c] === `
99
+ ` && (c += 1);
100
+ }
101
+ r === s && (t.push(this.buffer.slice(i, c)), i = c), s = c, r = c;
102
+ }
103
+ return i > 0 && (this.buffer = this.buffer.slice(i)), t;
104
+ }
105
+ }
106
+ function X() {
107
+ let e = "";
108
+ const n = (t) => {
109
+ const i = [];
110
+ let s = 0, r = 0, a = 0;
111
+ for (; a < e.length; ) {
112
+ const c = e[a];
113
+ if (c !== "\r" && c !== `
114
+ `) {
115
+ a += 1;
116
+ continue;
117
+ }
118
+ let o = a + 1;
119
+ if (c === "\r") {
120
+ if (o === e.length && !t) break;
121
+ e[o] === `
122
+ ` && (o += 1);
123
+ }
124
+ a === r && (i.push(e.slice(s, o)), s = o), r = o, a = o;
125
+ }
126
+ return s > 0 && (e = e.slice(s)), i;
127
+ };
128
+ return {
129
+ push(t) {
130
+ return t && (e += t), n(!1);
131
+ },
132
+ finish() {
133
+ const t = n(!0);
134
+ return e = "", t;
135
+ }
136
+ };
137
+ }
138
+ function p(e) {
139
+ return e?.toLowerCase().includes("text/event-stream") ?? !1;
140
+ }
141
+ const T = /* @__PURE__ */ new WeakMap();
142
+ async function Y(e, n, t) {
143
+ O(n.data);
144
+ const i = T.get(e);
145
+ if (i) return i(n, t);
146
+ const s = await e(I(n, t.signal));
147
+ if (t.signal.aborted)
148
+ throw f(l.REQUEST_ABORTED, "request aborted");
149
+ x(s);
150
+ const r = U(s.header);
151
+ return t.onHeaders({ taskId: n.taskId, statusCode: s.statusCode, header: r }), n.enableChunked && p(r["content-type"]) && (typeof s.data == "string" || D(s.data)) ? (await N(s.data, n.taskId, t), { taskId: n.taskId, statusCode: s.statusCode, data: "", header: r }) : {
152
+ taskId: n.taskId,
153
+ statusCode: s.statusCode,
154
+ data: await B(s.data, n),
155
+ header: r
156
+ };
157
+ }
158
+ function I(e, n) {
159
+ const t = e.data, i = { ...e.header }, s = e.method.toUpperCase();
160
+ return s === "GET" || s === "HEAD" ? {
161
+ url: R(e.url, g(t)),
162
+ method: e.method,
163
+ header: i,
164
+ responseType: e.responseType,
165
+ enableChunked: e.enableChunked,
166
+ signal: n
167
+ } : {
168
+ url: e.url,
169
+ method: e.method,
170
+ header: i,
171
+ data: L(t, i),
172
+ responseType: e.responseType,
173
+ enableChunked: e.enableChunked,
174
+ signal: n
175
+ };
176
+ }
177
+ function R(e, n) {
178
+ if (!n) return e;
179
+ const t = e.indexOf("#"), i = t >= 0 ? e.slice(t) : "", s = t >= 0 ? e.slice(0, t) : e;
180
+ return `${s}${s.includes("?") ? "&" : "?"}${n}${i}`;
181
+ }
182
+ function g(e) {
183
+ return e == null ? "" : typeof e == "string" ? e : typeof e != "object" || Array.isArray(e) ? String(e) : Object.entries(e).map(([n, t]) => `${encodeURIComponent(n)}=${encodeURIComponent(String(t))}`).join("&");
184
+ }
185
+ function L(e, n) {
186
+ if (e == null || typeof e == "string") return e;
187
+ let t = S(n, "content-type");
188
+ return t || (t = "application/json", n["content-type"] = t), t.toLowerCase().includes("application/json") ? JSON.stringify(e) : t.toLowerCase().includes("application/x-www-form-urlencoded") ? g(e) : String(e);
189
+ }
190
+ function S(e, n) {
191
+ const t = Object.keys(e).find((i) => i.toLowerCase() === n);
192
+ return t ? String(e[t]) : void 0;
193
+ }
194
+ function O(e) {
195
+ if (!(!(e instanceof ArrayBuffer) && !ArrayBuffer.isView(e)))
196
+ throw f(
197
+ l.INVALID_PARAM,
198
+ "request data does not support ArrayBuffer"
199
+ );
200
+ }
201
+ function x(e) {
202
+ if (!e || typeof e != "object" || typeof e.statusCode != "number")
203
+ throw f(
204
+ l.REQUEST_FAILED,
205
+ "host request adapter returned an invalid response"
206
+ );
207
+ }
208
+ function D(e) {
209
+ return !!(e && typeof e == "object" && "getReader" in e);
210
+ }
211
+ async function N(e, n, t) {
212
+ const i = new k(), s = (o) => {
213
+ for (const u of i.push(o)) t.onChunk({ taskId: n, chunk: u });
214
+ };
215
+ if (typeof e == "string") {
216
+ s(e);
217
+ for (const o of i.finish()) t.onChunk({ taskId: n, chunk: o });
218
+ return;
219
+ }
220
+ const r = e.getReader(), a = new TextDecoder(), c = () => void r.cancel().catch(() => {
221
+ });
222
+ t.signal.addEventListener("abort", c, { once: !0 });
223
+ try {
224
+ for (; ; ) {
225
+ if (t.signal.aborted) return;
226
+ const u = await r.read();
227
+ if (u.done) break;
228
+ const d = typeof u.value == "string" ? u.value : a.decode(u.value, { stream: !0 });
229
+ d && s(d);
230
+ }
231
+ const o = a.decode();
232
+ o && s(o);
233
+ for (const u of i.finish()) t.onChunk({ taskId: n, chunk: u });
234
+ } finally {
235
+ t.signal.removeEventListener("abort", c), r.releaseLock();
236
+ }
237
+ }
238
+ function U(e) {
239
+ const n = {};
240
+ for (const [t, i] of Object.entries(e ?? {}))
241
+ t.toLowerCase() !== "set-cookie" && (n[t.toLowerCase()] = String(i));
242
+ return n;
243
+ }
244
+ async function B(e, n) {
245
+ if (e instanceof ArrayBuffer || ArrayBuffer.isView(e))
246
+ throw f(
247
+ l.REQUEST_FAILED,
248
+ "request response does not support ArrayBuffer"
249
+ );
250
+ if (n.dataType === "json" && typeof e == "string")
251
+ try {
252
+ return JSON.parse(e);
253
+ } catch {
254
+ return e;
255
+ }
256
+ return e;
257
+ }
258
+ const P = "miniapp_simulator_event", A = "skillbuilder-miniapp", C = {
259
+ cn: {
260
+ production: "https://apm-fe.xiaohongshu.com/api/data",
261
+ development: "https://apm-fe-test.xiaohongshu.com/api/data"
262
+ },
263
+ sg: {
264
+ production: "https://apm-fe.rnote.com/api/data",
265
+ development: "https://apm-fe.rnote.com/api/data"
266
+ }
267
+ }, F = 10, H = 1e4;
268
+ function b() {
269
+ return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}`;
270
+ }
271
+ function q(e, n) {
272
+ const t = typeof window < "u";
273
+ return {
274
+ clientTime: Date.now(),
275
+ context_sdkSessionId: n.sessionId,
276
+ context_pageSessionId: n.pageSessionId,
277
+ context_sdkSeqId: n.seqId,
278
+ context_nameTracker: "wapT",
279
+ context_platform: "PC",
280
+ context_accountGeographicZone: n.region,
281
+ context_appVersion: "discovery-0.0.0",
282
+ context_osVersion: "unknown",
283
+ context_deviceModel: "",
284
+ context_deviceId: "",
285
+ context_package: "",
286
+ context_networkType: "unknow",
287
+ context_networkQuality: "UNKNOWN",
288
+ context_matchedPath: t ? window.location.pathname : "",
289
+ context_route: t ? window.location.href : "",
290
+ context_userAgent: typeof navigator < "u" ? navigator.userAgent : "",
291
+ context_artifactName: A,
292
+ context_artifactVersion: E,
293
+ context_deviceLevel: "unknown",
294
+ context_feSdkVersion: "1.3.13",
295
+ context_userId: n.userId,
296
+ measurement_name: P,
297
+ measurement_data: {
298
+ event_name: e.name,
299
+ timestamp: e.timestamp,
300
+ ...e.payload
301
+ }
302
+ };
303
+ }
304
+ function V(e, n) {
305
+ if (!(typeof fetch != "function" || n.length === 0))
306
+ try {
307
+ const t = {
308
+ method: "POST",
309
+ headers: {
310
+ "content-type": "application/json",
311
+ "Biz-Type": "apm_fe",
312
+ Batch: "true"
313
+ },
314
+ body: JSON.stringify(n)
315
+ };
316
+ typeof navigator < "u" && "sendBeacon" in navigator && (t.keepalive = !0), Promise.resolve(fetch(e, t)).catch(() => {
317
+ });
318
+ } catch {
319
+ }
320
+ }
321
+ function j(e) {
322
+ if (typeof console > "u") return;
323
+ const n = e.measurement_name ?? "apm";
324
+ console.groupCollapsed(`[apm] ${n}`), console.log(e), console.groupEnd();
325
+ }
326
+ function Q(e) {
327
+ const n = e.debug === !0, t = b(), i = b();
328
+ let s = 0, r = [], a = null, c = 0, o = !1;
329
+ const u = () => {
330
+ if (o = !1, a !== null && (clearTimeout(a), a = null), r.length === 0) return;
331
+ const h = r;
332
+ r = [], V(e.endpoint, h);
333
+ }, d = () => {
334
+ if (a !== null && (clearTimeout(a), a = null), c > 0) {
335
+ o = !0;
336
+ return;
337
+ }
338
+ u();
339
+ }, y = () => {
340
+ a === null && (a = setTimeout(d, H));
341
+ };
342
+ return {
343
+ sendCustomPoint(h) {
344
+ const v = s++;
345
+ c += 1, Promise.resolve().then(() => e.resolveUserId()).catch(() => "").then((w) => {
346
+ try {
347
+ const m = q(h, {
348
+ sessionId: t,
349
+ pageSessionId: i,
350
+ seqId: v,
351
+ userId: w,
352
+ region: e.region
353
+ });
354
+ if (n) {
355
+ j(m);
356
+ return;
357
+ }
358
+ r.push(m), r.length >= F ? setTimeout(() => d()) : y();
359
+ } catch {
360
+ }
361
+ }).finally(() => {
362
+ c -= 1, c === 0 && o && u();
363
+ });
364
+ },
365
+ flush: d
366
+ };
367
+ }
368
+ function W(e) {
369
+ const n = e.region ?? "cn";
370
+ if (e.endpoint) return e.endpoint;
371
+ const t = z();
372
+ return C[n][t];
373
+ }
374
+ function z() {
375
+ if (typeof window > "u") return "production";
376
+ const e = window.location.hostname.toLowerCase();
377
+ return e === "localhost" || e === "127.0.0.1" || e === "0.0.0.0" || e.includes(".sit.") || // hostname.includes(".beta.") ||
378
+ e.startsWith("local.") ? "development" : "production";
379
+ }
380
+ function $(e, n) {
381
+ if (e === !1) return null;
382
+ try {
383
+ const t = e.region ?? "cn", i = Q({
384
+ endpoint: W(e),
385
+ region: t,
386
+ resolveUserId: n ?? (() => Promise.resolve("")),
387
+ debug: e.debug
388
+ });
389
+ return { send: (s) => i.sendCustomPoint(s), flush: () => i.flush() };
390
+ } catch {
391
+ return null;
392
+ }
393
+ }
394
+ class K {
395
+ constructor(n, t, i, s) {
396
+ this.resolveContext = s, this.unsubscribers = [], this.common = {
397
+ business_line: "",
398
+ sdk_version: "",
399
+ content_mode: "",
400
+ renderer: ""
401
+ };
402
+ const r = $(n, i);
403
+ if (!r) {
404
+ this.send = () => {
405
+ }, this.flush = () => {
406
+ };
407
+ return;
408
+ }
409
+ this.send = r.send, this.flush = r.flush, this.common = {
410
+ ...this.common,
411
+ ...n === !1 ? {} : n.context,
412
+ business_line: n === !1 ? "" : n.business_line ?? "unknown"
413
+ }, this.bindEvents(t), this.bindFlushOnHidden();
414
+ }
415
+ /** 页面隐藏时立即冲刷缓冲,避免关闭前丢数据 */
416
+ bindFlushOnHidden() {
417
+ if (typeof document > "u") return;
418
+ const n = () => {
419
+ document.visibilityState === "hidden" && this.flush();
420
+ };
421
+ document.addEventListener("visibilitychange", n), this.unsubscribers.push(() => document.removeEventListener("visibilitychange", n));
422
+ }
423
+ bindEvents(n) {
424
+ this.unsubscribers.push(
425
+ n.on("beforeLoad", (t) => {
426
+ t.url && this.track("simulator_before_load", {
427
+ url: t.url,
428
+ source: t.source
429
+ });
430
+ })
431
+ ), this.unsubscribers.push(
432
+ n.on("ready", () => {
433
+ this.track("simulator_ready", {});
434
+ })
435
+ ), this.unsubscribers.push(
436
+ n.on("load", (t) => {
437
+ t.url && this.track("simulator_load", { url: t.url, duration: t.duration });
438
+ })
439
+ ), this.unsubscribers.push(
440
+ n.on("error", (t) => {
441
+ this.track("simulator_load_error", {
442
+ url: t.url,
443
+ error_name: t.code,
444
+ message: t.message
445
+ });
446
+ })
447
+ ), this.unsubscribers.push(
448
+ n.on("renderDone", (t) => {
449
+ t.url && this.track("simulator_render_done", { url: t.url, duration: t.duration });
450
+ })
451
+ ), this.unsubscribers.push(
452
+ n.on("navigation", (t) => {
453
+ t.blocked && this.track("simulator_navigation_blocked", { source: t.from, url: t.to });
454
+ })
455
+ ), this.unsubscribers.push(
456
+ n.on("guestError", (t) => {
457
+ this.track("simulator_guest_error", {
458
+ type: t.type,
459
+ error_name: t.name,
460
+ message: t.message?.slice(0, 1024),
461
+ stack: t.stack?.slice(0, 1024),
462
+ source: t.source,
463
+ url: t.url,
464
+ disposition: t.disposition,
465
+ effective_directive: t.effective_directive,
466
+ violated_directive: t.violated_directive,
467
+ blocked_uri: t.blocked_uri,
468
+ source_file: t.source_file,
469
+ line_number: t.line_number,
470
+ column_number: t.column_number,
471
+ original_policy: t.original_policy,
472
+ error_code: t.code,
473
+ request_id: t.request_id,
474
+ model: t.model,
475
+ operation: t.operation,
476
+ error_details: t.details
477
+ });
478
+ })
479
+ ), this.unsubscribers.push(
480
+ n.on("destroy", (t) => {
481
+ this.track("simulator_destroy", { message: t.reason ?? "" });
482
+ })
483
+ );
484
+ }
485
+ /** 初始化公共字段并上报 simulator_init */
486
+ trackInit(n) {
487
+ this.common = {
488
+ ...this.common,
489
+ sdk_version: n.sdkVersion,
490
+ content_mode: n.contentMode,
491
+ renderer: n.renderer
492
+ }, this.track("simulator_init", { url: n.appUrl });
493
+ }
494
+ /** 上报 reload 事件 */
495
+ trackReload(n) {
496
+ this.track("simulator_reload", { url: n });
497
+ }
498
+ /** srcdoc 注入完成 */
499
+ trackInjectDone(n) {
500
+ this.track("simulator_inject_done", {
501
+ url: n.url,
502
+ result: n.injected ? "injected" : "fallback",
503
+ duration: n.duration
504
+ });
505
+ }
506
+ /** 权限弹窗操作结果 */
507
+ trackPermissionResult(n) {
508
+ this.track("simulator_permission_result", n);
509
+ }
510
+ /** zip/files 解析完成 */
511
+ trackParseDone(n) {
512
+ this.track("simulator_parse_done", n);
513
+ }
514
+ /** SW 注册 + 激活结果(renderer: iframe-service-worker);scope 复用 url 字段 */
515
+ trackSwRegister(n) {
516
+ this.track("simulator_sw_register", n);
517
+ }
518
+ /** SW MOUNT(文件表挂载 + ACK)结果 */
519
+ trackSwMount(n) {
520
+ this.track("simulator_sw_mount", n);
521
+ }
522
+ /** 远程加载内部阶段;stage 保持低基数枚举,扩展字段只承载耗时与结果。 */
523
+ trackLoadStage(n, t) {
524
+ this.track("simulator_load_stage", { stage: n, ...t });
525
+ }
526
+ /** bridge 调用完成回调 */
527
+ handleBridgeInvoke(n) {
528
+ if (n.event === "reportTracker") return;
529
+ const t = {
530
+ name: n.event,
531
+ result: n.success ? "success" : "fail"
532
+ };
533
+ n.success ? t.duration = n.duration : t.message = n.error, this.track("bridge_invoke", t);
534
+ }
535
+ /** 发送打点:自动合入公共字段 */
536
+ track(n, t) {
537
+ try {
538
+ let i = {};
539
+ try {
540
+ i = this.resolveContext?.() ?? {};
541
+ } catch {
542
+ }
543
+ this.send({
544
+ name: n,
545
+ payload: { ...this.common, ...t, ...i },
546
+ timestamp: Date.now()
547
+ });
548
+ } catch {
549
+ }
550
+ }
551
+ destroy() {
552
+ queueMicrotask(() => this.flush());
553
+ for (const n of this.unsubscribers)
554
+ n();
555
+ this.unsubscribers.length = 0;
556
+ }
557
+ }
558
+ function Z(e) {
559
+ return !(e === void 0 || e === !1);
560
+ }
561
+ export {
562
+ l as M,
563
+ G as a,
564
+ f as b,
565
+ Q as c,
566
+ X as d,
567
+ Y as e,
568
+ Z as f,
569
+ K as g,
570
+ p as i,
571
+ M as o,
572
+ W as r,
573
+ E as v
574
+ };