execbro 1.10.23 → 1.10.25

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 (141) hide show
  1. package/README.md +2 -1
  2. package/build/__tests__/helpers/fake-cdp-server.d.ts +9 -0
  3. package/build/__tests__/helpers/fake-cdp-server.d.ts.map +1 -1
  4. package/build/__tests__/helpers/fake-cdp-server.js +20 -2
  5. package/build/__tests__/helpers/fake-cdp-server.js.map +1 -1
  6. package/build/__tests__/integration/connection-health.test.js +8 -1
  7. package/build/__tests__/integration/connection-health.test.js.map +1 -1
  8. package/build/__tests__/integration/socket-close-midflight.test.d.ts +2 -0
  9. package/build/__tests__/integration/socket-close-midflight.test.d.ts.map +1 -0
  10. package/build/__tests__/integration/socket-close-midflight.test.js +106 -0
  11. package/build/__tests__/integration/socket-close-midflight.test.js.map +1 -0
  12. package/build/__tests__/integration/stale-target-probe.test.d.ts +2 -0
  13. package/build/__tests__/integration/stale-target-probe.test.d.ts.map +1 -0
  14. package/build/__tests__/integration/stale-target-probe.test.js +85 -0
  15. package/build/__tests__/integration/stale-target-probe.test.js.map +1 -0
  16. package/build/__tests__/unit/componentSource.test.d.ts +2 -0
  17. package/build/__tests__/unit/componentSource.test.d.ts.map +1 -0
  18. package/build/__tests__/unit/componentSource.test.js +67 -0
  19. package/build/__tests__/unit/componentSource.test.js.map +1 -0
  20. package/build/__tests__/unit/componentSourceResolve.test.d.ts +2 -0
  21. package/build/__tests__/unit/componentSourceResolve.test.d.ts.map +1 -0
  22. package/build/__tests__/unit/componentSourceResolve.test.js +91 -0
  23. package/build/__tests__/unit/componentSourceResolve.test.js.map +1 -0
  24. package/build/__tests__/unit/deviceResolution.test.d.ts +2 -0
  25. package/build/__tests__/unit/deviceResolution.test.d.ts.map +1 -0
  26. package/build/__tests__/unit/deviceResolution.test.js +108 -0
  27. package/build/__tests__/unit/deviceResolution.test.js.map +1 -0
  28. package/build/__tests__/unit/executor.test.js +48 -12
  29. package/build/__tests__/unit/executor.test.js.map +1 -1
  30. package/build/__tests__/unit/getLogsEmptyContract.test.d.ts +2 -0
  31. package/build/__tests__/unit/getLogsEmptyContract.test.d.ts.map +1 -0
  32. package/build/__tests__/unit/getLogsEmptyContract.test.js +99 -0
  33. package/build/__tests__/unit/getLogsEmptyContract.test.js.map +1 -0
  34. package/build/__tests__/unit/inspectorHarvest.test.d.ts +2 -0
  35. package/build/__tests__/unit/inspectorHarvest.test.d.ts.map +1 -0
  36. package/build/__tests__/unit/inspectorHarvest.test.js +61 -0
  37. package/build/__tests__/unit/inspectorHarvest.test.js.map +1 -0
  38. package/build/__tests__/unit/inspectorSource.test.d.ts +2 -0
  39. package/build/__tests__/unit/inspectorSource.test.d.ts.map +1 -0
  40. package/build/__tests__/unit/inspectorSource.test.js +74 -0
  41. package/build/__tests__/unit/inspectorSource.test.js.map +1 -0
  42. package/build/__tests__/unit/logDiagnosis.test.d.ts +2 -0
  43. package/build/__tests__/unit/logDiagnosis.test.d.ts.map +1 -0
  44. package/build/__tests__/unit/logDiagnosis.test.js +81 -0
  45. package/build/__tests__/unit/logDiagnosis.test.js.map +1 -0
  46. package/build/__tests__/unit/pendingExecutions.test.d.ts +2 -0
  47. package/build/__tests__/unit/pendingExecutions.test.d.ts.map +1 -0
  48. package/build/__tests__/unit/pendingExecutions.test.js +70 -0
  49. package/build/__tests__/unit/pendingExecutions.test.js.map +1 -0
  50. package/build/__tests__/unit/reloadAppAutoConnect.test.d.ts +2 -0
  51. package/build/__tests__/unit/reloadAppAutoConnect.test.d.ts.map +1 -0
  52. package/build/__tests__/unit/reloadAppAutoConnect.test.js +63 -0
  53. package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -0
  54. package/build/__tests__/unit/selectionBuffer.test.d.ts +2 -0
  55. package/build/__tests__/unit/selectionBuffer.test.d.ts.map +1 -0
  56. package/build/__tests__/unit/selectionBuffer.test.js +86 -0
  57. package/build/__tests__/unit/selectionBuffer.test.js.map +1 -0
  58. package/build/__tests__/unit/selectionPoller.test.d.ts +2 -0
  59. package/build/__tests__/unit/selectionPoller.test.d.ts.map +1 -0
  60. package/build/__tests__/unit/selectionPoller.test.js +109 -0
  61. package/build/__tests__/unit/selectionPoller.test.js.map +1 -0
  62. package/build/__tests__/unit/symbolicate.test.d.ts +2 -0
  63. package/build/__tests__/unit/symbolicate.test.d.ts.map +1 -0
  64. package/build/__tests__/unit/symbolicate.test.js +154 -0
  65. package/build/__tests__/unit/symbolicate.test.js.map +1 -0
  66. package/build/__tests__/unit/transportClassify.test.js +108 -7
  67. package/build/__tests__/unit/transportClassify.test.js.map +1 -1
  68. package/build/core/componentSource.d.ts +62 -0
  69. package/build/core/componentSource.d.ts.map +1 -0
  70. package/build/core/componentSource.js +268 -0
  71. package/build/core/componentSource.js.map +1 -0
  72. package/build/core/connection.d.ts +30 -0
  73. package/build/core/connection.d.ts.map +1 -1
  74. package/build/core/connection.js +101 -28
  75. package/build/core/connection.js.map +1 -1
  76. package/build/core/debugGlobals.d.ts.map +1 -1
  77. package/build/core/debugGlobals.js +89 -32
  78. package/build/core/debugGlobals.js.map +1 -1
  79. package/build/core/errors.d.ts +7 -1
  80. package/build/core/errors.d.ts.map +1 -1
  81. package/build/core/errors.js +8 -1
  82. package/build/core/errors.js.map +1 -1
  83. package/build/core/guides.js +1 -1
  84. package/build/core/index.d.ts +4 -1
  85. package/build/core/index.d.ts.map +1 -1
  86. package/build/core/index.js +4 -1
  87. package/build/core/index.js.map +1 -1
  88. package/build/core/inspector.d.ts +24 -0
  89. package/build/core/inspector.d.ts.map +1 -1
  90. package/build/core/inspector.js +58 -0
  91. package/build/core/inspector.js.map +1 -1
  92. package/build/core/jsExecute.d.ts +76 -1
  93. package/build/core/jsExecute.d.ts.map +1 -1
  94. package/build/core/jsExecute.js +193 -32
  95. package/build/core/jsExecute.js.map +1 -1
  96. package/build/core/logDiagnosis.d.ts +65 -0
  97. package/build/core/logDiagnosis.d.ts.map +1 -0
  98. package/build/core/logDiagnosis.js +51 -0
  99. package/build/core/logDiagnosis.js.map +1 -0
  100. package/build/core/register.d.ts.map +1 -1
  101. package/build/core/register.js +22 -6
  102. package/build/core/register.js.map +1 -1
  103. package/build/core/selectionBuffer.d.ts +42 -0
  104. package/build/core/selectionBuffer.d.ts.map +1 -0
  105. package/build/core/selectionBuffer.js +51 -0
  106. package/build/core/selectionBuffer.js.map +1 -0
  107. package/build/core/selectionPoller.d.ts +13 -0
  108. package/build/core/selectionPoller.d.ts.map +1 -0
  109. package/build/core/selectionPoller.js +102 -0
  110. package/build/core/selectionPoller.js.map +1 -0
  111. package/build/core/state.d.ts +10 -0
  112. package/build/core/state.d.ts.map +1 -1
  113. package/build/core/state.js +21 -0
  114. package/build/core/state.js.map +1 -1
  115. package/build/core/symbolicate.d.ts +18 -0
  116. package/build/core/symbolicate.d.ts.map +1 -0
  117. package/build/core/symbolicate.js +119 -0
  118. package/build/core/symbolicate.js.map +1 -0
  119. package/build/core/types.d.ts +8 -0
  120. package/build/core/types.d.ts.map +1 -1
  121. package/build/tools/componentTools.d.ts.map +1 -1
  122. package/build/tools/componentTools.js +78 -9
  123. package/build/tools/componentTools.js.map +1 -1
  124. package/build/tools/connectionTools.d.ts.map +1 -1
  125. package/build/tools/connectionTools.js +10 -4
  126. package/build/tools/connectionTools.js.map +1 -1
  127. package/build/tools/executionTools.js +7 -7
  128. package/build/tools/executionTools.js.map +1 -1
  129. package/build/tools/interactionTools.d.ts.map +1 -1
  130. package/build/tools/interactionTools.js +1 -0
  131. package/build/tools/interactionTools.js.map +1 -1
  132. package/build/tools/logTools.d.ts.map +1 -1
  133. package/build/tools/logTools.js +77 -69
  134. package/build/tools/logTools.js.map +1 -1
  135. package/build/tools/networkTools.d.ts.map +1 -1
  136. package/build/tools/networkTools.js +63 -13
  137. package/build/tools/networkTools.js.map +1 -1
  138. package/build/tools/screenshotTools.d.ts.map +1 -1
  139. package/build/tools/screenshotTools.js +3 -0
  140. package/build/tools/screenshotTools.js.map +1 -1
  141. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { ExecutionResult } from "./types.js";
