@vxrn/compiler 1.25.16 → 1.26.0

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 (130) hide show
  1. package/dist/cjs/cache.cjs +4 -2
  2. package/dist/cjs/configure.cjs +9 -1
  3. package/dist/cjs/index.cjs +87 -5
  4. package/dist/cjs/reactNativeCodegen.cjs +140 -0
  5. package/dist/cjs/reactNativeViewConfig.cjs +489 -0
  6. package/dist/cjs/transformBabel.cjs +15 -20
  7. package/dist/cjs/transformBabel.test.cjs +260 -0
  8. package/dist/cjs/transformHermesAsync.cjs +61 -0
  9. package/dist/cjs/transformHermesLoops.cjs +319 -0
  10. package/dist/cjs/transformHermesLoops.test.cjs +257 -0
  11. package/dist/cjs/transformSWC.cjs +110 -138
  12. package/dist/cjs/transformSWC.test.cjs +117 -0
  13. package/dist/cjs/transformWorklets.cjs +123 -0
  14. package/dist/cjs/transformWorklets.test.cjs +604 -0
  15. package/dist/cjs/worklets/autoworklet.cjs +265 -0
  16. package/dist/cjs/worklets/globals.cjs +73 -0
  17. package/dist/cjs/worklets/hash.cjs +38 -0
  18. package/dist/cjs/worklets/scope.cjs +370 -0
  19. package/dist/cjs/worklets/serialize.cjs +101 -0
  20. package/dist/cjs/worklets/transform.cjs +266 -0
  21. package/dist/cjs/worklets/types.cjs +18 -0
  22. package/dist/esm/cache.mjs +5 -3
  23. package/dist/esm/cache.mjs.map +1 -1
  24. package/dist/esm/configure.mjs +8 -1
  25. package/dist/esm/configure.mjs.map +1 -1
  26. package/dist/esm/index.js +75 -6
  27. package/dist/esm/index.js.map +1 -1
  28. package/dist/esm/index.mjs +75 -6
  29. package/dist/esm/index.mjs.map +1 -1
  30. package/dist/esm/reactNativeCodegen.mjs +104 -0
  31. package/dist/esm/reactNativeCodegen.mjs.map +1 -0
  32. package/dist/esm/reactNativeViewConfig.mjs +460 -0
  33. package/dist/esm/reactNativeViewConfig.mjs.map +1 -0
  34. package/dist/esm/transformBabel.mjs +14 -19
  35. package/dist/esm/transformBabel.mjs.map +1 -1
  36. package/dist/esm/transformBabel.test.mjs +261 -1
  37. package/dist/esm/transformBabel.test.mjs.map +1 -1
  38. package/dist/esm/transformHermesAsync.mjs +25 -0
  39. package/dist/esm/transformHermesAsync.mjs.map +1 -0
  40. package/dist/esm/transformHermesLoops.mjs +283 -0
  41. package/dist/esm/transformHermesLoops.mjs.map +1 -0
  42. package/dist/esm/transformHermesLoops.test.mjs +234 -0
  43. package/dist/esm/transformHermesLoops.test.mjs.map +1 -0
  44. package/dist/esm/transformSWC.mjs +96 -139
  45. package/dist/esm/transformSWC.mjs.map +1 -1
  46. package/dist/esm/transformSWC.test.mjs +118 -0
  47. package/dist/esm/transformSWC.test.mjs.map +1 -0
  48. package/dist/esm/transformWorklets.mjs +82 -0
  49. package/dist/esm/transformWorklets.mjs.map +1 -0
  50. package/dist/esm/transformWorklets.test.mjs +581 -0
  51. package/dist/esm/transformWorklets.test.mjs.map +1 -0
  52. package/dist/esm/worklets/autoworklet.mjs +234 -0
  53. package/dist/esm/worklets/autoworklet.mjs.map +1 -0
  54. package/dist/esm/worklets/globals.mjs +46 -0
  55. package/dist/esm/worklets/globals.mjs.map +1 -0
  56. package/dist/esm/worklets/hash.mjs +13 -0
  57. package/dist/esm/worklets/hash.mjs.map +1 -0
  58. package/dist/esm/worklets/scope.mjs +345 -0
  59. package/dist/esm/worklets/scope.mjs.map +1 -0
  60. package/dist/esm/worklets/serialize.mjs +75 -0
  61. package/dist/esm/worklets/serialize.mjs.map +1 -0
  62. package/dist/esm/worklets/transform.mjs +229 -0
  63. package/dist/esm/worklets/transform.mjs.map +1 -0
  64. package/dist/esm/worklets/types.mjs +2 -0
  65. package/dist/esm/worklets/types.mjs.map +1 -0
  66. package/package.json +11 -6
  67. package/src/cache.ts +10 -3
  68. package/src/configure.ts +12 -0
  69. package/src/index.ts +96 -13
  70. package/src/reactNativeCodegen.ts +181 -0
  71. package/src/reactNativeViewConfig.ts +593 -0
  72. package/src/transformBabel.test.ts +268 -1
  73. package/src/transformBabel.ts +21 -31
  74. package/src/transformHermesAsync.ts +30 -0
  75. package/src/transformHermesLoops.test.ts +341 -0
  76. package/src/transformHermesLoops.ts +435 -0
  77. package/src/transformSWC.test.ts +132 -0
  78. package/src/transformSWC.ts +121 -161
  79. package/src/transformWorklets.test.ts +708 -0
  80. package/src/transformWorklets.ts +160 -0
  81. package/src/types.ts +4 -4
  82. package/src/worklets/autoworklet.ts +391 -0
  83. package/src/worklets/globals.ts +129 -0
  84. package/src/worklets/hash.ts +14 -0
  85. package/src/worklets/scope.ts +401 -0
  86. package/src/worklets/serialize.ts +114 -0
  87. package/src/worklets/transform.ts +319 -0
  88. package/src/worklets/types.ts +26 -0
  89. package/types/cache.d.ts +1 -0
  90. package/types/cache.d.ts.map +1 -1
  91. package/types/configure.d.ts +2 -0
  92. package/types/configure.d.ts.map +1 -1
  93. package/types/index.d.ts +6 -0
  94. package/types/index.d.ts.map +1 -1
  95. package/types/reactNativeCodegen.d.ts +5 -0
  96. package/types/reactNativeCodegen.d.ts.map +1 -0
  97. package/types/reactNativeViewConfig.d.ts +35 -0
  98. package/types/reactNativeViewConfig.d.ts.map +1 -0
  99. package/types/transformBabel.d.ts +3 -3
  100. package/types/transformBabel.d.ts.map +1 -1
  101. package/types/transformHermesAsync.d.ts +5 -0
  102. package/types/transformHermesAsync.d.ts.map +1 -0
  103. package/types/transformHermesLoops.d.ts +5 -0
  104. package/types/transformHermesLoops.d.ts.map +1 -0
  105. package/types/transformHermesLoops.test.d.ts +2 -0
  106. package/types/transformHermesLoops.test.d.ts.map +1 -0
  107. package/types/transformSWC.d.ts +13 -3
  108. package/types/transformSWC.d.ts.map +1 -1
  109. package/types/transformSWC.test.d.ts +2 -0
  110. package/types/transformSWC.test.d.ts.map +1 -0
  111. package/types/transformWorklets.d.ts +23 -0
  112. package/types/transformWorklets.d.ts.map +1 -0
  113. package/types/transformWorklets.test.d.ts +2 -0
  114. package/types/transformWorklets.test.d.ts.map +1 -0
  115. package/types/types.d.ts +4 -4
  116. package/types/types.d.ts.map +1 -1
  117. package/types/worklets/autoworklet.d.ts +14 -0
  118. package/types/worklets/autoworklet.d.ts.map +1 -0
  119. package/types/worklets/globals.d.ts +4 -0
  120. package/types/worklets/globals.d.ts.map +1 -0
  121. package/types/worklets/hash.d.ts +5 -0
  122. package/types/worklets/hash.d.ts.map +1 -0
  123. package/types/worklets/scope.d.ts +7 -0
  124. package/types/worklets/scope.d.ts.map +1 -0
  125. package/types/worklets/serialize.d.ts +12 -0
  126. package/types/worklets/serialize.d.ts.map +1 -0
  127. package/types/worklets/transform.d.ts +10 -0
  128. package/types/worklets/transform.d.ts.map +1 -0
  129. package/types/worklets/types.d.ts +21 -0
  130. package/types/worklets/types.d.ts.map +1 -0
