1. 'use strict';
    
  2. 
    
  3. const rollup = require('rollup');
    
  4. const babel = require('@rollup/plugin-babel').babel;
    
  5. const closure = require('./plugins/closure-plugin');
    
  6. const commonjs = require('@rollup/plugin-commonjs');
    
  7. const flowRemoveTypes = require('flow-remove-types');
    
  8. const prettier = require('rollup-plugin-prettier');
    
  9. const replace = require('@rollup/plugin-replace');
    
  10. const stripBanner = require('rollup-plugin-strip-banner');
    
  11. const chalk = require('chalk');
    
  12. const resolve = require('@rollup/plugin-node-resolve').nodeResolve;
    
  13. const fs = require('fs');
    
  14. const argv = require('minimist')(process.argv.slice(2));
    
  15. const Modules = require('./modules');
    
  16. const Bundles = require('./bundles');
    
  17. const Stats = require('./stats');
    
  18. const Sync = require('./sync');
    
  19. const sizes = require('./plugins/sizes-plugin');
    
  20. const useForks = require('./plugins/use-forks-plugin');
    
  21. const dynamicImports = require('./plugins/dynamic-imports');
    
  22. const Packaging = require('./packaging');
    
  23. const {asyncRimRaf} = require('./utils');
    
  24. const codeFrame = require('@babel/code-frame');
    
  25. const Wrappers = require('./wrappers');
    
  26. 
    
  27. const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;
    
  28. 
    
  29. // Default to building in experimental mode. If the release channel is set via
    
  30. // an environment variable, then check if it's "experimental".
    
  31. const __EXPERIMENTAL__ =
    
  32.   typeof RELEASE_CHANNEL === 'string'
    
  33.     ? RELEASE_CHANNEL === 'experimental'
    
  34.     : true;
    
  35. 
    
  36. // Errors in promises should be fatal.
    
  37. let loggedErrors = new Set();
    
  38. process.on('unhandledRejection', err => {
    
  39.   if (loggedErrors.has(err)) {
    
  40.     // No need to print it twice.
    
  41.     process.exit(1);
    
  42.   }
    
  43.   throw err;
    
  44. });
    
  45. 
    
  46. const {
    
  47.   NODE_ES2015,
    
  48.   ESM_DEV,
    
  49.   ESM_PROD,
    
  50.   UMD_DEV,
    
  51.   UMD_PROD,
    
  52.   UMD_PROFILING,
    
  53.   NODE_DEV,
    
  54.   NODE_PROD,
    
  55.   NODE_PROFILING,
    
  56.   BUN_DEV,
    
  57.   BUN_PROD,
    
  58.   FB_WWW_DEV,
    
  59.   FB_WWW_PROD,
    
  60.   FB_WWW_PROFILING,
    
  61.   RN_OSS_DEV,
    
  62.   RN_OSS_PROD,
    
  63.   RN_OSS_PROFILING,
    
  64.   RN_FB_DEV,
    
  65.   RN_FB_PROD,
    
  66.   RN_FB_PROFILING,
    
  67.   BROWSER_SCRIPT,
    
  68. } = Bundles.bundleTypes;
    
  69. 
    
  70. const {getFilename} = Bundles;
    
  71. 
    
  72. function parseRequestedNames(names, toCase) {
    
  73.   let result = [];
    
  74.   for (let i = 0; i < names.length; i++) {
    
  75.     let splitNames = names[i].split(',');
    
  76.     for (let j = 0; j < splitNames.length; j++) {
    
  77.       let name = splitNames[j].trim();
    
  78.       if (!name) {
    
  79.         continue;
    
  80.       }
    
  81.       if (toCase === 'uppercase') {
    
  82.         name = name.toUpperCase();
    
  83.       } else if (toCase === 'lowercase') {
    
  84.         name = name.toLowerCase();
    
  85.       }
    
  86.       result.push(name);
    
  87.     }
    
  88.   }
    
  89.   return result;
    
  90. }
    
  91. 
    
  92. const requestedBundleTypes = argv.type
    
  93.   ? parseRequestedNames([argv.type], 'uppercase')
    
  94.   : [];
    
  95. const requestedBundleNames = parseRequestedNames(argv._, 'lowercase');
    
  96. const forcePrettyOutput = argv.pretty;
    
  97. const isWatchMode = argv.watch;
    
  98. const syncFBSourcePath = argv['sync-fbsource'];
    
  99. const syncWWWPath = argv['sync-www'];
    
  100. 
    
  101. // Non-ES2015 stuff applied before closure compiler.
    
  102. const babelPlugins = [
    
  103.   // These plugins filter out non-ES2015.
    
  104.   ['@babel/plugin-proposal-class-properties', {loose: true}],
    
  105.   'syntax-trailing-function-commas',
    
  106.   // These use loose mode which avoids embedding a runtime.
    
  107.   // TODO: Remove object spread from the source. Prefer Object.assign instead.
    
  108.   [
    
  109.     '@babel/plugin-proposal-object-rest-spread',
    
  110.     {loose: true, useBuiltIns: true},
    
  111.   ],
    
  112.   ['@babel/plugin-transform-template-literals', {loose: true}],
    
  113.   // TODO: Remove for...of from the source. It requires a runtime to be embedded.
    
  114.   '@babel/plugin-transform-for-of',
    
  115.   // TODO: Remove array spread from the source. Prefer .apply instead.
    
  116.   ['@babel/plugin-transform-spread', {loose: true, useBuiltIns: true}],
    
  117.   '@babel/plugin-transform-parameters',
    
  118.   // TODO: Remove array destructuring from the source. Requires runtime.
    
  119.   ['@babel/plugin-transform-destructuring', {loose: true, useBuiltIns: true}],
    
  120.   // Transform Object spread to shared/assign
    
  121.   require('../babel/transform-object-assign'),
    
  122. ];
    
  123. 
    
  124. const babelToES5Plugins = [
    
  125.   // These plugins transform DEV mode. Closure compiler deals with these in PROD.
    
  126.   '@babel/plugin-transform-literals',
    
  127.   '@babel/plugin-transform-arrow-functions',
    
  128.   '@babel/plugin-transform-block-scoped-functions',
    
  129.   '@babel/plugin-transform-shorthand-properties',
    
  130.   '@babel/plugin-transform-computed-properties',
    
  131.   ['@babel/plugin-transform-block-scoping', {throwIfClosureRequired: true}],
    
  132. ];
    
  133. 
    
  134. function getBabelConfig(
    
  135.   updateBabelOptions,
    
  136.   bundleType,
    
  137.   packageName,
    
  138.   externals,
    
  139.   isDevelopment,
    
  140.   bundle
    
  141. ) {
    
  142.   const canAccessReactObject =
    
  143.     packageName === 'react' || externals.indexOf('react') !== -1;
    
  144.   let options = {
    
  145.     exclude: '/**/node_modules/**',
    
  146.     babelrc: false,
    
  147.     configFile: false,
    
  148.     presets: [],
    
  149.     plugins: [...babelPlugins],
    
  150.     babelHelpers: 'bundled',
    
  151.   };
    
  152.   if (isDevelopment) {
    
  153.     options.plugins.push(
    
  154.       ...babelToES5Plugins,
    
  155.       // Turn console.error/warn() into a custom wrapper
    
  156.       [
    
  157.         require('../babel/transform-replace-console-calls'),
    
  158.         {
    
  159.           shouldError: !canAccessReactObject,
    
  160.         },
    
  161.       ]
    
  162.     );
    
  163.   }
    
  164.   if (updateBabelOptions) {
    
  165.     options = updateBabelOptions(options);
    
  166.   }
    
  167.   // Controls whether to replace error messages with error codes in production.
    
  168.   // By default, error messages are replaced in production.
    
  169.   if (!isDevelopment && bundle.minifyWithProdErrorCodes !== false) {
    
  170.     options.plugins.push(require('../error-codes/transform-error-messages'));
    
  171.   }
    
  172. 
    
  173.   return options;
    
  174. }
    
  175. 
    
  176. let getRollupInteropValue = id => {
    
  177.   // We're setting Rollup to assume that imports are ES modules unless otherwise specified.
    
  178.   // However, we also compile ES import syntax to `require()` using Babel.
    
  179.   // This causes Rollup to turn uses of `import SomeDefaultImport from 'some-module' into
    
  180.   // references to `SomeDefaultImport.default` due to CJS/ESM interop.
    
  181.   // Some CJS modules don't have a `.default` export, and the rewritten import is incorrect.
    
  182.   // Specifying `interop: 'default'` instead will have Rollup use the imported variable as-is,
    
  183.   // without adding a `.default` to the reference.
    
  184.   const modulesWithCommonJsExports = [
    
  185.     'art/core/transform',
    
  186.     'art/modes/current',
    
  187.     'art/modes/fast-noSideEffects',
    
  188.     'art/modes/svg',
    
  189.     'JSResourceReferenceImpl',
    
  190.     'error-stack-parser',
    
  191.     'neo-async',
    
  192.     'webpack/lib/dependencies/ModuleDependency',
    
  193.     'webpack/lib/dependencies/NullDependency',
    
  194.     'webpack/lib/Template',
    
  195.   ];
    
  196. 
    
  197.   if (modulesWithCommonJsExports.includes(id)) {
    
  198.     return 'default';
    
  199.   }
    
  200. 
    
  201.   // For all other modules, handle imports without any import helper utils
    
  202.   return 'esModule';
    
  203. };
    
  204. 
    
  205. function getRollupOutputOptions(
    
  206.   outputPath,
    
  207.   format,
    
  208.   globals,
    
  209.   globalName,
    
  210.   bundleType
    
  211. ) {
    
  212.   const isProduction = isProductionBundleType(bundleType);
    
  213. 
    
  214.   return {
    
  215.     file: outputPath,
    
  216.     format,
    
  217.     globals,
    
  218.     freeze: !isProduction,
    
  219.     interop: getRollupInteropValue,
    
  220.     name: globalName,
    
  221.     sourcemap: false,
    
  222.     esModule: false,
    
  223.     exports: 'auto',
    
  224.   };
    
  225. }
    
  226. 
    
  227. function getFormat(bundleType) {
    
  228.   switch (bundleType) {
    
  229.     case UMD_DEV:
    
  230.     case UMD_PROD:
    
  231.     case UMD_PROFILING:
    
  232.       return `umd`;
    
  233.     case NODE_ES2015:
    
  234.     case NODE_DEV:
    
  235.     case NODE_PROD:
    
  236.     case NODE_PROFILING:
    
  237.     case BUN_DEV:
    
  238.     case BUN_PROD:
    
  239.     case FB_WWW_DEV:
    
  240.     case FB_WWW_PROD:
    
  241.     case FB_WWW_PROFILING:
    
  242.     case RN_OSS_DEV:
    
  243.     case RN_OSS_PROD:
    
  244.     case RN_OSS_PROFILING:
    
  245.     case RN_FB_DEV:
    
  246.     case RN_FB_PROD:
    
  247.     case RN_FB_PROFILING:
    
  248.       return `cjs`;
    
  249.     case ESM_DEV:
    
  250.     case ESM_PROD:
    
  251.       return `es`;
    
  252.     case BROWSER_SCRIPT:
    
  253.       return `iife`;
    
  254.   }
    
  255. }
    
  256. 
    
  257. function isProductionBundleType(bundleType) {
    
  258.   switch (bundleType) {
    
  259.     case NODE_ES2015:
    
  260.       return true;
    
  261.     case ESM_DEV:
    
  262.     case UMD_DEV:
    
  263.     case NODE_DEV:
    
  264.     case BUN_DEV:
    
  265.     case FB_WWW_DEV:
    
  266.     case RN_OSS_DEV:
    
  267.     case RN_FB_DEV:
    
  268.       return false;
    
  269.     case ESM_PROD:
    
  270.     case UMD_PROD:
    
  271.     case NODE_PROD:
    
  272.     case BUN_PROD:
    
  273.     case UMD_PROFILING:
    
  274.     case NODE_PROFILING:
    
  275.     case FB_WWW_PROD:
    
  276.     case FB_WWW_PROFILING:
    
  277.     case RN_OSS_PROD:
    
  278.     case RN_OSS_PROFILING:
    
  279.     case RN_FB_PROD:
    
  280.     case RN_FB_PROFILING:
    
  281.     case BROWSER_SCRIPT:
    
  282.       return true;
    
  283.     default:
    
  284.       throw new Error(`Unknown type: ${bundleType}`);
    
  285.   }
    
  286. }
    
  287. 
    
  288. function isProfilingBundleType(bundleType) {
    
  289.   switch (bundleType) {
    
  290.     case NODE_ES2015:
    
  291.     case FB_WWW_DEV:
    
  292.     case FB_WWW_PROD:
    
  293.     case NODE_DEV:
    
  294.     case NODE_PROD:
    
  295.     case BUN_DEV:
    
  296.     case BUN_PROD:
    
  297.     case RN_FB_DEV:
    
  298.     case RN_FB_PROD:
    
  299.     case RN_OSS_DEV:
    
  300.     case RN_OSS_PROD:
    
  301.     case ESM_DEV:
    
  302.     case ESM_PROD:
    
  303.     case UMD_DEV:
    
  304.     case UMD_PROD:
    
  305.     case BROWSER_SCRIPT:
    
  306.       return false;
    
  307.     case FB_WWW_PROFILING:
    
  308.     case NODE_PROFILING:
    
  309.     case RN_FB_PROFILING:
    
  310.     case RN_OSS_PROFILING:
    
  311.     case UMD_PROFILING:
    
  312.       return true;
    
  313.     default:
    
  314.       throw new Error(`Unknown type: ${bundleType}`);
    
  315.   }
    
  316. }
    
  317. 
    
  318. function forbidFBJSImports() {
    
  319.   return {
    
  320.     name: 'forbidFBJSImports',
    
  321.     resolveId(importee, importer) {
    
  322.       if (/^fbjs\//.test(importee)) {
    
  323.         throw new Error(
    
  324.           `Don't import ${importee} (found in ${importer}). ` +
    
  325.             `Use the utilities in packages/shared/ instead.`
    
  326.         );
    
  327.       }
    
  328.     },
    
  329.   };
    
  330. }
    
  331. 
    
  332. function getPlugins(
    
  333.   entry,
    
  334.   externals,
    
  335.   updateBabelOptions,
    
  336.   filename,
    
  337.   packageName,
    
  338.   bundleType,
    
  339.   globalName,
    
  340.   moduleType,
    
  341.   pureExternalModules,
    
  342.   bundle
    
  343. ) {
    
  344.   try {
    
  345.     const forks = Modules.getForks(bundleType, entry, moduleType, bundle);
    
  346.     const isProduction = isProductionBundleType(bundleType);
    
  347.     const isProfiling = isProfilingBundleType(bundleType);
    
  348.     const isUMDBundle =
    
  349.       bundleType === UMD_DEV ||
    
  350.       bundleType === UMD_PROD ||
    
  351.       bundleType === UMD_PROFILING;
    
  352.     const isFBWWWBundle =
    
  353.       bundleType === FB_WWW_DEV ||
    
  354.       bundleType === FB_WWW_PROD ||
    
  355.       bundleType === FB_WWW_PROFILING;
    
  356.     const isRNBundle =
    
  357.       bundleType === RN_OSS_DEV ||
    
  358.       bundleType === RN_OSS_PROD ||
    
  359.       bundleType === RN_OSS_PROFILING ||
    
  360.       bundleType === RN_FB_DEV ||
    
  361.       bundleType === RN_FB_PROD ||
    
  362.       bundleType === RN_FB_PROFILING;
    
  363.     const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput;
    
  364.     return [
    
  365.       // Keep dynamic imports as externals
    
  366.       dynamicImports(),
    
  367.       {
    
  368.         name: 'rollup-plugin-flow-remove-types',
    
  369.         transform(code) {
    
  370.           const transformed = flowRemoveTypes(code);
    
  371.           return {
    
  372.             code: transformed.toString(),
    
  373.             map: transformed.generateMap(),
    
  374.           };
    
  375.         },
    
  376.       },
    
  377.       // Shim any modules that need forking in this environment.
    
  378.       useForks(forks),
    
  379.       // Ensure we don't try to bundle any fbjs modules.
    
  380.       forbidFBJSImports(),
    
  381.       // Use Node resolution mechanism.
    
  382.       resolve({
    
  383.         // skip: externals, // TODO: options.skip was removed in @rollup/plugin-node-resolve 3.0.0
    
  384.       }),
    
  385.       // Remove license headers from individual modules
    
  386.       stripBanner({
    
  387.         exclude: 'node_modules/**/*',
    
  388.       }),
    
  389.       // Compile to ES2015.
    
  390.       babel(
    
  391.         getBabelConfig(
    
  392.           updateBabelOptions,
    
  393.           bundleType,
    
  394.           packageName,
    
  395.           externals,
    
  396.           !isProduction,
    
  397.           bundle
    
  398.         )
    
  399.       ),
    
  400.       // Remove 'use strict' from individual source files.
    
  401.       {
    
  402.         transform(source) {
    
  403.           return source.replace(/['"]use strict["']/g, '');
    
  404.         },
    
  405.       },
    
  406.       // Turn __DEV__ and process.env checks into constants.
    
  407.       replace({
    
  408.         preventAssignment: true,
    
  409.         values: {
    
  410.           __DEV__: isProduction ? 'false' : 'true',
    
  411.           __PROFILE__: isProfiling || !isProduction ? 'true' : 'false',
    
  412.           __UMD__: isUMDBundle ? 'true' : 'false',
    
  413.           'process.env.NODE_ENV': isProduction
    
  414.             ? "'production'"
    
  415.             : "'development'",
    
  416.           __EXPERIMENTAL__,
    
  417.         },
    
  418.       }),
    
  419.       // The CommonJS plugin *only* exists to pull "art" into "react-art".
    
  420.       // I'm going to port "art" to ES modules to avoid this problem.
    
  421.       // Please don't enable this for anything else!
    
  422.       isUMDBundle && entry === 'react-art' && commonjs(),
    
  423.       // Apply dead code elimination and/or minification.
    
  424.       // closure doesn't yet support leaving ESM imports intact
    
  425.       isProduction &&
    
  426.         bundleType !== ESM_PROD &&
    
  427.         closure({
    
  428.           compilation_level: 'SIMPLE',
    
  429.           language_in: 'ECMASCRIPT_2020',
    
  430.           language_out:
    
  431.             bundleType === NODE_ES2015
    
  432.               ? 'ECMASCRIPT_2020'
    
  433.               : bundleType === BROWSER_SCRIPT
    
  434.               ? 'ECMASCRIPT5'
    
  435.               : 'ECMASCRIPT5_STRICT',
    
  436.           emit_use_strict:
    
  437.             bundleType !== BROWSER_SCRIPT &&
    
  438.             bundleType !== ESM_PROD &&
    
  439.             bundleType !== ESM_DEV,
    
  440.           env: 'CUSTOM',
    
  441.           warning_level: 'QUIET',
    
  442.           apply_input_source_maps: false,
    
  443.           use_types_for_optimization: false,
    
  444.           process_common_js_modules: false,
    
  445.           rewrite_polyfills: false,
    
  446.           inject_libraries: false,
    
  447.           allow_dynamic_import: true,
    
  448. 
    
  449.           // Don't let it create global variables in the browser.
    
  450.           // https://github.com/facebook/react/issues/10909
    
  451.           assume_function_wrapper: !isUMDBundle,
    
  452.           renaming: !shouldStayReadable,
    
  453.         }),
    
  454.       // Add the whitespace back if necessary.
    
  455.       shouldStayReadable &&
    
  456.         prettier({
    
  457.           parser: 'flow',
    
  458.           singleQuote: false,
    
  459.           trailingComma: 'none',
    
  460.           bracketSpacing: true,
    
  461.         }),
    
  462.       // License and haste headers, top-level `if` blocks.
    
  463.       {
    
  464.         renderChunk(source) {
    
  465.           return Wrappers.wrapBundle(
    
  466.             source,
    
  467.             bundleType,
    
  468.             globalName,
    
  469.             filename,
    
  470.             moduleType,
    
  471.             bundle.wrapWithModuleBoundaries
    
  472.           );
    
  473.         },
    
  474.       },
    
  475.       // Record bundle size.
    
  476.       sizes({
    
  477.         getSize: (size, gzip) => {
    
  478.           const currentSizes = Stats.currentBuildResults.bundleSizes;
    
  479.           const recordIndex = currentSizes.findIndex(
    
  480.             record =>
    
  481.               record.filename === filename && record.bundleType === bundleType
    
  482.           );
    
  483.           const index = recordIndex !== -1 ? recordIndex : currentSizes.length;
    
  484.           currentSizes[index] = {
    
  485.             filename,
    
  486.             bundleType,
    
  487.             packageName,
    
  488.             size,
    
  489.             gzip,
    
  490.           };
    
  491.         },
    
  492.       }),
    
  493.     ].filter(Boolean);
    
  494.   } catch (error) {
    
  495.     console.error(
    
  496.       chalk.red(`There was an error preparing plugins for entry "${entry}"`)
    
  497.     );
    
  498.     throw error;
    
  499.   }
    
  500. }
    
  501. 
    
  502. function shouldSkipBundle(bundle, bundleType) {
    
  503.   const shouldSkipBundleType = bundle.bundleTypes.indexOf(bundleType) === -1;
    
  504.   if (shouldSkipBundleType) {
    
  505.     return true;
    
  506.   }
    
  507.   if (requestedBundleTypes.length > 0) {
    
  508.     const isAskingForDifferentType = requestedBundleTypes.every(
    
  509.       requestedType => bundleType.indexOf(requestedType) === -1
    
  510.     );
    
  511.     if (isAskingForDifferentType) {
    
  512.       return true;
    
  513.     }
    
  514.   }
    
  515.   if (requestedBundleNames.length > 0) {
    
  516.     // If the name ends with `something/index` we only match if the
    
  517.     // entry ends in something. Such as `react-dom/index` only matches
    
  518.     // `react-dom` but not `react-dom/server`. Everything else is fuzzy
    
  519.     // search.
    
  520.     const entryLowerCase = bundle.entry.toLowerCase() + '/index.js';
    
  521.     const isAskingForDifferentNames = requestedBundleNames.every(
    
  522.       requestedName => {
    
  523.         const matchEntry = entryLowerCase.indexOf(requestedName) !== -1;
    
  524.         if (!bundle.name) {
    
  525.           return !matchEntry;
    
  526.         }
    
  527.         const matchName =
    
  528.           bundle.name.toLowerCase().indexOf(requestedName) !== -1;
    
  529.         return !matchEntry && !matchName;
    
  530.       }
    
  531.     );
    
  532.     if (isAskingForDifferentNames) {
    
  533.       return true;
    
  534.     }
    
  535.   }
    
  536.   return false;
    
  537. }
    
  538. 
    
  539. function resolveEntryFork(resolvedEntry, isFBBundle) {
    
  540.   // Pick which entry point fork to use:
    
  541.   // .modern.fb.js
    
  542.   // .classic.fb.js
    
  543.   // .fb.js
    
  544.   // .stable.js
    
  545.   // .experimental.js
    
  546.   // .js
    
  547. 
    
  548.   if (isFBBundle) {
    
  549.     const resolvedFBEntry = resolvedEntry.replace(
    
  550.       '.js',
    
  551.       __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js'
    
  552.     );
    
  553.     if (fs.existsSync(resolvedFBEntry)) {
    
  554.       return resolvedFBEntry;
    
  555.     }
    
  556.     const resolvedGenericFBEntry = resolvedEntry.replace('.js', '.fb.js');
    
  557.     if (fs.existsSync(resolvedGenericFBEntry)) {
    
  558.       return resolvedGenericFBEntry;
    
  559.     }
    
  560.     // Even if it's a FB bundle we fallthrough to pick stable or experimental if we don't have an FB fork.
    
  561.   }
    
  562.   const resolvedForkedEntry = resolvedEntry.replace(
    
  563.     '.js',
    
  564.     __EXPERIMENTAL__ ? '.experimental.js' : '.stable.js'
    
  565.   );
    
  566.   if (fs.existsSync(resolvedForkedEntry)) {
    
  567.     return resolvedForkedEntry;
    
  568.   }
    
  569.   // Just use the plain .js one.
    
  570.   return resolvedEntry;
    
  571. }
    
  572. 
    
  573. async function createBundle(bundle, bundleType) {
    
  574.   const filename = getFilename(bundle, bundleType);
    
  575.   const logKey =
    
  576.     chalk.white.bold(filename) + chalk.dim(` (${bundleType.toLowerCase()})`);
    
  577.   const format = getFormat(bundleType);
    
  578.   const packageName = Packaging.getPackageName(bundle.entry);
    
  579. 
    
  580.   const isFBWWWBundle =
    
  581.     bundleType === FB_WWW_DEV ||
    
  582.     bundleType === FB_WWW_PROD ||
    
  583.     bundleType === FB_WWW_PROFILING;
    
  584. 
    
  585.   const isFBRNBundle =
    
  586.     bundleType === RN_FB_DEV ||
    
  587.     bundleType === RN_FB_PROD ||
    
  588.     bundleType === RN_FB_PROFILING;
    
  589. 
    
  590.   let resolvedEntry = resolveEntryFork(
    
  591.     require.resolve(bundle.entry),
    
  592.     isFBWWWBundle || isFBRNBundle
    
  593.   );
    
  594. 
    
  595.   const shouldBundleDependencies =
    
  596.     bundleType === UMD_DEV ||
    
  597.     bundleType === UMD_PROD ||
    
  598.     bundleType === UMD_PROFILING;
    
  599.   const peerGlobals = Modules.getPeerGlobals(bundle.externals, bundleType);
    
  600.   let externals = Object.keys(peerGlobals);
    
  601.   if (!shouldBundleDependencies) {
    
  602.     const deps = Modules.getDependencies(bundleType, bundle.entry);
    
  603.     externals = externals.concat(deps);
    
  604.   }
    
  605. 
    
  606.   const importSideEffects = Modules.getImportSideEffects();
    
  607.   const pureExternalModules = Object.keys(importSideEffects).filter(
    
  608.     module => !importSideEffects[module]
    
  609.   );
    
  610. 
    
  611.   const rollupConfig = {
    
  612.     input: resolvedEntry,
    
  613.     treeshake: {
    
  614.       moduleSideEffects: (id, external) =>
    
  615.         !(external && pureExternalModules.includes(id)),
    
  616.       propertyReadSideEffects: false,
    
  617.     },
    
  618.     external(id) {
    
  619.       const containsThisModule = pkg => id === pkg || id.startsWith(pkg + '/');
    
  620.       const isProvidedByDependency = externals.some(containsThisModule);
    
  621.       if (!shouldBundleDependencies && isProvidedByDependency) {
    
  622.         if (id.indexOf('/src/') !== -1) {
    
  623.           throw Error(
    
  624.             'You are trying to import ' +
    
  625.               id +
    
  626.               ' but ' +
    
  627.               externals.find(containsThisModule) +
    
  628.               ' is one of npm dependencies, ' +
    
  629.               'so it will not contain that source file. You probably want ' +
    
  630.               'to create a new bundle entry point for it instead.'
    
  631.           );
    
  632.         }
    
  633.         return true;
    
  634.       }
    
  635.       return !!peerGlobals[id];
    
  636.     },
    
  637.     onwarn: handleRollupWarning,
    
  638.     plugins: getPlugins(
    
  639.       bundle.entry,
    
  640.       externals,
    
  641.       bundle.babel,
    
  642.       filename,
    
  643.       packageName,
    
  644.       bundleType,
    
  645.       bundle.global,
    
  646.       bundle.moduleType,
    
  647.       pureExternalModules,
    
  648.       bundle
    
  649.     ),
    
  650.     output: {
    
  651.       externalLiveBindings: false,
    
  652.       freeze: false,
    
  653.       interop: getRollupInteropValue,
    
  654.       esModule: false,
    
  655.     },
    
  656.   };
    
  657.   const mainOutputPath = Packaging.getBundleOutputPath(
    
  658.     bundle,
    
  659.     bundleType,
    
  660.     filename,
    
  661.     packageName
    
  662.   );
    
  663. 
    
  664.   const rollupOutputOptions = getRollupOutputOptions(
    
  665.     mainOutputPath,
    
  666.     format,
    
  667.     peerGlobals,
    
  668.     bundle.global,
    
  669.     bundleType
    
  670.   );
    
  671. 
    
  672.   if (isWatchMode) {
    
  673.     rollupConfig.output = [rollupOutputOptions];
    
  674.     const watcher = rollup.watch(rollupConfig);
    
  675.     watcher.on('event', async event => {
    
  676.       switch (event.code) {
    
  677.         case 'BUNDLE_START':
    
  678.           console.log(`${chalk.bgYellow.black(' BUILDING ')} ${logKey}`);
    
  679.           break;
    
  680.         case 'BUNDLE_END':
    
  681.           console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`);
    
  682.           break;
    
  683.         case 'ERROR':
    
  684.         case 'FATAL':
    
  685.           console.log(`${chalk.bgRed.black(' OH NOES! ')} ${logKey}\n`);
    
  686.           handleRollupError(event.error);
    
  687.           break;
    
  688.       }
    
  689.     });
    
  690.   } else {
    
  691.     console.log(`${chalk.bgYellow.black(' BUILDING ')} ${logKey}`);
    
  692.     try {
    
  693.       const result = await rollup.rollup(rollupConfig);
    
  694.       await result.write(rollupOutputOptions);
    
  695.     } catch (error) {
    
  696.       console.log(`${chalk.bgRed.black(' OH NOES! ')} ${logKey}\n`);
    
  697.       handleRollupError(error);
    
  698.       throw error;
    
  699.     }
    
  700.     console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`);
    
  701.   }
    
  702. }
    
  703. 
    
  704. function handleRollupWarning(warning) {
    
  705.   if (warning.code === 'UNUSED_EXTERNAL_IMPORT') {
    
  706.     const match = warning.message.match(/external module "([^"]+)"/);
    
  707.     if (!match || typeof match[1] !== 'string') {
    
  708.       throw new Error(
    
  709.         'Could not parse a Rollup warning. ' + 'Fix this method.'
    
  710.       );
    
  711.     }
    
  712.     const importSideEffects = Modules.getImportSideEffects();
    
  713.     const externalModule = match[1];
    
  714.     if (typeof importSideEffects[externalModule] !== 'boolean') {
    
  715.       throw new Error(
    
  716.         'An external module "' +
    
  717.           externalModule +
    
  718.           '" is used in a DEV-only code path ' +
    
  719.           'but we do not know if it is safe to omit an unused require() to it in production. ' +
    
  720.           'Please add it to the `importSideEffects` list in `scripts/rollup/modules.js`.'
    
  721.       );
    
  722.     }
    
  723.     // Don't warn. We will remove side effectless require() in a later pass.
    
  724.     return;
    
  725.   }
    
  726. 
    
  727.   if (warning.code === 'CIRCULAR_DEPENDENCY') {
    
  728.     // Ignored
    
  729.   } else if (typeof warning.code === 'string') {
    
  730.     // This is a warning coming from Rollup itself.
    
  731.     // These tend to be important (e.g. clashes in namespaced exports)
    
  732.     // so we'll fail the build on any of them.
    
  733.     console.error();
    
  734.     console.error(warning.message || warning);
    
  735.     console.error();
    
  736.     process.exit(1);
    
  737.   } else {
    
  738.     // The warning is from one of the plugins.
    
  739.     // Maybe it's not important, so just print it.
    
  740.     console.warn(warning.message || warning);
    
  741.   }
    
  742. }
    
  743. 
    
  744. function handleRollupError(error) {
    
  745.   loggedErrors.add(error);
    
  746.   if (!error.code) {
    
  747.     console.error(error);
    
  748.     return;
    
  749.   }
    
  750.   console.error(
    
  751.     `\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --`
    
  752.   );
    
  753.   console.error(error.stack);
    
  754.   if (error.loc && error.loc.file) {
    
  755.     const {file, line, column} = error.loc;
    
  756.     // This looks like an error from Rollup, e.g. missing export.
    
  757.     // We'll use the accurate line numbers provided by Rollup but
    
  758.     // use Babel code frame because it looks nicer.
    
  759.     const rawLines = fs.readFileSync(file, 'utf-8');
    
  760.     // column + 1 is required due to rollup counting column start position from 0
    
  761.     // whereas babel-code-frame counts from 1
    
  762.     const frame = codeFrame(rawLines, line, column + 1, {
    
  763.       highlightCode: true,
    
  764.     });
    
  765.     console.error(frame);
    
  766.   } else if (error.codeFrame) {
    
  767.     // This looks like an error from a plugin (e.g. Babel).
    
  768.     // In this case we'll resort to displaying the provided code frame
    
  769.     // because we can't be sure the reported location is accurate.
    
  770.     console.error(error.codeFrame);
    
  771.   }
    
  772. }
    
  773. 
    
  774. async function buildEverything() {
    
  775.   if (!argv['unsafe-partial']) {
    
  776.     await asyncRimRaf('build');
    
  777.   }
    
  778. 
    
  779.   // Run them serially for better console output
    
  780.   // and to avoid any potential race conditions.
    
  781. 
    
  782.   let bundles = [];
    
  783.   // eslint-disable-next-line no-for-of-loops/no-for-of-loops
    
  784.   for (const bundle of Bundles.bundles) {
    
  785.     bundles.push(
    
  786.       [bundle, NODE_ES2015],
    
  787.       [bundle, ESM_DEV],
    
  788.       [bundle, ESM_PROD],
    
  789.       [bundle, UMD_DEV],
    
  790.       [bundle, UMD_PROD],
    
  791.       [bundle, UMD_PROFILING],
    
  792.       [bundle, NODE_DEV],
    
  793.       [bundle, NODE_PROD],
    
  794.       [bundle, NODE_PROFILING],
    
  795.       [bundle, BUN_DEV],
    
  796.       [bundle, BUN_PROD],
    
  797.       [bundle, FB_WWW_DEV],
    
  798.       [bundle, FB_WWW_PROD],
    
  799.       [bundle, FB_WWW_PROFILING],
    
  800.       [bundle, RN_OSS_DEV],
    
  801.       [bundle, RN_OSS_PROD],
    
  802.       [bundle, RN_OSS_PROFILING],
    
  803.       [bundle, RN_FB_DEV],
    
  804.       [bundle, RN_FB_PROD],
    
  805.       [bundle, RN_FB_PROFILING],
    
  806.       [bundle, BROWSER_SCRIPT]
    
  807.     );
    
  808.   }
    
  809. 
    
  810.   bundles = bundles.filter(([bundle, bundleType]) => {
    
  811.     return !shouldSkipBundle(bundle, bundleType);
    
  812.   });
    
  813. 
    
  814.   if (process.env.CIRCLE_NODE_TOTAL) {
    
  815.     // In CI, parallelize bundles across multiple tasks.
    
  816.     const nodeTotal = parseInt(process.env.CIRCLE_NODE_TOTAL, 10);
    
  817.     const nodeIndex = parseInt(process.env.CIRCLE_NODE_INDEX, 10);
    
  818.     bundles = bundles.filter((_, i) => i % nodeTotal === nodeIndex);
    
  819.   }
    
  820. 
    
  821.   // eslint-disable-next-line no-for-of-loops/no-for-of-loops
    
  822.   for (const [bundle, bundleType] of bundles) {
    
  823.     await createBundle(bundle, bundleType);
    
  824.   }
    
  825. 
    
  826.   await Packaging.copyAllShims();
    
  827.   await Packaging.prepareNpmPackages();
    
  828. 
    
  829.   if (syncFBSourcePath) {
    
  830.     await Sync.syncReactNative(syncFBSourcePath);
    
  831.   } else if (syncWWWPath) {
    
  832.     await Sync.syncReactDom('build/facebook-www', syncWWWPath);
    
  833.   }
    
  834. 
    
  835.   console.log(Stats.printResults());
    
  836.   if (!forcePrettyOutput) {
    
  837.     Stats.saveResults();
    
  838.   }
    
  839. }
    
  840. 
    
  841. buildEverything();