rnxsim 0.1.313 → 0.1.314
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/LICENSE +11 -10
- package/README.md +5 -0
- package/cli/app-config.ts +65 -0
- package/cli/app-fonts.ts +408 -0
- package/cli/app-project.ts +231 -0
- package/cli/app-splash.ts +185 -0
- package/cli/app-state-reset.ts +24 -0
- package/cli/auth.ts +155 -0
- package/cli/bin.ts +594 -0
- package/cli/bridge-diagnostics.ts +226 -0
- package/cli/bridge-flow-runner.ts +2830 -0
- package/cli/browser-evals.ts +96 -0
- package/cli/commands/agent-wrapper.ts +986 -0
- package/cli/commands/agent.ts +423 -0
- package/cli/commands/app-fonts.ts +98 -0
- package/cli/commands/assert.ts +541 -0
- package/cli/commands/auth.ts +59 -0
- package/cli/commands/camera.ts +266 -0
- package/cli/commands/cleanup.ts +169 -0
- package/cli/commands/compat.ts +87 -0
- package/cli/commands/config.ts +32 -0
- package/cli/commands/control.ts +2142 -0
- package/cli/commands/cpu-profile.ts +269 -0
- package/cli/commands/daemon-mac-app.ts +169 -0
- package/cli/commands/daemon.ts +874 -0
- package/cli/commands/debug.ts +719 -0
- package/cli/commands/desktop.ts +39 -0
- package/cli/commands/detect.ts +197 -0
- package/cli/commands/detox.ts +385 -0
- package/cli/commands/device.ts +133 -0
- package/cli/commands/diagnose.ts +589 -0
- package/cli/commands/electron.ts +95 -0
- package/cli/commands/film.ts +379 -0
- package/cli/commands/flow.ts +1124 -0
- package/cli/commands/inspect/actions.ts +622 -0
- package/cli/commands/inspect/core.ts +2405 -0
- package/cli/commands/inspect/count.ts +17 -0
- package/cli/commands/inspect/describe.ts +192 -0
- package/cli/commands/inspect/env.ts +23 -0
- package/cli/commands/inspect/find.ts +171 -0
- package/cli/commands/inspect/get-layout.ts +39 -0
- package/cli/commands/inspect/keyboard.ts +52 -0
- package/cli/commands/inspect/list.ts +58 -0
- package/cli/commands/inspect/memory.ts +215 -0
- package/cli/commands/inspect/redaction.ts +39 -0
- package/cli/commands/inspect/resolve-target.ts +82 -0
- package/cli/commands/inspect/screens.ts +78 -0
- package/cli/commands/inspect/settle.ts +22 -0
- package/cli/commands/inspect/settling.ts +158 -0
- package/cli/commands/inspect/shared.ts +353 -0
- package/cli/commands/inspect/sleep.ts +14 -0
- package/cli/commands/inspect/tree.ts +32 -0
- package/cli/commands/inspect/url.ts +17 -0
- package/cli/commands/inspect/wait-event.ts +210 -0
- package/cli/commands/inspect/wait-idle.ts +24 -0
- package/cli/commands/inspect/wait-ready.ts +74 -0
- package/cli/commands/inspect/wait-selector.ts +54 -0
- package/cli/commands/inspect/wait.ts +31 -0
- package/cli/commands/inspect.ts +4519 -0
- package/cli/commands/install-desktop.ts +351 -0
- package/cli/commands/login.ts +331 -0
- package/cli/commands/logout.ts +31 -0
- package/cli/commands/maestro-generate.ts +361 -0
- package/cli/commands/maestro.ts +453 -0
- package/cli/commands/mode.ts +57 -0
- package/cli/commands/no-bridge-hint.ts +80 -0
- package/cli/commands/perf.ts +66 -0
- package/cli/commands/permissions.ts +203 -0
- package/cli/commands/profile.ts +108 -0
- package/cli/commands/react.ts +353 -0
- package/cli/commands/record.ts +1434 -0
- package/cli/commands/report-issue.ts +305 -0
- package/cli/commands/reset.ts +85 -0
- package/cli/commands/runtime.ts +351 -0
- package/cli/commands/screenshot-command.ts +106 -0
- package/cli/commands/screenshot-layers.ts +143 -0
- package/cli/commands/screenshot-mode.ts +37 -0
- package/cli/commands/screenshot.ts +488 -0
- package/cli/commands/screenshots-capture.ts +607 -0
- package/cli/commands/screenshots.ts +127 -0
- package/cli/commands/serve.ts +168 -0
- package/cli/commands/setup.ts +545 -0
- package/cli/commands/shell-boolean-mode.ts +81 -0
- package/cli/commands/skills.ts +467 -0
- package/cli/commands/slides.ts +361 -0
- package/cli/commands/state.ts +87 -0
- package/cli/commands/storage.ts +58 -0
- package/cli/commands/telemetry.ts +54 -0
- package/cli/commands/three-mode.ts +763 -0
- package/cli/commands/timeline.ts +122 -0
- package/cli/commands/upgrade.ts +208 -0
- package/cli/commands/upload.ts +1225 -0
- package/cli/commands/version.ts +54 -0
- package/cli/commands/what-happened.ts +327 -0
- package/cli/current-sim.ts +204 -0
- package/cli/desktop-companion.ts +300 -0
- package/cli/drivers/electron.ts +70 -0
- package/cli/drivers/index.ts +20 -0
- package/cli/drivers/playwright-provisioning.ts +180 -0
- package/cli/drivers/playwright.ts +698 -0
- package/cli/drivers/registry.ts +65 -0
- package/cli/drivers/types.ts +102 -0
- package/cli/flow-file.ts +142 -0
- package/cli/flow-live-status.ts +120 -0
- package/cli/flow-session.ts +187 -0
- package/cli/help.ts +80 -0
- package/cli/hidden-runtime-alias.ts +19 -0
- package/cli/hints.ts +216 -0
- package/cli/inspect-notice-state.ts +114 -0
- package/cli/maestro-js.ts +334 -0
- package/cli/open-url.ts +8 -0
- package/cli/parent-pid.ts +204 -0
- package/cli/parse-args.ts +211 -0
- package/cli/prompt.ts +51 -0
- package/cli/recording-access.ts +107 -0
- package/cli/registry.ts +1 -0
- package/cli/resolve-assets.ts +63 -0
- package/cli/run-registry.ts +226 -0
- package/cli/runtime-notes.ts +66 -0
- package/cli/runtime-summary.ts +25 -0
- package/cli/setup-repository.ts +187 -0
- package/cli/telemetry.ts +187 -0
- package/cli/ws-bridge.ts +798 -0
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-XZ2KTPCU.js → agent-7YBDCYMA.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-JJYYW2WH.js → agent-wrapper-2GHFBHCR.js} +2 -2
- package/dist-cli/chunks/{app-fonts-IXRNQG6B.js → app-fonts-RSNVPQSU.js} +2 -2
- package/dist-cli/chunks/{assert-54T5SK5F.js → assert-XCMX3XJX.js} +2 -2
- package/dist-cli/chunks/{auth-FI5UDI45.js → auth-B442HRAX.js} +2 -2
- package/dist-cli/chunks/{beta-JV6UKADW.js → beta-XJ55JK3M.js} +2 -2
- package/dist-cli/chunks/camera-UGYSSLIK.js +33 -0
- package/dist-cli/chunks/{chunk-3NV2NCNX.js → chunk-277AEQZX.js} +2 -2
- package/dist-cli/chunks/{chunk-2YR5BGA5.js → chunk-2JNSK774.js} +2 -2
- package/dist-cli/chunks/{chunk-RSZWCKNT.js → chunk-32WOTSTR.js} +3 -3
- package/dist-cli/chunks/{chunk-WEXDAC74.js → chunk-3S753SNQ.js} +2 -2
- package/dist-cli/chunks/{chunk-IJO63TDP.js → chunk-46ZOLOYA.js} +2 -2
- package/dist-cli/chunks/{chunk-WUSWBCWA.js → chunk-5L7ELDQL.js} +8 -9
- package/dist-cli/chunks/{chunk-WF3T4SVI.js → chunk-7OOPFSQS.js} +2 -2
- package/dist-cli/chunks/{chunk-TZFFR3SD.js → chunk-7SV3RPRW.js} +2 -2
- package/dist-cli/chunks/{chunk-WWZIXIRD.js → chunk-7ZC35MOU.js} +1 -1
- package/dist-cli/chunks/chunk-AMG5E6CC.js +9 -0
- package/dist-cli/chunks/{chunk-WINYQ44O.js → chunk-APWNH3A4.js} +1 -1
- package/dist-cli/chunks/chunk-B57XUKY3.js +4 -0
- package/dist-cli/chunks/{chunk-YDGQTMQL.js → chunk-C2NL26TD.js} +1 -1
- package/dist-cli/chunks/{chunk-NMF2ZMZQ.js → chunk-D2FNUWAB.js} +4 -4
- package/dist-cli/chunks/{chunk-YIFT42WN.js → chunk-E5T4XSJ3.js} +2 -2
- package/dist-cli/chunks/{chunk-46EUUFJ5.js → chunk-EAC34EQS.js} +1 -1
- package/dist-cli/chunks/{chunk-OVFJFXUD.js → chunk-EG32ML36.js} +2 -2
- package/dist-cli/chunks/{chunk-5YJCOWCH.js → chunk-FXUAC6D5.js} +1 -1
- package/dist-cli/chunks/chunk-GQSL4USA.js +6 -0
- package/dist-cli/chunks/{chunk-VFCMSYZK.js → chunk-HAXW27SS.js} +2 -2
- package/dist-cli/chunks/{chunk-2D2UPBBR.js → chunk-IZAHPAN6.js} +1 -1
- package/dist-cli/chunks/{chunk-7GN3LVWB.js → chunk-J62KM5TB.js} +2 -2
- package/dist-cli/chunks/{chunk-BTWORNNG.js → chunk-JEMCD5E4.js} +1 -1
- package/dist-cli/chunks/{chunk-DCEMHR2Y.js → chunk-JZS3Q37N.js} +2 -2
- package/dist-cli/chunks/{chunk-D4FFVGI5.js → chunk-KR4JON7D.js} +1 -1
- package/dist-cli/chunks/chunk-KWCYKQIQ.js +4 -0
- package/dist-cli/chunks/{chunk-VNQEB4L7.js → chunk-MCWPL644.js} +2 -2
- package/dist-cli/chunks/chunk-MJYK3N2I.js +4 -0
- package/dist-cli/chunks/{chunk-5TEF3ET3.js → chunk-O6TRIZNS.js} +2 -2
- package/dist-cli/chunks/{chunk-QKDWYITG.js → chunk-P7XL2E73.js} +3 -3
- package/dist-cli/chunks/{chunk-BBULZ7CG.js → chunk-PFQTUKQ4.js} +62 -87
- package/dist-cli/chunks/{chunk-GGRX24GF.js → chunk-PG5RZCTN.js} +2 -2
- package/dist-cli/chunks/{chunk-W6K4EFPH.js → chunk-QGRI2Z4M.js} +2 -2
- package/dist-cli/chunks/{chunk-ZMJD5GEC.js → chunk-QLXXE7GE.js} +1 -1
- package/dist-cli/chunks/{chunk-VZXWHRUZ.js → chunk-QOJJJWJE.js} +89 -133
- package/dist-cli/chunks/{chunk-OZSSI4WN.js → chunk-RWZY5427.js} +2 -2
- package/dist-cli/chunks/{chunk-UC6U3MML.js → chunk-RZKU2K3J.js} +2 -2
- package/dist-cli/chunks/{chunk-IJ5CAZZC.js → chunk-SBV4IK4H.js} +1 -1
- package/dist-cli/chunks/{chunk-DZS6WPUI.js → chunk-SGMVFFMK.js} +1 -1
- package/dist-cli/chunks/{chunk-OHAZNXLK.js → chunk-TAX4UT2N.js} +1 -1
- package/dist-cli/chunks/{chunk-5DHC6KHQ.js → chunk-TUOFAWXT.js} +1 -1
- package/dist-cli/chunks/{chunk-GASE6UBA.js → chunk-UHZLOHGP.js} +1 -1
- package/dist-cli/chunks/{chunk-F5ZRSS3C.js → chunk-VC7V76U3.js} +1 -1
- package/dist-cli/chunks/{chunk-RTN5C5RL.js → chunk-VQVMLW4U.js} +1 -1
- package/dist-cli/chunks/{chunk-WMIIKMGK.js → chunk-VUKKYPZN.js} +2 -2
- package/dist-cli/chunks/{chunk-5TPRP5QT.js → chunk-WGGRJDRE.js} +1 -1
- package/dist-cli/chunks/chunk-X6H76EKP.js +15 -0
- package/dist-cli/chunks/chunk-XLZ5FNRT.js +27 -0
- package/dist-cli/chunks/{chunk-HI5TFJWN.js → chunk-XULEACM4.js} +2 -2
- package/dist-cli/chunks/{chunk-MJRLLB4R.js → chunk-YFSDM7AX.js} +4 -4
- package/dist-cli/chunks/chunk-YWI3UEVX.js +5 -0
- package/dist-cli/chunks/{chunk-XEVZYVIW.js → chunk-ZBSJO4NB.js} +10 -9
- package/dist-cli/chunks/{cleanup-P27PA6JI.js → cleanup-EYLGCA6Z.js} +2 -2
- package/dist-cli/chunks/cli-version-LL2UGIHE.js +4 -0
- package/dist-cli/chunks/{compat-ZD65FED3.js → compat-TLJYHB4E.js} +2 -2
- package/dist-cli/chunks/{config-XMJRNM2A.js → config-4JWUOEXK.js} +2 -2
- package/dist-cli/chunks/{control-KMIQT3QP.js → control-HPAOYF4N.js} +2 -2
- package/dist-cli/chunks/daemon-OYLASXLE.js +4 -0
- package/dist-cli/chunks/{debug-PT4HOP7N.js → debug-4BKXF6KI.js} +5 -5
- package/dist-cli/chunks/{desktop-S3FG72AK.js → desktop-ZQ6ZD2S6.js} +3 -3
- package/dist-cli/chunks/{detox-B3D4IFCN.js → detox-WNPASSS3.js} +2 -2
- package/dist-cli/chunks/{device-XBNDSB2R.js → device-BXLXVG3V.js} +2 -2
- package/dist-cli/chunks/{diagnose-HMQXJE5N.js → diagnose-3QX7W5RW.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-BLCZ5BSZ.js → disk-cleanup-KSWKI7WB.js} +2 -2
- package/dist-cli/chunks/drivers-EPIEFF7P.js +4 -0
- package/dist-cli/chunks/{film-BJGTBYZB.js → film-GDMR33VO.js} +3 -3
- package/dist-cli/chunks/flow-NKMPBYCJ.js +4 -0
- package/dist-cli/chunks/help-OGCBHOKA.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-ANOYADHM.js → hidden-runtime-alias-S2GTDX3T.js} +2 -2
- package/dist-cli/chunks/home-paths-QRCDLTTV.js +4 -0
- package/dist-cli/chunks/inspect-FUYMOZPY.js +4 -0
- package/dist-cli/chunks/install-desktop-FR6YKW7Y.js +4 -0
- package/dist-cli/chunks/{login-FJ737MWG.js → login-IJAPUZHI.js} +4 -4
- package/dist-cli/chunks/{logout-ZCNMMHMY.js → logout-QMXDFU2X.js} +2 -2
- package/dist-cli/chunks/{maestro-SZTNKLDF.js → maestro-ZXU3YCVX.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-DCFAIZ4H.js → maestro-generate-PYB5QY7K.js} +3 -3
- package/dist-cli/chunks/{mode-GRMQCRXR.js → mode-WGUCL5FZ.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-W36EWFFB.js → optional-demo-registry-WH2O6H36.js} +2 -2
- package/dist-cli/chunks/{perf-QYBAAUZG.js → perf-TOD3UFAH.js} +2 -2
- package/dist-cli/chunks/{permissions-3QCQ6VF4.js → permissions-I5BRJGTB.js} +2 -2
- package/dist-cli/chunks/{record-QPPC2S4E.js → record-ZYL2FYSK.js} +3 -3
- package/dist-cli/chunks/{report-issue-7NMFP4HK.js → report-issue-TAI6DYZO.js} +2 -2
- package/dist-cli/chunks/reset-7YGYKQPQ.js +4 -0
- package/dist-cli/chunks/runtime-B4JO6QRI.js +4 -0
- package/dist-cli/chunks/{screenshot-command-67AECJFB.js → screenshot-command-7ANLODZY.js} +7 -7
- package/dist-cli/chunks/{screenshot-layers-ASWBYPJL.js → screenshot-layers-A7FYXSVU.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-PXA3HFQK.js → screenshots-capture-WT2ZY6CB.js} +2 -2
- package/dist-cli/chunks/serve-TG5WKA4V.js +44 -0
- package/dist-cli/chunks/{setup-7DWPMRSB.js → setup-PCWLD22V.js} +2 -2
- package/dist-cli/chunks/{skills-S3Y22TUA.js → skills-27ZHWCQS.js} +2 -2
- package/dist-cli/chunks/state-ZQVY46ZO.js +14 -0
- package/dist-cli/chunks/{storage-XUIMJWAJ.js → storage-OYC57C4X.js} +6 -6
- package/dist-cli/chunks/store-32HSPZHI.js +4 -0
- package/dist-cli/chunks/telemetry-PBJR7XHR.js +4 -0
- package/dist-cli/chunks/{timeline-TMPLQPSP.js → timeline-RAJJFQT6.js} +2 -2
- package/dist-cli/chunks/{upgrade-7HDSIM7K.js → upgrade-OEFNZRIP.js} +2 -2
- package/dist-cli/chunks/upload-LQJITLKK.js +4 -0
- package/dist-cli/chunks/version-NIXTY6PL.js +6 -0
- package/dist-cli/chunks/{web-DG3WBYD3.js → web-XBUTBVGR.js} +2 -2
- package/dist-cli/chunks/{what-happened-XFVUTZR7.js → what-happened-YNHRFUDX.js} +3 -3
- 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.cjs +20 -0
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +67 -28
- package/dist-lib/host/bridge-host.cjs +140 -12
- 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/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2815 -40
- 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.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +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 +2549 -2061
- package/dist-lib/sdk.mjs +2543 -2061
- package/dist-lib/skills.cjs +480 -280
- package/dist-lib/vite.cjs +1 -1
- package/package.json +8 -2
- package/src/bridge-constants.ts +3 -4
- package/src/bridge-contract.ts +251 -0
- package/src/connect.ts +83 -0
- package/src/disk-cleanup.ts +30 -0
- package/src/home-paths.ts +81 -38
- package/src/host/bridge-host.ts +134 -6
- package/src/index.ts +27 -1
- package/src/sdk.ts +8 -0
- package/src/sim-client.ts +660 -0
- package/dist-cli/chunks/camera-VL73YIKP.js +0 -22
- package/dist-cli/chunks/chunk-4NPPOV2N.js +0 -5
- package/dist-cli/chunks/chunk-FSUYIVJ6.js +0 -9
- package/dist-cli/chunks/chunk-G2WW6L2C.js +0 -23
- package/dist-cli/chunks/chunk-KTHV3RUS.js +0 -26
- package/dist-cli/chunks/chunk-LF2ZVT7O.js +0 -6
- package/dist-cli/chunks/chunk-NFK7T35W.js +0 -4
- package/dist-cli/chunks/chunk-TIVZIMMW.js +0 -4
- package/dist-cli/chunks/cli-version-WWLPBDQ7.js +0 -4
- package/dist-cli/chunks/daemon-G2ME7NLB.js +0 -4
- package/dist-cli/chunks/drivers-LDECZGP2.js +0 -4
- package/dist-cli/chunks/flow-UEQNVTU7.js +0 -4
- package/dist-cli/chunks/help-T5FYSVGB.js +0 -4
- package/dist-cli/chunks/home-paths-GT3LFNOR.js +0 -4
- package/dist-cli/chunks/inspect-ZA6XF5LD.js +0 -4
- package/dist-cli/chunks/install-desktop-TIMUDHPL.js +0 -4
- package/dist-cli/chunks/runtime-XOAXMSTU.js +0 -4
- package/dist-cli/chunks/serve-BI2NBAXG.js +0 -44
- package/dist-cli/chunks/store-JTHEJLAZ.js +0 -4
- package/dist-cli/chunks/telemetry-ZYJGD2DB.js +0 -4
- package/dist-cli/chunks/upload-GMSZPWM6.js +0 -4
- package/dist-cli/chunks/version-HOCHZ37L.js +0 -6
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import {
|
|
2
|
+
callInBridge,
|
|
3
|
+
callInBridgeWrite,
|
|
4
|
+
createBridgeFromParsed,
|
|
5
|
+
parseBridgeCliArgs,
|
|
6
|
+
} from '../ws-bridge'
|
|
7
|
+
import type {
|
|
8
|
+
AppSettingsSnapshot,
|
|
9
|
+
SystemPermissionApp,
|
|
10
|
+
SystemPermissionKind,
|
|
11
|
+
SystemPermissionMutation,
|
|
12
|
+
SystemPermissionStatus,
|
|
13
|
+
} from '@sootsim/globals'
|
|
14
|
+
|
|
15
|
+
interface PermissionsOptions {
|
|
16
|
+
port?: number
|
|
17
|
+
verbose?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const STATUSES: readonly SystemPermissionStatus[] = [
|
|
21
|
+
'not-determined',
|
|
22
|
+
'restricted',
|
|
23
|
+
'denied',
|
|
24
|
+
'authorized',
|
|
25
|
+
'limited',
|
|
26
|
+
'provisional',
|
|
27
|
+
'ephemeral',
|
|
28
|
+
'unavailable',
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const KINDS: readonly SystemPermissionKind[] = [
|
|
32
|
+
'app-tracking-transparency',
|
|
33
|
+
'bluetooth',
|
|
34
|
+
'calendars',
|
|
35
|
+
'camera',
|
|
36
|
+
'contacts',
|
|
37
|
+
'face-id',
|
|
38
|
+
'local-network',
|
|
39
|
+
'location-always',
|
|
40
|
+
'location-when-in-use',
|
|
41
|
+
'media-library',
|
|
42
|
+
'microphone',
|
|
43
|
+
'motion',
|
|
44
|
+
'notifications',
|
|
45
|
+
'photo-library',
|
|
46
|
+
'photo-library-add-only',
|
|
47
|
+
'reminders',
|
|
48
|
+
'siri',
|
|
49
|
+
'speech-recognition',
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
function printHelp(): void {
|
|
53
|
+
console.log(`
|
|
54
|
+
rnxsim permissions — inspect and change simulated operating-system permissions
|
|
55
|
+
|
|
56
|
+
usage:
|
|
57
|
+
rnxsim permissions list [--json]
|
|
58
|
+
rnxsim permissions get <app-id> [--json]
|
|
59
|
+
rnxsim permissions set <app-id> <kind> <status> [--once] [--accuracy full|reduced] [--json]
|
|
60
|
+
rnxsim permissions reset <app-id> [kind] [--json]
|
|
61
|
+
`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function print(value: unknown, json: boolean): void {
|
|
65
|
+
console.log(json ? JSON.stringify(value, null, 2) : value)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function flagValue(args: string[], flag: string): string | undefined {
|
|
69
|
+
const index = args.indexOf(flag)
|
|
70
|
+
return index >= 0 ? args[index + 1] : undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function permissionKind(value: string): SystemPermissionKind | null {
|
|
74
|
+
return KINDS.find((candidate) => candidate === value) ?? null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function permissionStatus(value: string): SystemPermissionStatus | null {
|
|
78
|
+
return STATUSES.find((candidate) => candidate === value) ?? null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function mutationFor(
|
|
82
|
+
status: SystemPermissionStatus,
|
|
83
|
+
once: boolean,
|
|
84
|
+
accuracy: 'full' | 'reduced' | undefined,
|
|
85
|
+
): SystemPermissionMutation {
|
|
86
|
+
switch (status) {
|
|
87
|
+
case 'authorized':
|
|
88
|
+
return {
|
|
89
|
+
status,
|
|
90
|
+
...(once ? { authorizationScope: 'once' } : null),
|
|
91
|
+
...(accuracy ? { locationAccuracy: accuracy } : null),
|
|
92
|
+
}
|
|
93
|
+
case 'not-determined':
|
|
94
|
+
case 'restricted':
|
|
95
|
+
case 'denied':
|
|
96
|
+
case 'limited':
|
|
97
|
+
case 'provisional':
|
|
98
|
+
case 'ephemeral':
|
|
99
|
+
case 'unavailable':
|
|
100
|
+
return { status }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function runPermissions(
|
|
105
|
+
args: string[],
|
|
106
|
+
opts: PermissionsOptions,
|
|
107
|
+
): Promise<number> {
|
|
108
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
109
|
+
printHelp()
|
|
110
|
+
return 0
|
|
111
|
+
}
|
|
112
|
+
const parsed = parseBridgeCliArgs(args, {
|
|
113
|
+
port: opts.port,
|
|
114
|
+
stripBooleanFlags: ['--json', '--once'],
|
|
115
|
+
stripValueFlags: ['--accuracy'],
|
|
116
|
+
})
|
|
117
|
+
const [command, appId, kindValue, statusValue] = parsed.positional
|
|
118
|
+
if (!command) {
|
|
119
|
+
printHelp()
|
|
120
|
+
return 1
|
|
121
|
+
}
|
|
122
|
+
const json = args.includes('--json')
|
|
123
|
+
const bridge = createBridgeFromParsed(parsed)
|
|
124
|
+
try {
|
|
125
|
+
if (command === 'list') {
|
|
126
|
+
const apps = await callInBridge<readonly SystemPermissionApp[]>(
|
|
127
|
+
bridge,
|
|
128
|
+
'SootSim.bridges.test.permissionListApps',
|
|
129
|
+
)
|
|
130
|
+
print(
|
|
131
|
+
json ? apps : apps.map((app) => `${app.appId}\t${app.displayName}`).join('\n'),
|
|
132
|
+
json,
|
|
133
|
+
)
|
|
134
|
+
return 0
|
|
135
|
+
}
|
|
136
|
+
if (!appId) throw new Error(`${command} requires an app id`)
|
|
137
|
+
if (command === 'get') {
|
|
138
|
+
const snapshot = await callInBridge<AppSettingsSnapshot>(
|
|
139
|
+
bridge,
|
|
140
|
+
'SootSim.bridges.test.permissionGetAppSettings',
|
|
141
|
+
appId,
|
|
142
|
+
)
|
|
143
|
+
print(snapshot, json)
|
|
144
|
+
return 0
|
|
145
|
+
}
|
|
146
|
+
if (command === 'reset') {
|
|
147
|
+
if (kindValue) {
|
|
148
|
+
const kind = permissionKind(kindValue)
|
|
149
|
+
if (!kind) throw new Error(`unknown permission kind: ${kindValue}`)
|
|
150
|
+
await callInBridgeWrite<AppSettingsSnapshot>(
|
|
151
|
+
bridge,
|
|
152
|
+
'SootSim.bridges.test.permissionSetAppPermission',
|
|
153
|
+
appId,
|
|
154
|
+
kind,
|
|
155
|
+
{ status: 'not-determined' },
|
|
156
|
+
)
|
|
157
|
+
} else {
|
|
158
|
+
await callInBridgeWrite<void>(
|
|
159
|
+
bridge,
|
|
160
|
+
'SootSim.bridges.test.permissionResetApp',
|
|
161
|
+
appId,
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
const snapshot = await callInBridge<AppSettingsSnapshot>(
|
|
165
|
+
bridge,
|
|
166
|
+
'SootSim.bridges.test.permissionGetAppSettings',
|
|
167
|
+
appId,
|
|
168
|
+
)
|
|
169
|
+
print(snapshot, json)
|
|
170
|
+
return 0
|
|
171
|
+
}
|
|
172
|
+
if (command !== 'set') throw new Error(`unknown permissions command: ${command}`)
|
|
173
|
+
if (!kindValue || !statusValue) {
|
|
174
|
+
throw new Error('set requires an app id, permission kind, and status')
|
|
175
|
+
}
|
|
176
|
+
const kind = permissionKind(kindValue)
|
|
177
|
+
if (!kind) throw new Error(`unknown permission kind: ${kindValue}`)
|
|
178
|
+
const status = permissionStatus(statusValue)
|
|
179
|
+
if (!status) throw new Error(`unknown permission status: ${statusValue}`)
|
|
180
|
+
const accuracyValue = flagValue(args, '--accuracy')
|
|
181
|
+
const accuracy =
|
|
182
|
+
accuracyValue === 'full' || accuracyValue === 'reduced' ? accuracyValue : undefined
|
|
183
|
+
if (accuracyValue && !accuracy) {
|
|
184
|
+
throw new Error(`unknown location accuracy: ${accuracyValue}`)
|
|
185
|
+
}
|
|
186
|
+
const snapshot = await callInBridgeWrite<AppSettingsSnapshot>(
|
|
187
|
+
bridge,
|
|
188
|
+
'SootSim.bridges.test.permissionSetAppPermission',
|
|
189
|
+
appId,
|
|
190
|
+
kind,
|
|
191
|
+
mutationFor(status, args.includes('--once'), accuracy),
|
|
192
|
+
)
|
|
193
|
+
print(snapshot, json)
|
|
194
|
+
return 0
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error(
|
|
197
|
+
` permissions failed: ${error instanceof Error ? error.message : error}`,
|
|
198
|
+
)
|
|
199
|
+
return 1
|
|
200
|
+
} finally {
|
|
201
|
+
bridge.close()
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// sootsim storage profile — manage isolated app storage profiles.
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
clearProfileStorage,
|
|
5
|
+
createProfile,
|
|
6
|
+
deleteProfile,
|
|
7
|
+
ensureProfile,
|
|
8
|
+
listProfiles,
|
|
9
|
+
} from '../../src/profiles'
|
|
10
|
+
|
|
11
|
+
interface ProfileOptions {
|
|
12
|
+
port?: number
|
|
13
|
+
verbose?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function printHelp() {
|
|
17
|
+
console.log(`
|
|
18
|
+
rnxsim storage profile — manage isolated storage profiles
|
|
19
|
+
|
|
20
|
+
usage:
|
|
21
|
+
rnxsim storage profile ls
|
|
22
|
+
rnxsim storage profile create <id>
|
|
23
|
+
rnxsim storage profile clear <id>
|
|
24
|
+
rnxsim storage profile delete <id>
|
|
25
|
+
|
|
26
|
+
profiles isolate cookies, localStorage, IndexedDB, cache, permissions, and
|
|
27
|
+
service workers in Electron and Playwright launches. Plain browser-tab launches
|
|
28
|
+
cannot honor profiles and will fail clearly if a profile is requested.
|
|
29
|
+
|
|
30
|
+
examples:
|
|
31
|
+
rnxsim storage profile ls
|
|
32
|
+
rnxsim storage profile create qa
|
|
33
|
+
rnxsim open 8081 --profile qa
|
|
34
|
+
rnxsim open 8081 --profile qa --driver playwright
|
|
35
|
+
rnxsim storage profile clear qa
|
|
36
|
+
rnxsim storage profile delete qa
|
|
37
|
+
`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function runProfile(args: string[], _opts: ProfileOptions): Promise<number> {
|
|
41
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
42
|
+
printHelp()
|
|
43
|
+
return 0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const subcommand = args[0] ?? 'ls'
|
|
47
|
+
try {
|
|
48
|
+
switch (subcommand) {
|
|
49
|
+
case 'ls':
|
|
50
|
+
case 'list': {
|
|
51
|
+
const profiles = listProfiles()
|
|
52
|
+
for (const profile of profiles) {
|
|
53
|
+
console.log(` ${profile.id}`)
|
|
54
|
+
}
|
|
55
|
+
return 0
|
|
56
|
+
}
|
|
57
|
+
case 'create': {
|
|
58
|
+
const id = args[1]
|
|
59
|
+
if (!id) {
|
|
60
|
+
console.error(' profile create expects <id>')
|
|
61
|
+
return 1
|
|
62
|
+
}
|
|
63
|
+
const profile = createProfile(id)
|
|
64
|
+
console.log(` created profile: ${profile.id}`)
|
|
65
|
+
return 0
|
|
66
|
+
}
|
|
67
|
+
case 'ensure': {
|
|
68
|
+
const id = args[1]
|
|
69
|
+
if (!id) {
|
|
70
|
+
console.error(' profile ensure expects <id>')
|
|
71
|
+
return 1
|
|
72
|
+
}
|
|
73
|
+
const profile = ensureProfile(id)
|
|
74
|
+
console.log(` profile: ${profile.id}`)
|
|
75
|
+
return 0
|
|
76
|
+
}
|
|
77
|
+
case 'clear': {
|
|
78
|
+
const id = args[1]
|
|
79
|
+
if (!id) {
|
|
80
|
+
console.error(' profile clear expects <id>')
|
|
81
|
+
return 1
|
|
82
|
+
}
|
|
83
|
+
ensureProfile(id)
|
|
84
|
+
clearProfileStorage(id)
|
|
85
|
+
console.log(` cleared profile: ${id}`)
|
|
86
|
+
return 0
|
|
87
|
+
}
|
|
88
|
+
case 'delete':
|
|
89
|
+
case 'rm': {
|
|
90
|
+
const id = args[1]
|
|
91
|
+
if (!id) {
|
|
92
|
+
console.error(' profile delete expects <id>')
|
|
93
|
+
return 1
|
|
94
|
+
}
|
|
95
|
+
const profile = deleteProfile(id)
|
|
96
|
+
console.log(` deleted profile: ${profile.id}`)
|
|
97
|
+
return 0
|
|
98
|
+
}
|
|
99
|
+
default:
|
|
100
|
+
console.error(` unknown profile command: ${subcommand}`)
|
|
101
|
+
printHelp()
|
|
102
|
+
return 1
|
|
103
|
+
}
|
|
104
|
+
} catch (err) {
|
|
105
|
+
console.error(` profile failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
106
|
+
return 1
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import {
|
|
2
|
+
callInBridge,
|
|
3
|
+
callInBridgeWrite,
|
|
4
|
+
createBridgeFromParsed,
|
|
5
|
+
parseBridgeCliArgs,
|
|
6
|
+
} from '../ws-bridge'
|
|
7
|
+
|
|
8
|
+
interface ReactOptions {
|
|
9
|
+
port?: number
|
|
10
|
+
verbose?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface SlowRow {
|
|
14
|
+
displayName: string
|
|
15
|
+
totalMs: number
|
|
16
|
+
avgMs: number
|
|
17
|
+
commitCount: number
|
|
18
|
+
slowestCommit: number
|
|
19
|
+
slowestMs: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface RerenderRow {
|
|
23
|
+
displayName: string
|
|
24
|
+
count: number
|
|
25
|
+
renders?: number
|
|
26
|
+
causes: Record<string, number>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface TreeRow {
|
|
30
|
+
id: number
|
|
31
|
+
displayName: string
|
|
32
|
+
kind: string
|
|
33
|
+
depth: number
|
|
34
|
+
childCount: number
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function printHelp() {
|
|
38
|
+
console.log(`
|
|
39
|
+
rnxsim perf react — inspect React component render cost in the tenant worker
|
|
40
|
+
|
|
41
|
+
usage:
|
|
42
|
+
rnxsim perf react profile start [--include-props] [--max-commits N]
|
|
43
|
+
rnxsim perf react profile stop
|
|
44
|
+
rnxsim perf react summary [--limit 10] [--json]
|
|
45
|
+
rnxsim perf react slow [--limit 5] [--json]
|
|
46
|
+
rnxsim perf react rerenders [--limit 5] [--json]
|
|
47
|
+
rnxsim perf react tree [--depth 3] [--find <name>] [--json]
|
|
48
|
+
rnxsim perf react why <fiber-id> [--json]
|
|
49
|
+
|
|
50
|
+
\`react summary\` is the demo-friendly shortcut: it runs both slow and
|
|
51
|
+
rerenders in one round-trip, prints them as a single table per side,
|
|
52
|
+
and surfaces the duration-zero warning prominently when the bundle is
|
|
53
|
+
running without React profiler timers.
|
|
54
|
+
|
|
55
|
+
examples:
|
|
56
|
+
rnxsim perf react profile start
|
|
57
|
+
rnxsim do tap-text Inbox
|
|
58
|
+
rnxsim perf react profile stop
|
|
59
|
+
rnxsim perf react summary --limit 10
|
|
60
|
+
rnxsim perf react slow --limit 10
|
|
61
|
+
rnxsim perf react rerenders --json
|
|
62
|
+
`)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function valueOf(args: string[], flag: string): string | undefined {
|
|
66
|
+
const idx = args.indexOf(flag)
|
|
67
|
+
if (idx >= 0 && idx + 1 < args.length) return args[idx + 1]
|
|
68
|
+
const prefix = `${flag}=`
|
|
69
|
+
const found = args.find((arg) => arg.startsWith(prefix))
|
|
70
|
+
return found ? found.slice(prefix.length) : undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function numberFlag(args: string[], flag: string, fallback: number): number {
|
|
74
|
+
const raw = valueOf(args, flag)
|
|
75
|
+
if (raw === undefined) return fallback
|
|
76
|
+
const value = Number(raw)
|
|
77
|
+
return Number.isFinite(value) && value > 0 ? Math.round(value) : fallback
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function formatTable(headers: string[], rows: string[][]): string {
|
|
81
|
+
const widths = headers.map((h, i) =>
|
|
82
|
+
Math.max(h.length, ...rows.map((row) => row[i]?.length ?? 0)),
|
|
83
|
+
)
|
|
84
|
+
const line = (cells: string[]) =>
|
|
85
|
+
cells
|
|
86
|
+
.map((cell, i) => cell.padEnd(widths[i]))
|
|
87
|
+
.join(' ')
|
|
88
|
+
.trimEnd()
|
|
89
|
+
return [
|
|
90
|
+
line(headers),
|
|
91
|
+
line(headers.map((h) => '-'.repeat(h.length))),
|
|
92
|
+
...rows.map(line),
|
|
93
|
+
]
|
|
94
|
+
.map((row) => ` ${row}`)
|
|
95
|
+
.join('\n')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function printJson(value: unknown) {
|
|
99
|
+
console.log(JSON.stringify(value, null, 2))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function printSlow(result: {
|
|
103
|
+
rows?: SlowRow[]
|
|
104
|
+
commits?: number
|
|
105
|
+
error?: string
|
|
106
|
+
durationWarning?: string
|
|
107
|
+
}) {
|
|
108
|
+
if (result.error) console.error(` warning: ${result.error}`)
|
|
109
|
+
if (result.durationWarning) console.error(` warning: ${result.durationWarning}`)
|
|
110
|
+
const rows = result.rows ?? []
|
|
111
|
+
if (rows.length === 0) {
|
|
112
|
+
console.log(` no React render samples yet (${result.commits ?? 0} commit(s))`)
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
console.log(
|
|
116
|
+
formatTable(
|
|
117
|
+
['component', 'total', 'avg', 'commits', 'slowest'],
|
|
118
|
+
rows.map((row) => [
|
|
119
|
+
row.displayName,
|
|
120
|
+
`${row.totalMs.toFixed(2)}ms`,
|
|
121
|
+
`${row.avgMs.toFixed(2)}ms`,
|
|
122
|
+
String(row.commitCount),
|
|
123
|
+
`#${row.slowestCommit} ${row.slowestMs.toFixed(2)}ms`,
|
|
124
|
+
]),
|
|
125
|
+
),
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function printRerenders(result: {
|
|
130
|
+
rows?: RerenderRow[]
|
|
131
|
+
commits?: number
|
|
132
|
+
error?: string
|
|
133
|
+
}) {
|
|
134
|
+
if (result.error) console.error(` warning: ${result.error}`)
|
|
135
|
+
const rows = result.rows ?? []
|
|
136
|
+
if (rows.length === 0) {
|
|
137
|
+
console.log(` no React render samples yet (${result.commits ?? 0} commit(s))`)
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
console.log(
|
|
141
|
+
formatTable(
|
|
142
|
+
['component', 'renders', 'causes'],
|
|
143
|
+
rows.map((row) => {
|
|
144
|
+
const causes = Object.entries(row.causes ?? {})
|
|
145
|
+
.filter(([, count]) => count > 0)
|
|
146
|
+
.sort((a, b) => b[1] - a[1])
|
|
147
|
+
.slice(0, 4)
|
|
148
|
+
.map(([cause, count]) => `${cause}:${count}`)
|
|
149
|
+
.join(', ')
|
|
150
|
+
return [row.displayName, String(row.renders ?? row.count), causes || '-']
|
|
151
|
+
}),
|
|
152
|
+
),
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function printTree(result: { rows?: TreeRow[]; roots?: number; error?: string }) {
|
|
157
|
+
if (result.error) console.error(` warning: ${result.error}`)
|
|
158
|
+
const rows = result.rows ?? []
|
|
159
|
+
if (rows.length === 0) {
|
|
160
|
+
console.log(` no React tree data yet (${result.roots ?? 0} root(s))`)
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
for (const row of rows) {
|
|
164
|
+
const indent = ' '.repeat(row.depth)
|
|
165
|
+
console.log(
|
|
166
|
+
` ${indent}@${row.id} ${row.displayName} [${row.kind}] children=${row.childCount}`,
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function printWhy(result: { sample?: any; error?: string }) {
|
|
172
|
+
if (result.error) {
|
|
173
|
+
console.error(` ${result.error}`)
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
const sample = result.sample
|
|
177
|
+
if (!sample) {
|
|
178
|
+
console.log(' no sample')
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
console.log(` @${sample.fiberId} ${sample.displayName}`)
|
|
182
|
+
console.log(` duration: ${Number(sample.actualDuration ?? 0).toFixed(2)}ms`)
|
|
183
|
+
console.log(` causes: ${(sample.causes ?? []).join(', ') || '-'}`)
|
|
184
|
+
if (sample.propDiffs?.length) {
|
|
185
|
+
console.log(' props:')
|
|
186
|
+
for (const diff of sample.propDiffs) {
|
|
187
|
+
const values =
|
|
188
|
+
'old' in diff || 'new' in diff
|
|
189
|
+
? ` ${JSON.stringify(diff.old)} → ${JSON.stringify(diff.new)}`
|
|
190
|
+
: ''
|
|
191
|
+
console.log(` ${diff.key}${values}`)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (sample.parentChain?.length) {
|
|
195
|
+
console.log(` parents: ${sample.parentChain.join(' ← ')}`)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export async function runReact(args: string[], opts: ReactOptions): Promise<number> {
|
|
200
|
+
const parsed = parseBridgeCliArgs(args, {
|
|
201
|
+
port: opts.port,
|
|
202
|
+
stripBooleanFlags: ['--json', '--include-props', '--help', '-h'],
|
|
203
|
+
stripValueFlags: ['--limit', '--depth', '--find', '--max-commits'],
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
207
|
+
printHelp()
|
|
208
|
+
return 0
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const [first, second] = parsed.positional
|
|
212
|
+
const json = args.includes('--json')
|
|
213
|
+
const bridge = createBridgeFromParsed(parsed)
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
if (first === 'profile' && second === 'start') {
|
|
217
|
+
const result = await callInBridgeWrite(
|
|
218
|
+
bridge,
|
|
219
|
+
'SootSim.bridges.reactProfile.start',
|
|
220
|
+
{
|
|
221
|
+
includeProps: args.includes('--include-props'),
|
|
222
|
+
maxCommits: numberFlag(args, '--max-commits', 2000),
|
|
223
|
+
},
|
|
224
|
+
)
|
|
225
|
+
if (json) printJson(result)
|
|
226
|
+
else console.log(' React profile started')
|
|
227
|
+
return 0
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (first === 'profile' && second === 'stop') {
|
|
231
|
+
const result = (await callInBridgeWrite(
|
|
232
|
+
bridge,
|
|
233
|
+
'SootSim.bridges.reactProfile.stop',
|
|
234
|
+
)) as { commits?: number; error?: string }
|
|
235
|
+
if (json) printJson(result)
|
|
236
|
+
else {
|
|
237
|
+
console.log(` React profile stopped (${result.commits ?? 0} commit(s))`)
|
|
238
|
+
if (result.error) console.error(` warning: ${result.error}`)
|
|
239
|
+
}
|
|
240
|
+
return result.error ? 1 : 0
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (first === 'summary') {
|
|
244
|
+
// run slow + rerenders in parallel against the existing bridge.
|
|
245
|
+
// demo-friendly: one command, one table per dimension, plus a
|
|
246
|
+
// single duration-zero warning that's easy to call out on stage.
|
|
247
|
+
const limit = numberFlag(args, '--limit', 10)
|
|
248
|
+
const [slowResult, rerendersResult] = (await Promise.all([
|
|
249
|
+
callInBridge(bridge, 'SootSim.bridges.reactProfile.slow', { limit }),
|
|
250
|
+
callInBridge(bridge, 'SootSim.bridges.reactProfile.rerenders', { limit }),
|
|
251
|
+
])) as [
|
|
252
|
+
{
|
|
253
|
+
rows?: SlowRow[]
|
|
254
|
+
commits?: number
|
|
255
|
+
error?: string
|
|
256
|
+
durationWarning?: string
|
|
257
|
+
},
|
|
258
|
+
{ rows?: RerenderRow[]; commits?: number; error?: string },
|
|
259
|
+
]
|
|
260
|
+
if (json) {
|
|
261
|
+
printJson({
|
|
262
|
+
commits: slowResult.commits ?? rerendersResult.commits ?? 0,
|
|
263
|
+
slow: slowResult,
|
|
264
|
+
rerenders: rerendersResult,
|
|
265
|
+
})
|
|
266
|
+
return 0
|
|
267
|
+
}
|
|
268
|
+
const commits = slowResult.commits ?? rerendersResult.commits ?? 0
|
|
269
|
+
console.log(` React profile summary (${commits} commit(s)):`)
|
|
270
|
+
if (slowResult.error) console.error(` warning: ${slowResult.error}`)
|
|
271
|
+
if (slowResult.durationWarning) {
|
|
272
|
+
console.error(` warning: ${slowResult.durationWarning}`)
|
|
273
|
+
}
|
|
274
|
+
if (rerendersResult.error) {
|
|
275
|
+
console.error(` warning: ${rerendersResult.error}`)
|
|
276
|
+
}
|
|
277
|
+
console.log('\n slowest renders:')
|
|
278
|
+
printSlow(slowResult)
|
|
279
|
+
console.log('\n most rerenders:')
|
|
280
|
+
printRerenders(rerendersResult)
|
|
281
|
+
// hint about the actualDuration-zero limitation when the slow
|
|
282
|
+
// table is empty/zero — the demo-stage signal is "no timer
|
|
283
|
+
// data, expect rerenders rows only".
|
|
284
|
+
const slowestRow = slowResult.rows?.[0]
|
|
285
|
+
const allZero =
|
|
286
|
+
slowResult.rows && slowResult.rows.length > 0
|
|
287
|
+
? slowResult.rows.every((r) => r.totalMs <= 0 && r.slowestMs <= 0)
|
|
288
|
+
: false
|
|
289
|
+
if (allZero && !slowResult.durationWarning) {
|
|
290
|
+
console.error(
|
|
291
|
+
`\n warning: every commit reports actualDuration=0ms — the React profiler timer is disabled in this bundle (rerender counts are still accurate; ${slowestRow?.displayName ? `top-listed: ${slowestRow.displayName}` : 'no slow signal'}).`,
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
return 0
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (first === 'slow') {
|
|
298
|
+
const result = (await callInBridge(bridge, 'SootSim.bridges.reactProfile.slow', {
|
|
299
|
+
limit: numberFlag(args, '--limit', 10),
|
|
300
|
+
})) as {
|
|
301
|
+
rows?: SlowRow[]
|
|
302
|
+
commits?: number
|
|
303
|
+
error?: string
|
|
304
|
+
durationWarning?: string
|
|
305
|
+
}
|
|
306
|
+
if (json) printJson(result)
|
|
307
|
+
else printSlow(result)
|
|
308
|
+
return 0
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (first === 'rerenders') {
|
|
312
|
+
const result = (await callInBridge(
|
|
313
|
+
bridge,
|
|
314
|
+
'SootSim.bridges.reactProfile.rerenders',
|
|
315
|
+
{ limit: numberFlag(args, '--limit', 10) },
|
|
316
|
+
)) as { rows?: RerenderRow[]; commits?: number; error?: string }
|
|
317
|
+
if (json) printJson(result)
|
|
318
|
+
else printRerenders(result)
|
|
319
|
+
return 0
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (first === 'tree') {
|
|
323
|
+
const result = (await callInBridge(bridge, 'SootSim.bridges.reactProfile.tree', {
|
|
324
|
+
depth: numberFlag(args, '--depth', 3),
|
|
325
|
+
find: valueOf(args, '--find'),
|
|
326
|
+
})) as { rows?: TreeRow[]; roots?: number; error?: string }
|
|
327
|
+
if (json) printJson(result)
|
|
328
|
+
else printTree(result)
|
|
329
|
+
return 0
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (first === 'why') {
|
|
333
|
+
const fiberId = Number(second)
|
|
334
|
+
if (!Number.isFinite(fiberId) || fiberId <= 0) {
|
|
335
|
+
console.error(' usage: rnxsim perf react why <fiber-id>')
|
|
336
|
+
return 1
|
|
337
|
+
}
|
|
338
|
+
const result = (await callInBridge(
|
|
339
|
+
bridge,
|
|
340
|
+
'SootSim.bridges.reactProfile.why',
|
|
341
|
+
Math.round(fiberId),
|
|
342
|
+
)) as { sample?: unknown; error?: string }
|
|
343
|
+
if (json) printJson(result)
|
|
344
|
+
else printWhy(result)
|
|
345
|
+
return result.error ? 1 : 0
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
printHelp()
|
|
349
|
+
return first ? 1 : 0
|
|
350
|
+
} finally {
|
|
351
|
+
bridge.close()
|
|
352
|
+
}
|
|
353
|
+
}
|