@@ -1,26 +1,35 @@
1
1
  import { extname } from 'node:path'
2
- import {
3
- type Output,
4
- type ParserConfig,
5
- type Options as SWCOptions,
6
- type TransformConfig,
7
- transform,
8
- } from '@swc/core'
9
- import { merge } from 'ts-deepmerge'
10
2
  import { normalizePath } from 'vite'
11
3
  import { configuration } from './configure'
12
- import { asyncGeneratorRegex, debug, parsers, runtimePublicPath } from './constants'
4
+ import { asyncGeneratorRegex, debug, runtimePublicPath } from './constants'
13
5
  import type { Options } from './types'
14
6
 
7
+ export interface Output {
8
+ code: string
9
+ map?: any
10
+ }
11
+
15
12
  // posix-only — id is normalized below
16
13
  const ignoreId = /node_modules\/(\.vite|vite)\//
17
14
 
15
+ export function shouldStripFlow(id: string, code: string): boolean {
16
+ const filename = id.split('?')[0]
17
+ if (!/\.jsx?$/.test(filename)) return false
18
+ if (/node_modules[\\/](?:react-native|@react-native)[\\/].*\.js$/.test(filename)) {
19
+ return true
20
+ }
21
+ // scan the complete comment preamble, including license blocks before @flow.
22
+ const header =
23
+ code.match(/^(?:#![^\r\n]*(?:\r?\n|$))?(?:\s|\/\*[\s\S]*?\*\/|\/\/[^\r\n]*)*/)?.[0] || ''
24
+ return /@flow\b/.test(header) || /\b(?:import|export)\s+type\b/.test(code)
25
+ }
26
+
18
27
  export async function transformSWC(
19
28
  id: string,
20
29
  code: string,
21
30
  options: Options & { es5?: boolean },
22
- swcOptions?: SWCOptions
23
- ) {
31
+ swcOptions?: any
32
+ ): Promise<Output | undefined> {
24
33
  // unify caller contracts (Vite plugin: POSIX id; patches.ts: native id)
25
34
  id = normalizePath(id.split('?')[0]).replace(normalizePath(process.cwd()), '')
26
35
 
@@ -32,9 +41,8 @@ export async function transformSWC(
32
41
  return
33
42
  }
34
43
 
35
- const parser = getParser(id, options.forceJSX)
36
-
37
- if (!parser) {
44
+ const lang = getLang(id, options.forceJSX)
45
+ if (!lang) {
38
46
  return
39
47
  }
40
48
 
@@ -45,108 +53,62 @@ export async function transformSWC(
45
53
  !options.forceJSX &&
46
54
  !id.includes('node_modules')
47
55
 
48
- const reactConfig = {
49
- refresh,
50
- development: !options.forceJSX && !options.production,
51
- runtime: 'automatic',
52
- importSource: 'react',
53
- ...(configuration.enableNativewind && !id.includes('node_modules')
54
- ? {
55
- importSource: 'nativewind',
56
- // pragma: 'createInteropElement',
57
- // pragmaFrag: '_InteropFragment',
58
- // swc doesnt actually change the import right
59
- // runtime: 'classic',
60
- }
61
- : {}),
62
- } satisfies TransformConfig['react']
63
-
64
- const transformOptions = ((): SWCOptions => {
65
- if (options.environment === 'client' || options.environment === 'ssr') {
66
- return {
67
- sourceMaps: shouldSourceMap(),
68
- jsc: {
69
- target: 'es2020',
70
- parser,
71
- transform: {
72
- useDefineForClassFields: true,
73
- react: reactConfig,
74
- },
75
- },
76
- }
77
- }
78
-
79
- const shouldEs5Transform =
80
- options.es5 ||
81
- (!process.env.VXRN_USE_BABEL_FOR_GENERATORS && asyncGeneratorRegex.test(code))
82
-
83
- const opts: SWCOptions = shouldEs5Transform
84
- ? {
85
- jsc: {
86
- parser,
87
- target: 'es5',
88
- transform: {
89
- useDefineForClassFields: true,
90
- react: reactConfig,
91
- },
92
- },
93
- }
94
- : {
95
- ...(!options.forceJSX && { env: SWC_ENV }),
96
- jsc: {
97
- ...(options.forceJSX && { target: 'esnext' }),
98
- parser,
99
- transform: {
100
- useDefineForClassFields: true,
101
- react: reactConfig,
102
- },
103
- },
104
- }
105
-
106
- return {
107
- sourceMaps: shouldSourceMap(),
108
- module: {
109
- importInterop: 'none',
110
- type: 'nodenext',
111
- },
112
- ...(options.mode === 'serve-cjs' && {
113
- module: {
114
- importInterop: 'none',
115
- type: 'commonjs',
116
- strict: true,
117
- },
118
- }),
119
- ...opts,
120
- }
121
- })()
122
-
123
- const finalOptions = merge(
124
- {
125
- filename: id,
126
- swcrc: false,
127
- configFile: false,
128
- ...transformOptions,
56
+ const importSource =
57
+ configuration.enableNativewind && !id.includes('node_modules')
58
+ ? 'nativewind'
59
+ : 'react'
60
+
61
+ const shouldEs5Transform =
62
+ options.es5 ||
63
+ (!process.env.VXRN_USE_BABEL_FOR_GENERATORS && asyncGeneratorRegex.test(code))
64
+
65
+ const target = shouldEs5Transform ? 'es2015' : 'es2020'
66
+ const sourceMaps =
67
+ swcOptions?.sourceMaps !== undefined
68
+ ? Boolean(swcOptions.sourceMaps)
69
+ : shouldSourceMap()
70
+
71
+ const oxcOptions: import('oxc-transform').TransformOptions = {
72
+ lang,
73
+ target,
74
+ assumptions: {
75
+ setPublicClassFields: true,
76
+ ...(swcOptions?.assumptions || {}),
77
+ },
78
+ sourcemap: sourceMaps,
79
+ jsx: {
80
+ runtime: 'automatic',
81
+ development: !options.forceJSX && !options.production,
82
+ refresh: Boolean(refresh),
83
+ importSource,
129
84
  },
130
- swcOptions || {}
131
- ) satisfies SWCOptions
85
+ }
132
86
 
133
- const result: Output = await (async () => {
87
+ const { transformSync } = await import('oxc-transform')
88
+
89
+ const result: Output = (() => {
134
90
  try {
135
91
  debug?.(
136
- `transformSWC ${id} using options:\n${JSON.stringify(finalOptions, null, 2)}`
92
+ `transformSWC (oxc) ${id} using options:\n${JSON.stringify(oxcOptions, null, 2)}`
137
93
  )
138
94
 
139
- return await transform(code, finalOptions)
140
- } catch (e: any) {
141
- const message: string = e.message
142
- const fileStartIndex = message.indexOf('╭─[')
143
- if (fileStartIndex !== -1) {
144
- const match = message.slice(fileStartIndex).match(/:(\d+):(\d+)]/)
145
- if (match) {
146
- e.line = match[1]
147
- e.column = match[2]
95
+ const res = transformSync(id, code, oxcOptions)
96
+ if (res.errors?.length) {
97
+ const err = res.errors[0]
98
+ const error: any = new Error(
99
+ err.message + (err.codeframe ? `\n${err.codeframe}` : '')
100
+ )
101
+ if (err.labels?.[0]) {
102
+ error.start = err.labels[0].start
103
+ error.end = err.labels[0].end
148
104
  }
105
+ throw error
149
106
  }
107
+ return {
108
+ code: res.code,
109
+ map: res.map,
110
+ }
111
+ } catch (e: any) {
150
112
  throw e
151
113
  }
152
114
  })()
@@ -163,7 +125,7 @@ export async function transformSWC(
163
125
  // fix for node_modules that ship tsx but don't use type-specific imports
164
126
  if (
165
127
  options.fixNonTypeSpecificImports ||
166
- (id.includes('node_modules') && parser.syntax === 'typescript')
128
+ (id.includes('node_modules') && (lang === 'ts' || lang === 'tsx'))
167
129
  ) {
168
130
  // we need to keep fake objects for type exports
169
131
  const typeExportsMatch = code.match(/^\s*export\s+type\s+([^\s]+)/gi)
@@ -199,6 +161,8 @@ export async function transformSWC(
199
161
  return result
200
162
  }
201
163
 
164
+ export const transformOxc = transformSWC
165
+
202
166
  function wrapSourceInRefreshRuntime(
203
167
  id: string,
204
168
  result: Output,
@@ -219,7 +183,11 @@ function wrapSourceInRefreshRuntimeWeb(
219
183
  result: Output,
220
184
  hasRefreshRuntime: boolean
221
185
  ) {
222
- const sourceMap = result.map ? JSON.parse(result.map) : undefined
186
+ const sourceMap = result.map
187
+ ? typeof result.map === 'string'
188
+ ? JSON.parse(result.map)
189
+ : { ...result.map }
190
+ : undefined
223
191
  if (sourceMap) {
224
192
  sourceMap.mappings = ';;' + sourceMap.mappings
225
193
  }
@@ -286,7 +254,11 @@ globalThis.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
286
254
  module.url = '${id}'
287
255
  module.hot = createHotContext(module.url)`
288
256
 
289
- const sourceMap = result.map ? JSON.parse(result.map) : undefined
257
+ const sourceMap = result.map
258
+ ? typeof result.map === 'string'
259
+ ? JSON.parse(result.map)
260
+ : { ...result.map }
261
+ : undefined
290
262
 
291
263
  if (sourceMap) {
292
264
  // we need ";" equal to number of lines added to the top
@@ -314,72 +286,60 @@ ${postfixCode}
314
286
  return result
315
287
  }
316
288
 
317
- const SWC_ENV = {
318
- targets: {
319
- node: '4',
320
- },
321
- // debug: true,
322
- include: [],
323
- // this breaks the uniswap app for any file with a ...spread
324
- exclude: [
325
- 'transform-spread',
326
- 'transform-destructuring',
327
- 'transform-object-rest-spread',
328
- // `transform-async-to-generator` is relying on `transform-destructuring`.
329
- // If we exclude `transform-destructuring` but not `transform-async-to-generator`, the SWC binary will panic
330
- // with error: `called `Option::unwrap()` on a `None` value`.
331
- // See: https://github.com/swc-project/swc/blob/v1.7.14/crates/swc_ecma_compat_es2015/src/generator.rs#L703-L705
332
- 'transform-async-to-generator',
333
- 'transform-regenerator', // Similar to above
334
- ],
335
- } satisfies SWCOptions['env']
336
-
337
289
  const refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/
338
290
 
339
- function shouldSourceMap() {
291
+ export function shouldSourceMap() {
340
292
  return process.env.VXRN_ENABLE_SOURCE_MAP === '1'
341
293
  }
342
294
 
343
- function getParser(id: string, forceJSX = false) {
295
+ function getLang(id: string, forceJSX = false): 'js' | 'jsx' | 'ts' | 'tsx' | undefined {
344
296
  if (id.endsWith('one-entry-native')) {
345
- return parsers['.tsx']
297
+ return 'tsx'
346
298
  }
347
299
 
348
300
  const extension = extname(id)
349
- let parser: ParserConfig = !extension ? parsers['.js'] : parsers[extension]
350
301
 
351
- if (extension === '.js' || extension === '.mjs') {
352
- if (forceJSX) {
353
- parser = parsers['.jsx']
354
- }
302
+ if (extension === '.tsx') return 'tsx'
303
+ if (extension === '.ts') return 'ts'
304
+ if (extension === '.jsx' || extension === '.mdx') return 'jsx'
305
+ if (extension === '.js' || extension === '.mjs' || extension === '.cjs') {
306
+ // native packages ship jsx inside plain js files; jsx mode also accepts
307
+ // ordinary javascript, matching the native bundler's parser.
308
+ return 'jsx'
309
+ }
355
310
 
356
- if (id.includes('expo-modules-core')) {
357
- parser = parsers['.jsx']
358
- }
311
+ if (!extension) {
312
+ return forceJSX ? 'jsx' : 'js'
359
313
  }
360
314
 
361
- return parser
315
+ return undefined
362
316
  }
363
317
 
364
318
  export const transformSWCStripJSX = async (id: string, code: string) => {
365
- const parser = getParser(id)
366
- if (!parser) return
367
- return await transform(code, {
368
- filename: id,
369
- swcrc: false,
370
- configFile: false,
371
- sourceMaps: shouldSourceMap(),
372
- jsc: {
373
- target: 'es2019',
374
- parser,
375
- transform: {
376
- useDefineForClassFields: true,
377
- react: {
378
- development: true,
379
- runtime: 'automatic',
380
- refresh: false,
381
- },
382
- },
319
+ const lang = getLang(id)
320
+ if (!lang) return
321
+
322
+ const { transformSync } = await import('oxc-transform')
323
+ const res = transformSync(id, code, {
324
+ lang,
325
+ target: 'es2020',
326
+ assumptions: {
327
+ setPublicClassFields: true,
328
+ },
329
+ sourcemap: shouldSourceMap(),
330
+ jsx: {
331
+ runtime: 'automatic',
332
+ development: true,
333
+ refresh: false,
383
334
  },
384
335
  })
336
+
337
+ if (res.errors?.length) {
338
+ const err = res.errors[0]
339
+ throw new Error(err.message + (err.codeframe ? `\n${err.codeframe}` : ''))
340
+ }
341
+
342
+ return { code: res.code, map: res.map as any }
385
343
  }
344
+
345
+ export const transformOxcStripJSX = transformSWCStripJSX