/** * 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. * * @format * */ "use strict"; /* eslint-disable lint/no-unclear-flowtypes */ const t = require("@babel/types"); const template = require("@babel/template").default; const traverse = require("@babel/traverse").default; const WRAP_NAME = "$$_REQUIRE"; // note: babel will prefix this with _ // Check first the `global` variable as the global object. This way serializers // can create a local variable called global to fake it as a global object // without having to pollute the window object on web. const IIFE_PARAM = template( "typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this" ); function wrapModule( fileAst, importDefaultName, importAllName, dependencyMapName ) { const params = buildParameters( importDefaultName, importAllName, dependencyMapName ); const factory = functionFromProgram(fileAst.program, params); const def = t.callExpression(t.identifier("__d"), [factory]); const ast = t.file(t.program([t.expressionStatement(def)])); const requireName = renameRequires(ast); return { ast, requireName }; } function wrapPolyfill(fileAst) { const factory = functionFromProgram(fileAst.program, ["global"]); const iife = t.callExpression(factory, [IIFE_PARAM().expression]); return t.file(t.program([t.expressionStatement(iife)])); } function wrapJson(source) { // Unused parameters; remember that's wrapping JSON. const moduleFactoryParameters = buildParameters( "_aUnused", "_bUnused", "_cUnused" ); return [ `__d(function(${moduleFactoryParameters.join(", ")}) {`, ` module.exports = ${source};`, "});" ].join("\n"); } function functionFromProgram(program, parameters) { return t.functionExpression( t.identifier(""), parameters.map(makeIdentifier), t.blockStatement(program.body, program.directives) ); } function makeIdentifier(name) { return t.identifier(name); } function buildParameters(importDefaultName, importAllName, dependencyMapName) { return [ "global", "require", importDefaultName, importAllName, "module", "exports", dependencyMapName ]; } function renameRequires(ast) { let newRequireName = WRAP_NAME; traverse(ast, { Program(path) { const body = path.get("body.0.expression.arguments.0.body"); newRequireName = body.scope.generateUid(WRAP_NAME); body.scope.rename("require", newRequireName); } }); return newRequireName; } module.exports = { WRAP_NAME, wrapJson, wrapModule, wrapPolyfill };