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.
Files changed (456) hide show
  1. package/dist/cli.mjs +212 -261
  2. package/dist/cli.mjs.map +1 -1
  3. package/dist/cli.native.js +216 -265
  4. package/dist/cli.native.js.map +1 -1
  5. package/dist/config/getAdditionalViteConfig.mjs +33 -62
  6. package/dist/config/getAdditionalViteConfig.mjs.map +1 -1
  7. package/dist/config/getAdditionalViteConfig.native.js +33 -62
  8. package/dist/config/getAdditionalViteConfig.native.js.map +1 -1
  9. package/dist/config/getBaseViteConfigOnly.mjs +84 -77
  10. package/dist/config/getBaseViteConfigOnly.mjs.map +1 -1
  11. package/dist/config/getBaseViteConfigOnly.native.js +86 -79
  12. package/dist/config/getBaseViteConfigOnly.native.js.map +1 -1
  13. package/dist/config/getBaseViteConfigWithPlugins.mjs +6 -4
  14. package/dist/config/getBaseViteConfigWithPlugins.mjs.map +1 -1
  15. package/dist/config/getBaseViteConfigWithPlugins.native.js +6 -4
  16. package/dist/config/getBaseViteConfigWithPlugins.native.js.map +1 -1
  17. package/dist/config/getBaseVitePlugins.mjs +102 -130
  18. package/dist/config/getBaseVitePlugins.mjs.map +1 -1
  19. package/dist/config/getBaseVitePlugins.native.js +123 -152
  20. package/dist/config/getBaseVitePlugins.native.js.map +1 -1
  21. package/dist/config/getNonCliModeOnlyVitePlugins.mjs +3 -3
  22. package/dist/config/getNonCliModeOnlyVitePlugins.mjs.map +1 -1
  23. package/dist/config/getNonCliModeOnlyVitePlugins.native.js +3 -1
  24. package/dist/config/getNonCliModeOnlyVitePlugins.native.js.map +1 -1
  25. package/dist/config/getOptimizeDeps.mjs +138 -42
  26. package/dist/config/getOptimizeDeps.mjs.map +1 -1
  27. package/dist/config/getOptimizeDeps.native.js +138 -42
  28. package/dist/config/getOptimizeDeps.native.js.map +1 -1
  29. package/dist/config/getOptionsFilled.mjs +48 -52
  30. package/dist/config/getOptionsFilled.mjs.map +1 -1
  31. package/dist/config/getOptionsFilled.native.js +51 -55
  32. package/dist/config/getOptionsFilled.native.js.map +1 -1
  33. package/dist/config/getReactNativePlugins.mjs +23 -15
  34. package/dist/config/getReactNativePlugins.mjs.map +1 -1
  35. package/dist/config/getReactNativePlugins.native.js +25 -16
  36. package/dist/config/getReactNativePlugins.native.js.map +1 -1
  37. package/dist/config/getServerOptionsFilled.mjs +33 -35
  38. package/dist/config/getServerOptionsFilled.mjs.map +1 -1
  39. package/dist/config/getServerOptionsFilled.native.js +35 -38
  40. package/dist/config/getServerOptionsFilled.native.js.map +1 -1
  41. package/dist/config/getViteServerConfig.mjs +34 -45
  42. package/dist/config/getViteServerConfig.mjs.map +1 -1
  43. package/dist/config/getViteServerConfig.native.js +35 -46
  44. package/dist/config/getViteServerConfig.native.js.map +1 -1
  45. package/dist/config/mergeUserConfig.mjs +50 -28
  46. package/dist/config/mergeUserConfig.mjs.map +1 -1
  47. package/dist/config/mergeUserConfig.native.js +60 -38
  48. package/dist/config/mergeUserConfig.native.js.map +1 -1
  49. package/dist/constants/defaults.mjs +29 -12
  50. package/dist/constants/defaults.mjs.map +1 -1
  51. package/dist/constants/defaults.native.js +29 -12
  52. package/dist/constants/defaults.native.js.map +1 -1
  53. package/dist/constants.mjs +41 -6
  54. package/dist/constants.mjs.map +1 -1
  55. package/dist/constants.native.js +41 -6
  56. package/dist/constants.native.js.map +1 -1
  57. package/dist/exports/build.mjs +218 -270
  58. package/dist/exports/build.mjs.map +1 -1
  59. package/dist/exports/build.native.js +226 -283
  60. package/dist/exports/build.native.js.map +1 -1
  61. package/dist/exports/clean.mjs +71 -78
  62. package/dist/exports/clean.mjs.map +1 -1
  63. package/dist/exports/clean.native.js +76 -90
  64. package/dist/exports/clean.native.js.map +1 -1
  65. package/dist/exports/createServer.mjs +43 -46
  66. package/dist/exports/createServer.mjs.map +1 -1
  67. package/dist/exports/createServer.native.js +45 -48
  68. package/dist/exports/createServer.native.js.map +1 -1
  69. package/dist/exports/dev.mjs +177 -201
  70. package/dist/exports/dev.mjs.map +1 -1
  71. package/dist/exports/dev.native.js +191 -215
  72. package/dist/exports/dev.native.js.map +1 -1
  73. package/dist/exports/loadEnv.mjs +51 -48
  74. package/dist/exports/loadEnv.mjs.map +1 -1
  75. package/dist/exports/loadEnv.native.js +59 -57
  76. package/dist/exports/loadEnv.native.js.map +1 -1
  77. package/dist/exports/patch.mjs +9 -7
  78. package/dist/exports/patch.mjs.map +1 -1
  79. package/dist/exports/patch.native.js +9 -7
  80. package/dist/exports/patch.native.js.map +1 -1
  81. package/dist/exports/prebuild.mjs +177 -157
  82. package/dist/exports/prebuild.mjs.map +1 -1
  83. package/dist/exports/prebuild.native.js +197 -160
  84. package/dist/exports/prebuild.native.js.map +1 -1
  85. package/dist/exports/prebuildWithoutExpo.mjs +46 -44
  86. package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
  87. package/dist/exports/prebuildWithoutExpo.native.js +48 -46
  88. package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
  89. package/dist/exports/runAndroid.mjs +9 -10
  90. package/dist/exports/runAndroid.mjs.map +1 -1
  91. package/dist/exports/runAndroid.native.js +10 -11
  92. package/dist/exports/runAndroid.native.js.map +1 -1
  93. package/dist/exports/runIos.mjs +9 -10
  94. package/dist/exports/runIos.mjs.map +1 -1
  95. package/dist/exports/runIos.native.js +10 -11
  96. package/dist/exports/runIos.native.js.map +1 -1
  97. package/dist/exports/serve.mjs +23 -31
  98. package/dist/exports/serve.mjs.map +1 -1
  99. package/dist/exports/serve.native.js +26 -34
  100. package/dist/exports/serve.native.js.map +1 -1
  101. package/dist/exports/serveStaticAssets.mjs +109 -113
  102. package/dist/exports/serveStaticAssets.mjs.map +1 -1
  103. package/dist/exports/serveStaticAssets.native.js +180 -192
  104. package/dist/exports/serveStaticAssets.native.js.map +1 -1
  105. package/dist/index.js +25 -14
  106. package/dist/index.mjs +25 -14
  107. package/dist/index.native.js +25 -14
  108. package/dist/patches/builtInDepPatches.mjs +346 -435
  109. package/dist/patches/builtInDepPatches.mjs.map +1 -1
  110. package/dist/patches/builtInDepPatches.native.js +349 -438
  111. package/dist/patches/builtInDepPatches.native.js.map +1 -1
  112. package/dist/plugins/applyBuiltInPatchesPlugin.mjs +11 -11
  113. package/dist/plugins/applyBuiltInPatchesPlugin.mjs.map +1 -1
  114. package/dist/plugins/applyBuiltInPatchesPlugin.native.js +11 -11
  115. package/dist/plugins/applyBuiltInPatchesPlugin.native.js.map +1 -1
  116. package/dist/plugins/autoDepOptimizePlugin.mjs +87 -90
  117. package/dist/plugins/autoDepOptimizePlugin.mjs.map +1 -1
  118. package/dist/plugins/autoDepOptimizePlugin.native.js +99 -102
  119. package/dist/plugins/autoDepOptimizePlugin.native.js.map +1 -1
  120. package/dist/plugins/clientInjectPlugin.mjs +13 -11
  121. package/dist/plugins/clientInjectPlugin.mjs.map +1 -1
  122. package/dist/plugins/clientInjectPlugin.native.js +13 -11
  123. package/dist/plugins/clientInjectPlugin.native.js.map +1 -1
  124. package/dist/plugins/defaultDepOptimizePlugin.mjs +15 -23
  125. package/dist/plugins/defaultDepOptimizePlugin.mjs.map +1 -1
  126. package/dist/plugins/defaultDepOptimizePlugin.native.js +15 -23
  127. package/dist/plugins/defaultDepOptimizePlugin.native.js.map +1 -1
  128. package/dist/plugins/expoManifestRequestHandlerPlugin.mjs +163 -179
  129. package/dist/plugins/expoManifestRequestHandlerPlugin.mjs.map +1 -1
  130. package/dist/plugins/expoManifestRequestHandlerPlugin.native.js +169 -191
  131. package/dist/plugins/expoManifestRequestHandlerPlugin.native.js.map +1 -1
  132. package/dist/plugins/getResolvedConfigSubset.mjs +6 -5
  133. package/dist/plugins/getResolvedConfigSubset.mjs.map +1 -1
  134. package/dist/plugins/getResolvedConfigSubset.native.js +6 -5
  135. package/dist/plugins/getResolvedConfigSubset.native.js.map +1 -1
  136. package/dist/plugins/reactNativeCommonJsPlugin.mjs +210 -178
  137. package/dist/plugins/reactNativeCommonJsPlugin.mjs.map +1 -1
  138. package/dist/plugins/reactNativeCommonJsPlugin.native.js +283 -259
  139. package/dist/plugins/reactNativeCommonJsPlugin.native.js.map +1 -1
  140. package/dist/plugins/reactNativeDevAssetPlugin.mjs +72 -83
  141. package/dist/plugins/reactNativeDevAssetPlugin.mjs.map +1 -1
  142. package/dist/plugins/reactNativeDevAssetPlugin.native.js +75 -92
  143. package/dist/plugins/reactNativeDevAssetPlugin.native.js.map +1 -1
  144. package/dist/plugins/reactNativeDevServer.mjs +283 -328
  145. package/dist/plugins/reactNativeDevServer.mjs.map +1 -1
  146. package/dist/plugins/reactNativeDevServer.native.js +332 -391
  147. package/dist/plugins/reactNativeDevServer.native.js.map +1 -1
  148. package/dist/plugins/rnCodegenPlugin.mjs +13 -12
  149. package/dist/plugins/rnCodegenPlugin.mjs.map +1 -1
  150. package/dist/plugins/rnCodegenPlugin.native.js +13 -12
  151. package/dist/plugins/rnCodegenPlugin.native.js.map +1 -1
  152. package/dist/plugins/rollupRemoveUnusedImports.mjs +8 -7
  153. package/dist/plugins/rollupRemoveUnusedImports.mjs.map +1 -1
  154. package/dist/plugins/rollupRemoveUnusedImports.native.js +8 -7
  155. package/dist/plugins/rollupRemoveUnusedImports.native.js.map +1 -1
  156. package/dist/plugins/workletImportsPlugin.mjs +127 -132
  157. package/dist/plugins/workletImportsPlugin.mjs.map +1 -1
  158. package/dist/plugins/workletImportsPlugin.native.js +192 -203
  159. package/dist/plugins/workletImportsPlugin.native.js.map +1 -1
  160. package/dist/rn-commands/bundle/buildBundle.mjs +45 -79
  161. package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
  162. package/dist/rn-commands/bundle/buildBundle.native.js +45 -85
  163. package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
  164. package/dist/runtime/hmr-client.mjs +133 -140
  165. package/dist/runtime/hmr-client.mjs.map +1 -1
  166. package/dist/runtime/hmr-client.native.js +223 -222
  167. package/dist/runtime/hmr-client.native.js.map +1 -1
  168. package/dist/runtime/hmr-runtime.mjs +192 -194
  169. package/dist/runtime/hmr-runtime.mjs.map +1 -1
  170. package/dist/runtime/hmr-runtime.native.js +424 -411
  171. package/dist/runtime/hmr-runtime.native.js.map +1 -1
  172. package/dist/runtime/hmr-types.mjs +0 -2
  173. package/dist/runtime/hmr-types.native.js +0 -2
  174. package/dist/runtime/native-prelude.mjs +2 -1
  175. package/dist/runtime/native-prelude.mjs.map +1 -1
  176. package/dist/runtime/native-prelude.native.js +2 -1
  177. package/dist/runtime/native-prelude.native.js.map +1 -1
  178. package/dist/runtime/react-refresh-utils.mjs +23 -22
  179. package/dist/runtime/react-refresh-utils.mjs.map +1 -1
  180. package/dist/runtime/react-refresh-utils.native.js +23 -27
  181. package/dist/runtime/react-refresh-utils.native.js.map +1 -1
  182. package/dist/serve/node.mjs +49 -49
  183. package/dist/serve/node.mjs.map +1 -1
  184. package/dist/serve/node.native.js +92 -96
  185. package/dist/serve/node.native.js.map +1 -1
  186. package/dist/types.mjs +0 -2
  187. package/dist/types.native.js +0 -2
  188. package/dist/user-interface/index.mjs +245 -262
  189. package/dist/user-interface/index.mjs.map +1 -1
  190. package/dist/user-interface/index.native.js +274 -298
  191. package/dist/user-interface/index.native.js.map +1 -1
  192. package/dist/utils/assert.mjs +7 -6
  193. package/dist/utils/assert.mjs.map +1 -1
  194. package/dist/utils/assert.native.js +7 -18
  195. package/dist/utils/assert.native.js.map +1 -1
  196. package/dist/utils/bindKeypressInput.mjs +36 -38
  197. package/dist/utils/bindKeypressInput.mjs.map +1 -1
  198. package/dist/utils/bindKeypressInput.native.js +36 -38
  199. package/dist/utils/bindKeypressInput.native.js.map +1 -1
  200. package/dist/utils/coerceToArray.mjs +2 -1
  201. package/dist/utils/coerceToArray.mjs.map +1 -1
  202. package/dist/utils/coerceToArray.native.js +2 -1
  203. package/dist/utils/coerceToArray.native.js.map +1 -1
  204. package/dist/utils/connectedNativeClients.mjs +3 -2
  205. package/dist/utils/connectedNativeClients.mjs.map +1 -1
  206. package/dist/utils/connectedNativeClients.native.js +3 -2
  207. package/dist/utils/connectedNativeClients.native.js.map +1 -1
  208. package/dist/utils/createNativeDevEngine.mjs +992 -966
  209. package/dist/utils/createNativeDevEngine.mjs.map +1 -1
  210. package/dist/utils/createNativeDevEngine.native.js +1184 -1179
  211. package/dist/utils/createNativeDevEngine.native.js.map +1 -1
  212. package/dist/utils/dispose.mjs +4 -3
  213. package/dist/utils/dispose.mjs.map +1 -1
  214. package/dist/utils/dispose.native.js +6 -5
  215. package/dist/utils/dispose.native.js.map +1 -1
  216. package/dist/utils/environmentUtils.mjs +5 -4
  217. package/dist/utils/environmentUtils.mjs.map +1 -1
  218. package/dist/utils/environmentUtils.native.js +5 -4
  219. package/dist/utils/environmentUtils.native.js.map +1 -1
  220. package/dist/utils/execSync.mjs +7 -5
  221. package/dist/utils/execSync.mjs.map +1 -1
  222. package/dist/utils/execSync.native.js +8 -6
  223. package/dist/utils/execSync.native.js.map +1 -1
  224. package/dist/utils/expoRun.mjs +27 -35
  225. package/dist/utils/expoRun.mjs.map +1 -1
  226. package/dist/utils/expoRun.native.js +27 -35
  227. package/dist/utils/expoRun.native.js.map +1 -1
  228. package/dist/utils/filterViteServerResolvedUrls.mjs +24 -22
  229. package/dist/utils/filterViteServerResolvedUrls.mjs.map +1 -1
  230. package/dist/utils/filterViteServerResolvedUrls.native.js +61 -63
  231. package/dist/utils/filterViteServerResolvedUrls.native.js.map +1 -1
  232. package/dist/utils/getBoundPort.mjs +6 -5
  233. package/dist/utils/getBoundPort.mjs.map +1 -1
  234. package/dist/utils/getBoundPort.native.js +8 -12
  235. package/dist/utils/getBoundPort.native.js.map +1 -1
  236. package/dist/utils/getCacheDir.mjs +3 -1
  237. package/dist/utils/getCacheDir.mjs.map +1 -1
  238. package/dist/utils/getCacheDir.native.js +3 -1
  239. package/dist/utils/getCacheDir.native.js.map +1 -1
  240. package/dist/utils/getServerEntry.mjs +6 -4
  241. package/dist/utils/getServerEntry.mjs.map +1 -1
  242. package/dist/utils/getServerEntry.native.js +8 -11
  243. package/dist/utils/getServerEntry.native.js.map +1 -1
  244. package/dist/utils/getVitePath.mjs +42 -42
  245. package/dist/utils/getVitePath.mjs.map +1 -1
  246. package/dist/utils/getVitePath.native.js +43 -41
  247. package/dist/utils/getVitePath.native.js.map +1 -1
  248. package/dist/utils/globDir.mjs +7 -11
  249. package/dist/utils/globDir.mjs.map +1 -1
  250. package/dist/utils/globDir.native.js +10 -14
  251. package/dist/utils/globDir.native.js.map +1 -1
  252. package/dist/utils/isWithin.mjs +4 -2
  253. package/dist/utils/isWithin.mjs.map +1 -1
  254. package/dist/utils/isWithin.native.js +4 -2
  255. package/dist/utils/isWithin.native.js.map +1 -1
  256. package/dist/utils/patches.mjs +233 -255
  257. package/dist/utils/patches.mjs.map +1 -1
  258. package/dist/utils/patches.native.js +415 -460
  259. package/dist/utils/patches.native.js.map +1 -1
  260. package/dist/utils/printServerUrls.mjs +9 -7
  261. package/dist/utils/printServerUrls.mjs.map +1 -1
  262. package/dist/utils/printServerUrls.native.js +48 -51
  263. package/dist/utils/printServerUrls.native.js.map +1 -1
  264. package/dist/utils/removeUndefined.mjs +8 -7
  265. package/dist/utils/removeUndefined.mjs.map +1 -1
  266. package/dist/utils/removeUndefined.native.js +8 -7
  267. package/dist/utils/removeUndefined.native.js.map +1 -1
  268. package/dist/utils/scanDepsToOptimize.mjs +194 -161
  269. package/dist/utils/scanDepsToOptimize.mjs.map +1 -1
  270. package/dist/utils/scanDepsToOptimize.native.js +227 -197
  271. package/dist/utils/scanDepsToOptimize.native.js.map +1 -1
  272. package/dist/utils/state.mjs +18 -18
  273. package/dist/utils/state.mjs.map +1 -1
  274. package/dist/utils/state.native.js +18 -18
  275. package/dist/utils/state.native.js.map +1 -1
  276. package/dist/utils/symbolicateNativeStack.mjs +54 -54
  277. package/dist/utils/symbolicateNativeStack.mjs.map +1 -1
  278. package/dist/utils/symbolicateNativeStack.native.js +58 -58
  279. package/dist/utils/symbolicateNativeStack.native.js.map +1 -1
  280. package/dist/utils/uniq.mjs +2 -1
  281. package/dist/utils/uniq.mjs.map +1 -1
  282. package/dist/utils/uniq.native.js +2 -1
  283. package/dist/utils/uniq.native.js.map +1 -1
  284. package/dist/utils/utils.mjs +19 -19
  285. package/dist/utils/utils.mjs.map +1 -1
  286. package/dist/utils/utils.native.js +38 -40
  287. package/dist/utils/utils.native.js.map +1 -1
  288. package/dist/vendor/debugger-app/index.mjs +0 -2
  289. package/dist/vendor/debugger-app/index.native.js +0 -2
  290. package/dist/vendor/debugger-app/src/debuggerWorker.mjs +0 -2
  291. package/dist/vendor/debugger-app/src/debuggerWorker.native.js +0 -2
  292. package/dist/vendor/debugger-app/src/index.mjs +0 -2
  293. package/dist/vendor/debugger-app/src/index.native.js +0 -2
  294. package/dist/vxrn-vite-plugin.mjs +34 -33
  295. package/dist/vxrn-vite-plugin.mjs.map +1 -1
  296. package/dist/vxrn-vite-plugin.native.js +35 -34
  297. package/dist/vxrn-vite-plugin.native.js.map +1 -1
  298. package/expo-plugin.cjs +12 -6
  299. package/package.json +12 -13
  300. package/src/config/getBaseViteConfigOnly.ts +6 -0
  301. package/src/exports/prebuild.ts +40 -12
  302. package/src/patches/builtInDepPatches.ts +24 -48
  303. package/src/utils/createNativeDevEngine.test.ts +1 -1
  304. package/src/utils/createNativeDevEngine.ts +15 -9
  305. package/src/utils/scanDepsToOptimize.ts +0 -3
  306. package/types/config/getBaseViteConfigOnly.d.ts.map +1 -1
  307. package/types/config/getOptimizeDeps.d.ts.map +1 -1
  308. package/types/config/getOptionsFilled.d.ts +15 -15
  309. package/types/config/getOptionsFilled.d.ts.map +1 -1
  310. package/types/exports/build.d.ts +11 -11
  311. package/types/exports/build.d.ts.map +1 -1
  312. package/types/exports/clean.d.ts +1 -1
  313. package/types/exports/clean.d.ts.map +1 -1
  314. package/types/exports/createServer.d.ts.map +1 -1
  315. package/types/exports/dev.d.ts.map +1 -1
  316. package/types/exports/patch.d.ts.map +1 -1
  317. package/types/exports/prebuild.d.ts +3 -3
  318. package/types/exports/prebuild.d.ts.map +1 -1
  319. package/types/exports/prebuildWithoutExpo.d.ts +1 -1
  320. package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
  321. package/types/exports/runAndroid.d.ts.map +1 -1
  322. package/types/exports/runIos.d.ts.map +1 -1
  323. package/types/exports/serve.d.ts.map +1 -1
  324. package/types/patches/builtInDepPatches.d.ts.map +1 -1
  325. package/types/plugins/autoDepOptimizePlugin.d.ts.map +1 -1
  326. package/types/plugins/rollupRemoveUnusedImports.d.ts.map +1 -1
  327. package/types/runtime/hmr-client.d.ts.map +1 -1
  328. package/types/runtime/hmr-runtime.d.ts.map +1 -1
  329. package/types/runtime/hmr-types.d.ts.map +1 -1
  330. package/types/utils/createNativeDevEngine.d.ts +1 -1
  331. package/types/utils/createNativeDevEngine.d.ts.map +1 -1
  332. package/types/utils/execSync.d.ts.map +1 -1
  333. package/types/utils/getServerEntry.d.ts.map +1 -1
  334. package/types/utils/scanDepsToOptimize.d.ts.map +1 -1
  335. package/types/vxrn-vite-plugin.d.ts.map +1 -1
  336. package/dist/config/getOptimizeDeps.test.mjs +0 -20
  337. package/dist/config/getOptimizeDeps.test.mjs.map +0 -1
  338. package/dist/config/getOptimizeDeps.test.native.js +0 -39
  339. package/dist/config/getOptimizeDeps.test.native.js.map +0 -1
  340. package/dist/config/getServerOptionsFilled.test.mjs +0 -20
  341. package/dist/config/getServerOptionsFilled.test.mjs.map +0 -1
  342. package/dist/config/getServerOptionsFilled.test.native.js +0 -20
  343. package/dist/config/getServerOptionsFilled.test.native.js.map +0 -1
  344. package/dist/config/getViteServerConfig.test.mjs +0 -26
  345. package/dist/config/getViteServerConfig.test.mjs.map +0 -1
  346. package/dist/config/getViteServerConfig.test.native.js +0 -26
  347. package/dist/config/getViteServerConfig.test.native.js.map +0 -1
  348. package/dist/config/mergeUserConfig.test.mjs +0 -108
  349. package/dist/config/mergeUserConfig.test.mjs.map +0 -1
  350. package/dist/config/mergeUserConfig.test.native.js +0 -108
  351. package/dist/config/mergeUserConfig.test.native.js.map +0 -1
  352. package/dist/exports/clean.test.mjs +0 -81
  353. package/dist/exports/clean.test.mjs.map +0 -1
  354. package/dist/exports/clean.test.native.js +0 -88
  355. package/dist/exports/clean.test.native.js.map +0 -1
  356. package/dist/exports/loadEnv.test.mjs +0 -65
  357. package/dist/exports/loadEnv.test.mjs.map +0 -1
  358. package/dist/exports/loadEnv.test.native.js +0 -65
  359. package/dist/exports/loadEnv.test.native.js.map +0 -1
  360. package/dist/index.js.map +0 -1
  361. package/dist/index.mjs.map +0 -1
  362. package/dist/index.native.js.map +0 -1
  363. package/dist/plugins/autoDepOptimizePlugin.test.mjs +0 -31
  364. package/dist/plugins/autoDepOptimizePlugin.test.mjs.map +0 -1
  365. package/dist/plugins/autoDepOptimizePlugin.test.native.js +0 -39
  366. package/dist/plugins/autoDepOptimizePlugin.test.native.js.map +0 -1
  367. package/dist/plugins/resolveIdScan.test.mjs +0 -31
  368. package/dist/plugins/resolveIdScan.test.mjs.map +0 -1
  369. package/dist/plugins/resolveIdScan.test.native.js +0 -38
  370. package/dist/plugins/resolveIdScan.test.native.js.map +0 -1
  371. package/dist/plugins/rnCodegenPlugin.test.mjs +0 -239
  372. package/dist/plugins/rnCodegenPlugin.test.mjs.map +0 -1
  373. package/dist/plugins/rnCodegenPlugin.test.native.js +0 -242
  374. package/dist/plugins/rnCodegenPlugin.test.native.js.map +0 -1
  375. package/dist/plugins/serverExtensions.test.mjs +0 -106
  376. package/dist/plugins/serverExtensions.test.mjs.map +0 -1
  377. package/dist/plugins/serverExtensions.test.native.js +0 -117
  378. package/dist/plugins/serverExtensions.test.native.js.map +0 -1
  379. package/dist/runtime/hmr-types.mjs.map +0 -1
  380. package/dist/runtime/hmr-types.native.js.map +0 -1
  381. package/dist/serve/node.test.mjs +0 -60
  382. package/dist/serve/node.test.mjs.map +0 -1
  383. package/dist/serve/node.test.native.js +0 -72
  384. package/dist/serve/node.test.native.js.map +0 -1
  385. package/dist/types.mjs.map +0 -1
  386. package/dist/types.native.js.map +0 -1
  387. package/dist/utils/bindKeypressInput.test.mjs +0 -48
  388. package/dist/utils/bindKeypressInput.test.mjs.map +0 -1
  389. package/dist/utils/bindKeypressInput.test.native.js +0 -48
  390. package/dist/utils/bindKeypressInput.test.native.js.map +0 -1
  391. package/dist/utils/createNativeDevEngine.test.mjs +0 -1788
  392. package/dist/utils/createNativeDevEngine.test.mjs.map +0 -1
  393. package/dist/utils/createNativeDevEngine.test.native.js +0 -1942
  394. package/dist/utils/createNativeDevEngine.test.native.js.map +0 -1
  395. package/dist/utils/createNativeDevEngineFailure.test.mjs +0 -44
  396. package/dist/utils/createNativeDevEngineFailure.test.mjs.map +0 -1
  397. package/dist/utils/createNativeDevEngineFailure.test.native.js +0 -54
  398. package/dist/utils/createNativeDevEngineFailure.test.native.js.map +0 -1
  399. package/dist/utils/getBoundPort.test.mjs +0 -71
  400. package/dist/utils/getBoundPort.test.mjs.map +0 -1
  401. package/dist/utils/getBoundPort.test.native.js +0 -82
  402. package/dist/utils/getBoundPort.test.native.js.map +0 -1
  403. package/dist/utils/imageSizePatch.test.mjs +0 -29
  404. package/dist/utils/imageSizePatch.test.mjs.map +0 -1
  405. package/dist/utils/imageSizePatch.test.native.js +0 -30
  406. package/dist/utils/imageSizePatch.test.native.js.map +0 -1
  407. package/dist/utils/patches.test.mjs +0 -242
  408. package/dist/utils/patches.test.mjs.map +0 -1
  409. package/dist/utils/patches.test.native.js +0 -271
  410. package/dist/utils/patches.test.native.js.map +0 -1
  411. package/dist/utils/symbolicateNativeStack.test.mjs +0 -96
  412. package/dist/utils/symbolicateNativeStack.test.mjs.map +0 -1
  413. package/dist/utils/symbolicateNativeStack.test.native.js +0 -96
  414. package/dist/utils/symbolicateNativeStack.test.native.js.map +0 -1
  415. package/dist/vendor/debugger-app/index.mjs.map +0 -1
  416. package/dist/vendor/debugger-app/index.native.js.map +0 -1
  417. package/dist/vendor/debugger-app/src/debuggerWorker.mjs.map +0 -1
  418. package/dist/vendor/debugger-app/src/debuggerWorker.native.js.map +0 -1
  419. package/dist/vendor/debugger-app/src/index.mjs.map +0 -1
  420. package/dist/vendor/debugger-app/src/index.native.js.map +0 -1
  421. package/types/config/getOptimizeDeps.test.d.ts +0 -2
  422. package/types/config/getOptimizeDeps.test.d.ts.map +0 -1
  423. package/types/config/getServerOptionsFilled.test.d.ts +0 -2
  424. package/types/config/getServerOptionsFilled.test.d.ts.map +0 -1
  425. package/types/config/getViteServerConfig.test.d.ts +0 -2
  426. package/types/config/getViteServerConfig.test.d.ts.map +0 -1
  427. package/types/config/mergeUserConfig.test.d.ts +0 -2
  428. package/types/config/mergeUserConfig.test.d.ts.map +0 -1
  429. package/types/exports/clean.test.d.ts +0 -2
  430. package/types/exports/clean.test.d.ts.map +0 -1
  431. package/types/exports/loadEnv.test.d.ts +0 -2
  432. package/types/exports/loadEnv.test.d.ts.map +0 -1
  433. package/types/plugins/autoDepOptimizePlugin.test.d.ts +0 -2
  434. package/types/plugins/autoDepOptimizePlugin.test.d.ts.map +0 -1
  435. package/types/plugins/resolveIdScan.test.d.ts +0 -2
  436. package/types/plugins/resolveIdScan.test.d.ts.map +0 -1
  437. package/types/plugins/rnCodegenPlugin.test.d.ts +0 -2
  438. package/types/plugins/rnCodegenPlugin.test.d.ts.map +0 -1
  439. package/types/plugins/serverExtensions.test.d.ts +0 -2
  440. package/types/plugins/serverExtensions.test.d.ts.map +0 -1
  441. package/types/serve/node.test.d.ts +0 -2
  442. package/types/serve/node.test.d.ts.map +0 -1
  443. package/types/utils/bindKeypressInput.test.d.ts +0 -2
  444. package/types/utils/bindKeypressInput.test.d.ts.map +0 -1
  445. package/types/utils/createNativeDevEngine.test.d.ts +0 -2
  446. package/types/utils/createNativeDevEngine.test.d.ts.map +0 -1
  447. package/types/utils/createNativeDevEngineFailure.test.d.ts +0 -2
  448. package/types/utils/createNativeDevEngineFailure.test.d.ts.map +0 -1
  449. package/types/utils/getBoundPort.test.d.ts +0 -2
  450. package/types/utils/getBoundPort.test.d.ts.map +0 -1
  451. package/types/utils/imageSizePatch.test.d.ts +0 -2
  452. package/types/utils/imageSizePatch.test.d.ts.map +0 -1
  453. package/types/utils/patches.test.d.ts +0 -2
  454. package/types/utils/patches.test.d.ts.map +0 -1
  455. package/types/utils/symbolicateNativeStack.test.d.ts +0 -2
  456. 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