@ait-co/devtools 0.1.141 → 0.1.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +4 -4
- package/README.md +4 -4
- package/dist/{attach-orchestrator-BG8TGJOZ.js → attach-orchestrator-0F0m_UqQ.js} +71 -9
- package/dist/{attach-orchestrator-BG8TGJOZ.js.map → attach-orchestrator-0F0m_UqQ.js.map} +1 -1
- package/dist/{attach-orchestrator-6kz_ZdWL.js → attach-orchestrator-D65KxFy_.js} +71 -9
- package/dist/{attach-orchestrator-6kz_ZdWL.js.map → attach-orchestrator-D65KxFy_.js.map} +1 -1
- package/dist/{attach-orchestrator-BEiz3wAx.js → attach-orchestrator-DL3NQ9ca.js} +71 -9
- package/dist/{attach-orchestrator-BEiz3wAx.js.map → attach-orchestrator-DL3NQ9ca.js.map} +1 -1
- package/dist/{cell-BMlFh08P.js → cell-BaLvusOl.js} +2 -2
- package/dist/{cell-BMlFh08P.js.map → cell-BaLvusOl.js.map} +1 -1
- package/dist/{cell-Dtgtusog.js → cell-CBUS3-nT.js} +2 -2
- package/dist/{cell-Dtgtusog.js.map → cell-CBUS3-nT.js.map} +1 -1
- package/dist/{cell-KsRXFdDs.js → cell-EBKKpAAT.js} +2 -2
- package/dist/{cell-KsRXFdDs.js.map → cell-EBKKpAAT.js.map} +1 -1
- package/dist/{debug-server-DWat7d-9.js → debug-server-B3ABDrRI.js} +4 -4
- package/dist/{debug-server-DWat7d-9.js.map → debug-server-B3ABDrRI.js.map} +1 -1
- package/dist/{debug-server-6c22qSWa.js → debug-server-BWhwrVXa.js} +4 -4
- package/dist/{debug-server-6c22qSWa.js.map → debug-server-BWhwrVXa.js.map} +1 -1
- package/dist/{debug-server-BQHbaKPT.js → debug-server-CfQNxxGW.js} +6 -6
- package/dist/{debug-server-BQHbaKPT.js.map → debug-server-CfQNxxGW.js.map} +1 -1
- package/dist/in-app/auto.js +299 -3
- package/dist/in-app/auto.js.map +1 -1
- package/dist/in-app/index.d.ts +161 -14
- package/dist/in-app/index.d.ts.map +1 -1
- package/dist/in-app/index.js +300 -4
- package/dist/in-app/index.js.map +1 -1
- package/dist/mcp/cli.js +82 -16
- package/dist/mcp/cli.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mock/index.d.ts +156 -98
- package/dist/mock/index.d.ts.map +1 -1
- package/dist/mock/index.js +52 -21
- package/dist/mock/index.js.map +1 -1
- package/dist/panel/index.js +9 -4
- package/dist/panel/index.js.map +1 -1
- package/dist/{pool-CrP5CPvU.d.ts → pool-DcaaOwUq.d.ts} +2 -2
- package/dist/{pool-CrP5CPvU.d.ts.map → pool-DcaaOwUq.d.ts.map} +1 -1
- package/dist/{qr-http-server-Cz1mA07b.cjs → qr-http-server--gl2-WKc.cjs} +9 -5
- package/dist/qr-http-server--gl2-WKc.cjs.map +1 -0
- package/dist/{qr-http-server-D4rGz8M7.js → qr-http-server-Bb7lMeqi.js} +9 -5
- package/dist/qr-http-server-Bb7lMeqi.js.map +1 -0
- package/dist/{qr-http-server-D1hpoyBF.js → qr-http-server-C_lqOrgc.js} +9 -5
- package/dist/qr-http-server-C_lqOrgc.js.map +1 -0
- package/dist/{qr-http-server-CTLdclg_.js → qr-http-server-CopuMbub.js} +9 -5
- package/dist/qr-http-server-CopuMbub.js.map +1 -0
- package/dist/{qr-http-server-D16Lq2ag.cjs → qr-http-server-D-Off6K1.cjs} +9 -5
- package/dist/qr-http-server-D-Off6K1.cjs.map +1 -0
- package/dist/{qr-http-server-DIjCV7h_.js → qr-http-server-DrbIVDjO.js} +9 -5
- package/dist/qr-http-server-DrbIVDjO.js.map +1 -0
- package/dist/qr-http-server-n1twN18z.js +1644 -0
- package/dist/qr-http-server-n1twN18z.js.map +1 -0
- package/dist/{relay-factory-C1X3G3WY.js → relay-factory-N9QobQxG.js} +6 -6
- package/dist/{relay-factory-C1X3G3WY.js.map → relay-factory-N9QobQxG.js.map} +1 -1
- package/dist/{relay-worker-BUXI0K0b.js → relay-worker-B5HKkGUY.js} +4 -4
- package/dist/{relay-worker-BUXI0K0b.js.map → relay-worker-B5HKkGUY.js.map} +1 -1
- package/dist/{relay-worker-DcyboK43.d.ts → relay-worker-YdlpZQl9.d.ts} +2 -2
- package/dist/{relay-worker-DcyboK43.d.ts.map → relay-worker-YdlpZQl9.d.ts.map} +1 -1
- package/dist/{runtime-BiigOuvb.d.ts → runtime-kn9DxOeg.d.ts} +2 -1
- package/dist/runtime-kn9DxOeg.d.ts.map +1 -0
- package/dist/test-runner/bin.js +8 -8
- package/dist/test-runner/bin.js.map +1 -1
- package/dist/test-runner/config.d.ts +1 -1
- package/dist/test-runner/config.js +1 -1
- package/dist/test-runner/pool.d.ts +1 -1
- package/dist/test-runner/pool.js +1 -1
- package/dist/test-runner/relay-factory.js +5 -5
- package/dist/test-runner/relay-worker.d.ts +1 -1
- package/dist/test-runner/relay-worker.js +1 -1
- package/dist/test-runner/report.d.ts +2 -2
- package/dist/test-runner/rpc.d.ts +1 -1
- package/dist/test-runner/runtime.d.ts +1 -1
- package/dist/test-runner/runtime.js +4 -0
- package/dist/test-runner/runtime.js.map +1 -1
- package/dist/test-runner/task-graph.d.ts +1 -1
- package/dist/{tunnel-DjtSENJU.cjs → tunnel-BVSMXctM.cjs} +2 -2
- package/dist/{tunnel-DjtSENJU.cjs.map → tunnel-BVSMXctM.cjs.map} +1 -1
- package/dist/{tunnel-5eBncITa.js → tunnel-D7xkimBu.js} +2 -2
- package/dist/{tunnel-5eBncITa.js.map → tunnel-D7xkimBu.js.map} +1 -1
- package/dist/unplugin/index.cjs +1 -1
- package/dist/unplugin/index.js +1 -1
- package/dist/unplugin/tunnel.cjs +1 -1
- package/dist/unplugin/tunnel.js +1 -1
- package/package.json +2 -2
- package/dist/qr-http-server-CTLdclg_.js.map +0 -1
- package/dist/qr-http-server-Cz1mA07b.cjs.map +0 -1
- package/dist/qr-http-server-D16Lq2ag.cjs.map +0 -1
- package/dist/qr-http-server-D1hpoyBF.js.map +0 -1
- package/dist/qr-http-server-D4rGz8M7.js.map +0 -1
- package/dist/qr-http-server-DIjCV7h_.js.map +0 -1
- package/dist/qr-http-server-wy3L7Yut.js +0 -1640
- package/dist/qr-http-server-wy3L7Yut.js.map +0 -1
- package/dist/runtime-BiigOuvb.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/in-app/gate.ts","../../src/in-app/attach.ts","../../src/in-app/eruda-overlay.ts","../../src/in-app/index.ts"],"mappings":";;AAwFA;;;;;;;;;AASA;;;;;AAmBA;;;;;AAQA;;;;;;;;;;;AA8EA;;;;;AAqCA;;;;;AAuBA;;;;;AA2EA;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/in-app/gate.ts","../../src/in-app/attach.ts","../../src/in-app/bridge-observer.ts","../../src/in-app/eruda-overlay.ts","../../src/in-app/index.ts"],"mappings":";;AAwFA;;;;;;;;;AASA;;;;;AAmBA;;;;;AAQA;;;;;;;;;;;AA8EA;;;;;AAqCA;;;;;AAuBA;;;;;AA2EA;;;;;;;;;;;;AC3RA;;;;;AAUC;;;;;;;;;;AA+OD;;;;;AAkKA;;;;;AA4CA;;;;UDraiB,gBAAA;EAAA,SACN,MAAA;;WAEA,QAAA;EEhDM;EAAA,SFkDN,YAAA;AAAA;;UAIM,iBAAA;EAAA,SACN,MAAA;EEhDoB;;;;;;;;AAY/B;;;;;;EAZ+B,SF+DpB,MAAA;AAAA;AAAA,KAGC,UAAA,GAAa,gBAAA,GAAmB,iBAAA;;;;;;;UAQ3B,SAAA;EEpDa;;;;AAAqB;;;;;;;;EAArB,SFiEnB,QAAA;EEtCL;;;;;;EAAA,SF8CK,YAAA,EAAc,eAAA;EExClB;;;;;;;;;AA2HP;;;;;AAoFA;;;;;;;;ACjQA;;EDkDO,SFkEI,cAAA,IAAkB,IAAA;AAAA;;AGpF7B;;;;;;;;ACxBA;;iBJ2IgB,iBAAA,CAAkB,QAAA;;;;;;;iBAqClB,cAAA,CAAe,QAAA;;;;;;;;;;;;;;;;;;;;iBAuBf,mBAAA,CAAoB,QAAA;;;;;;;;;;;;;;;;;;;;;;iBA2EpB,iBAAA,CAAkB,KAAA,EAAO,SAAA,GAAY,UAAA;;;;;;AA7NrD;;;;;AAQA;;;;;;;;;;;AA8EA;;;;;AAqCA;;;;;AAuBA;;;;iBChNgB,qBAAA,CAAsB,QAAA,UAAkB,MAAA;AAAA,QAoChD,MAAA;EAAA,UACI,MAAA;IDsP6B;;;;;;;IC9OrC,uBAAA;EAAA;AAAA;AA7CJ;;;;;AAUC;;;;;;;;;;AA+OD;;;;;AAkKA;;;;;AA4CA;;AAvcA,iBAyPgB,kBAAA,CAAA;;;;ACjPhB;;;;;;;;;;;;;;;AAUA;;;;;iBDyYgB,iBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;iBA4CA,WAAA,CAAY,UAAA,GAAY,UAAA;;;;ADraxC;;;;;;;;;AASA;;;;;AAmBA;;;;;AAQA;;;;;;;;;;;AA8EA;;;;;AAqCA;;;;;AAuBA;AAAA,UE3NiB,iBAAA;EACf,MAAA;EF0NkC;EExNlC,SAAA;AAAA;;UAIe,cAAA;EACf,MAAA;EF8RuC;EE5RvC,EAAA;EACA,MAAA;AAAA;;;;;ADAF;UCQiB,mBAAA;EACf,OAAA,EAAS,MAAA,SAAe,iBAAA;EACxB,IAAA,EAAM,cAAA;AAAA;ADAP;;;;;AAAA,cCQY,iBAAA;AAAA,QAWL,MAAA;EAAA,UACI,MAAA;IDee;;AA4M3B;;;;;ICnNI,YAAA,GAAe,mBAAA;IDqXc;;;;AA4CjC;IC3ZI,wBAAA;MACE,eAAA,IAAmB,IAAA,UAAc,MAAA;MAAA,CAChC,GAAA;IAAA;;IAGH,kBAAA;MACE,WAAA,IAAe,OAAA;MAAA,CACd,GAAA;IAAA;IA9D2B;IAiE9B,wBAAA;MACE,IAAA,IAAQ,KAAA,UAAe,IAAA;MAAA,CACtB,GAAA;IAAA;EAAA;AAAA;;;;;;AAhDP;;;;;;iBAsKgB,qBAAA,CAAA;;;;;;iBAoFA,uBAAA,CAAA;;;;AFhOhB;;;;;;;;;AASA;;;;;AAmBA;;;;;AAQA;;;;;;;;;;;AA8EA;;;;;AAqCA;;;;;AAuBA;;;iBG/MsB,UAAA,CAAA,GAAc,OAAA;;AH0RpC;;;;;;;;;;;;iBG1PgB,YAAA,CAAA;;;;;AHmHhB;;;;;AAqCA;;;;;AAuBA;;iBIvMgB,cAAA,CAAA,GAAkB,UAAA"}
|
package/dist/in-app/index.js
CHANGED
|
@@ -247,6 +247,186 @@ const RELAY_AUTH_REJECT_CLOSE_CODE = 4401;
|
|
|
247
247
|
*/
|
|
248
248
|
const RELAY_AUTH_REJECT_REASON = "totp-rejected";
|
|
249
249
|
//#endregion
|
|
250
|
+
//#region src/in-app/bridge-observer.ts
|
|
251
|
+
/**
|
|
252
|
+
* CustomEvent fired (no detail) on every start/settle so the indicator badge
|
|
253
|
+
* re-renders promptly. SECRET-HANDLING: carries no detail payload at all — the
|
|
254
|
+
* badge reads the enum-only `window.__ait_bridge` snapshot on receipt.
|
|
255
|
+
*/
|
|
256
|
+
const BRIDGE_CALL_EVENT = "ait:bridge-call";
|
|
257
|
+
/**
|
|
258
|
+
* Pending entries older than this are pruned on the next start — a safety net
|
|
259
|
+
* for the fallback path where a settle signal might be missed, so the pending
|
|
260
|
+
* list can never grow unbounded or show a forever-stuck row. Generous enough
|
|
261
|
+
* that a genuinely slow native call (the exact signal we want to surface) still
|
|
262
|
+
* shows while it is plausibly in flight.
|
|
263
|
+
*/
|
|
264
|
+
const MAX_PENDING_AGE_MS = 12e4;
|
|
265
|
+
/** Guard so the observer wraps the bridge at most once per page lifecycle. */
|
|
266
|
+
let bridgeObserverInstalled = false;
|
|
267
|
+
/** Monotonic id source for the primary (3.0) path, where native gives us none. */
|
|
268
|
+
let callIdCounter = 0;
|
|
269
|
+
/** Undo hooks that {@link uninstallBridgeObserver} runs to restore originals. */
|
|
270
|
+
let restoreHooks = [];
|
|
271
|
+
/** Drops pending entries older than {@link MAX_PENDING_AGE_MS}. */
|
|
272
|
+
function pruneStale(state, now) {
|
|
273
|
+
for (const id of Object.keys(state.pending)) {
|
|
274
|
+
const entry = state.pending[id];
|
|
275
|
+
if (entry !== void 0 && now - entry.startedAt > MAX_PENDING_AGE_MS) delete state.pending[id];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/** Fires the payload-less notify event so the badge re-renders. */
|
|
279
|
+
function broadcast() {
|
|
280
|
+
if (typeof window === "undefined") return;
|
|
281
|
+
window.dispatchEvent(new CustomEvent(BRIDGE_CALL_EVENT));
|
|
282
|
+
}
|
|
283
|
+
/** Records a call start: add to pending, set last=pending, notify. */
|
|
284
|
+
function startCall(state, id, method, now) {
|
|
285
|
+
pruneStale(state, now);
|
|
286
|
+
state.pending[id] = {
|
|
287
|
+
method,
|
|
288
|
+
startedAt: now
|
|
289
|
+
};
|
|
290
|
+
state.last = {
|
|
291
|
+
method,
|
|
292
|
+
at: now,
|
|
293
|
+
status: "pending"
|
|
294
|
+
};
|
|
295
|
+
broadcast();
|
|
296
|
+
}
|
|
297
|
+
/** Records a call settle: remove from pending, stamp last, notify. */
|
|
298
|
+
function settleCall(state, id, status, now) {
|
|
299
|
+
const entry = state.pending[id];
|
|
300
|
+
delete state.pending[id];
|
|
301
|
+
state.last = {
|
|
302
|
+
method: entry?.method ?? state.last?.method ?? "unknown",
|
|
303
|
+
at: now,
|
|
304
|
+
status
|
|
305
|
+
};
|
|
306
|
+
broadcast();
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Parses an outbound `ReactNativeWebView.postMessage` JSON envelope and records
|
|
310
|
+
* a START for async request/response calls only. Event subscriptions
|
|
311
|
+
* (`addEventListener`/`removeEventListener`/`callEventMethod`), cleanup, and
|
|
312
|
+
* constants are ignored — they are not the "spinner is a pending call" signal.
|
|
313
|
+
*
|
|
314
|
+
* SECRET-HANDLING: reads `type`/`name`/`functionName`/`callbackId`/`eventId`
|
|
315
|
+
* ONLY — never `params`/`args`.
|
|
316
|
+
*/
|
|
317
|
+
function observeOutbound(state, message) {
|
|
318
|
+
if (typeof message !== "string") return;
|
|
319
|
+
let parsed;
|
|
320
|
+
try {
|
|
321
|
+
parsed = JSON.parse(message);
|
|
322
|
+
} catch {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const now = Date.now();
|
|
326
|
+
if (parsed.type === "callAsyncMethod" && typeof parsed.name === "string" && typeof parsed.callbackId === "string") {
|
|
327
|
+
startCall(state, parsed.callbackId, parsed.name, now);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (parsed.type === "method" && typeof parsed.functionName === "string" && typeof parsed.eventId === "string") startCall(state, parsed.eventId, parsed.functionName, now);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Parses a `__GRANITE_NATIVE_EMITTER.emit` event name and records a SETTLE for
|
|
334
|
+
* 2.x async resolves/rejects (`<method>/resolve/<eventId>` |
|
|
335
|
+
* `<method>/reject/<eventId>`). Event-bridge emits (`.../onEvent/...`) are
|
|
336
|
+
* ignored. SECRET-HANDLING: reads the event NAME only — never the emitted args.
|
|
337
|
+
*/
|
|
338
|
+
function observeSettle(state, event) {
|
|
339
|
+
if (typeof event !== "string") return;
|
|
340
|
+
const match = /\/(resolve|reject)\/([^/]+)$/.exec(event);
|
|
341
|
+
if (match === null) return;
|
|
342
|
+
settleCall(state, match[2], match[1] === "resolve" ? "resolved" : "rejected", Date.now());
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Installs the native-bridge call observer (#749). Idempotent per page
|
|
346
|
+
* lifecycle. Called by {@link maybeAttach} after the gate passes (debug builds
|
|
347
|
+
* only). Prefers the 3.0 single-dispatcher wrap; falls back to the universal
|
|
348
|
+
* 2.x postMessage-start + emitter-settle pair. A context with no observable
|
|
349
|
+
* bridge (env 2 mock) leaves `window.__ait_bridge` as an empty snapshot — the
|
|
350
|
+
* badge then shows the heartbeat only, which is correct.
|
|
351
|
+
*
|
|
352
|
+
* Never throws into the host app — a wrapped hook that somehow fails is caught
|
|
353
|
+
* and the original behavior is always preserved.
|
|
354
|
+
*/
|
|
355
|
+
function installBridgeObserver() {
|
|
356
|
+
if (bridgeObserverInstalled) return;
|
|
357
|
+
if (typeof window === "undefined") return;
|
|
358
|
+
bridgeObserverInstalled = true;
|
|
359
|
+
const state = {
|
|
360
|
+
pending: Object.create(null),
|
|
361
|
+
last: null
|
|
362
|
+
};
|
|
363
|
+
window.__ait_bridge = state;
|
|
364
|
+
const nativeBridge = window.__appsInTossNativeBridge;
|
|
365
|
+
if (nativeBridge !== void 0 && typeof nativeBridge.callAsyncMethod === "function") {
|
|
366
|
+
const original = nativeBridge.callAsyncMethod;
|
|
367
|
+
const wrapped = function(name, params) {
|
|
368
|
+
const id = `c${++callIdCounter}`;
|
|
369
|
+
startCall(state, id, String(name), Date.now());
|
|
370
|
+
let result;
|
|
371
|
+
try {
|
|
372
|
+
result = original.call(this, name, params);
|
|
373
|
+
} catch (err) {
|
|
374
|
+
settleCall(state, id, "rejected", Date.now());
|
|
375
|
+
throw err;
|
|
376
|
+
}
|
|
377
|
+
if (result !== null && typeof result.then === "function") result.then(() => settleCall(state, id, "resolved", Date.now()), () => settleCall(state, id, "rejected", Date.now()));
|
|
378
|
+
else settleCall(state, id, "resolved", Date.now());
|
|
379
|
+
return result;
|
|
380
|
+
};
|
|
381
|
+
nativeBridge.callAsyncMethod = wrapped;
|
|
382
|
+
restoreHooks.push(() => {
|
|
383
|
+
nativeBridge.callAsyncMethod = original;
|
|
384
|
+
});
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
const webView = window.ReactNativeWebView;
|
|
388
|
+
if (webView !== void 0 && typeof webView.postMessage === "function") {
|
|
389
|
+
const originalPost = webView.postMessage;
|
|
390
|
+
webView.postMessage = function(message) {
|
|
391
|
+
try {
|
|
392
|
+
observeOutbound(state, message);
|
|
393
|
+
} catch {}
|
|
394
|
+
originalPost.call(this, message);
|
|
395
|
+
};
|
|
396
|
+
restoreHooks.push(() => {
|
|
397
|
+
webView.postMessage = originalPost;
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
const emitter = window.__GRANITE_NATIVE_EMITTER;
|
|
401
|
+
if (emitter !== void 0 && typeof emitter.emit === "function") {
|
|
402
|
+
const originalEmit = emitter.emit;
|
|
403
|
+
emitter.emit = function(event, args) {
|
|
404
|
+
try {
|
|
405
|
+
observeSettle(state, event);
|
|
406
|
+
} catch {}
|
|
407
|
+
originalEmit.call(this, event, args);
|
|
408
|
+
};
|
|
409
|
+
restoreHooks.push(() => {
|
|
410
|
+
emitter.emit = originalEmit;
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Restores every wrapped bridge hook and removes `window.__ait_bridge` (#749).
|
|
416
|
+
* Idempotent; safe to call when nothing was installed. Wired into
|
|
417
|
+
* {@link detachDebugSurface} (#748) so no bridge wrap survives a run's end.
|
|
418
|
+
*/
|
|
419
|
+
function uninstallBridgeObserver() {
|
|
420
|
+
if (!bridgeObserverInstalled) return;
|
|
421
|
+
bridgeObserverInstalled = false;
|
|
422
|
+
const hooks = restoreHooks;
|
|
423
|
+
restoreHooks = [];
|
|
424
|
+
for (const undo of hooks) try {
|
|
425
|
+
undo();
|
|
426
|
+
} catch {}
|
|
427
|
+
if (typeof window !== "undefined") window.__ait_bridge = void 0;
|
|
428
|
+
}
|
|
429
|
+
//#endregion
|
|
250
430
|
//#region src/in-app/eruda-overlay.ts
|
|
251
431
|
/**
|
|
252
432
|
* In-app eruda console overlay for the debug attach flow.
|
|
@@ -283,6 +463,12 @@ const RELAY_AUTH_REJECT_REASON = "totp-rejected";
|
|
|
283
463
|
/** Module-level guard against double mount across repeated `maybeAttach` calls. */
|
|
284
464
|
let erudaMounted = false;
|
|
285
465
|
/**
|
|
466
|
+
* The loaded eruda module, captured on a successful {@link mountEruda} so
|
|
467
|
+
* {@link unmountEruda} can call `.destroy()` on the same instance during
|
|
468
|
+
* graceful detach (#748). `null` when eruda was never mounted.
|
|
469
|
+
*/
|
|
470
|
+
let erudaModule = null;
|
|
471
|
+
/**
|
|
286
472
|
* Mounts the eruda in-page console once.
|
|
287
473
|
*
|
|
288
474
|
* Idempotent: repeated calls after a successful mount are no-ops, mirroring the
|
|
@@ -298,12 +484,38 @@ async function mountEruda() {
|
|
|
298
484
|
if (erudaMounted || typeof document === "undefined") return;
|
|
299
485
|
erudaMounted = true;
|
|
300
486
|
try {
|
|
301
|
-
(await import("eruda")).default
|
|
487
|
+
const eruda = (await import("eruda")).default;
|
|
488
|
+
eruda.init();
|
|
489
|
+
erudaModule = eruda;
|
|
302
490
|
} catch (err) {
|
|
303
491
|
erudaMounted = false;
|
|
304
492
|
console.debug("[@ait-co/devtools] eruda console mount skipped:", err);
|
|
305
493
|
}
|
|
306
494
|
}
|
|
495
|
+
/**
|
|
496
|
+
* Unmounts the eruda in-page console (#748 graceful detach).
|
|
497
|
+
*
|
|
498
|
+
* Calls `eruda.destroy()`, which removes eruda's floating entry button, any
|
|
499
|
+
* open panel, and its `#eruda` shadow host — returning the phone screen to a
|
|
500
|
+
* clean, non-debug state when a debug session ends. After a successful unmount
|
|
501
|
+
* the guard is reset so a later {@link mountEruda} (a fresh attach) can
|
|
502
|
+
* re-mount.
|
|
503
|
+
*
|
|
504
|
+
* Idempotent: a call when eruda was never mounted (or already unmounted) is a
|
|
505
|
+
* no-op. Fail-silent: a `destroy()` throw is swallowed — teardown must never
|
|
506
|
+
* throw into the host app.
|
|
507
|
+
*/
|
|
508
|
+
function unmountEruda() {
|
|
509
|
+
if (!erudaMounted || erudaModule === null) return;
|
|
510
|
+
try {
|
|
511
|
+
erudaModule.destroy();
|
|
512
|
+
} catch (err) {
|
|
513
|
+
console.debug("[@ait-co/devtools] eruda console unmount skipped:", err);
|
|
514
|
+
} finally {
|
|
515
|
+
erudaMounted = false;
|
|
516
|
+
erudaModule = null;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
307
519
|
//#endregion
|
|
308
520
|
//#region src/in-app/attach.ts
|
|
309
521
|
/**
|
|
@@ -467,6 +679,81 @@ function createFailFastSocket(url) {
|
|
|
467
679
|
}, 0);
|
|
468
680
|
return sock;
|
|
469
681
|
}
|
|
682
|
+
/** Grace window before a non-terminal relay close tears the surface down. */
|
|
683
|
+
const RECONNECT_GRACE_MS = 5e3;
|
|
684
|
+
/** One-shot guard so the teardown runs at most once per page lifecycle. */
|
|
685
|
+
let debugSurfaceDetached = false;
|
|
686
|
+
/** Pending grace-window timer for a non-terminal close, or `null`. */
|
|
687
|
+
let pendingDetachTimer = null;
|
|
688
|
+
/** Cancels a scheduled teardown — called when a relay socket re-opens. */
|
|
689
|
+
function cancelScheduledDetach() {
|
|
690
|
+
if (pendingDetachTimer !== null) {
|
|
691
|
+
clearTimeout(pendingDetachTimer);
|
|
692
|
+
pendingDetachTimer = null;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Schedules {@link detachDebugSurface} after {@link RECONNECT_GRACE_MS} unless
|
|
697
|
+
* a reconnect cancels it first. No-op if teardown already ran or is already
|
|
698
|
+
* scheduled. Defensive: if `setTimeout` is somehow unavailable, tears down
|
|
699
|
+
* immediately rather than never.
|
|
700
|
+
*/
|
|
701
|
+
function scheduleDetach() {
|
|
702
|
+
if (debugSurfaceDetached || pendingDetachTimer !== null) return;
|
|
703
|
+
if (typeof setTimeout === "undefined") {
|
|
704
|
+
detachDebugSurface();
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
pendingDetachTimer = setTimeout(() => {
|
|
708
|
+
pendingDetachTimer = null;
|
|
709
|
+
detachDebugSurface();
|
|
710
|
+
}, RECONNECT_GRACE_MS);
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Idempotent, non-throwing teardown of the in-app debug surface (issue #748).
|
|
714
|
+
*
|
|
715
|
+
* Removes every debug-surface element WE injected and restores the one side
|
|
716
|
+
* effect WE applied:
|
|
717
|
+
* 1. The CDP-injected `#__ait_debug_indicator` badge (the persistent
|
|
718
|
+
* "Debugger Disconnected" element). Its live heartbeat/pending-call timer
|
|
719
|
+
* (#749) is stopped first via the badge controller's `stop()` so no 1 Hz
|
|
720
|
+
* interval leaks past detach; `buildIndicatorExpression` also
|
|
721
|
+
* self-dismisses the node — this is the in-app hard guarantee, idempotent,
|
|
722
|
+
* a no-op if it is already gone.
|
|
723
|
+
* 2. The eruda in-page console (floating button + any open panel).
|
|
724
|
+
* 3. The native-bridge call observer (#749) — its `callAsyncMethod` /
|
|
725
|
+
* `postMessage` / emitter wraps are restored and `window.__ait_bridge` is
|
|
726
|
+
* removed, so nothing we wrapped survives the run's end.
|
|
727
|
+
* 4. keepAwake — forced on at attach; restored here so a run that ends
|
|
728
|
+
* WITHOUT a page unload does not leave the screen pinned awake (the
|
|
729
|
+
* existing `beforeunload` restore only covers the unload path).
|
|
730
|
+
*
|
|
731
|
+
* Deliberately NOT touched: the `window.WebSocket` observer proxy (kept so the
|
|
732
|
+
* #478 post-4401 fail-fast survives; it is non-blocking and never absorbs
|
|
733
|
+
* input), and any NATIVE overlay (out of our layer — see the block comment
|
|
734
|
+
* above and issue #748 hypothesis (a)).
|
|
735
|
+
*
|
|
736
|
+
* Never throws into the host app — every step is individually guarded.
|
|
737
|
+
* Exported for unit tests and for a consumer that wants to force a clean detach.
|
|
738
|
+
*/
|
|
739
|
+
function detachDebugSurface() {
|
|
740
|
+
if (debugSurfaceDetached) return;
|
|
741
|
+
debugSurfaceDetached = true;
|
|
742
|
+
cancelScheduledDetach();
|
|
743
|
+
try {
|
|
744
|
+
if (typeof window !== "undefined") window.__ait_indicator?.stop?.();
|
|
745
|
+
if (typeof document !== "undefined") document.getElementById("__ait_debug_indicator")?.remove();
|
|
746
|
+
} catch {}
|
|
747
|
+
try {
|
|
748
|
+
unmountEruda();
|
|
749
|
+
} catch {}
|
|
750
|
+
try {
|
|
751
|
+
uninstallBridgeObserver();
|
|
752
|
+
} catch {}
|
|
753
|
+
try {
|
|
754
|
+
setScreenAwakeMode({ enabled: false }).catch(() => {});
|
|
755
|
+
} catch {}
|
|
756
|
+
}
|
|
470
757
|
/**
|
|
471
758
|
* Wraps `window.WebSocket` with a relay-origin-scoped observer (issue #478).
|
|
472
759
|
*
|
|
@@ -489,19 +776,27 @@ function installRelayWsObserver(relayUrl) {
|
|
|
489
776
|
if (relayKey === null) return;
|
|
490
777
|
wsObserverInstalled = true;
|
|
491
778
|
window.__ait_relay_ws_observed = true;
|
|
779
|
+
window.addEventListener("pagehide", () => detachDebugSurface(), { once: true });
|
|
492
780
|
const NativeWebSocket = window.WebSocket;
|
|
493
781
|
const observed = new Proxy(NativeWebSocket, { construct(target, args) {
|
|
494
782
|
const url = String(args[0]);
|
|
495
783
|
if (wsOriginKey(url) !== relayKey) return Reflect.construct(target, args);
|
|
496
784
|
if (relayAuthExpired) return createFailFastSocket(url);
|
|
497
785
|
const ws = Reflect.construct(target, args);
|
|
498
|
-
ws.addEventListener("open", () =>
|
|
786
|
+
ws.addEventListener("open", () => {
|
|
787
|
+
broadcastRelayWsState("open");
|
|
788
|
+
cancelScheduledDetach();
|
|
789
|
+
});
|
|
499
790
|
ws.addEventListener("close", (event) => {
|
|
500
791
|
broadcastRelayWsState("close");
|
|
501
792
|
if (event.code === 4401) {
|
|
502
793
|
relayAuthExpired = true;
|
|
503
794
|
notifyAuthExpired();
|
|
504
|
-
|
|
795
|
+
detachDebugSurface();
|
|
796
|
+
} else scheduleDetach();
|
|
797
|
+
});
|
|
798
|
+
ws.addEventListener("error", () => {
|
|
799
|
+
scheduleDetach();
|
|
505
800
|
});
|
|
506
801
|
return ws;
|
|
507
802
|
} });
|
|
@@ -597,6 +892,7 @@ function maybeAttach(gateResult = checkDebugGate()) {
|
|
|
597
892
|
const atCode = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("at") : null;
|
|
598
893
|
const src = deriveTargetScriptUrl(gateResult.relayUrl, atCode);
|
|
599
894
|
installRelayWsObserver(gateResult.relayUrl);
|
|
895
|
+
installBridgeObserver();
|
|
600
896
|
if (document.querySelector(`script[src="${src}"]`) !== null) {
|
|
601
897
|
attached = true;
|
|
602
898
|
return;
|
|
@@ -667,6 +963,6 @@ function checkDebugGate() {
|
|
|
667
963
|
});
|
|
668
964
|
}
|
|
669
965
|
//#endregion
|
|
670
|
-
export { checkDebugGate, deriveTargetScriptUrl, evaluateDebugGate, isPrivateAppsHost, isTossminiHost, isTrycloudflareHost, maybeAttach, mountEruda, reportWebViewType };
|
|
966
|
+
export { BRIDGE_CALL_EVENT, checkDebugGate, deriveTargetScriptUrl, detachDebugSurface, evaluateDebugGate, installBridgeObserver, isPrivateAppsHost, isTossminiHost, isTrycloudflareHost, maybeAttach, mountEruda, reportWebViewType, uninstallBridgeObserver, unmountEruda };
|
|
671
967
|
|
|
672
968
|
//# sourceMappingURL=index.js.map
|