/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* strict-local
* @format
*/
"use strict";
const addParamsToDefineCall = require("../../lib/addParamsToDefineCall");
const generate = require("../worker/generate");
const mergeSourceMaps = require("../worker/mergeSourceMaps");
const reverseDependencyMapReferences = require("./reverse-dependency-map-references");
const virtualModule = require("../module").virtual;
const _require = require("@babel/core"),
transformSync = _require.transformSync;
// Transformed modules have the form
// __d(function(require, module, global, exports, dependencyMap) {
// /* code */
// });
//
// This function adds the numeric module ID, and an array with dependencies of
// the dependencies of the module before the closing parenthesis.
function addModuleIdsToModuleWrapper(module, idForPath) {
const dependencies = module.dependencies,
file = module.file;
const code = file.code; // calling `idForPath` on the module itself first gives us a lower module id
// for the file itself than for its dependencies. That reflects their order
// in the bundle.
const fileId = idForPath(file);
const paramsToAdd = [fileId];
if (dependencies.length) {
paramsToAdd.push(dependencies.map(idForPath));
}
return addParamsToDefineCall.apply(void 0, [code].concat(paramsToAdd));
}
exports.addModuleIdsToModuleWrapper = addModuleIdsToModuleWrapper;
function inlineModuleIds(module, idForPath) {
const dependencies = module.dependencies,
file = module.file;
const code = file.code,
map = file.map,
path = file.path; // calling `idForPath` on the module itself first gives us a lower module id
// for the file itself than for its dependencies. That reflects their order
// in the bundle.
const fileId = idForPath(file);
const dependencyIds = dependencies.map(idForPath);
const _transformSync = transformSync(code, {
ast: true,
babelrc: false,
code: false,
configFile: false,
plugins: [
[
reverseDependencyMapReferences,
{
dependencyIds
}
]
]
}),
ast = _transformSync.ast;
const _generate = generate(ast, path, "", true),
generatedCode = _generate.code,
generatedMap = _generate.map;
return {
moduleCode: addParamsToDefineCall(generatedCode, fileId),
moduleMap: map && generatedMap && mergeSourceMaps(path, map, generatedMap)
};
}
exports.inlineModuleIds = inlineModuleIds;
// Adds the module ids to a file if the file is a module. If it's not (e.g. a
// script) it just keeps it as-is.
function getModuleCodeAndMap(module, idForPath, options) {
const file = module.file;
if (file.type !== "module") {
return {
moduleCode: file.code,
moduleMap: file.map
};
}
if (!options.enableIDInlining) {
return {
moduleCode: addModuleIdsToModuleWrapper(module, idForPath),
moduleMap: file.map
};
}
return inlineModuleIds(module, idForPath);
}
exports.getModuleCodeAndMap = getModuleCodeAndMap; // Concatenates many iterables, by calling them sequentially.
exports.concat = function* concat() {
for (
var _len = arguments.length, iterables = new Array(_len), _key = 0;
_key < _len;
_key++
) {
iterables[_key] = arguments[_key];
}
for (const it of iterables) {
yield* it;
}
}; // Creates an idempotent function that returns numeric IDs for objects based
// on their `path` property.
exports.createIdForPathFn = () => {
const seen = new Map();
let next = 0;
return _ref => {
let path = _ref.path;
let id = seen.get(path);
if (id == null) {
id = next++;
seen.set(path, id);
}
return id;
};
}; // creates a series of virtual modules with require calls to the passed-in
// modules.
exports.requireCallsTo = function*(modules, idForPath, getRunModuleStatement) {
for (const module of modules) {
const id = idForPath(module.file);
yield virtualModule(
getRunModuleStatement(id),
`/<generated>/require-${id}.js`
);
}
}; // Divides the modules into two types: the ones that are loaded at startup, and
// the ones loaded deferredly (lazy loaded).
exports.partition = (modules, preloadedModules) => {
const startup = [];
const deferred = [];
for (const module of modules) {
(preloadedModules.has(module.file.path) ? startup : deferred).push(module);
}
return [startup, deferred];
}; // Transforms a new Module object into an old one, so that it can be passed
// around code.
exports.toModuleTransport = (module, idsForPath) => {
const dependencies = module.dependencies,
file = module.file;
const _getModuleCodeAndMap = getModuleCodeAndMap(
module,
x => idsForPath(x).moduleId,
{
enableIDInlining: true
}
),
moduleCode = _getModuleCodeAndMap.moduleCode,
moduleMap = _getModuleCodeAndMap.moduleMap;
return {
code: moduleCode,
dependencies,
// ID is required but we provide an invalid one for "script"s.
id: file.type === "module" ? idsForPath(file).localId : -1,
map: moduleMap,
name: file.path,
sourcePath: file.path
};
};