rnxsim 0.1.485 → 0.1.487

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 (54) hide show
  1. package/cli/commands/agent-wrapper.ts +10 -8
  2. package/detox/index.ts +104 -11
  3. package/dist-lib/agent-daemon-client.cjs +1 -1
  4. package/dist-lib/agent-events.cjs +1 -1
  5. package/dist-lib/agent-identity.cjs +1 -1
  6. package/dist-lib/agent-sessions.cjs +1 -1
  7. package/dist-lib/attached-projects.cjs +1 -1
  8. package/dist-lib/auth/shared-session.cjs +1 -1
  9. package/dist-lib/backend-origin.cjs +1 -1
  10. package/dist-lib/beta.cjs +1 -1
  11. package/dist-lib/beta.mjs +1 -1
  12. package/dist-lib/bridge-constants.cjs +1 -1
  13. package/dist-lib/bridge-contract-input.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.mjs +1 -1
  15. package/dist-lib/bridge-contract.cjs +1 -1
  16. package/dist-lib/bridge-contract.mjs +1 -1
  17. package/dist-lib/capture-contract.cjs +1 -1
  18. package/dist-lib/capture-contract.mjs +1 -1
  19. package/dist-lib/cli-constants.cjs +1 -1
  20. package/dist-lib/cloud-contract.cjs +1 -1
  21. package/dist-lib/cloud-contract.mjs +1 -1
  22. package/dist-lib/cloud.cjs +1 -1
  23. package/dist-lib/cloud.mjs +1 -1
  24. package/dist-lib/config.cjs +1 -1
  25. package/dist-lib/detox/index.cjs +93 -12
  26. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  27. package/dist-lib/home-paths.cjs +1 -1
  28. package/dist-lib/host/bridge-host.cjs +1 -1
  29. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  30. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  31. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  32. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  33. package/dist-lib/host/websocket-proxy.cjs +1 -1
  34. package/dist-lib/index.cjs +1 -1
  35. package/dist-lib/jump-to-source-babel.cjs +1 -1
  36. package/dist-lib/jump-to-source-native.cjs +1 -1
  37. package/dist-lib/menu.cjs +1 -1
  38. package/dist-lib/menu.mjs +1 -1
  39. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  40. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  41. package/dist-lib/metro-production-bundle.cjs +1 -1
  42. package/dist-lib/metro-production-bundle.mjs +1 -1
  43. package/dist-lib/metro.cjs +1 -1
  44. package/dist-lib/profiles.cjs +1 -1
  45. package/dist-lib/public-brand.cjs +1 -1
  46. package/dist-lib/react-native-host-modules.cjs +1 -1
  47. package/dist-lib/react-native-host-modules.mjs +1 -1
  48. package/dist-lib/render-mode.cjs +1 -1
  49. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  50. package/dist-lib/sdk.cjs +1 -1
  51. package/dist-lib/sdk.mjs +1 -1
  52. package/dist-lib/skills.cjs +1 -1
  53. package/dist-lib/vite.cjs +1 -1
  54. package/package.json +1 -1
@@ -284,14 +284,6 @@ export async function runAgentWrapper(argv: string[]): Promise<number> {
284
284
  }
285
285
  }
286
286
 
287
- emit({
288
- type: 'ready',
289
- sessionId,
290
- projectId,
291
- provider,
292
- cwd,
293
- } as AgentEvent)
294
-
295
287
  // serialize turn execution per-session — queue prompts while one is in
296
288
  // flight. both codex and claude serialize per-session internally, but
297
289
  // gating here keeps wrapper event ordering honest.
@@ -452,6 +444,16 @@ export async function runAgentWrapper(argv: string[]): Promise<number> {
452
444
  } as AgentEvent)
453
445
  })
454
446
 
447
+ // readiness means the prompt channel is open and orphan handling is armed.
448
+ // callers may act on this event immediately, including deleting the session.
449
+ emit({
450
+ type: 'ready',
451
+ sessionId,
452
+ projectId,
453
+ provider,
454
+ cwd,
455
+ } as AgentEvent)
456
+
455
457
  return exitPromise
456
458
  }
457
459
 
package/detox/index.ts CHANGED
@@ -55,11 +55,45 @@ let _context: BrowserContext | null = null
55
55
  let _page: Page | null = null
56
56
  let _synchronizationEnabled = false
57
57
  let _suspendedAppId: string | null = null
58
+ let _browserCompromised: string | null = null
58
59
  let browserIdentity = 0
