/*** 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-webpack/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) {
// eslint-disable-next-line react-internal/no-production-logging
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);
}}}}};};