babel-preset-expo 12.0.0-preview.1 → 12.0.0-preview.3
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.
|
@@ -263,14 +263,94 @@ function reactServerActionsPlugin(api) {
|
|
|
263
263
|
if (!state.file.metadata.isModuleMarkedWithUseServerDirective) {
|
|
264
264
|
return;
|
|
265
265
|
}
|
|
266
|
-
//
|
|
267
|
-
|
|
266
|
+
// Convert `export default function foo() {}` to `function foo() {}; export { foo as default }`
|
|
267
|
+
if (path.node.declaration) {
|
|
268
|
+
if (t.isFunctionDeclaration(path.node.declaration)) {
|
|
269
|
+
let { id } = path.node.declaration;
|
|
270
|
+
if (id == null) {
|
|
271
|
+
const moduleScope = path.scope.getProgramParent();
|
|
272
|
+
const extractedIdentifier = moduleScope.generateUidIdentifier('$$INLINE_ACTION');
|
|
273
|
+
id = extractedIdentifier;
|
|
274
|
+
// Transform `async function () {}` to `async function $$INLINE_ACTION() {}`
|
|
275
|
+
path.node.declaration.id = extractedIdentifier;
|
|
276
|
+
}
|
|
277
|
+
const exportedSpecifier = t.exportSpecifier(id, t.identifier('default'));
|
|
278
|
+
path.replaceWith(path.node.declaration);
|
|
279
|
+
path.insertAfter(t.exportNamedDeclaration(null, [exportedSpecifier]));
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
// Convert anonymous function expressions to named function expressions and export them as default.
|
|
283
|
+
// export default foo = async () => {}
|
|
284
|
+
// vvv
|
|
285
|
+
// const foo = async () => {}
|
|
286
|
+
// (() => _registerServerReference(foo, "file:///unknown", "default"))();
|
|
287
|
+
// export { foo as default };
|
|
288
|
+
if (t.isAssignmentExpression(path.node.declaration) &&
|
|
289
|
+
t.isArrowFunctionExpression(path.node.declaration.right)) {
|
|
290
|
+
if (!t.isIdentifier(path.node.declaration.left)) {
|
|
291
|
+
throw path.buildCodeFrameError(`Expected an assignment to an identifier but found ${path.node.declaration.left.type}.`);
|
|
292
|
+
}
|
|
293
|
+
const { left, right } = path.node.declaration;
|
|
294
|
+
const id = left;
|
|
295
|
+
const exportedSpecifier = t.exportSpecifier(id, t.identifier('default'));
|
|
296
|
+
// Replace `export default foo = async () => {}` with `const foo = async () => {}`
|
|
297
|
+
path.replaceWith(t.variableDeclaration('const', [t.variableDeclarator(id, right)]));
|
|
298
|
+
// Insert `(() => _registerServerReference(foo, "file:///unknown", "default"))();`
|
|
299
|
+
path.insertAfter(t.exportNamedDeclaration(null, [exportedSpecifier]));
|
|
300
|
+
}
|
|
301
|
+
else if (t.isArrowFunctionExpression(path.node.declaration) &&
|
|
302
|
+
path.node.declaration) {
|
|
303
|
+
// export default async () => {}
|
|
304
|
+
// Give the function a name
|
|
305
|
+
// const $$INLINE_ACTION = async () => {}
|
|
306
|
+
const moduleScope = path.scope.getProgramParent();
|
|
307
|
+
const extractedIdentifier = moduleScope.generateUidIdentifier('$$INLINE_ACTION');
|
|
308
|
+
// @ts-expect-error: Transform `export default async () => {}` to `const $$INLINE_ACTION = async () => {}`
|
|
309
|
+
path.node.declaration = t.variableDeclaration('const', [
|
|
310
|
+
t.variableDeclarator(extractedIdentifier, path.node.declaration),
|
|
311
|
+
]);
|
|
312
|
+
// Strip the `export default`
|
|
313
|
+
path.replaceWith(path.node.declaration);
|
|
314
|
+
// export { $$INLINE_ACTION as default }
|
|
315
|
+
const exportedSpecifier = t.exportSpecifier(extractedIdentifier, t.identifier('default'));
|
|
316
|
+
path.insertAfter(t.exportNamedDeclaration(null, [exportedSpecifier]));
|
|
317
|
+
}
|
|
318
|
+
else if (
|
|
319
|
+
// Match `export default foo;`
|
|
320
|
+
t.isIdentifier(path.node.declaration)) {
|
|
321
|
+
// Ensure the `path.node.declaration` is a function or a variable for a function.
|
|
322
|
+
const binding = path.scope.getBinding(path.node.declaration.name);
|
|
323
|
+
const isServerActionType = t.isFunctionDeclaration(binding?.path.node ?? path.node.declaration) ||
|
|
324
|
+
t.isArrowFunctionExpression(binding?.path.node ?? path.node.declaration) ||
|
|
325
|
+
// `const foo = async () => {}`
|
|
326
|
+
(t.isVariableDeclarator(binding?.path.node) &&
|
|
327
|
+
t.isArrowFunctionExpression(binding?.path.node.init));
|
|
328
|
+
if (isServerActionType) {
|
|
329
|
+
// Convert `export default foo;` to `export { foo as default };`
|
|
330
|
+
const exportedSpecifier = t.exportSpecifier(path.node.declaration, t.identifier('default'));
|
|
331
|
+
path.replaceWith(t.exportNamedDeclaration(null, [exportedSpecifier]));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
// Unclear when this happens.
|
|
336
|
+
throw path.buildCodeFrameError(`Cannot create server action. Expected a assignment expression but found ${path.node.declaration.type}.`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
// TODO: Unclear when this happens.
|
|
342
|
+
throw path.buildCodeFrameError(`Not implemented: 'export default' declarations in "use server" files. Try using 'export { name as default }' instead.`);
|
|
343
|
+
}
|
|
268
344
|
},
|
|
269
345
|
ExportNamedDeclaration(path, state) {
|
|
270
346
|
assertExpoMetadata(state.file.metadata);
|
|
271
347
|
if (!state.file.metadata.isModuleMarkedWithUseServerDirective) {
|
|
272
348
|
return;
|
|
273
349
|
}
|
|
350
|
+
// This can happen with `export {};` and TypeScript types.
|
|
351
|
+
if (!path.node.declaration && !path.node.specifiers.length) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
274
354
|
const registerServerReferenceId = addReactImport();
|
|
275
355
|
const actionModuleId = getActionModuleId();
|
|
276
356
|
const createRegisterCall = (identifier, exported = identifier) => {
|
|
@@ -287,11 +367,12 @@ function reactServerActionsPlugin(api) {
|
|
|
287
367
|
for (const specifier of path.node.specifiers) {
|
|
288
368
|
// `export * as ns from './foo';`
|
|
289
369
|
if (t.isExportNamespaceSpecifier(specifier)) {
|
|
290
|
-
throw path.buildCodeFrameError('
|
|
370
|
+
throw path.buildCodeFrameError('Namespace exports for server actions are not supported. Re-export named actions instead: export { foo } from "./bar".');
|
|
291
371
|
}
|
|
292
372
|
else if (t.isExportDefaultSpecifier(specifier)) {
|
|
373
|
+
// NOTE: This is handled by ExportDefaultDeclaration
|
|
293
374
|
// `export default foo;`
|
|
294
|
-
throw path.buildCodeFrameError('
|
|
375
|
+
throw path.buildCodeFrameError('Internal error while extracting server actions. Expected `export default variable;` to be extracted. (ExportDefaultSpecifier in ExportNamedDeclaration)');
|
|
295
376
|
}
|
|
296
377
|
else if (t.isExportSpecifier(specifier)) {
|
|
297
378
|
// `export { foo };`
|
|
@@ -311,9 +392,6 @@ function reactServerActionsPlugin(api) {
|
|
|
311
392
|
}
|
|
312
393
|
state.file.metadata.extractedActions.push({ localName, exportedName });
|
|
313
394
|
}
|
|
314
|
-
else {
|
|
315
|
-
throw path.buildCodeFrameError('Not implemented: whatever this is');
|
|
316
|
-
}
|
|
317
395
|
}
|
|
318
396
|
return;
|
|
319
397
|
}
|
|
@@ -339,6 +417,14 @@ function reactServerActionsPlugin(api) {
|
|
|
339
417
|
}
|
|
340
418
|
return [innerPath.get('id').node];
|
|
341
419
|
}
|
|
420
|
+
else if (
|
|
421
|
+
// TypeScript type exports
|
|
422
|
+
innerPath.isTypeAlias() ||
|
|
423
|
+
innerPath.isTSDeclareFunction() ||
|
|
424
|
+
innerPath.isTSInterfaceDeclaration() ||
|
|
425
|
+
innerPath.isTSTypeAliasDeclaration()) {
|
|
426
|
+
return [];
|
|
427
|
+
}
|
|
342
428
|
else {
|
|
343
429
|
throw innerPath.buildCodeFrameError(`Unimplemented server action export`);
|
|
344
430
|
}
|
|
@@ -17,6 +17,7 @@ function expoUseDomDirectivePlugin(api) {
|
|
|
17
17
|
// TODO: Is exporting
|
|
18
18
|
const isProduction = api.caller(common_1.getIsProd);
|
|
19
19
|
const platform = api.caller((caller) => caller?.platform);
|
|
20
|
+
const projectRoot = api.caller(common_1.getPossibleProjectRoot);
|
|
20
21
|
return {
|
|
21
22
|
name: 'expo-use-dom-directive',
|
|
22
23
|
visitor: {
|
|
@@ -59,6 +60,23 @@ function expoUseDomDirectivePlugin(api) {
|
|
|
59
60
|
if (!hasDefaultExport) {
|
|
60
61
|
throw path.buildCodeFrameError('The "use dom" directive requires a default export to be present in the file.');
|
|
61
62
|
}
|
|
63
|
+
// Assert that _layout routes cannot be used in DOM components.
|
|
64
|
+
const fileBasename = (0, path_1.basename)(filePath);
|
|
65
|
+
if (projectRoot &&
|
|
66
|
+
// Detecting if the file is in the router root would be extensive as it would cause a more complex
|
|
67
|
+
// cache key for each file. Instead, let's just check if the file is in the project root and is not a node_module,
|
|
68
|
+
// then we can assert that users should not use `_layout` or `+api` with "use dom".
|
|
69
|
+
filePath.includes(projectRoot) &&
|
|
70
|
+
!filePath.match(/node_modules/)) {
|
|
71
|
+
if (fileBasename.match(/^_layout\.[jt]sx?$/)) {
|
|
72
|
+
throw path.buildCodeFrameError('Layout routes cannot be marked as DOM components because they cannot render native views.');
|
|
73
|
+
}
|
|
74
|
+
else if (
|
|
75
|
+
// No API routes
|
|
76
|
+
fileBasename.match(/\+api\.[jt]sx?$/)) {
|
|
77
|
+
throw path.buildCodeFrameError('API routes cannot be marked as DOM components.');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
62
80
|
const outputKey = url_1.default.pathToFileURL(filePath).href;
|
|
63
81
|
const proxyModule = [
|
|
64
82
|
`import React from 'react';`,
|
|
@@ -81,7 +99,7 @@ function expoUseDomDirectivePlugin(api) {
|
|
|
81
99
|
else {
|
|
82
100
|
proxyModule.push(
|
|
83
101
|
// Add the basename to improve the Safari debug preview option.
|
|
84
|
-
`const source = { uri: new URL("/_expo/@dom/${
|
|
102
|
+
`const source = { uri: new URL("/_expo/@dom/${fileBasename}?file=" + ${JSON.stringify(outputKey)}, require("react-native/Libraries/Core/Devtools/getDevServer")().url).toString() };`);
|
|
85
103
|
}
|
|
86
104
|
proxyModule.push(`
|
|
87
105
|
export default React.forwardRef((props, ref) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-preset-expo",
|
|
3
|
-
"version": "12.0.0-preview.
|
|
3
|
+
"version": "12.0.0-preview.3",
|
|
4
4
|
"description": "The Babel preset for Expo projects",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"files": [
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@babel/plugin-transform-parameters": "^7.22.15",
|
|
48
48
|
"@babel/preset-react": "^7.22.15",
|
|
49
49
|
"@babel/preset-typescript": "^7.23.0",
|
|
50
|
-
"@react-native/babel-preset": "0.76.
|
|
50
|
+
"@react-native/babel-preset": "0.76.1",
|
|
51
51
|
"babel-plugin-react-native-web": "~0.19.13",
|
|
52
52
|
"react-refresh": "^0.14.2"
|
|
53
53
|
},
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"jest": "^29.2.1",
|
|
71
71
|
"react-compiler-runtime": "^19.0.0-beta-8a03594-20241020"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "d5b7ec4949eb461634b2f02a1a0ff1df2a0e2a21"
|
|
74
74
|
}
|