59
60
  let contextIdentity = 0
60
61
  let nextBrowserIdentity = 0
61
62
  let nextContextIdentity = 0
62
63
 
64
+ // maximum duration for browser/context lifecycle operations (closeContext,
65
+ // newContext, newPage). playwright does not bound context.close() or context
66
+ // creation; this bound converts an opaque 180s Jest hook timeout into a
67
+ // named failure that identifies which lifecycle step stalled.
68
+ const BROWSER_LIFECYCLE_TIMEOUT_MS = 30_000
69
+
70
+ async function withLifecycleTimeout<T>(
71
+ actionName: string,
72
+ targetContextId: number,
73
+ fn: () => Promise<T>,
74
+ timeoutMs = BROWSER_LIFECYCLE_TIMEOUT_MS,
75
+ ): Promise<T> {
76
+ const start = Date.now()
77
+ let timer: ReturnType<typeof setTimeout> | undefined
78
+ try {
79
+ return await Promise.race([
80
+ fn(),
81
+ new Promise<never>((_, reject) => {
82
+ timer = setTimeout(() => {
83
+ const elapsed = Date.now() - start
84
+ reject(
85
+ new Error(
86
+ `sootsim browser lifecycle error: ${actionName} did not settle after ${elapsed}ms (context=${targetContextId})`,
87
+ ),
88
+ )
89
+ }, timeoutMs)
90
+ }),
91
+ ])
92
+ } finally {
93
+ if (timer) clearTimeout(timer)
94
+ }
95
+ }
96
+
63
97
  const STATUS_BAR_OVERRIDE_EVENT = 'sootsim:statusBarOverride'
64
98
 
65
99
  type StatusBarConfig = {
@@ -75,6 +109,9 @@ type StatusBarConfig = {
75
109
  }
76
110
 
77
111
  function getPage(): Page {
112
+ if (_browserCompromised) {
113
+ throw new Error(`sootsim browser is compromised: ${_browserCompromised}`)
114
+ }
78
115
  if (!_page)
79
116
  throw new Error('sootsim driver not initialized -- call device.launchApp() first')
80
117
  return _page
@@ -280,13 +317,33 @@ async function waitForSootsimWorkletsIdle(page: Page, timeout = 3000): Promise<v
280
317
  }
281
318
  }
282
319
 
320
+ function reapOwnedBrowser(): void {
321
+ const reap = _reapBrowserNow
322
+ _reapBrowserNow = null
323
+ _browser = null
324
+ try {
325
+ reap?.()
326
+ } catch {}
327
+ }
328
+
283
329
  async function closeContext() {
330
+ if (_browserCompromised) {
331
+ throw new Error(`sootsim browser is compromised: ${_browserCompromised}`)
332
+ }
333
+ if (!_context) return
284
334
  const context = _context
285
- _context = null
286
- _page = null
287
- contextIdentity = 0
288
- _synchronizationEnabled = false
289
- if (context) await context.close()
335
+ const closingContextId = contextIdentity
336
+ try {
337
+ await withLifecycleTimeout('context.close()', closingContextId, () => context.close())
338
+ _context = null
339
+ _page = null
340
+ contextIdentity = 0
341
+ _synchronizationEnabled = false
342
+ } catch (error) {
343
+ _browserCompromised = error instanceof Error ? error.message : String(error)
344
+ reapOwnedBrowser()
345
+ throw error
346
+ }
290
347
  }
291
348
 
