rnxsim 0.1.365 → 0.1.367
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/cli/bin.ts +18 -0
- package/cli/bridge-flow-runner.ts +16 -153
- package/cli/commands/assert.ts +1 -1
- package/cli/commands/box/checkout-plane.ts +126 -0
- package/cli/commands/box/rnx-command.ts +68 -0
- package/cli/commands/box.ts +200 -0
- package/cli/commands/control.ts +15 -76
- package/cli/commands/detox.ts +18 -1
- package/cli/commands/do-chain.ts +412 -0
- package/cli/commands/flow.ts +2 -11
- package/cli/commands/inspect/core.ts +302 -725
- package/cli/commands/inspect/describe.ts +3 -76
- package/cli/commands/inspect/find.ts +3 -6
- package/cli/commands/inspect/get-layout.ts +14 -1
- package/cli/commands/inspect/resolve-target.ts +41 -47
- package/cli/commands/inspect/shared.ts +28 -123
- package/cli/commands/inspect/tree.ts +6 -15
- package/cli/commands/inspect/wait-ready.ts +2 -2
- package/cli/commands/inspect/wait-selector.ts +4 -8
- package/cli/commands/inspect.ts +23 -17
- package/cli/commands/install-desktop.ts +44 -7
- package/cli/commands/maestro-generate.ts +0 -2
- package/cli/commands/platform.ts +68 -0
- package/cli/commands/state.ts +5 -2
- package/cli/outbound-endpoints.ts +6 -1
- package/cli/parse-args.ts +13 -2
- package/cli/ws-bridge.ts +30 -2
- package/detox/index.ts +37 -18
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-BVMNQFKF.js → agent-EKKIAKP5.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-B6YFXGC3.js → agent-wrapper-MHLQUGA6.js} +2 -2
- package/dist-cli/chunks/{app-fonts-MEI6R6XR.js → app-fonts-HN6ADRTQ.js} +2 -2
- package/dist-cli/chunks/{assert-JGHI53HV.js → assert-IMR6QCN6.js} +3 -3
- package/dist-cli/chunks/{auth-STEOXUS7.js → auth-27LPMQNH.js} +2 -2
- package/dist-cli/chunks/{beta-HT3FLS5T.js → beta-6RXBB5AI.js} +2 -2
- package/dist-cli/chunks/box-DORLF3GP.js +1709 -0
- package/dist-cli/chunks/{camera-ZCLFSLON.js → camera-2G7JZ5DL.js} +2 -2
- package/dist-cli/chunks/{chunk-RI3NS77J.js → chunk-3QZJLNYY.js} +1 -1
- package/dist-cli/chunks/{chunk-FHWZPUGC.js → chunk-3VBVEDDA.js} +1 -1
- package/dist-cli/chunks/{chunk-EAFKG5R3.js → chunk-4BWGLTKU.js} +2 -2
- package/dist-cli/chunks/chunk-4XSNO374.js +423 -0
- package/dist-cli/chunks/{chunk-GZEUDDAW.js → chunk-5DGMFUZG.js} +2 -2
- package/dist-cli/chunks/{chunk-TKCGP3DD.js → chunk-6DBS5EGX.js} +2 -2
- package/dist-cli/chunks/{chunk-HIDS3PYC.js → chunk-6SO6I3D5.js} +2 -2
- package/dist-cli/chunks/chunk-75EFOPXE.js +32 -0
- package/dist-cli/chunks/{chunk-FIXRGPUT.js → chunk-A5AJFVOF.js} +1 -1
- package/dist-cli/chunks/{chunk-2SFMW5K6.js → chunk-AM2ODYAN.js} +1 -1
- package/dist-cli/chunks/{chunk-BGRGP3QR.js → chunk-AVOROGA3.js} +1 -1
- package/dist-cli/chunks/chunk-AXMMLO7D.js +130 -0
- package/dist-cli/chunks/{chunk-XXNPISER.js → chunk-BSEXEYNX.js} +2 -2
- package/dist-cli/chunks/{chunk-67ATAITF.js → chunk-CM6ZKZW7.js} +2 -2
- package/dist-cli/chunks/{chunk-MR3YPNUI.js → chunk-DNVABCEC.js} +2 -2
- package/dist-cli/chunks/{chunk-5AS7S6HY.js → chunk-E33A4AIR.js} +2 -2
- package/dist-cli/chunks/{chunk-DBJZUCFP.js → chunk-EFMOXYDD.js} +2 -2
- package/dist-cli/chunks/{chunk-ZTWUNK45.js → chunk-EV4P5UBP.js} +2 -2
- package/dist-cli/chunks/{chunk-EVBQDQVY.js → chunk-G5IUIGGC.js} +1 -1
- package/dist-cli/chunks/chunk-GMLOCV3E.js +312 -0
- package/dist-cli/chunks/{chunk-DQFOHIRF.js → chunk-GRN2FHVW.js} +1 -1
- package/dist-cli/chunks/{chunk-CYIE65QN.js → chunk-HFFXPUEP.js} +1 -1
- package/dist-cli/chunks/chunk-HG6T4OOR.js +4 -0
- package/dist-cli/chunks/{chunk-GK7PGYFH.js → chunk-HNT2OXPZ.js} +1 -1
- package/dist-cli/chunks/chunk-IPEURNLI.js +24 -0
- package/dist-cli/chunks/chunk-IR44SFBA.js +5 -0
- package/dist-cli/chunks/chunk-JMSLXZFW.js +4 -0
- package/dist-cli/chunks/{chunk-WGNDJARS.js → chunk-JPXQKLNH.js} +1 -1
- package/dist-cli/chunks/chunk-K3EC6JDE.js +4 -0
- package/dist-cli/chunks/chunk-KHX65HAU.js +4 -0
- package/dist-cli/chunks/{chunk-MACI34ST.js → chunk-LWOVKHRC.js} +2 -2
- package/dist-cli/chunks/{chunk-QIQL7Y5V.js → chunk-MQN5DWTI.js} +2 -2
- package/dist-cli/chunks/{chunk-5VHWQGGF.js → chunk-N3BXQEUF.js} +1 -1
- package/dist-cli/chunks/{chunk-O2ORLK6W.js → chunk-N5OSV26B.js} +2 -2
- package/dist-cli/chunks/chunk-PHNURIH3.js +4 -0
- package/dist-cli/chunks/{chunk-JRPU5TFI.js → chunk-PP2KNVXP.js} +3 -3
- package/dist-cli/chunks/{chunk-UR345KM3.js → chunk-PROKNJVY.js} +2 -2
- package/dist-cli/chunks/chunk-QXLLY4IM.js +7 -0
- package/dist-cli/chunks/{chunk-2CXHDTQ5.js → chunk-RNQTOGM7.js} +1 -1
- package/dist-cli/chunks/{chunk-M5KJCLUW.js → chunk-RPNKKVBN.js} +27 -27
- package/dist-cli/chunks/{chunk-EFXNSJ55.js → chunk-RSNLI2NH.js} +2 -2
- package/dist-cli/chunks/{chunk-25BTVHK2.js → chunk-RZGHV2WI.js} +2 -2
- package/dist-cli/chunks/chunk-SGGL3AFV.js +497 -0
- package/dist-cli/chunks/chunk-SH5ETJKG.js +4 -0
- package/dist-cli/chunks/{chunk-MRNW4GVL.js → chunk-T6J4YP56.js} +2 -2
- package/dist-cli/chunks/{chunk-R4FQZXJC.js → chunk-TWUE7WF5.js} +2 -2
- package/dist-cli/chunks/{chunk-X5ZOZVHC.js → chunk-U44VEQRN.js} +1 -1
- package/dist-cli/chunks/{chunk-XRO5WQXP.js → chunk-URLVQHC3.js} +1 -1
- package/dist-cli/chunks/{chunk-JAFF4RAU.js → chunk-VANZFTUE.js} +1 -1
- package/dist-cli/chunks/{chunk-6BAF6GFS.js → chunk-VB2YBH46.js} +1 -1
- package/dist-cli/chunks/{chunk-O6P4N2JD.js → chunk-VFU2SJ7M.js} +2 -2
- package/dist-cli/chunks/{chunk-XPOTXF5Q.js → chunk-VUBJ6FXU.js} +15 -15
- package/dist-cli/chunks/{chunk-XR4KID25.js → chunk-W5PATILQ.js} +2 -2
- package/dist-cli/chunks/chunk-WI5V4TYG.js +38 -0
- package/dist-cli/chunks/{chunk-NEH4T67X.js → chunk-XTRHQAOV.js} +2 -2
- package/dist-cli/chunks/chunk-XWUTJLBM.js +27 -0
- package/dist-cli/chunks/{chunk-TULWPOAY.js → chunk-XYRUQQUR.js} +2 -2
- package/dist-cli/chunks/chunk-YBFB3RM7.js +4 -0
- package/dist-cli/chunks/chunk-YGQVQ2VG.js +4 -0
- package/dist-cli/chunks/{chunk-J66US2OZ.js → chunk-YINACV32.js} +1 -1
- package/dist-cli/chunks/chunk-YV7ERO2V.js +5 -0
- package/dist-cli/chunks/{cleanup-G4TEYVKY.js → cleanup-GVFHQ3KH.js} +2 -2
- package/dist-cli/chunks/cli-version-DPX5MA2M.js +4 -0
- package/dist-cli/chunks/{compat-EZ5NP32J.js → compat-AYRTXYAM.js} +2 -2
- package/dist-cli/chunks/{config-27M2DGCS.js → config-K7LOOV62.js} +2 -2
- package/dist-cli/chunks/connect-H3CNY4IO.js +4 -0
- package/dist-cli/chunks/control-SMHZ2CF5.js +4 -0
- package/dist-cli/chunks/daemon-TEZUNI73.js +4 -0
- package/dist-cli/chunks/{debug-EXU3D7PC.js → debug-ELGHG57T.js} +3 -3
- package/dist-cli/chunks/{desktop-SHHPZAWQ.js → desktop-4G7FK3MP.js} +3 -3
- package/dist-cli/chunks/detox-JKXGEJIZ.js +52 -0
- package/dist-cli/chunks/{device-4NI26HG6.js → device-IV3AR6KG.js} +2 -2
- package/dist-cli/chunks/{diagnose-P4SFXH6J.js → diagnose-3ERGF7EW.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-BUAKWYMY.js → disk-cleanup-ALFEVZ4B.js} +2 -2
- package/dist-cli/chunks/do-chain-K2B4OHM7.js +5 -0
- package/dist-cli/chunks/drivers-KJYXA3M3.js +4 -0
- package/dist-cli/chunks/env-2KF6IYZE.js +4 -0
- package/dist-cli/chunks/{film-Y2BAQINB.js → film-UQXJFAD5.js} +3 -3
- package/dist-cli/chunks/flow-ASTUH56E.js +4 -0
- package/dist-cli/chunks/help-SNNYFELA.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-U2MAY2XV.js → hidden-runtime-alias-VJCWCFVO.js} +2 -2
- package/dist-cli/chunks/{home-paths-PAJMZCOS.js → home-paths-EGUZZ6J6.js} +2 -2
- package/dist-cli/chunks/inspect-XANAADQT.js +4 -0
- package/dist-cli/chunks/install-desktop-JKQA7UY6.js +4 -0
- package/dist-cli/chunks/{login-D53XKBEO.js → login-6KQGD7HK.js} +2 -2
- package/dist-cli/chunks/{logout-HZQKLNUJ.js → logout-2FCOVLBC.js} +2 -2
- package/dist-cli/chunks/{maestro-XSS2KX6L.js → maestro-HPSSEVJD.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-DNDQX3JQ.js → maestro-generate-KQQ6JHMR.js} +5 -5
- package/dist-cli/chunks/{mode-LEVGOKI3.js → mode-SH7KRZET.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-2XZIJNDG.js → optional-demo-registry-NAMCAVFX.js} +2 -2
- package/dist-cli/chunks/{perf-OKMAXDLB.js → perf-LWKAHXUL.js} +2 -2
- package/dist-cli/chunks/{permissions-VG5TBUTN.js → permissions-EZTKWTXV.js} +2 -2
- package/dist-cli/chunks/platform-KSOJIVN5.js +6 -0
- package/dist-cli/chunks/privacy-EJULWP7L.js +4 -0
- package/dist-cli/chunks/{record-BQYGZOMV.js → record-2IC7BAQN.js} +3 -3
- package/dist-cli/chunks/{report-issue-HCPZESWE.js → report-issue-MMX6HOQO.js} +2 -2
- package/dist-cli/chunks/reset-PKFZA4NC.js +4 -0
- package/dist-cli/chunks/resolve-target-AFKU3BRE.js +4 -0
- package/dist-cli/chunks/runtime-XHWWPOIN.js +4 -0
- package/dist-cli/chunks/{screenshot-command-DWEYPJE7.js → screenshot-command-JYUXDVSA.js} +3 -3
- package/dist-cli/chunks/{screenshot-layers-5GMBXLO7.js → screenshot-layers-OGRY6AA3.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-5KCI7IZD.js → screenshots-capture-QHDN65XS.js} +2 -2
- package/dist-cli/chunks/{serve-QNKTA2HR.js → serve-W4BKAG4J.js} +3 -3
- package/dist-cli/chunks/setup-WJPMPSAC.js +4 -0
- package/dist-cli/chunks/sim-client-UOQGFBPO.js +4 -0
- package/dist-cli/chunks/{skills-DOEALD3X.js → skills-OPPXOD63.js} +2 -2
- package/dist-cli/chunks/state-TDAN7BOM.js +14 -0
- package/dist-cli/chunks/{storage-E7WUWN3E.js → storage-CFB2YGLY.js} +2 -2
- package/dist-cli/chunks/store-4TEED4ZU.js +4 -0
- package/dist-cli/chunks/telemetry-S6N7CV6G.js +4 -0
- package/dist-cli/chunks/{timeline-IKNUGQ2A.js → timeline-ASOOVP4C.js} +2 -2
- package/dist-cli/chunks/{upgrade-VS3OKXE2.js → upgrade-6MVJISHG.js} +2 -2
- package/dist-cli/chunks/upload-CBNIRFEW.js +4 -0
- package/dist-cli/chunks/{version-F4XHNTBZ.js → version-5GS7CWRL.js} +2 -2
- package/dist-cli/chunks/{web-F72724QL.js → web-QRRMYMV4.js} +2 -2
- package/dist-cli/chunks/welcome-33FXMAMB.js +5 -0
- package/dist-cli/chunks/{what-happened-APK7YKOV.js → what-happened-GAZJGKXX.js} +2 -2
- package/dist-cli/chunks/ws-bridge-DIXUAPLQ.js +4 -0
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +336 -0
- package/dist-lib/bridge-contract-input.mjs +303 -0
- package/dist-lib/bridge-contract.cjs +29 -1
- package/dist-lib/bridge-contract.mjs +19 -0
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +35 -19
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +5 -1
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +244 -594
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +303 -657
- package/dist-lib/sdk.mjs +301 -652
- package/dist-lib/skills.cjs +256 -339
- package/dist-lib/vite.cjs +1 -1
- package/package.json +10 -1
- package/skills/contrast/SKILL.md +3 -0
- package/skills/rnx-debug/SKILL.md +8 -0
- package/skills/rnx-test/SKILL.md +21 -0
- package/src/app-url.ts +40 -0
- package/src/bridge-contract-input.ts +359 -0
- package/src/bridge-contract.ts +121 -1
- package/src/host/bridge-host.ts +7 -12
- package/src/index.ts +7 -0
- package/src/sim-client.ts +24 -9
- package/dist-cli/chunks/chunk-2JFZ5Z7Q.js +0 -4
- package/dist-cli/chunks/chunk-4WFN4DFR.js +0 -5
- package/dist-cli/chunks/chunk-52ES4API.js +0 -38
- package/dist-cli/chunks/chunk-622E4JET.js +0 -767
- package/dist-cli/chunks/chunk-EFL2ASZO.js +0 -124
- package/dist-cli/chunks/chunk-IWPS3EKJ.js +0 -15
- package/dist-cli/chunks/chunk-MCHKBFUL.js +0 -4
- package/dist-cli/chunks/chunk-OSZ5HZSI.js +0 -24
- package/dist-cli/chunks/chunk-W3UIDI3W.js +0 -5
- package/dist-cli/chunks/chunk-XKRUNS7A.js +0 -32
- package/dist-cli/chunks/chunk-YE3M3YD4.js +0 -944
- package/dist-cli/chunks/chunk-ZCP4CRP6.js +0 -4
- package/dist-cli/chunks/chunk-ZGD7GZRI.js +0 -4
- package/dist-cli/chunks/chunk-ZGH5U4AJ.js +0 -27
- package/dist-cli/chunks/cli-version-ZM3PVKQ5.js +0 -4
- package/dist-cli/chunks/control-4QR43FXV.js +0 -4
- package/dist-cli/chunks/daemon-2U4CJ6AT.js +0 -4
- package/dist-cli/chunks/detox-RQ6FFSBS.js +0 -52
- package/dist-cli/chunks/drivers-OVCUPQTM.js +0 -4
- package/dist-cli/chunks/flow-ELTLKKZ3.js +0 -4
- package/dist-cli/chunks/help-CDEZAG2L.js +0 -4
- package/dist-cli/chunks/inspect-VVQRPJLS.js +0 -4
- package/dist-cli/chunks/install-desktop-YXSRKR35.js +0 -4
- package/dist-cli/chunks/privacy-MNRHREME.js +0 -4
- package/dist-cli/chunks/reset-R4E4W4YI.js +0 -4
- package/dist-cli/chunks/runtime-XRQZ7W34.js +0 -4
- package/dist-cli/chunks/setup-RNMM5GO5.js +0 -4
- package/dist-cli/chunks/state-3HH2IHIF.js +0 -14
- package/dist-cli/chunks/store-HUPZUCFG.js +0 -4
- package/dist-cli/chunks/telemetry-IJ53XR2Y.js +0 -4
- package/dist-cli/chunks/upload-A57NAAHF.js +0 -4
- package/dist-cli/chunks/welcome-B72RRMBW.js +0 -5
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.367 | (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;
|
|
@@ -1175,8 +1175,18 @@ var REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE, REACT_NATIVE_ROOT_EXPORT_STR
|
|
|
1175
1175
|
var init_react_native_root_export_coverage = __esm({
|
|
1176
1176
|
"../compat/src/generated/react-native-root-export-coverage.ts"() {
|
|
1177
1177
|
"use strict";
|
|
1178
|
-
REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE = 0.
|
|
1179
|
-
REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE = 0.
|
|
1178
|
+
REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE = 0.99;
|
|
1179
|
+
REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE = 0.765;
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1183
|
+
// ../compat/src/generated/react-native-webview-coverage.ts
|
|
1184
|
+
var REACT_NATIVE_WEBVIEW_WILL_IT_WORK_COVERAGE, REACT_NATIVE_WEBVIEW_STRICT_COVERAGE;
|
|
1185
|
+
var init_react_native_webview_coverage = __esm({
|
|
1186
|
+
"../compat/src/generated/react-native-webview-coverage.ts"() {
|
|
1187
|
+
"use strict";
|
|
1188
|
+
REACT_NATIVE_WEBVIEW_WILL_IT_WORK_COVERAGE = 0.74;
|
|
1189
|
+
REACT_NATIVE_WEBVIEW_STRICT_COVERAGE = 0.223;
|
|
1180
1190
|
}
|
|
1181
1191
|
});
|
|
1182
1192
|
|
|
@@ -1220,6 +1230,7 @@ var init_registry = __esm({
|
|
|
1220
1230
|
"use strict";
|
|
1221
1231
|
init_capability_inventory_coverage();
|
|
1222
1232
|
init_react_native_root_export_coverage();
|
|
1233
|
+
init_react_native_webview_coverage();
|
|
1223
1234
|
init_unsupported_packages();
|
|
1224
1235
|
COMPAT_CATEGORIES = [
|
|
1225
1236
|
"All",
|
|
@@ -1371,10 +1382,11 @@ var init_registry = __esm({
|
|
|
1371
1382
|
versions: [
|
|
1372
1383
|
{
|
|
1373
1384
|
range: ">=11.0.0",
|
|
1374
|
-
coverage:
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1385
|
+
coverage: REACT_NATIVE_WEBVIEW_WILL_IT_WORK_COVERAGE,
|
|
1386
|
+
strictCoverage: REACT_NATIVE_WEBVIEW_STRICT_COVERAGE,
|
|
1387
|
+
note: "native-seam only: the published package runs unchanged and routes RNCWebView through the tenant-to-shell hosted iframe surface. coverage is generated from app-source use in six pinned applications; equal-surface strict coverage includes the shared, iOS, and Android public prop and ref surface. paired native and SootSim runtime conformance covers local HTML, base URL, URI loading, load and navigation callbacks, both injection phases, two-way messaging, imperative URI reload and injection, content scrolling, parent translation, and onOpenWindow target delivery.",
|
|
1388
|
+
working: "source.uri/source.html/source.baseUrl, Chromium cross-origin URI loading under the shell COEP, same-origin URI cookies, source.html persistent localStorage, document-start ReactNativeWebView bootstrap and injectedJavaScriptBeforeContentLoaded/injectedJavaScript on source.html, strict ReactNativeWebView.postMessage bridge envelope in both directions, onMessage synthetic event with navigation fields, onOpenWindow target delivery for source.html, successful onLoad/Start/End and onNavigationStateChange, ref.reload on URI pages, ref.injectJavaScript/postMessage, internal content scrolling, renderLoading, javaScriptEnabled sandbox, layout, inherited clipping and visibility, parked/live presentation",
|
|
1389
|
+
missing: "Safari/WebKit cross-origin URI pages without COEP-compatible response headers remain permanently loading because WebKit ignores iframe credentialless; Chromium credentialless cross-origin URI frames send no credentials, including cookies set by their own origin, and use ephemeral storage; iframe pixels in canvas screenshots; script injection, ReactNativeWebView bootstrap, and onOpenWindow for remote pages, which get no bridge at all because a browser cannot script a cross-origin frame; cross-origin ref.goBack/goForward/stopLoading and truthful canGoBack/canGoForward values; failed HTTP/refused navigation callbacks (onError/onHttpError and renderError); onShouldStartLoadWithRequest, allowsBackForwardNavigationGestures, userAgent, dataDetectorTypes, cacheEnabled, incognito, scalesPageToFit, originWhitelist enforcement"
|
|
1378
1390
|
}
|
|
1379
1391
|
]
|
|
1380
1392
|
},
|
|
@@ -20244,6 +20256,10 @@ var init_bridge_host = __esm({
|
|
|
20244
20256
|
return msg?.action === "type" ? "typed text" : "used keyboard";
|
|
20245
20257
|
case "tree":
|
|
20246
20258
|
return "dumped tree";
|
|
20259
|
+
case "query":
|
|
20260
|
+
return "queried semantic tree";
|
|
20261
|
+
case "resolve":
|
|
20262
|
+
return "resolved semantic selector";
|
|
20247
20263
|
case "focus":
|
|
20248
20264
|
return "focused sim";
|
|
20249
20265
|
case "close":
|
|
@@ -20692,7 +20708,9 @@ var init_current_sim = __esm({
|
|
|
20692
20708
|
var ws_bridge_exports = {};
|
|
20693
20709
|
__export(ws_bridge_exports, {
|
|
20694
20710
|
BridgeSimLockedError: () => BridgeSimLockedError,
|
|
20711
|
+
RNX_PLACEMENT_ENV: () => RNX_PLACEMENT_ENV,
|
|
20695
20712
|
bridgePortForShellBaseUrl: () => bridgePortForShellBaseUrl,
|
|
20713
|
+
bridgeWsUrl: () => bridgeWsUrl,
|
|
20696
20714
|
callInBridge: () => callInBridge,
|
|
20697
20715
|
callInBridgeWrite: () => callInBridgeWrite,
|
|
20698
20716
|
checkSimHealth: () => checkSimHealth,
|
|
@@ -20703,8 +20721,15 @@ __export(ws_bridge_exports, {
|
|
|
20703
20721
|
printBridgeWorldNotice: () => printBridgeWorldNotice,
|
|
20704
20722
|
resolveBridgeWorld: () => resolveBridgeWorld,
|
|
20705
20723
|
resolveDefaultBridgePort: () => resolveDefaultBridgePort,
|
|
20724
|
+
resolvePlacement: () => resolvePlacement,
|
|
20706
20725
|
worldForBridgePort: () => worldForBridgePort
|
|
20707
20726
|
});
|
|
20727
|
+
function resolvePlacement() {
|
|
20728
|
+
return process.env[RNX_PLACEMENT_ENV] === "local-box" ? "local-box" : "host";
|
|
20729
|
+
}
|
|
20730
|
+
function bridgeWsUrl(wsPort) {
|
|
20731
|
+
return `ws://localhost:${wsPort}`;
|
|
20732
|
+
}
|
|
20708
20733
|
function liveDevBridgeLockfiles() {
|
|
20709
20734
|
return readDevBridgeLockfiles().filter((lockfile) => isDevBridgeLockfileFresh(lockfile));
|
|
20710
20735
|
}
|
|
@@ -20925,7 +20950,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
20925
20950
|
let nextId = 1;
|
|
20926
20951
|
const commandTimeoutMs = opts.commandTimeoutMs ?? 15e3;
|
|
20927
20952
|
const pending = /* @__PURE__ */ new Map();
|
|
20928
|
-
const ws = new import_ws3.WebSocket(
|
|
20953
|
+
const ws = new import_ws3.WebSocket(bridgeWsUrl(wsPort));
|
|
20929
20954
|
const identity = getCliIdentity();
|
|
20930
20955
|
const ready = new Promise((resolve7, reject) => {
|
|
20931
20956
|
ws.on("open", () => {
|
|
@@ -20945,7 +20970,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
20945
20970
|
});
|
|
20946
20971
|
ws.on("error", (err) => {
|
|
20947
20972
|
const cause = err.message ? `: ${err.message}` : "";
|
|
20948
|
-
reject(new Error(`could not connect to
|
|
20973
|
+
reject(new Error(`could not connect to ${bridgeWsUrl(wsPort)}${cause}`));
|
|
20949
20974
|
});
|
|
20950
20975
|
});
|
|
20951
20976
|
ready.catch(() => {
|
|
@@ -21148,7 +21173,7 @@ async function callInBridge(bridge, path18, ...args) {
|
|
|
21148
21173
|
async function callInBridgeWrite(bridge, path18, ...args) {
|
|
21149
21174
|
return bridge.send({ type: "call", path: path18, args, acquireLock: true });
|
|
21150
21175
|
}
|
|
21151
|
-
var import_node_fs9, import_node_path11, import_ws3, resolvedWorld, BridgeSimLockedError;
|
|
21176
|
+
var import_node_fs9, import_node_path11, import_ws3, RNX_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError;
|
|
21152
21177
|
var init_ws_bridge = __esm({
|
|
21153
21178
|
"cli/ws-bridge.ts"() {
|
|
21154
21179
|
"use strict";
|
|
@@ -21159,6 +21184,7 @@ var init_ws_bridge = __esm({
|
|
|
21159
21184
|
init_cli_constants();
|
|
21160
21185
|
init_home_paths();
|
|
21161
21186
|
init_current_sim();
|
|
21187
|
+
RNX_PLACEMENT_ENV = "RNX_PLACEMENT";
|
|
21162
21188
|
resolvedWorld = null;
|
|
21163
21189
|
BridgeSimLockedError = class extends Error {
|
|
21164
21190
|
lock;
|
|
@@ -21171,6 +21197,45 @@ var init_ws_bridge = __esm({
|
|
|
21171
21197
|
}
|
|
21172
21198
|
});
|
|
21173
21199
|
|
|
21200
|
+
// src/app-url.ts
|
|
21201
|
+
function normalizeAppUrlTarget(target) {
|
|
21202
|
+
const trimmed = target.trim();
|
|
21203
|
+
if (!trimmed) {
|
|
21204
|
+
throw new Error("expected <url-or-route>");
|
|
21205
|
+
}
|
|
21206
|
+
if (APP_URL_SCHEME_RE.test(trimmed) || trimmed.startsWith("/")) {
|
|
21207
|
+
return trimmed;
|
|
21208
|
+
}
|
|
21209
|
+
return `/${trimmed}`;
|
|
21210
|
+
}
|
|
21211
|
+
function isAppDeepLinkTarget(target) {
|
|
21212
|
+
const trimmed = target.trim();
|
|
21213
|
+
if (!trimmed) return false;
|
|
21214
|
+
if (trimmed.startsWith("/")) return true;
|
|
21215
|
+
if (!APP_URL_SCHEME_RE.test(trimmed)) return false;
|
|
21216
|
+
return !/^https?:\/\//i.test(trimmed);
|
|
21217
|
+
}
|
|
21218
|
+
async function openAppUrl(bridge, target) {
|
|
21219
|
+
const normalized = normalizeAppUrlTarget(target);
|
|
21220
|
+
const result = await bridge.send({
|
|
21221
|
+
type: "call",
|
|
21222
|
+
path: "SootSim.bridges.test.openDeepLink",
|
|
21223
|
+
args: [normalized]
|
|
21224
|
+
});
|
|
21225
|
+
if (result !== null && typeof result === "object" && Reflect.get(result, "ok") === false) {
|
|
21226
|
+
const error = Reflect.get(result, "error");
|
|
21227
|
+
throw new Error(typeof error === "string" ? error : "deep-link dispatch failed");
|
|
21228
|
+
}
|
|
21229
|
+
return normalized;
|
|
21230
|
+
}
|
|
21231
|
+
var APP_URL_SCHEME_RE;
|
|
21232
|
+
var init_app_url = __esm({
|
|
21233
|
+
"src/app-url.ts"() {
|
|
21234
|
+
"use strict";
|
|
21235
|
+
APP_URL_SCHEME_RE = /^[A-Za-z][A-Za-z0-9+.-]*:/;
|
|
21236
|
+
}
|
|
21237
|
+
});
|
|
21238
|
+
|
|
21174
21239
|
// src/dev-bundle-resolution.ts
|
|
21175
21240
|
function buildUnresolvedTargetError(targetLabel) {
|
|
21176
21241
|
return new Error(
|
|
@@ -21839,7 +21904,107 @@ var init_app_splash = __esm({
|
|
|
21839
21904
|
}
|
|
21840
21905
|
});
|
|
21841
21906
|
|
|
21907
|
+
// src/bridge-contract.ts
|
|
21908
|
+
var init_bridge_contract = __esm({
|
|
21909
|
+
"src/bridge-contract.ts"() {
|
|
21910
|
+
"use strict";
|
|
21911
|
+
}
|
|
21912
|
+
});
|
|
21913
|
+
|
|
21842
21914
|
// cli/commands/inspect/core.ts
|
|
21915
|
+
function isSemanticGeometry(value) {
|
|
21916
|
+
return value !== null && typeof value === "object" && [
|
|
21917
|
+
Reflect.get(value, "x"),
|
|
21918
|
+
Reflect.get(value, "y"),
|
|
21919
|
+
Reflect.get(value, "width"),
|
|
21920
|
+
Reflect.get(value, "height")
|
|
21921
|
+
].every(
|
|
21922
|
+
(coordinate) => typeof coordinate === "number" ? Number.isFinite(coordinate) : false
|
|
21923
|
+
);
|
|
21924
|
+
}
|
|
21925
|
+
function isSimSemanticTree(value) {
|
|
21926
|
+
if (!Array.isArray(value)) return false;
|
|
21927
|
+
return value.every((node) => {
|
|
21928
|
+
if (node === null || typeof node !== "object" || !Number.isInteger(Reflect.get(node, "nodeId")) || typeof Reflect.get(node, "type") !== "string" || !isSemanticGeometry(Reflect.get(node, "geometry"))) {
|
|
21929
|
+
return false;
|
|
21930
|
+
}
|
|
21931
|
+
for (const key of ["testID", "text", "role", "label"]) {
|
|
21932
|
+
const value2 = Reflect.get(node, key);
|
|
21933
|
+
if (value2 !== void 0 && typeof value2 !== "string") return false;
|
|
21934
|
+
}
|
|
21935
|
+
const pressable = Reflect.get(node, "pressable");
|
|
21936
|
+
if (pressable !== void 0 && pressable !== true) return false;
|
|
21937
|
+
const children = Reflect.get(node, "children");
|
|
21938
|
+
return children === void 0 || isSimSemanticTree(children);
|
|
21939
|
+
});
|
|
21940
|
+
}
|
|
21941
|
+
function isSemanticQueryResult(value) {
|
|
21942
|
+
const total = value !== null && typeof value === "object" ? Reflect.get(value, "total") : void 0;
|
|
21943
|
+
return value !== null && typeof value === "object" && typeof total === "number" && Number.isInteger(total) && total >= 0 && isSimSemanticTree(Reflect.get(value, "nodes"));
|
|
21944
|
+
}
|
|
21945
|
+
function globRegex(glob) {
|
|
21946
|
+
const escaped = glob.replace(/[.+^$(){}|[\]\\]/g, "\\$&");
|
|
21947
|
+
return new RegExp(`^${escaped.replace(/\*/g, ".*").replace(/\?/g, ".")}$`, "i");
|
|
21948
|
+
}
|
|
21949
|
+
function formatSemanticTree(nodes, opts = {}) {
|
|
21950
|
+
const filter = opts.filter?.toLowerCase() ?? "";
|
|
21951
|
+
const testIDRegex = opts.testIdLike ? globRegex(opts.testIdLike) : null;
|
|
21952
|
+
const onlyRegex = opts.onlyGlob ? globRegex(opts.onlyGlob) : null;
|
|
21953
|
+
const lines = [];
|
|
21954
|
+
const visit = (node, indent) => {
|
|
21955
|
+
const joined = [node.role, node.label, node.text, node.testID].filter((value) => typeof value === "string").join(" ");
|
|
21956
|
+
const matches = (!filter || joined.toLowerCase().includes(filter)) && (!testIDRegex || testIDRegex.test(node.testID ?? "")) && (!onlyRegex || onlyRegex.test(joined));
|
|
21957
|
+
if (matches) {
|
|
21958
|
+
const parts = [
|
|
21959
|
+
node.role ? `[${node.role}]` : node.pressable ? "[tap]" : `<${node.type}>`
|
|
21960
|
+
];
|
|
21961
|
+
if (node.text) {
|
|
21962
|
+
const text = opts.fullText || node.text.length <= 50 ? node.text : `${node.text.slice(0, 49).trimEnd()}\u2026`;
|
|
21963
|
+
parts.push(JSON.stringify(text));
|
|
21964
|
+
}
|
|
21965
|
+
if (node.testID) parts.push(`#${node.testID}`);
|
|
21966
|
+
if (node.label && node.label !== node.text) {
|
|
21967
|
+
parts.push(`label=${JSON.stringify(node.label)}`);
|
|
21968
|
+
}
|
|
21969
|
+
if (!opts.hideXy) {
|
|
21970
|
+
const geometry = node.geometry;
|
|
21971
|
+
parts.push(
|
|
21972
|
+
`@(${Math.round(geometry.x)},${Math.round(geometry.y)}) ${Math.round(geometry.width)}x${Math.round(geometry.height)}`
|
|
21973
|
+
);
|
|
21974
|
+
}
|
|
21975
|
+
if (node.pressable) parts.push("(tap)");
|
|
21976
|
+
lines.push(`${" ".repeat(indent + 1)}${parts.join(" ")}`);
|
|
21977
|
+
}
|
|
21978
|
+
for (const child of node.children ?? []) visit(child, indent + 1);
|
|
21979
|
+
};
|
|
21980
|
+
let roots = nodes;
|
|
21981
|
+
if (opts.subtreeRoot) {
|
|
21982
|
+
const pending = [...nodes];
|
|
21983
|
+
let found;
|
|
21984
|
+
while (pending.length > 0 && !found) {
|
|
21985
|
+
const candidate = pending.shift();
|
|
21986
|
+
if (!candidate) continue;
|
|
21987
|
+
if (candidate.testID === opts.subtreeRoot) found = candidate;
|
|
21988
|
+
else pending.push(...candidate.children ?? []);
|
|
21989
|
+
}
|
|
21990
|
+
if (!found) return `__SUBTREE_NOT_FOUND__:${opts.subtreeRoot}`;
|
|
21991
|
+
roots = [found];
|
|
21992
|
+
}
|
|
21993
|
+
for (const root of roots) visit(root, 0);
|
|
21994
|
+
return lines.join("\n");
|
|
21995
|
+
}
|
|
21996
|
+
async function inspectDescribe(bridge, dumpOpts) {
|
|
21997
|
+
const dumpDepth = dumpOpts.maxDepth ?? 12;
|
|
21998
|
+
const result = await bridge.send({
|
|
21999
|
+
type: "query",
|
|
22000
|
+
query: { kind: "tree", depth: dumpDepth }
|
|
22001
|
+
});
|
|
22002
|
+
if (!isSemanticQueryResult(result)) return {};
|
|
22003
|
+
return {
|
|
22004
|
+
tree: formatSemanticTree(result.nodes, dumpOpts),
|
|
22005
|
+
nodeCount: result.total
|
|
22006
|
+
};
|
|
22007
|
+
}
|
|
21843
22008
|
function scoreLayoutTextContrast(input) {
|
|
21844
22009
|
const required = input.fontSize >= 18 || input.fontSize >= 14 && (input.fontWeight ?? 400) >= 700 ? 3 : 4.5;
|
|
21845
22010
|
const { normal, background } = input;
|
|
@@ -22053,9 +22218,6 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
22053
22218
|
type: typeof n.type === 'string' ? n.type : 'node',
|
|
22054
22219
|
text,
|
|
22055
22220
|
box: { x: round(abs.x), y: round(abs.y), w: round(layout.width), h: round(layout.height) },
|
|
22056
|
-
borderRadius: 0,
|
|
22057
|
-
padding: { t: 0, r: 0, b: 0, l: 0 },
|
|
22058
|
-
fontSize: 0,
|
|
22059
22221
|
}
|
|
22060
22222
|
if (!includeStyle) return base
|
|
22061
22223
|
// computedStyle has the resolved values; style is the curated subset \u2014
|
|
@@ -22124,11 +22286,56 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
22124
22286
|
return elements
|
|
22125
22287
|
})()`;
|
|
22126
22288
|
}
|
|
22127
|
-
function
|
|
22128
|
-
|
|
22289
|
+
function waitReadyReason(status) {
|
|
22290
|
+
if (status.bridgeError) {
|
|
22291
|
+
return `sim unreachable: ${status.bridgeError} \u2014 the target tab is closed or no sim is connected (check \`rnx list\`, reopen with \`rnx open\`)`;
|
|
22292
|
+
}
|
|
22293
|
+
const base = status.externalError ? `guest app errored: ${status.externalError}` : status.loadingText ? `still showing "${status.loadingText}"` : status.externalReady === false ? "guest app is still loading" : status.flag !== true && status.targets > 0 ? "native content is rendered but the ready signal has not settled" : status.flag !== true ? "guest app has not emitted sootsim:externalAppReady" : status.targets <= 0 ? "ready flag emitted but no visible app content is inspectable yet" : "node tree is still changing";
|
|
22294
|
+
return !status.externalError && status.suppressedEntryError ? `${base} (suppressed entry error: ${status.suppressedEntryError})` : base;
|
|
22129
22295
|
}
|
|
22130
|
-
function
|
|
22131
|
-
|
|
22296
|
+
async function inspectWaitReady(bridge, timeoutMs = 2e4, options = {}) {
|
|
22297
|
+
const start = Date.now();
|
|
22298
|
+
let result;
|
|
22299
|
+
try {
|
|
22300
|
+
result = await bridge.send(
|
|
22301
|
+
{
|
|
22302
|
+
type: "waitFor",
|
|
22303
|
+
waitForOptions: { condition: { type: "ready" }, timeoutMs }
|
|
22304
|
+
},
|
|
22305
|
+
{ timeoutMs: timeoutMs + 1e3 }
|
|
22306
|
+
);
|
|
22307
|
+
} catch (error) {
|
|
22308
|
+
const bridgeError = error instanceof Error ? error.message : String(error);
|
|
22309
|
+
if (bridgeError.startsWith("multiple sims are connected:") || bridgeError.startsWith("saved sim ")) {
|
|
22310
|
+
throw error;
|
|
22311
|
+
}
|
|
22312
|
+
result = {
|
|
22313
|
+
matched: false,
|
|
22314
|
+
elapsedMs: Date.now() - start,
|
|
22315
|
+
polls: 0,
|
|
22316
|
+
error: bridgeError
|
|
22317
|
+
};
|
|
22318
|
+
}
|
|
22319
|
+
const probe3 = result.probe;
|
|
22320
|
+
const status = {
|
|
22321
|
+
ready: result.matched,
|
|
22322
|
+
elapsedMs: result.elapsedMs,
|
|
22323
|
+
nodes: probe3?.nodes ?? 0,
|
|
22324
|
+
targets: probe3?.targets ?? 0,
|
|
22325
|
+
liveFrameActive: probe3?.liveFrameActive ?? false,
|
|
22326
|
+
liveFrameChannels: probe3?.liveFrameChannels ?? 0,
|
|
22327
|
+
liveFramePublishes: probe3?.liveFramePublishes ?? 0,
|
|
22328
|
+
flag: probe3?.flag,
|
|
22329
|
+
loadingText: probe3?.loadingText ?? "",
|
|
22330
|
+
externalReady: probe3?.externalReady ?? null,
|
|
22331
|
+
externalStatus: probe3?.externalStatus ?? "",
|
|
22332
|
+
externalError: probe3?.externalError ?? "",
|
|
22333
|
+
suppressedEntryError: probe3?.suppressedEntryError ?? "",
|
|
22334
|
+
errors: probe3?.errors ?? 0,
|
|
22335
|
+
bridgeError: result.error ?? ""
|
|
22336
|
+
};
|
|
22337
|
+
if (!status.ready && options.onProgress) options.onProgress(status);
|
|
22338
|
+
return status;
|
|
22132
22339
|
}
|
|
22133
22340
|
function consoleEntriesEval(level, limit) {
|
|
22134
22341
|
const getter = level === "error" ? "getErrors" : "getWarnings";
|
|
@@ -22182,156 +22389,12 @@ async function getShellState(bridge, readyTimeoutMs = 0) {
|
|
|
22182
22389
|
}
|
|
22183
22390
|
}
|
|
22184
22391
|
}
|
|
22185
|
-
var LAYOUT_GET_NATIVE_EVAL,
|
|
22392
|
+
var LAYOUT_GET_NATIVE_EVAL, MERGED_CONSOLE_COUNT_EVAL;
|
|
22186
22393
|
var init_core = __esm({
|
|
22187
22394
|
"cli/commands/inspect/core.ts"() {
|
|
22188
22395
|
"use strict";
|
|
22396
|
+
init_bridge_contract();
|
|
22189
22397
|
LAYOUT_GET_NATIVE_EVAL = layoutGetNativeEval();
|
|
22190
|
-
WAIT_READY_PROBE = `(async () => {
|
|
22191
|
-
const t = window.__sootsimTest
|
|
22192
|
-
let nodes = 0
|
|
22193
|
-
try { nodes = (await t?.getNodeCount?.()) || 0 } catch {}
|
|
22194
|
-
let targets = 0
|
|
22195
|
-
let liveFrameActive = false
|
|
22196
|
-
let liveFrameChannels = 0
|
|
22197
|
-
let liveFramePublishes = 0
|
|
22198
|
-
let loadingText = ''
|
|
22199
|
-
const cleanText = (value) =>
|
|
22200
|
-
typeof value === 'string' ? value.replace(/\\s+/g, ' ').trim() : ''
|
|
22201
|
-
const loadingSignal = (value) => {
|
|
22202
|
-
const text = cleanText(value)
|
|
22203
|
-
if (!text) return ''
|
|
22204
|
-
return /^(opening app\\b|looking for your app\\b|building bundle\\b|preparing rnx runtime\\b|loading native bundle\\b|loading rnx stubs\\b|loading bundle loader\\b|loading native stubs\\b|loading compat bridge\\b|loading react-native shim\\b|loading react bridge\\b|loading reconciler\\b|loading replacement modules\\b|injecting rnx modules\\b|warming sqlite engine\\b|capturing root component\\b|reloading app\\b|loading(?:[.!\u2026]*)?$|connecting(?:[.!\u2026]*)?$)/i.test(text)
|
|
22205
|
-
? text
|
|
22206
|
-
: ''
|
|
22207
|
-
}
|
|
22208
|
-
try {
|
|
22209
|
-
const loading = window.__sootsimConnectRNLoading
|
|
22210
|
-
if (loading && loading.active === true) {
|
|
22211
|
-
loadingText = [loading.title, loading.detail].map(cleanText).filter(Boolean).join(' ')
|
|
22212
|
-
}
|
|
22213
|
-
} catch {}
|
|
22214
|
-
try {
|
|
22215
|
-
if (typeof t?.listInspectable === 'function') {
|
|
22216
|
-
const list = await t.listInspectable({})
|
|
22217
|
-
if (Array.isArray(list)) {
|
|
22218
|
-
const screenW = window.innerWidth || 0
|
|
22219
|
-
const screenH = window.innerHeight || 0
|
|
22220
|
-
const isVisible = (n) => {
|
|
22221
|
-
const layout = n?.layout
|
|
22222
|
-
if (!layout || layout.width <= 0 || layout.height <= 0) return false
|
|
22223
|
-
const abs = n?.absolutePosition || n?.absolute
|
|
22224
|
-
if (!abs) return true
|
|
22225
|
-
const device = n?.device || {}
|
|
22226
|
-
const w = Number(device.width) || screenW
|
|
22227
|
-
const h = Number(device.height) || screenH
|
|
22228
|
-
return (
|
|
22229
|
-
abs.x + layout.width > 0 &&
|
|
22230
|
-
abs.y + layout.height > 0 &&
|
|
22231
|
-
abs.x < w &&
|
|
22232
|
-
abs.y < h
|
|
22233
|
-
)
|
|
22234
|
-
}
|
|
22235
|
-
const hasContentSignal = (n) => {
|
|
22236
|
-
const role = n?.accessibilityRole || n?.role
|
|
22237
|
-
const label = cleanText(n?.accessibilityLabel || n?.label)
|
|
22238
|
-
const handlers = Array.isArray(n?.handlers) ? n.handlers : []
|
|
22239
|
-
const text = cleanText(n?.text)
|
|
22240
|
-
const testID = cleanText(n?.testID || n?.testId)
|
|
22241
|
-
const loading = loadingSignal(text) || loadingSignal(label) || loadingSignal(testID)
|
|
22242
|
-
if (!loadingText && loading) {
|
|
22243
|
-
loadingText = loading
|
|
22244
|
-
}
|
|
22245
|
-
if (handlers.length > 0) return true
|
|
22246
|
-
if (role) return true
|
|
22247
|
-
if (n?.isTextInput) return true
|
|
22248
|
-
if (text) return true
|
|
22249
|
-
if (label) return true
|
|
22250
|
-
if (testID && !/^splash|loading/i.test(testID)) return true
|
|
22251
|
-
return false
|
|
22252
|
-
}
|
|
22253
|
-
targets = list.filter(n => isVisible(n) && hasContentSignal(n)).length
|
|
22254
|
-
}
|
|
22255
|
-
}
|
|
22256
|
-
} catch {}
|
|
22257
|
-
try {
|
|
22258
|
-
const stats = await t?.getImageLoaderStats?.()
|
|
22259
|
-
const presentation = stats?.liveFramePresentation
|
|
22260
|
-
liveFrameChannels = Number(presentation?.activeChannels) || 0
|
|
22261
|
-
liveFramePublishes = Number(presentation?.publishes) || 0
|
|
22262
|
-
const previous = window.__sootsimWaitReadyLiveFramePublishes
|
|
22263
|
-
liveFrameActive =
|
|
22264
|
-
liveFrameChannels > 0 &&
|
|
22265
|
-
typeof previous === 'number' &&
|
|
22266
|
-
liveFramePublishes > previous
|
|
22267
|
-
window.__sootsimWaitReadyLiveFramePublishes = liveFramePublishes
|
|
22268
|
-
} catch {}
|
|
22269
|
-
let externalReady = null
|
|
22270
|
-
let externalStatus = ''
|
|
22271
|
-
let externalError = ''
|
|
22272
|
-
let suppressedEntryError = ''
|
|
22273
|
-
try {
|
|
22274
|
-
const getExternalAppState = t?.getExternalAppState
|
|
22275
|
-
const external = typeof getExternalAppState === 'function'
|
|
22276
|
-
? await Promise.race([
|
|
22277
|
-
getExternalAppState(),
|
|
22278
|
-
new Promise((resolve) => setTimeout(
|
|
22279
|
-
() => resolve({
|
|
22280
|
-
state: {
|
|
22281
|
-
ready: false,
|
|
22282
|
-
loading: true,
|
|
22283
|
-
status: 'waiting for tenant worker...',
|
|
22284
|
-
},
|
|
22285
|
-
}),
|
|
22286
|
-
1000,
|
|
22287
|
-
)),
|
|
22288
|
-
])
|
|
22289
|
-
: null
|
|
22290
|
-
const state = external?.state
|
|
22291
|
-
if (state && typeof state === 'object') {
|
|
22292
|
-
externalReady = state.ready === true
|
|
22293
|
-
if (typeof state.status === 'string') externalStatus = state.status
|
|
22294
|
-
if (typeof state.error === 'string') externalError = state.error
|
|
22295
|
-
}
|
|
22296
|
-
if (!externalError && Array.isArray(external?.entryErrors)) {
|
|
22297
|
-
// suppressed-and-continued entry errors (bundle-loader's patched __r
|
|
22298
|
-
// swallows entry throws and moves on) must NOT gate readiness \u2014 the
|
|
22299
|
-
// app frequently runs fine after one (e.g. metro's "Unknown named
|
|
22300
|
-
// module" probing noise). they surface separately as a diagnostic
|
|
22301
|
-
// for the timeout path.
|
|
22302
|
-
const isReal = (item) => item && typeof item.message === 'string' && item.message.trim()
|
|
22303
|
-
const fatal = external.entryErrors.find((item) => isReal(item) && item.suppressed !== true)
|
|
22304
|
-
if (fatal) externalError = fatal.message
|
|
22305
|
-
const suppressed = external.entryErrors.find((item) => isReal(item) && item.suppressed === true)
|
|
22306
|
-
if (suppressed) suppressedEntryError = suppressed.message
|
|
22307
|
-
}
|
|
22308
|
-
// once the app has errored its last status ("injecting sootsim
|
|
22309
|
-
// modules...") is stale \u2014 reporting it makes a dead app read as one that
|
|
22310
|
-
// is still booting.
|
|
22311
|
-
if (externalError) loadingText = ''
|
|
22312
|
-
else if (externalReady === false && externalStatus) loadingText = externalStatus
|
|
22313
|
-
} catch {}
|
|
22314
|
-
let errors = 0
|
|
22315
|
-
try { errors = window.__sootsimConsole?.count?.()?.errors ?? 0 } catch {}
|
|
22316
|
-
return {
|
|
22317
|
-
flag: (window).__sootsimExternalAppReady,
|
|
22318
|
-
at: (window).__sootsimExternalAppReadyAt || 0,
|
|
22319
|
-
nodes,
|
|
22320
|
-
targets,
|
|
22321
|
-
liveFrameActive,
|
|
22322
|
-
liveFrameChannels,
|
|
22323
|
-
liveFramePublishes,
|
|
22324
|
-
errors,
|
|
22325
|
-
loadingText,
|
|
22326
|
-
externalReady,
|
|
22327
|
-
externalStatus,
|
|
22328
|
-
externalError,
|
|
22329
|
-
suppressedEntryError,
|
|
22330
|
-
}
|
|
22331
|
-
})()`;
|
|
22332
|
-
READY_CONTENT_NODE_FLOOR = 100;
|
|
22333
|
-
READY_NODE_STABLE_MS = 750;
|
|
22334
|
-
READY_PROBE_POLL_MS = 150;
|
|
22335
22398
|
MERGED_CONSOLE_COUNT_EVAL = `(() => {
|
|
22336
22399
|
const norm = (s) => (typeof s === 'string' ? s : (() => { try { return JSON.stringify(s) } catch { return String(s) } })())
|
|
22337
22400
|
const key = (lvl, ts, args) => lvl + '|' + Math.round((ts || 0) / 250) + '|' + (Array.isArray(args) ? args.map(norm).join(' ') : norm(args))
|
|
@@ -24002,7 +24065,6 @@ __export(control_exports, {
|
|
|
24002
24065
|
buildShellUrl: () => buildShellUrl,
|
|
24003
24066
|
closeSimsBulk: () => closeSimsBulk,
|
|
24004
24067
|
ensureBridgeForOpen: () => ensureBridgeForOpen,
|
|
24005
|
-
normalizeDeepLinkTarget: () => normalizeDeepLinkTarget,
|
|
24006
24068
|
planBulkCloseTargets: () => planBulkCloseTargets,
|
|
24007
24069
|
playwrightHostPidForSim: () => playwrightHostPidForSim,
|
|
24008
24070
|
printConnectedSims: () => printConnectedSims,
|
|
@@ -24063,26 +24125,6 @@ function resolveDriverHeadless(args, driverId) {
|
|
|
24063
24125
|
function normalizeKnownTarget(target) {
|
|
24064
24126
|
return target.trim();
|
|
24065
24127
|
}
|
|
24066
|
-
function normalizeDeepLinkTarget(target) {
|
|
24067
|
-
const trimmed = target.trim();
|
|
24068
|
-
if (!trimmed) {
|
|
24069
|
-
throw new Error("expected <url-or-route>");
|
|
24070
|
-
}
|
|
24071
|
-
if (DEEP_LINK_SCHEME_RE.test(trimmed) || trimmed.startsWith("/")) {
|
|
24072
|
-
return trimmed;
|
|
24073
|
-
}
|
|
24074
|
-
return `/${trimmed}`;
|
|
24075
|
-
}
|
|
24076
|
-
function isObjectRecord(value) {
|
|
24077
|
-
return value !== null && typeof value === "object";
|
|
24078
|
-
}
|
|
24079
|
-
function shouldOpenAsDeepLink(target) {
|
|
24080
|
-
const trimmed = target.trim();
|
|
24081
|
-
if (!trimmed) return false;
|
|
24082
|
-
if (trimmed.startsWith("/")) return true;
|
|
24083
|
-
if (!DEEP_LINK_SCHEME_RE.test(trimmed)) return false;
|
|
24084
|
-
return !/^https?:\/\//i.test(trimmed);
|
|
24085
|
-
}
|
|
24086
24128
|
async function ensureBridgeForOpen(preferredPort, explicitPort = false) {
|
|
24087
24129
|
const lock = readDaemonLockfile();
|
|
24088
24130
|
assertExplicitBridgeLock(preferredPort, explicitPort, lock);
|
|
@@ -24843,15 +24885,11 @@ async function maybeDescribeAfterOpen(wsPort, simId, args) {
|
|
|
24843
24885
|
try {
|
|
24844
24886
|
let readyProbe = null;
|
|
24845
24887
|
try {
|
|
24846
|
-
readyProbe = await bridge
|
|
24847
|
-
type: "evaluate",
|
|
24848
|
-
code: WAIT_READY_PROBE
|
|
24849
|
-
});
|
|
24888
|
+
readyProbe = await inspectWaitReady(bridge, 1);
|
|
24850
24889
|
} catch {
|
|
24851
24890
|
}
|
|
24852
24891
|
if (readyProbe) {
|
|
24853
|
-
|
|
24854
|
-
if (!readyEnough) {
|
|
24892
|
+
if (!readyProbe.ready) {
|
|
24855
24893
|
const reason = readyProbe.loadingText ? `still showing "${readyProbe.loadingText}"` : readyProbe.flag !== true ? "guest ready event has not fired" : readyProbe.targets <= 0 ? "no visible app content is inspectable yet" : "app tree is still stabilizing";
|
|
24856
24894
|
console.log(
|
|
24857
24895
|
` app still loading: ${reason} (nodes: ${readyProbe.nodes}, targets: ${readyProbe.targets})`
|
|
@@ -24859,26 +24897,16 @@ async function maybeDescribeAfterOpen(wsPort, simId, args) {
|
|
|
24859
24897
|
console.log(" before interacting, run: rnx wait ready --max-ms 120000");
|
|
24860
24898
|
}
|
|
24861
24899
|
}
|
|
24862
|
-
const
|
|
24863
|
-
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
|
|
24870
|
-
return { tree, shell }
|
|
24871
|
-
})()`;
|
|
24872
|
-
const result = await bridge.send({ type: "evaluate", code });
|
|
24900
|
+
const result = await inspectDescribe(bridge, {
|
|
24901
|
+
describe: true,
|
|
24902
|
+
verbose: false,
|
|
24903
|
+
filter: "",
|
|
24904
|
+
compact: true,
|
|
24905
|
+
hideXy: false,
|
|
24906
|
+
maxDepth: 12
|
|
24907
|
+
});
|
|
24873
24908
|
if (!result?.tree) return;
|
|
24874
24909
|
console.log("");
|
|
24875
|
-
if (result.shell?.state) {
|
|
24876
|
-
const parts = [
|
|
24877
|
-
`state=${result.shell.state}`,
|
|
24878
|
-
result.shell.activeApp ? `app=${result.shell.activeApp}` : null
|
|
24879
|
-
].filter(Boolean);
|
|
24880
|
-
console.log(` shell: ${parts.join(" ")}`);
|
|
24881
|
-
}
|
|
24882
24910
|
console.log(result.tree);
|
|
24883
24911
|
} finally {
|
|
24884
24912
|
bridge.close();
|
|
@@ -24932,26 +24960,10 @@ async function runLinkCommand(args, opts = {}) {
|
|
|
24932
24960
|
console.error(" examples: rnx open /settings | rnx open myapp://settings");
|
|
24933
24961
|
process.exit(1);
|
|
24934
24962
|
}
|
|
24935
|
-
let target;
|
|
24936
|
-
try {
|
|
24937
|
-
target = normalizeDeepLinkTarget(parsed.positional[0] ?? "");
|
|
24938
|
-
} catch (err) {
|
|
24939
|
-
console.error(` rnx open: ${err instanceof Error ? err.message : String(err)}`);
|
|
24940
|
-
process.exit(1);
|
|
24941
|
-
}
|
|
24942
24963
|
const bridge = createBridgeFromParsed(parsed);
|
|
24943
24964
|
const simHint = parsed.simId ? ` --sim ${parsed.simId}` : "";
|
|
24944
24965
|
try {
|
|
24945
|
-
const
|
|
24946
|
-
type: "call",
|
|
24947
|
-
path: "SootSim.bridges.test.openDeepLink",
|
|
24948
|
-
args: [target]
|
|
24949
|
-
});
|
|
24950
|
-
if (isObjectRecord(result) && result.ok === false) {
|
|
24951
|
-
throw new Error(
|
|
24952
|
-
typeof result.error === "string" ? result.error : "deep-link dispatch failed"
|
|
24953
|
-
);
|
|
24954
|
-
}
|
|
24966
|
+
const target = await openAppUrl(bridge, parsed.positional[0] ?? "");
|
|
24955
24967
|
console.log(` opened deep link: ${target}`);
|
|
24956
24968
|
} catch (err) {
|
|
24957
24969
|
console.error(` link failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -25014,7 +25026,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
25014
25026
|
process.exit(1);
|
|
25015
25027
|
}
|
|
25016
25028
|
const target = parsed.positional[0] || "";
|
|
25017
|
-
if (
|
|
25029
|
+
if (isAppDeepLinkTarget(target)) {
|
|
25018
25030
|
if (openInNewSim) {
|
|
25019
25031
|
console.error(
|
|
25020
25032
|
" rnx open: deep links target the current app; remove --new, --profile, or --ephemeral"
|
|
@@ -25551,7 +25563,7 @@ async function runCloseCommand(args, opts = {}) {
|
|
|
25551
25563
|
bridge.close();
|
|
25552
25564
|
}
|
|
25553
25565
|
}
|
|
25554
|
-
var import_node_child_process6, import_node_fs13, import_node_os3, import_node_path16, import_settings, import_ws5, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS
|
|
25566
|
+
var import_node_child_process6, import_node_fs13, import_node_os3, import_node_path16, import_settings, import_ws5, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS;
|
|
25555
25567
|
var init_control = __esm({
|
|
25556
25568
|
"cli/commands/control.ts"() {
|
|
25557
25569
|
"use strict";
|
|
@@ -25562,6 +25574,7 @@ var init_control = __esm({
|
|
|
25562
25574
|
import_settings = require("sootsim-engine/settings");
|
|
25563
25575
|
import_ws5 = require("ws");
|
|
25564
25576
|
init_dev_server_scanner();
|
|
25577
|
+
init_app_url();
|
|
25565
25578
|
init_backend_origin();
|
|
25566
25579
|
init_bridge_constants();
|
|
25567
25580
|
init_config();
|
|
@@ -25598,7 +25611,6 @@ var init_control = __esm({
|
|
|
25598
25611
|
photos: "/app/photos",
|
|
25599
25612
|
camera: "/app/camera"
|
|
25600
25613
|
};
|
|
25601
|
-
DEEP_LINK_SCHEME_RE = /^[A-Za-z][A-Za-z0-9+.-]*:/;
|
|
25602
25614
|
}
|
|
25603
25615
|
});
|
|
25604
25616
|
|
|
@@ -26702,16 +26714,16 @@ __export(bridge_flow_runner_exports, {
|
|
|
26702
26714
|
function sleep3(ms) {
|
|
26703
26715
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
26704
26716
|
}
|
|
26705
|
-
function
|
|
26717
|
+
function isObjectRecord(value) {
|
|
26706
26718
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
26707
26719
|
}
|
|
26708
26720
|
function readStringKey(value, key) {
|
|
26709
|
-
if (!
|
|
26721
|
+
if (!isObjectRecord(value)) return null;
|
|
26710
26722
|
const raw = value[key];
|
|
26711
26723
|
return typeof raw === "string" && raw.length > 0 ? raw : null;
|
|
26712
26724
|
}
|
|
26713
26725
|
function readBooleanKey(value, key) {
|
|
26714
|
-
if (!
|
|
26726
|
+
if (!isObjectRecord(value)) return false;
|
|
26715
26727
|
return value[key] === true;
|
|
26716
26728
|
}
|
|
26717
26729
|
function readRecentShellAppId(state) {
|
|
@@ -26846,7 +26858,6 @@ var init_bridge_flow_runner = __esm({
|
|
|
26846
26858
|
lastRecordingDurationMs = null;
|
|
26847
26859
|
lastRecordingFrameStats = null;
|
|
26848
26860
|
flowTraceSteps = [];
|
|
26849
|
-
simRouteHint = null;
|
|
26850
26861
|
// set by runStep when a step throws — lets the outer flow command
|
|
26851
26862
|
// dump a rich per-step failure bundle (screenshot + describe.json +
|
|
26852
26863
|
// console + network) keyed by the failing step.
|
|
@@ -26854,50 +26865,6 @@ var init_bridge_flow_runner = __esm({
|
|
|
26854
26865
|
get simId() {
|
|
26855
26866
|
return this.opts.simId;
|
|
26856
26867
|
}
|
|
26857
|
-
setSimRouteHint(urlLike) {
|
|
26858
|
-
this.simRouteHint = this.normalizeSimRoute(urlLike);
|
|
26859
|
-
}
|
|
26860
|
-
normalizeSimRoute(urlLike) {
|
|
26861
|
-
if (!urlLike) return null;
|
|
26862
|
-
try {
|
|
26863
|
-
const url = new URL(urlLike);
|
|
26864
|
-
url.searchParams.delete("inspectOpen");
|
|
26865
|
-
const search = url.searchParams.toString();
|
|
26866
|
-
return `${url.origin}${url.pathname}${search ? `?${search}` : ""}`;
|
|
26867
|
-
} catch {
|
|
26868
|
-
return urlLike;
|
|
26869
|
-
}
|
|
26870
|
-
}
|
|
26871
|
-
// sim ids rotate on `window.location.reload()` when the shell reconnects.
|
|
26872
|
-
// after launchApp we re-resolve the primary sim so the rest of the flow
|
|
26873
|
-
// doesn't send commands to a dead id.
|
|
26874
|
-
async refreshSimId() {
|
|
26875
|
-
if (!this.opts.simId) return;
|
|
26876
|
-
try {
|
|
26877
|
-
const sims = await this.bridge.listSims();
|
|
26878
|
-
const current = sims.find((b) => b.id === this.opts.simId);
|
|
26879
|
-
if (current) {
|
|
26880
|
-
this.simRouteHint = this.normalizeSimRoute(current.url || current.origin);
|
|
26881
|
-
}
|
|
26882
|
-
const stillThere = sims.find(
|
|
26883
|
-
(b) => b.id === this.opts.simId && b.readyState === "open"
|
|
26884
|
-
);
|
|
26885
|
-
if (stillThere) return;
|
|
26886
|
-
if (!this.simRouteHint) return;
|
|
26887
|
-
const hinted = this.simRouteHint && sims.find(
|
|
26888
|
-
(b) => b.readyState === "open" && this.normalizeSimRoute(b.url || b.origin) === this.simRouteHint
|
|
26889
|
-
);
|
|
26890
|
-
if (!hinted) return;
|
|
26891
|
-
const primary = sims.find((b) => b.isPrimary && b.readyState === "open");
|
|
26892
|
-
const firstOpen = sims.find((b) => b.readyState === "open");
|
|
26893
|
-
const next = hinted ?? primary ?? firstOpen;
|
|
26894
|
-
if (next) {
|
|
26895
|
-
this.opts.simId = next.id;
|
|
26896
|
-
console.log(` [flow] sim rotated to ${next.id}`);
|
|
26897
|
-
}
|
|
26898
|
-
} catch {
|
|
26899
|
-
}
|
|
26900
|
-
}
|
|
26901
26868
|
async evaluate(code, timeoutMs) {
|
|
26902
26869
|
return this.bridge.send(
|
|
26903
26870
|
{
|
|
@@ -26926,63 +26893,17 @@ var init_bridge_flow_runner = __esm({
|
|
|
26926
26893
|
});
|
|
26927
26894
|
}
|
|
26928
26895
|
async waitForTree(timeout = DEFAULT_TIMEOUT) {
|
|
26929
|
-
const
|
|
26930
|
-
|
|
26931
|
-
|
|
26932
|
-
|
|
26933
|
-
let lastProgressAt = 0;
|
|
26934
|
-
let lastNodes = -1;
|
|
26935
|
-
let nodeStableSince = startedAt;
|
|
26936
|
-
while (Date.now() < deadline) {
|
|
26937
|
-
try {
|
|
26938
|
-
const probe3 = await this.evaluate(
|
|
26939
|
-
WAIT_READY_PROBE,
|
|
26940
|
-
// the readiness probe is cheap — cap it well under the bridge-wide
|
|
26941
|
-
// command timeout so a non-responsive sim is detected in seconds,
|
|
26942
|
-
// not after a full 15s-per-poll stall.
|
|
26943
|
-
8e3
|
|
26944
|
-
);
|
|
26945
|
-
consecutiveBridgeFailures = 0;
|
|
26946
|
-
if (probe3?.externalError) {
|
|
26947
|
-
throw new Error(`app failed to load: ${probe3.externalError}`);
|
|
26948
|
-
}
|
|
26949
|
-
if (probe3) {
|
|
26950
|
-
const now = Date.now();
|
|
26951
|
-
if (probe3.nodes !== lastNodes) {
|
|
26952
|
-
lastNodes = probe3.nodes;
|
|
26953
|
-
nodeStableSince = now;
|
|
26954
|
-
}
|
|
26955
|
-
const hasReadySignal = probe3.flag === true && readyProbeHasContent(probe3);
|
|
26956
|
-
const hasRenderedContentWithoutReadySignal = probe3.flag !== true && readyProbeHasTargetContent(probe3);
|
|
26957
|
-
const ready = (hasReadySignal || hasRenderedContentWithoutReadySignal) && probe3.externalReady !== false && !probe3.externalError && !probe3.loadingText && now - nodeStableSince >= READY_NODE_STABLE_MS;
|
|
26958
|
-
if (ready) return;
|
|
26959
|
-
}
|
|
26960
|
-
} catch (err) {
|
|
26961
|
-
lastError = err instanceof Error ? err : new Error(String(err));
|
|
26962
|
-
if (lastError.message.startsWith("app failed to load:")) {
|
|
26963
|
-
throw lastError;
|
|
26964
|
-
}
|
|
26965
|
-
consecutiveBridgeFailures++;
|
|
26966
|
-
if (consecutiveBridgeFailures >= 4) {
|
|
26967
|
-
throw new Error(
|
|
26968
|
-
`target sim is not responding to the bridge (${lastError.message}). it is likely a stale orphan \u2014 run \`rnx list\`, then close it with \`rnx close <id>\` or start a fresh one with \`rnx open --new <port>\`.`
|
|
26969
|
-
);
|
|
26970
|
-
}
|
|
26971
|
-
await this.refreshSimId();
|
|
26972
|
-
}
|
|
26973
|
-
const elapsed = Date.now() - startedAt;
|
|
26974
|
-
if (elapsed - lastProgressAt >= 5e3) {
|
|
26975
|
-
lastProgressAt = elapsed;
|
|
26976
|
-
console.log(
|
|
26977
|
-
` [flow] waiting for app to be ready\u2026 (${Math.round(elapsed / 1e3)}s)`
|
|
26978
|
-
);
|
|
26979
|
-
}
|
|
26980
|
-
await sleep3(READY_PROBE_POLL_MS);
|
|
26896
|
+
const status = await inspectWaitReady(this.bridge, scaledTimeout(timeout));
|
|
26897
|
+
if (status.ready) return;
|
|
26898
|
+
if (status.externalError) {
|
|
26899
|
+
throw new Error(`app failed to load: ${status.externalError}`);
|
|
26981
26900
|
}
|
|
26982
|
-
if (
|
|
26983
|
-
throw
|
|
26901
|
+
if (status.bridgeError) {
|
|
26902
|
+
throw new Error(
|
|
26903
|
+
`target sim is not responding to the bridge (${status.bridgeError}). it is likely a stale orphan; run \`rnx list\`, then close it with \`rnx close <id>\` or start a fresh one with \`rnx open --new <port>\`.`
|
|
26904
|
+
);
|
|
26984
26905
|
}
|
|
26985
|
-
throw new Error(`app not ready after ${timeout}ms`);
|
|
26906
|
+
throw new Error(`app not ready after ${timeout}ms: ${waitReadyReason(status)}`);
|
|
26986
26907
|
}
|
|
26987
26908
|
async ensureRecordingStarted() {
|
|
26988
26909
|
if (!this.opts.recordingOutputDir) {
|
|
@@ -27960,8 +27881,6 @@ var init_bridge_flow_runner = __esm({
|
|
|
27960
27881
|
async reloadGuestApp() {
|
|
27961
27882
|
await this.evaluate("window.location.reload()").catch(() => {
|
|
27962
27883
|
});
|
|
27963
|
-
await sleep3(500);
|
|
27964
|
-
await this.refreshSimId();
|
|
27965
27884
|
}
|
|
27966
27885
|
async resetGuestAppData(launchOptions) {
|
|
27967
27886
|
const reset = await this.bridge.send(
|
|
@@ -27998,7 +27917,6 @@ var init_bridge_flow_runner = __esm({
|
|
|
27998
27917
|
const deadline = Date.now() + 1e4;
|
|
27999
27918
|
let lastError = null;
|
|
28000
27919
|
while (Date.now() < deadline) {
|
|
28001
|
-
await this.refreshSimId();
|
|
28002
27920
|
try {
|
|
28003
27921
|
if (this.recordingEnabled) await this.ensureRecordingStarted();
|
|
28004
27922
|
if (this.profilingEnabled) await this.startProfile();
|
|
@@ -28013,11 +27931,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
28013
27931
|
);
|
|
28014
27932
|
}
|
|
28015
27933
|
async launchApp(opts) {
|
|
28016
|
-
await this.refreshSimId();
|
|
28017
27934
|
let hasLaunchArguments = false;
|
|
28018
27935
|
let launchArguments;
|
|
28019
|
-
if (
|
|
28020
|
-
if (!
|
|
27936
|
+
if (isObjectRecord(opts) && Object.prototype.hasOwnProperty.call(opts, "arguments")) {
|
|
27937
|
+
if (!isObjectRecord(opts.arguments)) {
|
|
28021
27938
|
throw new Error("launchApp.arguments must be a JSON object");
|
|
28022
27939
|
}
|
|
28023
27940
|
hasLaunchArguments = true;
|
|
@@ -28069,7 +27986,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
28069
27986
|
await this.waitForTree(12e4);
|
|
28070
27987
|
if (this.opts.onAfterLaunch) {
|
|
28071
27988
|
try {
|
|
28072
|
-
await this.opts.onAfterLaunch();
|
|
27989
|
+
await this.opts.onAfterLaunch(this.opts.simId);
|
|
28073
27990
|
} catch (err) {
|
|
28074
27991
|
console.warn(
|
|
28075
27992
|
` warn: onAfterLaunch hook threw: ${err instanceof Error ? err.message : err}`
|
|
@@ -28102,7 +28019,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
28102
28019
|
}
|
|
28103
28020
|
resolveShellLaunchAppId(opts, state) {
|
|
28104
28021
|
if (typeof opts === "string" && opts.length > 0) return opts;
|
|
28105
|
-
if (
|
|
28022
|
+
if (isObjectRecord(opts)) {
|
|
28106
28023
|
const explicit = readStringKey(opts, "appId") || readStringKey(opts, "id");
|
|
28107
28024
|
if (explicit) return explicit;
|
|
28108
28025
|
}
|