2
+ import type { RawComponentStack } from "./componentSource.js";
2
3
  /**
3
4
  * Toggle the Element Inspector via DevSettings native module.
4
5
  * This enables the inspector overlay programmatically.
@@ -52,4 +53,27 @@ export declare function inspectAtPoint(x: number, y: number, options?: {
52
53
  includeFrame?: boolean;
53
54
  device?: string;
54
55
  }): Promise<ExecutionResult>;
56
+ /**
57
+ * Harvests raw _debugStack strings for whatever sits at (x, y). Returns an
58
+ * empty list rather than throwing, so callers can always fall back to the
59
+ * unenriched payload.
60
+ */
61
+ export declare function harvestStacksAtPoint(x: number, y: number, device?: string): Promise<RawComponentStack[]>;
62
+ /** Same, but derives the point from an inspected element's frame. */
63
+ export declare function harvestStacksAtFrame(frame: {
64
+ left?: number;
65
+ top?: number;
66
+ width?: number;
67
+ height?: number;
68
+ } | null | undefined, device?: string): Promise<RawComponentStack[]>;
69
+ /**
70
+ * Attaches source location to an inspector payload. Never throws and never
71
+ * removes existing fields - a failure adds only a `sourceUnavailable` reason.
72
+ */
73
+ export declare function enrichWithSource(payload: Record<string, unknown>, stacks: RawComponentStack[]): Promise<Record<string, unknown>>;
74
+ /** Buffered selections, newest first, each with source resolved lazily on read. */
75
+ export declare function getSelectionHistory(options: {
76
+ device?: string;
77
+ limit?: number;
78
+ }): Promise<Record<string, unknown>[]>;
55
79
  //# sourceMappingURL=inspector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAqBtF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqCzE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA4ErF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,4BAA4B,CAC9C,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAqN1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,cAAc,CAChC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,GAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACd,GACP,OAAO,CAAC,eAAe,CAAC,CAiN1B"}
