@vxrn/compiler 1.25.13 → 1.25.16-1788753284749
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cache.cjs +3 -1
- package/dist/cjs/configure.cjs +9 -1
- package/dist/cjs/index.cjs +82 -4
- package/dist/cjs/reactNativeCodegen.cjs +140 -0
- package/dist/cjs/reactNativeViewConfig.cjs +489 -0
- package/dist/cjs/transformBabel.cjs +15 -20
- package/dist/cjs/transformBabel.test.cjs +260 -0
- package/dist/cjs/transformHermesLoops.cjs +317 -0
- package/dist/cjs/transformHermesLoops.test.cjs +220 -0
- package/dist/cjs/transformSWC.cjs +102 -137
- package/dist/cjs/transformSWC.test.cjs +74 -0
- package/dist/cjs/transformWorklets.cjs +121 -0
- package/dist/cjs/transformWorklets.test.cjs +604 -0
- package/dist/cjs/worklets/autoworklet.cjs +265 -0
- package/dist/cjs/worklets/globals.cjs +71 -0
- package/dist/cjs/worklets/hash.cjs +38 -0
- package/dist/cjs/worklets/scope.cjs +370 -0
- package/dist/cjs/worklets/serialize.cjs +101 -0
- package/dist/cjs/worklets/transform.cjs +232 -0
- package/dist/cjs/worklets/types.cjs +18 -0
- package/dist/esm/cache.mjs +4 -2
- package/dist/esm/cache.mjs.map +1 -1
- package/dist/esm/configure.mjs +8 -1
- package/dist/esm/configure.mjs.map +1 -1
- package/dist/esm/index.js +72 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +72 -5
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/reactNativeCodegen.mjs +104 -0
- package/dist/esm/reactNativeCodegen.mjs.map +1 -0
- package/dist/esm/reactNativeViewConfig.mjs +460 -0
- package/dist/esm/reactNativeViewConfig.mjs.map +1 -0
- package/dist/esm/transformBabel.mjs +14 -19
- package/dist/esm/transformBabel.mjs.map +1 -1
- package/dist/esm/transformBabel.test.mjs +261 -1
- package/dist/esm/transformBabel.test.mjs.map +1 -1
- package/dist/esm/transformHermesLoops.mjs +281 -0
- package/dist/esm/transformHermesLoops.mjs.map +1 -0
- package/dist/esm/transformHermesLoops.test.mjs +197 -0
- package/dist/esm/transformHermesLoops.test.mjs.map +1 -0
- package/dist/esm/transformSWC.mjs +89 -138
- package/dist/esm/transformSWC.mjs.map +1 -1
- package/dist/esm/transformSWC.test.mjs +75 -0
- package/dist/esm/transformSWC.test.mjs.map +1 -0
- package/dist/esm/transformWorklets.mjs +81 -0
- package/dist/esm/transformWorklets.mjs.map +1 -0
- package/dist/esm/transformWorklets.test.mjs +581 -0
- package/dist/esm/transformWorklets.test.mjs.map +1 -0
- package/dist/esm/worklets/autoworklet.mjs +234 -0
- package/dist/esm/worklets/autoworklet.mjs.map +1 -0
- package/dist/esm/worklets/globals.mjs +45 -0
- package/dist/esm/worklets/globals.mjs.map +1 -0
- package/dist/esm/worklets/hash.mjs +13 -0
- package/dist/esm/worklets/hash.mjs.map +1 -0
- package/dist/esm/worklets/scope.mjs +345 -0
- package/dist/esm/worklets/scope.mjs.map +1 -0
- package/dist/esm/worklets/serialize.mjs +75 -0
- package/dist/esm/worklets/serialize.mjs.map +1 -0
- package/dist/esm/worklets/transform.mjs +196 -0
- package/dist/esm/worklets/transform.mjs.map +1 -0
- package/dist/esm/worklets/types.mjs +2 -0
- package/dist/esm/worklets/types.mjs.map +1 -0
- package/package.json +10 -6
- package/src/cache.ts +9 -2
- package/src/configure.ts +12 -0
- package/src/index.ts +93 -13
- package/src/reactNativeCodegen.ts +181 -0
- package/src/reactNativeViewConfig.ts +593 -0
- package/src/transformBabel.test.ts +268 -1
- package/src/transformBabel.ts +21 -31
- package/src/transformHermesLoops.test.ts +282 -0
- package/src/transformHermesLoops.ts +433 -0
- package/src/transformSWC.test.ts +88 -0
- package/src/transformSWC.ts +109 -160
- package/src/transformWorklets.test.ts +708 -0
- package/src/transformWorklets.ts +160 -0
- package/src/types.ts +4 -4
- package/src/worklets/autoworklet.ts +391 -0
- package/src/worklets/globals.ts +125 -0
- package/src/worklets/hash.ts +14 -0
- package/src/worklets/scope.ts +401 -0
- package/src/worklets/serialize.ts +114 -0
- package/src/worklets/transform.ts +282 -0
- package/src/worklets/types.ts +26 -0
- package/types/cache.d.ts +1 -0
- package/types/cache.d.ts.map +1 -1
- package/types/configure.d.ts +2 -0
- package/types/configure.d.ts.map +1 -1
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -1
- package/types/reactNativeCodegen.d.ts +5 -0
- package/types/reactNativeCodegen.d.ts.map +1 -0
- package/types/reactNativeViewConfig.d.ts +35 -0
- package/types/reactNativeViewConfig.d.ts.map +1 -0
- package/types/transformBabel.d.ts +3 -3
- package/types/transformBabel.d.ts.map +1 -1
- package/types/transformHermesLoops.d.ts +5 -0
- package/types/transformHermesLoops.d.ts.map +1 -0
- package/types/transformHermesLoops.test.d.ts +2 -0
- package/types/transformHermesLoops.test.d.ts.map +1 -0
- package/types/transformSWC.d.ts +12 -3
- package/types/transformSWC.d.ts.map +1 -1
- package/types/transformSWC.test.d.ts +2 -0
- package/types/transformSWC.test.d.ts.map +1 -0
- package/types/transformWorklets.d.ts +22 -0
- package/types/transformWorklets.d.ts.map +1 -0
- package/types/transformWorklets.test.d.ts +2 -0
- package/types/transformWorklets.test.d.ts.map +1 -0
- package/types/types.d.ts +4 -4
- package/types/types.d.ts.map +1 -1
- package/types/worklets/autoworklet.d.ts +14 -0
- package/types/worklets/autoworklet.d.ts.map +1 -0
- package/types/worklets/globals.d.ts +3 -0
- package/types/worklets/globals.d.ts.map +1 -0
- package/types/worklets/hash.d.ts +5 -0
- package/types/worklets/hash.d.ts.map +1 -0
- package/types/worklets/scope.d.ts +7 -0
- package/types/worklets/scope.d.ts.map +1 -0
- package/types/worklets/serialize.d.ts +12 -0
- package/types/worklets/serialize.d.ts.map +1 -0
- package/types/worklets/transform.d.ts +6 -0
- package/types/worklets/transform.d.ts.map +1 -0
- package/types/worklets/types.d.ts +21 -0
- package/types/worklets/types.d.ts.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vxrn/compiler",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.16-1788753284749",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./package.json": "./package.json",
|
|
@@ -35,16 +35,20 @@
|
|
|
35
35
|
"@babel/plugin-transform-flow-strip-types": "^7.27.1",
|
|
36
36
|
"@babel/plugin-transform-react-jsx": "^7.27.1",
|
|
37
37
|
"@babel/plugin-transform-regenerator": "^7.28.4",
|
|
38
|
-
"@
|
|
39
|
-
"@vxrn/utils": "1.25.
|
|
40
|
-
"@vxrn/vite-native-client": "1.25.
|
|
38
|
+
"@jridgewell/remapping": "^2.3.0",
|
|
39
|
+
"@vxrn/utils": "1.25.16-1788753284749",
|
|
40
|
+
"@vxrn/vite-native-client": "1.25.16-1788753284749",
|
|
41
41
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
42
42
|
"babel-plugin-syntax-hermes-parser": "^0.32.0",
|
|
43
|
+
"hermes-parser": "^0.32.0",
|
|
44
|
+
"magic-string": "^0.30.21",
|
|
45
|
+
"oxc-parser": "^0.112.0",
|
|
46
|
+
"oxc-transform": "^0.112.0",
|
|
43
47
|
"oxc-transform-react": "^0.145.0",
|
|
44
|
-
"react-native-css-interop": "^0.2.6"
|
|
45
|
-
"ts-deepmerge": "^7.0.2"
|
|
48
|
+
"react-native-css-interop": "^0.2.6"
|
|
46
49
|
},
|
|
47
50
|
"devDependencies": {
|
|
51
|
+
"@jridgewell/trace-mapping": "^0.3.25",
|
|
48
52
|
"@tamagui/build": "2.6.2",
|
|
49
53
|
"depcheck": "^1.4.7",
|
|
50
54
|
"rolldown": "^1.2.4",
|
package/src/cache.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto'
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
|
-
import { configuration } from './configure'
|
|
4
|
+
import { configuration, isNativeWorkletsEnabled } from './configure'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Fast file-based cache for babel transforms
|
|
@@ -23,9 +23,15 @@ interface CacheStats {
|
|
|
23
23
|
hits: 0
|
|
24
24
|
misses: 0
|
|
25
25
|
writes: 0
|
|
26
|
+
errors: 0
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
const stats: CacheStats = {
|
|
29
|
+
const stats: CacheStats = {
|
|
30
|
+
hits: 0,
|
|
31
|
+
misses: 0,
|
|
32
|
+
writes: 0,
|
|
33
|
+
errors: 0,
|
|
34
|
+
}
|
|
29
35
|
|
|
30
36
|
function getCacheDir(): string {
|
|
31
37
|
// Use .vxrn cache directory
|
|
@@ -43,6 +49,7 @@ function getConfigFingerprint(): string {
|
|
|
43
49
|
JSON.stringify({
|
|
44
50
|
compiler: configuration.enableCompiler,
|
|
45
51
|
reanimated: configuration.enableReanimated,
|
|
52
|
+
nativeWorklets: isNativeWorkletsEnabled(),
|
|
46
53
|
nativewind: configuration.enableNativewind,
|
|
47
54
|
nativeCSS: configuration.enableNativeCSS,
|
|
48
55
|
// bump when the transform engine changes, so entries written by a
|
package/src/configure.ts
CHANGED
|
@@ -18,6 +18,7 @@ type CompilerConfig =
|
|
|
18
18
|
type Conf = {
|
|
19
19
|
enableNativewind?: boolean
|
|
20
20
|
enableReanimated?: boolean
|
|
21
|
+
enableNativeWorklets?: boolean
|
|
21
22
|
enableCompiler?: CompilerConfig
|
|
22
23
|
enableNativeCSS?: boolean
|
|
23
24
|
}
|
|
@@ -25,10 +26,21 @@ type Conf = {
|
|
|
25
26
|
export const configuration: Conf = {
|
|
26
27
|
enableNativewind: false,
|
|
27
28
|
enableReanimated: false,
|
|
29
|
+
enableNativeWorklets: true,
|
|
28
30
|
enableCompiler: false,
|
|
29
31
|
enableNativeCSS: false,
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
export function isNativeWorkletsEnabled() {
|
|
35
|
+
if (
|
|
36
|
+
process.env.VXRN_NATIVE_WORKLETS === 'false' ||
|
|
37
|
+
process.env.VXRN_NATIVE_WORKLETS === '0'
|
|
38
|
+
) {
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
return configuration.enableNativeWorklets !== false
|
|
42
|
+
}
|
|
43
|
+
|
|
32
44
|
export function configureVXRNCompilerPlugin(_: Conf) {
|
|
33
45
|
Object.assign(configuration, _)
|
|
34
46
|
}
|
package/src/index.ts
CHANGED
|
@@ -12,19 +12,24 @@ import { resolvePath } from '@vxrn/utils'
|
|
|
12
12
|
import { cssToReactNativeRuntime } from 'react-native-css-interop/css-to-rn/index.js'
|
|
13
13
|
import type { OutputChunk } from 'rolldown'
|
|
14
14
|
import type { PluginOption, ResolvedConfig, UserConfig } from 'vite'
|
|
15
|
-
import { configuration } from './configure'
|
|
15
|
+
import { configuration, isNativeWorkletsEnabled } from './configure'
|
|
16
16
|
import { debug, runtimePublicPath, validParsers } from './constants'
|
|
17
17
|
import {
|
|
18
18
|
getBabelOptions,
|
|
19
19
|
transformBabel,
|
|
20
20
|
transformOxcReactCompiler,
|
|
21
21
|
} from './transformBabel'
|
|
22
|
+
import { shouldSourceMap } from './transformSWC'
|
|
23
|
+
import { shouldTransformWorklets, transformWorklets } from './transformWorklets'
|
|
22
24
|
import type { Environment, GetTransformProps, Options } from './types'
|
|
23
25
|
import { getCachedTransform, logCacheStats, setCachedTransform } from './cache'
|
|
24
26
|
|
|
25
27
|
export * from './configure'
|
|
26
28
|
export * from './transformBabel'
|
|
27
29
|
export * from './transformSWC'
|
|
30
|
+
export * from './transformWorklets'
|
|
31
|
+
export * from './reactNativeCodegen'
|
|
32
|
+
export * from './transformHermesLoops'
|
|
28
33
|
export type { GetTransform } from './types'
|
|
29
34
|
|
|
30
35
|
// Performance tracking
|
|
@@ -148,7 +153,7 @@ async function performBabelTransform({
|
|
|
148
153
|
return null
|
|
149
154
|
}
|
|
150
155
|
|
|
151
|
-
if (userTransform !== 'swc') {
|
|
156
|
+
if (userTransform !== 'swc' && userTransform !== 'oxc') {
|
|
152
157
|
const babelOptions = getBabelOptions({
|
|
153
158
|
...transformProps,
|
|
154
159
|
userSetting: userTransform,
|
|
@@ -175,20 +180,95 @@ async function performBabelTransform({
|
|
|
175
180
|
return cached
|
|
176
181
|
}
|
|
177
182
|
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
// React compiler through oxc's rust port instead of babel.
|
|
184
|
+
let compilerOut: { code: string; map?: any } | null = null
|
|
185
|
+
const compilerPluginIndex =
|
|
186
|
+
babelOptions.plugins?.findIndex(
|
|
187
|
+
(x) => Array.isArray(x) && x[0] === 'babel-plugin-react-compiler'
|
|
188
|
+
) ?? -1
|
|
189
|
+
|
|
190
|
+
if (compilerPluginIndex !== -1) {
|
|
191
|
+
const compilerTarget =
|
|
192
|
+
(babelOptions.plugins![compilerPluginIndex] as any[])[1]?.target ?? '19'
|
|
193
|
+
compilerOut = await transformOxcReactCompiler(
|
|
194
|
+
id,
|
|
195
|
+
code,
|
|
196
|
+
compilerTarget,
|
|
197
|
+
shouldSourceMap()
|
|
198
|
+
)
|
|
199
|
+
babelOptions.plugins!.splice(compilerPluginIndex, 1)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let curCode = compilerOut ? compilerOut.code : code
|
|
203
|
+
|
|
204
|
+
// Native Worklets through custom native/Oxc worklet transformer instead of babel.
|
|
205
|
+
let workletsOut: { code: string; map?: any } | null = null
|
|
206
|
+
const isWorkletPlugin = (entry: any) => {
|
|
207
|
+
if (!entry) return false
|
|
208
|
+
const name =
|
|
209
|
+
typeof entry === 'string' ? entry : Array.isArray(entry) ? entry[0] : null
|
|
210
|
+
return (
|
|
211
|
+
typeof name === 'string' &&
|
|
212
|
+
(name.includes('react-native-worklets') ||
|
|
213
|
+
name.includes('react-native-reanimated'))
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
const workletPluginIndex = babelOptions.plugins?.findIndex(isWorkletPlugin) ?? -1
|
|
217
|
+
let workletPluginOptions: any = undefined
|
|
218
|
+
if (workletPluginIndex !== -1) {
|
|
219
|
+
const entry = babelOptions.plugins![workletPluginIndex]
|
|
220
|
+
if (Array.isArray(entry) && entry[1] && typeof entry[1] === 'object') {
|
|
221
|
+
workletPluginOptions = entry[1]
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (
|
|
226
|
+
isNativeWorkletsEnabled() &&
|
|
227
|
+
(workletPluginIndex !== -1 || shouldTransformWorklets({ id, code: curCode }))
|
|
228
|
+
) {
|
|
229
|
+
workletsOut = await transformWorklets(id, curCode, shouldSourceMap(), {
|
|
230
|
+
projectRoot,
|
|
231
|
+
...workletPluginOptions,
|
|
232
|
+
})
|
|
233
|
+
if (workletPluginIndex !== -1) {
|
|
234
|
+
babelOptions.plugins!.splice(workletPluginIndex, 1)
|
|
235
|
+
}
|
|
236
|
+
curCode = workletsOut.code
|
|
237
|
+
}
|
|
186
238
|
|
|
187
239
|
// Cache miss - do the transform
|
|
188
240
|
const startTime = Date.now()
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
241
|
+
let babelOut: { code?: string | null; map?: any } | null = null
|
|
242
|
+
|
|
243
|
+
if (babelOptions.plugins?.length === 0) {
|
|
244
|
+
let finalMap: any = undefined
|
|
245
|
+
if (shouldSourceMap()) {
|
|
246
|
+
const intermediateMaps = [compilerOut?.map, workletsOut?.map].filter(Boolean)
|
|
247
|
+
if (intermediateMaps.length === 1) {
|
|
248
|
+
finalMap = intermediateMaps[0]
|
|
249
|
+
} else if (intermediateMaps.length > 1) {
|
|
250
|
+
const remapping = (await import('@jridgewell/remapping')).default
|
|
251
|
+
finalMap = remapping(intermediateMaps.slice().reverse(), () => null)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
babelOut = { code: curCode, map: finalMap }
|
|
255
|
+
} else {
|
|
256
|
+
const babelOptsWithMap =
|
|
257
|
+
shouldSourceMap() && (workletsOut?.map || compilerOut?.map)
|
|
258
|
+
? { ...babelOptions, sourceMaps: true }
|
|
259
|
+
: babelOptions
|
|
260
|
+
babelOut = await transformBabel(id, curCode, babelOptsWithMap)
|
|
261
|
+
if (shouldSourceMap() && babelOut?.map) {
|
|
262
|
+
const priorMaps = [compilerOut?.map, workletsOut?.map].filter(Boolean)
|
|
263
|
+
if (priorMaps.length > 0) {
|
|
264
|
+
const remapping = (await import('@jridgewell/remapping')).default
|
|
265
|
+
babelOut.map = remapping(
|
|
266
|
+
[babelOut.map, ...priorMaps.slice().reverse()],
|
|
267
|
+
() => null
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
192
272
|
const babelTime = Date.now() - startTime
|
|
193
273
|
|
|
194
274
|
if (babelOut?.code) {
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import MagicString from 'magic-string'
|
|
2
|
+
import {
|
|
3
|
+
generateViewConfig,
|
|
4
|
+
parseSpec,
|
|
5
|
+
renderViewConfigModule,
|
|
6
|
+
} from './reactNativeViewConfig'
|
|
7
|
+
|
|
8
|
+
// vite's normalizePath, inlined so this stays usable from the metro transformer
|
|
9
|
+
// worker, which must not pull vite into a worker process.
|
|
10
|
+
function normalizePath(id: string) {
|
|
11
|
+
return id.replace(/\\/g, '/')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const CODEGEN_FILE_RE = /(?:NativeComponent\.[cm]?[jt]sx?$|[/\\]specs?[/\\])/
|
|
15
|
+
const CODEGEN_CALL_RE = /codegenNativeComponent\s*[<(]/
|
|
16
|
+
|
|
17
|
+
// oxc reports positions as start/end, hermes-parser (the flow specs) as range
|
|
18
|
+
const startOf = (node: any): number => node.start ?? node.range[0]
|
|
19
|
+
const endOf = (node: any): number => node.end ?? node.range[1]
|
|
20
|
+
|
|
21
|
+
function unwrapExpression(node: any): any {
|
|
22
|
+
while (node) {
|
|
23
|
+
if (
|
|
24
|
+
node.type === 'TSAsExpression' ||
|
|
25
|
+
node.type === 'TSSatisfiesExpression' ||
|
|
26
|
+
node.type === 'TSTypeAssertion' ||
|
|
27
|
+
node.type === 'TypeCastExpression' ||
|
|
28
|
+
node.type === 'AsExpression' ||
|
|
29
|
+
node.type === 'ParenthesizedExpression'
|
|
30
|
+
) {
|
|
31
|
+
node = node.expression
|
|
32
|
+
} else if (
|
|
33
|
+
node.type === 'SequenceExpression' &&
|
|
34
|
+
Array.isArray(node.expressions) &&
|
|
35
|
+
node.expressions.length > 0
|
|
36
|
+
) {
|
|
37
|
+
node = node.expressions[node.expressions.length - 1]
|
|
38
|
+
} else {
|
|
39
|
+
break
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return node
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isCodegenDeclaration(declaration: any): boolean {
|
|
46
|
+
if (!declaration) return false
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
declaration.left &&
|
|
50
|
+
declaration.left.left &&
|
|
51
|
+
declaration.left.left.name === 'codegenNativeComponent'
|
|
52
|
+
) {
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const unwrapped = unwrapExpression(declaration)
|
|
57
|
+
return (
|
|
58
|
+
unwrapped?.type === 'CallExpression' &&
|
|
59
|
+
unwrapped.callee?.type === 'Identifier' &&
|
|
60
|
+
unwrapped.callee.name === 'codegenNativeComponent'
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isCodegenNativeCommandsDeclaration(declaration: any): boolean {
|
|
65
|
+
if (!declaration) return false
|
|
66
|
+
const unwrapped = unwrapExpression(declaration)
|
|
67
|
+
return (
|
|
68
|
+
unwrapped?.type === 'CallExpression' &&
|
|
69
|
+
unwrapped.callee?.type === 'Identifier' &&
|
|
70
|
+
unwrapped.callee.name === 'codegenNativeCommands'
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function transformReactNativeCodegen(
|
|
75
|
+
code: string,
|
|
76
|
+
id: string,
|
|
77
|
+
projectRoot?: string
|
|
78
|
+
): { code: string; map: any } | null | undefined {
|
|
79
|
+
const cleanId = normalizePath(id.split('?')[0])
|
|
80
|
+
|
|
81
|
+
if (!CODEGEN_FILE_RE.test(cleanId)) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// the transform runs more than once over the same module, so it must not
|
|
86
|
+
// reject the output it just produced. matching the bare name matches the
|
|
87
|
+
// surviving `import codegenNativeComponent from ...` too; only a remaining
|
|
88
|
+
// CALL means the file still needs generating. a comment marker cannot do
|
|
89
|
+
// this job because oxc drops leading comments on the next pass.
|
|
90
|
+
if (!CODEGEN_CALL_RE.test(code)) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const program = parseSpec(code, cleanId, projectRoot)
|
|
95
|
+
const body = program?.body
|
|
96
|
+
if (!body) {
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let defaultExport: any = null
|
|
101
|
+
let commandsExport: any = null
|
|
102
|
+
|
|
103
|
+
for (const node of body) {
|
|
104
|
+
if (node.type === 'ExportDefaultDeclaration') {
|
|
105
|
+
if (isCodegenDeclaration(node.declaration)) {
|
|
106
|
+
defaultExport = node
|
|
107
|
+
}
|
|
108
|
+
} else if (node.type === 'ExportNamedDeclaration') {
|
|
109
|
+
if (node.declaration && node.declaration.declarations) {
|
|
110
|
+
const firstDeclaration = node.declaration.declarations[0]
|
|
111
|
+
if (firstDeclaration?.type === 'VariableDeclarator') {
|
|
112
|
+
const isValidCommandsExport = isCodegenNativeCommandsDeclaration(
|
|
113
|
+
firstDeclaration.init
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
if (isValidCommandsExport) {
|
|
117
|
+
if (
|
|
118
|
+
firstDeclaration.id?.type === 'Identifier' &&
|
|
119
|
+
firstDeclaration.id.name !== 'Commands'
|
|
120
|
+
) {
|
|
121
|
+
throw new Error("Native commands must be exported with the name 'Commands'")
|
|
122
|
+
}
|
|
123
|
+
commandsExport = node
|
|
124
|
+
} else {
|
|
125
|
+
if (
|
|
126
|
+
firstDeclaration.id?.type === 'Identifier' &&
|
|
127
|
+
firstDeclaration.id.name === 'Commands'
|
|
128
|
+
) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
"'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands."
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} else if (node.specifiers && node.specifiers.length > 0) {
|
|
136
|
+
for (const specifier of node.specifiers) {
|
|
137
|
+
if (
|
|
138
|
+
specifier.type === 'ExportSpecifier' &&
|
|
139
|
+
((specifier.local?.type === 'Identifier' &&
|
|
140
|
+
specifier.local.name === 'Commands') ||
|
|
141
|
+
(specifier.exported?.type === 'Identifier' &&
|
|
142
|
+
specifier.exported.name === 'Commands'))
|
|
143
|
+
) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
"'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands."
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (!defaultExport) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const generated = generateViewConfig(program)
|
|
158
|
+
if (!generated) {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const s = new MagicString(code)
|
|
163
|
+
|
|
164
|
+
if (commandsExport) {
|
|
165
|
+
let removeEnd = endOf(commandsExport)
|
|
166
|
+
if (code[removeEnd] === '\r') removeEnd++
|
|
167
|
+
if (code[removeEnd] === '\n') removeEnd++
|
|
168
|
+
s.remove(startOf(commandsExport), removeEnd)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
s.overwrite(
|
|
172
|
+
startOf(defaultExport),
|
|
173
|
+
endOf(defaultExport),
|
|
174
|
+
renderViewConfigModule(generated)
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
code: s.toString(),
|
|
179
|
+
map: s.generateMap({ hires: true, source: cleanId }),
|
|
180
|
+
}
|
|
181
|
+
}
|