292
349
  async function closeBrowser() {
@@ -296,11 +353,25 @@ async function closeBrowser() {
296
353
  _browser = null
297
354
  _reapBrowserNow = null
298
355
  browserIdentity = 0
299
- await closeContext()
356
+
357
+ let closeError: Error | null = null
358
+ try {
359
+ await closeContext()
360
+ } catch (error) {
361
+ closeError = error instanceof Error ? error : new Error(String(error))
362
+ }
363
+
364
+ // reap Chrome directly without waiting on an unbounded browser.close()
300
365
  try {
301
- await browser.close()
302
- } finally {
303
366
  reapBrowserNow?.()
367
+ } catch {}
368
+
369
+ try {
370
+ await browser.close()
371
+ } catch {}
372
+
373
+ if (closeError) {
374
+ throw closeError
304
375
  }
305
376
  }
306
377
 
@@ -1299,6 +1370,9 @@ export const device = {
1299
1370
  // toggled on an existing context.
1300
1371
  recordVideoDir?: string
1301
1372
  }) {
1373
+ if (_browserCompromised) {
1374
+ throw new Error(`sootsim browser is compromised: ${_browserCompromised}`)
1375
+ }
1302
1376
  if (
1303
1377
  _page &&
1304
1378
  opts?.newInstance === false &&
@@ -1362,7 +1436,18 @@ export const device = {
1362
1436
  size: { width: 500, height: 900 },
1363
1437
  }
1364
1438
  }
1365
- _context = await _browser.newContext(contextOpts)
1439
+ const newContextIdentity = ++nextContextIdentity
1440
+ try {
1441
+ _context = await withLifecycleTimeout(
1442
+ '_browser.newContext()',
1443
+ newContextIdentity,
1444
+ () => _browser!.newContext(contextOpts),
1445
+ )
1446
+ } catch (error) {
1447
+ _browserCompromised = error instanceof Error ? error.message : String(error)
1448
+ reapOwnedBrowser()
1449
+ throw error
1450
+ }
1366
1451
  await _context.exposeBinding('__sootsimHostCapture', async (source, value) => {
1367
1452
  const request = readBrowserCompositeCaptureRequest(value)
1368
1453
  const session = await source.page.context().newCDPSession(source.page)
@@ -1381,8 +1466,16 @@ export const device = {
1381
1466
  await session.detach()
1382
1467
  }
1383
1468
  })
1384
- _page = await _context.newPage()
1385
- contextIdentity = ++nextContextIdentity
1469
+ try {
1470
+ _page = await withLifecycleTimeout('_context.newPage()', newContextIdentity, () =>
1471
+ _context!.newPage(),
1472
+ )
1473
+ } catch (error) {
1474
+ _browserCompromised = error instanceof Error ? error.message : String(error)
1475
+ reapOwnedBrowser()
1476
+ throw error
1477
+ }
1478
+ contextIdentity = newContextIdentity
1386
1479
  }
1387
1480
 
1388
1481
  const url = opts?.url || BASE_URL
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_DEFAULT_MS = 500;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1881,12 +1881,38 @@ var _context = null;
1881
1881
  var _page = null;
1882
1882
  var _synchronizationEnabled = false;
1883
1883
  var _suspendedAppId = null;
1884
+ var _browserCompromised = null;
1884
1885
  var browserIdentity = 0;
1885
1886
  var contextIdentity = 0;
1886
1887
  var nextBrowserIdentity = 0;
1887
1888
  var nextContextIdentity = 0;
1889
+ var BROWSER_LIFECYCLE_TIMEOUT_MS = 3e4;
1890
+ async function withLifecycleTimeout(actionName, targetContextId, fn, timeoutMs = BROWSER_LIFECYCLE_TIMEOUT_MS) {
1891
+ const start = Date.now();
1892
+ let timer;
1893
+ try {
1894
+ return await Promise.race([
1895
+ fn(),
1896
+ new Promise((_, reject) => {
1897
+ timer = setTimeout(() => {
1898
+ const elapsed = Date.now() - start;
1899
+ reject(
1900
+ new Error(
1901
+ `sootsim browser lifecycle error: ${actionName} did not settle after ${elapsed}ms (context=${targetContextId})`
1902
+ )
1903
+ );
1904
+ }, timeoutMs);
1905
+ })
1906
+ ]);
1907
+ } finally {
1908
+ if (timer) clearTimeout(timer);
1909
+ }
1910
+ }
1888
1911
  var STATUS_BAR_OVERRIDE_EVENT = "sootsim:statusBarOverride";
1889
1912
  function getPage() {
1913
+ if (_browserCompromised) {
1914
+ throw new Error(`sootsim browser is compromised: ${_browserCompromised}`);
1915
+ }
1890
1916
  if (!_page)
1891
1917
  throw new Error("sootsim driver not initialized -- call device.launchApp() first");
1892
1918
  return _page;
@@ -2052,13 +2078,33 @@ async function waitForSootsimWorkletsIdle(page, timeout = 3e3) {
2052
2078
  );
2053
2079
  }
2054
2080
  }