1
+ {"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAO9D;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAqBtF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqCzE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA4ErF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,4BAA4B,CAC9C,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAqN1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,cAAc,CAChC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,GAAE;IACL,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACd,GACP,OAAO,CAAC,eAAe,CAAC,CAiN1B;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACtC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAc9B;AAED,qEAAqE;AACrE,wBAAsB,oBAAoB,CACtC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EAC1F,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAW9B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,iBAAiB,EAAE,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAUlC;AAED,mFAAmF;AACnF,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAiBrC"}
@@ -1,4 +1,6 @@
1
1
  import { executeInApp } from "./jsExecute.js";
2
+ import { resolveStacksToSource, buildDebugStackHarvestExpression } from "./componentSource.js";
3
+ import { selectionBuffer } from "./selectionBuffer.js";
2
4
  // ============================================================================
3
5
  // Coordinate-Based Element Inspection (via DevTools Inspector API)
4
6
  // ============================================================================
@@ -600,4 +602,60 @@ export async function inspectAtPoint(x, y, options = {}) {
600
602
  // measure paths without letting a hung Hermes runtime stall the tool.
601
603
  return executeInApp(expression, true, { timeoutMs: 5000, originatingToolName: "inspect_at_point" }, device);
602
604
  }
605
+ /**
606
+ * Harvests raw _debugStack strings for whatever sits at (x, y). Returns an
607
+ * empty list rather than throwing, so callers can always fall back to the
608
+ * unenriched payload.
609
+ */
610
+ export async function harvestStacksAtPoint(x, y, device) {
611
+ try {
612
+ const res = await executeInApp(buildDebugStackHarvestExpression(x, y), true, { timeoutMs: 5000, originatingToolName: "get_inspector_selection" }, device);
613
+ if (!res.success || !res.result)
614
+ return [];
615
+ const parsed = JSON.parse(res.result);
616
+ return parsed.stacks ?? [];
617
+ }
618
+ catch {
619
+ return [];
620
+ }
621
+ }
622
+ /** Same, but derives the point from an inspected element's frame. */
623
+ export async function harvestStacksAtFrame(frame, device) {
624
+ if (!frame ||
625
+ frame.left === undefined ||
626
+ frame.top === undefined ||
627
+ frame.width === undefined ||
628
+ frame.height === undefined) {
629
+ return [];
630
+ }
631
+ return harvestStacksAtPoint(frame.left + frame.width / 2, frame.top + frame.height / 2, device);
632
+ }
633
+ /**
634
+ * Attaches source location to an inspector payload. Never throws and never
635
+ * removes existing fields - a failure adds only a `sourceUnavailable` reason.
636
+ */
637
+ export async function enrichWithSource(payload, stacks) {
638
+ try {
639
+ const resolved = await resolveStacksToSource(stacks);
640
+ if (resolved.source) {
641
+ return { ...payload, source: resolved.source, ancestors: resolved.ancestors };
642
+ }
643
+ return { ...payload, sourceUnavailable: resolved.sourceUnavailable ?? "unknown" };
644
+ }
645
+ catch {
646
+ return { ...payload, sourceUnavailable: "resolution-failed" };
647
+ }
648
+ }
649
+ /** Buffered selections, newest first, each with source resolved lazily on read. */
650
+ export async function getSelectionHistory(options) {
651
+ const entries = selectionBuffer.list({ device: options.device, limit: options.limit ?? 10 });
652
+ return Promise.all(entries.map(async (entry) => enrichWithSource({
653
+ element: entry.element,
654
+ path: entry.path,
655
+ frame: entry.frame,
656
+ style: entry.style,
657
+ device: entry.device,
658
+ timestamp: entry.timestamp,
659
+ }, entry.stacks)));
660
+ }
603
661
  //# sourceMappingURL=inspector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../src/core/inspector.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,15 @@
