diff --git a/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack-bundled.js b/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack-bundled.js deleted file mode 100644 index f4226a93d86bc..0000000000000 --- a/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack-bundled.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-client/src/ReactFlightClientStreamConfigNode'; -export * from 'react-client/src/ReactClientConsoleConfigServer'; -export * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack'; -export * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer'; -export * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigTargetTurbopackServer'; -export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM'; -export const usedWithSSR = true; diff --git a/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack.js b/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack.js index b6f2b77dd3686..f4226a93d86bc 100644 --- a/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack.js +++ b/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-turbopack.js @@ -9,7 +9,8 @@ export * from 'react-client/src/ReactFlightClientStreamConfigNode'; export * from 'react-client/src/ReactClientConsoleConfigServer'; -export * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerNode'; +export * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack'; +export * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer'; export * from 'react-server-dom-turbopack/src/client/ReactFlightClientConfigTargetTurbopackServer'; export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM'; export const usedWithSSR = true; diff --git a/packages/react-server-dom-turbopack/client.node.unbundled.js b/packages/react-server-dom-turbopack/client.node.unbundled.js deleted file mode 100644 index c2e364f42f133..0000000000000 --- a/packages/react-server-dom-turbopack/client.node.unbundled.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from './src/client/ReactFlightDOMClientNode'; diff --git a/packages/react-server-dom-turbopack/esm/package.json b/packages/react-server-dom-turbopack/esm/package.json deleted file mode 100644 index 3dbc1ca591c05..0000000000000 --- a/packages/react-server-dom-turbopack/esm/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/packages/react-server-dom-turbopack/esm/react-server-dom-turbopack-node-loader.production.js b/packages/react-server-dom-turbopack/esm/react-server-dom-turbopack-node-loader.production.js deleted file mode 100644 index ef6486656cafe..0000000000000 --- a/packages/react-server-dom-turbopack/esm/react-server-dom-turbopack-node-loader.production.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from '../src/ReactFlightTurbopackNodeLoader.js'; diff --git a/packages/react-server-dom-turbopack/node-register.js b/packages/react-server-dom-turbopack/node-register.js deleted file mode 100644 index 0d399f3842731..0000000000000 --- a/packages/react-server-dom-turbopack/node-register.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -module.exports = require('./src/ReactFlightTurbopackNodeRegister'); diff --git a/packages/react-server-dom-turbopack/npm/client.node.unbundled.js b/packages/react-server-dom-turbopack/npm/client.node.unbundled.js deleted file mode 100644 index 04eb5b1972bed..0000000000000 --- a/packages/react-server-dom-turbopack/npm/client.node.unbundled.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -if (process.env.NODE_ENV === 'production') { - module.exports = require('./cjs/react-server-dom-turbopack-client.node.unbundled.production.js'); -} else { - module.exports = require('./cjs/react-server-dom-turbopack-client.node.unbundled.development.js'); -} diff --git a/packages/react-server-dom-turbopack/npm/esm/package.json b/packages/react-server-dom-turbopack/npm/esm/package.json deleted file mode 100644 index 3dbc1ca591c05..0000000000000 --- a/packages/react-server-dom-turbopack/npm/esm/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/packages/react-server-dom-turbopack/npm/node-register.js b/packages/react-server-dom-turbopack/npm/node-register.js deleted file mode 100644 index 7506743f033fa..0000000000000 --- a/packages/react-server-dom-turbopack/npm/node-register.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -module.exports = require('./cjs/react-server-dom-turbopack-node-register.js'); diff --git a/packages/react-server-dom-turbopack/npm/server.node.unbundled.js b/packages/react-server-dom-turbopack/npm/server.node.unbundled.js deleted file mode 100644 index 1e8648ccef133..0000000000000 --- a/packages/react-server-dom-turbopack/npm/server.node.unbundled.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -var s; -if (process.env.NODE_ENV === 'production') { - s = require('./cjs/react-server-dom-turbopack-server.node.unbundled.production.js'); -} else { - s = require('./cjs/react-server-dom-turbopack-server.node.unbundled.development.js'); -} - -exports.renderToPipeableStream = s.renderToPipeableStream; -exports.decodeReplyFromBusboy = s.decodeReplyFromBusboy; -exports.decodeReply = s.decodeReply; -exports.decodeAction = s.decodeAction; -exports.decodeFormState = s.decodeFormState; -exports.registerServerReference = s.registerServerReference; -exports.registerClientReference = s.registerClientReference; -exports.createClientModuleProxy = s.createClientModuleProxy; -exports.createTemporaryReferenceSet = s.createTemporaryReferenceSet; diff --git a/packages/react-server-dom-turbopack/npm/static.node.unbundled.js b/packages/react-server-dom-turbopack/npm/static.node.unbundled.js deleted file mode 100644 index e77863bf36a60..0000000000000 --- a/packages/react-server-dom-turbopack/npm/static.node.unbundled.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -var s; -if (process.env.NODE_ENV === 'production') { - s = require('./cjs/react-server-dom-turbopack-server.node.unbundled.production.js'); -} else { - s = require('./cjs/react-server-dom-turbopack-server.node.unbundled.development.js'); -} - -if (s.prerenderToNodeStream) { - exports.prerenderToNodeStream = s.prerenderToNodeStream; -} diff --git a/packages/react-server-dom-turbopack/package.json b/packages/react-server-dom-turbopack/package.json index 93cd7d37a04ae..3b638137612da 100644 --- a/packages/react-server-dom-turbopack/package.json +++ b/packages/react-server-dom-turbopack/package.json @@ -16,20 +16,15 @@ "client.browser.js", "client.edge.js", "client.node.js", - "client.node.unbundled.js", "server.js", "server.browser.js", "server.edge.js", "server.node.js", - "server.node.unbundled.js", "static.js", "static.browser.js", "static.edge.js", "static.node.js", - "static.node.unbundled.js", - "node-register.js", - "cjs/", - "esm/" + "cjs/" ], "exports": { ".": "./index.js", @@ -37,11 +32,7 @@ "workerd": "./client.edge.js", "deno": "./client.edge.js", "worker": "./client.edge.js", - "node": { - "turbopack": "./client.node.js", - "webpack": "./client.node.js", - "default": "./client.node.unbundled.js" - }, + "node": "./client.node.js", "edge-light": "./client.edge.js", "browser": "./client.browser.js", "default": "./client.browser.js" @@ -49,16 +40,11 @@ "./client.browser": "./client.browser.js", "./client.edge": "./client.edge.js", "./client.node": "./client.node.js", - "./client.node.unbundled": "./client.node.unbundled.js", "./server": { "react-server": { "workerd": "./server.edge.js", "deno": "./server.browser.js", - "node": { - "turbopack": "./server.node.js", - "webpack": "./server.node.js", - "default": "./server.node.unbundled.js" - }, + "node": "./server.node.js", "edge-light": "./server.edge.js", "browser": "./server.browser.js" }, @@ -67,16 +53,11 @@ "./server.browser": "./server.browser.js", "./server.edge": "./server.edge.js", "./server.node": "./server.node.js", - "./server.node.unbundled": "./server.node.unbundled.js", "./static": { "react-server": { "workerd": "./static.edge.js", "deno": "./static.browser.js", - "node": { - "turbopack": "./static.node.js", - "webpack": "./static.node.js", - "default": "./static.node.unbundled.js" - }, + "node": "./static.node.js", "edge-light": "./static.edge.js", "browser": "./static.browser.js" }, @@ -85,9 +66,6 @@ "./static.browser": "./static.browser.js", "./static.edge": "./static.edge.js", "./static.node": "./static.node.js", - "./static.node.unbundled": "./static.node.unbundled.js", - "./node-loader": "./esm/react-server-dom-turbopack-node-loader.production.js", - "./node-register": "./node-register.js", "./src/*": "./src/*.js", "./package.json": "./package.json" }, diff --git a/packages/react-server-dom-turbopack/server.node.unbundled.js b/packages/react-server-dom-turbopack/server.node.unbundled.js deleted file mode 100644 index 9b8455bf66877..0000000000000 --- a/packages/react-server-dom-turbopack/server.node.unbundled.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export { - renderToPipeableStream, - decodeReplyFromBusboy, - decodeReply, - decodeAction, - decodeFormState, - registerServerReference, - registerClientReference, - createClientModuleProxy, - createTemporaryReferenceSet, -} from './src/server/react-flight-dom-server.node.unbundled'; diff --git a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeLoader.js b/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeLoader.js deleted file mode 100644 index b2f80e6b915f7..0000000000000 --- a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeLoader.js +++ /dev/null @@ -1,483 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import * as acorn from 'acorn-loose'; - -type ResolveContext = { - conditions: Array, - parentURL: string | void, -}; - -type ResolveFunction = ( - string, - ResolveContext, - ResolveFunction, -) => {url: string} | Promise<{url: string}>; - -type GetSourceContext = { - format: string, -}; - -type GetSourceFunction = ( - string, - GetSourceContext, - GetSourceFunction, -) => Promise<{source: Source}>; - -type TransformSourceContext = { - format: string, - url: string, -}; - -type TransformSourceFunction = ( - Source, - TransformSourceContext, - TransformSourceFunction, -) => Promise<{source: Source}>; - -type LoadContext = { - conditions: Array, - format: string | null | void, - importAssertions: Object, -}; - -type LoadFunction = ( - string, - LoadContext, - LoadFunction, -) => Promise<{format: string, shortCircuit?: boolean, source: Source}>; - -type Source = string | ArrayBuffer | Uint8Array; - -let warnedAboutConditionsFlag = false; - -let stashedGetSource: null | GetSourceFunction = null; -let stashedResolve: null | ResolveFunction = null; - -export async function resolve( - specifier: string, - context: ResolveContext, - defaultResolve: ResolveFunction, -): Promise<{url: string}> { - // We stash this in case we end up needing to resolve export * statements later. - stashedResolve = defaultResolve; - - if (!context.conditions.includes('react-server')) { - context = { - ...context, - conditions: [...context.conditions, 'react-server'], - }; - if (!warnedAboutConditionsFlag) { - warnedAboutConditionsFlag = true; - // eslint-disable-next-line react-internal/no-production-logging - console.warn( - 'You did not run Node.js with the `--conditions react-server` flag. ' + - 'Any "react-server" override will only work with ESM imports.', - ); - } - } - return await defaultResolve(specifier, context, defaultResolve); -} - -export async function getSource( - url: string, - context: GetSourceContext, - defaultGetSource: GetSourceFunction, -): Promise<{source: Source}> { - // We stash this in case we end up needing to resolve export * statements later. - stashedGetSource = defaultGetSource; - return defaultGetSource(url, context, defaultGetSource); -} - -function addLocalExportedNames(names: Map, node: any) { - switch (node.type) { - case 'Identifier': - names.set(node.name, node.name); - return; - case 'ObjectPattern': - for (let i = 0; i < node.properties.length; i++) - addLocalExportedNames(names, node.properties[i]); - return; - case 'ArrayPattern': - for (let i = 0; i < node.elements.length; i++) { - const element = node.elements[i]; - if (element) addLocalExportedNames(names, element); - } - return; - case 'Property': - addLocalExportedNames(names, node.value); - return; - case 'AssignmentPattern': - addLocalExportedNames(names, node.left); - return; - case 'RestElement': - addLocalExportedNames(names, node.argument); - return; - case 'ParenthesizedExpression': - addLocalExportedNames(names, node.expression); - return; - } -} - -function transformServerModule( - source: string, - body: any, - url: string, - loader: LoadFunction, -): string { - // If the same local name is exported more than once, we only need one of the names. - const localNames: Map = new Map(); - const localTypes: Map = new Map(); - - for (let i = 0; i < body.length; i++) { - const node = body[i]; - switch (node.type) { - case 'ExportAllDeclaration': - // If export * is used, the other file needs to explicitly opt into "use server" too. - break; - case 'ExportDefaultDeclaration': - if (node.declaration.type === 'Identifier') { - localNames.set(node.declaration.name, 'default'); - } else if (node.declaration.type === 'FunctionDeclaration') { - if (node.declaration.id) { - localNames.set(node.declaration.id.name, 'default'); - localTypes.set(node.declaration.id.name, 'function'); - } else { - // TODO: This needs to be rewritten inline because it doesn't have a local name. - } - } - continue; - case 'ExportNamedDeclaration': - if (node.declaration) { - if (node.declaration.type === 'VariableDeclaration') { - const declarations = node.declaration.declarations; - for (let j = 0; j < declarations.length; j++) { - addLocalExportedNames(localNames, declarations[j].id); - } - } else { - const name = node.declaration.id.name; - localNames.set(name, name); - if (node.declaration.type === 'FunctionDeclaration') { - localTypes.set(name, 'function'); - } - } - } - if (node.specifiers) { - const specifiers = node.specifiers; - for (let j = 0; j < specifiers.length; j++) { - const specifier = specifiers[j]; - localNames.set(specifier.local.name, specifier.exported.name); - } - } - continue; - } - } - if (localNames.size === 0) { - return source; - } - let newSrc = source + '\n\n;'; - newSrc += - 'import {registerServerReference} from "react-server-dom-turbopack/server";\n'; - localNames.forEach(function (exported, local) { - if (localTypes.get(local) !== 'function') { - // We first check if the export is a function and if so annotate it. - newSrc += 'if (typeof ' + local + ' === "function") '; - } - newSrc += 'registerServerReference(' + local + ','; - newSrc += JSON.stringify(url) + ','; - newSrc += JSON.stringify(exported) + ');\n'; - }); - return newSrc; -} - -function addExportNames(names: Array, node: any) { - switch (node.type) { - case 'Identifier': - names.push(node.name); - return; - case 'ObjectPattern': - for (let i = 0; i < node.properties.length; i++) - addExportNames(names, node.properties[i]); - return; - case 'ArrayPattern': - for (let i = 0; i < node.elements.length; i++) { - const element = node.elements[i]; - if (element) addExportNames(names, element); - } - return; - case 'Property': - addExportNames(names, node.value); - return; - case 'AssignmentPattern': - addExportNames(names, node.left); - return; - case 'RestElement': - addExportNames(names, node.argument); - return; - case 'ParenthesizedExpression': - addExportNames(names, node.expression); - return; - } -} - -function resolveClientImport( - specifier: string, - parentURL: string, -): {url: string} | Promise<{url: string}> { - // Resolve an import specifier as if it was loaded by the client. This doesn't use - // the overrides that this loader does but instead reverts to the default. - // This resolution algorithm will not necessarily have the same configuration - // as the actual client loader. It should mostly work and if it doesn't you can - // always convert to explicit exported names instead. - const conditions = ['node', 'import']; - if (stashedResolve === null) { - throw new Error( - 'Expected resolve to have been called before transformSource', - ); - } - return stashedResolve(specifier, {conditions, parentURL}, stashedResolve); -} - -async function parseExportNamesInto( - body: any, - names: Array, - parentURL: string, - loader: LoadFunction, -): Promise { - for (let i = 0; i < body.length; i++) { - const node = body[i]; - switch (node.type) { - case 'ExportAllDeclaration': - if (node.exported) { - addExportNames(names, node.exported); - continue; - } else { - const {url} = await resolveClientImport(node.source.value, parentURL); - const {source} = await loader( - url, - {format: 'module', conditions: [], importAssertions: {}}, - loader, - ); - if (typeof source !== 'string') { - throw new Error('Expected the transformed source to be a string.'); - } - let childBody; - try { - childBody = acorn.parse(source, { - ecmaVersion: '2024', - sourceType: 'module', - }).body; - } catch (x) { - // eslint-disable-next-line react-internal/no-production-logging - console.error('Error parsing %s %s', url, x.message); - continue; - } - await parseExportNamesInto(childBody, names, url, loader); - continue; - } - case 'ExportDefaultDeclaration': - names.push('default'); - continue; - case 'ExportNamedDeclaration': - if (node.declaration) { - if (node.declaration.type === 'VariableDeclaration') { - const declarations = node.declaration.declarations; - for (let j = 0; j < declarations.length; j++) { - addExportNames(names, declarations[j].id); - } - } else { - addExportNames(names, node.declaration.id); - } - } - if (node.specifiers) { - const specifiers = node.specifiers; - for (let j = 0; j < specifiers.length; j++) { - addExportNames(names, specifiers[j].exported); - } - } - continue; - } - } -} - -async function transformClientModule( - body: any, - url: string, - loader: LoadFunction, -): Promise { - const names: Array = []; - - await parseExportNamesInto(body, names, url, loader); - - if (names.length === 0) { - return ''; - } - - let newSrc = - 'import {registerClientReference} from "react-server-dom-turbopack/server";\n'; - for (let i = 0; i < names.length; i++) { - const name = names[i]; - if (name === 'default') { - newSrc += 'export default '; - newSrc += 'registerClientReference(function() {'; - newSrc += - 'throw new Error(' + - JSON.stringify( - `Attempted to call the default export of ${url} from the server ` + - `but it's on the client. It's not possible to invoke a client function from ` + - `the server, it can only be rendered as a Component or passed to props of a ` + - `Client Component.`, - ) + - ');'; - } else { - newSrc += 'export const ' + name + ' = '; - newSrc += 'registerClientReference(function() {'; - newSrc += - 'throw new Error(' + - JSON.stringify( - `Attempted to call ${name}() from the server but ${name} is on the client. ` + - `It's not possible to invoke a client function from the server, it can ` + - `only be rendered as a Component or passed to props of a Client Component.`, - ) + - ');'; - } - newSrc += '},'; - newSrc += JSON.stringify(url) + ','; - newSrc += JSON.stringify(name) + ');\n'; - } - return newSrc; -} - -async function loadClientImport( - url: string, - defaultTransformSource: TransformSourceFunction, -): Promise<{format: string, shortCircuit?: boolean, source: Source}> { - if (stashedGetSource === null) { - throw new Error( - 'Expected getSource to have been called before transformSource', - ); - } - // TODO: Validate that this is another module by calling getFormat. - const {source} = await stashedGetSource( - url, - {format: 'module'}, - stashedGetSource, - ); - const result = await defaultTransformSource( - source, - {format: 'module', url}, - defaultTransformSource, - ); - return {format: 'module', source: result.source}; -} - -async function transformModuleIfNeeded( - source: string, - url: string, - loader: LoadFunction, -): Promise { - // Do a quick check for the exact string. If it doesn't exist, don't - // bother parsing. - if ( - source.indexOf('use client') === -1 && - source.indexOf('use server') === -1 - ) { - return source; - } - - let body; - try { - body = acorn.parse(source, { - ecmaVersion: '2024', - sourceType: 'module', - }).body; - } catch (x) { - // eslint-disable-next-line react-internal/no-production-logging - console.error('Error parsing %s %s', url, x.message); - return source; - } - - let useClient = false; - let useServer = false; - for (let i = 0; i < body.length; i++) { - const node = body[i]; - if (node.type !== 'ExpressionStatement' || !node.directive) { - break; - } - if (node.directive === 'use client') { - useClient = true; - } - if (node.directive === 'use server') { - useServer = true; - } - } - - if (!useClient && !useServer) { - return source; - } - - if (useClient && useServer) { - throw new Error( - 'Cannot have both "use client" and "use server" directives in the same file.', - ); - } - - if (useClient) { - return transformClientModule(body, url, loader); - } - - return transformServerModule(source, body, url, loader); -} - -export async function transformSource( - source: Source, - context: TransformSourceContext, - defaultTransformSource: TransformSourceFunction, -): Promise<{source: Source}> { - const transformed = await defaultTransformSource( - source, - context, - defaultTransformSource, - ); - if (context.format === 'module') { - const transformedSource = transformed.source; - if (typeof transformedSource !== 'string') { - throw new Error('Expected source to have been transformed to a string.'); - } - const newSrc = await transformModuleIfNeeded( - transformedSource, - context.url, - (url: string, ctx: LoadContext, defaultLoad: LoadFunction) => { - return loadClientImport(url, defaultTransformSource); - }, - ); - return {source: newSrc}; - } - return transformed; -} - -export async function load( - url: string, - context: LoadContext, - defaultLoad: LoadFunction, -): Promise<{format: string, shortCircuit?: boolean, source: Source}> { - const result = await defaultLoad(url, context, defaultLoad); - if (result.format === 'module') { - if (typeof result.source !== 'string') { - throw new Error('Expected source to have been loaded into a string.'); - } - const newSrc = await transformModuleIfNeeded( - result.source, - url, - defaultLoad, - ); - return {format: 'module', source: newSrc}; - } - return result; -} diff --git a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js b/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js deleted file mode 100644 index fa7965cc89945..0000000000000 --- a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -const acorn = require('acorn-loose'); - -const url = require('url'); - -const Module = require('module'); - -module.exports = function register() { - const Server: any = require('react-server-dom-turbopack/server'); - const registerServerReference = Server.registerServerReference; - const createClientModuleProxy = Server.createClientModuleProxy; - - // $FlowFixMe[prop-missing] found when upgrading Flow - const originalCompile = Module.prototype._compile; - - // $FlowFixMe[prop-missing] found when upgrading Flow - Module.prototype._compile = function ( - this: any, - content: string, - filename: string, - ): void { - // Do a quick check for the exact string. If it doesn't exist, don't - // bother parsing. - if ( - content.indexOf('use client') === -1 && - content.indexOf('use server') === -1 - ) { - return originalCompile.apply(this, arguments); - } - - let body; - try { - body = acorn.parse(content, { - ecmaVersion: '2024', - sourceType: 'source', - }).body; - } catch (x) { - console['error']('Error parsing %s %s', url, x.message); - return originalCompile.apply(this, arguments); - } - - let useClient = false; - let useServer = false; - for (let i = 0; i < body.length; i++) { - const node = body[i]; - if (node.type !== 'ExpressionStatement' || !node.directive) { - break; - } - if (node.directive === 'use client') { - useClient = true; - } - if (node.directive === 'use server') { - useServer = true; - } - } - - if (!useClient && !useServer) { - return originalCompile.apply(this, arguments); - } - - if (useClient && useServer) { - throw new Error( - 'Cannot have both "use client" and "use server" directives in the same file.', - ); - } - - if (useClient) { - const moduleId: string = (url.pathToFileURL(filename).href: any); - this.exports = createClientModuleProxy(moduleId); - } - - if (useServer) { - originalCompile.apply(this, arguments); - - const moduleId: string = (url.pathToFileURL(filename).href: any); - - const exports = this.exports; - - // This module is imported server to server, but opts in to exposing functions by - // reference. If there are any functions in the export. - if (typeof exports === 'function') { - // The module exports a function directly, - registerServerReference( - (exports: any), - moduleId, - // Represents the whole Module object instead of a particular import. - null, - ); - } else { - const keys = Object.keys(exports); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const value = exports[keys[i]]; - if (typeof value === 'function') { - registerServerReference((value: any), moduleId, key); - } - } - } - } - }; -}; diff --git a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOM-test.js b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOM-test.js index eef2e824543e7..0cf2876fedba6 100644 --- a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOM-test.js +++ b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOM-test.js @@ -30,7 +30,7 @@ let Suspense; let ReactServerScheduler; let reactServerAct; -describe('ReactFlightDOM', () => { +describe('ReactFlightTurbopackDOM', () => { beforeEach(() => { // For this first reset we are going to load the dom-node version of react-server-dom-turbopack/server // This can be thought of as essentially being the React Server Components scope with react-server @@ -43,7 +43,7 @@ describe('ReactFlightDOM', () => { // Simulate the condition resolution jest.mock('react-server-dom-turbopack/server', () => - require('react-server-dom-turbopack/server.node.unbundled'), + require('react-server-dom-turbopack/server.node'), ); jest.mock('react', () => require('react/react.react-server')); diff --git a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMBrowser-test.js b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMBrowser-test.js index a47cca7068801..d90e1189d508e 100644 --- a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMBrowser-test.js +++ b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMBrowser-test.js @@ -23,7 +23,7 @@ let ReactServerDOMClient; let ReactServerScheduler; let reactServerAct; -describe('ReactFlightDOMBrowser', () => { +describe('ReactFlightTurbopackDOMBrowser', () => { beforeEach(() => { jest.resetModules(); diff --git a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMEdge-test.js b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMEdge-test.js index 67d25c967f472..767e1f1ed0ebc 100644 --- a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMEdge-test.js +++ b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMEdge-test.js @@ -28,7 +28,7 @@ let ReactServerDOMServer; let ReactServerDOMClient; let use; -describe('ReactFlightDOMEdge', () => { +describe('ReactFlightTurbopackDOMEdge', () => { beforeEach(() => { jest.resetModules(); diff --git a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMForm-test.js b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMForm-test.js deleted file mode 100644 index e7da697fad8e9..0000000000000 --- a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMForm-test.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @emails react-core - */ - -'use strict'; - -import {insertNodesAndExecuteScripts} from 'react-dom/src/test-utils/FizzTestUtils'; - -// Polyfills for test environment -global.ReadableStream = - require('web-streams-polyfill/ponyfill/es6').ReadableStream; -global.TextEncoder = require('util').TextEncoder; -global.TextDecoder = require('util').TextDecoder; - -// Don't wait before processing work on the server. -// TODO: we can replace this with FlightServer.act(). -global.setTimeout = cb => cb(); - -let container; -let serverExports; -let turbopackServerMap; -let React; -let ReactDOMServer; -let ReactServerDOMServer; -let ReactServerDOMClient; - -describe('ReactFlightDOMForm', () => { - beforeEach(() => { - jest.resetModules(); - // Simulate the condition resolution - jest.mock('react', () => require('react/react.react-server')); - jest.mock('react-server-dom-turbopack/server', () => - require('react-server-dom-turbopack/server.edge'), - ); - ReactServerDOMServer = require('react-server-dom-turbopack/server.edge'); - const TurbopackMock = require('./utils/TurbopackMock'); - serverExports = TurbopackMock.serverExports; - turbopackServerMap = TurbopackMock.turbopackServerMap; - __unmockReact(); - jest.resetModules(); - React = require('react'); - ReactServerDOMClient = require('react-server-dom-turbopack/client.edge'); - ReactDOMServer = require('react-dom/server.edge'); - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - }); - - async function POST(formData) { - const boundAction = await ReactServerDOMServer.decodeAction( - formData, - turbopackServerMap, - ); - return boundAction(); - } - - function submit(submitter) { - const form = submitter.form || submitter; - if (!submitter.form) { - submitter = undefined; - } - const submitEvent = new Event('submit', {bubbles: true, cancelable: true}); - submitEvent.submitter = submitter; - const returnValue = form.dispatchEvent(submitEvent); - if (!returnValue) { - return; - } - const action = - (submitter && submitter.getAttribute('formaction')) || form.action; - if (!/\s*javascript:/i.test(action)) { - const method = (submitter && submitter.formMethod) || form.method; - const encType = (submitter && submitter.formEnctype) || form.enctype; - if (method === 'post' && encType === 'multipart/form-data') { - let formData; - if (submitter) { - const temp = document.createElement('input'); - temp.name = submitter.name; - temp.value = submitter.value; - submitter.parentNode.insertBefore(temp, submitter); - formData = new FormData(form); - temp.parentNode.removeChild(temp); - } else { - formData = new FormData(form); - } - return POST(formData); - } - throw new Error('Navigate to: ' + action); - } - } - - async function readIntoContainer(stream) { - const reader = stream.getReader(); - let result = ''; - while (true) { - const {done, value} = await reader.read(); - if (done) { - break; - } - result += Buffer.from(value).toString('utf8'); - } - const temp = document.createElement('div'); - temp.innerHTML = result; - insertNodesAndExecuteScripts(temp, container, null); - } - - it('can submit a passed server action without hydrating it', async () => { - let foo = null; - - const serverAction = serverExports(function action(formData) { - foo = formData.get('foo'); - return 'hello'; - }); - function App() { - return ( -
- -
- ); - } - const rscStream = ReactServerDOMServer.renderToReadableStream(); - const response = ReactServerDOMClient.createFromReadableStream(rscStream, { - ssrManifest: { - moduleMap: null, - moduleLoading: null, - }, - }); - const ssrStream = await ReactDOMServer.renderToReadableStream(response); - await readIntoContainer(ssrStream); - - const form = container.firstChild; - - expect(foo).toBe(null); - - const result = await submit(form); - - expect(result).toBe('hello'); - expect(foo).toBe('bar'); - }); -}); diff --git a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMNode-test.js b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMNode-test.js index 1276d4d0be40b..a7b6ff75d57ba 100644 --- a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMNode-test.js +++ b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMNode-test.js @@ -24,7 +24,7 @@ let use; let ReactServerScheduler; let reactServerAct; -describe('ReactFlightDOMNode', () => { +describe('ReactFlightTurbopackDOMNode', () => { beforeEach(() => { jest.resetModules(); diff --git a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReply-test.js b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReply-test.js index cf328ab2e8fe3..04abb546df394 100644 --- a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReply-test.js +++ b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReply-test.js @@ -23,7 +23,7 @@ let ReactServerDOMServer; let ReactServerDOMClient; let ReactServerScheduler; -describe('ReactFlightDOMReply', () => { +describe('ReactFlightTurbopackDOMReply', () => { beforeEach(() => { jest.resetModules(); diff --git a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReplyEdge-test.js b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReplyEdge-test.js index 0cd8605c7e8d6..cbc06ef80d503 100644 --- a/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReplyEdge-test.js +++ b/packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReplyEdge-test.js @@ -20,7 +20,7 @@ let turbopackServerMap; let ReactServerDOMServer; let ReactServerDOMClient; -describe('ReactFlightDOMReply', () => { +describe('ReactFlightDOMTurbopackReply', () => { beforeEach(() => { jest.resetModules(); // Simulate the condition resolution diff --git a/packages/react-server-dom-turbopack/src/__tests__/utils/TurbopackMock.js b/packages/react-server-dom-turbopack/src/__tests__/utils/TurbopackMock.js index 35c1aae80a02b..5ed6fa5357408 100644 --- a/packages/react-server-dom-turbopack/src/__tests__/utils/TurbopackMock.js +++ b/packages/react-server-dom-turbopack/src/__tests__/utils/TurbopackMock.js @@ -8,7 +8,6 @@ 'use strict'; const url = require('url'); -const Module = require('module'); let turbopackModuleIdx = 0; const turbopackServerModules = {}; @@ -23,21 +22,9 @@ global.__turbopack_require__ = function (id) { return turbopackClientModules[id] || turbopackServerModules[id]; }; -const previousCompile = Module.prototype._compile; - -const register = require('react-server-dom-turbopack/node-register'); -// Register node compile -register(); - -const nodeCompile = Module.prototype._compile; - -if (previousCompile === nodeCompile) { - throw new Error( - 'Expected the Node loader to register the _compile extension', - ); -} - -Module.prototype._compile = previousCompile; +const Server = require('react-server-dom-turbopack/server'); +const registerServerReference = Server.registerServerReference; +const createClientModuleProxy = Server.createClientModuleProxy; exports.turbopackMap = turbopackClientMap; exports.turbopackModules = turbopackClientModules; @@ -46,20 +33,6 @@ exports.moduleLoading = { prefix: '/prefix/', }; -exports.clientModuleError = function clientModuleError(moduleError) { - const idx = '' + turbopackModuleIdx++; - turbopackErroredModules[idx] = moduleError; - const path = url.pathToFileURL(idx).href; - turbopackClientMap[path] = { - id: idx, - chunks: [], - name: '*', - }; - const mod = new Module(); - nodeCompile.call(mod, '"use client"', idx); - return mod.exports; -}; - exports.clientExports = function clientExports(moduleExports, chunkUrl) { const chunks = []; if (chunkUrl !== undefined) { @@ -107,9 +80,7 @@ exports.clientExports = function clientExports(moduleExports, chunkUrl) { name: 's', }; } - const mod = new Module(); - nodeCompile.call(mod, '"use client"', idx); - return mod.exports; + return createClientModuleProxy(path); }; // This tests server to server references. There's another case of client to server references. @@ -142,8 +113,25 @@ exports.serverExports = function serverExports(moduleExports) { name: 's', }; } - const mod = new Module(); - mod.exports = moduleExports; - nodeCompile.call(mod, '"use server"', idx); - return mod.exports; + + if (typeof exports === 'function') { + // The module exports a function directly, + registerServerReference( + (exports: any), + idx, + // Represents the whole Module object instead of a particular import. + null, + ); + } else { + const keys = Object.keys(exports); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const value = exports[keys[i]]; + if (typeof value === 'function') { + registerServerReference((value: any), idx, key); + } + } + } + + return moduleExports; }; diff --git a/packages/react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled.js b/packages/react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled.js deleted file mode 100644 index badc2ed50b691..0000000000000 --- a/packages/react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export { - renderToPipeableStream, - prerenderToNodeStream, - decodeReplyFromBusboy, - decodeReply, - decodeAction, - decodeFormState, - registerServerReference, - registerClientReference, - createClientModuleProxy, - createTemporaryReferenceSet, -} from './ReactFlightDOMServerNode'; diff --git a/packages/react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled.stable.js b/packages/react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled.stable.js deleted file mode 100644 index 0d159704067ea..0000000000000 --- a/packages/react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled.stable.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export { - renderToPipeableStream, - decodeReplyFromBusboy, - decodeReply, - decodeAction, - decodeFormState, - registerServerReference, - registerClientReference, - createClientModuleProxy, - createTemporaryReferenceSet, -} from './ReactFlightDOMServerNode'; diff --git a/packages/react-server-dom-turbopack/static.node.unbundled.js b/packages/react-server-dom-turbopack/static.node.unbundled.js deleted file mode 100644 index b2134459afc7a..0000000000000 --- a/packages/react-server-dom-turbopack/static.node.unbundled.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export {prerenderToNodeStream} from './src/server/react-flight-dom-server.node.unbundled'; diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index ea4d1a034bf47..081b91b9d0b80 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -534,18 +534,6 @@ const bundles = [ wrapWithModuleBoundaries: false, externals: ['react', 'util', 'async_hooks', 'react-dom'], }, - { - bundleTypes: [NODE_DEV, NODE_PROD], - moduleType: RENDERER, - entry: - 'react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled', - name: 'react-server-dom-turbopack-server.node.unbundled', - condition: 'react-server', - global: 'ReactServerDOMServer', - minifyWithProdErrorCodes: false, - wrapWithModuleBoundaries: false, - externals: ['react', 'util', 'async_hooks', 'react-dom'], - }, { bundleTypes: [NODE_DEV, NODE_PROD], moduleType: RENDERER, @@ -577,15 +565,6 @@ const bundles = [ wrapWithModuleBoundaries: false, externals: ['react', 'react-dom', 'util'], }, - { - bundleTypes: [NODE_DEV, NODE_PROD], - moduleType: RENDERER, - entry: 'react-server-dom-turbopack/client.node.unbundled', - global: 'ReactServerDOMClient', - minifyWithProdErrorCodes: false, - wrapWithModuleBoundaries: false, - externals: ['react', 'react-dom', 'util'], - }, { bundleTypes: [NODE_DEV, NODE_PROD], moduleType: RENDERER, @@ -596,35 +575,6 @@ const bundles = [ externals: ['react', 'react-dom'], }, - /******* React Server DOM Turbopack Plugin *******/ - // There is no plugin the moment because Turbopack - // does not expose a plugin interface yet. - - /******* React Server DOM Turbopack Node.js Loader *******/ - { - bundleTypes: [ESM_PROD], - moduleType: RENDERER_UTILS, - entry: 'react-server-dom-turbopack/node-loader', - condition: 'react-server', - global: 'ReactServerTurbopackNodeLoader', - minifyWithProdErrorCodes: false, - wrapWithModuleBoundaries: false, - externals: ['acorn'], - }, - - /******* React Server DOM Turbopack Node.js CommonJS Loader *******/ - { - bundleTypes: [NODE_ES2015], - moduleType: RENDERER_UTILS, - entry: 'react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister', - name: 'react-server-dom-turbopack-node-register', - condition: 'react-server', - global: 'ReactFlightWebpackNodeRegister', - minifyWithProdErrorCodes: false, - wrapWithModuleBoundaries: false, - externals: ['url', 'module', 'react-server-dom-turbopack/server'], - }, - /******* React Server DOM ESM Server *******/ { bundleTypes: [NODE_DEV, NODE_PROD], diff --git a/scripts/shared/inlinedHostConfigs.js b/scripts/shared/inlinedHostConfigs.js index be5706c927c7c..514ecc4567b05 100644 --- a/scripts/shared/inlinedHostConfigs.js +++ b/scripts/shared/inlinedHostConfigs.js @@ -104,49 +104,6 @@ module.exports = [ }, { shortName: 'dom-node-turbopack', - entryPoints: [ - 'react-server-dom-turbopack/client.node.unbundled', - 'react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled', - ], - paths: [ - 'react-dom', - 'react-dom-bindings', - 'react-dom/client', - 'react-dom/profiling', - 'react-dom/server', - 'react-dom/server.node', - 'react-dom/static', - 'react-dom/static.node', - 'react-dom/src/server/react-dom-server.node', - 'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node - 'react-dom/src/server/ReactDOMFizzStaticNode.js', - 'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js', - 'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js', - 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js', - 'react-server-dom-turbopack', - 'react-server-dom-turbopack/client.node.unbundled', - 'react-server-dom-turbopack/server', - 'react-server-dom-turbopack/server.node.unbundled', - 'react-server-dom-turbopack/static', - 'react-server-dom-turbopack/static.node.unbundled', - 'react-server-dom-turbopack/src/client/ReactFlightDOMClientNode.js', // react-server-dom-turbopack/client.node.unbundled - 'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerNode.js', - 'react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled', - 'react-server-dom-turbopack/src/server/ReactFlightDOMServerNode.js', // react-server-dom-turbopack/src/server/react-flight-dom-server.node.unbundled - 'react-server-dom-turbopack/node-register', - 'react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js', - 'react-devtools', - 'react-devtools-core', - 'react-devtools-shell', - 'react-devtools-shared', - 'shared/ReactDOMSharedInternals', - 'react-server/src/ReactFlightServerConfigDebugNode.js', - ], - isFlowTyped: true, - isServerSupported: true, - }, - { - shortName: 'dom-node-turbopack-bundled', entryPoints: [ 'react-server-dom-turbopack/client.node', 'react-server-dom-turbopack/src/server/react-flight-dom-server.node',