2081
+ function reapOwnedBrowser() {
2082
+ const reap = _reapBrowserNow;
2083
+ _reapBrowserNow = null;
2084
+ _browser = null;
2085
+ try {
2086
+ reap?.();
2087
+ } catch {
2088
+ }
2089
+ }
2055
2090
  async function closeContext() {
2091
+ if (_browserCompromised) {
2092
+ throw new Error(`sootsim browser is compromised: ${_browserCompromised}`);
2093
+ }
2094
+ if (!_context) return;
2056
2095
  const context = _context;
2057
- _context = null;
2058
- _page = null;
2059
- contextIdentity = 0;
2060
- _synchronizationEnabled = false;
2061
- if (context) await context.close();
2096
+ const closingContextId = contextIdentity;
2097
+ try {
2098
+ await withLifecycleTimeout("context.close()", closingContextId, () => context.close());
2099
+ _context = null;
2100
+ _page = null;
2101
+ contextIdentity = 0;
2102
+ _synchronizationEnabled = false;
2103
+ } catch (error) {
2104
+ _browserCompromised = error instanceof Error ? error.message : String(error);
2105
+ reapOwnedBrowser();
2106
+ throw error;
2107
+ }
2062
2108
  }
2063
2109
  async function closeBrowser() {
2064
2110
  if (!_browser) return;
@@ -2067,11 +2113,22 @@ async function closeBrowser() {
2067
2113
  _browser = null;
2068
2114
  _reapBrowserNow = null;
2069
2115
  browserIdentity = 0;
2070
- await closeContext();
2116
+ let closeError = null;
2117
+ try {
2118
+ await closeContext();
2119
+ } catch (error) {
2120
+ closeError = error instanceof Error ? error : new Error(String(error));
2121
+ }
2071
2122
  try {
2072
- await browser.close();
2073
- } finally {
2074
2123
  reapBrowserNow?.();
2124
+ } catch {
2125
+ }
2126
+ try {
2127
+ await browser.close();
2128
+ } catch {
2129
+ }
2130
+ if (closeError) {
2131
+ throw closeError;
2075
2132
  }
2076
2133
  }
2077
2134
  async function waitForSootsimIdle(page, maxMs = 3e3, strict = false) {
@@ -2798,6 +2855,9 @@ var device = {
2798
2855
  _currentUrl: "",
2799
2856
  _platform: DETOX_PLATFORM,
2800
2857
  async launchApp(opts) {
2858
+ if (_browserCompromised) {
2859
+ throw new Error(`sootsim browser is compromised: ${_browserCompromised}`);
2860
+ }
2801
2861
  if (_page && opts?.newInstance === false && !opts.delete && !opts.recordVideoDir && _suspendedAppId) {
2802
2862
  const page = _page;
2803
2863
  const appId = _suspendedAppId;
@@ -2842,7 +2902,18 @@ var device = {
2842
2902
  size: { width: 500, height: 900 }
2843
2903
  };
2844
2904
  }
2845
- _context = await _browser.newContext(contextOpts);
2905
+ const newContextIdentity = ++nextContextIdentity;
2906
+ try {
2907
+ _context = await withLifecycleTimeout(
2908
+ "_browser.newContext()",
2909
+ newContextIdentity,
2910
+ () => _browser.newContext(contextOpts)
2911
+ );
2912
+ } catch (error) {
2913
+ _browserCompromised = error instanceof Error ? error.message : String(error);
2914
+ reapOwnedBrowser();
2915
+ throw error;
2916
+ }
2846
2917
  await _context.exposeBinding("__sootsimHostCapture", async (source, value) => {
2847
2918
  const request = readBrowserCompositeCaptureRequest(value);
2848
2919
  const session = await source.page.context().newCDPSession(source.page);
@@ -2861,8 +2932,18 @@ var device = {
2861
2932
  await session.detach();
2862
2933
  }
2863
2934
  });
2864
- _page = await _context.newPage();
2865
- contextIdentity = ++nextContextIdentity;
2935
+ try {
2936
+ _page = await withLifecycleTimeout(
2937
+ "_context.newPage()",
2938
+ newContextIdentity,
2939
+ () => _context.newPage()
2940
+ );
2941
+ } catch (error) {
2942
+ _browserCompromised = error instanceof Error ? error.message : String(error);
2943
+ reapOwnedBrowser();
2944
+ throw error;
2945
+ }
2946
+ contextIdentity = newContextIdentity;
2866
2947
  }
2867
2948
  const url = opts?.url || BASE_URL;
2868
2949
  device._currentUrl = url;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/menu.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/menu.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "rnx";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-fingerprint-registry.ts
4
4
  var RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.485 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.487 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.485",
3
+ "version": "0.1.487",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for rnx.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",