1
+ import WebSocket from "ws";
1
2
  import { ExecutionResult, ExecuteOptions } from "./types.js";
3
+ import type { DeviceInfo } from "./types.js";
2
4
  export interface ExpressionValidation {
3
5
  valid: boolean;
4
6
  expression: string;
5
7
  error?: string;
8
+ /**
9
+ * Set when the pre-flight rewrote the caller's source rather than rejecting
10
+ * it. Surfaced to the caller so an agent can see its input was transformed.
11
+ */
12
+ rewritten?: "iife-wrap";
6
13
  }
7
14
  /**
8
15
  * Check if a string contains emoji or other problematic Unicode characters
@@ -20,13 +27,81 @@ export declare function stripLeadingComments(expression: string): string;
20
27
  * Returns cleaned expression or error with helpful message
21
28
  */
22
29
  export declare function validateAndPreprocessExpression(expression: string): ExpressionValidation;
30
+ /**
31
+ * Rewrite a multi-statement source into the IIFE that Hermes can compile,
32
+ * returning `null` when the rewrite would not be safe.
33
+ *
34
+ * `stmt1; stmt2; value` becomes `(function(){ stmt1; stmt2; return value; })()`.
35
+ * Bails out when the final segment cannot yield a value, so those callers still
36
+ * get the explanatory error rather than a silently broken transform.
37
+ */
38
+ export declare function wrapMultiStatementInIife(src: string): string | null;
39
+ export declare function splitTopLevelStatements(src: string): string[];
23
40
  export declare const TIMEOUT_HARD_CAP_MS = 120000;
24
41
  export declare function markConnectionEstablished(): void;
25
42
  export declare function clampTimeoutMs(input: number): {
26
43
  value: number;
27
44
  clampedFrom?: number;
28
45
  };
