1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. const acorn = require('acorn-loose');
    
  11. 
    
  12. const url = require('url');
    
  13. 
    
  14. const Module = require('module');
    
  15. 
    
  16. module.exports = function register() {
    
  17.   const Server: any = require('react-server-dom-turbopack/server');
    
  18.   const registerServerReference = Server.registerServerReference;
    
  19.   const createClientModuleProxy = Server.createClientModuleProxy;
    
  20. 
    
  21.   // $FlowFixMe[prop-missing] found when upgrading Flow
    
  22.   const originalCompile = Module.prototype._compile;
    
  23. 
    
  24.   // $FlowFixMe[prop-missing] found when upgrading Flow
    
  25.   Module.prototype._compile = function (
    
  26.     this: any,
    
  27.     content: string,
    
  28.     filename: string,
    
  29.   ): void {
    
  30.     // Do a quick check for the exact string. If it doesn't exist, don't
    
  31.     // bother parsing.
    
  32.     if (
    
  33.       content.indexOf('use client') === -1 &&
    
  34.       content.indexOf('use server') === -1
    
  35.     ) {
    
  36.       return originalCompile.apply(this, arguments);
    
  37.     }
    
  38. 
    
  39.     let body;
    
  40.     try {
    
  41.       body = acorn.parse(content, {
    
  42.         ecmaVersion: '2024',
    
  43.         sourceType: 'source',
    
  44.       }).body;
    
  45.     } catch (x) {
    
  46.       // eslint-disable-next-line react-internal/no-production-logging
    
  47.       console.error('Error parsing %s %s', url, x.message);
    
  48.       return originalCompile.apply(this, arguments);
    
  49.     }
    
  50. 
    
  51.     let useClient = false;
    
  52.     let useServer = false;
    
  53.     for (let i = 0; i < body.length; i++) {
    
  54.       const node = body[i];
    
  55.       if (node.type !== 'ExpressionStatement' || !node.directive) {
    
  56.         break;
    
  57.       }
    
  58.       if (node.directive === 'use client') {
    
  59.         useClient = true;
    
  60.       }
    
  61.       if (node.directive === 'use server') {
    
  62.         useServer = true;
    
  63.       }
    
  64.     }
    
  65. 
    
  66.     if (!useClient && !useServer) {
    
  67.       return originalCompile.apply(this, arguments);
    
  68.     }
    
  69. 
    
  70.     if (useClient && useServer) {
    
  71.       throw new Error(
    
  72.         'Cannot have both "use client" and "use server" directives in the same file.',
    
  73.       );
    
  74.     }
    
  75. 
    
  76.     if (useClient) {
    
  77.       const moduleId: string = (url.pathToFileURL(filename).href: any);
    
  78.       this.exports = createClientModuleProxy(moduleId);
    
  79.     }
    
  80. 
    
  81.     if (useServer) {
    
  82.       originalCompile.apply(this, arguments);
    
  83. 
    
  84.       const moduleId: string = (url.pathToFileURL(filename).href: any);
    
  85. 
    
  86.       const exports = this.exports;
    
  87. 
    
  88.       // This module is imported server to server, but opts in to exposing functions by
    
  89.       // reference. If there are any functions in the export.
    
  90.       if (typeof exports === 'function') {
    
  91.         // The module exports a function directly,
    
  92.         registerServerReference(
    
  93.           (exports: any),
    
  94.           moduleId,
    
  95.           // Represents the whole Module object instead of a particular import.
    
  96.           null,
    
  97.         );
    
  98.       } else {
    
  99.         const keys = Object.keys(exports);
    
  100.         for (let i = 0; i < keys.length; i++) {
    
  101.           const key = keys[i];
    
  102.           const value = exports[keys[i]];
    
  103.           if (typeof value === 'function') {
    
  104.             registerServerReference((value: any), moduleId, key);
    
  105.           }
    
  106.         }
    
  107.       }
    
  108.     }
    
  109.   };
    
  110. };