execbro 1.10.24 → 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.
- package/build/__tests__/helpers/fake-cdp-server.d.ts +9 -0
- package/build/__tests__/helpers/fake-cdp-server.d.ts.map +1 -1
- package/build/__tests__/helpers/fake-cdp-server.js +20 -2
- package/build/__tests__/helpers/fake-cdp-server.js.map +1 -1
- package/build/__tests__/integration/connection-health.test.js +8 -1
- package/build/__tests__/integration/connection-health.test.js.map +1 -1
- package/build/__tests__/integration/socket-close-midflight.test.d.ts +2 -0
- package/build/__tests__/integration/socket-close-midflight.test.d.ts.map +1 -0
- package/build/__tests__/integration/socket-close-midflight.test.js +106 -0
- package/build/__tests__/integration/socket-close-midflight.test.js.map +1 -0
- package/build/__tests__/integration/stale-target-probe.test.d.ts +2 -0
- package/build/__tests__/integration/stale-target-probe.test.d.ts.map +1 -0
- package/build/__tests__/integration/stale-target-probe.test.js +85 -0
- package/build/__tests__/integration/stale-target-probe.test.js.map +1 -0
- package/build/__tests__/unit/deviceResolution.test.d.ts +2 -0
- package/build/__tests__/unit/deviceResolution.test.d.ts.map +1 -0
- package/build/__tests__/unit/deviceResolution.test.js +108 -0
- package/build/__tests__/unit/deviceResolution.test.js.map +1 -0
- package/build/__tests__/unit/executor.test.js +48 -12
- package/build/__tests__/unit/executor.test.js.map +1 -1
- package/build/__tests__/unit/getLogsEmptyContract.test.d.ts +2 -0
- package/build/__tests__/unit/getLogsEmptyContract.test.d.ts.map +1 -0
- package/build/__tests__/unit/getLogsEmptyContract.test.js +99 -0
- package/build/__tests__/unit/getLogsEmptyContract.test.js.map +1 -0
- package/build/__tests__/unit/logDiagnosis.test.d.ts +2 -0
- package/build/__tests__/unit/logDiagnosis.test.d.ts.map +1 -0
- package/build/__tests__/unit/logDiagnosis.test.js +81 -0
- package/build/__tests__/unit/logDiagnosis.test.js.map +1 -0
- package/build/__tests__/unit/pendingExecutions.test.d.ts +2 -0
- package/build/__tests__/unit/pendingExecutions.test.d.ts.map +1 -0
- package/build/__tests__/unit/pendingExecutions.test.js +70 -0
- package/build/__tests__/unit/pendingExecutions.test.js.map +1 -0
- package/build/__tests__/unit/reloadAppAutoConnect.test.d.ts +2 -0
- package/build/__tests__/unit/reloadAppAutoConnect.test.d.ts.map +1 -0
- package/build/__tests__/unit/reloadAppAutoConnect.test.js +63 -0
- package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -0
- package/build/__tests__/unit/transportClassify.test.js +108 -7
- package/build/__tests__/unit/transportClassify.test.js.map +1 -1
- package/build/core/connection.d.ts +30 -0
- package/build/core/connection.d.ts.map +1 -1
- package/build/core/connection.js +97 -28
- package/build/core/connection.js.map +1 -1
- package/build/core/debugGlobals.d.ts.map +1 -1
- package/build/core/debugGlobals.js +89 -32
- package/build/core/debugGlobals.js.map +1 -1
- package/build/core/errors.d.ts +7 -1
- package/build/core/errors.d.ts.map +1 -1
- package/build/core/errors.js +8 -1
- package/build/core/errors.js.map +1 -1
- package/build/core/jsExecute.d.ts +76 -1
- package/build/core/jsExecute.d.ts.map +1 -1
- package/build/core/jsExecute.js +193 -32
- package/build/core/jsExecute.js.map +1 -1
- package/build/core/logDiagnosis.d.ts +65 -0
- package/build/core/logDiagnosis.d.ts.map +1 -0
- package/build/core/logDiagnosis.js +51 -0
- package/build/core/logDiagnosis.js.map +1 -0
- package/build/core/register.d.ts.map +1 -1
- package/build/core/register.js +22 -6
- package/build/core/register.js.map +1 -1
- package/build/core/state.d.ts +10 -0
- package/build/core/state.d.ts.map +1 -1
- package/build/core/state.js +21 -0
- package/build/core/state.js.map +1 -1
- package/build/core/types.d.ts +8 -0
- package/build/core/types.d.ts.map +1 -1
- package/build/tools/connectionTools.d.ts.map +1 -1
- package/build/tools/connectionTools.js +7 -3
- package/build/tools/connectionTools.js.map +1 -1
- package/build/tools/executionTools.js +7 -7
- package/build/tools/executionTools.js.map +1 -1
- package/build/tools/logTools.d.ts.map +1 -1
- package/build/tools/logTools.js +77 -69
- package/build/tools/logTools.js.map +1 -1
- package/build/tools/networkTools.d.ts.map +1 -1
- package/build/tools/networkTools.js +63 -13
- package/build/tools/networkTools.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,6 +30,7 @@ export declare class FakeCDPServer {
|
|
|
30
30
|
private server;
|
|
31
31
|
private connections;
|
|
32
32
|
private evaluateHandler;
|
|
33
|
+
private autoAnswerProbe;
|
|
33
34
|
private _receivedMessages;
|
|
34
35
|
port: number;
|
|
35
36
|
start(): Promise<number>;
|
|
@@ -42,6 +43,14 @@ export declare class FakeCDPServer {
|
|
|
42
43
|
respondWithError(errorType: string, message: string): void;
|
|
43
44
|
/** Convenience: don't respond (causes timeout) */
|
|
44
45
|
respondWithTimeout(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Control the built-in `1+1` liveness answer. Turn off to simulate a stale
|
|
48
|
+
* CDP target: the socket stays open and keeps ponging, but no evaluate —
|
|
49
|
+
* probe included — ever comes back.
|
|
50
|
+
*/
|
|
51
|
+
setAutoAnswerProbe(enabled: boolean): void;
|
|
52
|
+
/** Drop every live device socket without shutting the server down. */
|
|
53
|
+
closeAllConnections(): void;
|
|
45
54
|
/** Get all received messages */
|
|
46
55
|
get receivedMessages(): {
|
|
47
56
|
id: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-cdp-server.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/fake-cdp-server.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACjB,MAAM,CAAC,EAAE;QACL,MAAM,CAAC,EAAE;YACL,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,CAAC,EAAE,OAAO,CAAC;YAChB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,WAAW,CAAC,EAAE,MAAM,CAAC;SACxB,CAAC;QACF,gBAAgB,CAAC,EAAE;YACf,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,EAAE,MAAM,CAAC;YACnB,YAAY,EAAE,MAAM,CAAC;YACrB,SAAS,CAAC,EAAE;gBACR,IAAI,EAAE,MAAM,CAAC;gBACb,OAAO,CAAC,EAAE,MAAM,CAAC;gBACjB,SAAS,CAAC,EAAE,MAAM,CAAC;gBACnB,WAAW,CAAC,EAAE,MAAM,CAAC;gBACrB,KAAK,CAAC,EAAE,OAAO,CAAC;aACnB,CAAC;SACL,CAAC;KACL,CAAC;IACF,KAAK,CAAC,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACL;AAED,KAAK,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,WAAW,GAAG,IAAI,CAAC;AAE/E,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,iBAAiB,CAA8E;IACvG,IAAI,SAAK;IAEH,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAqB9B,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"fake-cdp-server.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/fake-cdp-server.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACjB,MAAM,CAAC,EAAE;QACL,MAAM,CAAC,EAAE;YACL,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,CAAC,EAAE,OAAO,CAAC;YAChB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,WAAW,CAAC,EAAE,MAAM,CAAC;SACxB,CAAC;QACF,gBAAgB,CAAC,EAAE;YACf,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,EAAE,MAAM,CAAC;YACnB,YAAY,EAAE,MAAM,CAAC;YACrB,SAAS,CAAC,EAAE;gBACR,IAAI,EAAE,MAAM,CAAC;gBACb,OAAO,CAAC,EAAE,MAAM,CAAC;gBACjB,SAAS,CAAC,EAAE,MAAM,CAAC;gBACnB,WAAW,CAAC,EAAE,MAAM,CAAC;gBACrB,KAAK,CAAC,EAAE,OAAO,CAAC;aACnB,CAAC;SACL,CAAC;KACL,CAAC;IACF,KAAK,CAAC,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACL;AAED,KAAK,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,WAAW,GAAG,IAAI,CAAC;AAE/E,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,iBAAiB,CAA8E;IACvG,IAAI,SAAK;IAEH,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAqB9B,OAAO,CAAC,aAAa;IA0CrB,uFAAuF;IACvF,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAI1C,mDAAmD;IACnD,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAW,GAAG,IAAI;IAMvD,+CAA+C;IAC/C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAmB1D,kDAAkD;IAClD,kBAAkB,IAAI,IAAI;IAK1B;;;;OAIG;IACH,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI1C,sEAAsE;IACtE,mBAAmB,IAAI,IAAI;IAM3B,gCAAgC;IAChC,IAAI,gBAAgB;YAzHmB,MAAM;gBAAU,MAAM;gBAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QA2H7F;IAED,uDAAuD;IACvD,IAAI,KAAK,IAAI,MAAM,CAElB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAY9B"}
|
|
@@ -3,6 +3,7 @@ export class FakeCDPServer {
|
|
|
3
3
|
server = null;
|
|
4
4
|
connections = [];
|
|
5
5
|
evaluateHandler = null;
|
|
6
|
+
autoAnswerProbe = true;
|
|
6
7
|
_receivedMessages = [];
|
|
7
8
|
port = 0;
|
|
8
9
|
async start() {
|
|
@@ -30,9 +31,12 @@ export class FakeCDPServer {
|
|
|
30
31
|
ws.send(JSON.stringify({ id: msg.id, result: {} }));
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
|
-
//
|
|
34
|
+
// Answer the liveness probe correctly so connectToDevice can proceed.
|
|
34
35
|
// The probe sends `1+1` with returnByValue; treat any such request as live.
|
|
35
|
-
|
|
36
|
+
// Tests that need to simulate a stale target (socket alive, JS context
|
|
37
|
+
// gone) turn this off via setAutoAnswerProbe(false) and let their own
|
|
38
|
+
// evaluate handler decide.
|
|
39
|
+
if (msg.method === "Runtime.evaluate" && this.autoAnswerProbe) {
|
|
36
40
|
const expr = msg.params?.expression ?? "";
|
|
37
41
|
if (expr === "1+1") {
|
|
38
42
|
ws.send(JSON.stringify({
|
|
@@ -95,6 +99,20 @@ export class FakeCDPServer {
|
|
|
95
99
|
// Set a handler that returns null — handleMessage skips sending
|
|
96
100
|
this.onEvaluate(() => null);
|
|
97
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Control the built-in `1+1` liveness answer. Turn off to simulate a stale
|
|
104
|
+
* CDP target: the socket stays open and keeps ponging, but no evaluate —
|
|
105
|
+
* probe included — ever comes back.
|
|
106
|
+
*/
|
|
107
|
+
setAutoAnswerProbe(enabled) {
|
|
108
|
+
this.autoAnswerProbe = enabled;
|
|
109
|
+
}
|
|
110
|
+
/** Drop every live device socket without shutting the server down. */
|
|
111
|
+
closeAllConnections() {
|
|
112
|
+
for (const ws of [...this.connections]) {
|
|
113
|
+
ws.close();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
98
116
|
/** Get all received messages */
|
|
99
117
|
get receivedMessages() {
|
|
100
118
|
return this._receivedMessages;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-cdp-server.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/fake-cdp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAa,MAAM,IAAI,CAAC;AAgChD,MAAM,OAAO,aAAa;IACd,MAAM,GAA2B,IAAI,CAAC;IACtC,WAAW,GAAgB,EAAE,CAAC;IAC9B,eAAe,GAA2B,IAAI,CAAC;IAC/C,iBAAiB,GAA2E,EAAE,CAAC;IACvG,IAAI,GAAG,CAAC,CAAC;IAET,KAAK,CAAC,KAAK;QACP,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE;gBAChD,IAAI,CAAC,IAAI,GAAI,IAAI,CAAC,MAAO,CAAC,OAAO,EAAuB,CAAC,IAAI,CAAC;gBAC9D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE;gBAChC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC1B,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;oBACtB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;oBACxC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACjC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBAChC,CAAC,CAAC,CAAC;gBACH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;oBAChB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;gBAChE,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,aAAa,CAAC,EAAa,EAAE,GAAqE;QACtG,yCAAyC;QACzC,IAAI,GAAG,CAAC,MAAM,KAAK,gBAAgB,IAAI,GAAG,CAAC,MAAM,KAAK,YAAY,IAAI,GAAG,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;YACpG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YACpD,OAAO;QACX,CAAC;QAED,
|
|
1
|
+
{"version":3,"file":"fake-cdp-server.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/fake-cdp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,14 @@ import { jest, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach
|
|
|
2
2
|
import { connectToDevice } from "../../core/connection.js";
|
|
3
3
|
import { checkAndEnsureConnection, getPassiveConnectionStatus } from "../../core/connection.js";
|
|
4
4
|
import { connectedApps, pendingExecutions, updateLastCDPMessageTime, clearAllCDPMessageTimes } from "../../core/state.js";
|
|
5
|
+
import { scanMetroPorts } from "../../core/metro.js";
|
|
5
6
|
import { FakeCDPServer } from "../helpers/fake-cdp-server.js";
|
|
7
|
+
// checkAndEnsureConnection() scans the real Metro ports, so the "nothing is
|
|
8
|
+
// available" case only holds when the machine running the suite genuinely has
|
|
9
|
+
// no Metro up. Developers usually do (port 8081), so probe the same ports the
|
|
10
|
+
// code under test scans and skip rather than fail on a false negative.
|
|
11
|
+
const metroPortsInUse = await scanMetroPorts();
|
|
12
|
+
const itWithoutMetro = metroPortsInUse.length > 0 ? it.skip : it;
|
|
6
13
|
describe("Connection health (integration)", () => {
|
|
7
14
|
let server;
|
|
8
15
|
beforeAll(() => {
|
|
@@ -125,7 +132,7 @@ describe("Connection health (integration)", () => {
|
|
|
125
132
|
});
|
|
126
133
|
});
|
|
127
134
|
describe("checkAndEnsureConnection", () => {
|
|
128
|
-
|
|
135
|
+
itWithoutMetro("returns failure when no Metro server is available", async () => {
|
|
129
136
|
const result = await checkAndEnsureConnection();
|
|
130
137
|
expect(result.connected).toBe(false);
|
|
131
138
|
expect(result.wasReconnected).toBe(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-health.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/connection-health.test.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"connection-health.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/connection-health.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-close-midflight.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/socket-close-midflight.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { jest, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from "@jest/globals";
|
|
2
|
+
import { connectToDevice } from "../../core/connection.js";
|
|
3
|
+
import { executeInApp } from "../../core/jsExecute.js";
|
|
4
|
+
import { connectedApps, pendingExecutions } from "../../core/state.js";
|
|
5
|
+
import { FakeCDPServer } from "../helpers/fake-cdp-server.js";
|
|
6
|
+
// A socket that dies mid-call used to leave the request parked for the whole
|
|
7
|
+
// timeoutMs and then report "Timeout: Expression took too long", which the
|
|
8
|
+
// auto-reconnect wrapper classified as a logical timeout — so it never retried.
|
|
9
|
+
// Telemetry: 48 events/30d across 12 tools, durations sitting exactly on the
|
|
10
|
+
// timeout values (5001 / 10001 / 30007ms).
|
|
11
|
+
describe("socket close mid-flight", () => {
|
|
12
|
+
let server;
|
|
13
|
+
let device;
|
|
14
|
+
const MARKER = "__MIDFLIGHT_MARKER__";
|
|
15
|
+
// Comfortably longer than the assertions below, so a pass cannot be the
|
|
16
|
+
// timeout merely being short.
|
|
17
|
+
const LONG_TIMEOUT_MS = 30_000;
|
|
18
|
+
beforeAll(() => {
|
|
19
|
+
jest.spyOn(console, "error").mockImplementation(() => { });
|
|
20
|
+
});
|
|
21
|
+
afterAll(() => {
|
|
22
|
+
jest.restoreAllMocks();
|
|
23
|
+
});
|
|
24
|
+
beforeEach(async () => {
|
|
25
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
26
|
+
try {
|
|
27
|
+
app.ws.close();
|
|
28
|
+
}
|
|
29
|
+
catch { /* ignore */ }
|
|
30
|
+
connectedApps.delete(key);
|
|
31
|
+
}
|
|
32
|
+
pendingExecutions.clear();
|
|
33
|
+
server = new FakeCDPServer();
|
|
34
|
+
const port = await server.start();
|
|
35
|
+
device = {
|
|
36
|
+
id: "test-device",
|
|
37
|
+
title: "Hermes React Native",
|
|
38
|
+
description: "Test Device",
|
|
39
|
+
appId: "com.test.app",
|
|
40
|
+
type: "node",
|
|
41
|
+
webSocketDebuggerUrl: `${server.wsUrl}/inspector/device?page=1`,
|
|
42
|
+
deviceName: "Test",
|
|
43
|
+
};
|
|
44
|
+
await connectToDevice(device, port, {
|
|
45
|
+
reconnectionConfig: { enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1 },
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
afterEach(async () => {
|
|
49
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
50
|
+
try {
|
|
51
|
+
app.ws.close();
|
|
52
|
+
}
|
|
53
|
+
catch { /* ignore */ }
|
|
54
|
+
connectedApps.delete(key);
|
|
55
|
+
}
|
|
56
|
+
pendingExecutions.clear();
|
|
57
|
+
await server.stop();
|
|
58
|
+
});
|
|
59
|
+
it("fails an in-flight call as a transport error instead of waiting out the timeout", async () => {
|
|
60
|
+
// Never answer; drop the socket instead.
|
|
61
|
+
server.onEvaluate((params) => {
|
|
62
|
+
const expr = String(params.expression ?? "");
|
|
63
|
+
if (expr.includes(MARKER)) {
|
|
64
|
+
setImmediate(() => server.closeAllConnections());
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
});
|
|
68
|
+
const started = Date.now();
|
|
69
|
+
const result = await executeInApp(`${MARKER}()`, false, {
|
|
70
|
+
timeoutMs: LONG_TIMEOUT_MS,
|
|
71
|
+
autoReconnect: false,
|
|
72
|
+
originatingToolName: "execute_in_app",
|
|
73
|
+
});
|
|
74
|
+
const elapsed = Date.now() - started;
|
|
75
|
+
expect(result.success).toBe(false);
|
|
76
|
+
expect(result.error).toMatch(/WebSocket connection is not open/i);
|
|
77
|
+
expect(elapsed).toBeLessThan(5_000);
|
|
78
|
+
});
|
|
79
|
+
it("fails a poll issued after the socket died instead of waiting out the poll timeout", async () => {
|
|
80
|
+
// First call returns the manual-await sentinel so we enter the poll
|
|
81
|
+
// loop, then the socket dies while the loop is sleeping between polls.
|
|
82
|
+
let answeredFirst = false;
|
|
83
|
+
server.onEvaluate((params) => {
|
|
84
|
+
const expr = String(params.expression ?? "");
|
|
85
|
+
if (!expr.includes(MARKER))
|
|
86
|
+
return null;
|
|
87
|
+
if (!answeredFirst) {
|
|
88
|
+
answeredFirst = true;
|
|
89
|
+
setImmediate(() => server.closeAllConnections());
|
|
90
|
+
return { result: { result: { type: "string", value: "__awaiting__" } } };
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
});
|
|
94
|
+
const started = Date.now();
|
|
95
|
+
const result = await executeInApp(`${MARKER}()`, true, {
|
|
96
|
+
timeoutMs: LONG_TIMEOUT_MS,
|
|
97
|
+
autoReconnect: false,
|
|
98
|
+
originatingToolName: "execute_in_app",
|
|
99
|
+
});
|
|
100
|
+
const elapsed = Date.now() - started;
|
|
101
|
+
expect(result.success).toBe(false);
|
|
102
|
+
expect(result.error).toMatch(/WebSocket connection is not open/i);
|
|
103
|
+
expect(elapsed).toBeLessThan(5_000);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=socket-close-midflight.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-close-midflight.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/socket-close-midflight.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-target-probe.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/stale-target-probe.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { jest, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from "@jest/globals";
|
|
2
|
+
import { connectToDevice } from "../../core/connection.js";
|
|
3
|
+
import { executeInApp } from "../../core/jsExecute.js";
|
|
4
|
+
import { connectedApps, pendingExecutions } from "../../core/state.js";
|
|
5
|
+
import { FakeCDPServer } from "../helpers/fake-cdp-server.js";
|
|
6
|
+
// A timeout while the socket is still OPEN is ambiguous. The 1s ping/pong
|
|
7
|
+
// keepalive terminates genuinely dead sockets within ~2s, so an OPEN socket
|
|
8
|
+
// means the transport was alive the whole time — but the CDP *target* can still
|
|
9
|
+
// be stale (app reloaded via shake / Metro 'r'), silently swallowing evaluates.
|
|
10
|
+
// Telemetry showed trivial expressions (`1+1`, `globalThis.__DEV__`) timing out
|
|
11
|
+
// this way, which no amount of "the expression was slow" explains.
|
|
12
|
+
//
|
|
13
|
+
// A single cheap probe separates the two cases.
|
|
14
|
+
describe("stale-target probe on ws=OPEN timeout", () => {
|
|
15
|
+
let server;
|
|
16
|
+
let device;
|
|
17
|
+
const MARKER = "__STALE_PROBE_MARKER__";
|
|
18
|
+
const EXPR_TIMEOUT_MS = 1_500;
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
jest.spyOn(console, "error").mockImplementation(() => { });
|
|
21
|
+
});
|
|
22
|
+
afterAll(() => {
|
|
23
|
+
jest.restoreAllMocks();
|
|
24
|
+
});
|
|
25
|
+
beforeEach(async () => {
|
|
26
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
27
|
+
try {
|
|
28
|
+
app.ws.close();
|
|
29
|
+
}
|
|
30
|
+
catch { /* ignore */ }
|
|
31
|
+
connectedApps.delete(key);
|
|
32
|
+
}
|
|
33
|
+
pendingExecutions.clear();
|
|
34
|
+
server = new FakeCDPServer();
|
|
35
|
+
const port = await server.start();
|
|
36
|
+
device = {
|
|
37
|
+
id: "test-device",
|
|
38
|
+
title: "Hermes React Native",
|
|
39
|
+
description: "Test Device",
|
|
40
|
+
appId: "com.test.app",
|
|
41
|
+
type: "node",
|
|
42
|
+
webSocketDebuggerUrl: `${server.wsUrl}/inspector/device?page=1`,
|
|
43
|
+
deviceName: "Test",
|
|
44
|
+
};
|
|
45
|
+
await connectToDevice(device, port, {
|
|
46
|
+
reconnectionConfig: { enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1 },
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
afterEach(async () => {
|
|
50
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
51
|
+
try {
|
|
52
|
+
app.ws.close();
|
|
53
|
+
}
|
|
54
|
+
catch { /* ignore */ }
|
|
55
|
+
connectedApps.delete(key);
|
|
56
|
+
}
|
|
57
|
+
pendingExecutions.clear();
|
|
58
|
+
await server.stop();
|
|
59
|
+
});
|
|
60
|
+
const isProbe = (expr) => expr.trim() === "1+1";
|
|
61
|
+
const probeOk = { result: { result: { type: "number", value: 2 } } };
|
|
62
|
+
it("leaves a genuinely slow expression alone when the probe still answers", async () => {
|
|
63
|
+
// Target is healthy: probes answer. The marker expression just never
|
|
64
|
+
// finishes — a real slow call, which must NOT trigger a reconnect.
|
|
65
|
+
server.onEvaluate((params) => {
|
|
66
|
+
const expr = String(params.expression ?? "");
|
|
67
|
+
if (isProbe(expr))
|
|
68
|
+
return probeOk;
|
|
69
|
+
return null;
|
|
70
|
+
});
|
|
71
|
+
const result = await executeInApp(`${MARKER}()`, false, {
|
|
72
|
+
timeoutMs: EXPR_TIMEOUT_MS,
|
|
73
|
+
originatingToolName: "execute_in_app",
|
|
74
|
+
});
|
|
75
|
+
expect(result.success).toBe(false);
|
|
76
|
+
expect(result.error).toMatch(/took too long/i);
|
|
77
|
+
expect(result.error).not.toMatch(/reconnect_attempted|reconnected_but_still_failed/);
|
|
78
|
+
});
|
|
79
|
+
// The silent-probe case is NOT tested here on purpose. Driving it through
|
|
80
|
+
// executeInApp reaches attemptQuickReconnect -> scanMetroPorts(), which
|
|
81
|
+
// scans real localhost ports and latches onto whatever Metro the developer
|
|
82
|
+
// happens to be running — it hung against a live dev server. That decision
|
|
83
|
+
// is covered without a socket by the classifyWithLivenessProbe unit tests.
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=stale-target-probe.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-target-probe.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/stale-target-probe.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,0EAA0E;AAC1E,4EAA4E;AAC5E,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,mEAAmE;AACnE,EAAE;AACF,gDAAgD;AAChD,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACnD,IAAI,MAAqB,CAAC;IAC1B,IAAI,MAAkB,CAAC;IAEvB,MAAM,MAAM,GAAG,wBAAwB,CAAC;IACxC,MAAM,eAAe,GAAG,KAAK,CAAC;IAE9B,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,GAAG,EAAE;QACV,IAAI,CAAC,eAAe,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/C,IAAI,CAAC;gBAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC9C,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAE1B,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QAElC,MAAM,GAAG;YACL,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,qBAAqB;YAC5B,WAAW,EAAE,aAAa;YAC1B,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,MAAM;YACZ,oBAAoB,EAAE,GAAG,MAAM,CAAC,KAAK,0BAA0B;YAC/D,UAAU,EAAE,MAAM;SACrB,CAAC;QAEF,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE;YAChC,kBAAkB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE;SACjH,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACjB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/C,IAAI,CAAC;gBAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC9C,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC1B,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC;IACxD,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;IAErE,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACnF,qEAAqE;QACrE,mEAAmE;QACnE,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,EAAE;YACzB,MAAM,IAAI,GAAG,MAAM,CAAE,MAAkC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;YAC1E,IAAI,OAAO,CAAC,IAAI,CAAC;gBAAE,OAAO,OAAO,CAAC;YAClC,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,MAAM,IAAI,EAAE,KAAK,EAAE;YACpD,SAAS,EAAE,eAAe;YAC1B,mBAAmB,EAAE,gBAAgB;SACxC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,kDAAkD,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,wEAAwE;IACxE,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;AAC/E,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceResolution.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/deviceResolution.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "@jest/globals";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
const { connectedApps } = await import("../../core/state.js");
|
|
4
|
+
const { resolveConnectedAppByDevice, describeDeviceResolution, getConnectedAppByDevice } = await import("../../core/connection.js");
|
|
5
|
+
function makeApp(key, deviceName, platform, ids = {}) {
|
|
6
|
+
return {
|
|
7
|
+
ws: { readyState: WebSocket.OPEN },
|
|
8
|
+
deviceInfo: {
|
|
9
|
+
id: key,
|
|
10
|
+
title: "Hermes React Native",
|
|
11
|
+
description: "",
|
|
12
|
+
appId: "com.test",
|
|
13
|
+
type: "node",
|
|
14
|
+
webSocketDebuggerUrl: `ws://localhost:8081/${key}`,
|
|
15
|
+
deviceName
|
|
16
|
+
},
|
|
17
|
+
port: 8081,
|
|
18
|
+
platform,
|
|
19
|
+
...ids
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
describe("resolveConnectedAppByDevice", () => {
|
|
23
|
+
beforeEach(() => connectedApps.clear());
|
|
24
|
+
afterEach(() => connectedApps.clear());
|
|
25
|
+
it("reports kind=none instead of throwing when nothing is connected", () => {
|
|
26
|
+
const resolution = resolveConnectedAppByDevice("iPhone 17 Pro");
|
|
27
|
+
expect(resolution.kind).toBe("none");
|
|
28
|
+
// The recoverable-miss contract: reload_app relies on this to run its
|
|
29
|
+
// auto-connect sweep rather than aborting on the first resolve.
|
|
30
|
+
expect(describeDeviceResolution(resolution)).toContain("No devices are currently connected");
|
|
31
|
+
});
|
|
32
|
+
it("matches on device name, simulator UDID, and adb serial", () => {
|
|
33
|
+
connectedApps.set("a", makeApp("a", "iPhone 17 Pro", "ios", { simulatorUdid: "549D04C7-A774-4313-BFC0-F132FF609274" }));
|
|
34
|
+
connectedApps.set("b", makeApp("b", "sdk_gphone16k_arm64 - 17 - API 37", "android", { adbSerial: "emulator-5554" }));
|
|
35
|
+
expect(resolveConnectedAppByDevice("iphone 17")).toMatchObject({ kind: "ok", app: { platform: "ios" } });
|
|
36
|
+
expect(resolveConnectedAppByDevice("549D04C7")).toMatchObject({ kind: "ok", app: { platform: "ios" } });
|
|
37
|
+
expect(resolveConnectedAppByDevice("emulator-5554")).toMatchObject({ kind: "ok", app: { platform: "android" } });
|
|
38
|
+
});
|
|
39
|
+
it("prefers the exact name over a broader substring match", () => {
|
|
40
|
+
connectedApps.set("a", makeApp("a", "iPhone 17 Pro", "ios"));
|
|
41
|
+
connectedApps.set("b", makeApp("b", "iPhone 17 Pro Max", "ios"));
|
|
42
|
+
const resolution = resolveConnectedAppByDevice("iPhone 17 Pro");
|
|
43
|
+
expect(resolution).toMatchObject({ kind: "ok" });
|
|
44
|
+
if (resolution.kind === "ok") {
|
|
45
|
+
expect(resolution.app.deviceInfo.deviceName).toBe("iPhone 17 Pro");
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
it("reports ambiguity when several devices match and none exactly", () => {
|
|
49
|
+
connectedApps.set("a", makeApp("a", "iPhone 17 Pro", "ios"));
|
|
50
|
+
connectedApps.set("b", makeApp("b", "iPhone 17 Pro Max", "ios"));
|
|
51
|
+
const resolution = resolveConnectedAppByDevice("iPhone 17");
|
|
52
|
+
expect(resolution.kind).toBe("ambiguous");
|
|
53
|
+
expect(describeDeviceResolution(resolution)).toContain("Multiple devices match");
|
|
54
|
+
});
|
|
55
|
+
it("names the platform mismatch when only the other platform is attached", () => {
|
|
56
|
+
connectedApps.set("b", makeApp("b", "sdk_gphone16k_arm64 - 17 - API 37", "android", { adbSerial: "emulator-5554" }));
|
|
57
|
+
const message = describeDeviceResolution(resolveConnectedAppByDevice("iPhone 17 Pro"));
|
|
58
|
+
expect(message).toContain("Only Android device(s) are attached");
|
|
59
|
+
expect(message).toContain("ios_launch_app");
|
|
60
|
+
});
|
|
61
|
+
it("names the mismatch in the other direction too", () => {
|
|
62
|
+
connectedApps.set("a", makeApp("a", "iPhone 17 Pro", "ios"));
|
|
63
|
+
const message = describeDeviceResolution(resolveConnectedAppByDevice("Pixel 7 Pro"));
|
|
64
|
+
expect(message).toContain("Only iOS device(s) are attached");
|
|
65
|
+
expect(message).toContain("android_launch_app");
|
|
66
|
+
});
|
|
67
|
+
it("falls back to listing connected devices when the platform is unclear", () => {
|
|
68
|
+
connectedApps.set("a", makeApp("a", "iPhone 17 Pro", "ios"));
|
|
69
|
+
const message = describeDeviceResolution(resolveConnectedAppByDevice("Squadra"));
|
|
70
|
+
expect(message).toContain('Connected devices: "iPhone 17 Pro"');
|
|
71
|
+
expect(message).toContain("get_apps");
|
|
72
|
+
});
|
|
73
|
+
it("drops apps whose socket is no longer OPEN", () => {
|
|
74
|
+
const stale = makeApp("a", "iPhone 17 Pro", "ios");
|
|
75
|
+
stale.ws = { readyState: WebSocket.CLOSED };
|
|
76
|
+
connectedApps.set("a", stale);
|
|
77
|
+
expect(resolveConnectedAppByDevice("iPhone 17 Pro").kind).toBe("none");
|
|
78
|
+
expect(connectedApps.size).toBe(0);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("getConnectedAppByDevice", () => {
|
|
82
|
+
beforeEach(() => connectedApps.clear());
|
|
83
|
+
afterEach(() => connectedApps.clear());
|
|
84
|
+
it("still throws UserInputError on a miss, now with a triage context", () => {
|
|
85
|
+
connectedApps.set("a", makeApp("a", "iPhone 17 Pro", "ios"));
|
|
86
|
+
try {
|
|
87
|
+
getConnectedAppByDevice("Pixel 7 Pro");
|
|
88
|
+
throw new Error("expected getConnectedAppByDevice to throw");
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
expect(error.name).toBe("UserInputError");
|
|
92
|
+
expect(error.context).toBe("device_mismatch");
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
it("tags the no-devices case distinctly", () => {
|
|
96
|
+
try {
|
|
97
|
+
getConnectedAppByDevice("Pixel 7 Pro");
|
|
98
|
+
throw new Error("expected getConnectedAppByDevice to throw");
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
expect(error.context).toBe("no_devices_connected");
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
it("returns null (never throws) when no device argument is given", () => {
|
|
105
|
+
expect(getConnectedAppByDevice()).toBeNull();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=deviceResolution.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceResolution.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/deviceResolution.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,32 +51,65 @@ describe("validateAndPreprocessExpression", () => {
|
|
|
51
51
|
expect(result.valid).toBe(false);
|
|
52
52
|
expect(result.error).toContain("empty");
|
|
53
53
|
});
|
|
54
|
-
|
|
54
|
+
// Hermes compiles async arrows/functions fine — they are expressions, and the
|
|
55
|
+
// manual-await wrapper resolves the Promise they return. Verified on-device
|
|
56
|
+
// (iOS 26 sim, Hermes): `(async () => { const r = await Promise.resolve(41);
|
|
57
|
+
// return r + 1; })()` evaluates to 42. Only a BARE top-level `await` is a
|
|
58
|
+
// genuine syntax error, because the wrapper emits `var __v=(<expr>);`.
|
|
59
|
+
it("accepts an async arrow expression", () => {
|
|
55
60
|
const result = validateAndPreprocessExpression("async () => { await fetch() }");
|
|
56
|
-
expect(result.valid).toBe(
|
|
57
|
-
expect(result.error).toMatch(/top-level await is not supported in Hermes/i);
|
|
61
|
+
expect(result.valid).toBe(true);
|
|
58
62
|
});
|
|
59
|
-
it("
|
|
63
|
+
it("accepts async IIFE", () => {
|
|
60
64
|
const result = validateAndPreprocessExpression("(async () => { await fetch() })()");
|
|
65
|
+
expect(result.valid).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it("points require() callers at Metro's __r registry", () => {
|
|
68
|
+
const result = validateAndPreprocessExpression("require('react-native').Dimensions.get('window')");
|
|
61
69
|
expect(result.valid).toBe(false);
|
|
62
|
-
expect(result.error).
|
|
70
|
+
expect(result.error).toContain("require()");
|
|
71
|
+
expect(result.error).toContain("__r");
|
|
63
72
|
});
|
|
64
73
|
it("strips comments and validates remaining expression", () => {
|
|
65
74
|
const result = validateAndPreprocessExpression("// setup\n__DEV__");
|
|
66
75
|
expect(result.valid).toBe(true);
|
|
67
76
|
expect(result.expression).toBe("__DEV__");
|
|
68
77
|
});
|
|
69
|
-
|
|
78
|
+
// The manual-await path emits `var __v=(<expr>);`, so a top-level `;` really
|
|
79
|
+
// does break compilation. Rather than reject, rewrite into the IIFE the old
|
|
80
|
+
// error message used to ask the caller to write by hand.
|
|
81
|
+
it("auto-wraps a multi-statement expression into an IIFE", () => {
|
|
70
82
|
const result = validateAndPreprocessExpression("var x = 1; x");
|
|
83
|
+
expect(result.valid).toBe(true);
|
|
84
|
+
expect(result.expression).toBe("(function(){ var x = 1; return x; })()");
|
|
85
|
+
expect(result.rewritten).toBe("iife-wrap");
|
|
86
|
+
});
|
|
87
|
+
it("auto-wraps multi-statement with console.log, returning the final value", () => {
|
|
88
|
+
const result = validateAndPreprocessExpression("console.log('[TEST] hello'); 1+1");
|
|
89
|
+
expect(result.valid).toBe(true);
|
|
90
|
+
expect(result.expression).toBe("(function(){ console.log('[TEST] hello'); return 1+1; })()");
|
|
91
|
+
});
|
|
92
|
+
it("auto-wraps the real-world globalThis assignment pattern", () => {
|
|
93
|
+
const result = validateAndPreprocessExpression("globalThis.__perfRow=0; globalThis.__perfMount=0; 'ok'");
|
|
94
|
+
expect(result.valid).toBe(true);
|
|
95
|
+
expect(result.expression).toBe("(function(){ globalThis.__perfRow=0; globalThis.__perfMount=0; return 'ok'; })()");
|
|
96
|
+
});
|
|
97
|
+
it("does not auto-wrap when the final statement cannot yield a value", () => {
|
|
98
|
+
const result = validateAndPreprocessExpression("var x = 1; if (x) { x++ }");
|
|
71
99
|
expect(result.valid).toBe(false);
|
|
72
100
|
expect(result.error).toContain("Multi-statement");
|
|
73
101
|
expect(result.error).toContain("IIFE");
|
|
74
102
|
});
|
|
75
|
-
it("
|
|
76
|
-
const result = validateAndPreprocessExpression("
|
|
103
|
+
it("does not auto-wrap when the final statement is a declaration", () => {
|
|
104
|
+
const result = validateAndPreprocessExpression("var x = 1; var y = 2");
|
|
77
105
|
expect(result.valid).toBe(false);
|
|
78
106
|
expect(result.error).toContain("Multi-statement");
|
|
79
107
|
});
|
|
108
|
+
it("preserves an explicit trailing return when auto-wrapping", () => {
|
|
109
|
+
const result = validateAndPreprocessExpression("var x = 1; return x");
|
|
110
|
+
expect(result.valid).toBe(true);
|
|
111
|
+
expect(result.expression).toBe("(function(){ var x = 1; return x; })()");
|
|
112
|
+
});
|
|
80
113
|
it("accepts trailing semicolon on a single statement", () => {
|
|
81
114
|
const result = validateAndPreprocessExpression("1 + 1;");
|
|
82
115
|
expect(result.valid).toBe(true);
|
|
@@ -103,13 +136,16 @@ describe("validateAndPreprocessExpression", () => {
|
|
|
103
136
|
expect(result.error).toMatch(/top-level await is not supported in Hermes/i);
|
|
104
137
|
expect(result.error).toMatch(/Promise\.resolve\(\)\.then/);
|
|
105
138
|
});
|
|
106
|
-
it("
|
|
139
|
+
it("accepts async function expressions", () => {
|
|
107
140
|
const result = validateAndPreprocessExpression("async function x() { return 1 }");
|
|
108
|
-
expect(result.valid).toBe(
|
|
109
|
-
expect(result.error).toMatch(/top-level await is not supported in Hermes/i);
|
|
141
|
+
expect(result.valid).toBe(true);
|
|
110
142
|
});
|
|
111
|
-
it("
|
|
143
|
+
it("accepts a concise async arrow IIFE", () => {
|
|
112
144
|
const result = validateAndPreprocessExpression("(async () => 1)()");
|
|
145
|
+
expect(result.valid).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
it("still rejects a bare top-level await inside an async IIFE's caller position", () => {
|
|
148
|
+
const result = validateAndPreprocessExpression("await (async () => 1)()");
|
|
113
149
|
expect(result.valid).toBe(false);
|
|
114
150
|
expect(result.error).toMatch(/top-level await is not supported in Hermes/i);
|
|
115
151
|
});
|