@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/dist/cjs/cache.cjs +21 -7
- package/dist/cjs/index.cjs +15 -10
- package/dist/cjs/transformBabel.cjs +71 -11
- package/dist/cjs/transformBabel.test.cjs +309 -0
- package/dist/cjs/transformWorklets.test.cjs +3 -1
- package/dist/esm/cache.mjs +21 -7
- package/dist/esm/cache.mjs.map +1 -1
- package/dist/esm/index.js +15 -10
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +15 -10
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/transformBabel.mjs +71 -13
- package/dist/esm/transformBabel.mjs.map +1 -1
- package/dist/esm/transformBabel.test.mjs +310 -1
- package/dist/esm/transformBabel.test.mjs.map +1 -1
- package/dist/esm/transformWorklets.test.mjs +3 -1
- package/dist/esm/transformWorklets.test.mjs.map +1 -1
- package/package.json +7 -6
- package/src/cache.ts +37 -7
- package/src/index.ts +33 -18
- package/src/transformBabel.test.ts +270 -0
- package/src/transformBabel.ts +104 -12
- package/src/transformWorklets.test.ts +7 -1
- package/types/cache.d.ts +2 -2
- package/types/cache.d.ts.map +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/transformBabel.d.ts +16 -1
- package/types/transformBabel.d.ts.map +1 -1
package/dist/cjs/cache.cjs
CHANGED
|
@@ -48,30 +48,44 @@ function getCacheDir() {
|
|
|
48
48
|
}
|
|
49
49
|
return cacheDir;
|
|
50
50
|
}
|
|
51
|
-
function getConfigFingerprint() {
|
|
51
|
+
function getConfigFingerprint(userBabelConfigPath) {
|
|
52
52
|
return (0, import_node_crypto.createHash)("sha1").update(JSON.stringify({
|
|
53
53
|
compiler: import_configure.configuration.enableCompiler,
|
|
54
54
|
reanimated: import_configure.configuration.enableReanimated,
|
|
55
55
|
nativeWorklets: (0, import_configure.isNativeWorkletsEnabled)(),
|
|
56
56
|
nativewind: import_configure.configuration.enableNativewind,
|
|
57
57
|
nativeCSS: import_configure.configuration.enableNativeCSS,
|
|
58
|
+
// transform output depends on the user babel config when one applies,
|
|
59
|
+
// so its identity joins the fingerprint. adding, removing, or editing
|
|
60
|
+
// babel.config.* must miss entries written without that change.
|
|
61
|
+
babelConfig: getBabelConfigIdentity(userBabelConfigPath),
|
|
58
62
|
// bump when the transform engine changes, so entries written by a
|
|
59
63
|
// previous engine aren't served for the same source
|
|
60
64
|
engine: "oxc-worklets-hermes-async"
|
|
61
65
|
})).digest("hex").slice(0, 8);
|
|
62
66
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
67
|
+
function getBabelConfigIdentity(configPath) {
|
|
68
|
+
if (!configPath) return null;
|
|
69
|
+
try {
|
|
70
|
+
const mtime = (0, import_node_fs.statSync)(configPath).mtimeMs;
|
|
71
|
+
const hash = (0, import_node_crypto.createHash)("sha1").update((0, import_node_fs.readFileSync)(configPath)).digest("hex").slice(0, 16);
|
|
72
|
+
return `${configPath}:${mtime}:${hash}`;
|
|
73
|
+
} catch {
|
|
74
|
+
return configPath;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function getCacheKey(filePath, environment, userBabelConfigPath) {
|
|
78
|
+
const hash = (0, import_node_crypto.createHash)("sha1").update(`${environment}:${filePath}:${getConfigFingerprint(userBabelConfigPath)}`).digest("hex");
|
|
65
79
|
return hash;
|
|
66
80
|
}
|
|
67
81
|
function getContentHash(code) {
|
|
68
82
|
return (0, import_node_crypto.createHash)("sha1").update(code).digest("hex").slice(0, 16);
|
|
69
83
|
}
|
|
70
|
-
function getCachedTransform(filePath, code, environment) {
|
|
84
|
+
function getCachedTransform(filePath, code, environment, userBabelConfigPath) {
|
|
71
85
|
try {
|
|
72
86
|
const cleanPath = filePath.startsWith("\0") ? filePath.slice(1) : filePath;
|
|
73
87
|
const cacheDir = getCacheDir();
|
|
74
|
-
const cacheKey = getCacheKey(cleanPath, environment);
|
|
88
|
+
const cacheKey = getCacheKey(cleanPath, environment, userBabelConfigPath);
|
|
75
89
|
const cachePath = (0, import_node_path.join)(cacheDir, `${cacheKey}.json`);
|
|
76
90
|
if (!(0, import_node_fs.existsSync)(cachePath)) {
|
|
77
91
|
stats.misses++;
|
|
@@ -98,11 +112,11 @@ function getCachedTransform(filePath, code, environment) {
|
|
|
98
112
|
return null;
|
|
99
113
|
}
|
|
100
114
|
}
|
|
101
|
-
function setCachedTransform(filePath, code, result, environment) {
|
|
115
|
+
function setCachedTransform(filePath, code, result, environment, userBabelConfigPath) {
|
|
102
116
|
try {
|
|
103
117
|
const cleanPath = filePath.startsWith("\0") ? filePath.slice(1) : filePath;
|
|
104
118
|
const cacheDir = getCacheDir();
|
|
105
|
-
const cacheKey = getCacheKey(cleanPath, environment);
|
|
119
|
+
const cacheKey = getCacheKey(cleanPath, environment, userBabelConfigPath);
|
|
106
120
|
const cachePath = (0, import_node_path.join)(cacheDir, `${cacheKey}.json`);
|
|
107
121
|
const mtime = (0, import_node_fs.statSync)(cleanPath).mtimeMs;
|
|
108
122
|
const hash = getContentHash(code);
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -155,7 +155,8 @@ async function performBabelTransform({
|
|
|
155
155
|
});
|
|
156
156
|
if (babelOptions) {
|
|
157
157
|
const hasCompilerPlugin = babelOptions.plugins?.some(x => Array.isArray(x) && x[0] === "babel-plugin-react-compiler");
|
|
158
|
-
const
|
|
158
|
+
const userBabelConfigPath = typeof babelOptions.configFile === "string" ? babelOptions.configFile : null;
|
|
159
|
+
const cached = (0, import_cache.getCachedTransform)(id, code, environment, userBabelConfigPath);
|
|
159
160
|
if (cached) {
|
|
160
161
|
perfStats.babel.byEnvironment[environment].transforms++;
|
|
161
162
|
if (hasCompilerPlugin && (cached.code.includes("react/compiler-runtime") || cached.code.includes("react-compiler-runtime"))) {
|
|
@@ -181,14 +182,18 @@ async function performBabelTransform({
|
|
|
181
182
|
let compilerOut = null;
|
|
182
183
|
const compilerPluginIndex = babelOptions.plugins?.findIndex(x => Array.isArray(x) && x[0] === "babel-plugin-react-compiler") ?? -1;
|
|
183
184
|
if (compilerPluginIndex !== -1) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
const compilerPluginConfig = babelOptions.plugins[compilerPluginIndex];
|
|
186
|
+
const compilerPluginOptions = compilerPluginConfig[1] || {};
|
|
187
|
+
const useBabelCompiler = compilerPluginOptions.compiler === "babel" || process.env.ONE_REACT_COMPILER === "babel" || process.env.VXRN_REACT_COMPILER === "babel";
|
|
188
|
+
if (!useBabelCompiler) {
|
|
189
|
+
if (useWorklets) {
|
|
190
|
+
workletPreparation = (0, import_transformWorklets.prepareWorkletsForReactCompiler)(id, curCode, (0, import_transformSWC.shouldSourceMap)());
|
|
191
|
+
if (workletPreparation) curCode = workletPreparation.code;
|
|
192
|
+
}
|
|
193
|
+
compilerOut = await (0, import_transformBabel.transformOxcReactCompiler)(id, curCode, compilerPluginOptions, (0, import_transformSWC.shouldSourceMap)());
|
|
194
|
+
if (compilerOut) curCode = compilerOut.code;
|
|
195
|
+
babelOptions.plugins.splice(compilerPluginIndex, 1);
|
|
187
196
|
}
|
|
188
|
-
const compilerTarget = babelOptions.plugins[compilerPluginIndex][1]?.target ?? "19";
|
|
189
|
-
compilerOut = await (0, import_transformBabel.transformOxcReactCompiler)(id, curCode, compilerTarget, (0, import_transformSWC.shouldSourceMap)());
|
|
190
|
-
if (compilerOut) curCode = compilerOut.code;
|
|
191
|
-
babelOptions.plugins.splice(compilerPluginIndex, 1);
|
|
192
197
|
}
|
|
193
198
|
let workletsOut = null;
|
|
194
199
|
if (useWorklets) {
|
|
@@ -201,7 +206,7 @@ async function performBabelTransform({
|
|
|
201
206
|
}
|
|
202
207
|
const startTime = Date.now();
|
|
203
208
|
let babelOut = null;
|
|
204
|
-
if (babelOptions.plugins?.length === 0) {
|
|
209
|
+
if (babelOptions.plugins?.length === 0 && !babelOptions.configFile && !babelOptions.babelrc) {
|
|
205
210
|
let finalMap = void 0;
|
|
206
211
|
if ((0, import_transformSWC.shouldSourceMap)()) {
|
|
207
212
|
const intermediateMaps = [workletPreparation?.map, compilerOut?.map, workletsOut?.map].filter(Boolean);
|
|
@@ -247,7 +252,7 @@ async function performBabelTransform({
|
|
|
247
252
|
code: outCode,
|
|
248
253
|
map: babelOut.map
|
|
249
254
|
};
|
|
250
|
-
(0, import_cache.setCachedTransform)(id, code, result, environment);
|
|
255
|
+
(0, import_cache.setCachedTransform)(id, code, result, environment, userBabelConfigPath);
|
|
251
256
|
return result;
|
|
252
257
|
}
|
|
253
258
|
}
|
|
@@ -33,33 +33,71 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
33
33
|
}), mod);
|
|
34
34
|
var transformBabel_exports = {};
|
|
35
35
|
__export(transformBabel_exports, {
|
|
36
|
+
findUserBabelConfig: () => findUserBabelConfig,
|
|
36
37
|
getBabelOptions: () => getBabelOptions,
|
|
38
|
+
stripFlowTypes: () => stripFlowTypes,
|
|
37
39
|
transformBabel: () => transformBabel,
|
|
38
40
|
transformOxcReactCompiler: () => transformOxcReactCompiler
|
|
39
41
|
});
|
|
40
42
|
module.exports = __toCommonJS(transformBabel_exports);
|
|
43
|
+
var import_node_fs = require("node:fs");
|
|
41
44
|
var import_node_path = require("node:path");
|
|
42
45
|
var import_utils = require("@vxrn/utils");
|
|
43
46
|
var import_vite = require("vite");
|
|
44
47
|
var import_configure = require("./configure.cjs");
|
|
45
48
|
var import_constants = require("./constants.cjs");
|
|
49
|
+
const USER_BABEL_CONFIG_FILES = ["babel.config.js", "babel.config.cjs", "babel.config.mjs", "babel.config.json", ".babelrc", ".babelrc.js", ".babelrc.json"];
|
|
50
|
+
const ONE_GENERATED_MARKER = "@one-generated";
|
|
51
|
+
function findUserBabelConfig(projectRoot) {
|
|
52
|
+
if (!projectRoot) return null;
|
|
53
|
+
for (const name of USER_BABEL_CONFIG_FILES) {
|
|
54
|
+
const fullPath = (0, import_node_path.join)(projectRoot, name);
|
|
55
|
+
if ((0, import_node_fs.existsSync)(fullPath)) {
|
|
56
|
+
try {
|
|
57
|
+
const content = (0, import_node_fs.readFileSync)(fullPath, "utf8");
|
|
58
|
+
if (content.includes(ONE_GENERATED_MARKER)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
return fullPath;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
46
69
|
function getBabelOptions(props) {
|
|
47
70
|
props = {
|
|
48
71
|
...props,
|
|
49
72
|
id: (0, import_vite.normalizePath)(props.id.split("?")[0])
|
|
50
73
|
};
|
|
74
|
+
const isProjectFile = !props.id.includes("node_modules");
|
|
75
|
+
const userBabelConfig = isProjectFile && props.projectRoot ? findUserBabelConfig(props.projectRoot) : null;
|
|
51
76
|
if (props.userSetting === "babel") {
|
|
52
|
-
return getOptions(props, true);
|
|
77
|
+
return getOptions(props, true, userBabelConfig);
|
|
53
78
|
}
|
|
54
79
|
if (typeof props.userSetting === "undefined" || typeof props.userSetting === "object" && props.userSetting.transform === "babel") {
|
|
55
80
|
if (props.userSetting?.excludeDefaultPlugins) {
|
|
56
|
-
return
|
|
81
|
+
return {
|
|
82
|
+
...props.userSetting,
|
|
83
|
+
...(userBabelConfig ? {
|
|
84
|
+
configFile: userBabelConfig,
|
|
85
|
+
babelrc: true
|
|
86
|
+
} : {})
|
|
87
|
+
};
|
|
57
88
|
}
|
|
58
|
-
return getOptions(props);
|
|
89
|
+
return getOptions(props, false, userBabelConfig);
|
|
90
|
+
}
|
|
91
|
+
const userSetting = props.userSetting;
|
|
92
|
+
if (userSetting === "swc" || userSetting === "oxc" || userSetting === false || typeof userSetting === "object" && userSetting !== null && (userSetting.transform === "swc" || userSetting.transform === "oxc")) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
if (userBabelConfig) {
|
|
96
|
+
return getOptions(props, false, userBabelConfig);
|
|
59
97
|
}
|
|
60
98
|
return null;
|
|
61
99
|
}
|
|
62
|
-
const getOptions = (props, force = false) => {
|
|
100
|
+
const getOptions = (props, force = false, userBabelConfig = null) => {
|
|
63
101
|
let plugins = [];
|
|
64
102
|
if (force || shouldBabelGenerators(props)) {
|
|
65
103
|
plugins = getBasePlugins(props);
|
|
@@ -85,22 +123,35 @@ const getOptions = (props, force = false) => {
|
|
|
85
123
|
(0, import_constants.debug)?.(`Using babel react compiler on file`);
|
|
86
124
|
plugins.push(getBabelReactCompilerPlugin(props));
|
|
87
125
|
}
|
|
88
|
-
if (plugins.length) {
|
|
126
|
+
if (plugins.length || userBabelConfig) {
|
|
89
127
|
return {
|
|
90
|
-
plugins
|
|
128
|
+
plugins,
|
|
129
|
+
...(userBabelConfig ? {
|
|
130
|
+
configFile: userBabelConfig,
|
|
131
|
+
babelrc: true
|
|
132
|
+
} : {})
|
|
91
133
|
};
|
|
92
134
|
}
|
|
93
135
|
return null;
|
|
94
136
|
};
|
|
95
|
-
async function transformOxcReactCompiler(id, code,
|
|
137
|
+
async function transformOxcReactCompiler(id, code, optionsOrTarget = "19", sourceMap = false) {
|
|
96
138
|
const {
|
|
97
139
|
transform
|
|
98
140
|
} = await import("oxc-transform-react");
|
|
141
|
+
const compilerOptions = typeof optionsOrTarget === "string" ? {
|
|
142
|
+
target: optionsOrTarget
|
|
143
|
+
} : optionsOrTarget || {};
|
|
144
|
+
const target = compilerOptions.target ?? "19";
|
|
99
145
|
const result = await transform(id, code, {
|
|
100
146
|
jsx: "preserve",
|
|
101
147
|
sourcemap: sourceMap,
|
|
102
148
|
reactCompiler: {
|
|
103
|
-
target
|
|
149
|
+
target,
|
|
150
|
+
...compilerOptions,
|
|
151
|
+
environment: {
|
|
152
|
+
enableCustomTypeDefinitionForReanimated: true,
|
|
153
|
+
...compilerOptions.environment
|
|
154
|
+
}
|
|
104
155
|
}
|
|
105
156
|
});
|
|
106
157
|
if (result.fatal) {
|
|
@@ -126,8 +177,8 @@ async function transformBabel(id, code, options) {
|
|
|
126
177
|
const babelOptions = {
|
|
127
178
|
filename: id,
|
|
128
179
|
compact: false,
|
|
129
|
-
babelrc: false,
|
|
130
|
-
configFile: false,
|
|
180
|
+
babelrc: options.babelrc ?? false,
|
|
181
|
+
configFile: options.configFile ?? false,
|
|
131
182
|
sourceMaps: false,
|
|
132
183
|
minified: false,
|
|
133
184
|
...options,
|
|
@@ -146,7 +197,7 @@ async function transformBabel(id, code, options) {
|
|
|
146
197
|
plugins: [...(isTS ? [] : [[hermesParserPlugin, {
|
|
147
198
|
parseLangTypes: "flow",
|
|
148
199
|
reactRuntimeTarget: "19"
|
|
149
|
-
}]]), ...(options.plugins || []), ...(isTS ? [] : ["@babel/plugin-transform-flow-strip-types"])]
|
|
200
|
+
}], "babel-plugin-transform-flow-enums"]), ...(options.plugins || []), ...(isTS ? [] : ["@babel/plugin-transform-flow-strip-types"])]
|
|
150
201
|
};
|
|
151
202
|
return await new Promise((res, rej) => {
|
|
152
203
|
babelCore.transform(code, babelOptions, (err, result) => {
|
|
@@ -157,6 +208,15 @@ async function transformBabel(id, code, options) {
|
|
|
157
208
|
});
|
|
158
209
|
});
|
|
159
210
|
}
|
|
211
|
+
async function stripFlowTypes(id, code, sourceMaps = true) {
|
|
212
|
+
const result = await transformBabel(id, code, {
|
|
213
|
+
sourceMaps
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
code: result.code,
|
|
217
|
+
map: result.map
|
|
218
|
+
};
|
|
219
|
+
}
|
|
160
220
|
const getBasePlugins = ({
|
|
161
221
|
development
|
|
162
222
|
}) => [["@babel/plugin-transform-destructuring"], ["@babel/plugin-transform-react-jsx", {
|
|
@@ -85,6 +85,23 @@ var import_transformBabel = require("./transformBabel.cjs");
|
|
|
85
85
|
(0, import_vitest.expect)(result?.code).toContain("codegenNativeComponent('VirtualView')");
|
|
86
86
|
(0, import_vitest.expect)(result?.code).not.toContain("HostComponent");
|
|
87
87
|
});
|
|
88
|
+
(0, import_vitest.it)("preserves React Native Flow enums as runtime values", async () => {
|
|
89
|
+
const result = await (0, import_transformBabel.transformBabel)("/project/VirtualView.js", `
|
|
90
|
+
// @flow strict-local
|
|
91
|
+
export enum VirtualViewRenderState {
|
|
92
|
+
Unknown = 0,
|
|
93
|
+
Rendered = 1,
|
|
94
|
+
None = 2,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const rendered = VirtualViewRenderState.Rendered
|
|
98
|
+
`, {
|
|
99
|
+
plugins: []
|
|
100
|
+
});
|
|
101
|
+
(0, import_vitest.expect)(result?.code).toContain("const VirtualViewRenderState =");
|
|
102
|
+
(0, import_vitest.expect)(result?.code).toContain("Rendered: 1");
|
|
103
|
+
(0, import_vitest.expect)(result?.code).toContain("VirtualViewRenderState.Rendered");
|
|
104
|
+
});
|
|
88
105
|
(0, import_vitest.it)("rejects a required transform error instead of returning untransformed source", async () => {
|
|
89
106
|
const negativeControl = () => ({
|
|
90
107
|
visitor: {
|
|
@@ -123,6 +140,24 @@ var import_transformBabel = require("./transformBabel.cjs");
|
|
|
123
140
|
const result = await (0, import_transformBabel.transformOxcReactCompiler)("/project/Counter.tsx", componentCode, "18", false);
|
|
124
141
|
(0, import_vitest.expect)(result.code).toContain("_c(");
|
|
125
142
|
});
|
|
143
|
+
(0, import_vitest.it)("supports mutating useSharedValue in useEffect via Reanimated environment defaults", async () => {
|
|
144
|
+
const reanimatedCode = `
|
|
145
|
+
import { useEffect } from 'react'
|
|
146
|
+
import { useSharedValue } from 'react-native-reanimated'
|
|
147
|
+
|
|
148
|
+
export function ReanimatedComponent() {
|
|
149
|
+
const val = useSharedValue(0)
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
val.value = 1
|
|
152
|
+
}, [val])
|
|
153
|
+
return <div>{val.value}</div>
|
|
154
|
+
}
|
|
155
|
+
`;
|
|
156
|
+
const result = await (0, import_transformBabel.transformOxcReactCompiler)("/project/ReanimatedComponent.tsx", reanimatedCode, {
|
|
157
|
+
target: "19"
|
|
158
|
+
}, false);
|
|
159
|
+
(0, import_vitest.expect)(result.code).toContain("_c(");
|
|
160
|
+
});
|
|
126
161
|
});
|
|
127
162
|
(0, import_vitest.describe)("compiler plugin multi-stage source map composition", () => {
|
|
128
163
|
(0, import_vitest.it)("composes earlier compiler maps when Babel also runs", async () => {
|
|
@@ -357,4 +392,278 @@ export async function* generatorProbe() {
|
|
|
357
392
|
});
|
|
358
393
|
}
|
|
359
394
|
});
|
|
395
|
+
});
|
|
396
|
+
(0, import_vitest.describe)("findUserBabelConfig and user Babel config respect", () => {
|
|
397
|
+
(0, import_vitest.it)("finds user babel config and ignores generated configs", () => {
|
|
398
|
+
const projectRoot = import_node_fs.default.realpathSync(import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "vxrn-babel-conf-")));
|
|
399
|
+
try {
|
|
400
|
+
(0, import_vitest.expect)((0, import_transformBabel.findUserBabelConfig)(projectRoot)).toBeNull();
|
|
401
|
+
const generatedFile = import_node_path.default.join(projectRoot, "babel.config.js");
|
|
402
|
+
import_node_fs.default.writeFileSync(generatedFile, "// @one-generated\nmodule.exports = {}");
|
|
403
|
+
(0, import_vitest.expect)((0, import_transformBabel.findUserBabelConfig)(projectRoot)).toBeNull();
|
|
404
|
+
import_node_fs.default.writeFileSync(generatedFile, "module.exports = { plugins: [] }");
|
|
405
|
+
(0, import_vitest.expect)((0, import_transformBabel.findUserBabelConfig)(projectRoot)).toBe(generatedFile);
|
|
406
|
+
} finally {
|
|
407
|
+
import_node_fs.default.rmSync(projectRoot, {
|
|
408
|
+
recursive: true,
|
|
409
|
+
force: true
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
(0, import_vitest.it)("includes user configFile and babelrc in getBabelOptions for project files", () => {
|
|
414
|
+
const projectRoot = import_node_fs.default.realpathSync(import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "vxrn-babel-conf-")));
|
|
415
|
+
const userConfig = import_node_path.default.join(projectRoot, "babel.config.json");
|
|
416
|
+
import_node_fs.default.writeFileSync(userConfig, '{"plugins": []}');
|
|
417
|
+
try {
|
|
418
|
+
const projectFileOptions = (0, import_transformBabel.getBabelOptions)({
|
|
419
|
+
id: import_node_path.default.join(projectRoot, "src", "index.tsx"),
|
|
420
|
+
code: `export const hello = () => 123`,
|
|
421
|
+
projectRoot,
|
|
422
|
+
development: true,
|
|
423
|
+
environment: "client",
|
|
424
|
+
reactForRNVersion: "19"
|
|
425
|
+
});
|
|
426
|
+
(0, import_vitest.expect)(projectFileOptions?.configFile).toBe(userConfig);
|
|
427
|
+
(0, import_vitest.expect)(projectFileOptions?.babelrc).toBe(true);
|
|
428
|
+
const nodeModulesOptions = (0, import_transformBabel.getBabelOptions)({
|
|
429
|
+
id: import_node_path.default.join(projectRoot, "node_modules", "foo", "index.js"),
|
|
430
|
+
code: `export const foo = 1`,
|
|
431
|
+
projectRoot,
|
|
432
|
+
development: true,
|
|
433
|
+
environment: "client",
|
|
434
|
+
reactForRNVersion: "19"
|
|
435
|
+
});
|
|
436
|
+
(0, import_vitest.expect)(nodeModulesOptions).toBeNull();
|
|
437
|
+
} finally {
|
|
438
|
+
import_node_fs.default.rmSync(projectRoot, {
|
|
439
|
+
recursive: true,
|
|
440
|
+
force: true
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
(0, import_vitest.it)("runs user babel config transforms via transformBabel", async () => {
|
|
445
|
+
const projectRoot = import_node_fs.default.realpathSync(import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "vxrn-babel-conf-")));
|
|
446
|
+
const userConfig = import_node_path.default.join(projectRoot, "babel.config.json");
|
|
447
|
+
import_node_fs.default.writeFileSync(userConfig, JSON.stringify({
|
|
448
|
+
comments: false
|
|
449
|
+
}));
|
|
450
|
+
try {
|
|
451
|
+
const code = "/* remove me */ export const x = 1";
|
|
452
|
+
const res = await (0, import_transformBabel.transformBabel)(import_node_path.default.join(projectRoot, "src", "index.ts"), code, {
|
|
453
|
+
configFile: userConfig,
|
|
454
|
+
babelrc: true
|
|
455
|
+
});
|
|
456
|
+
(0, import_vitest.expect)(res.code).not.toContain("remove me");
|
|
457
|
+
(0, import_vitest.expect)(res.code).toContain("export const x = 1");
|
|
458
|
+
} finally {
|
|
459
|
+
import_node_fs.default.rmSync(projectRoot, {
|
|
460
|
+
recursive: true,
|
|
461
|
+
force: true
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
(0, import_vitest.describe)("explicit swc/oxc per-file choice with a user babel config", () => {
|
|
467
|
+
(0, import_vitest.it)("returns null for swc/oxc string and object forms", () => {
|
|
468
|
+
const projectRoot = import_node_fs.default.realpathSync(import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "vxrn-babel-conf-")));
|
|
469
|
+
const userConfig = import_node_path.default.join(projectRoot, "babel.config.js");
|
|
470
|
+
import_node_fs.default.writeFileSync(userConfig, "module.exports = { plugins: [] }");
|
|
471
|
+
try {
|
|
472
|
+
const base = {
|
|
473
|
+
id: import_node_path.default.join(projectRoot, "src", "index.tsx"),
|
|
474
|
+
code: `export const x = 1`,
|
|
475
|
+
projectRoot,
|
|
476
|
+
development: true,
|
|
477
|
+
environment: "client",
|
|
478
|
+
reactForRNVersion: "19"
|
|
479
|
+
};
|
|
480
|
+
(0, import_vitest.expect)((0, import_transformBabel.getBabelOptions)({
|
|
481
|
+
...base,
|
|
482
|
+
userSetting: "swc"
|
|
483
|
+
})).toBeNull();
|
|
484
|
+
(0, import_vitest.expect)((0, import_transformBabel.getBabelOptions)({
|
|
485
|
+
...base,
|
|
486
|
+
userSetting: "oxc"
|
|
487
|
+
})).toBeNull();
|
|
488
|
+
(0, import_vitest.expect)((0, import_transformBabel.getBabelOptions)({
|
|
489
|
+
...base,
|
|
490
|
+
userSetting: {
|
|
491
|
+
transform: "swc"
|
|
492
|
+
}
|
|
493
|
+
})).toBeNull();
|
|
494
|
+
(0, import_vitest.expect)((0, import_transformBabel.getBabelOptions)({
|
|
495
|
+
...base,
|
|
496
|
+
userSetting: {
|
|
497
|
+
transform: "oxc"
|
|
498
|
+
}
|
|
499
|
+
})).toBeNull();
|
|
500
|
+
(0, import_vitest.expect)((0, import_transformBabel.getBabelOptions)({
|
|
501
|
+
...base,
|
|
502
|
+
userSetting: "babel"
|
|
503
|
+
})?.configFile).toBe(userConfig);
|
|
504
|
+
(0, import_vitest.expect)((0, import_transformBabel.getBabelOptions)({
|
|
505
|
+
...base,
|
|
506
|
+
userSetting: {
|
|
507
|
+
transform: "babel"
|
|
508
|
+
}
|
|
509
|
+
})?.configFile).toBe(userConfig);
|
|
510
|
+
(0, import_vitest.expect)((0, import_transformBabel.getBabelOptions)(base)?.configFile).toBe(userConfig);
|
|
511
|
+
} finally {
|
|
512
|
+
import_node_fs.default.rmSync(projectRoot, {
|
|
513
|
+
recursive: true,
|
|
514
|
+
force: true
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
(0, import_vitest.it)("skips the transform end-to-end for object-form swc", async () => {
|
|
519
|
+
const {
|
|
520
|
+
createVXRNCompilerPlugin
|
|
521
|
+
} = await import("./index");
|
|
522
|
+
const projectRoot = import_node_fs.default.realpathSync(import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "vxrn-babel-conf-")));
|
|
523
|
+
const srcDir = import_node_path.default.join(projectRoot, "src");
|
|
524
|
+
import_node_fs.default.mkdirSync(srcDir, {
|
|
525
|
+
recursive: true
|
|
526
|
+
});
|
|
527
|
+
const file = import_node_path.default.join(srcDir, "index.ts");
|
|
528
|
+
const code = `export const x = 1`;
|
|
529
|
+
import_node_fs.default.writeFileSync(file, code);
|
|
530
|
+
import_node_fs.default.writeFileSync(import_node_path.default.join(projectRoot, "babel.config.js"), "module.exports = { plugins: [] }");
|
|
531
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
532
|
+
enableCompiler: false,
|
|
533
|
+
enableReanimated: false
|
|
534
|
+
});
|
|
535
|
+
try {
|
|
536
|
+
const plugins = await createVXRNCompilerPlugin({
|
|
537
|
+
transform: () => ({
|
|
538
|
+
transform: "swc"
|
|
539
|
+
})
|
|
540
|
+
});
|
|
541
|
+
const plugin = plugins.find(p => p.name === "one:compiler");
|
|
542
|
+
await plugin.configResolved({
|
|
543
|
+
root: projectRoot,
|
|
544
|
+
build: {}
|
|
545
|
+
});
|
|
546
|
+
const hook = plugin.transform.handler || plugin.transform;
|
|
547
|
+
const result = await hook.call({
|
|
548
|
+
environment: {
|
|
549
|
+
name: "client"
|
|
550
|
+
}
|
|
551
|
+
}, code, file);
|
|
552
|
+
(0, import_vitest.expect)(result == null).toBe(true);
|
|
553
|
+
} finally {
|
|
554
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
555
|
+
enableCompiler: false,
|
|
556
|
+
enableReanimated: false
|
|
557
|
+
});
|
|
558
|
+
import_node_fs.default.rmSync(projectRoot, {
|
|
559
|
+
recursive: true,
|
|
560
|
+
force: true
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
(0, import_vitest.describe)("user babel config end-to-end through the compiler plugin", () => {
|
|
566
|
+
(0, import_vitest.it)("runs the user config when default plugins are empty", async () => {
|
|
567
|
+
const {
|
|
568
|
+
createVXRNCompilerPlugin
|
|
569
|
+
} = await import("./index");
|
|
570
|
+
const projectRoot = import_node_fs.default.realpathSync(import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "vxrn-babel-e2e-")));
|
|
571
|
+
const srcDir = import_node_path.default.join(projectRoot, "src");
|
|
572
|
+
import_node_fs.default.mkdirSync(srcDir, {
|
|
573
|
+
recursive: true
|
|
574
|
+
});
|
|
575
|
+
const file = import_node_path.default.join(srcDir, "index.ts");
|
|
576
|
+
const marker = "babel-e2e-probe";
|
|
577
|
+
const code = `/* ${marker} */ export const x = 1`;
|
|
578
|
+
import_node_fs.default.writeFileSync(file, code);
|
|
579
|
+
import_node_fs.default.writeFileSync(import_node_path.default.join(projectRoot, "babel.config.json"), JSON.stringify({
|
|
580
|
+
comments: false
|
|
581
|
+
}));
|
|
582
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
583
|
+
enableCompiler: false,
|
|
584
|
+
enableReanimated: false
|
|
585
|
+
});
|
|
586
|
+
try {
|
|
587
|
+
const plugins = await createVXRNCompilerPlugin();
|
|
588
|
+
const plugin = plugins.find(p => p.name === "one:compiler");
|
|
589
|
+
await plugin.configResolved({
|
|
590
|
+
root: projectRoot,
|
|
591
|
+
build: {}
|
|
592
|
+
});
|
|
593
|
+
const hook = plugin.transform.handler || plugin.transform;
|
|
594
|
+
const result = await hook.call({
|
|
595
|
+
environment: {
|
|
596
|
+
name: "client"
|
|
597
|
+
}
|
|
598
|
+
}, code, file);
|
|
599
|
+
(0, import_vitest.expect)(result).toBeDefined();
|
|
600
|
+
(0, import_vitest.expect)(result.code).toContain("export const x = 1");
|
|
601
|
+
(0, import_vitest.expect)(result.code).not.toContain(marker);
|
|
602
|
+
} finally {
|
|
603
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
604
|
+
enableCompiler: false,
|
|
605
|
+
enableReanimated: false
|
|
606
|
+
});
|
|
607
|
+
import_node_fs.default.rmSync(projectRoot, {
|
|
608
|
+
recursive: true,
|
|
609
|
+
force: true
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
(0, import_vitest.it)("invalidates the cache when the user babel config is added or edited", async () => {
|
|
614
|
+
const {
|
|
615
|
+
createVXRNCompilerPlugin
|
|
616
|
+
} = await import("./index");
|
|
617
|
+
const projectRoot = import_node_fs.default.realpathSync(import_node_fs.default.mkdtempSync(import_node_path.default.join(import_node_os.default.tmpdir(), "vxrn-babel-cache-")));
|
|
618
|
+
const srcDir = import_node_path.default.join(projectRoot, "src");
|
|
619
|
+
import_node_fs.default.mkdirSync(srcDir, {
|
|
620
|
+
recursive: true
|
|
621
|
+
});
|
|
622
|
+
const file = import_node_path.default.join(srcDir, "index.ts");
|
|
623
|
+
const marker = "babel-cache-probe";
|
|
624
|
+
const code = `/* ${marker} */ export const x = 1`;
|
|
625
|
+
import_node_fs.default.writeFileSync(file, code);
|
|
626
|
+
const userConfig = import_node_path.default.join(projectRoot, "babel.config.json");
|
|
627
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
628
|
+
enableCompiler: false,
|
|
629
|
+
enableReanimated: false
|
|
630
|
+
});
|
|
631
|
+
try {
|
|
632
|
+
const plugins = await createVXRNCompilerPlugin({
|
|
633
|
+
transform: () => "babel"
|
|
634
|
+
});
|
|
635
|
+
const plugin = plugins.find(p => p.name === "one:compiler");
|
|
636
|
+
await plugin.configResolved({
|
|
637
|
+
root: projectRoot,
|
|
638
|
+
build: {}
|
|
639
|
+
});
|
|
640
|
+
const hook = plugin.transform.handler || plugin.transform;
|
|
641
|
+
const context = {
|
|
642
|
+
environment: {
|
|
643
|
+
name: "client"
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
const res1 = await hook.call(context, code, file);
|
|
647
|
+
(0, import_vitest.expect)(res1.code).toContain(marker);
|
|
648
|
+
import_node_fs.default.writeFileSync(userConfig, JSON.stringify({
|
|
649
|
+
comments: false
|
|
650
|
+
}));
|
|
651
|
+
const res2 = await hook.call(context, code, file);
|
|
652
|
+
(0, import_vitest.expect)(res2.code).not.toContain(marker);
|
|
653
|
+
import_node_fs.default.writeFileSync(userConfig, JSON.stringify({
|
|
654
|
+
comments: true
|
|
655
|
+
}));
|
|
656
|
+
const res3 = await hook.call(context, code, file);
|
|
657
|
+
(0, import_vitest.expect)(res3.code).toContain(marker);
|
|
658
|
+
} finally {
|
|
659
|
+
(0, import_configure.configureVXRNCompilerPlugin)({
|
|
660
|
+
enableCompiler: false,
|
|
661
|
+
enableReanimated: false
|
|
662
|
+
});
|
|
663
|
+
import_node_fs.default.rmSync(projectRoot, {
|
|
664
|
+
recursive: true,
|
|
665
|
+
force: true
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
});
|
|
360
669
|
});
|
|
@@ -24,6 +24,7 @@ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
|
24
24
|
}) : target, mod));
|
|
25
25
|
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
26
26
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
27
|
+
var import_node_module = require("node:module");
|
|
27
28
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
28
29
|
var import_vitest = require("vitest");
|
|
29
30
|
var import_configure = require("./configure.cjs");
|
|
@@ -322,7 +323,8 @@ var ${innerVar[1]} = {`);
|
|
|
322
323
|
(0, import_vitest.expect)(typeof scaleFn).toBe("function");
|
|
323
324
|
(0, import_vitest.expect)(scaleFn.__workletHash).toBeDefined();
|
|
324
325
|
(0, import_vitest.expect)(typeof scaleFn.__workletHash).toBe("number");
|
|
325
|
-
(0,
|
|
326
|
+
const installedWorklets = (0, import_node_module.createRequire)(import_node_path.default.resolve(process.cwd(), "package.json"))("react-native-worklets/package.json").version;
|
|
327
|
+
(0, import_vitest.expect)(scaleFn.__pluginVersion).toBe(installedWorklets);
|
|
326
328
|
(0, import_vitest.expect)(scaleFn.__closure).toEqual({
|
|
327
329
|
multiplier: 5
|
|
328
330
|
});
|
package/dist/esm/cache.mjs
CHANGED
|
@@ -17,30 +17,44 @@ function getCacheDir() {
|
|
|
17
17
|
}
|
|
18
18
|
return cacheDir;
|
|
19
19
|
}
|
|
20
|
-
function getConfigFingerprint() {
|
|
20
|
+
function getConfigFingerprint(userBabelConfigPath) {
|
|
21
21
|
return createHash("sha1").update(JSON.stringify({
|
|
22
22
|
compiler: configuration.enableCompiler,
|
|
23
23
|
reanimated: configuration.enableReanimated,
|
|
24
24
|
nativeWorklets: isNativeWorkletsEnabled(),
|
|
25
25
|
nativewind: configuration.enableNativewind,
|
|
26
26
|
nativeCSS: configuration.enableNativeCSS,
|
|
27
|
+
// transform output depends on the user babel config when one applies,
|
|
28
|
+
// so its identity joins the fingerprint. adding, removing, or editing
|
|
29
|
+
// babel.config.* must miss entries written without that change.
|
|
30
|
+
babelConfig: getBabelConfigIdentity(userBabelConfigPath),
|
|
27
31
|
// bump when the transform engine changes, so entries written by a
|
|
28
32
|
// previous engine aren't served for the same source
|
|
29
33
|
engine: "oxc-worklets-hermes-async"
|
|
30
34
|
})).digest("hex").slice(0, 8);
|
|
31
35
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
36
|
+
function getBabelConfigIdentity(configPath) {
|
|
37
|
+
if (!configPath) return null;
|
|
38
|
+
try {
|
|
39
|
+
const mtime = statSync(configPath).mtimeMs;
|
|
40
|
+
const hash = createHash("sha1").update(readFileSync(configPath)).digest("hex").slice(0, 16);
|
|
41
|
+
return `${configPath}:${mtime}:${hash}`;
|
|
42
|
+
} catch {
|
|
43
|
+
return configPath;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function getCacheKey(filePath, environment, userBabelConfigPath) {
|
|
47
|
+
const hash = createHash("sha1").update(`${environment}:${filePath}:${getConfigFingerprint(userBabelConfigPath)}`).digest("hex");
|
|
34
48
|
return hash;
|
|
35
49
|
}
|
|
36
50
|
function getContentHash(code) {
|
|
37
51
|
return createHash("sha1").update(code).digest("hex").slice(0, 16);
|
|
38
52
|
}
|
|
39
|
-
function getCachedTransform(filePath, code, environment) {
|
|
53
|
+
function getCachedTransform(filePath, code, environment, userBabelConfigPath) {
|
|
40
54
|
try {
|
|
41
55
|
const cleanPath = filePath.startsWith("\0") ? filePath.slice(1) : filePath;
|
|
42
56
|
const cacheDir = getCacheDir();
|
|
43
|
-
const cacheKey = getCacheKey(cleanPath, environment);
|
|
57
|
+
const cacheKey = getCacheKey(cleanPath, environment, userBabelConfigPath);
|
|
44
58
|
const cachePath = join(cacheDir, `${cacheKey}.json`);
|
|
45
59
|
if (!existsSync(cachePath)) {
|
|
46
60
|
stats.misses++;
|
|
@@ -67,11 +81,11 @@ function getCachedTransform(filePath, code, environment) {
|
|
|
67
81
|
return null;
|
|
68
82
|
}
|
|
69
83
|
}
|
|
70
|
-
function setCachedTransform(filePath, code, result, environment) {
|
|
84
|
+
function setCachedTransform(filePath, code, result, environment, userBabelConfigPath) {
|
|
71
85
|
try {
|
|
72
86
|
const cleanPath = filePath.startsWith("\0") ? filePath.slice(1) : filePath;
|
|
73
87
|
const cacheDir = getCacheDir();
|
|
74
|
-
const cacheKey = getCacheKey(cleanPath, environment);
|
|
88
|
+
const cacheKey = getCacheKey(cleanPath, environment, userBabelConfigPath);
|
|
75
89
|
const cachePath = join(cacheDir, `${cacheKey}.json`);
|
|
76
90
|
const mtime = statSync(cleanPath).mtimeMs;
|
|
77
91
|
const hash = getContentHash(code);
|