29
- export type TransportPattern = "no_apps" | "ws_closed" | "target_closed" | "cdp_eval_too_long";
46
+ export type TransportPattern = "no_apps" | "ws_closed" | "target_closed" | "stale_target";
47
+ /**
48
+ * True for the one ambiguous failure shape: our own timer fired while the
49
+ * socket was still OPEN.
50
+ *
51
+ * Everything else is already decided. ws=CLOSED is transport (handled in
52
+ * classifyTransportError); a CDP-sourced error carries its own signal. This
53
+ * case alone can be either a genuinely slow expression or a stale CDP target
54
+ * that silently swallows evaluates while the device socket keeps ponging — and
55
+ * only a probe can tell them apart.
56
+ */
57
+ export declare function isEvalTimeoutOnLiveSocket(message: string, source: "cdp" | "server-timer" | "logical"): boolean;
58
+ export type ProbeTargetApp = {
59
+ ws: WebSocket;
60
+ port: number;
61
+ deviceInfo: {
62
+ id?: string;
63
+ };
64
+ };
65
+ /**
66
+ * Is our CDP page still listed by Metro?
67
+ *
68
+ * This is the signal that a JS-level probe cannot provide: it goes over Metro's
69
+ * HTTP /json, so a blocked JavaScript thread has no effect on the answer.
70
+ *
71
+ * Conservative on purpose — an empty list (Metro unreachable, momentary blip)
72
+ * or a missing id counts as "still there". A false "gone" costs a reconnect and
73
+ * a retry that RE-RUNS the caller's expression, which must never happen on a
74
+ * guess.
75
+ */
76
+ export declare function isTargetStillAdvertised(app: {
77
+ port: number;
78
+ deviceInfo: {
79
+ id?: string;
80
+ };
81
+ }, fetchTargets?: (port: number) => Promise<DeviceInfo[]>): Promise<boolean>;
82
+ /**
83
+ * classifyTransportError plus disambiguation for the one ambiguous shape: our
84
+ * timer fired while the socket was still OPEN.
85
+ *
86
+ * The transport was alive (the 1s ping/pong keepalive would have killed a dead
87
+ * socket within ~2s), so this is one of three things:
88
+ *
89
+ * 1. a genuinely slow ASYNC expression -> probe answers -> logical
90
+ * 2. a genuinely slow SYNC expression -> probe silent, but the
91
+ * (busy loop, big serialize) page is still listed -> logical
92
+ * 3. a stale CDP target (app reloaded -> probe silent AND the
93
+ * via shake / Metro 'r') page is gone -> transport
94
+ *
95
+ * Both signals are required for case 3. The probe alone cannot separate 2 from
96
+ * 3 — it is itself a Runtime.evaluate, so a blocked JS thread silences it
97
+ * exactly like a dead context. Verified on-device: a 15s busy loop silenced the
98
+ * probe and was misread as stale, triggering a reconnect that re-ran the
99
+ * expression. Metro's target list is independent of the JS thread and settles it.
100
+ *
101
+ * `probe` and `targetStillAdvertised` are injectable so the decision is
102
+ * testable without a socket or a Metro server.
103
+ */
104
+ export declare function classifyWithLivenessProbe(message: string, source: "cdp" | "server-timer" | "logical", app: ProbeTargetApp | null, probe?: (ws: WebSocket, timeoutMs: number) => Promise<boolean>, targetStillAdvertised?: (app: ProbeTargetApp) => Promise<boolean>): Promise<TransportClassification>;
30
105
  export type TransportClassification = {
31
106
  kind: "transport";
32
107
  pattern: TransportPattern;
@@ -1 +1 @@
1
- {"version":3,"file":"jsExecute.d.ts","sourceRoot":"","sources":["../../src/core/jsExecute.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAiB7D,MAAM,WAAW,oBAAoB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAK/D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA2B/D;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,CAuExF;AA2HD,eAAO,MAAM,mBAAmB,SAAU,CAAC;AAS3C,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAQrF;AAMD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAE/F,MAAM,MAAM,uBAAuB,GAC7B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1B;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,KAAK,GAAG,cAAc,GAAG,SAAS,GAC3C,uBAAuB,CAyBzB;AAuBD;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AA+UD;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAC9B,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,OAAc,EAC5B,OAAO,GAAE,cAAmB,EAC5B,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CA8E1B"}
1
+ {"version":3,"file":"jsExecute.d.ts","sourceRoot":"","sources":["../../src/core/jsExecute.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { getFirstConnectedApp, getConnectedAppByDevice, connectToDevice } from "
5
5
  import { fetchDevices, selectMainDevice, scanMetroPorts } from "./metro.js";
6
6
  import { cancelReconnectionTimer } from "./connectionState.js";
7
7
  import { trackAutoReconnect } from "./telemetry.js";
8
+ import { probeCdpAlive } from "./probe.js";
8
9
  // Hermes runtime compatibility: polyfill for 'global' which doesn't exist in Hermes
9
10
  // In Hermes, globalThis is the standard way to access global scope
10
11
  const GLOBAL_POLYFILL = `var global = typeof global !== 'undefined' ? global : globalThis;`;
@@ -91,21 +92,39 @@ export function validateAndPreprocessExpression(expression) {
91
92
  valid: false,
92
93
  expression: escaped,
93
94
  error: "require() is not available in Hermes Runtime.evaluate. " +
94
- "Modules cannot be imported at runtime. Only pre-existing global variables are accessible. " +
95
- "Use list_debug_globals to discover available globals, or add `globalThis.__MY_VAR__ = myModule;` in your app code."
95
+ "Modules cannot be imported at runtime. " +
96
+ "In a Metro dev build you can reach already-loaded modules through Metro's registry: " +
97
+ "`(function(){ var hit=null; __r.getModules().forEach(function(m,id){ " +
98
+ "if(!hit && m.verboseName && m.verboseName.indexOf('react-native/index.js') !== -1) hit=id; }); " +
99
+ "return __r(hit).Dimensions.get('window'); })()` " +
100
+ "(swap the verboseName match for the module you want). " +
101
+ "Otherwise use list_debug_globals to discover exposed globals, or add " +
102
+ "`globalThis.__MY_VAR__ = myModule;` in your app code."
96
103
  };
97
104
  }
98
105
  // Check for multi-statement expressions. Runtime.evaluate compiles input as
99
106
  // a single expression — `console.log('x'); 1+1` raises `')' expected at end
100
107
  // of parenthesized expression`. Internal callers wrap in (function(){...})()
101
108
  // so any `;` they use is at brace depth 1 and won't be flagged.
102
- if (hasTopLevelStatementSeparator(trimmed)) {
109
+ // executeWithManualAwait emits `var __v=(<expr>);`, so a depth-0 `;` breaks
110
+ // compilation. Rewrite into the IIFE ourselves instead of making the caller
111
+ // do it — this was the single largest execute_in_app failure class
112
+ // (125 events / 42 installations over 30d).
113
+ const wrapped = wrapMultiStatementInIife(trimmed);
114
+ if (wrapped) {
115
+ return { valid: true, expression: wrapped, rewritten: "iife-wrap" };
116
+ }
117
+ // More than one statement, but the last one can't yield a value — we can't
118
+ // synthesize a sensible `return`, so explain rather than guess.
119
+ if (splitTopLevelStatements(trimmed).length > 1) {
103
120
  return {
104
121
  valid: false,
105
122
  expression: escaped,
106
123
  error: "Multi-statement expressions are not supported by Hermes Runtime.evaluate " +
107
- "(compiles input as a single expression). " +
108
- "Wrap the body in an IIFE: `(function(){ stmt1; stmt2; return result; })()`."
124
+ "(compiles input as a single expression), and the final statement does not " +
125
+ "produce a value to return. " +
126
+ "Wrap the body in an IIFE with an explicit result: " +
127
+ "`(function(){ stmt1; stmt2; return result; })()`."
109
128
  };
110
129
  }
111
130
  return {
@@ -116,21 +135,19 @@ export function validateAndPreprocessExpression(expression) {
116
135
  function isIdentChar(c) {
117
136
  return c !== undefined && /[A-Za-z0-9_$]/.test(c);
118
137
  }
119
- // Detect top-level `await`, `async function`, `async (...) => ...`, or
120
- // `(async ...)` IIFE forms in `src`. Walks char-by-char tracking string,
138
+ // Detect a bare top-level `await` in `src`. Walks char-by-char tracking string,
121
139
  // template, comment, and bracket depth so we don't false-positive on
122
140
  // substrings inside strings, identifiers like `awaiting`, etc.
141
+ //
142
+ // NOTE: `async function`/`async () => {}`/`(async () => {})()` are deliberately
143
+ // NOT flagged. Hermes compiles them (they are expressions), the manual-await
144
+ // wrapper in executeWithManualAwait resolves the Promise they return, and
145
+ // telemetry showed this pre-flight rejecting ~20 legitimate calls/30d across 10
146
+ // installations. Verified on-device (iOS 26 sim, Hermes): an async arrow with an
147
+ // internal `await` evaluates correctly. Only a bare top-level `await` is a real
148
+ // syntax error, because the wrapper emits `var __v=(<expr>);` — a non-async
149
+ // context.
123
150
  function looksLikeTopLevelAwait(src) {
124
- // Cheap prefix checks for async-function / async-arrow / async-IIFE forms.
125
- // Whitespace-tolerant on `async <keyword>` / `async (`.
126
- const asyncPrefix = /^async\s*(?:function\b|\()/;
127
- if (asyncPrefix.test(src))
128
- return true;
129
- // `(async () => ...)()` or `(async(...)...)` — match `(async` followed by
130
- // a non-identifier char (so `(asyncFoo` doesn't trigger).
131
- const parenAsync = /^\(\s*async(?:\s|\()/;
132
- if (parenAsync.test(src))
133
- return true;
134
151
  // Depth-tracked scan for a standalone `await` token at depth 0.
135
152
  let i = 0;
136
153
  let parens = 0;
@@ -210,10 +227,40 @@ function looksLikeTopLevelAwait(src) {
210
227
  }
211
228
  return false;
212
229
  }
213
- // Walk `src` tracking string/template/comment and bracket depth. Returns true
214
- // iff a `;` appears at depth 0 with non-whitespace following it (i.e. it
215
- // separates two top-level statements rather than terminating a single one).
216
- function hasTopLevelStatementSeparator(src) {
230
+ // Statement forms that cannot be the final segment of an auto-wrapped IIFE,
231
+ // because prefixing them with `return` is either a syntax error or drops the
232
+ // value the caller wanted back. `return` itself is handled separately.
233
+ const NON_VALUE_STATEMENT_START = /^(?:if|for|while|do|switch|try|catch|finally|throw|var|let|const|function|class|debugger|break|continue|with|else)\b|^\{/;
234
+ /**
235
+ * Rewrite a multi-statement source into the IIFE that Hermes can compile,
236
+ * returning `null` when the rewrite would not be safe.
237
+ *
238
+ * `stmt1; stmt2; value` becomes `(function(){ stmt1; stmt2; return value; })()`.
239
+ * Bails out when the final segment cannot yield a value, so those callers still
240
+ * get the explanatory error rather than a silently broken transform.
241
+ */
242
+ export function wrapMultiStatementInIife(src) {
243
+ const segments = splitTopLevelStatements(src);
244
+ if (segments.length <= 1)
245
+ return null;
246
+ const last = segments[segments.length - 1];
247
+ if (NON_VALUE_STATEMENT_START.test(last))
248
+ return null;
249
+ const head = segments.slice(0, -1);
250
+ const body = last.startsWith("return") && !isIdentChar(last[6]) ? last : `return ${last}`;
251
+ return `(function(){ ${[...head, body].join("; ")}; })()`;
252
+ }
253
+ // Walk `src` tracking string/template/comment and bracket depth, splitting on
254
+ // `;` at depth 0. Returns the trimmed top-level statements; a trailing `;` that
255
+ // merely terminates the final statement produces no extra segment.
256
+ export function splitTopLevelStatements(src) {
257
+ const segments = [];
258
+ let segmentStart = 0;
259
+ const push = (end) => {
260
+ const seg = src.slice(segmentStart, end).trim();
261
+ if (seg.length > 0)
262
+ segments.push(seg);
263
+ };
217
264
  let i = 0;
218
265
  let parens = 0;
219
266
  let braces = 0;
@@ -224,14 +271,14 @@ function hasTopLevelStatementSeparator(src) {
224
271
  if (ch === "/" && next === "/") {
225
272
  const nl = src.indexOf("\n", i + 2);
226
273
  if (nl === -1)
227
- return false;
274
+ break;
228
275
  i = nl + 1;
229
276
  continue;
230
277
  }
231
278
  if (ch === "/" && next === "*") {
232
279
  const end = src.indexOf("*/", i + 2);
233
280
  if (end === -1)
234
- return false;
281
+ break;
235
282
  i = end + 2;
236
283
  continue;
237
284
  }
@@ -264,13 +311,13 @@ function hasTopLevelStatementSeparator(src) {
264
311
  else if (ch === "]")
265
312
  brackets--;
266
313
  else if (ch === ";" && parens === 0 && braces === 0 && brackets === 0) {
267
- const rest = src.slice(i + 1).trim();
268
- if (rest.length > 0)
269
- return true;
314
+ push(i);
315
+ segmentStart = i + 1;
270
316
  }
271
317
  i++;
272
318
  }
273
- return false;
319
+ push(src.length);
320
+ return segments;
274
321
  }
275
322
  // ============================================================================
276
323
  // Per-call timeoutMs: clamp + defaults
@@ -294,6 +341,84 @@ export function clampTimeoutMs(input) {
294
341
  }
295
342
  return { value: input };
296
343
  }
344
+ // How long to wait for the disambiguating probe on a ws=OPEN timeout. Matches
345
+ // PROBE_TIMEOUT_MS in connection.ts, which uses the same probe to reject stale
346
+ // CDP targets at connect time.
347
+ const STALE_TARGET_PROBE_TIMEOUT_MS = 1_500;
348
+ /**
349
+ * True for the one ambiguous failure shape: our own timer fired while the
350
+ * socket was still OPEN.
351
+ *
352
+ * Everything else is already decided. ws=CLOSED is transport (handled in
353
+ * classifyTransportError); a CDP-sourced error carries its own signal. This
354
+ * case alone can be either a genuinely slow expression or a stale CDP target
355
+ * that silently swallows evaluates while the device socket keeps ponging — and
356
+ * only a probe can tell them apart.
357
+ */
358
+ export function isEvalTimeoutOnLiveSocket(message, source) {
359
+ if (source !== "server-timer")
360
+ return false;
361
+ return /ws=OPEN/i.test(message);
362
+ }
363
+ /**
364
+ * Is our CDP page still listed by Metro?
365
+ *
366
+ * This is the signal that a JS-level probe cannot provide: it goes over Metro's
367
+ * HTTP /json, so a blocked JavaScript thread has no effect on the answer.
368
+ *
369
+ * Conservative on purpose — an empty list (Metro unreachable, momentary blip)
370
+ * or a missing id counts as "still there". A false "gone" costs a reconnect and
371
+ * a retry that RE-RUNS the caller's expression, which must never happen on a
372
+ * guess.
373
+ */
374
+ export async function isTargetStillAdvertised(app, fetchTargets = fetchDevices) {
375
+ const id = app.deviceInfo?.id;
376
+ if (!id)
377
+ return true;
378
+ const targets = await fetchTargets(app.port);
379
+ if (targets.length === 0)
380
+ return true;
381
+ return targets.some((t) => t.id === id);
382
+ }
383
+ /**
384
+ * classifyTransportError plus disambiguation for the one ambiguous shape: our
385
+ * timer fired while the socket was still OPEN.
386
+ *
387
+ * The transport was alive (the 1s ping/pong keepalive would have killed a dead
388
+ * socket within ~2s), so this is one of three things:
389
+ *
390
+ * 1. a genuinely slow ASYNC expression -> probe answers -> logical
391
+ * 2. a genuinely slow SYNC expression -> probe silent, but the
392
+ * (busy loop, big serialize) page is still listed -> logical
393
+ * 3. a stale CDP target (app reloaded -> probe silent AND the
394
+ * via shake / Metro 'r') page is gone -> transport
395
+ *
396
+ * Both signals are required for case 3. The probe alone cannot separate 2 from
397
+ * 3 — it is itself a Runtime.evaluate, so a blocked JS thread silences it
398
+ * exactly like a dead context. Verified on-device: a 15s busy loop silenced the
399
+ * probe and was misread as stale, triggering a reconnect that re-ran the
400
+ * expression. Metro's target list is independent of the JS thread and settles it.
401
+ *
402
+ * `probe` and `targetStillAdvertised` are injectable so the decision is
403
+ * testable without a socket or a Metro server.
404
+ */
405
+ export async function classifyWithLivenessProbe(message, source, app, probe = probeCdpAlive, targetStillAdvertised = isTargetStillAdvertised) {
406
+ const base = classifyTransportError(message, source);
407
+ if (base.kind === "transport")
408
+ return base;
409
+ if (!isEvalTimeoutOnLiveSocket(message, source))
410
+ return base;
411
+ if (!app)
412
+ return base;
413
+ const alive = await probe(app.ws, STALE_TARGET_PROBE_TIMEOUT_MS);
414
+ if (alive)
415
+ return base;
416
+ // Probe silent. Only a target that Metro no longer lists is truly stale;
417
+ // otherwise the JS thread is just busy and retrying would re-run the call.
418
+ if (await targetStillAdvertised(app))
419
+ return base;
420
+ return { kind: "transport", pattern: "stale_target" };
421
+ }
297
422
  /**
298
423
  * Classify an error message into transport-vs-logical for auto-reconnect routing.
299
424
  *
@@ -304,6 +429,17 @@ export function clampTimeoutMs(input) {
304
429
  export function classifyTransportError(message, source) {
305
430
  if (!message)
306
431
  return { kind: "logical" };
432
+ // A server-timer expiry is normally logical ("this expression is slow").
433
+ // But the timer snapshots ws state into the message, and a CLOSED socket
434
+ // means the call never had a live transport to answer it — that is a
435
+ // transport failure no matter which timer noticed. Checked before the
436
+ // server-timer bail-out, which otherwise swallowed it.
437
+ //
438
+ // Primarily a backstop: failPendingExecutionsForSocket now fails in-flight
439
+ // calls at close time, so most of these surface as "WebSocket connection is
440
+ // not open" instead. This covers the race where our timer fires first.
441
+ if (/ws=CLOSED/i.test(message))
442
+ return { kind: "transport", pattern: "ws_closed" };
307
443
  if (source === "server-timer")
308
444
  return { kind: "logical" };
309
445
  if (/No apps connected/i.test(message))
@@ -317,9 +453,14 @@ export function classifyTransportError(message, source) {
317
453
  if (/target closed/i.test(message) || /Inspector detached/i.test(message)) {
318
454
  return { kind: "transport", pattern: "target_closed" };
319
455
  }
320
- if (source === "cdp" && /Expression took too long to evaluate/i.test(message)) {
321
- return { kind: "transport", pattern: "cdp_eval_too_long" };
322
- }
456
+ // NOTE: there used to be a `cdp_eval_too_long` branch here for a CDP-side
457
+ // "Expression took too long to evaluate". It was unreachable: the only
458
+ // producer of that phrase is our own timer in executeCDP, whose message
459
+ // always starts with "Timeout: Expression took too long" and is therefore
460
+ // tagged `server-timer` and handled above. Telemetry agrees — 367 such
461
+ // events over 90 days, none of them lacking our "Connection state:" block.
462
+ // Retrying is also wrong here: the 1s ping/pong keepalive terminates dead
463
+ // sockets within ~2s, so a still-OPEN socket had a live transport all along.
323
464
  return { kind: "logical" };
324
465
  }
325
466
  // Error patterns that indicate a stale/destroyed context
@@ -401,6 +542,14 @@ function executeCDP(app, cleanedExpression, awaitPromise, timeoutMs) {
401
542
  const TIMEOUT_MS = timeoutMs;
402
543
  const currentMessageId = getNextMessageId();
403
544
  const wrappedExpression = `${GLOBAL_POLYFILL} ${cleanedExpression}`;
545
+ // Every send funnels through here, including executeWithManualAwait's poll
546
+ // loop — which re-enters between sleeps and so can start on a socket that
547
+ // died since the previous send. ws.send() on a CLOSED socket does not
548
+ // throw; it simply never gets a reply, so without this the call burns its
549
+ // full timeout and then reports a misleading "took too long".
550
+ if (app.ws.readyState !== WebSocket.OPEN) {
551
+ return Promise.resolve({ success: false, error: "WebSocket connection is not open." });
552
+ }
404
553
  return new Promise((resolve) => {
405
554
  const timeoutId = setTimeout(() => {
406
555
  pendingExecutions.delete(currentMessageId);
@@ -430,7 +579,9 @@ function executeCDP(app, cleanedExpression, awaitPromise, timeoutMs) {
430
579
  ].join("\n");
431
580
  resolve({ success: false, error: errorMessage });
432
581
  }, TIMEOUT_MS);
433
- pendingExecutions.set(currentMessageId, { resolve, timeoutId });
582
+ // Tag with the socket so a close event can fail this call immediately
583
+ // rather than letting it sit until TIMEOUT_MS.
584
+ pendingExecutions.set(currentMessageId, { resolve, timeoutId, ws: app.ws });
434
585
  try {
435
586
  app.ws.send(JSON.stringify({
436
587
  id: currentMessageId,
@@ -654,7 +805,17 @@ export async function executeInApp(expression, awaitPromise = true, options = {}
654
805
  const source = first.error?.startsWith("Timeout: Expression took too long")
655
806
  ? "server-timer"
656
807
  : "cdp";
657
- const classification = classifyTransportError(first.error ?? "", source);
808
+ // getConnectedAppByDevice throws when an explicit device name matches
809
+ // nothing; that failure is already reported via `first`, so fall back to
810
+ // "nothing to probe" rather than replacing the original error.
811
+ let probeApp = null;
812
+ try {
813
+ probeApp = getConnectedAppByDevice(device);
814
+ }
815
+ catch {
816
+ probeApp = null;
817
+ }
818
+ const classification = await classifyWithLivenessProbe(first.error ?? "", source, probeApp);
658
819
  if (classification.kind !== "transport") {
659
820
  trackAutoReconnect("not_needed", toolName);
660
821
  return withClampMeta(first);