@vxrn/compiler 1.26.1 → 1.27.1-1789414853455

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -172,8 +172,12 @@ async function performBabelTransform({
172
172
  (x) => Array.isArray(x) && x[0] === 'babel-plugin-react-compiler'
173
173
  )
174
174
 
175
- // Check cache first
176
- const cached = getCachedTransform(id, code, environment)
175
+ // Check cache first. the user babel config feeds the transform output,
176
+ // so its identity joins the key: adding or editing babel.config.* must
177
+ // miss entries cached without that change.
178
+ const userBabelConfigPath =
179
+ typeof babelOptions.configFile === 'string' ? babelOptions.configFile : null
180
+ const cached = getCachedTransform(id, code, environment, userBabelConfigPath)
177
181
  if (cached) {
178
182
  perfStats.babel.byEnvironment[environment].transforms++
179
183
  if (
@@ -214,25 +218,32 @@ async function performBabelTransform({
214
218
  ) ?? -1
215
219
 
216
220
  if (compilerPluginIndex !== -1) {
217
- // mark callbacks before react compiler moves them into memoized bindings.
218
- if (useWorklets) {
219
- workletPreparation = prepareWorkletsForReactCompiler(
221
+ const compilerPluginConfig = babelOptions.plugins![compilerPluginIndex] as any[]
222
+ const compilerPluginOptions = compilerPluginConfig[1] || {}
223
+ const useBabelCompiler =
224
+ compilerPluginOptions.compiler === 'babel' ||
225
+ process.env.ONE_REACT_COMPILER === 'babel' ||
226
+ process.env.VXRN_REACT_COMPILER === 'babel'
227
+
228
+ if (!useBabelCompiler) {
229
+ // mark callbacks before react compiler moves them into memoized bindings.
230
+ if (useWorklets) {
231
+ workletPreparation = prepareWorkletsForReactCompiler(
232
+ id,
233
+ curCode,
234
+ shouldSourceMap()
235
+ )
236
+ if (workletPreparation) curCode = workletPreparation.code
237
+ }
238
+ compilerOut = await transformOxcReactCompiler(
220
239
  id,
221
240
  curCode,
241
+ compilerPluginOptions,
222
242
  shouldSourceMap()
223
243
  )
224
- if (workletPreparation) curCode = workletPreparation.code
244
+ if (compilerOut) curCode = compilerOut.code
245
+ babelOptions.plugins!.splice(compilerPluginIndex, 1)
225
246
  }
226
- const compilerTarget =
227
- (babelOptions.plugins![compilerPluginIndex] as any[])[1]?.target ?? '19'
228
- compilerOut = await transformOxcReactCompiler(
229
- id,
230
- curCode,
231
- compilerTarget,
232
- shouldSourceMap()
233
- )
234
- if (compilerOut) curCode = compilerOut.code
235
- babelOptions.plugins!.splice(compilerPluginIndex, 1)
236
247
  }
237
248
 
238
249
  let workletsOut: { code: string; map?: any } | null = null
@@ -251,7 +262,11 @@ async function performBabelTransform({
251
262
  const startTime = Date.now()
252
263
  let babelOut: { code?: string | null; map?: any } | null = null
253
264
 
254
- if (babelOptions.plugins?.length === 0) {
265
+ if (
266
+ babelOptions.plugins?.length === 0 &&
267
+ !babelOptions.configFile &&
268
+ !babelOptions.babelrc
269
+ ) {
255
270
  let finalMap: any = undefined
256
271
  if (shouldSourceMap()) {
257
272
  const intermediateMaps = [
@@ -311,7 +326,7 @@ async function performBabelTransform({
311
326
  const result = { code: outCode, map: babelOut.map }
312
327
 
313
328
  // Cache the result
314
- setCachedTransform(id, code, result, environment)
329
+ setCachedTransform(id, code, result, environment, userBabelConfigPath)
315
330
 
316
331
  return result
317
332
  }
@@ -4,6 +4,7 @@ import path from 'node:path'
4
4
  import { afterEach, describe, expect, it } from 'vitest'
5
5
  import { configureVXRNCompilerPlugin } from './configure'
6
6
  import {
7
+ findUserBabelConfig,
7
8
  getBabelOptions,
8
9
  transformBabel,
9
10
  transformOxcReactCompiler,
@@ -67,6 +68,27 @@ describe('transformBabel Flow parsing', () => {
67
68
  expect(result?.code).not.toContain('HostComponent')
68
69
  })
69
70
 
71
+ it('preserves React Native Flow enums as runtime values', async () => {
72
+ const result = await transformBabel(
73
+ '/project/VirtualView.js',
74
+ `
75
+ // @flow strict-local
76
+ export enum VirtualViewRenderState {
77
+ Unknown = 0,
78
+ Rendered = 1,
79
+ None = 2,
80
+ }
81
+
82
+ export const rendered = VirtualViewRenderState.Rendered
83
+ `,
84
+ { plugins: [] }
85
+ )
86
+
87
+ expect(result?.code).toContain('const VirtualViewRenderState =')
88
+ expect(result?.code).toContain('Rendered: 1')
89
+ expect(result?.code).toContain('VirtualViewRenderState.Rendered')
90
+ })
91
+
70
92
  it('rejects a required transform error instead of returning untransformed source', async () => {
71
93
  const negativeControl = () => ({
72
94
  visitor: {
@@ -130,6 +152,29 @@ describe('transformOxcReactCompiler', () => {
130
152
 
131
153
  expect(result.code).toContain('_c(')
132
154
  })
155
+
156
+ it('supports mutating useSharedValue in useEffect via Reanimated environment defaults', async () => {
157
+ const reanimatedCode = `
158
+ import { useEffect } from 'react'
159
+ import { useSharedValue } from 'react-native-reanimated'
160
+
161
+ export function ReanimatedComponent() {
162
+ const val = useSharedValue(0)
163
+ useEffect(() => {
164
+ val.value = 1
165
+ }, [val])
166
+ return <div>{val.value}</div>
167
+ }
168
+ `
169
+ const result = await transformOxcReactCompiler(
170
+ '/project/ReanimatedComponent.tsx',
171
+ reanimatedCode,
172
+ { target: '19' },
173
+ false
174
+ )
175
+
176
+ expect(result.code).toContain('_c(')
177
+ })
133
178
  })
134
179
 
135
180
  describe('compiler plugin multi-stage source map composition', () => {
@@ -346,3 +391,228 @@ describe('shared compiler worklets backend selection', () => {
346
391
  }
347
392
  })
348
393
  })
394
+
395
+ describe('findUserBabelConfig and user Babel config respect', () => {
396
+ it('finds user babel config and ignores generated configs', () => {
397
+ const projectRoot = fs.realpathSync(
398
+ fs.mkdtempSync(path.join(os.tmpdir(), 'vxrn-babel-conf-'))
399
+ )
400
+ try {
401
+ expect(findUserBabelConfig(projectRoot)).toBeNull()
402
+
403
+ // Created with @one-generated marker -> ignored
404
+ const generatedFile = path.join(projectRoot, 'babel.config.js')
405
+ fs.writeFileSync(generatedFile, '// @one-generated\nmodule.exports = {}')
406
+ expect(findUserBabelConfig(projectRoot)).toBeNull()
407
+
408
+ // Overwritten with user config -> detected
409
+ fs.writeFileSync(generatedFile, 'module.exports = { plugins: [] }')
410
+ expect(findUserBabelConfig(projectRoot)).toBe(generatedFile)
411
+ } finally {
412
+ fs.rmSync(projectRoot, { recursive: true, force: true })
413
+ }
414
+ })
415
+
416
+ it('includes user configFile and babelrc in getBabelOptions for project files', () => {
417
+ const projectRoot = fs.realpathSync(
418
+ fs.mkdtempSync(path.join(os.tmpdir(), 'vxrn-babel-conf-'))
419
+ )
420
+ const userConfig = path.join(projectRoot, 'babel.config.json')
421
+ fs.writeFileSync(userConfig, '{"plugins": []}')
422
+ try {
423
+ // For project file:
424
+ const projectFileOptions = getBabelOptions({
425
+ id: path.join(projectRoot, 'src', 'index.tsx'),
426
+ code: `export const hello = () => 123`,
427
+ projectRoot,
428
+ development: true,
429
+ environment: 'client',
430
+ reactForRNVersion: '19',
431
+ })
432
+ expect(projectFileOptions?.configFile).toBe(userConfig)
433
+ expect(projectFileOptions?.babelrc).toBe(true)
434
+
435
+ // For node_modules file: should not attach user configFile
436
+ const nodeModulesOptions = getBabelOptions({
437
+ id: path.join(projectRoot, 'node_modules', 'foo', 'index.js'),
438
+ code: `export const foo = 1`,
439
+ projectRoot,
440
+ development: true,
441
+ environment: 'client',
442
+ reactForRNVersion: '19',
443
+ })
444
+ expect(nodeModulesOptions).toBeNull()
445
+ } finally {
446
+ fs.rmSync(projectRoot, { recursive: true, force: true })
447
+ }
448
+ })
449
+
450
+ it('runs user babel config transforms via transformBabel', async () => {
451
+ const projectRoot = fs.realpathSync(
452
+ fs.mkdtempSync(path.join(os.tmpdir(), 'vxrn-babel-conf-'))
453
+ )
454
+ const userConfig = path.join(projectRoot, 'babel.config.json')
455
+ // A babel config that injects a banner/plugin or standard babel syntax
456
+ fs.writeFileSync(
457
+ userConfig,
458
+ JSON.stringify({
459
+ comments: false,
460
+ })
461
+ )
462
+ try {
463
+ const code = '/* remove me */ export const x = 1'
464
+ const res = await transformBabel(
465
+ path.join(projectRoot, 'src', 'index.ts'),
466
+ code,
467
+ {
468
+ configFile: userConfig,
469
+ babelrc: true,
470
+ }
471
+ )
472
+ expect(res.code).not.toContain('remove me')
473
+ expect(res.code).toContain('export const x = 1')
474
+ } finally {
475
+ fs.rmSync(projectRoot, { recursive: true, force: true })
476
+ }
477
+ })
478
+ })
479
+
480
+ describe('explicit swc/oxc per-file choice with a user babel config', () => {
481
+ it('returns null for swc/oxc string and object forms', () => {
482
+ const projectRoot = fs.realpathSync(
483
+ fs.mkdtempSync(path.join(os.tmpdir(), 'vxrn-babel-conf-'))
484
+ )
485
+ const userConfig = path.join(projectRoot, 'babel.config.js')
486
+ fs.writeFileSync(userConfig, 'module.exports = { plugins: [] }')
487
+ try {
488
+ const base = {
489
+ id: path.join(projectRoot, 'src', 'index.tsx'),
490
+ code: `export const x = 1`,
491
+ projectRoot,
492
+ development: true,
493
+ environment: 'client' as const,
494
+ reactForRNVersion: '19' as const,
495
+ }
496
+ // merely adding babel.config.js must not flip an explicit non-babel choice
497
+ expect(getBabelOptions({ ...base, userSetting: 'swc' })).toBeNull()
498
+ expect(getBabelOptions({ ...base, userSetting: 'oxc' })).toBeNull()
499
+ expect(getBabelOptions({ ...base, userSetting: { transform: 'swc' } })).toBeNull()
500
+ expect(getBabelOptions({ ...base, userSetting: { transform: 'oxc' } })).toBeNull()
501
+ // controls: babel choices still resolve through the user config
502
+ expect(getBabelOptions({ ...base, userSetting: 'babel' })?.configFile).toBe(
503
+ userConfig
504
+ )
505
+ expect(
506
+ getBabelOptions({ ...base, userSetting: { transform: 'babel' } })?.configFile
507
+ ).toBe(userConfig)
508
+ expect(getBabelOptions(base)?.configFile).toBe(userConfig)
509
+ } finally {
510
+ fs.rmSync(projectRoot, { recursive: true, force: true })
511
+ }
512
+ })
513
+
514
+ it('skips the transform end-to-end for object-form swc', async () => {
515
+ const { createVXRNCompilerPlugin } = await import('./index')
516
+ const projectRoot = fs.realpathSync(
517
+ fs.mkdtempSync(path.join(os.tmpdir(), 'vxrn-babel-conf-'))
518
+ )
519
+ const srcDir = path.join(projectRoot, 'src')
520
+ fs.mkdirSync(srcDir, { recursive: true })
521
+ const file = path.join(srcDir, 'index.ts')
522
+ const code = `export const x = 1`
523
+ fs.writeFileSync(file, code)
524
+ fs.writeFileSync(
525
+ path.join(projectRoot, 'babel.config.js'),
526
+ 'module.exports = { plugins: [] }'
527
+ )
528
+ configureVXRNCompilerPlugin({ enableCompiler: false, enableReanimated: false })
529
+ try {
530
+ const plugins = await createVXRNCompilerPlugin({
531
+ transform: () => ({ transform: 'swc' }) as any,
532
+ })
533
+ const plugin = plugins.find((p: any) => p.name === 'one:compiler') as any
534
+ await plugin.configResolved({ root: projectRoot, build: {} })
535
+ const hook = plugin.transform.handler || plugin.transform
536
+ const result = await hook.call({ environment: { name: 'client' } }, code, file)
537
+ expect(result == null).toBe(true)
538
+ } finally {
539
+ configureVXRNCompilerPlugin({ enableCompiler: false, enableReanimated: false })
540
+ fs.rmSync(projectRoot, { recursive: true, force: true })
541
+ }
542
+ })
543
+ })
544
+
545
+ describe('user babel config end-to-end through the compiler plugin', () => {
546
+ it('runs the user config when default plugins are empty', async () => {
547
+ const { createVXRNCompilerPlugin } = await import('./index')
548
+ const projectRoot = fs.realpathSync(
549
+ fs.mkdtempSync(path.join(os.tmpdir(), 'vxrn-babel-e2e-'))
550
+ )
551
+ const srcDir = path.join(projectRoot, 'src')
552
+ fs.mkdirSync(srcDir, { recursive: true })
553
+ const file = path.join(srcDir, 'index.ts')
554
+ const marker = 'babel-e2e-probe'
555
+ const code = `/* ${marker} */ export const x = 1`
556
+ fs.writeFileSync(file, code)
557
+ fs.writeFileSync(
558
+ path.join(projectRoot, 'babel.config.json'),
559
+ JSON.stringify({ comments: false })
560
+ )
561
+ configureVXRNCompilerPlugin({ enableCompiler: false, enableReanimated: false })
562
+ try {
563
+ const plugins = await createVXRNCompilerPlugin()
564
+ const plugin = plugins.find((p: any) => p.name === 'one:compiler') as any
565
+ await plugin.configResolved({ root: projectRoot, build: {} })
566
+ const hook = plugin.transform.handler || plugin.transform
567
+ const result = await hook.call({ environment: { name: 'client' } }, code, file)
568
+ // default plugins are empty here, but the user configFile must still
569
+ // route through transformBabel instead of taking the skip fast-path
570
+ expect(result).toBeDefined()
571
+ expect(result.code).toContain('export const x = 1')
572
+ expect(result.code).not.toContain(marker)
573
+ } finally {
574
+ configureVXRNCompilerPlugin({ enableCompiler: false, enableReanimated: false })
575
+ fs.rmSync(projectRoot, { recursive: true, force: true })
576
+ }
577
+ })
578
+
579
+ it('invalidates the cache when the user babel config is added or edited', async () => {
580
+ const { createVXRNCompilerPlugin } = await import('./index')
581
+ const projectRoot = fs.realpathSync(
582
+ fs.mkdtempSync(path.join(os.tmpdir(), 'vxrn-babel-cache-'))
583
+ )
584
+ const srcDir = path.join(projectRoot, 'src')
585
+ fs.mkdirSync(srcDir, { recursive: true })
586
+ const file = path.join(srcDir, 'index.ts')
587
+ const marker = 'babel-cache-probe'
588
+ const code = `/* ${marker} */ export const x = 1`
589
+ fs.writeFileSync(file, code)
590
+ const userConfig = path.join(projectRoot, 'babel.config.json')
591
+ configureVXRNCompilerPlugin({ enableCompiler: false, enableReanimated: false })
592
+ try {
593
+ const plugins = await createVXRNCompilerPlugin({
594
+ transform: () => 'babel' as const,
595
+ })
596
+ const plugin = plugins.find((p: any) => p.name === 'one:compiler') as any
597
+ await plugin.configResolved({ root: projectRoot, build: {} })
598
+ const hook = plugin.transform.handler || plugin.transform
599
+ const context = { environment: { name: 'client' } }
600
+
601
+ const res1 = await hook.call(context, code, file)
602
+ expect(res1.code).toContain(marker)
603
+
604
+ // adding a config without touching the source must miss the cache
605
+ fs.writeFileSync(userConfig, JSON.stringify({ comments: false }))
606
+ const res2 = await hook.call(context, code, file)
607
+ expect(res2.code).not.toContain(marker)
608
+
609
+ // editing the config contents must miss again
610
+ fs.writeFileSync(userConfig, JSON.stringify({ comments: true }))
611
+ const res3 = await hook.call(context, code, file)
612
+ expect(res3.code).toContain(marker)
613
+ } finally {
614
+ configureVXRNCompilerPlugin({ enableCompiler: false, enableReanimated: false })
615
+ fs.rmSync(projectRoot, { recursive: true, force: true })
616
+ }
617
+ })
618
+ })
@@ -1,4 +1,5 @@
1
- import { extname, relative } from 'node:path'
1
+ import { existsSync, readFileSync } from 'node:fs'
2
+ import { extname, join, relative } from 'node:path'
2
3
  // type-only, so that importing this module does not drag babel in. every metro
3
4
  // worker loads it through the package index, and on the native transform path
4
5
  // babel is never called at all: loading it there is pure startup cost.
@@ -13,6 +14,37 @@ type Props = GetTransformProps & {
13
14
  userSetting?: GetTransformResponse
14
15
  }
15
16
 
17
+ const USER_BABEL_CONFIG_FILES = [
18
+ 'babel.config.js',
19
+ 'babel.config.cjs',
20
+ 'babel.config.mjs',
21
+ 'babel.config.json',
22
+ '.babelrc',
23
+ '.babelrc.js',
24
+ '.babelrc.json',
25
+ ] as const
26
+
27
+ const ONE_GENERATED_MARKER = '@one-generated'
28
+
29
+ export function findUserBabelConfig(projectRoot?: string): string | null {
30
+ if (!projectRoot) return null
31
+ for (const name of USER_BABEL_CONFIG_FILES) {
32
+ const fullPath = join(projectRoot, name)
33
+ if (existsSync(fullPath)) {
34
+ try {
35
+ const content = readFileSync(fullPath, 'utf8')
36
+ if (content.includes(ONE_GENERATED_MARKER)) {
37
+ continue
38
+ }
39
+ } catch {
40
+ continue
41
+ }
42
+ return fullPath
43
+ }
44
+ }
45
+ return null
46
+ }
47
+
16
48
  export function getBabelOptions(props: Props): babel.TransformOptions | null {
17
49
  // unify caller contracts (the Vite plugin hands POSIX ids; the native/patches
18
50
  // path hands OS-native ids) so every path matcher below can assume forward
@@ -20,22 +52,53 @@ export function getBabelOptions(props: Props): babel.TransformOptions | null {
20
52
  // reason. without it, RN's own files aren't matched on Windows.
21
53
  props = { ...props, id: normalizePath(props.id.split('?')[0]) }
22
54
 
55
+ const isProjectFile = !props.id.includes('node_modules')
56
+ const userBabelConfig =
57
+ isProjectFile && props.projectRoot
58
+ ? findUserBabelConfig(props.projectRoot)
59
+ : null
60
+
23
61
  if (props.userSetting === 'babel') {
24
- return getOptions(props, true)
62
+ return getOptions(props, true, userBabelConfig)
25
63
  }
26
64
  if (
27
65
  typeof props.userSetting === 'undefined' ||
28
66
  (typeof props.userSetting === 'object' && props.userSetting.transform === 'babel')
29
67
  ) {
30
68
  if (props.userSetting?.excludeDefaultPlugins) {
31
- return props.userSetting
69
+ return {
70
+ ...props.userSetting,
71
+ ...(userBabelConfig
72
+ ? { configFile: userBabelConfig, babelrc: true }
73
+ : {}),
74
+ }
32
75
  }
33
- return getOptions(props)
76
+ return getOptions(props, false, userBabelConfig)
77
+ }
78
+ // an explicit per-file opt-out of babel survives a user config. without
79
+ // this, merely adding babel.config.js flips swc/oxc files to babel.
80
+ const userSetting = props.userSetting
81
+ if (
82
+ userSetting === 'swc' ||
83
+ userSetting === 'oxc' ||
84
+ userSetting === false ||
85
+ (typeof userSetting === 'object' &&
86
+ userSetting !== null &&
87
+ (userSetting.transform === 'swc' || userSetting.transform === 'oxc'))
88
+ ) {
89
+ return null
90
+ }
91
+ if (userBabelConfig) {
92
+ return getOptions(props, false, userBabelConfig)
34
93
  }
35
94
  return null
36
95
  }
37
96
 
38
- const getOptions = (props: Props, force = false): babel.TransformOptions | null => {
97
+ const getOptions = (
98
+ props: Props,
99
+ force = false,
100
+ userBabelConfig: string | null = null
101
+ ): babel.TransformOptions | null => {
39
102
  let plugins: babel.PluginItem[] = []
40
103
 
41
104
  if (force || shouldBabelGenerators(props)) {
@@ -72,8 +135,13 @@ const getOptions = (props: Props, force = false): babel.TransformOptions | null
72
135
  plugins.push(getBabelReactCompilerPlugin(props))
73
136
  }
74
137
 
75
- if (plugins.length) {
76
- return { plugins }
138
+ if (plugins.length || userBabelConfig) {
139
+ return {
140
+ plugins,
141
+ ...(userBabelConfig
142
+ ? { configFile: userBabelConfig, babelrc: true }
143
+ : {}),
144
+ }
77
145
  }
78
146
 
79
147
  return null
@@ -91,14 +159,27 @@ const getOptions = (props: Props, force = false): babel.TransformOptions | null
91
159
  export async function transformOxcReactCompiler(
92
160
  id: string,
93
161
  code: string,
94
- target: '18' | '19',
162
+ optionsOrTarget: '18' | '19' | (Record<string, any> & { target?: '18' | '19' }) = '19',
95
163
  sourceMap = false
96
164
  ) {
97
165
  const { transform } = await import('oxc-transform-react')
166
+ const compilerOptions =
167
+ typeof optionsOrTarget === 'string'
168
+ ? { target: optionsOrTarget }
169
+ : optionsOrTarget || {}
170
+
171
+ const target = compilerOptions.target ?? '19'
98
172
  const result = await transform(id, code, {
99
173
  jsx: 'preserve',
100
174
  sourcemap: sourceMap,
101
- reactCompiler: { target },
175
+ reactCompiler: {
176
+ target,
177
+ ...compilerOptions,
178
+ environment: {
179
+ enableCustomTypeDefinitionForReanimated: true,
180
+ ...compilerOptions.environment,
181
+ },
182
+ },
102
183
  })
103
184
 
104
185
  // `errors` with fatal:false are react compiler BAILOUTS ("Cannot access refs
@@ -140,8 +221,8 @@ export async function transformBabel(
140
221
  const babelOptions = {
141
222
  filename: id,
142
223
  compact: false,
143
- babelrc: false,
144
- configFile: false,
224
+ babelrc: options.babelrc ?? false,
225
+ configFile: options.configFile ?? false,
145
226
  sourceMaps: false,
146
227
  minified: false,
147
228
  ...options,
@@ -168,7 +249,10 @@ export async function transformBabel(
168
249
  plugins: [
169
250
  ...(isTS
170
251
  ? []
171
- : [[hermesParserPlugin, { parseLangTypes: 'flow', reactRuntimeTarget: '19' }]]),
252
+ : [
253
+ [hermesParserPlugin, { parseLangTypes: 'flow', reactRuntimeTarget: '19' }],
254
+ 'babel-plugin-transform-flow-enums',
255
+ ]),
172
256
  ...(options.plugins || []),
173
257
  ...(isTS ? [] : ['@babel/plugin-transform-flow-strip-types']),
174
258
  ],
@@ -184,6 +268,14 @@ export async function transformBabel(
184
268
  })
185
269
  }
186
270
 
271
+ export async function stripFlowTypes(id: string, code: string, sourceMaps = true) {
272
+ const result = await transformBabel(id, code, { sourceMaps })
273
+ return {
274
+ code: result.code!,
275
+ map: result.map,
276
+ }
277
+ }
278
+
187
279
  const getBasePlugins = ({ development }: Props) =>
188
280
  [
189
281
  ['@babel/plugin-transform-destructuring'],
@@ -1,5 +1,6 @@
1
1
  import fs from 'node:fs'
2
2
  import os from 'node:os'
3
+ import { createRequire } from 'node:module'
3
4
  import path from 'node:path'
4
5
  import { afterEach, describe, expect, it } from 'vitest'
5
6
  import { configureVXRNCompilerPlugin } from './configure'
@@ -381,7 +382,12 @@ describe('transformWorklets', () => {
381
382
  expect(typeof scaleFn).toBe('function')
382
383
  expect(scaleFn.__workletHash).toBeDefined()
383
384
  expect(typeof scaleFn.__workletHash).toBe('number')
384
- expect(scaleFn.__pluginVersion).toBe('0.10.1')
385
+ // /app has no package.json, so the stamp comes from the worklets runtime
386
+ // this workspace actually installs
387
+ const installedWorklets = createRequire(path.resolve(process.cwd(), 'package.json'))(
388
+ 'react-native-worklets/package.json'
389
+ ).version
390
+ expect(scaleFn.__pluginVersion).toBe(installedWorklets)
385
391
  expect(scaleFn.__closure).toEqual({ multiplier: 5 })
386
392
  expect(scaleFn.__initData).toBeDefined()
387
393
  expect(scaleFn.__initData.code).toContain('__closure')
package/types/cache.d.ts CHANGED
@@ -4,14 +4,14 @@ interface CacheStats {
4
4
  writes: 0;
5
5
  errors: 0;
6
6
  }
7
- export declare function getCachedTransform(filePath: string, code: string, environment: string): {
7
+ export declare function getCachedTransform(filePath: string, code: string, environment: string, userBabelConfigPath?: string | null): {
8
8
  code: string;
9
9
  map?: any;
10
10
  } | null;
11
11
  export declare function setCachedTransform(filePath: string, code: string, result: {
12
12
  code: string;
13
13
  map?: any;
14
- }, environment: string): void;
14
+ }, environment: string, userBabelConfigPath?: string | null): void;
15
15
  /** Drop every cached transform, for `react-native bundle --reset-cache`. */
16
16
  export declare function clearTransformCache(): void;
17
17
  export declare function getCacheStats(): CacheStats;
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AA4BA,UAAU,UAAU;IAClB,IAAI,EAAE,CAAC,CAAA;IACP,MAAM,EAAE,CAAC,CAAA;IACT,MAAM,EAAE,CAAC,CAAA;IACT,MAAM,EAAE,CAAC,CAAA;CACV;AAiDD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,GAAG,CAAA;CAAE,GAAG,IAAI,CAoCpC;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,GAAG,CAAA;CAAE,EACnC,WAAW,EAAE,MAAM,GAClB,IAAI,CAwBN;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED,wBAAgB,aAAa,IAAI,IAAI,CAapC"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AA4BA,UAAU,UAAU;IAClB,IAAI,EAAE,CAAC,CAAA;IACP,MAAM,EAAE,CAAC,CAAA;IACT,MAAM,EAAE,CAAC,CAAA;IACT,MAAM,EAAE,CAAC,CAAA;CACV;AA6ED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,GAAG,CAAA;CAAE,GAAG,IAAI,CAoCpC;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,GAAG,CAAA;CAAE,EACnC,WAAW,EAAE,MAAM,EACnB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,GAClC,IAAI,CAwBN;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED,wBAAgB,aAAa,IAAI,IAAI,CAapC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,MAAM,CAAA;AAcpE,OAAO,KAAK,EAAkC,OAAO,EAAE,MAAM,SAAS,CAAA;AAGtE,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AA2R3C,wBAAsB,wBAAwB,CAC5C,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,YAAY,EAAE,CAAC,CA6VzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,MAAM,CAAA;AAcpE,OAAO,KAAK,EAAkC,OAAO,EAAE,MAAM,SAAS,CAAA;AAGtE,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AA0S3C,wBAAsB,wBAAwB,CAC5C,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,YAAY,EAAE,CAAC,CA6VzB"}
@@ -3,6 +3,7 @@ import type { GetTransformProps, GetTransformResponse } from './types';
3
3
  type Props = GetTransformProps & {
4
4
  userSetting?: GetTransformResponse;
5
5
  };
6
+ export declare function findUserBabelConfig(projectRoot?: string): string | null;
6
7
  export declare function getBabelOptions(props: Props): babel.TransformOptions | null;
7
8
  /**
8
9
  * Run the react compiler through oxc's rust port instead of babel.
@@ -13,7 +14,9 @@ export declare function getBabelOptions(props: Props): babel.TransformOptions |
13
14
  * still applies the project's jsxImportSource and dev-mode settings, exactly
14
15
  * as it did when babel only stripped types here.
15
16
  */
16
- export declare function transformOxcReactCompiler(id: string, code: string, target: '18' | '19', sourceMap?: boolean): Promise<{
17
+ export declare function transformOxcReactCompiler(id: string, code: string, optionsOrTarget?: '18' | '19' | (Record<string, any> & {
18
+ target?: '18' | '19';
19
+ }), sourceMap?: boolean): Promise<{
17
20
  code: string;
18
21
  map: any;
19
22
  }>;
@@ -21,5 +24,17 @@ export declare function transformOxcReactCompiler(id: string, code: string, targ
21
24
  * Transform input to mostly ES5 compatible code, keep ESM syntax, and transform generators.
22
25
  */
23
26
  export declare function transformBabel(id: string, code: string, options: babel.TransformOptions): Promise<babel.BabelFileResult>;
27
+ export declare function stripFlowTypes(id: string, code: string, sourceMaps?: boolean): Promise<{
28
+ code: string;
29
+ map: {
30
+ version: number;
31
+ sources: string[];
32
+ names: string[];
33
+ sourceRoot?: string | undefined;
34
+ sourcesContent?: string[] | undefined;
35
+ mappings: string;
36
+ file: string;
37
+ } | null | undefined;
38
+ }>;
24
39
  export {};
25
40
  //# sourceMappingURL=transformBabel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transformBabel.d.ts","sourceRoot":"","sources":["../src/transformBabel.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,KAAK,MAAM,aAAa,CAAA;AAKzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEtE,KAAK,KAAK,GAAG,iBAAiB,GAAG;IAC/B,WAAW,CAAC,EAAE,oBAAoB,CAAA;CACnC,CAAA;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAoB3E;AA8CD;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,IAAI,GAAG,IAAI,EACnB,SAAS,UAAQ;;;GA4BlB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC,gBAAgB,kCAsDhC"}
1
+ {"version":3,"file":"transformBabel.d.ts","sourceRoot":"","sources":["../src/transformBabel.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,KAAK,MAAM,aAAa,CAAA;AAKzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEtE,KAAK,KAAK,GAAG,iBAAiB,GAAG;IAC/B,WAAW,CAAC,EAAE,oBAAoB,CAAA;CACnC,CAAA;AAcD,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBvE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,gBAAgB,GAAG,IAAI,CA+C3E;AAuDD;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,eAAe,GAAE,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,CAAQ,EACtF,SAAS,UAAQ;;;GAyClB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC,gBAAgB,kCAyDhC;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,UAAO;;;;;;;;;;;GAM/E"}