rnxsim 0.1.403 → 0.1.405
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 +17 -4
- 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 +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +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 +1 -1
- package/dist-lib/host/bridge-host.cjs +1 -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 +30 -6
- 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-fingerprint-registry.cjs +186 -0
- package/dist-lib/metro-fingerprint-registry.mjs +156 -0
- package/dist-lib/metro-production-bundle.cjs +66 -17
- package/dist-lib/metro-production-bundle.mjs +62 -15
- package/dist-lib/metro.cjs +30 -6
- 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 +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +56 -24
- package/dist-lib/vite.cjs +1 -1
- package/package.json +8 -1
- package/src/metro-fingerprint-registry.ts +302 -0
- package/src/metro-plugin.ts +47 -4
- package/src/metro-production-bundle.ts +94 -16
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.405 | (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;
|
|
@@ -1347,23 +1347,35 @@ var init_supported_native_packages = __esm({
|
|
|
1347
1347
|
"expo-apple-authentication",
|
|
1348
1348
|
// preset
|
|
1349
1349
|
"expo-application",
|
|
1350
|
-
// coverage
|
|
1350
|
+
// visual-proof+coverage
|
|
1351
1351
|
"expo-asset",
|
|
1352
1352
|
// preset+coverage
|
|
1353
1353
|
"expo-audio",
|
|
1354
1354
|
// coverage
|
|
1355
1355
|
"expo-av",
|
|
1356
1356
|
// coverage
|
|
1357
|
+
"expo-background-fetch",
|
|
1358
|
+
// visual-proof
|
|
1359
|
+
"expo-background-task",
|
|
1360
|
+
// visual-proof
|
|
1357
1361
|
"expo-battery",
|
|
1358
|
-
// coverage
|
|
1362
|
+
// visual-proof+coverage
|
|
1359
1363
|
"expo-blur",
|
|
1360
1364
|
// preset+coverage
|
|
1365
|
+
"expo-brightness",
|
|
1366
|
+
// visual-proof
|
|
1367
|
+
"expo-calendar",
|
|
1368
|
+
// visual-proof
|
|
1361
1369
|
"expo-camera",
|
|
1362
1370
|
// coverage
|
|
1371
|
+
"expo-cellular",
|
|
1372
|
+
// visual-proof
|
|
1363
1373
|
"expo-clipboard",
|
|
1364
1374
|
// preset+coverage
|
|
1365
1375
|
"expo-constants",
|
|
1366
|
-
// preset+coverage
|
|
1376
|
+
// preset+visual-proof+coverage
|
|
1377
|
+
"expo-contacts",
|
|
1378
|
+
// visual-proof
|
|
1367
1379
|
"expo-crypto",
|
|
1368
1380
|
// preset+coverage
|
|
1369
1381
|
"expo-dev-client",
|
|
@@ -1385,23 +1397,27 @@ var init_supported_native_packages = __esm({
|
|
|
1385
1397
|
"expo-ignore-battery-optimizations",
|
|
1386
1398
|
// coverage
|
|
1387
1399
|
"expo-image",
|
|
1388
|
-
// preset+coverage
|
|
1400
|
+
// preset+visual-proof+coverage
|
|
1389
1401
|
"expo-image-manipulator",
|
|
1390
1402
|
// coverage
|
|
1391
1403
|
"expo-image-picker",
|
|
1392
1404
|
// preset+coverage
|
|
1393
1405
|
"expo-insights",
|
|
1394
1406
|
// coverage
|
|
1407
|
+
"expo-intent-launcher",
|
|
1408
|
+
// visual-proof
|
|
1395
1409
|
"expo-keep-awake",
|
|
1396
1410
|
// coverage
|
|
1397
1411
|
"expo-linear-gradient",
|
|
1398
|
-
// preset+coverage
|
|
1412
|
+
// preset+visual-proof+coverage
|
|
1399
1413
|
"expo-linking",
|
|
1400
1414
|
// preset+coverage
|
|
1401
1415
|
"expo-local-authentication",
|
|
1402
1416
|
// coverage
|
|
1403
1417
|
"expo-localization",
|
|
1404
1418
|
// coverage
|
|
1419
|
+
"expo-mail-composer",
|
|
1420
|
+
// visual-proof
|
|
1405
1421
|
"expo-media-library",
|
|
1406
1422
|
// coverage
|
|
1407
1423
|
"expo-mesh-gradient",
|
|
@@ -1409,35 +1425,51 @@ var init_supported_native_packages = __esm({
|
|
|
1409
1425
|
"expo-modules-core",
|
|
1410
1426
|
// preset
|
|
1411
1427
|
"expo-network",
|
|
1412
|
-
// preset+coverage
|
|
1428
|
+
// preset+visual-proof+coverage
|
|
1413
1429
|
"expo-notifications",
|
|
1414
1430
|
// preset+coverage
|
|
1431
|
+
"expo-print",
|
|
1432
|
+
// visual-proof
|
|
1433
|
+
"expo-screen-capture",
|
|
1434
|
+
// visual-proof
|
|
1415
1435
|
"expo-screen-corner-radius",
|
|
1416
1436
|
// coverage
|
|
1417
1437
|
"expo-screen-orientation",
|
|
1418
|
-
// coverage
|
|
1438
|
+
// visual-proof+coverage
|
|
1419
1439
|
"expo-secure-store",
|
|
1420
|
-
// coverage
|
|
1440
|
+
// visual-proof+coverage
|
|
1441
|
+
"expo-sensors",
|
|
1442
|
+
// visual-proof
|
|
1443
|
+
"expo-sharing",
|
|
1444
|
+
// visual-proof
|
|
1445
|
+
"expo-sms",
|
|
1446
|
+
// visual-proof
|
|
1447
|
+
"expo-speech",
|
|
1448
|
+
// visual-proof
|
|
1421
1449
|
"expo-speech-recognition",
|
|
1422
1450
|
// preset
|
|
1423
1451
|
"expo-splash-screen",
|
|
1424
|
-
// coverage
|
|
1452
|
+
// visual-proof+coverage
|
|
1425
1453
|
"expo-sqlite",
|
|
1426
1454
|
// preset+coverage
|
|
1427
1455
|
"expo-store-review",
|
|
1428
|
-
// coverage
|
|
1456
|
+
// visual-proof+coverage
|
|
1429
1457
|
"expo-symbols",
|
|
1430
1458
|
// coverage
|
|
1431
1459
|
"expo-system-ui",
|
|
1432
1460
|
// coverage
|
|
1433
1461
|
"expo-task-manager",
|
|
1434
|
-
// coverage
|
|
1462
|
+
// visual-proof+coverage
|
|
1435
1463
|
"expo-testflight",
|
|
1436
1464
|
// coverage
|
|
1437
1465
|
"expo-tracking-transparency",
|
|
1438
|
-
// coverage
|
|
1466
|
+
// visual-proof+coverage
|
|
1439
1467
|
"expo-updates",
|
|
1440
1468
|
// preset+coverage
|
|
1469
|
+
"expo-video",
|
|
1470
|
+
// visual-proof
|
|
1471
|
+
"expo-video-thumbnails",
|
|
1472
|
+
// visual-proof
|
|
1441
1473
|
"expo-web-browser",
|
|
1442
1474
|
// preset
|
|
1443
1475
|
"expo-winter-fetch",
|
|
@@ -1461,7 +1493,7 @@ var init_supported_native_packages = __esm({
|
|
|
1461
1493
|
"posthog-react-native-session-replay",
|
|
1462
1494
|
// preset+coverage
|
|
1463
1495
|
"react-native",
|
|
1464
|
-
// preset+coverage
|
|
1496
|
+
// preset+visual-proof+coverage
|
|
1465
1497
|
"react-native-actions-shortcuts",
|
|
1466
1498
|
// coverage
|
|
1467
1499
|
"react-native-adjust",
|
|
@@ -1485,7 +1517,7 @@ var init_supported_native_packages = __esm({
|
|
|
1485
1517
|
"react-native-bootsplash",
|
|
1486
1518
|
// preset+coverage
|
|
1487
1519
|
"react-native-bottom-tabs",
|
|
1488
|
-
// preset
|
|
1520
|
+
// preset+visual-proof
|
|
1489
1521
|
"react-native-branch",
|
|
1490
1522
|
// coverage
|
|
1491
1523
|
"react-native-config",
|
|
@@ -1507,7 +1539,7 @@ var init_supported_native_packages = __esm({
|
|
|
1507
1539
|
"react-native-fs",
|
|
1508
1540
|
// coverage
|
|
1509
1541
|
"react-native-gesture-handler",
|
|
1510
|
-
// preset+coverage
|
|
1542
|
+
// preset+visual-proof+coverage
|
|
1511
1543
|
"react-native-get-device-locale",
|
|
1512
1544
|
// coverage
|
|
1513
1545
|
"react-native-get-location",
|
|
@@ -1535,7 +1567,7 @@ var init_supported_native_packages = __esm({
|
|
|
1535
1567
|
"react-native-key-command",
|
|
1536
1568
|
// coverage
|
|
1537
1569
|
"react-native-keyboard-controller",
|
|
1538
|
-
// preset
|
|
1570
|
+
// preset+visual-proof
|
|
1539
1571
|
"react-native-keychain",
|
|
1540
1572
|
// coverage
|
|
1541
1573
|
"react-native-keys",
|
|
@@ -1565,7 +1597,7 @@ var init_supported_native_packages = __esm({
|
|
|
1565
1597
|
"react-native-notification-badge",
|
|
1566
1598
|
// coverage
|
|
1567
1599
|
"react-native-pager-view",
|
|
1568
|
-
// preset
|
|
1600
|
+
// preset+visual-proof
|
|
1569
1601
|
"react-native-pdf",
|
|
1570
1602
|
// coverage
|
|
1571
1603
|
"react-native-permissions",
|
|
@@ -1585,7 +1617,7 @@ var init_supported_native_packages = __esm({
|
|
|
1585
1617
|
"react-native-randombytes",
|
|
1586
1618
|
// coverage
|
|
1587
1619
|
"react-native-reanimated",
|
|
1588
|
-
// preset+coverage
|
|
1620
|
+
// preset+visual-proof+coverage
|
|
1589
1621
|
"react-native-restart",
|
|
1590
1622
|
// coverage
|
|
1591
1623
|
"react-native-restart-newarch",
|
|
@@ -1593,11 +1625,11 @@ var init_supported_native_packages = __esm({
|
|
|
1593
1625
|
"react-native-rsa-signer",
|
|
1594
1626
|
// coverage
|
|
1595
1627
|
"react-native-safe-area-context",
|
|
1596
|
-
// preset+coverage
|
|
1628
|
+
// preset+visual-proof+coverage
|
|
1597
1629
|
"react-native-screen-corner-radius",
|
|
1598
1630
|
// coverage
|
|
1599
1631
|
"react-native-screens",
|
|
1600
|
-
// preset+coverage
|
|
1632
|
+
// preset+visual-proof+coverage
|
|
1601
1633
|
"react-native-securerandom",
|
|
1602
1634
|
// coverage
|
|
1603
1635
|
"react-native-settings",
|
|
@@ -1613,7 +1645,7 @@ var init_supported_native_packages = __esm({
|
|
|
1613
1645
|
"react-native-splash-screen",
|
|
1614
1646
|
// coverage
|
|
1615
1647
|
"react-native-svg",
|
|
1616
|
-
// preset
|
|
1648
|
+
// preset+visual-proof
|
|
1617
1649
|
"react-native-system-bars",
|
|
1618
1650
|
// coverage
|
|
1619
1651
|
"react-native-teleport",
|
|
@@ -1627,7 +1659,7 @@ var init_supported_native_packages = __esm({
|
|
|
1627
1659
|
"react-native-turbo-haptics",
|
|
1628
1660
|
// coverage
|
|
1629
1661
|
"react-native-uitextview",
|
|
1630
|
-
// coverage
|
|
1662
|
+
// visual-proof+coverage
|
|
1631
1663
|
"react-native-ulid-jsi",
|
|
1632
1664
|
// coverage
|
|
1633
1665
|
"react-native-ux-cam",
|
|
@@ -1647,7 +1679,7 @@ var init_supported_native_packages = __esm({
|
|
|
1647
1679
|
"react-native-webp-format",
|
|
1648
1680
|
// coverage
|
|
1649
1681
|
"react-native-webview",
|
|
1650
|
-
// preset
|
|
1682
|
+
// preset+visual-proof
|
|
1651
1683
|
"react-native-worklets",
|
|
1652
1684
|
// preset+coverage
|
|
1653
1685
|
"react-native-xxhash",
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.405 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rnxsim",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.405",
|
|
4
4
|
"description": "Vite and Metro plugins, testing drivers, and SDK exports for rnx.",
|
|
5
5
|
"author": "Tamagui LLC",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -45,6 +45,13 @@
|
|
|
45
45
|
"import": "./dist-lib/metro-production-bundle.mjs",
|
|
46
46
|
"default": "./dist-lib/metro-production-bundle.cjs"
|
|
47
47
|
},
|
|
48
|
+
"./metro-fingerprint-registry": {
|
|
49
|
+
"types": "./src/metro-fingerprint-registry.ts",
|
|
50
|
+
"source": "./src/metro-fingerprint-registry.ts",
|
|
51
|
+
"bun": "./src/metro-fingerprint-registry.ts",
|
|
52
|
+
"import": "./dist-lib/metro-fingerprint-registry.mjs",
|
|
53
|
+
"default": "./dist-lib/metro-fingerprint-registry.cjs"
|
|
54
|
+
},
|
|
48
55
|
"./react-native-host-modules": {
|
|
49
56
|
"types": "./src/react-native-host-modules.ts",
|
|
50
57
|
"source": "./src/react-native-host-modules.ts",
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
export const RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2
|
|
2
|
+
export const RNX_METRO_FINGERPRINT_POINTER_PATH = '/compile/metro-fingerprints.json'
|
|
3
|
+
export const RNX_METRO_FINGERPRINT_MAX_POINTER_BYTES = 16 * 1024
|
|
4
|
+
export const RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES = 8 * 1024 * 1024
|
|
5
|
+
|
|
6
|
+
export type RNXMetroFingerprintPlatform = 'ios' | 'android'
|
|
7
|
+
|
|
8
|
+
export interface RNXMetroFingerprintAtom {
|
|
9
|
+
key: string
|
|
10
|
+
exports: string[]
|
|
11
|
+
literals: string[]
|
|
12
|
+
dependencyArity: number
|
|
13
|
+
factoryDigest: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface RNXMetroFingerprintNode {
|
|
17
|
+
atom: number
|
|
18
|
+
internalDependencies: Array<{ position: number; node: number }>
|
|
19
|
+
landmarkPath?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface RNXMetroFingerprintRoot {
|
|
23
|
+
node: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface RNXMetroFingerprintTemplate {
|
|
27
|
+
packageName: string
|
|
28
|
+
packageVersion: string
|
|
29
|
+
sourceIntegrity: string
|
|
30
|
+
profile: string
|
|
31
|
+
platform: RNXMetroFingerprintPlatform
|
|
32
|
+
nodes: RNXMetroFingerprintNode[]
|
|
33
|
+
roots: RNXMetroFingerprintRoot[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface RNXMetroFingerprintCandidate {
|
|
37
|
+
template: number
|
|
38
|
+
root: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface RNXMetroFingerprintRegistry {
|
|
42
|
+
schemaVersion: typeof RNX_METRO_FINGERPRINT_SCHEMA_VERSION
|
|
43
|
+
revision: string
|
|
44
|
+
atoms: RNXMetroFingerprintAtom[]
|
|
45
|
+
templates: RNXMetroFingerprintTemplate[]
|
|
46
|
+
candidatesByFactoryDigest: Record<string, RNXMetroFingerprintCandidate[]>
|
|
47
|
+
candidatesByDiscriminator: Record<string, RNXMetroFingerprintCandidate[]>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface RNXMetroFingerprintPointer {
|
|
51
|
+
schemaVersion: typeof RNX_METRO_FINGERPRINT_SCHEMA_VERSION
|
|
52
|
+
revision: string
|
|
53
|
+
integrity: string
|
|
54
|
+
bytes: number
|
|
55
|
+
payloadUrl: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
59
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isSha256(value: unknown): value is string {
|
|
63
|
+
return typeof value === 'string' && /^[a-f0-9]{64}$/.test(value)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function readStringArray(value: unknown): string[] | null {
|
|
67
|
+
if (!Array.isArray(value) || !value.every((entry) => typeof entry === 'string')) {
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
const entries = [...value]
|
|
71
|
+
if (
|
|
72
|
+
new Set(entries).size !== entries.length ||
|
|
73
|
+
entries.some((entry, index) => index > 0 && entries[index - 1] >= entry)
|
|
74
|
+
) {
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
return entries
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function parseRNXMetroFingerprintPointer(
|
|
81
|
+
value: unknown,
|
|
82
|
+
): RNXMetroFingerprintPointer | null {
|
|
83
|
+
if (!isRecord(value)) return null
|
|
84
|
+
const { schemaVersion, revision, integrity, bytes, payloadUrl } = value
|
|
85
|
+
if (
|
|
86
|
+
schemaVersion !== RNX_METRO_FINGERPRINT_SCHEMA_VERSION ||
|
|
87
|
+
!isSha256(revision) ||
|
|
88
|
+
!isSha256(integrity) ||
|
|
89
|
+
typeof bytes !== 'number' ||
|
|
90
|
+
!Number.isSafeInteger(bytes) ||
|
|
91
|
+
bytes < 1 ||
|
|
92
|
+
typeof payloadUrl !== 'string' ||
|
|
93
|
+
payloadUrl.length === 0
|
|
94
|
+
) {
|
|
95
|
+
return null
|
|
96
|
+
}
|
|
97
|
+
return { schemaVersion, revision, integrity, bytes, payloadUrl }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function parseRNXMetroFingerprintRegistry(
|
|
101
|
+
value: unknown,
|
|
102
|
+
): RNXMetroFingerprintRegistry | null {
|
|
103
|
+
if (!isRecord(value)) return null
|
|
104
|
+
const { schemaVersion, revision } = value
|
|
105
|
+
if (
|
|
106
|
+
schemaVersion !== RNX_METRO_FINGERPRINT_SCHEMA_VERSION ||
|
|
107
|
+
!isSha256(revision) ||
|
|
108
|
+
!Array.isArray(value.atoms) ||
|
|
109
|
+
!Array.isArray(value.templates) ||
|
|
110
|
+
!isRecord(value.candidatesByFactoryDigest) ||
|
|
111
|
+
!isRecord(value.candidatesByDiscriminator)
|
|
112
|
+
) {
|
|
113
|
+
return null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const atoms: RNXMetroFingerprintAtom[] = []
|
|
117
|
+
for (const atomValue of value.atoms) {
|
|
118
|
+
if (!isRecord(atomValue)) return null
|
|
119
|
+
const exports = readStringArray(atomValue.exports)
|
|
120
|
+
const literals = readStringArray(atomValue.literals)
|
|
121
|
+
if (
|
|
122
|
+
typeof atomValue.key !== 'string' ||
|
|
123
|
+
atomValue.key.length === 0 ||
|
|
124
|
+
!exports ||
|
|
125
|
+
!literals ||
|
|
126
|
+
typeof atomValue.dependencyArity !== 'number' ||
|
|
127
|
+
!Number.isSafeInteger(atomValue.dependencyArity) ||
|
|
128
|
+
atomValue.dependencyArity < 0 ||
|
|
129
|
+
!isSha256(atomValue.factoryDigest)
|
|
130
|
+
) {
|
|
131
|
+
return null
|
|
132
|
+
}
|
|
133
|
+
atoms.push({
|
|
134
|
+
key: atomValue.key,
|
|
135
|
+
exports,
|
|
136
|
+
literals,
|
|
137
|
+
dependencyArity: atomValue.dependencyArity,
|
|
138
|
+
factoryDigest: atomValue.factoryDigest,
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const templates: RNXMetroFingerprintTemplate[] = []
|
|
143
|
+
for (const templateValue of value.templates) {
|
|
144
|
+
if (
|
|
145
|
+
!isRecord(templateValue) ||
|
|
146
|
+
typeof templateValue.packageName !== 'string' ||
|
|
147
|
+
templateValue.packageName.length === 0 ||
|
|
148
|
+
typeof templateValue.packageVersion !== 'string' ||
|
|
149
|
+
templateValue.packageVersion.length === 0 ||
|
|
150
|
+
!isSha256(templateValue.sourceIntegrity) ||
|
|
151
|
+
typeof templateValue.profile !== 'string' ||
|
|
152
|
+
templateValue.profile.length === 0 ||
|
|
153
|
+
(templateValue.platform !== 'ios' && templateValue.platform !== 'android') ||
|
|
154
|
+
!Array.isArray(templateValue.nodes) ||
|
|
155
|
+
templateValue.nodes.length === 0 ||
|
|
156
|
+
!Array.isArray(templateValue.roots) ||
|
|
157
|
+
templateValue.roots.length === 0
|
|
158
|
+
) {
|
|
159
|
+
return null
|
|
160
|
+
}
|
|
161
|
+
const nodes: RNXMetroFingerprintNode[] = []
|
|
162
|
+
for (const nodeValue of templateValue.nodes) {
|
|
163
|
+
if (
|
|
164
|
+
!isRecord(nodeValue) ||
|
|
165
|
+
typeof nodeValue.atom !== 'number' ||
|
|
166
|
+
!Number.isSafeInteger(nodeValue.atom) ||
|
|
167
|
+
nodeValue.atom < 0 ||
|
|
168
|
+
nodeValue.atom >= atoms.length ||
|
|
169
|
+
!Array.isArray(nodeValue.internalDependencies) ||
|
|
170
|
+
(nodeValue.landmarkPath !== undefined &&
|
|
171
|
+
(typeof nodeValue.landmarkPath !== 'string' ||
|
|
172
|
+
nodeValue.landmarkPath.length === 0))
|
|
173
|
+
) {
|
|
174
|
+
return null
|
|
175
|
+
}
|
|
176
|
+
const internalDependencies: Array<{ position: number; node: number }> = []
|
|
177
|
+
const positions = new Set<number>()
|
|
178
|
+
for (const edgeValue of nodeValue.internalDependencies) {
|
|
179
|
+
if (
|
|
180
|
+
!isRecord(edgeValue) ||
|
|
181
|
+
typeof edgeValue.position !== 'number' ||
|
|
182
|
+
!Number.isSafeInteger(edgeValue.position) ||
|
|
183
|
+
edgeValue.position < 0 ||
|
|
184
|
+
positions.has(edgeValue.position) ||
|
|
185
|
+
typeof edgeValue.node !== 'number' ||
|
|
186
|
+
!Number.isSafeInteger(edgeValue.node) ||
|
|
187
|
+
edgeValue.node < 0 ||
|
|
188
|
+
edgeValue.node >= templateValue.nodes.length
|
|
189
|
+
) {
|
|
190
|
+
return null
|
|
191
|
+
}
|
|
192
|
+
positions.add(edgeValue.position)
|
|
193
|
+
internalDependencies.push({
|
|
194
|
+
position: edgeValue.position,
|
|
195
|
+
node: edgeValue.node,
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
internalDependencies.sort((left, right) => left.position - right.position)
|
|
199
|
+
nodes.push({
|
|
200
|
+
atom: nodeValue.atom,
|
|
201
|
+
internalDependencies,
|
|
202
|
+
...(typeof nodeValue.landmarkPath === 'string'
|
|
203
|
+
? { landmarkPath: nodeValue.landmarkPath }
|
|
204
|
+
: {}),
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
const roots: RNXMetroFingerprintRoot[] = []
|
|
208
|
+
for (const rootValue of templateValue.roots) {
|
|
209
|
+
if (
|
|
210
|
+
!isRecord(rootValue) ||
|
|
211
|
+
typeof rootValue.node !== 'number' ||
|
|
212
|
+
!Number.isSafeInteger(rootValue.node) ||
|
|
213
|
+
rootValue.node < 0 ||
|
|
214
|
+
rootValue.node >= nodes.length ||
|
|
215
|
+
!nodes[rootValue.node].landmarkPath
|
|
216
|
+
) {
|
|
217
|
+
return null
|
|
218
|
+
}
|
|
219
|
+
roots.push({ node: rootValue.node })
|
|
220
|
+
}
|
|
221
|
+
templates.push({
|
|
222
|
+
packageName: templateValue.packageName,
|
|
223
|
+
packageVersion: templateValue.packageVersion,
|
|
224
|
+
sourceIntegrity: templateValue.sourceIntegrity,
|
|
225
|
+
profile: templateValue.profile,
|
|
226
|
+
platform: templateValue.platform,
|
|
227
|
+
nodes,
|
|
228
|
+
roots,
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const candidatesByFactoryDigest: Record<string, RNXMetroFingerprintCandidate[]> = {}
|
|
233
|
+
for (const [factoryDigest, candidateValues] of Object.entries(
|
|
234
|
+
value.candidatesByFactoryDigest,
|
|
235
|
+
)) {
|
|
236
|
+
if (!isSha256(factoryDigest) || !Array.isArray(candidateValues)) return null
|
|
237
|
+
const candidates: RNXMetroFingerprintCandidate[] = []
|
|
238
|
+
for (const candidateValue of candidateValues) {
|
|
239
|
+
if (
|
|
240
|
+
!isRecord(candidateValue) ||
|
|
241
|
+
typeof candidateValue.template !== 'number' ||
|
|
242
|
+
!Number.isSafeInteger(candidateValue.template) ||
|
|
243
|
+
candidateValue.template < 0 ||
|
|
244
|
+
candidateValue.template >= templates.length ||
|
|
245
|
+
typeof candidateValue.root !== 'number' ||
|
|
246
|
+
!Number.isSafeInteger(candidateValue.root) ||
|
|
247
|
+
candidateValue.root < 0 ||
|
|
248
|
+
candidateValue.root >= templates[candidateValue.template].roots.length
|
|
249
|
+
) {
|
|
250
|
+
return null
|
|
251
|
+
}
|
|
252
|
+
const template = templates[candidateValue.template]
|
|
253
|
+
const root = template.roots[candidateValue.root]
|
|
254
|
+
if (atoms[template.nodes[root.node].atom].factoryDigest !== factoryDigest) {
|
|
255
|
+
return null
|
|
256
|
+
}
|
|
257
|
+
candidates.push({
|
|
258
|
+
template: candidateValue.template,
|
|
259
|
+
root: candidateValue.root,
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
candidatesByFactoryDigest[factoryDigest] = candidates
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const candidatesByDiscriminator: Record<string, RNXMetroFingerprintCandidate[]> = {}
|
|
266
|
+
for (const [discriminator, candidateValues] of Object.entries(
|
|
267
|
+
value.candidatesByDiscriminator,
|
|
268
|
+
)) {
|
|
269
|
+
if (!/^(?:e|l|ea|la|el|ela):[a-f0-9]{16}$/.test(discriminator)) return null
|
|
270
|
+
if (!Array.isArray(candidateValues) || candidateValues.length === 0) return null
|
|
271
|
+
const candidates: RNXMetroFingerprintCandidate[] = []
|
|
272
|
+
for (const candidateValue of candidateValues) {
|
|
273
|
+
if (
|
|
274
|
+
!isRecord(candidateValue) ||
|
|
275
|
+
typeof candidateValue.template !== 'number' ||
|
|
276
|
+
!Number.isSafeInteger(candidateValue.template) ||
|
|
277
|
+
candidateValue.template < 0 ||
|
|
278
|
+
candidateValue.template >= templates.length ||
|
|
279
|
+
typeof candidateValue.root !== 'number' ||
|
|
280
|
+
!Number.isSafeInteger(candidateValue.root) ||
|
|
281
|
+
candidateValue.root < 0 ||
|
|
282
|
+
candidateValue.root >= templates[candidateValue.template].roots.length
|
|
283
|
+
) {
|
|
284
|
+
return null
|
|
285
|
+
}
|
|
286
|
+
candidates.push({
|
|
287
|
+
template: candidateValue.template,
|
|
288
|
+
root: candidateValue.root,
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
candidatesByDiscriminator[discriminator] = candidates
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
schemaVersion,
|
|
296
|
+
revision,
|
|
297
|
+
atoms,
|
|
298
|
+
templates,
|
|
299
|
+
candidatesByFactoryDigest,
|
|
300
|
+
candidatesByDiscriminator,
|
|
301
|
+
}
|
|
302
|
+
}
|
package/src/metro-plugin.ts
CHANGED
|
@@ -24,9 +24,11 @@ import {
|
|
|
24
24
|
isReplacementModuleRequestUrl,
|
|
25
25
|
} from './host/replacement-module-handler'
|
|
26
26
|
import {
|
|
27
|
-
|
|
27
|
+
appendRNXMetroModuleIdentityFooter,
|
|
28
|
+
RNX_METRO_MODULE_IDENTITY_VERSION,
|
|
28
29
|
toRNXDevelopmentBundleUrl,
|
|
29
30
|
toRNXProductionBundleUrl,
|
|
31
|
+
type RNXMetroModuleIdentityMetadata,
|
|
30
32
|
} from './metro-production-bundle'
|
|
31
33
|
import {
|
|
32
34
|
isRootRuntimeAssetPath,
|
|
@@ -39,8 +41,19 @@ import {
|
|
|
39
41
|
const prefix = '/__soot'
|
|
40
42
|
export { toRNXDevelopmentBundleUrl, toRNXProductionBundleUrl }
|
|
41
43
|
|
|
44
|
+
type MetroSerializerModule = {
|
|
45
|
+
path: string
|
|
46
|
+
dependencies?: ReadonlyMap<
|
|
47
|
+
string,
|
|
48
|
+
{
|
|
49
|
+
absolutePath?: string
|
|
50
|
+
data?: { name?: string }
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
type MetroSerializerGraph = {
|
|
43
|
-
dependencies?: ReadonlyMap<unknown,
|
|
56
|
+
dependencies?: ReadonlyMap<unknown, MetroSerializerModule>
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
type MetroSerializerOptions = {
|
|
@@ -160,9 +173,39 @@ function appendRNXModulePaths(
|
|
|
160
173
|
throw new Error('rnxsim: bundle module IDs were not unique')
|
|
161
174
|
}
|
|
162
175
|
|
|
176
|
+
const specifiersByModuleId = new Map<string, Set<string>>()
|
|
177
|
+
for (const module of dependencies.values()) {
|
|
178
|
+
for (const [dependencyKey, dependency] of module.dependencies ?? []) {
|
|
179
|
+
const specifier = dependency.data?.name ?? dependencyKey
|
|
180
|
+
if (
|
|
181
|
+
specifier.length === 0 ||
|
|
182
|
+
specifier.startsWith('.') ||
|
|
183
|
+
specifier.startsWith('/') ||
|
|
184
|
+
typeof dependency.absolutePath !== 'string'
|
|
185
|
+
) {
|
|
186
|
+
continue
|
|
187
|
+
}
|
|
188
|
+
const moduleId = String(createModuleId(dependency.absolutePath))
|
|
189
|
+
if (!Object.prototype.hasOwnProperty.call(modulePaths, moduleId)) continue
|
|
190
|
+
const found = specifiersByModuleId.get(moduleId)
|
|
191
|
+
if (found) found.add(specifier)
|
|
192
|
+
else specifiersByModuleId.set(moduleId, new Set([specifier]))
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const logicalSpecifiers = Object.fromEntries(
|
|
196
|
+
[...specifiersByModuleId]
|
|
197
|
+
.sort(([left], [right]) => Number(left) - Number(right))
|
|
198
|
+
.map(([moduleId, specifiers]) => [moduleId, [...specifiers].sort()]),
|
|
199
|
+
)
|
|
200
|
+
const identity: RNXMetroModuleIdentityMetadata = {
|
|
201
|
+
version: RNX_METRO_MODULE_IDENTITY_VERSION,
|
|
202
|
+
identitySource: 'rnx-plugin',
|
|
203
|
+
modulePaths,
|
|
204
|
+
logicalSpecifiers,
|
|
205
|
+
}
|
|
163
206
|
return typeof result === 'string'
|
|
164
|
-
?
|
|
165
|
-
: { ...result, code:
|
|
207
|
+
? appendRNXMetroModuleIdentityFooter(result, identity)
|
|
208
|
+
: { ...result, code: appendRNXMetroModuleIdentityFooter(result.code, identity) }
|
|
166
209
|
}
|
|
167
210
|
|
|
168
211
|
export function withRNX<T extends Record<string, unknown>>(
|