vxrn 1.27.1 → 2.0.0-beta.45.1
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/dist/cli.mjs +212 -261
- package/dist/cli.mjs.map +1 -1
- package/dist/cli.native.js +216 -265
- package/dist/cli.native.js.map +1 -1
- package/dist/config/getAdditionalViteConfig.mjs +33 -62
- package/dist/config/getAdditionalViteConfig.mjs.map +1 -1
- package/dist/config/getAdditionalViteConfig.native.js +33 -62
- package/dist/config/getAdditionalViteConfig.native.js.map +1 -1
- package/dist/config/getBaseViteConfigOnly.mjs +84 -77
- package/dist/config/getBaseViteConfigOnly.mjs.map +1 -1
- package/dist/config/getBaseViteConfigOnly.native.js +86 -79
- package/dist/config/getBaseViteConfigOnly.native.js.map +1 -1
- package/dist/config/getBaseViteConfigWithPlugins.mjs +6 -4
- package/dist/config/getBaseViteConfigWithPlugins.mjs.map +1 -1
- package/dist/config/getBaseViteConfigWithPlugins.native.js +6 -4
- package/dist/config/getBaseViteConfigWithPlugins.native.js.map +1 -1
- package/dist/config/getBaseVitePlugins.mjs +102 -130
- package/dist/config/getBaseVitePlugins.mjs.map +1 -1
- package/dist/config/getBaseVitePlugins.native.js +123 -152
- package/dist/config/getBaseVitePlugins.native.js.map +1 -1
- package/dist/config/getNonCliModeOnlyVitePlugins.mjs +3 -3
- package/dist/config/getNonCliModeOnlyVitePlugins.mjs.map +1 -1
- package/dist/config/getNonCliModeOnlyVitePlugins.native.js +3 -1
- package/dist/config/getNonCliModeOnlyVitePlugins.native.js.map +1 -1
- package/dist/config/getOptimizeDeps.mjs +138 -42
- package/dist/config/getOptimizeDeps.mjs.map +1 -1
- package/dist/config/getOptimizeDeps.native.js +138 -42
- package/dist/config/getOptimizeDeps.native.js.map +1 -1
- package/dist/config/getOptionsFilled.mjs +48 -52
- package/dist/config/getOptionsFilled.mjs.map +1 -1
- package/dist/config/getOptionsFilled.native.js +51 -55
- package/dist/config/getOptionsFilled.native.js.map +1 -1
- package/dist/config/getReactNativePlugins.mjs +23 -15
- package/dist/config/getReactNativePlugins.mjs.map +1 -1
- package/dist/config/getReactNativePlugins.native.js +25 -16
- package/dist/config/getReactNativePlugins.native.js.map +1 -1
- package/dist/config/getServerOptionsFilled.mjs +33 -35
- package/dist/config/getServerOptionsFilled.mjs.map +1 -1
- package/dist/config/getServerOptionsFilled.native.js +35 -38
- package/dist/config/getServerOptionsFilled.native.js.map +1 -1
- package/dist/config/getViteServerConfig.mjs +34 -45
- package/dist/config/getViteServerConfig.mjs.map +1 -1
- package/dist/config/getViteServerConfig.native.js +35 -46
- package/dist/config/getViteServerConfig.native.js.map +1 -1
- package/dist/config/mergeUserConfig.mjs +50 -28
- package/dist/config/mergeUserConfig.mjs.map +1 -1
- package/dist/config/mergeUserConfig.native.js +60 -38
- package/dist/config/mergeUserConfig.native.js.map +1 -1
- package/dist/constants/defaults.mjs +29 -12
- package/dist/constants/defaults.mjs.map +1 -1
- package/dist/constants/defaults.native.js +29 -12
- package/dist/constants/defaults.native.js.map +1 -1
- package/dist/constants.mjs +41 -6
- package/dist/constants.mjs.map +1 -1
- package/dist/constants.native.js +41 -6
- package/dist/constants.native.js.map +1 -1
- package/dist/exports/build.mjs +218 -270
- package/dist/exports/build.mjs.map +1 -1
- package/dist/exports/build.native.js +226 -283
- package/dist/exports/build.native.js.map +1 -1
- package/dist/exports/clean.mjs +71 -78
- package/dist/exports/clean.mjs.map +1 -1
- package/dist/exports/clean.native.js +76 -90
- package/dist/exports/clean.native.js.map +1 -1
- package/dist/exports/createServer.mjs +43 -46
- package/dist/exports/createServer.mjs.map +1 -1
- package/dist/exports/createServer.native.js +45 -48
- package/dist/exports/createServer.native.js.map +1 -1
- package/dist/exports/dev.mjs +177 -201
- package/dist/exports/dev.mjs.map +1 -1
- package/dist/exports/dev.native.js +191 -215
- package/dist/exports/dev.native.js.map +1 -1
- package/dist/exports/loadEnv.mjs +51 -48
- package/dist/exports/loadEnv.mjs.map +1 -1
- package/dist/exports/loadEnv.native.js +59 -57
- package/dist/exports/loadEnv.native.js.map +1 -1
- package/dist/exports/patch.mjs +9 -7
- package/dist/exports/patch.mjs.map +1 -1
- package/dist/exports/patch.native.js +9 -7
- package/dist/exports/patch.native.js.map +1 -1
- package/dist/exports/prebuild.mjs +177 -157
- package/dist/exports/prebuild.mjs.map +1 -1
- package/dist/exports/prebuild.native.js +197 -160
- package/dist/exports/prebuild.native.js.map +1 -1
- package/dist/exports/prebuildWithoutExpo.mjs +46 -44
- package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
- package/dist/exports/prebuildWithoutExpo.native.js +48 -46
- package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
- package/dist/exports/runAndroid.mjs +9 -10
- package/dist/exports/runAndroid.mjs.map +1 -1
- package/dist/exports/runAndroid.native.js +10 -11
- package/dist/exports/runAndroid.native.js.map +1 -1
- package/dist/exports/runIos.mjs +9 -10
- package/dist/exports/runIos.mjs.map +1 -1
- package/dist/exports/runIos.native.js +10 -11
- package/dist/exports/runIos.native.js.map +1 -1
- package/dist/exports/serve.mjs +23 -31
- package/dist/exports/serve.mjs.map +1 -1
- package/dist/exports/serve.native.js +26 -34
- package/dist/exports/serve.native.js.map +1 -1
- package/dist/exports/serveStaticAssets.mjs +109 -113
- package/dist/exports/serveStaticAssets.mjs.map +1 -1
- package/dist/exports/serveStaticAssets.native.js +180 -192
- package/dist/exports/serveStaticAssets.native.js.map +1 -1
- package/dist/index.js +25 -14
- package/dist/index.mjs +25 -14
- package/dist/index.native.js +25 -14
- package/dist/patches/builtInDepPatches.mjs +346 -435
- package/dist/patches/builtInDepPatches.mjs.map +1 -1
- package/dist/patches/builtInDepPatches.native.js +349 -438
- package/dist/patches/builtInDepPatches.native.js.map +1 -1
- package/dist/plugins/applyBuiltInPatchesPlugin.mjs +11 -11
- package/dist/plugins/applyBuiltInPatchesPlugin.mjs.map +1 -1
- package/dist/plugins/applyBuiltInPatchesPlugin.native.js +11 -11
- package/dist/plugins/applyBuiltInPatchesPlugin.native.js.map +1 -1
- package/dist/plugins/autoDepOptimizePlugin.mjs +87 -90
- package/dist/plugins/autoDepOptimizePlugin.mjs.map +1 -1
- package/dist/plugins/autoDepOptimizePlugin.native.js +99 -102
- package/dist/plugins/autoDepOptimizePlugin.native.js.map +1 -1
- package/dist/plugins/clientInjectPlugin.mjs +13 -11
- package/dist/plugins/clientInjectPlugin.mjs.map +1 -1
- package/dist/plugins/clientInjectPlugin.native.js +13 -11
- package/dist/plugins/clientInjectPlugin.native.js.map +1 -1
- package/dist/plugins/defaultDepOptimizePlugin.mjs +15 -23
- package/dist/plugins/defaultDepOptimizePlugin.mjs.map +1 -1
- package/dist/plugins/defaultDepOptimizePlugin.native.js +15 -23
- package/dist/plugins/defaultDepOptimizePlugin.native.js.map +1 -1
- package/dist/plugins/expoManifestRequestHandlerPlugin.mjs +163 -179
- package/dist/plugins/expoManifestRequestHandlerPlugin.mjs.map +1 -1
- package/dist/plugins/expoManifestRequestHandlerPlugin.native.js +169 -191
- package/dist/plugins/expoManifestRequestHandlerPlugin.native.js.map +1 -1
- package/dist/plugins/getResolvedConfigSubset.mjs +6 -5
- package/dist/plugins/getResolvedConfigSubset.mjs.map +1 -1
- package/dist/plugins/getResolvedConfigSubset.native.js +6 -5
- package/dist/plugins/getResolvedConfigSubset.native.js.map +1 -1
- package/dist/plugins/reactNativeCommonJsPlugin.mjs +210 -178
- package/dist/plugins/reactNativeCommonJsPlugin.mjs.map +1 -1
- package/dist/plugins/reactNativeCommonJsPlugin.native.js +283 -259
- package/dist/plugins/reactNativeCommonJsPlugin.native.js.map +1 -1
- package/dist/plugins/reactNativeDevAssetPlugin.mjs +72 -83
- package/dist/plugins/reactNativeDevAssetPlugin.mjs.map +1 -1
- package/dist/plugins/reactNativeDevAssetPlugin.native.js +75 -92
- package/dist/plugins/reactNativeDevAssetPlugin.native.js.map +1 -1
- package/dist/plugins/reactNativeDevServer.mjs +283 -328
- package/dist/plugins/reactNativeDevServer.mjs.map +1 -1
- package/dist/plugins/reactNativeDevServer.native.js +332 -391
- package/dist/plugins/reactNativeDevServer.native.js.map +1 -1
- package/dist/plugins/rnCodegenPlugin.mjs +13 -12
- package/dist/plugins/rnCodegenPlugin.mjs.map +1 -1
- package/dist/plugins/rnCodegenPlugin.native.js +13 -12
- package/dist/plugins/rnCodegenPlugin.native.js.map +1 -1
- package/dist/plugins/rollupRemoveUnusedImports.mjs +8 -7
- package/dist/plugins/rollupRemoveUnusedImports.mjs.map +1 -1
- package/dist/plugins/rollupRemoveUnusedImports.native.js +8 -7
- package/dist/plugins/rollupRemoveUnusedImports.native.js.map +1 -1
- package/dist/plugins/workletImportsPlugin.mjs +127 -132
- package/dist/plugins/workletImportsPlugin.mjs.map +1 -1
- package/dist/plugins/workletImportsPlugin.native.js +192 -203
- package/dist/plugins/workletImportsPlugin.native.js.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.mjs +45 -79
- package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.native.js +45 -85
- package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
- package/dist/runtime/hmr-client.mjs +133 -140
- package/dist/runtime/hmr-client.mjs.map +1 -1
- package/dist/runtime/hmr-client.native.js +223 -222
- package/dist/runtime/hmr-client.native.js.map +1 -1
- package/dist/runtime/hmr-runtime.mjs +192 -194
- package/dist/runtime/hmr-runtime.mjs.map +1 -1
- package/dist/runtime/hmr-runtime.native.js +424 -411
- package/dist/runtime/hmr-runtime.native.js.map +1 -1
- package/dist/runtime/hmr-types.mjs +0 -2
- package/dist/runtime/hmr-types.native.js +0 -2
- package/dist/runtime/native-prelude.mjs +2 -1
- package/dist/runtime/native-prelude.mjs.map +1 -1
- package/dist/runtime/native-prelude.native.js +2 -1
- package/dist/runtime/native-prelude.native.js.map +1 -1
- package/dist/runtime/react-refresh-utils.mjs +23 -22
- package/dist/runtime/react-refresh-utils.mjs.map +1 -1
- package/dist/runtime/react-refresh-utils.native.js +23 -27
- package/dist/runtime/react-refresh-utils.native.js.map +1 -1
- package/dist/serve/node.mjs +49 -49
- package/dist/serve/node.mjs.map +1 -1
- package/dist/serve/node.native.js +92 -96
- package/dist/serve/node.native.js.map +1 -1
- package/dist/types.mjs +0 -2
- package/dist/types.native.js +0 -2
- package/dist/user-interface/index.mjs +245 -262
- package/dist/user-interface/index.mjs.map +1 -1
- package/dist/user-interface/index.native.js +274 -298
- package/dist/user-interface/index.native.js.map +1 -1
- package/dist/utils/assert.mjs +7 -6
- package/dist/utils/assert.mjs.map +1 -1
- package/dist/utils/assert.native.js +7 -18
- package/dist/utils/assert.native.js.map +1 -1
- package/dist/utils/bindKeypressInput.mjs +36 -38
- package/dist/utils/bindKeypressInput.mjs.map +1 -1
- package/dist/utils/bindKeypressInput.native.js +36 -38
- package/dist/utils/bindKeypressInput.native.js.map +1 -1
- package/dist/utils/coerceToArray.mjs +2 -1
- package/dist/utils/coerceToArray.mjs.map +1 -1
- package/dist/utils/coerceToArray.native.js +2 -1
- package/dist/utils/coerceToArray.native.js.map +1 -1
- package/dist/utils/connectedNativeClients.mjs +3 -2
- package/dist/utils/connectedNativeClients.mjs.map +1 -1
- package/dist/utils/connectedNativeClients.native.js +3 -2
- package/dist/utils/connectedNativeClients.native.js.map +1 -1
- package/dist/utils/createNativeDevEngine.mjs +992 -966
- package/dist/utils/createNativeDevEngine.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.native.js +1184 -1179
- package/dist/utils/createNativeDevEngine.native.js.map +1 -1
- package/dist/utils/dispose.mjs +4 -3
- package/dist/utils/dispose.mjs.map +1 -1
- package/dist/utils/dispose.native.js +6 -5
- package/dist/utils/dispose.native.js.map +1 -1
- package/dist/utils/environmentUtils.mjs +5 -4
- package/dist/utils/environmentUtils.mjs.map +1 -1
- package/dist/utils/environmentUtils.native.js +5 -4
- package/dist/utils/environmentUtils.native.js.map +1 -1
- package/dist/utils/execSync.mjs +7 -5
- package/dist/utils/execSync.mjs.map +1 -1
- package/dist/utils/execSync.native.js +8 -6
- package/dist/utils/execSync.native.js.map +1 -1
- package/dist/utils/expoRun.mjs +27 -35
- package/dist/utils/expoRun.mjs.map +1 -1
- package/dist/utils/expoRun.native.js +27 -35
- package/dist/utils/expoRun.native.js.map +1 -1
- package/dist/utils/filterViteServerResolvedUrls.mjs +24 -22
- package/dist/utils/filterViteServerResolvedUrls.mjs.map +1 -1
- package/dist/utils/filterViteServerResolvedUrls.native.js +61 -63
- package/dist/utils/filterViteServerResolvedUrls.native.js.map +1 -1
- package/dist/utils/getBoundPort.mjs +6 -5
- package/dist/utils/getBoundPort.mjs.map +1 -1
- package/dist/utils/getBoundPort.native.js +8 -12
- package/dist/utils/getBoundPort.native.js.map +1 -1
- package/dist/utils/getCacheDir.mjs +3 -1
- package/dist/utils/getCacheDir.mjs.map +1 -1
- package/dist/utils/getCacheDir.native.js +3 -1
- package/dist/utils/getCacheDir.native.js.map +1 -1
- package/dist/utils/getServerEntry.mjs +6 -4
- package/dist/utils/getServerEntry.mjs.map +1 -1
- package/dist/utils/getServerEntry.native.js +8 -11
- package/dist/utils/getServerEntry.native.js.map +1 -1
- package/dist/utils/getVitePath.mjs +42 -42
- package/dist/utils/getVitePath.mjs.map +1 -1
- package/dist/utils/getVitePath.native.js +43 -41
- package/dist/utils/getVitePath.native.js.map +1 -1
- package/dist/utils/globDir.mjs +7 -11
- package/dist/utils/globDir.mjs.map +1 -1
- package/dist/utils/globDir.native.js +10 -14
- package/dist/utils/globDir.native.js.map +1 -1
- package/dist/utils/isWithin.mjs +4 -2
- package/dist/utils/isWithin.mjs.map +1 -1
- package/dist/utils/isWithin.native.js +4 -2
- package/dist/utils/isWithin.native.js.map +1 -1
- package/dist/utils/patches.mjs +233 -255
- package/dist/utils/patches.mjs.map +1 -1
- package/dist/utils/patches.native.js +415 -460
- package/dist/utils/patches.native.js.map +1 -1
- package/dist/utils/printServerUrls.mjs +9 -7
- package/dist/utils/printServerUrls.mjs.map +1 -1
- package/dist/utils/printServerUrls.native.js +48 -51
- package/dist/utils/printServerUrls.native.js.map +1 -1
- package/dist/utils/removeUndefined.mjs +8 -7
- package/dist/utils/removeUndefined.mjs.map +1 -1
- package/dist/utils/removeUndefined.native.js +8 -7
- package/dist/utils/removeUndefined.native.js.map +1 -1
- package/dist/utils/scanDepsToOptimize.mjs +194 -161
- package/dist/utils/scanDepsToOptimize.mjs.map +1 -1
- package/dist/utils/scanDepsToOptimize.native.js +227 -197
- package/dist/utils/scanDepsToOptimize.native.js.map +1 -1
- package/dist/utils/state.mjs +18 -18
- package/dist/utils/state.mjs.map +1 -1
- package/dist/utils/state.native.js +18 -18
- package/dist/utils/state.native.js.map +1 -1
- package/dist/utils/symbolicateNativeStack.mjs +54 -54
- package/dist/utils/symbolicateNativeStack.mjs.map +1 -1
- package/dist/utils/symbolicateNativeStack.native.js +58 -58
- package/dist/utils/symbolicateNativeStack.native.js.map +1 -1
- package/dist/utils/uniq.mjs +2 -1
- package/dist/utils/uniq.mjs.map +1 -1
- package/dist/utils/uniq.native.js +2 -1
- package/dist/utils/uniq.native.js.map +1 -1
- package/dist/utils/utils.mjs +19 -19
- package/dist/utils/utils.mjs.map +1 -1
- package/dist/utils/utils.native.js +38 -40
- package/dist/utils/utils.native.js.map +1 -1
- package/dist/vendor/debugger-app/index.mjs +0 -2
- package/dist/vendor/debugger-app/index.native.js +0 -2
- package/dist/vendor/debugger-app/src/debuggerWorker.mjs +0 -2
- package/dist/vendor/debugger-app/src/debuggerWorker.native.js +0 -2
- package/dist/vendor/debugger-app/src/index.mjs +0 -2
- package/dist/vendor/debugger-app/src/index.native.js +0 -2
- package/dist/vxrn-vite-plugin.mjs +34 -33
- package/dist/vxrn-vite-plugin.mjs.map +1 -1
- package/dist/vxrn-vite-plugin.native.js +35 -34
- package/dist/vxrn-vite-plugin.native.js.map +1 -1
- package/expo-plugin.cjs +12 -6
- package/package.json +12 -13
- package/src/config/getBaseViteConfigOnly.ts +6 -0
- package/src/exports/prebuild.ts +40 -12
- package/src/patches/builtInDepPatches.ts +24 -48
- package/src/utils/createNativeDevEngine.test.ts +1 -1
- package/src/utils/createNativeDevEngine.ts +15 -9
- package/src/utils/scanDepsToOptimize.ts +0 -3
- package/types/config/getBaseViteConfigOnly.d.ts.map +1 -1
- package/types/config/getOptimizeDeps.d.ts.map +1 -1
- package/types/config/getOptionsFilled.d.ts +15 -15
- package/types/config/getOptionsFilled.d.ts.map +1 -1
- package/types/exports/build.d.ts +11 -11
- package/types/exports/build.d.ts.map +1 -1
- package/types/exports/clean.d.ts +1 -1
- package/types/exports/clean.d.ts.map +1 -1
- package/types/exports/createServer.d.ts.map +1 -1
- package/types/exports/dev.d.ts.map +1 -1
- package/types/exports/patch.d.ts.map +1 -1
- package/types/exports/prebuild.d.ts +3 -3
- package/types/exports/prebuild.d.ts.map +1 -1
- package/types/exports/prebuildWithoutExpo.d.ts +1 -1
- package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
- package/types/exports/runAndroid.d.ts.map +1 -1
- package/types/exports/runIos.d.ts.map +1 -1
- package/types/exports/serve.d.ts.map +1 -1
- package/types/patches/builtInDepPatches.d.ts.map +1 -1
- package/types/plugins/autoDepOptimizePlugin.d.ts.map +1 -1
- package/types/plugins/rollupRemoveUnusedImports.d.ts.map +1 -1
- package/types/runtime/hmr-client.d.ts.map +1 -1
- package/types/runtime/hmr-runtime.d.ts.map +1 -1
- package/types/runtime/hmr-types.d.ts.map +1 -1
- package/types/utils/createNativeDevEngine.d.ts +1 -1
- package/types/utils/createNativeDevEngine.d.ts.map +1 -1
- package/types/utils/execSync.d.ts.map +1 -1
- package/types/utils/getServerEntry.d.ts.map +1 -1
- package/types/utils/scanDepsToOptimize.d.ts.map +1 -1
- package/types/vxrn-vite-plugin.d.ts.map +1 -1
- package/dist/config/getOptimizeDeps.test.mjs +0 -20
- package/dist/config/getOptimizeDeps.test.mjs.map +0 -1
- package/dist/config/getOptimizeDeps.test.native.js +0 -39
- package/dist/config/getOptimizeDeps.test.native.js.map +0 -1
- package/dist/config/getServerOptionsFilled.test.mjs +0 -20
- package/dist/config/getServerOptionsFilled.test.mjs.map +0 -1
- package/dist/config/getServerOptionsFilled.test.native.js +0 -20
- package/dist/config/getServerOptionsFilled.test.native.js.map +0 -1
- package/dist/config/getViteServerConfig.test.mjs +0 -26
- package/dist/config/getViteServerConfig.test.mjs.map +0 -1
- package/dist/config/getViteServerConfig.test.native.js +0 -26
- package/dist/config/getViteServerConfig.test.native.js.map +0 -1
- package/dist/config/mergeUserConfig.test.mjs +0 -108
- package/dist/config/mergeUserConfig.test.mjs.map +0 -1
- package/dist/config/mergeUserConfig.test.native.js +0 -108
- package/dist/config/mergeUserConfig.test.native.js.map +0 -1
- package/dist/exports/clean.test.mjs +0 -81
- package/dist/exports/clean.test.mjs.map +0 -1
- package/dist/exports/clean.test.native.js +0 -88
- package/dist/exports/clean.test.native.js.map +0 -1
- package/dist/exports/loadEnv.test.mjs +0 -65
- package/dist/exports/loadEnv.test.mjs.map +0 -1
- package/dist/exports/loadEnv.test.native.js +0 -65
- package/dist/exports/loadEnv.test.native.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/index.native.js.map +0 -1
- package/dist/plugins/autoDepOptimizePlugin.test.mjs +0 -31
- package/dist/plugins/autoDepOptimizePlugin.test.mjs.map +0 -1
- package/dist/plugins/autoDepOptimizePlugin.test.native.js +0 -39
- package/dist/plugins/autoDepOptimizePlugin.test.native.js.map +0 -1
- package/dist/plugins/resolveIdScan.test.mjs +0 -31
- package/dist/plugins/resolveIdScan.test.mjs.map +0 -1
- package/dist/plugins/resolveIdScan.test.native.js +0 -38
- package/dist/plugins/resolveIdScan.test.native.js.map +0 -1
- package/dist/plugins/rnCodegenPlugin.test.mjs +0 -239
- package/dist/plugins/rnCodegenPlugin.test.mjs.map +0 -1
- package/dist/plugins/rnCodegenPlugin.test.native.js +0 -242
- package/dist/plugins/rnCodegenPlugin.test.native.js.map +0 -1
- package/dist/plugins/serverExtensions.test.mjs +0 -106
- package/dist/plugins/serverExtensions.test.mjs.map +0 -1
- package/dist/plugins/serverExtensions.test.native.js +0 -117
- package/dist/plugins/serverExtensions.test.native.js.map +0 -1
- package/dist/runtime/hmr-types.mjs.map +0 -1
- package/dist/runtime/hmr-types.native.js.map +0 -1
- package/dist/serve/node.test.mjs +0 -60
- package/dist/serve/node.test.mjs.map +0 -1
- package/dist/serve/node.test.native.js +0 -72
- package/dist/serve/node.test.native.js.map +0 -1
- package/dist/types.mjs.map +0 -1
- package/dist/types.native.js.map +0 -1
- package/dist/utils/bindKeypressInput.test.mjs +0 -48
- package/dist/utils/bindKeypressInput.test.mjs.map +0 -1
- package/dist/utils/bindKeypressInput.test.native.js +0 -48
- package/dist/utils/bindKeypressInput.test.native.js.map +0 -1
- package/dist/utils/createNativeDevEngine.test.mjs +0 -1788
- package/dist/utils/createNativeDevEngine.test.mjs.map +0 -1
- package/dist/utils/createNativeDevEngine.test.native.js +0 -1942
- package/dist/utils/createNativeDevEngine.test.native.js.map +0 -1
- package/dist/utils/createNativeDevEngineFailure.test.mjs +0 -44
- package/dist/utils/createNativeDevEngineFailure.test.mjs.map +0 -1
- package/dist/utils/createNativeDevEngineFailure.test.native.js +0 -54
- package/dist/utils/createNativeDevEngineFailure.test.native.js.map +0 -1
- package/dist/utils/getBoundPort.test.mjs +0 -71
- package/dist/utils/getBoundPort.test.mjs.map +0 -1
- package/dist/utils/getBoundPort.test.native.js +0 -82
- package/dist/utils/getBoundPort.test.native.js.map +0 -1
- package/dist/utils/imageSizePatch.test.mjs +0 -29
- package/dist/utils/imageSizePatch.test.mjs.map +0 -1
- package/dist/utils/imageSizePatch.test.native.js +0 -30
- package/dist/utils/imageSizePatch.test.native.js.map +0 -1
- package/dist/utils/patches.test.mjs +0 -242
- package/dist/utils/patches.test.mjs.map +0 -1
- package/dist/utils/patches.test.native.js +0 -271
- package/dist/utils/patches.test.native.js.map +0 -1
- package/dist/utils/symbolicateNativeStack.test.mjs +0 -96
- package/dist/utils/symbolicateNativeStack.test.mjs.map +0 -1
- package/dist/utils/symbolicateNativeStack.test.native.js +0 -96
- package/dist/utils/symbolicateNativeStack.test.native.js.map +0 -1
- package/dist/vendor/debugger-app/index.mjs.map +0 -1
- package/dist/vendor/debugger-app/index.native.js.map +0 -1
- package/dist/vendor/debugger-app/src/debuggerWorker.mjs.map +0 -1
- package/dist/vendor/debugger-app/src/debuggerWorker.native.js.map +0 -1
- package/dist/vendor/debugger-app/src/index.mjs.map +0 -1
- package/dist/vendor/debugger-app/src/index.native.js.map +0 -1
- package/types/config/getOptimizeDeps.test.d.ts +0 -2
- package/types/config/getOptimizeDeps.test.d.ts.map +0 -1
- package/types/config/getServerOptionsFilled.test.d.ts +0 -2
- package/types/config/getServerOptionsFilled.test.d.ts.map +0 -1
- package/types/config/getViteServerConfig.test.d.ts +0 -2
- package/types/config/getViteServerConfig.test.d.ts.map +0 -1
- package/types/config/mergeUserConfig.test.d.ts +0 -2
- package/types/config/mergeUserConfig.test.d.ts.map +0 -1
- package/types/exports/clean.test.d.ts +0 -2
- package/types/exports/clean.test.d.ts.map +0 -1
- package/types/exports/loadEnv.test.d.ts +0 -2
- package/types/exports/loadEnv.test.d.ts.map +0 -1
- package/types/plugins/autoDepOptimizePlugin.test.d.ts +0 -2
- package/types/plugins/autoDepOptimizePlugin.test.d.ts.map +0 -1
- package/types/plugins/resolveIdScan.test.d.ts +0 -2
- package/types/plugins/resolveIdScan.test.d.ts.map +0 -1
- package/types/plugins/rnCodegenPlugin.test.d.ts +0 -2
- package/types/plugins/rnCodegenPlugin.test.d.ts.map +0 -1
- package/types/plugins/serverExtensions.test.d.ts +0 -2
- package/types/plugins/serverExtensions.test.d.ts.map +0 -1
- package/types/serve/node.test.d.ts +0 -2
- package/types/serve/node.test.d.ts.map +0 -1
- package/types/utils/bindKeypressInput.test.d.ts +0 -2
- package/types/utils/bindKeypressInput.test.d.ts.map +0 -1
- package/types/utils/createNativeDevEngine.test.d.ts +0 -2
- package/types/utils/createNativeDevEngine.test.d.ts.map +0 -1
- package/types/utils/createNativeDevEngineFailure.test.d.ts +0 -2
- package/types/utils/createNativeDevEngineFailure.test.d.ts.map +0 -1
- package/types/utils/getBoundPort.test.d.ts +0 -2
- package/types/utils/getBoundPort.test.d.ts.map +0 -1
- package/types/utils/imageSizePatch.test.d.ts +0 -2
- package/types/utils/imageSizePatch.test.d.ts.map +0 -1
- package/types/utils/patches.test.d.ts +0 -2
- package/types/utils/patches.test.d.ts.map +0 -1
- package/types/utils/symbolicateNativeStack.test.d.ts +0 -2
- package/types/utils/symbolicateNativeStack.test.d.ts.map +0 -1
|
@@ -1,1788 +0,0 @@
|
|
|
1
|
-
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
-
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { createContext, runInContext, runInNewContext } from "node:vm";
|
|
6
|
-
import { TraceMap, originalPositionFor } from "@jridgewell/trace-mapping";
|
|
7
|
-
import { rolldown } from "rolldown";
|
|
8
|
-
import { dev } from "rolldown/experimental";
|
|
9
|
-
import { normalizePath } from "vite";
|
|
10
|
-
import { describe, expect, it, vi } from "vitest";
|
|
11
|
-
import { getNativePrelude } from "../runtime/native-prelude.mjs";
|
|
12
|
-
import { workletImportsPlugin } from "../plugins/workletImportsPlugin.mjs";
|
|
13
|
-
import { buildNativeBundle, createNativeDevAssetRegistry, createNativeDevEngine, getHermesSWCIncludes, getHmrRuntimeSource, getNativeAssetData, getNativeTransformConfig, hermesCompatSWCPlugin, hmrClientNoopPlugin, nativeAnimatedGuardPlugin, normalizeNativeCommonJSInterop, postProcessNativeBundle, vxrnCompilerPlugin, wrapNativeBundleModuleScope } from "./createNativeDevEngine.mjs";
|
|
14
|
-
describe.each(["ios", "android"])("native plugin adapters on %s", platform => {
|
|
15
|
-
it.each(["dev", "build"])("binds configured plugins to the %s bundle", async mode => {
|
|
16
|
-
const root2 = await mkdtemp(join(tmpdir(), "vxrn-native-plugin-adapter-"));
|
|
17
|
-
await writeFile(join(root2, "entry.js"), `globalThis.nativePluginResult = [__GLOBAL_PLUGIN__, __DIRECT_PLUGIN__, 'plain-plugin']`);
|
|
18
|
-
const factories = ["global", "direct"].map(name => vi.fn(context => ({
|
|
19
|
-
name: `${name}-native`,
|
|
20
|
-
transform(code, id) {
|
|
21
|
-
if (id.endsWith("/entry.js")) return code.replace(`__${name.toUpperCase()}_PLUGIN__`, JSON.stringify({
|
|
22
|
-
name,
|
|
23
|
-
...context
|
|
24
|
-
}));
|
|
25
|
-
}
|
|
26
|
-
})));
|
|
27
|
-
const plugins = factories.map((vxrnNative, index) => ({
|
|
28
|
-
name: `adapter-${index}`,
|
|
29
|
-
api: {
|
|
30
|
-
vxrnNative
|
|
31
|
-
}
|
|
32
|
-
}));
|
|
33
|
-
const previousPlugins = globalThis.__vxrnAddNativePlugins;
|
|
34
|
-
globalThis.__vxrnAddNativePlugins = [plugins[0]];
|
|
35
|
-
const configuredPlugins = [plugins[1], {
|
|
36
|
-
name: "plain-native-plugin",
|
|
37
|
-
transform(code, id) {
|
|
38
|
-
if (id.endsWith("/__virtual-native-entry.tsx")) return `import './entry.js'`;
|
|
39
|
-
if (id.endsWith("/entry.js")) return code.replace("plain-plugin", "plain");
|
|
40
|
-
}
|
|
41
|
-
}];
|
|
42
|
-
let native;
|
|
43
|
-
try {
|
|
44
|
-
let code;
|
|
45
|
-
if (mode === "dev") {
|
|
46
|
-
native = await createNativeDevEngine({
|
|
47
|
-
root: root2,
|
|
48
|
-
platform,
|
|
49
|
-
port: 0,
|
|
50
|
-
plugins: configuredPlugins
|
|
51
|
-
});
|
|
52
|
-
code = (await native.getBundle()).code;
|
|
53
|
-
} else code = (await buildNativeBundle({
|
|
54
|
-
root: root2,
|
|
55
|
-
platform,
|
|
56
|
-
entryFile: "entry.js",
|
|
57
|
-
plugins: configuredPlugins
|
|
58
|
-
})).code;
|
|
59
|
-
const context = {
|
|
60
|
-
console,
|
|
61
|
-
setTimeout,
|
|
62
|
-
clearTimeout,
|
|
63
|
-
__GLOBAL_PLUGIN__: "unadapted",
|
|
64
|
-
__DIRECT_PLUGIN__: "unadapted"
|
|
65
|
-
};
|
|
66
|
-
runInNewContext(code, context);
|
|
67
|
-
expect(Reflect.get(context, "nativePluginResult")).toEqual([{
|
|
68
|
-
name: "global",
|
|
69
|
-
root: root2,
|
|
70
|
-
platform,
|
|
71
|
-
dev: mode === "dev"
|
|
72
|
-
}, {
|
|
73
|
-
name: "direct",
|
|
74
|
-
root: root2,
|
|
75
|
-
platform,
|
|
76
|
-
dev: mode === "dev"
|
|
77
|
-
}, "plain"]);
|
|
78
|
-
for (const factory of factories) expect(factory).toHaveBeenCalledExactlyOnceWith({
|
|
79
|
-
root: root2,
|
|
80
|
-
platform,
|
|
81
|
-
dev: mode === "dev"
|
|
82
|
-
});
|
|
83
|
-
} finally {
|
|
84
|
-
await native?.close();
|
|
85
|
-
globalThis.__vxrnAddNativePlugins = previousPlugins;
|
|
86
|
-
await rm(root2, {
|
|
87
|
-
recursive: true,
|
|
88
|
-
force: true
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
const nativeTransformProbe = `
|
|
94
|
-
export const transformProbe = () => {
|
|
95
|
-
'worklet'
|
|
96
|
-
return 'transformed'
|
|
97
|
-
}
|
|
98
|
-
`;
|
|
99
|
-
describe.each(["rolldown-dev", "rolldown-build", "metro-module", "metro-script"])("native async through %s", pipeline => {
|
|
100
|
-
it("preserves defaults, lexical bindings, bigint, rejection, and iterator cleanup", async () => {
|
|
101
|
-
const id = "/project/native-async.js";
|
|
102
|
-
const source = `
|
|
103
|
-
globalThis.result = (function(parentArgument) {
|
|
104
|
-
const events = [];
|
|
105
|
-
const run = async(value = 2n, fail = false) => {
|
|
106
|
-
try {
|
|
107
|
-
const awaited = await (fail ? Promise.reject(new Error('rejected')) : Promise.resolve(3n));
|
|
108
|
-
events.push('after-await');
|
|
109
|
-
return [String(value + awaited), this.base, arguments[0]];
|
|
110
|
-
} catch (error) { return error.message; }
|
|
111
|
-
finally { events.push('finally'); }
|
|
112
|
-
};
|
|
113
|
-
const badDefault = async(value = (() => { throw new Error('default'); })()) => value;
|
|
114
|
-
let synchronousThrow = false;
|
|
115
|
-
let rejectedDefault;
|
|
116
|
-
try { rejectedDefault = badDefault().catch(error => error.message); }
|
|
117
|
-
catch { synchronousThrow = true; }
|
|
118
|
-
async function* values() {
|
|
119
|
-
try { yield 1n; yield 2n; }
|
|
120
|
-
finally { events.push('closed'); }
|
|
121
|
-
}
|
|
122
|
-
const first = async() => { for await (const value of values()) return String(value); };
|
|
123
|
-
return Promise.all([run(), run(4n), run(undefined, true), rejectedDefault, first()])
|
|
124
|
-
.then(values => ({ values, events, synchronousThrow }));
|
|
125
|
-
}).call({ base: 7 }, 'lexical');
|
|
126
|
-
`;
|
|
127
|
-
let output;
|
|
128
|
-
if (pipeline.startsWith("metro")) {
|
|
129
|
-
const {
|
|
130
|
-
transform
|
|
131
|
-
} = await import("@vxrn/vite-plugin-metro/metroNativeWorker");
|
|
132
|
-
const data = (await transform({}, "/project", id, Buffer.from(source), {
|
|
133
|
-
dev: false,
|
|
134
|
-
platform: "ios",
|
|
135
|
-
type: pipeline === "metro-script" ? "script" : "module"
|
|
136
|
-
})).output[0].data;
|
|
137
|
-
const {
|
|
138
|
-
fromRawMappings
|
|
139
|
-
} = await import("metro-source-map");
|
|
140
|
-
output = {
|
|
141
|
-
code: data.code,
|
|
142
|
-
map: fromRawMappings([{
|
|
143
|
-
code: data.code,
|
|
144
|
-
path: id,
|
|
145
|
-
source,
|
|
146
|
-
map: data.map
|
|
147
|
-
}]).toMap()
|
|
148
|
-
};
|
|
149
|
-
} else {
|
|
150
|
-
const plugin = hermesCompatSWCPlugin(pipeline === "rolldown-dev", true);
|
|
151
|
-
output = await Reflect.apply(plugin.transform, void 0, [source, id]);
|
|
152
|
-
}
|
|
153
|
-
const context = {};
|
|
154
|
-
context.__d = factory => {
|
|
155
|
-
const module = {
|
|
156
|
-
exports: {}
|
|
157
|
-
};
|
|
158
|
-
factory(context, name => {
|
|
159
|
-
throw new Error(`unexpected dependency ${name}`);
|
|
160
|
-
}, () => {}, () => {}, module, module.exports, []);
|
|
161
|
-
};
|
|
162
|
-
runInNewContext(output.code, context);
|
|
163
|
-
const result = await context.result;
|
|
164
|
-
expect(result.values).toEqual([["5", 7, "lexical"], ["7", 7, "lexical"], "rejected", "default", "1"]);
|
|
165
|
-
expect(result.synchronousThrow).toBe(false);
|
|
166
|
-
expect(result.events.filter(value => value === "finally")).toHaveLength(3);
|
|
167
|
-
expect(result.events.filter(value => value === "closed")).toHaveLength(1);
|
|
168
|
-
const {
|
|
169
|
-
originalPositionFor: originalPositionFor2,
|
|
170
|
-
TraceMap: TraceMap2
|
|
171
|
-
} = await import("@jridgewell/trace-mapping");
|
|
172
|
-
const lines = output.code.split("\n");
|
|
173
|
-
const line = lines.findIndex(value => value.includes("after-await"));
|
|
174
|
-
const position = originalPositionFor2(new TraceMap2(output.map), {
|
|
175
|
-
line: line + 1,
|
|
176
|
-
column: lines[line].indexOf("events.push")
|
|
177
|
-
});
|
|
178
|
-
expect(position.source).toBe(id);
|
|
179
|
-
expect(position.line).toBe(source.split("\n").findIndex(value => value.includes("after-await")) + 1);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
describe.each(["shared", "rolldown", "metro"])("React Compiler worklets through %s", pipeline => {
|
|
183
|
-
it.each([["block", "useDerivedValue(() => { return value + 8 }, [value])", 18], ["expression", "useDerivedValue(() => value + 8, [value])", 18], ["object", "useDerivedValue(() => ({ lift: value + 8 }), [value])", {
|
|
184
|
-
lift: 18
|
|
185
|
-
}], ["nested", "useDerivedValue(() => runOnUI(() => value + 8), [value])", 18], ["gesture", "useDerivedValue(() => Gesture.Pan().onUpdate(() => value + 8), [value])", 18]])("preserves %s callbacks on the UI runtime and memoizes stable inputs", async (_name, callback, expected) => {
|
|
186
|
-
const compiler = await import("@vxrn/compiler");
|
|
187
|
-
const {
|
|
188
|
-
parseSync
|
|
189
|
-
} = await import("oxc-parser");
|
|
190
|
-
const {
|
|
191
|
-
default: MagicString
|
|
192
|
-
} = await import("magic-string");
|
|
193
|
-
const {
|
|
194
|
-
TraceMap: TraceMap2,
|
|
195
|
-
originalPositionFor: originalPositionFor2
|
|
196
|
-
} = await import("@jridgewell/trace-mapping");
|
|
197
|
-
const projectRoot = await createWorkletsProject(false);
|
|
198
|
-
const sourceMaps = process.env.VXRN_ENABLE_SOURCE_MAP;
|
|
199
|
-
process.env.VXRN_ENABLE_SOURCE_MAP = "1";
|
|
200
|
-
compiler.configureVXRNCompilerPlugin({
|
|
201
|
-
enableCompiler: true,
|
|
202
|
-
enableReanimated: true,
|
|
203
|
-
enableNativeWorklets: true
|
|
204
|
-
});
|
|
205
|
-
try {
|
|
206
|
-
const id = join(projectRoot, "useProbe.ts");
|
|
207
|
-
const source = `export function useProbe(value) {
|
|
208
|
-
return ${callback};
|
|
209
|
-
}
|
|
210
|
-
`;
|
|
211
|
-
await writeFile(id, source);
|
|
212
|
-
let result;
|
|
213
|
-
if (pipeline === "shared") {
|
|
214
|
-
const plugin = (await compiler.createVXRNCompilerPlugin()).find(p => p.name === "one:compiler");
|
|
215
|
-
await plugin.configResolved({
|
|
216
|
-
root: projectRoot,
|
|
217
|
-
build: {}
|
|
218
|
-
});
|
|
219
|
-
result = await (plugin.transform.handler || plugin.transform).call({
|
|
220
|
-
environment: {
|
|
221
|
-
name: "ios"
|
|
222
|
-
}
|
|
223
|
-
}, source, id);
|
|
224
|
-
} else if (pipeline === "metro") {
|
|
225
|
-
const {
|
|
226
|
-
transform
|
|
227
|
-
} = await import("@vxrn/vite-plugin-metro/metroNativeWorker");
|
|
228
|
-
const data = (await transform({}, projectRoot, id, Buffer.from(source), {
|
|
229
|
-
dev: false,
|
|
230
|
-
platform: "ios",
|
|
231
|
-
type: "module",
|
|
232
|
-
customTransformOptions: {
|
|
233
|
-
reactCompiler: true,
|
|
234
|
-
worklets: true
|
|
235
|
-
}
|
|
236
|
-
})).output[0].data;
|
|
237
|
-
const msm = await import("metro-source-map");
|
|
238
|
-
result = {
|
|
239
|
-
code: data.code,
|
|
240
|
-
map: msm.fromRawMappings([{
|
|
241
|
-
code: data.code,
|
|
242
|
-
path: id,
|
|
243
|
-
source,
|
|
244
|
-
map: data.map
|
|
245
|
-
}]).toMap()
|
|
246
|
-
};
|
|
247
|
-
} else {
|
|
248
|
-
const plugin = vxrnCompilerPlugin("ios", false, projectRoot, true);
|
|
249
|
-
result = await Reflect.apply(plugin.transform, void 0, [source, id]);
|
|
250
|
-
}
|
|
251
|
-
const runnable = new MagicString(result.code);
|
|
252
|
-
for (const node of parseSync("probe.js", result.code).program.body) {
|
|
253
|
-
if (node.type === "ImportDeclaration") runnable.remove(node.start, node.end);
|
|
254
|
-
if (node.type === "ExportNamedDeclaration" && node.declaration) runnable.remove(node.start, node.declaration.start);
|
|
255
|
-
}
|
|
256
|
-
let cache;
|
|
257
|
-
let cacheCalls = 0;
|
|
258
|
-
const memo = size => {
|
|
259
|
-
cacheCalls++;
|
|
260
|
-
return cache ??= Array(size).fill(/* @__PURE__ */Symbol.for("react.memo_cache_sentinel"));
|
|
261
|
-
};
|
|
262
|
-
const module = {
|
|
263
|
-
exports: {}
|
|
264
|
-
};
|
|
265
|
-
const probe = new Function("_c", "useDerivedValue", "runOnUI", "Gesture", "__d", "module", `${runnable}
|
|
266
|
-
return ${pipeline === "metro" ? "module.exports.useProbe" : "useProbe"}`)(memo, fn => fn, fn => fn, {
|
|
267
|
-
Pan: () => ({
|
|
268
|
-
onUpdate: fn => fn
|
|
269
|
-
})
|
|
270
|
-
}, factory => factory(globalThis, () => ({
|
|
271
|
-
c: memo
|
|
272
|
-
}), () => {}, () => {}, module, module.exports, []), module);
|
|
273
|
-
const first = probe(10);
|
|
274
|
-
expect(first.__initData?.code).toBeTypeOf("string");
|
|
275
|
-
for (const onUI of [false, true]) {
|
|
276
|
-
let fn = first;
|
|
277
|
-
let value;
|
|
278
|
-
for (let depth = 0; depth < 2; depth++) {
|
|
279
|
-
expect(fn.__initData?.code).toBeTypeOf("string");
|
|
280
|
-
value = onUI ? new Function("runOnUI", `return (${fn.__initData.code})`)(fn2 => fn2).call({
|
|
281
|
-
__closure: fn.__closure
|
|
282
|
-
}) : fn();
|
|
283
|
-
if (typeof value !== "function") break;
|
|
284
|
-
fn = value;
|
|
285
|
-
}
|
|
286
|
-
expect(value).toEqual(expected);
|
|
287
|
-
}
|
|
288
|
-
expect(probe(10)).toBe(first);
|
|
289
|
-
expect(cacheCalls).toBe(2);
|
|
290
|
-
expect(probe(20)).not.toBe(first);
|
|
291
|
-
const lines = result.code.split("\n");
|
|
292
|
-
const line = lines.findIndex(text => text.includes("function useProbe("));
|
|
293
|
-
expect(line).toBeGreaterThanOrEqual(0);
|
|
294
|
-
const position = originalPositionFor2(new TraceMap2(result.map), {
|
|
295
|
-
line: line + 1,
|
|
296
|
-
column: lines[line].indexOf("function")
|
|
297
|
-
});
|
|
298
|
-
expect(position.source).toBe(id);
|
|
299
|
-
expect(position.line).toBe(1);
|
|
300
|
-
} finally {
|
|
301
|
-
if (sourceMaps === void 0) delete process.env.VXRN_ENABLE_SOURCE_MAP;else process.env.VXRN_ENABLE_SOURCE_MAP = sourceMaps;
|
|
302
|
-
compiler.configureVXRNCompilerPlugin({
|
|
303
|
-
enableCompiler: false,
|
|
304
|
-
enableReanimated: false,
|
|
305
|
-
enableNativeWorklets: false
|
|
306
|
-
});
|
|
307
|
-
await rm(projectRoot, {
|
|
308
|
-
recursive: true,
|
|
309
|
-
force: true
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
async function createWorkletsProject(throwOnTransform = true) {
|
|
315
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-transform-failure-"));
|
|
316
|
-
const packageRoot = join(testRoot, "node_modules/react-native-worklets");
|
|
317
|
-
await mkdir(packageRoot, {
|
|
318
|
-
recursive: true
|
|
319
|
-
});
|
|
320
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
321
|
-
name: "react-native-worklets",
|
|
322
|
-
version: "0.10.1"
|
|
323
|
-
}));
|
|
324
|
-
await writeFile(join(packageRoot, "plugin.js"), throwOnTransform ? `module.exports = () => ({
|
|
325
|
-
visitor: {
|
|
326
|
-
Program() {
|
|
327
|
-
throw new Error('NATIVE_TRANSFORM_NEGATIVE_CONTROL')
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
})` : `module.exports = () => ({ visitor: {} })`);
|
|
331
|
-
await writeFile(join(testRoot, "entry.ts"), nativeTransformProbe);
|
|
332
|
-
return testRoot;
|
|
333
|
-
}
|
|
334
|
-
describe("native prelude", () => {
|
|
335
|
-
it("does not advertise a host event API that cannot remove listeners", () => {
|
|
336
|
-
const context = {
|
|
337
|
-
addEventListener() {}
|
|
338
|
-
};
|
|
339
|
-
runInNewContext(getNativePrelude({
|
|
340
|
-
dev: false,
|
|
341
|
-
platform: "ios"
|
|
342
|
-
}), context);
|
|
343
|
-
expect(Reflect.get(context, "addEventListener")).toBeUndefined();
|
|
344
|
-
});
|
|
345
|
-
it("preserves a complete host event API", () => {
|
|
346
|
-
const addEventListener = () => {};
|
|
347
|
-
const removeEventListener = () => {};
|
|
348
|
-
const context = {
|
|
349
|
-
addEventListener,
|
|
350
|
-
removeEventListener
|
|
351
|
-
};
|
|
352
|
-
runInNewContext(getNativePrelude({
|
|
353
|
-
dev: false,
|
|
354
|
-
platform: "ios"
|
|
355
|
-
}), context);
|
|
356
|
-
expect(context.addEventListener).toBe(addEventListener);
|
|
357
|
-
expect(context.removeEventListener).toBe(removeEventListener);
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
describe("native pure-function worklet imports", () => {
|
|
361
|
-
it("keeps live module versions isolated across a transitive HMR update", async () => {
|
|
362
|
-
const root2 = await createWorkletsProject(false);
|
|
363
|
-
const packageRoot = join(root2, "node_modules/pure-math");
|
|
364
|
-
await mkdir(packageRoot, {
|
|
365
|
-
recursive: true
|
|
366
|
-
});
|
|
367
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
368
|
-
type: "module",
|
|
369
|
-
exports: "./index.js"
|
|
370
|
-
}));
|
|
371
|
-
const dependency = join(packageRoot, "amount.ios.js");
|
|
372
|
-
await writeFile(dependency, "export const amount = 2");
|
|
373
|
-
await writeFile(join(packageRoot, "amount.android.js"), "export const amount = 99");
|
|
374
|
-
await writeFile(join(packageRoot, "index.js"), `
|
|
375
|
-
import { amount } from './amount'
|
|
376
|
-
const instance = globalThis.moduleInitializations = (globalThis.moduleInitializations || 0) + 1
|
|
377
|
-
export default function calculate(value) { return value + amount }
|
|
378
|
-
export function reads() { return instance }
|
|
379
|
-
`);
|
|
380
|
-
await writeFile(join(root2, "entry.mjs"), `
|
|
381
|
-
import calculate, { reads } from 'pure-math'
|
|
382
|
-
globalThis.calculate = calculate
|
|
383
|
-
globalThis.reads = reads
|
|
384
|
-
if (import.meta.hot) import.meta.hot.accept(() => {})
|
|
385
|
-
`);
|
|
386
|
-
const compiler = await import("@vxrn/compiler");
|
|
387
|
-
compiler.configureVXRNCompilerPlugin({
|
|
388
|
-
enableReanimated: true,
|
|
389
|
-
enableNativeWorklets: true
|
|
390
|
-
});
|
|
391
|
-
let resolveUpdate;
|
|
392
|
-
const updated = new Promise(resolve => {
|
|
393
|
-
resolveUpdate = resolve;
|
|
394
|
-
});
|
|
395
|
-
const native = await createNativeDevEngine({
|
|
396
|
-
root: root2,
|
|
397
|
-
port: 0,
|
|
398
|
-
platform: "ios",
|
|
399
|
-
plugins: [workletImportsPlugin({
|
|
400
|
-
"pure-math": ["default", "reads"]
|
|
401
|
-
}), {
|
|
402
|
-
name: "worklet-import-fixture",
|
|
403
|
-
transform(_code, id) {
|
|
404
|
-
if (id.endsWith("/__virtual-native-entry.tsx")) return `import './entry.mjs'`;
|
|
405
|
-
}
|
|
406
|
-
}],
|
|
407
|
-
onHmrUpdate: resolveUpdate
|
|
408
|
-
});
|
|
409
|
-
try {
|
|
410
|
-
const initial = await native.getBundle();
|
|
411
|
-
const rn = {
|
|
412
|
-
console,
|
|
413
|
-
setTimeout,
|
|
414
|
-
clearTimeout
|
|
415
|
-
};
|
|
416
|
-
runInNewContext(initial.code, rn);
|
|
417
|
-
expect(rn.calculate(10)).toBe(12);
|
|
418
|
-
expect(rn.reads()).toBe(1);
|
|
419
|
-
const ui = createContext({});
|
|
420
|
-
const compiled = /* @__PURE__ */new Map();
|
|
421
|
-
const reconstruct = worklet => {
|
|
422
|
-
if (!worklet.__initData || !worklet.__workletHash) throw new Error("remote function");
|
|
423
|
-
let fn = compiled.get(worklet.__workletHash);
|
|
424
|
-
if (!fn) {
|
|
425
|
-
fn = runInContext(`(${worklet.__initData.code})`, ui);
|
|
426
|
-
compiled.set(worklet.__workletHash, fn);
|
|
427
|
-
}
|
|
428
|
-
const closure = Object.fromEntries(Object.entries(worklet.__closure).map(([name, value]) => [name, typeof value === "function" ? reconstruct(value) : value]));
|
|
429
|
-
return fn.bind({
|
|
430
|
-
__closure: closure
|
|
431
|
-
});
|
|
432
|
-
};
|
|
433
|
-
expect(() => reconstruct(value => value + 2)).toThrow("remote function");
|
|
434
|
-
const old = reconstruct(rn.calculate);
|
|
435
|
-
const oldReads = reconstruct(rn.reads);
|
|
436
|
-
expect(old(10)).toBe(12);
|
|
437
|
-
expect(reconstruct(rn.calculate)(11)).toBe(13);
|
|
438
|
-
expect(oldReads()).toBe(1);
|
|
439
|
-
expect(rn.reads()).toBe(1);
|
|
440
|
-
const runtime = rn.__rolldown_runtime__;
|
|
441
|
-
await native.engine.registerClient(runtime.clientId);
|
|
442
|
-
await writeFile(dependency, "export const amount = 3");
|
|
443
|
-
const update = await updated;
|
|
444
|
-
expect(update.type).toBe("hmr:update");
|
|
445
|
-
expect(runtime.applyHmrUpdate(update.code, update.changedIds, update.seq)).toBe(true);
|
|
446
|
-
expect(rn.calculate(10)).toBe(13);
|
|
447
|
-
const next = reconstruct(rn.calculate);
|
|
448
|
-
expect([old(10), next(10), old(10), next(10)]).toEqual([12, 13, 12, 13]);
|
|
449
|
-
const nextReads = reconstruct(rn.reads);
|
|
450
|
-
expect([oldReads(), nextReads(), oldReads(), nextReads()]).toEqual([1, 2, 1, 2]);
|
|
451
|
-
expect(ui.moduleInitializations).toBe(2);
|
|
452
|
-
expect(rn.reads()).toBe(2);
|
|
453
|
-
await writeFile(join(root2, "production.mjs"), `import calculate, { reads } from 'pure-math'; globalThis.calculate = calculate; globalThis.reads = reads`);
|
|
454
|
-
const production = await buildNativeBundle({
|
|
455
|
-
root: root2,
|
|
456
|
-
platform: "android",
|
|
457
|
-
entryFile: "production.mjs",
|
|
458
|
-
plugins: [workletImportsPlugin({
|
|
459
|
-
"pure-math": ["default", "reads"]
|
|
460
|
-
})]
|
|
461
|
-
});
|
|
462
|
-
expect(production.code).not.toContain("__esmMin");
|
|
463
|
-
const productionRN = {
|
|
464
|
-
console
|
|
465
|
-
};
|
|
466
|
-
runInNewContext(production.code, productionRN);
|
|
467
|
-
expect(productionRN.calculate(10)).toBe(109);
|
|
468
|
-
expect(reconstruct(productionRN.calculate)(10)).toBe(109);
|
|
469
|
-
expect(reconstruct(productionRN.reads)()).toBe(3);
|
|
470
|
-
expect(productionRN.reads()).toBe(1);
|
|
471
|
-
const unminifiedProduction = await buildNativeBundle({
|
|
472
|
-
root: root2,
|
|
473
|
-
platform: "android",
|
|
474
|
-
entryFile: "production.mjs",
|
|
475
|
-
minify: false,
|
|
476
|
-
plugins: [workletImportsPlugin({
|
|
477
|
-
"pure-math": ["default", "reads"]
|
|
478
|
-
})]
|
|
479
|
-
});
|
|
480
|
-
expect(unminifiedProduction.code).toContain("__esmMin");
|
|
481
|
-
const unminifiedRN = {
|
|
482
|
-
console
|
|
483
|
-
};
|
|
484
|
-
runInNewContext(unminifiedProduction.code, unminifiedRN);
|
|
485
|
-
expect(unminifiedRN.calculate(10)).toBe(109);
|
|
486
|
-
expect(reconstruct(unminifiedRN.calculate)(10)).toBe(109);
|
|
487
|
-
expect(reconstruct(unminifiedRN.reads)()).toBe(3);
|
|
488
|
-
const sharedPlugin = workletImportsPlugin({
|
|
489
|
-
"pure-math": ["default", "reads"]
|
|
490
|
-
});
|
|
491
|
-
expect(await Promise.all(["ios", "android"].map(async platform => {
|
|
492
|
-
const output = await buildNativeBundle({
|
|
493
|
-
root: root2,
|
|
494
|
-
platform,
|
|
495
|
-
entryFile: "production.mjs",
|
|
496
|
-
plugins: [sharedPlugin]
|
|
497
|
-
});
|
|
498
|
-
const context = {
|
|
499
|
-
console
|
|
500
|
-
};
|
|
501
|
-
runInNewContext(output.code, context);
|
|
502
|
-
return context.calculate(10);
|
|
503
|
-
}))).toEqual([13, 109]);
|
|
504
|
-
} finally {
|
|
505
|
-
await native.close();
|
|
506
|
-
compiler.configureVXRNCompilerPlugin({
|
|
507
|
-
enableReanimated: false,
|
|
508
|
-
enableNativeWorklets: false
|
|
509
|
-
});
|
|
510
|
-
await rm(root2, {
|
|
511
|
-
recursive: true,
|
|
512
|
-
force: true
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
it.each([["unselected", "export default function value() { return 1 }; export const other = 2", `import { other } from 'pure-math'; globalThis.value = other`, /unselected export other/], ["missing", "export const other = 2", `import value from 'pure-math'; globalThis.value = value`, /default.*not exported|MISSING_EXPORT/], ["builtin", `import fs from 'node:fs'; export default function value() { return fs.readFileSync('x') }`, `import value from 'pure-math'; globalThis.value = value`, /runtime dependency node:fs/], ["global", "export default function value() { return process.pid }", `import value from 'pure-math'; globalThis.value = value`, /unsupported runtime globals: process/], ["dynamic", `export default function value() { return import('./other.js') }`, `import value from 'pure-math'; globalThis.value = value`, /dynamic imports are unsupported/]])("rejects %s through the native engine", async (_name, source, entry, expected) => {
|
|
517
|
-
const root2 = await createWorkletsProject(false);
|
|
518
|
-
const packageRoot = join(root2, "node_modules/pure-math");
|
|
519
|
-
await mkdir(packageRoot, {
|
|
520
|
-
recursive: true
|
|
521
|
-
});
|
|
522
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
523
|
-
type: "module",
|
|
524
|
-
exports: "./index.js"
|
|
525
|
-
}));
|
|
526
|
-
await writeFile(join(packageRoot, "index.js"), source);
|
|
527
|
-
await writeFile(join(root2, "entry.mjs"), entry);
|
|
528
|
-
const compiler = await import("@vxrn/compiler");
|
|
529
|
-
compiler.configureVXRNCompilerPlugin({
|
|
530
|
-
enableReanimated: true,
|
|
531
|
-
enableNativeWorklets: true
|
|
532
|
-
});
|
|
533
|
-
const native = await createNativeDevEngine({
|
|
534
|
-
root: root2,
|
|
535
|
-
port: 0,
|
|
536
|
-
platform: "ios",
|
|
537
|
-
plugins: [workletImportsPlugin({
|
|
538
|
-
"pure-math": ["default"]
|
|
539
|
-
}), {
|
|
540
|
-
name: "worklet-import-negative-fixture",
|
|
541
|
-
transform(_code, id) {
|
|
542
|
-
if (id.endsWith("/__virtual-native-entry.tsx")) return `import './entry.mjs'`;
|
|
543
|
-
}
|
|
544
|
-
}]
|
|
545
|
-
});
|
|
546
|
-
try {
|
|
547
|
-
await expect(native.getBundle()).rejects.toThrow(expected);
|
|
548
|
-
} finally {
|
|
549
|
-
await native.close();
|
|
550
|
-
compiler.configureVXRNCompilerPlugin({
|
|
551
|
-
enableReanimated: false,
|
|
552
|
-
enableNativeWorklets: false
|
|
553
|
-
});
|
|
554
|
-
await rm(root2, {
|
|
555
|
-
recursive: true,
|
|
556
|
-
force: true
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
});
|
|
560
|
-
});
|
|
561
|
-
describe("native Rolldown HMR runtime", () => {
|
|
562
|
-
it.each([true, false])("keeps CommonJS default components callable through the native HMR wire path (Babel=%s)", async babel => {
|
|
563
|
-
const root2 = await mkdtemp(join(tmpdir(), "vxrn-native-hmr-interop-"));
|
|
564
|
-
const entry = join(root2, "entry.mjs");
|
|
565
|
-
const packageRoot = join(root2, "node_modules/component");
|
|
566
|
-
await mkdir(packageRoot, {
|
|
567
|
-
recursive: true
|
|
568
|
-
});
|
|
569
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
570
|
-
main: "./component(view).js"
|
|
571
|
-
}));
|
|
572
|
-
await writeFile(join(packageRoot, "component(view).js"), babel ? `Object.defineProperty(exports, '__esModule', { value: true }); exports.default = function Component() { return 42 }` : `module.exports = function Component() { return 42 }`);
|
|
573
|
-
const source = version => `
|
|
574
|
-
import Component from 'component'
|
|
575
|
-
globalThis.renderComponent = Component
|
|
576
|
-
export const version = ${version}
|
|
577
|
-
if (import.meta.hot) import.meta.hot.accept(() => {})
|
|
578
|
-
`;
|
|
579
|
-
await writeFile(entry, source(1));
|
|
580
|
-
let resolveUpdate;
|
|
581
|
-
const updateReceived = new Promise(resolve => {
|
|
582
|
-
resolveUpdate = resolve;
|
|
583
|
-
});
|
|
584
|
-
const native = await createNativeDevEngine({
|
|
585
|
-
root: root2,
|
|
586
|
-
port: 0,
|
|
587
|
-
platform: "ios",
|
|
588
|
-
plugins: [{
|
|
589
|
-
name: "native-hmr-fixture-entry",
|
|
590
|
-
transform(_code, id) {
|
|
591
|
-
if (id.endsWith("/__virtual-native-entry.tsx")) return `import './entry.mjs'`;
|
|
592
|
-
}
|
|
593
|
-
}],
|
|
594
|
-
onHmrUpdate: resolveUpdate
|
|
595
|
-
});
|
|
596
|
-
try {
|
|
597
|
-
const initial = await native.getBundle();
|
|
598
|
-
const context = {
|
|
599
|
-
console,
|
|
600
|
-
setTimeout,
|
|
601
|
-
clearTimeout
|
|
602
|
-
};
|
|
603
|
-
runInNewContext(initial.code, context);
|
|
604
|
-
expect(context.renderComponent()).toBe(42);
|
|
605
|
-
const runtime = context.__rolldown_runtime__;
|
|
606
|
-
await native.engine.registerClient(runtime.clientId);
|
|
607
|
-
await writeFile(entry, source(2));
|
|
608
|
-
const update = await updateReceived;
|
|
609
|
-
expect(update.type).toBe("hmr:update");
|
|
610
|
-
expect(update.clientId).toBe(runtime.clientId);
|
|
611
|
-
expect(runtime.applyHmrUpdate(update.code, update.changedIds, update.seq)).toBe(true);
|
|
612
|
-
expect(context.renderComponent()).toBe(42);
|
|
613
|
-
} finally {
|
|
614
|
-
await native.close();
|
|
615
|
-
await rm(root2, {
|
|
616
|
-
recursive: true,
|
|
617
|
-
force: true
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
});
|
|
621
|
-
it("registers a Rolldown 1.2 client and applies a self-accepted patch", {
|
|
622
|
-
timeout: 3e4
|
|
623
|
-
}, async () => {
|
|
624
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-hmr-"));
|
|
625
|
-
const entry = join(testRoot, "entry.js");
|
|
626
|
-
const source = version => `
|
|
627
|
-
globalThis.__vxrnHmrBody = '${version}'
|
|
628
|
-
export const value = '${version}'
|
|
629
|
-
if (import.meta.hot) {
|
|
630
|
-
import.meta.hot.accept((next) => {
|
|
631
|
-
globalThis.__vxrnHmrAccepted = next.value
|
|
632
|
-
})
|
|
633
|
-
}
|
|
634
|
-
`;
|
|
635
|
-
await writeFile(entry, source("v1"));
|
|
636
|
-
let resolveInitialOutput;
|
|
637
|
-
const initialOutput = new Promise(resolve => {
|
|
638
|
-
resolveInitialOutput = resolve;
|
|
639
|
-
});
|
|
640
|
-
let resolveHmrUpdate;
|
|
641
|
-
const hmrUpdate = new Promise(resolve => {
|
|
642
|
-
resolveHmrUpdate = resolve;
|
|
643
|
-
});
|
|
644
|
-
let registeredClientId;
|
|
645
|
-
const engine = await dev({
|
|
646
|
-
cwd: testRoot,
|
|
647
|
-
input: entry,
|
|
648
|
-
experimental: {
|
|
649
|
-
devMode: {
|
|
650
|
-
implement: getHmrRuntimeSource()
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}, {
|
|
654
|
-
format: "esm"
|
|
655
|
-
}, {
|
|
656
|
-
onOutput(result) {
|
|
657
|
-
resolveInitialOutput(result);
|
|
658
|
-
},
|
|
659
|
-
onHmrUpdates(result) {
|
|
660
|
-
if (!(result instanceof Error) && result.updates.some(item => item.clientId === registeredClientId && item.update.type === "Patch")) resolveHmrUpdate(result);
|
|
661
|
-
}
|
|
662
|
-
});
|
|
663
|
-
try {
|
|
664
|
-
await engine.run();
|
|
665
|
-
const initial = await initialOutput;
|
|
666
|
-
if (initial instanceof Error) throw initial;
|
|
667
|
-
const chunk = initial.output.find(item => item.type === "chunk" && item.isEntry);
|
|
668
|
-
expect(chunk).toBeTruthy();
|
|
669
|
-
delete globalThis.__rolldown_runtime__;
|
|
670
|
-
await import(`data:text/javascript;base64,${Buffer.from(chunk.code).toString("base64")}`);
|
|
671
|
-
const runtime = globalThis.__rolldown_runtime__;
|
|
672
|
-
expect(typeof runtime.clientId).toBe("string");
|
|
673
|
-
registeredClientId = runtime.clientId;
|
|
674
|
-
await engine.registerClient(runtime.clientId);
|
|
675
|
-
await writeFile(entry, source("v2"));
|
|
676
|
-
const patch = (await Promise.race([hmrUpdate, new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */new Error("timed out waiting for HMR patch")), 1e4))])).updates.find(item => item.clientId === runtime.clientId && item.update.type === "Patch")?.update;
|
|
677
|
-
expect(patch).toBeTruthy();
|
|
678
|
-
const applyHmrUpdate = Reflect.get(runtime, "applyHmrUpdate");
|
|
679
|
-
expect(Reflect.apply(applyHmrUpdate, runtime, [patch.code, patch.changedIds, patch.seq])).toBe(true);
|
|
680
|
-
expect(globalThis.__vxrnHmrBody).toBe("v2");
|
|
681
|
-
expect(globalThis.__vxrnHmrAccepted).toBe("v2");
|
|
682
|
-
} finally {
|
|
683
|
-
await engine.close();
|
|
684
|
-
await rm(testRoot, {
|
|
685
|
-
recursive: true,
|
|
686
|
-
force: true
|
|
687
|
-
});
|
|
688
|
-
delete globalThis.__rolldown_runtime__;
|
|
689
|
-
delete globalThis.__vxrnHmrBody;
|
|
690
|
-
delete globalThis.__vxrnHmrAccepted;
|
|
691
|
-
}
|
|
692
|
-
});
|
|
693
|
-
it("propagates a non-component update to a React Refresh boundary", {
|
|
694
|
-
timeout: 3e4
|
|
695
|
-
}, async () => {
|
|
696
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-refresh-boundary-"));
|
|
697
|
-
const entry = join(testRoot, "entry.js");
|
|
698
|
-
const leaf = join(testRoot, "leaf.js");
|
|
699
|
-
await writeFile(entry, `
|
|
700
|
-
import { value } from './leaf.js'
|
|
701
|
-
globalThis.__vxrnRefreshBoundaryValue = value
|
|
702
|
-
export function App() {}
|
|
703
|
-
if (import.meta.hot) {
|
|
704
|
-
import.meta.hot.acceptReactRefresh(() => {
|
|
705
|
-
globalThis.__vxrnRefreshBoundaryAccepted = true
|
|
706
|
-
})
|
|
707
|
-
}
|
|
708
|
-
`);
|
|
709
|
-
await writeFile(leaf, `export const value = 'v1'`);
|
|
710
|
-
let resolveInitialOutput;
|
|
711
|
-
const initialOutput = new Promise(resolve => {
|
|
712
|
-
resolveInitialOutput = resolve;
|
|
713
|
-
});
|
|
714
|
-
let resolveHmrUpdate;
|
|
715
|
-
const hmrUpdate = new Promise(resolve => {
|
|
716
|
-
resolveHmrUpdate = resolve;
|
|
717
|
-
});
|
|
718
|
-
let registeredClientId;
|
|
719
|
-
const engine = await dev({
|
|
720
|
-
cwd: testRoot,
|
|
721
|
-
input: entry,
|
|
722
|
-
experimental: {
|
|
723
|
-
devMode: {
|
|
724
|
-
implement: getHmrRuntimeSource()
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
}, {
|
|
728
|
-
format: "esm"
|
|
729
|
-
}, {
|
|
730
|
-
onOutput(result) {
|
|
731
|
-
resolveInitialOutput(result);
|
|
732
|
-
},
|
|
733
|
-
onHmrUpdates(result) {
|
|
734
|
-
if (!(result instanceof Error) && result.updates.some(item => item.clientId === registeredClientId && item.update.type === "Patch")) resolveHmrUpdate(result);
|
|
735
|
-
}
|
|
736
|
-
});
|
|
737
|
-
const previousRefreshRuntime = Reflect.get(globalThis, "__ReactRefresh");
|
|
738
|
-
Reflect.set(globalThis, "__ReactRefresh", {
|
|
739
|
-
isLikelyComponentType(value) {
|
|
740
|
-
return typeof value === "function";
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
try {
|
|
744
|
-
await engine.run();
|
|
745
|
-
const initial = await initialOutput;
|
|
746
|
-
if (initial instanceof Error) throw initial;
|
|
747
|
-
const chunk = initial.output.find(item => item.type === "chunk" && item.isEntry);
|
|
748
|
-
expect(chunk).toBeTruthy();
|
|
749
|
-
Reflect.deleteProperty(globalThis, "__rolldown_runtime__");
|
|
750
|
-
await import(`data:text/javascript;base64,${Buffer.from(chunk.code).toString("base64")}`);
|
|
751
|
-
const runtime = Reflect.get(globalThis, "__rolldown_runtime__");
|
|
752
|
-
registeredClientId = runtime.clientId;
|
|
753
|
-
await engine.registerClient(runtime.clientId);
|
|
754
|
-
await writeFile(leaf, `export const value = 'v2'`);
|
|
755
|
-
const patch = (await Promise.race([hmrUpdate, new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */new Error("timed out waiting for HMR patch")), 1e4))])).updates.find(item => item.clientId === runtime.clientId && item.update.type === "Patch")?.update;
|
|
756
|
-
expect(patch).toBeTruthy();
|
|
757
|
-
const applyHmrUpdate = Reflect.get(runtime, "applyHmrUpdate");
|
|
758
|
-
expect(Reflect.apply(applyHmrUpdate, runtime, [patch.code, patch.changedIds, patch.seq])).toBe(true);
|
|
759
|
-
expect(Reflect.get(globalThis, "__vxrnRefreshBoundaryValue")).toBe("v2");
|
|
760
|
-
expect(Reflect.get(globalThis, "__vxrnRefreshBoundaryAccepted")).toBe(true);
|
|
761
|
-
} finally {
|
|
762
|
-
await engine.close();
|
|
763
|
-
await rm(testRoot, {
|
|
764
|
-
recursive: true,
|
|
765
|
-
force: true
|
|
766
|
-
});
|
|
767
|
-
Reflect.deleteProperty(globalThis, "__rolldown_runtime__");
|
|
768
|
-
Reflect.deleteProperty(globalThis, "__vxrnRefreshBoundaryValue");
|
|
769
|
-
Reflect.deleteProperty(globalThis, "__vxrnRefreshBoundaryAccepted");
|
|
770
|
-
if (previousRefreshRuntime === void 0) Reflect.deleteProperty(globalThis, "__ReactRefresh");else Reflect.set(globalThis, "__ReactRefresh", previousRefreshRuntime);
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
});
|
|
774
|
-
describe("native production import.meta lowering", () => {
|
|
775
|
-
it("emits a Hermes-compatible bundle for guarded import.meta.env reads", async () => {
|
|
776
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-import-meta-"));
|
|
777
|
-
await writeFile(join(testRoot, "entry.js"), `globalThis.__vxrnNativeImportMetaProbe = typeof import.meta !== 'undefined' && import.meta.env.DEV`);
|
|
778
|
-
try {
|
|
779
|
-
const result = await buildNativeBundle({
|
|
780
|
-
root: testRoot,
|
|
781
|
-
platform: "ios",
|
|
782
|
-
entryFile: "entry.js"
|
|
783
|
-
});
|
|
784
|
-
expect(result.code).not.toContain("typeof import.meta");
|
|
785
|
-
const context = {
|
|
786
|
-
globalThis: {},
|
|
787
|
-
process: {
|
|
788
|
-
env: {}
|
|
789
|
-
}
|
|
790
|
-
};
|
|
791
|
-
runInNewContext(result.code, context);
|
|
792
|
-
expect(Reflect.get(context.globalThis, "__vxrnNativeImportMetaProbe")).toBe(false);
|
|
793
|
-
} finally {
|
|
794
|
-
await rm(testRoot, {
|
|
795
|
-
recursive: true,
|
|
796
|
-
force: true
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
});
|
|
800
|
-
});
|
|
801
|
-
describe("native animated guard transform", () => {
|
|
802
|
-
it("preserves line count and returns a composable source map", async () => {
|
|
803
|
-
const plugin = nativeAnimatedGuardPlugin();
|
|
804
|
-
if (typeof plugin.transform !== "function") throw new Error("native animated guard transform hook is not callable");
|
|
805
|
-
const source = ["function call(methodName) {", " const method = nullthrows(NativeAnimatedModule)[methodName];", " method();", "}"].join("\n");
|
|
806
|
-
const result = await Reflect.apply(plugin.transform, void 0, [source, "/project/node_modules/react-native/src/private/animated/NativeAnimatedHelper.js"]);
|
|
807
|
-
expect(result.code.split("\n")).toHaveLength(source.split("\n").length);
|
|
808
|
-
expect(result.code).toContain("if (typeof method !== 'function') return");
|
|
809
|
-
expect(result.map).toEqual({
|
|
810
|
-
version: 3,
|
|
811
|
-
sources: ["/project/node_modules/react-native/src/private/animated/NativeAnimatedHelper.js"],
|
|
812
|
-
sourcesContent: [source],
|
|
813
|
-
names: [],
|
|
814
|
-
mappings: "AAAA;AACA;AACA;AACA"
|
|
815
|
-
});
|
|
816
|
-
});
|
|
817
|
-
});
|
|
818
|
-
const root = "/tmp/vxrn-native-env-define-test-nonexistent";
|
|
819
|
-
describe("getNativeTransformConfig platform env defines", () => {
|
|
820
|
-
for (const platform of ["ios", "android"]) for (const dev2 of [true, false]) it(`injects TAMAGUI_TARGET=native for ${platform} (dev=${dev2})`, () => {
|
|
821
|
-
const {
|
|
822
|
-
define
|
|
823
|
-
} = getNativeTransformConfig(platform, dev2, root);
|
|
824
|
-
expect(define["import.meta.env.TAMAGUI_TARGET"]).toBe("\"native\"");
|
|
825
|
-
expect(define["process.env.TAMAGUI_TARGET"]).toBe("\"native\"");
|
|
826
|
-
expect(define["import.meta.env.TAMAGUI_ENVIRONMENT"]).toBe(JSON.stringify(platform));
|
|
827
|
-
expect(define["import.meta.env.VITE_ENVIRONMENT"]).toBe(JSON.stringify(platform));
|
|
828
|
-
expect(define["import.meta.env.VITE_NATIVE"]).toBe("\"1\"");
|
|
829
|
-
expect(define["import.meta.env.EXPO_OS"]).toBe(JSON.stringify(platform));
|
|
830
|
-
const envObject = JSON.parse(define["import.meta.env"]);
|
|
831
|
-
expect(envObject.TAMAGUI_TARGET).toBe("native");
|
|
832
|
-
expect(envObject.TAMAGUI_ENVIRONMENT).toBe(platform);
|
|
833
|
-
});
|
|
834
|
-
it("inlines EXPO_PUBLIC values supplied by the native build environment", () => {
|
|
835
|
-
const key = "EXPO_PUBLIC_VXRN_NATIVE_ENV_PROBE";
|
|
836
|
-
const previous = process.env[key];
|
|
837
|
-
process.env[key] = "native-env-value";
|
|
838
|
-
try {
|
|
839
|
-
const {
|
|
840
|
-
define
|
|
841
|
-
} = getNativeTransformConfig("ios", false, root);
|
|
842
|
-
expect(define[`process.env.${key}`]).toBe("\"native-env-value\"");
|
|
843
|
-
expect(define[`import.meta.env.${key}`]).toBe("\"native-env-value\"");
|
|
844
|
-
expect(JSON.parse(define["import.meta.env"])[key]).toBe("native-env-value");
|
|
845
|
-
} finally {
|
|
846
|
-
if (previous === void 0) delete process.env[key];else process.env[key] = previous;
|
|
847
|
-
}
|
|
848
|
-
});
|
|
849
|
-
it("keeps native platform values authoritative over inherited SSR env", () => {
|
|
850
|
-
const previousEnvironment = process.env.VITE_ENVIRONMENT;
|
|
851
|
-
const previousNative = process.env.VITE_NATIVE;
|
|
852
|
-
process.env.VITE_ENVIRONMENT = "ssr";
|
|
853
|
-
process.env.VITE_NATIVE = "";
|
|
854
|
-
try {
|
|
855
|
-
const {
|
|
856
|
-
define
|
|
857
|
-
} = getNativeTransformConfig("ios", false, root);
|
|
858
|
-
const envObject = JSON.parse(define["import.meta.env"]);
|
|
859
|
-
expect(define["process.env.VITE_ENVIRONMENT"]).toBe("\"ios\"");
|
|
860
|
-
expect(define["import.meta.env.VITE_ENVIRONMENT"]).toBe("\"ios\"");
|
|
861
|
-
expect(define["process.env.VITE_NATIVE"]).toBe("\"1\"");
|
|
862
|
-
expect(define["import.meta.env.VITE_NATIVE"]).toBe("\"1\"");
|
|
863
|
-
expect(envObject.VITE_ENVIRONMENT).toBe("ios");
|
|
864
|
-
expect(envObject.VITE_NATIVE).toBe("1");
|
|
865
|
-
} finally {
|
|
866
|
-
if (previousEnvironment === void 0) delete process.env.VITE_ENVIRONMENT;else process.env.VITE_ENVIRONMENT = previousEnvironment;
|
|
867
|
-
if (previousNative === void 0) delete process.env.VITE_NATIVE;else process.env.VITE_NATIVE = previousNative;
|
|
868
|
-
}
|
|
869
|
-
});
|
|
870
|
-
});
|
|
871
|
-
describe("wrapNativeBundleModuleScope", () => {
|
|
872
|
-
const RUNTIME_MARKER = "//#region \\0rolldown/runtime.js";
|
|
873
|
-
it("wraps module code after the prelude so top-level vars do not leak to global", () => {
|
|
874
|
-
const out = wrapNativeBundleModuleScope(`globalThis.global = globalThis;
|
|
875
|
-
globalThis.__DEV__ = true;
|
|
876
|
-
${RUNTIME_MARKER}
|
|
877
|
-
var fetch_hot, fetch$1, Headers, Request, Response$1;
|
|
878
|
-
globalThis.__rolldown_runtime__ = {};
|
|
879
|
-
`);
|
|
880
|
-
const openIdx = out.indexOf(";(function() {");
|
|
881
|
-
expect(openIdx).toBeGreaterThan(-1);
|
|
882
|
-
expect(out.indexOf("globalThis.__DEV__")).toBeLessThan(openIdx);
|
|
883
|
-
expect(out.indexOf("var fetch_hot")).toBeGreaterThan(openIdx);
|
|
884
|
-
expect(() => new Function(out)).not.toThrow();
|
|
885
|
-
});
|
|
886
|
-
it("is a no-op when the runtime marker is absent (e.g. prod bundle)", () => {
|
|
887
|
-
const input = "var x = 1;\nconsole.log(x);\n";
|
|
888
|
-
expect(wrapNativeBundleModuleScope(input)).toBe(input);
|
|
889
|
-
});
|
|
890
|
-
});
|
|
891
|
-
describe("getHermesSWCIncludes", () => {
|
|
892
|
-
const CLASS_SET = ["transform-classes", "transform-parameters", "transform-block-scoping", "transform-class-properties", "transform-class-static-block", "transform-private-methods", "transform-private-property-in-object"];
|
|
893
|
-
it("always includes the full Hermes class-transform set (dev and prod)", () => {
|
|
894
|
-
expect(getHermesSWCIncludes(true)).toEqual(expect.arrayContaining(CLASS_SET));
|
|
895
|
-
expect(getHermesSWCIncludes(false)).toEqual(expect.arrayContaining(CLASS_SET));
|
|
896
|
-
});
|
|
897
|
-
it("adds transform-async-to-generator in development and production", () => {
|
|
898
|
-
expect(getHermesSWCIncludes(true)).toContain("transform-async-to-generator");
|
|
899
|
-
expect(getHermesSWCIncludes(false)).toContain("transform-async-to-generator");
|
|
900
|
-
});
|
|
901
|
-
it("lowers async generators for the Hermes development interpreter", async () => {
|
|
902
|
-
const plugin = hermesCompatSWCPlugin(true);
|
|
903
|
-
if (typeof plugin.transform !== "function") throw new Error("Hermes compatibility transform hook is not callable");
|
|
904
|
-
const result = await Reflect.apply(plugin.transform, void 0, ["export async function* values() { yield await Promise.resolve(1) }", "/project/async-generator.ts"]);
|
|
905
|
-
expect(result.code).not.toContain("async function*");
|
|
906
|
-
expect(result.code).not.toContain("async function *");
|
|
907
|
-
});
|
|
908
|
-
it("downlevels private fields, public class fields, and static blocks for Hermes", async () => {
|
|
909
|
-
const plugin = hermesCompatSWCPlugin(true);
|
|
910
|
-
if (typeof plugin.transform !== "function") throw new Error("Hermes compatibility transform hook is not callable");
|
|
911
|
-
const result = await Reflect.apply(plugin.transform, void 0, [`
|
|
912
|
-
class TransformProbe {
|
|
913
|
-
#privateField = 1
|
|
914
|
-
publicField = 2
|
|
915
|
-
static {
|
|
916
|
-
TransformProbe.initialized = true
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
getSecret() {
|
|
920
|
-
return this.#privateField
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
`, "/project/TransformProbe.ts"]);
|
|
924
|
-
expect(result.code).not.toContain("#privateField");
|
|
925
|
-
expect(result.code).not.toMatch(/^\s*publicField\s*=/m);
|
|
926
|
-
expect(result.code).not.toContain("static {");
|
|
927
|
-
expect(result.code).toContain("this.publicField = 2");
|
|
928
|
-
});
|
|
929
|
-
it("preserves per-iteration bindings used by lazy method getters", async () => {
|
|
930
|
-
const plugin = hermesCompatSWCPlugin(true);
|
|
931
|
-
if (typeof plugin.transform !== "function") throw new Error("Hermes compatibility transform hook is not callable");
|
|
932
|
-
const result = await Reflect.apply(plugin.transform, void 0, [`
|
|
933
|
-
const installedGroups = new WeakMap()
|
|
934
|
-
function install(inst, methods) {
|
|
935
|
-
const proto = Object.getPrototypeOf(inst)
|
|
936
|
-
for (const key in methods) {
|
|
937
|
-
const fn = methods[key]
|
|
938
|
-
Object.defineProperty(proto, key, {
|
|
939
|
-
get() { return fn.bind(this) }
|
|
940
|
-
})
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
function Schema() {
|
|
944
|
-
install(this, {
|
|
945
|
-
nullish() { return 'nullish' },
|
|
946
|
-
apply(fn) { return fn(this) }
|
|
947
|
-
})
|
|
948
|
-
}
|
|
949
|
-
globalThis.__vxrnBlockScopeProbe = new Schema().nullish()
|
|
950
|
-
`, "/project/block-scope-loop.ts"]);
|
|
951
|
-
try {
|
|
952
|
-
new Function(result.code)();
|
|
953
|
-
expect(Reflect.get(globalThis, "__vxrnBlockScopeProbe")).toBe("nullish");
|
|
954
|
-
} finally {
|
|
955
|
-
Reflect.deleteProperty(globalThis, "__vxrnBlockScopeProbe");
|
|
956
|
-
}
|
|
957
|
-
});
|
|
958
|
-
it("bundles lowered classes whose constructors use default and rest parameters", async () => {
|
|
959
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-hermes-parameters-"));
|
|
960
|
-
const entry = join(testRoot, "entry.js");
|
|
961
|
-
await writeFile(entry, `
|
|
962
|
-
class ParameterProbe {
|
|
963
|
-
prefix = 'value'
|
|
964
|
-
|
|
965
|
-
constructor(value = 'default', ...rest) {
|
|
966
|
-
this.result = [this.prefix, value, ...rest].join(':')
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
export const result = new ParameterProbe(undefined, 'rest-a', 'rest-b').result
|
|
971
|
-
`);
|
|
972
|
-
const build = await rolldown({
|
|
973
|
-
input: entry,
|
|
974
|
-
plugins: [hermesCompatSWCPlugin(true)]
|
|
975
|
-
});
|
|
976
|
-
try {
|
|
977
|
-
const chunk = (await build.generate({
|
|
978
|
-
format: "esm"
|
|
979
|
-
})).output.find(item => item.type === "chunk");
|
|
980
|
-
expect(chunk).toBeTruthy();
|
|
981
|
-
if (!chunk) throw new Error("Rolldown did not emit a JavaScript chunk");
|
|
982
|
-
expect((await import(`data:text/javascript;base64,${Buffer.from(chunk.code).toString("base64")}`)).result).toBe("value:default:rest-a:rest-b");
|
|
983
|
-
} finally {
|
|
984
|
-
await build.close();
|
|
985
|
-
await rm(testRoot, {
|
|
986
|
-
recursive: true,
|
|
987
|
-
force: true
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
});
|
|
991
|
-
});
|
|
992
|
-
describe("hmrClientNoopPlugin", () => {
|
|
993
|
-
const plugin = hmrClientNoopPlugin();
|
|
994
|
-
const resolveId = plugin.resolveId;
|
|
995
|
-
const load = plugin.load;
|
|
996
|
-
const VIRTUAL_ID = "\0vxrn-hmr-client-noop";
|
|
997
|
-
it.each([["react-native/Libraries/Utilities/HMRClient", void 0], ["../Utilities/HMRClient", "/project/node_modules/react-native/Libraries/Core.js"], ["../../Utilities/HMRClient.js", "/project/react-native/Libraries/Core.js"], ["..\\Utilities\\HMRClient.js", "C:\\project\\react-native\\Libraries\\Core.js"], ["../Utilities/HMRClient.ts", "/project/node_modules/react-native/Core.js"], ["../Utilities/HMRClient.tsx", "/project/node_modules/react-native/Core.js"], ["../Utilities/HMRClient.cjs", "/project/node_modules/react-native/Core.js"]])("aliases RN HMRClient specifier %j to the no-op virtual module", (source, importer) => {
|
|
998
|
-
expect(resolveId(source, importer)).toEqual({
|
|
999
|
-
id: VIRTUAL_ID,
|
|
1000
|
-
external: false
|
|
1001
|
-
});
|
|
1002
|
-
});
|
|
1003
|
-
it.each(["react-native/Libraries/Utilities/HMRClientRegistry", "some/MyUtilities/HMRClient", "react-native/Libraries/Core/setUpDeveloperTools", "react"])("does not touch unrelated specifier %j", source => {
|
|
1004
|
-
expect(resolveId(source)).toBeUndefined();
|
|
1005
|
-
});
|
|
1006
|
-
it("does not alias an app-authored Utilities/HMRClient module", () => {
|
|
1007
|
-
expect(resolveId("../Utilities/HMRClient", "/project/src/App.tsx")).toBeUndefined();
|
|
1008
|
-
});
|
|
1009
|
-
it("loads a no-op module exposing every HMRClient method RN calls", () => {
|
|
1010
|
-
const result = load(VIRTUAL_ID);
|
|
1011
|
-
expect(result?.moduleType).toBe("js");
|
|
1012
|
-
for (const method of ["setup", "enable", "disable", "registerBundle", "log", "isEnabled"]) expect(result.code).toContain(method);
|
|
1013
|
-
expect(result.code).toContain("export default HMRClient");
|
|
1014
|
-
});
|
|
1015
|
-
it("does not load unrelated ids", () => {
|
|
1016
|
-
expect(load("\0some-other-virtual")).toBeUndefined();
|
|
1017
|
-
});
|
|
1018
|
-
});
|
|
1019
|
-
describe("vxrnCompilerPlugin React Refresh registration", () => {
|
|
1020
|
-
it("keeps initial-bundle registrations visible to rolldown", async () => {
|
|
1021
|
-
const previousNodeEnv = process.env.NODE_ENV;
|
|
1022
|
-
process.env.NODE_ENV = "test";
|
|
1023
|
-
try {
|
|
1024
|
-
const transform = vxrnCompilerPlugin("ios", true).transform;
|
|
1025
|
-
const code = (await transform("export const marker = \"$RefreshReg$(\"; export function Probe() { return <div>probe</div> }", "/project/src/Probe.tsx")).code;
|
|
1026
|
-
expect(code).toContain("var __vxrnRefreshReg = globalThis.$RefreshReg$");
|
|
1027
|
-
expect(code).toContain("__vxrnRefreshReg(");
|
|
1028
|
-
expect(code).toContain("\"$RefreshReg$(\"");
|
|
1029
|
-
expect(code).toContain("import.meta.hot.acceptReactRefresh(");
|
|
1030
|
-
} finally {
|
|
1031
|
-
process.env.NODE_ENV = previousNodeEnv;
|
|
1032
|
-
}
|
|
1033
|
-
});
|
|
1034
|
-
});
|
|
1035
|
-
describe("native required transform failures", () => {
|
|
1036
|
-
it.each([true, false])("rejects valid worklet source when its required compiler transform fails (dev=%s)", async dev2 => {
|
|
1037
|
-
const testRoot = await createWorkletsProject();
|
|
1038
|
-
const compiler = await import("@vxrn/compiler");
|
|
1039
|
-
const spy = vi.spyOn(compiler, "transformWorklets").mockRejectedValue(/* @__PURE__ */new Error("NATIVE_TRANSFORM_NEGATIVE_CONTROL"));
|
|
1040
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1041
|
-
enableReanimated: true
|
|
1042
|
-
});
|
|
1043
|
-
try {
|
|
1044
|
-
const plugin = vxrnCompilerPlugin("ios", dev2, testRoot);
|
|
1045
|
-
if (typeof plugin.transform !== "function") throw new Error("vxrn compiler transform hook is not callable");
|
|
1046
|
-
await expect(Reflect.apply(plugin.transform, void 0, [nativeTransformProbe, join(testRoot, "entry.ts")])).rejects.toThrow("NATIVE_TRANSFORM_NEGATIVE_CONTROL");
|
|
1047
|
-
} finally {
|
|
1048
|
-
spy.mockRestore();
|
|
1049
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1050
|
-
enableReanimated: false
|
|
1051
|
-
});
|
|
1052
|
-
await rm(testRoot, {
|
|
1053
|
-
recursive: true,
|
|
1054
|
-
force: true
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
|
-
});
|
|
1058
|
-
it("returns a dev build error and no output when the required compiler transform fails", async () => {
|
|
1059
|
-
const testRoot = await createWorkletsProject();
|
|
1060
|
-
const compiler = await import("@vxrn/compiler");
|
|
1061
|
-
const spy = vi.spyOn(compiler, "transformWorklets").mockRejectedValue(/* @__PURE__ */new Error("NATIVE_TRANSFORM_NEGATIVE_CONTROL"));
|
|
1062
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1063
|
-
enableReanimated: true
|
|
1064
|
-
});
|
|
1065
|
-
let resolveOutput;
|
|
1066
|
-
const output = new Promise(resolve => {
|
|
1067
|
-
resolveOutput = resolve;
|
|
1068
|
-
});
|
|
1069
|
-
const engine = await dev({
|
|
1070
|
-
cwd: testRoot,
|
|
1071
|
-
input: join(testRoot, "entry.ts"),
|
|
1072
|
-
plugins: [vxrnCompilerPlugin("ios", true, testRoot)]
|
|
1073
|
-
}, {
|
|
1074
|
-
format: "esm"
|
|
1075
|
-
}, {
|
|
1076
|
-
onOutput: resolveOutput
|
|
1077
|
-
});
|
|
1078
|
-
try {
|
|
1079
|
-
await engine.run();
|
|
1080
|
-
const result = await output;
|
|
1081
|
-
expect(result).toBeInstanceOf(Error);
|
|
1082
|
-
expect(String(result)).toContain("NATIVE_TRANSFORM_NEGATIVE_CONTROL");
|
|
1083
|
-
} finally {
|
|
1084
|
-
spy.mockRestore();
|
|
1085
|
-
await engine.close();
|
|
1086
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1087
|
-
enableReanimated: false
|
|
1088
|
-
});
|
|
1089
|
-
await rm(testRoot, {
|
|
1090
|
-
recursive: true,
|
|
1091
|
-
force: true
|
|
1092
|
-
});
|
|
1093
|
-
}
|
|
1094
|
-
});
|
|
1095
|
-
it("emits no production bundle when the required compiler transform fails", async () => {
|
|
1096
|
-
const testRoot = await createWorkletsProject();
|
|
1097
|
-
const compiler = await import("@vxrn/compiler");
|
|
1098
|
-
const spy = vi.spyOn(compiler, "transformWorklets").mockRejectedValue(/* @__PURE__ */new Error("NATIVE_TRANSFORM_NEGATIVE_CONTROL"));
|
|
1099
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1100
|
-
enableReanimated: true
|
|
1101
|
-
});
|
|
1102
|
-
try {
|
|
1103
|
-
await expect(buildNativeBundle({
|
|
1104
|
-
root: testRoot,
|
|
1105
|
-
platform: "ios",
|
|
1106
|
-
entryFile: "entry.ts"
|
|
1107
|
-
})).rejects.toThrow("NATIVE_TRANSFORM_NEGATIVE_CONTROL");
|
|
1108
|
-
} finally {
|
|
1109
|
-
spy.mockRestore();
|
|
1110
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1111
|
-
enableReanimated: false
|
|
1112
|
-
});
|
|
1113
|
-
await rm(testRoot, {
|
|
1114
|
-
recursive: true,
|
|
1115
|
-
force: true
|
|
1116
|
-
});
|
|
1117
|
-
}
|
|
1118
|
-
});
|
|
1119
|
-
it("rejects Hermes compatibility transform errors instead of returning source", async () => {
|
|
1120
|
-
const plugin = hermesCompatSWCPlugin(true);
|
|
1121
|
-
if (typeof plugin.transform !== "function") throw new Error("Hermes compatibility transform hook is not callable");
|
|
1122
|
-
await expect(Reflect.apply(plugin.transform, void 0, ["class TransformProbe { value = ; }", "/project/TransformProbe.ts"])).rejects.toBeTruthy();
|
|
1123
|
-
});
|
|
1124
|
-
it("returns maps for every required production transform", async () => {
|
|
1125
|
-
const testRoot = await createWorkletsProject(false);
|
|
1126
|
-
const compiler = await import("@vxrn/compiler");
|
|
1127
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1128
|
-
enableReanimated: true
|
|
1129
|
-
});
|
|
1130
|
-
try {
|
|
1131
|
-
const compilerPlugin = vxrnCompilerPlugin("ios", false, testRoot, true);
|
|
1132
|
-
if (typeof compilerPlugin.transform !== "function") throw new Error("vxrn compiler transform hook is not callable");
|
|
1133
|
-
expect((await Reflect.apply(compilerPlugin.transform, void 0, [nativeTransformProbe, join(testRoot, "entry.ts")])).map).toBeTruthy();
|
|
1134
|
-
const hermesPlugin = hermesCompatSWCPlugin(false, true);
|
|
1135
|
-
if (typeof hermesPlugin.transform !== "function") throw new Error("Hermes compatibility transform hook is not callable");
|
|
1136
|
-
expect((await Reflect.apply(hermesPlugin.transform, void 0, ["export class TransformProbe { value = 1 }", join(testRoot, "TransformProbe.ts")])).map).toBeTruthy();
|
|
1137
|
-
} finally {
|
|
1138
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1139
|
-
enableReanimated: false
|
|
1140
|
-
});
|
|
1141
|
-
await rm(testRoot, {
|
|
1142
|
-
recursive: true,
|
|
1143
|
-
force: true
|
|
1144
|
-
});
|
|
1145
|
-
}
|
|
1146
|
-
});
|
|
1147
|
-
it("composes source maps across React Compiler, Fast Refresh, and module wrapper back to original source lines", async () => {
|
|
1148
|
-
const {
|
|
1149
|
-
TraceMap: TraceMap2,
|
|
1150
|
-
originalPositionFor: originalPositionFor2
|
|
1151
|
-
} = await import("@jridgewell/trace-mapping");
|
|
1152
|
-
const compiler = await import("@vxrn/compiler");
|
|
1153
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1154
|
-
enableCompiler: true
|
|
1155
|
-
});
|
|
1156
|
-
try {
|
|
1157
|
-
const plugin = vxrnCompilerPlugin("ios", true, "/project", true);
|
|
1158
|
-
if (typeof plugin.transform !== "function") throw new Error("transform hook not callable");
|
|
1159
|
-
const inputCode = `import { useState } from 'react'
|
|
1160
|
-
|
|
1161
|
-
export function Counter() {
|
|
1162
|
-
const [count, setCount] = useState(0)
|
|
1163
|
-
return <button onClick={() => setCount(count + 1)}>{count}</button>
|
|
1164
|
-
}
|
|
1165
|
-
`;
|
|
1166
|
-
const id = "/project/Counter.tsx";
|
|
1167
|
-
const result = await Reflect.apply(plugin.transform, void 0, [inputCode, id]);
|
|
1168
|
-
expect(result).toBeDefined();
|
|
1169
|
-
expect(result.map).toBeDefined();
|
|
1170
|
-
const tracer = new TraceMap2(result.map);
|
|
1171
|
-
const counterLineIndex = result.code.split("\n").findIndex(l => l.includes("function Counter"));
|
|
1172
|
-
expect(counterLineIndex).toBeGreaterThan(0);
|
|
1173
|
-
const pos = originalPositionFor2(tracer, {
|
|
1174
|
-
line: counterLineIndex + 1,
|
|
1175
|
-
column: 16
|
|
1176
|
-
});
|
|
1177
|
-
expect(pos.source).toBe(id);
|
|
1178
|
-
expect(pos.line).toBe(3);
|
|
1179
|
-
} finally {
|
|
1180
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1181
|
-
enableCompiler: false
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
});
|
|
1185
|
-
it("composes source maps accurately across mixed path (React Compiler + Babel + Fast Refresh + module wrapper)", async () => {
|
|
1186
|
-
const {
|
|
1187
|
-
TraceMap: TraceMap2,
|
|
1188
|
-
originalPositionFor: originalPositionFor2
|
|
1189
|
-
} = await import("@jridgewell/trace-mapping");
|
|
1190
|
-
const compiler = await import("@vxrn/compiler");
|
|
1191
|
-
const origEnv = process.env.VXRN_USE_BABEL_FOR_GENERATORS;
|
|
1192
|
-
process.env.VXRN_USE_BABEL_FOR_GENERATORS = "1";
|
|
1193
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1194
|
-
enableCompiler: true,
|
|
1195
|
-
enableReanimated: false
|
|
1196
|
-
});
|
|
1197
|
-
try {
|
|
1198
|
-
const plugin = vxrnCompilerPlugin("ios", true, "/project", true);
|
|
1199
|
-
if (typeof plugin.transform !== "function") throw new Error("transform hook not callable");
|
|
1200
|
-
const inputCode = `export function Counter() { return <View />; }
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
export async function* probe() { throw new Error("MARKER"); }
|
|
1209
|
-
`;
|
|
1210
|
-
const id = "/project/Counter.tsx";
|
|
1211
|
-
const result = await Reflect.apply(plugin.transform, void 0, [inputCode, id]);
|
|
1212
|
-
expect(result).toBeDefined();
|
|
1213
|
-
expect(result.map).toBeDefined();
|
|
1214
|
-
expect(result.code.includes("_wrapAsyncGenerator") || result.code.includes("regeneratorRuntime")).toBe(true);
|
|
1215
|
-
const tracer = new TraceMap2(result.map);
|
|
1216
|
-
const lines = result.code.split("\n");
|
|
1217
|
-
const markerLineIndex = lines.findIndex(l => l.includes("MARKER"));
|
|
1218
|
-
expect(markerLineIndex).toBeGreaterThan(0);
|
|
1219
|
-
const markerCol = lines[markerLineIndex].indexOf("throw");
|
|
1220
|
-
const pos = originalPositionFor2(tracer, {
|
|
1221
|
-
line: markerLineIndex + 1,
|
|
1222
|
-
column: markerCol
|
|
1223
|
-
});
|
|
1224
|
-
expect(pos.source).toBe(id);
|
|
1225
|
-
expect(pos.line).toBe(9);
|
|
1226
|
-
expect(pos.column).toBe(33);
|
|
1227
|
-
const compilerOut = await compiler.transformOxcReactCompiler(id, inputCode, "19", true);
|
|
1228
|
-
const remapping = (await import("@jridgewell/remapping")).default;
|
|
1229
|
-
const badPos = originalPositionFor2(new TraceMap2(remapping([result.map, compilerOut.map], () => null)), {
|
|
1230
|
-
line: markerLineIndex + 1,
|
|
1231
|
-
column: markerCol
|
|
1232
|
-
});
|
|
1233
|
-
expect(badPos.source).toBeNull();
|
|
1234
|
-
expect(badPos.line).toBeNull();
|
|
1235
|
-
} finally {
|
|
1236
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1237
|
-
enableCompiler: false
|
|
1238
|
-
});
|
|
1239
|
-
if (origEnv !== void 0) process.env.VXRN_USE_BABEL_FOR_GENERATORS = origEnv;else delete process.env.VXRN_USE_BABEL_FOR_GENERATORS;
|
|
1240
|
-
}
|
|
1241
|
-
});
|
|
1242
|
-
it("transforms worklets via native Rust/Wasm SWC with zero Babel execution and accurate sourcemaps", async () => {
|
|
1243
|
-
const {
|
|
1244
|
-
TraceMap: TraceMap2,
|
|
1245
|
-
originalPositionFor: originalPositionFor2
|
|
1246
|
-
} = await import("@jridgewell/trace-mapping");
|
|
1247
|
-
const compiler = await import("@vxrn/compiler");
|
|
1248
|
-
const {
|
|
1249
|
-
vi: vi2
|
|
1250
|
-
} = await import("vitest");
|
|
1251
|
-
const babelSpy = vi2.spyOn(compiler, "transformBabel");
|
|
1252
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1253
|
-
enableReanimated: true,
|
|
1254
|
-
enableNativeWorklets: true,
|
|
1255
|
-
enableCompiler: false
|
|
1256
|
-
});
|
|
1257
|
-
try {
|
|
1258
|
-
const projectRoot = process.cwd();
|
|
1259
|
-
const plugin = vxrnCompilerPlugin("ios", true, projectRoot, true);
|
|
1260
|
-
if (typeof plugin.transform !== "function") throw new Error("transform hook not callable");
|
|
1261
|
-
const inputCode = `import { useAnimatedStyle } from 'react-native-reanimated'
|
|
1262
|
-
|
|
1263
|
-
export function Box() {
|
|
1264
|
-
const animatedStyle = useAnimatedStyle(() => {
|
|
1265
|
-
return { opacity: 1 }
|
|
1266
|
-
})
|
|
1267
|
-
return <div style={animatedStyle} />
|
|
1268
|
-
}
|
|
1269
|
-
`;
|
|
1270
|
-
const id = join(projectRoot, "Box.tsx");
|
|
1271
|
-
const result = await Reflect.apply(plugin.transform, void 0, [inputCode, id]);
|
|
1272
|
-
expect(result).toBeDefined();
|
|
1273
|
-
expect(result.code).toContain("__workletHash");
|
|
1274
|
-
expect(result.code).toContain("__closure");
|
|
1275
|
-
expect(babelSpy).not.toHaveBeenCalled();
|
|
1276
|
-
expect(result.map).toBeDefined();
|
|
1277
|
-
const tracer = new TraceMap2(result.map);
|
|
1278
|
-
const boxLineIndex = result.code.split("\n").findIndex(l => l.includes("export function Box"));
|
|
1279
|
-
expect(boxLineIndex).toBeGreaterThan(0);
|
|
1280
|
-
const pos = originalPositionFor2(tracer, {
|
|
1281
|
-
line: boxLineIndex + 1,
|
|
1282
|
-
column: 16
|
|
1283
|
-
});
|
|
1284
|
-
expect(pos.source).toBe(id);
|
|
1285
|
-
expect(pos.line).toBe(3);
|
|
1286
|
-
} finally {
|
|
1287
|
-
babelSpy.mockRestore();
|
|
1288
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1289
|
-
enableReanimated: false,
|
|
1290
|
-
enableNativeWorklets: false
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
|
-
});
|
|
1294
|
-
it("retains the existing Babel backend by default when enableNativeWorklets is false for auto-detected Reanimated and ordinary configured worklets plugin", async () => {
|
|
1295
|
-
const compiler = await import("@vxrn/compiler");
|
|
1296
|
-
const {
|
|
1297
|
-
vi: vi2
|
|
1298
|
-
} = await import("vitest");
|
|
1299
|
-
const babelSpy = vi2.spyOn(compiler, "transformBabel").mockResolvedValue({
|
|
1300
|
-
code: "/* babel transformed */"
|
|
1301
|
-
});
|
|
1302
|
-
const workletSpy = vi2.spyOn(compiler, "transformWorklets");
|
|
1303
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1304
|
-
enableReanimated: true,
|
|
1305
|
-
enableNativeWorklets: false
|
|
1306
|
-
});
|
|
1307
|
-
const getBabelOptionsSpy = vi2.spyOn(compiler, "getBabelOptions").mockReturnValue({
|
|
1308
|
-
plugins: ["react-native-reanimated/plugin"]
|
|
1309
|
-
});
|
|
1310
|
-
try {
|
|
1311
|
-
const projectRoot = process.cwd();
|
|
1312
|
-
const plugin = vxrnCompilerPlugin("ios", true, projectRoot, false);
|
|
1313
|
-
if (typeof plugin.transform !== "function") throw new Error("transform hook not callable");
|
|
1314
|
-
const inputCode = `export function fn() { 'worklet'; return 1 }`;
|
|
1315
|
-
const id = join(projectRoot, "DefaultWorklet.tsx");
|
|
1316
|
-
expect(await Reflect.apply(plugin.transform, void 0, [inputCode, id])).toBeDefined();
|
|
1317
|
-
expect(babelSpy).toHaveBeenCalledWith(id, inputCode, expect.objectContaining({
|
|
1318
|
-
plugins: expect.arrayContaining(["react-native-reanimated/plugin"])
|
|
1319
|
-
}));
|
|
1320
|
-
expect(workletSpy).not.toHaveBeenCalled();
|
|
1321
|
-
} finally {
|
|
1322
|
-
babelSpy.mockRestore();
|
|
1323
|
-
workletSpy.mockRestore();
|
|
1324
|
-
getBabelOptionsSpy.mockRestore();
|
|
1325
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1326
|
-
enableReanimated: false,
|
|
1327
|
-
enableNativeWorklets: false
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
});
|
|
1331
|
-
it("intercepts tuple worklet plugins with options, executes native SWC with options, and skips Babel when enableNativeWorklets is true", async () => {
|
|
1332
|
-
const compiler = await import("@vxrn/compiler");
|
|
1333
|
-
const {
|
|
1334
|
-
vi: vi2
|
|
1335
|
-
} = await import("vitest");
|
|
1336
|
-
const babelSpy = vi2.spyOn(compiler, "transformBabel");
|
|
1337
|
-
const workletSpy = vi2.spyOn(compiler, "transformWorklets");
|
|
1338
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1339
|
-
enableReanimated: true,
|
|
1340
|
-
enableNativeWorklets: true
|
|
1341
|
-
});
|
|
1342
|
-
const getBabelOptionsSpy = vi2.spyOn(compiler, "getBabelOptions").mockReturnValue({
|
|
1343
|
-
plugins: [["react-native-reanimated/plugin", {
|
|
1344
|
-
globals: ["customGlobal"]
|
|
1345
|
-
}]]
|
|
1346
|
-
});
|
|
1347
|
-
try {
|
|
1348
|
-
const projectRoot = process.cwd();
|
|
1349
|
-
const plugin = vxrnCompilerPlugin("ios", true, projectRoot, false);
|
|
1350
|
-
if (typeof plugin.transform !== "function") throw new Error("transform hook not callable");
|
|
1351
|
-
const inputCode = `export function fn() { 'worklet'; return customGlobal * 2 }`;
|
|
1352
|
-
const id = join(projectRoot, "TupleWorklet.tsx");
|
|
1353
|
-
const result = await Reflect.apply(plugin.transform, void 0, [inputCode, id]);
|
|
1354
|
-
expect(result).toBeDefined();
|
|
1355
|
-
expect(result.code).toContain("__workletHash");
|
|
1356
|
-
expect(workletSpy).toHaveBeenCalledWith(id, expect.any(String), false, expect.objectContaining({
|
|
1357
|
-
globals: ["customGlobal"],
|
|
1358
|
-
projectRoot
|
|
1359
|
-
}));
|
|
1360
|
-
expect(babelSpy).not.toHaveBeenCalled();
|
|
1361
|
-
} finally {
|
|
1362
|
-
babelSpy.mockRestore();
|
|
1363
|
-
workletSpy.mockRestore();
|
|
1364
|
-
getBabelOptionsSpy.mockRestore();
|
|
1365
|
-
compiler.configureVXRNCompilerPlugin({
|
|
1366
|
-
enableReanimated: false,
|
|
1367
|
-
enableNativeWorklets: false
|
|
1368
|
-
});
|
|
1369
|
-
}
|
|
1370
|
-
});
|
|
1371
|
-
});
|
|
1372
|
-
describe("native production minification", () => {
|
|
1373
|
-
async function writeMinifyFixture() {
|
|
1374
|
-
const root2 = await mkdtemp(join(tmpdir(), "vxrn-native-minify-"));
|
|
1375
|
-
const dep = join(root2, "node_modules", "legacy-color");
|
|
1376
|
-
await mkdir(dep, {
|
|
1377
|
-
recursive: true
|
|
1378
|
-
});
|
|
1379
|
-
await writeFile(join(dep, "package.json"), JSON.stringify({
|
|
1380
|
-
name: "legacy-color",
|
|
1381
|
-
main: "index.js"
|
|
1382
|
-
}));
|
|
1383
|
-
await writeFile(join(dep, "index.js"), `function LegacyColor(value) { this.value = value }
|
|
1384
|
-
LegacyColor.prototype.describe = function () { return 'legacy:' + this.value }
|
|
1385
|
-
module.exports = LegacyColor`);
|
|
1386
|
-
await writeFile(join(root2, "views.js"), `'use strict';
|
|
1387
|
-
import LegacyColor from 'legacy-color'
|
|
1388
|
-
import { level } from './entry.js'
|
|
1389
|
-
export const describeHeader = () => new LegacyColor(level()).describe()`);
|
|
1390
|
-
await writeFile(join(root2, "entry.js"), `import { describeHeader } from './views.js'
|
|
1391
|
-
export const level = () => 'header'
|
|
1392
|
-
globalThis.minifyProbe = describeHeader()`);
|
|
1393
|
-
return root2;
|
|
1394
|
-
}
|
|
1395
|
-
function runFixture(code) {
|
|
1396
|
-
const context = {
|
|
1397
|
-
console
|
|
1398
|
-
};
|
|
1399
|
-
runInNewContext(code, context);
|
|
1400
|
-
return Reflect.get(context, "minifyProbe");
|
|
1401
|
-
}
|
|
1402
|
-
it("minifies when asked, leaves the bundle alone when not, and both behave the same", async () => {
|
|
1403
|
-
const root2 = await writeMinifyFixture();
|
|
1404
|
-
try {
|
|
1405
|
-
const [plain, minified] = await Promise.all([false, true].map(minify => buildNativeBundle({
|
|
1406
|
-
root: root2,
|
|
1407
|
-
platform: "ios",
|
|
1408
|
-
entryFile: "entry.js",
|
|
1409
|
-
minify
|
|
1410
|
-
})));
|
|
1411
|
-
expect(plain.code).toContain("__toESM");
|
|
1412
|
-
expect(plain.code).toContain("describeHeader");
|
|
1413
|
-
expect(plain.code.split("\n").length).toBeGreaterThan(40);
|
|
1414
|
-
expect(minified.code).not.toContain("describeHeader");
|
|
1415
|
-
expect(minified.code).not.toContain("//#region");
|
|
1416
|
-
expect(minified.code.length).toBeLessThan(plain.code.length * .7);
|
|
1417
|
-
expect(runFixture(minified.code)).toBe("legacy:header");
|
|
1418
|
-
expect(runFixture(plain.code)).toBe("legacy:header");
|
|
1419
|
-
} finally {
|
|
1420
|
-
await rm(root2, {
|
|
1421
|
-
recursive: true,
|
|
1422
|
-
force: true
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1425
|
-
});
|
|
1426
|
-
it("defaults to react native's rule: minify a production bundle, never a dev one", async () => {
|
|
1427
|
-
const root2 = await writeMinifyFixture();
|
|
1428
|
-
try {
|
|
1429
|
-
const [prod, devBundle, explicitOff] = await Promise.all([buildNativeBundle({
|
|
1430
|
-
root: root2,
|
|
1431
|
-
platform: "ios",
|
|
1432
|
-
entryFile: "entry.js"
|
|
1433
|
-
}), buildNativeBundle({
|
|
1434
|
-
root: root2,
|
|
1435
|
-
platform: "ios",
|
|
1436
|
-
entryFile: "entry.js",
|
|
1437
|
-
dev: true
|
|
1438
|
-
}), buildNativeBundle({
|
|
1439
|
-
root: root2,
|
|
1440
|
-
platform: "ios",
|
|
1441
|
-
entryFile: "entry.js",
|
|
1442
|
-
minify: false
|
|
1443
|
-
})]);
|
|
1444
|
-
expect(prod.code).not.toContain("describeHeader");
|
|
1445
|
-
expect(devBundle.code).toContain("describeHeader");
|
|
1446
|
-
expect(explicitOff.code).toContain("describeHeader");
|
|
1447
|
-
expect(prod.code.length).toBeLessThan(explicitOff.code.length);
|
|
1448
|
-
} finally {
|
|
1449
|
-
await rm(root2, {
|
|
1450
|
-
recursive: true,
|
|
1451
|
-
force: true
|
|
1452
|
-
});
|
|
1453
|
-
}
|
|
1454
|
-
});
|
|
1455
|
-
});
|
|
1456
|
-
describe("native production assets", () => {
|
|
1457
|
-
it("registers scale siblings and keeps monorepo assets inside assetsDest", async () => {
|
|
1458
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-assets-"));
|
|
1459
|
-
const appRoot = join(testRoot, "workspace/apps/native-app");
|
|
1460
|
-
const appAssets = join(appRoot, "assets");
|
|
1461
|
-
const packageAssets = join(testRoot, "workspace/node_modules/example/assets");
|
|
1462
|
-
const assetsDest = join(testRoot, "output");
|
|
1463
|
-
await mkdir(appAssets, {
|
|
1464
|
-
recursive: true
|
|
1465
|
-
});
|
|
1466
|
-
await mkdir(packageAssets, {
|
|
1467
|
-
recursive: true
|
|
1468
|
-
});
|
|
1469
|
-
await writeFile(join(appAssets, "icon.png"), "icon-1x");
|
|
1470
|
-
await writeFile(join(appAssets, "icon@2x.png"), "icon-2x");
|
|
1471
|
-
await writeFile(join(appAssets, "icon@3x.png"), "icon-3x");
|
|
1472
|
-
await writeFile(join(packageAssets, "back.png"), "back-1x");
|
|
1473
|
-
await writeFile(join(packageAssets, "back@2x.png"), "back-2x");
|
|
1474
|
-
await writeFile(join(appRoot, "entry.js"), `
|
|
1475
|
-
import icon from './assets/icon.png'
|
|
1476
|
-
import back from '../../node_modules/example/assets/back.png'
|
|
1477
|
-
globalThis.__nativeAssetProbe = [icon, back]
|
|
1478
|
-
`);
|
|
1479
|
-
try {
|
|
1480
|
-
const assetData = await getNativeAssetData(join(appAssets, "icon.png"), appRoot, "ios");
|
|
1481
|
-
expect(assetData.scales).toEqual([1, 2, 3]);
|
|
1482
|
-
expect(assetData.files.map(file => file.slice(appAssets.length + 1))).toEqual(["icon.png", "icon@2x.png", "icon@3x.png"]);
|
|
1483
|
-
expect(assetData.hash).not.toBe("");
|
|
1484
|
-
const registry = createNativeDevAssetRegistry();
|
|
1485
|
-
registry.register(assetData);
|
|
1486
|
-
expect(registry.resolve("/assets/assets/icon@2x.png", assetData.hash)?.filePath).toBe(join(appAssets, "icon@2x.png"));
|
|
1487
|
-
expect(registry.resolve("/assets/assets/icon.png", "stale-content-hash")).toBeUndefined();
|
|
1488
|
-
expect(registry.resolve("/assets/../../package.json", assetData.hash)).toBeUndefined();
|
|
1489
|
-
const result = await buildNativeBundle({
|
|
1490
|
-
root: appRoot,
|
|
1491
|
-
platform: "ios",
|
|
1492
|
-
entryFile: "entry.js",
|
|
1493
|
-
assetsDest
|
|
1494
|
-
});
|
|
1495
|
-
const registered = [];
|
|
1496
|
-
runInNewContext(result.code, {
|
|
1497
|
-
console,
|
|
1498
|
-
require: id => id === "react-native/Libraries/Image/AssetRegistry" ? {
|
|
1499
|
-
registerAsset: asset => {
|
|
1500
|
-
registered.push(asset);
|
|
1501
|
-
return asset;
|
|
1502
|
-
}
|
|
1503
|
-
} : {}
|
|
1504
|
-
});
|
|
1505
|
-
expect(registered.map(asset => [asset.name, asset.scales])).toEqual([["icon", [1, 2, 3]], ["back", [1, 2]]]);
|
|
1506
|
-
for (const file of ["icon.png", "icon@2x.png", "icon@3x.png"]) expect(existsSync(join(assetsDest, "assets/assets", file))).toBe(true);
|
|
1507
|
-
for (const file of ["back.png", "back@2x.png"]) expect(existsSync(join(assetsDest, "assets/_/_/node_modules/example/assets", file))).toBe(true);
|
|
1508
|
-
expect(existsSync(join(testRoot, "node_modules/example/assets/back.png"))).toBe(false);
|
|
1509
|
-
} finally {
|
|
1510
|
-
await rm(testRoot, {
|
|
1511
|
-
recursive: true,
|
|
1512
|
-
force: true
|
|
1513
|
-
});
|
|
1514
|
-
}
|
|
1515
|
-
});
|
|
1516
|
-
});
|
|
1517
|
-
describe("native conditional exports", () => {
|
|
1518
|
-
it("uses the require condition for CommonJS calls", async () => {
|
|
1519
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-conditions-"));
|
|
1520
|
-
const packageRoot = join(testRoot, "node_modules/conditional-helper");
|
|
1521
|
-
await mkdir(packageRoot, {
|
|
1522
|
-
recursive: true
|
|
1523
|
-
});
|
|
1524
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
1525
|
-
name: "conditional-helper",
|
|
1526
|
-
exports: {
|
|
1527
|
-
".": {
|
|
1528
|
-
import: "./esm.js",
|
|
1529
|
-
require: "./cjs.cjs"
|
|
1530
|
-
}
|
|
1531
|
-
},
|
|
1532
|
-
type: "module"
|
|
1533
|
-
}));
|
|
1534
|
-
await writeFile(join(packageRoot, "esm.js"), `export default function helper() { return 'import' }`);
|
|
1535
|
-
await writeFile(join(packageRoot, "cjs.cjs"), `module.exports = function helper() { return 'require' }`);
|
|
1536
|
-
await writeFile(join(testRoot, "entry.cjs"), `
|
|
1537
|
-
const helper = require('conditional-helper')
|
|
1538
|
-
globalThis.__vxrnConditionalExportProbe = helper()
|
|
1539
|
-
`);
|
|
1540
|
-
try {
|
|
1541
|
-
const result = await buildNativeBundle({
|
|
1542
|
-
root: testRoot,
|
|
1543
|
-
platform: "ios",
|
|
1544
|
-
entryFile: "entry.cjs",
|
|
1545
|
-
dev: true
|
|
1546
|
-
});
|
|
1547
|
-
const context = {
|
|
1548
|
-
clearTimeout,
|
|
1549
|
-
console,
|
|
1550
|
-
process: {
|
|
1551
|
-
env: {}
|
|
1552
|
-
},
|
|
1553
|
-
setTimeout
|
|
1554
|
-
};
|
|
1555
|
-
runInNewContext(result.code, context);
|
|
1556
|
-
expect(Reflect.get(context, "__vxrnConditionalExportProbe")).toBe("require");
|
|
1557
|
-
} finally {
|
|
1558
|
-
await rm(testRoot, {
|
|
1559
|
-
recursive: true,
|
|
1560
|
-
force: true
|
|
1561
|
-
});
|
|
1562
|
-
}
|
|
1563
|
-
});
|
|
1564
|
-
it("unwraps the default export of Babel CommonJS modules in dev output", {
|
|
1565
|
-
timeout: 3e4
|
|
1566
|
-
}, async () => {
|
|
1567
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-cjs-default-"));
|
|
1568
|
-
const packageRoot = join(testRoot, "node_modules/default-export-helper");
|
|
1569
|
-
await mkdir(packageRoot, {
|
|
1570
|
-
recursive: true
|
|
1571
|
-
});
|
|
1572
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
1573
|
-
name: "default-export-helper",
|
|
1574
|
-
main: "./index.js"
|
|
1575
|
-
}));
|
|
1576
|
-
await writeFile(join(packageRoot, "index.js"), `Object.defineProperty(exports, '__esModule', { value: true }); exports.default = function Component() {}`);
|
|
1577
|
-
await writeFile(join(testRoot, "entry.js"), `import Component from 'default-export-helper'; globalThis.__vxrnCjsDefaultProbe = typeof Component`);
|
|
1578
|
-
let resolveOutput;
|
|
1579
|
-
const output = new Promise(resolve => {
|
|
1580
|
-
resolveOutput = resolve;
|
|
1581
|
-
});
|
|
1582
|
-
const engine = await dev({
|
|
1583
|
-
cwd: testRoot,
|
|
1584
|
-
input: join(testRoot, "entry.js"),
|
|
1585
|
-
experimental: {
|
|
1586
|
-
devMode: {
|
|
1587
|
-
implement: getHmrRuntimeSource()
|
|
1588
|
-
}
|
|
1589
|
-
}
|
|
1590
|
-
}, {
|
|
1591
|
-
format: "esm",
|
|
1592
|
-
codeSplitting: false,
|
|
1593
|
-
strictExecutionOrder: true
|
|
1594
|
-
}, {
|
|
1595
|
-
onOutput: resolveOutput
|
|
1596
|
-
});
|
|
1597
|
-
try {
|
|
1598
|
-
await engine.run();
|
|
1599
|
-
const result = await output;
|
|
1600
|
-
if (result instanceof Error) throw result;
|
|
1601
|
-
const chunk = result.output.find(item => item.type === "chunk" && item.isEntry);
|
|
1602
|
-
if (!chunk || chunk.type !== "chunk") throw new Error("Rolldown did not emit a native dev entry chunk");
|
|
1603
|
-
const nodeModeCode = chunk.code.replace(/(\b__toESM(?:\$\d+)?\(\s*require[\w$]*\(\)\s*)\)/, "$1, 1)");
|
|
1604
|
-
expect(nodeModeCode).not.toBe(chunk.code);
|
|
1605
|
-
Reflect.deleteProperty(globalThis, "__rolldown_runtime__");
|
|
1606
|
-
await import(`data:text/javascript;base64,${Buffer.from(nodeModeCode).toString("base64")}`);
|
|
1607
|
-
expect(Reflect.get(globalThis, "__vxrnCjsDefaultProbe")).toBe("object");
|
|
1608
|
-
Reflect.deleteProperty(globalThis, "__rolldown_runtime__");
|
|
1609
|
-
Reflect.deleteProperty(globalThis, "__vxrnCjsDefaultProbe");
|
|
1610
|
-
const normalized = normalizeNativeCommonJSInterop(nodeModeCode);
|
|
1611
|
-
await import(`data:text/javascript;base64,${Buffer.from(normalized).toString("base64")}`);
|
|
1612
|
-
expect(Reflect.get(globalThis, "__vxrnCjsDefaultProbe")).toBe("function");
|
|
1613
|
-
} finally {
|
|
1614
|
-
await engine.close();
|
|
1615
|
-
Reflect.deleteProperty(globalThis, "__rolldown_runtime__");
|
|
1616
|
-
Reflect.deleteProperty(globalThis, "__vxrnCjsDefaultProbe");
|
|
1617
|
-
await rm(testRoot, {
|
|
1618
|
-
recursive: true,
|
|
1619
|
-
force: true
|
|
1620
|
-
});
|
|
1621
|
-
}
|
|
1622
|
-
});
|
|
1623
|
-
it("unwraps the default export of Babel CommonJS modules in production output", async () => {
|
|
1624
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-prod-cjs-default-"));
|
|
1625
|
-
const packageRoot = join(testRoot, "node_modules/default-export-helper");
|
|
1626
|
-
await mkdir(packageRoot, {
|
|
1627
|
-
recursive: true
|
|
1628
|
-
});
|
|
1629
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
1630
|
-
name: "default-export-helper",
|
|
1631
|
-
main: "./index.js"
|
|
1632
|
-
}));
|
|
1633
|
-
await writeFile(join(packageRoot, "index.js"), `Object.defineProperty(exports, '__esModule', { value: true }); exports.default = function Component() {}`);
|
|
1634
|
-
await writeFile(join(testRoot, "entry.js"), `import Component from 'default-export-helper'; globalThis.__vxrnProdCjsDefaultProbe = typeof Component`);
|
|
1635
|
-
try {
|
|
1636
|
-
const result = await buildNativeBundle({
|
|
1637
|
-
root: testRoot,
|
|
1638
|
-
platform: "ios",
|
|
1639
|
-
entryFile: "entry.js"
|
|
1640
|
-
});
|
|
1641
|
-
const context = {
|
|
1642
|
-
clearTimeout,
|
|
1643
|
-
console,
|
|
1644
|
-
process: {
|
|
1645
|
-
env: {}
|
|
1646
|
-
},
|
|
1647
|
-
setTimeout
|
|
1648
|
-
};
|
|
1649
|
-
runInNewContext(result.code, context);
|
|
1650
|
-
expect(Reflect.get(context, "__vxrnProdCjsDefaultProbe")).toBe("function");
|
|
1651
|
-
} finally {
|
|
1652
|
-
await rm(testRoot, {
|
|
1653
|
-
recursive: true,
|
|
1654
|
-
force: true
|
|
1655
|
-
});
|
|
1656
|
-
}
|
|
1657
|
-
});
|
|
1658
|
-
});
|
|
1659
|
-
describe("native Flow sources", () => {
|
|
1660
|
-
it.each(["", `/* ${"license text ".repeat(150)} */
|
|
1661
|
-
`])("strips third-party Flow following a license header (%#)", async license => {
|
|
1662
|
-
const testRoot = await mkdtemp(join(tmpdir(), "vxrn-native-flow-"));
|
|
1663
|
-
const packageRoot = join(testRoot, "node_modules/@flowy-scope/flowy-lib");
|
|
1664
|
-
await mkdir(packageRoot, {
|
|
1665
|
-
recursive: true
|
|
1666
|
-
});
|
|
1667
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
1668
|
-
name: "@flowy-scope/flowy-lib",
|
|
1669
|
-
main: "./js/Flowy.js"
|
|
1670
|
-
}));
|
|
1671
|
-
await mkdir(join(packageRoot, "js"), {
|
|
1672
|
-
recursive: true
|
|
1673
|
-
});
|
|
1674
|
-
await writeFile(join(packageRoot, "js/Flowy.js"), `${license}/**
|
|
1675
|
-
* @flow
|
|
1676
|
-
* @format
|
|
1677
|
-
*/
|
|
1678
|
-
|
|
1679
|
-
type FlowyProps = {|
|
|
1680
|
-
+value: number,
|
|
1681
|
-
|}
|
|
1682
|
-
|
|
1683
|
-
export default class Flowy {
|
|
1684
|
-
_seen: boolean = false
|
|
1685
|
-
|
|
1686
|
-
measure(props: FlowyProps): number {
|
|
1687
|
-
const { value, ...rest }: FlowyProps = props
|
|
1688
|
-
this._seen = true
|
|
1689
|
-
return ((value: any): number) + Object.keys(rest).length
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
`);
|
|
1693
|
-
await writeFile(join(testRoot, "entry.js"), `import Flowy from '@flowy-scope/flowy-lib'
|
|
1694
|
-
globalThis.__vxrnFlowProbe = new Flowy().measure({ value: 41 }) + 1
|
|
1695
|
-
`);
|
|
1696
|
-
try {
|
|
1697
|
-
const result = await buildNativeBundle({
|
|
1698
|
-
root: testRoot,
|
|
1699
|
-
platform: "ios",
|
|
1700
|
-
entryFile: "entry.js"
|
|
1701
|
-
});
|
|
1702
|
-
const context = {
|
|
1703
|
-
clearTimeout,
|
|
1704
|
-
console,
|
|
1705
|
-
process: {
|
|
1706
|
-
env: {}
|
|
1707
|
-
},
|
|
1708
|
-
setTimeout
|
|
1709
|
-
};
|
|
1710
|
-
runInNewContext(result.code, context);
|
|
1711
|
-
expect(Reflect.get(context, "__vxrnFlowProbe")).toBe(42);
|
|
1712
|
-
} finally {
|
|
1713
|
-
await rm(testRoot, {
|
|
1714
|
-
recursive: true,
|
|
1715
|
-
force: true
|
|
1716
|
-
});
|
|
1717
|
-
}
|
|
1718
|
-
});
|
|
1719
|
-
});
|
|
1720
|
-
describe("native bundle source maps", () => {
|
|
1721
|
-
const generatedPositionOf = (code, marker) => {
|
|
1722
|
-
const index = code.indexOf(marker);
|
|
1723
|
-
expect(index).toBeGreaterThan(-1);
|
|
1724
|
-
const before = code.slice(0, index);
|
|
1725
|
-
const lastNewline = before.lastIndexOf("\n");
|
|
1726
|
-
return {
|
|
1727
|
-
line: (before.match(/\n/g)?.length ?? 0) + 1,
|
|
1728
|
-
column: index - lastNewline - 1
|
|
1729
|
-
};
|
|
1730
|
-
};
|
|
1731
|
-
it("resolves a frame to the authored file and line across an app file and a package file", {
|
|
1732
|
-
timeout: 6e4
|
|
1733
|
-
}, async () => {
|
|
1734
|
-
const testRoot = realpathSync(await mkdtemp(join(tmpdir(), "vxrn-native-sourcemap-")));
|
|
1735
|
-
const packageRoot = join(testRoot, "node_modules/probe-package");
|
|
1736
|
-
await mkdir(packageRoot, {
|
|
1737
|
-
recursive: true
|
|
1738
|
-
});
|
|
1739
|
-
await writeFile(join(packageRoot, "package.json"), JSON.stringify({
|
|
1740
|
-
name: "probe-package",
|
|
1741
|
-
main: "index.js",
|
|
1742
|
-
type: "module"
|
|
1743
|
-
}));
|
|
1744
|
-
await writeFile(join(packageRoot, "index.js"), [`function packageThrow() {`, ` throw new Error('__probe_package__')`, `}`, ``, `export default packageThrow`].join("\n"));
|
|
1745
|
-
await writeFile(join(testRoot, "entry.js"), [`import packageThrow from 'probe-package'`, ``, `function appThrow() {`, ` throw new Error('__probe_app__')`, `}`, ``, `globalThis.__probe = [appThrow, packageThrow]`].join("\n"));
|
|
1746
|
-
try {
|
|
1747
|
-
const result = await buildNativeBundle({
|
|
1748
|
-
root: testRoot,
|
|
1749
|
-
platform: "ios",
|
|
1750
|
-
entryFile: "entry.js",
|
|
1751
|
-
dev: true,
|
|
1752
|
-
sourcemap: true
|
|
1753
|
-
});
|
|
1754
|
-
expect(result.map).toBeTruthy();
|
|
1755
|
-
const traced = new TraceMap(JSON.parse(result.map));
|
|
1756
|
-
const app = originalPositionFor(traced, generatedPositionOf(result.code, "__probe_app__"));
|
|
1757
|
-
const pkg = originalPositionFor(traced, generatedPositionOf(result.code, "__probe_package__"));
|
|
1758
|
-
expect(app.source?.endsWith("/entry.js")).toBe(true);
|
|
1759
|
-
expect(app.line).toBe(4);
|
|
1760
|
-
expect(pkg.source?.endsWith("/index.js")).toBe(true);
|
|
1761
|
-
expect(pkg.line).toBe(2);
|
|
1762
|
-
expect(app.source).toBe(normalizePath(join(testRoot, "entry.js")));
|
|
1763
|
-
expect(pkg.source).toBe(normalizePath(join(packageRoot, "index.js")));
|
|
1764
|
-
} finally {
|
|
1765
|
-
await rm(testRoot, {
|
|
1766
|
-
recursive: true,
|
|
1767
|
-
force: true
|
|
1768
|
-
});
|
|
1769
|
-
}
|
|
1770
|
-
});
|
|
1771
|
-
});
|
|
1772
|
-
describe("postProcessNativeBundle", () => {
|
|
1773
|
-
const lines = code => code.split("\n").length;
|
|
1774
|
-
it("keeps the blank line above an export default", () => {
|
|
1775
|
-
const input = ["var a = 1;", "", "export default a;", "var b = 2;", ""].join("\n");
|
|
1776
|
-
const out = postProcessNativeBundle(input);
|
|
1777
|
-
expect(lines(out)).toBe(lines(input));
|
|
1778
|
-
expect(out.split("\n")[2]).toBe("a;");
|
|
1779
|
-
});
|
|
1780
|
-
it("keeps the lines of a multi-line export statement", () => {
|
|
1781
|
-
const input = ["var a = 1;", "export {", " a", "};", "var b = 2;", ""].join("\n");
|
|
1782
|
-
const out = postProcessNativeBundle(input);
|
|
1783
|
-
expect(lines(out)).toBe(lines(input));
|
|
1784
|
-
expect(out).not.toContain("export {");
|
|
1785
|
-
expect(out.split("\n")[4]).toBe("var b = 2;");
|
|
1786
|
-
});
|
|
1787
|
-
});
|
|
1788
|
-
//# sourceMappingURL=createNativeDevEngine.test.mjs.map
|