diff options
author | Florian Dold <florian.dold@gmail.com> | 2018-09-20 02:56:13 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2018-09-20 02:56:13 +0200 |
commit | bbff7403fbf46f9ad92240ac213df8d30ef31b64 (patch) | |
tree | c58400ec5124da1c7d56b01aea83309f80a56c3b /node_modules/webpack/lib/optimize/ConcatenatedModule.js | |
parent | 003fb34971cf63466184351b4db5f7c67df4f444 (diff) |
update packages
Diffstat (limited to 'node_modules/webpack/lib/optimize/ConcatenatedModule.js')
-rw-r--r-- | node_modules/webpack/lib/optimize/ConcatenatedModule.js | 2322 |
1 files changed, 1495 insertions, 827 deletions
diff --git a/node_modules/webpack/lib/optimize/ConcatenatedModule.js b/node_modules/webpack/lib/optimize/ConcatenatedModule.js index bfb772496..52d33e6f3 100644 --- a/node_modules/webpack/lib/optimize/ConcatenatedModule.js +++ b/node_modules/webpack/lib/optimize/ConcatenatedModule.js @@ -1,827 +1,1495 @@ -/*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
-*/
-"use strict";
-
-const Module = require("../Module");
-const Template = require("../Template");
-const Parser = require("../Parser");
-const crypto = require("crypto");
-const acorn = require("acorn");
-const escope = require("escope");
-const ReplaceSource = require("webpack-sources/lib/ReplaceSource");
-const ConcatSource = require("webpack-sources/lib/ConcatSource");
-const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
-const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
-const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency");
-const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency");
-const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
-const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
-
-function ensureNsObjSource(info, moduleToInfoMap, requestShortener) {
- if(!info.hasNamespaceObject) {
- info.hasNamespaceObject = true;
- const name = info.exportMap.get(true);
- const nsObj = [`var ${name} = {};`];
- for(const exportName of info.module.providedExports) {
- const finalName = getFinalName(info, exportName, moduleToInfoMap, requestShortener, false);
- nsObj.push(`__webpack_require__.d(${name}, ${JSON.stringify(exportName)}, function() { return ${finalName}; });`);
- }
- info.namespaceObjectSource = nsObj.join("\n") + "\n";
- }
-}
-
-function getExternalImport(importedModule, info, exportName, asCall) {
- if(exportName === true) return info.name;
- const used = importedModule.isUsed(exportName);
- if(!used) return "/* unused reexport */undefined";
- if(info.interop && exportName === "default") {
- return asCall ? `${info.interopName}()` : `${info.interopName}.a`;
- }
- // TODO use Template.toNormalComment when merging with pure-module
- const comment = used !== exportName ? ` /* ${exportName} */` : "";
- const reference = `${info.name}[${JSON.stringify(used)}${comment}]`;
- if(asCall)
- return `Object(${reference})`;
- return reference;
-}
-
-function getFinalName(info, exportName, moduleToInfoMap, requestShortener, asCall) {
- switch(info.type) {
- case "concatenated":
- {
- const directExport = info.exportMap.get(exportName);
- if(directExport) {
- if(exportName === true)
- ensureNsObjSource(info, moduleToInfoMap, requestShortener);
- const name = info.internalNames.get(directExport);
- if(!name)
- throw new Error(`The export "${directExport}" in "${info.module.readableIdentifier(requestShortener)}" has no internal name`);
- return name;
- }
- const reexport = info.reexportMap.get(exportName);
- if(reexport) {
- const refInfo = moduleToInfoMap.get(reexport.module);
- if(refInfo) {
- // module is in the concatenation
- return getFinalName(refInfo, reexport.exportName, moduleToInfoMap, requestShortener, asCall);
- }
- }
- const problem = `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier(requestShortener)}"` +
- ` (known exports: ${Array.from(info.exportMap.keys()).filter(name => name !== true).join(" ")}, ` +
- `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`;
- // TODO use Template.toNormalComment when merging with pure-module
- return `/* ${problem} */ undefined`;
- }
- case "external":
- {
- const importedModule = info.module;
- return getExternalImport(importedModule, info, exportName, asCall);
- }
- }
-}
-
-function getSymbolsFromScope(s, untilScope) {
- const allUsedNames = new Set();
- let scope = s;
- while(scope) {
- if(untilScope === scope) break;
- scope.variables.forEach(variable => allUsedNames.add(variable.name));
- scope = scope.upper;
- }
- return allUsedNames;
-}
-
-function getAllReferences(variable) {
- let set = variable.references;
- // Look for inner scope variables too (like in class Foo { t() { Foo } })
- const identifiers = new Set(variable.identifiers);
- for(const scope of variable.scope.childScopes) {
- for(const innerVar of scope.variables) {
- if(innerVar.identifiers.some(id => identifiers.has(id))) {
- set = set.concat(innerVar.references);
- break;
- }
- }
- }
- return set;
-}
-
-function reduceSet(a, b) {
- for(const item of b)
- a.add(item);
- return a;
-}
-
-function getPathInAst(ast, node) {
- if(ast === node) {
- return [];
- }
- const nr = node.range;
- var i;
- if(Array.isArray(ast)) {
- for(i = 0; i < ast.length; i++) {
- const enterResult = enterNode(ast[i]);
- if(typeof enterResult !== "undefined")
- return enterResult;
- }
- } else if(ast && typeof ast === "object") {
- const keys = Object.keys(ast);
- for(i = 0; i < keys.length; i++) {
- const value = ast[keys[i]];
- if(Array.isArray(value)) {
- const pathResult = getPathInAst(value, node);
- if(typeof pathResult !== "undefined")
- return pathResult;
- } else if(value && typeof value === "object") {
- const enterResult = enterNode(value);
- if(typeof enterResult !== "undefined")
- return enterResult;
- }
- }
- }
-
- function enterNode(n) {
- const r = n.range;
- if(r) {
- if(r[0] <= nr[0] && r[1] >= nr[1]) {
- const path = getPathInAst(n, node);
- if(path) {
- path.push(n);
- return path;
- }
- }
- }
- return undefined;
- }
-}
-
-class ConcatenatedModule extends Module {
- constructor(rootModule, modules) {
- super();
- super.setChunks(rootModule._chunks);
- this.rootModule = rootModule;
- this.usedExports = rootModule.usedExports;
- this.providedExports = rootModule.providedExports;
- this.optimizationBailout = rootModule.optimizationBailout;
- this.used = rootModule.used;
- this.index = rootModule.index;
- this.index2 = rootModule.index2;
- this.depth = rootModule.depth;
- this.built = modules.some(m => m.built);
- this.cacheable = modules.every(m => m.cacheable);
- const modulesSet = new Set(modules);
- this.reasons = rootModule.reasons.filter(reason => !(reason.dependency instanceof HarmonyImportDependency) || !modulesSet.has(reason.module));
- this.meta = rootModule.meta;
- this.moduleArgument = rootModule.moduleArgument;
- this.exportsArgument = rootModule.exportsArgument;
- this.strict = true;
- this._numberOfConcatenatedModules = modules.length;
-
- this.dependencies = [];
- this.dependenciesWarnings = [];
- this.dependenciesErrors = [];
- this.fileDependencies = [];
- this.contextDependencies = [];
- this.warnings = [];
- this.errors = [];
- this.assets = {};
- this._orderedConcatenationList = this._createOrderedConcatenationList(rootModule, modulesSet);
- for(const info of this._orderedConcatenationList) {
- if(info.type === "concatenated") {
- const m = info.module;
-
- // populate dependencies
- m.dependencies.filter(dep => !(dep instanceof HarmonyImportDependency) || !modulesSet.has(dep.module))
- .forEach(d => this.dependencies.push(d));
- // populate dep warning
- m.dependenciesWarnings.forEach(depWarning => this.dependenciesWarnings.push(depWarning));
- // populate dep errors
- m.dependenciesErrors.forEach(depError => this.dependenciesErrors.push(depError));
- // populate file dependencies
- if(m.fileDependencies) m.fileDependencies.forEach(file => this.fileDependencies.push(file));
- // populate context dependencies
- if(m.contextDependencies) m.contextDependencies.forEach(context => this.contextDependencies.push(context));
- // populate warnings
- m.warnings.forEach(warning => this.warnings.push(warning));
- // populate errors
- m.errors.forEach(error => this.errors.push(error));
-
- Object.assign(this.assets, m.assets);
- }
- }
- this._identifier = this._createIdentifier();
- }
-
- get modules() {
- return this._orderedConcatenationList
- .filter(info => info.type === "concatenated")
- .map(info => info.module);
- }
-
- identifier() {
- return this._identifier;
- }
-
- readableIdentifier(requestShortener) {
- return this.rootModule.readableIdentifier(requestShortener) + ` + ${this._numberOfConcatenatedModules - 1} modules`;
- }
-
- libIdent(options) {
- return this.rootModule.libIdent(options);
- }
-
- nameForCondition() {
- return this.rootModule.nameForCondition();
- }
-
- build(options, compilation, resolver, fs, callback) {
- throw new Error("Cannot build this module. It should be already built.");
- }
-
- size() {
- // Guess size from embedded modules
- return this._orderedConcatenationList.reduce((sum, info) => {
- switch(info.type) {
- case "concatenated":
- return sum + info.module.size();
- case "external":
- return sum + 5;
- }
- return sum;
- }, 0);
- }
-
- _createOrderedConcatenationList(rootModule, modulesSet) {
- const list = [];
- const set = new Set();
-
- function getConcatenatedImports(module) {
- // TODO need changes when merging with the pure-module branch
- const allDeps = module.dependencies
- .filter(dep => dep instanceof HarmonyImportDependency && dep.module);
-
- return allDeps.map(dep => () => dep.module);
- }
-
- function enterModule(getModule) {
- const module = getModule();
- if(set.has(module)) return;
- set.add(module);
- if(modulesSet.has(module)) {
- const imports = getConcatenatedImports(module);
- imports.forEach(enterModule);
- list.push({
- type: "concatenated",
- module
- });
- } else {
- list.push({
- type: "external",
- get module() {
- // We need to use a getter here, because the module in the dependency
- // could be replaced by some other process (i. e. also replaced with a
- // concatenated module)
- return getModule();
- }
- });
- }
- }
-
- enterModule(() => rootModule);
-
- return list;
- }
-
- _createIdentifier() {
- let orderedConcatenationListIdentifiers = "";
- for(let i = 0; i < this._orderedConcatenationList.length; i++) {
- if(this._orderedConcatenationList[i].type === "concatenated") {
- orderedConcatenationListIdentifiers += this._orderedConcatenationList[i].module.identifier();
- orderedConcatenationListIdentifiers += " ";
- }
- }
- const hash = crypto.createHash("md5");
- hash.update(orderedConcatenationListIdentifiers);
- return this.rootModule.identifier() + " " + hash.digest("hex");
- }
-
- source(dependencyTemplates, outputOptions, requestShortener) {
- // Metainfo for each module
- const modulesWithInfo = this._orderedConcatenationList.map((info, idx) => {
- switch(info.type) {
- case "concatenated":
- {
- const exportMap = new Map();
- const reexportMap = new Map();
- info.module.dependencies.forEach(dep => {
- if(dep instanceof HarmonyExportSpecifierDependency) {
- if(!exportMap.has(dep.name))
- exportMap.set(dep.name, dep.id);
- } else if(dep instanceof HarmonyExportExpressionDependency) {
- if(!exportMap.has("default"))
- exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__");
- } else if(dep instanceof HarmonyExportImportedSpecifierDependency) {
- const exportName = dep.name;
- const importName = dep.id;
- const importedModule = dep.importDependency.module;
- if(exportName && importName) {
- if(!reexportMap.has(exportName)) {
- reexportMap.set(exportName, {
- module: importedModule,
- exportName: importName,
- dependency: dep
- });
- }
- } else if(exportName) {
- if(!reexportMap.has(exportName)) {
- reexportMap.set(exportName, {
- module: importedModule,
- exportName: true,
- dependency: dep
- });
- }
- } else if(importedModule) {
- importedModule.providedExports.forEach(name => {
- if(dep.activeExports.has(name) || name === "default")
- return;
- if(!reexportMap.has(name)) {
- reexportMap.set(name, {
- module: importedModule,
- exportName: name,
- dependency: dep
- });
- }
- });
- }
- }
- });
- return {
- type: "concatenated",
- module: info.module,
- index: idx,
- ast: undefined,
- source: undefined,
- globalScope: undefined,
- moduleScope: undefined,
- internalNames: new Map(),
- exportMap: exportMap,
- reexportMap: reexportMap,
- hasNamespaceObject: false,
- namespaceObjectSource: null
- };
- }
- case "external":
- return {
- type: "external",
- module: info.module,
- index: idx,
- name: undefined,
- interopName: undefined,
- interop: undefined
- };
- default:
- throw new Error(`Unsupported concatenation entry type ${info.type}`);
- }
- });
-
- // Create mapping from module to info
- const moduleToInfoMap = new Map();
- modulesWithInfo.forEach(m => moduleToInfoMap.set(m.module, m));
-
- // Configure template decorators for dependencies
- const innerDependencyTemplates = new Map(dependencyTemplates);
-
- innerDependencyTemplates.set(HarmonyImportSpecifierDependency, new HarmonyImportSpecifierDependencyConcatenatedTemplate(
- dependencyTemplates.get(HarmonyImportSpecifierDependency),
- moduleToInfoMap
- ));
- innerDependencyTemplates.set(HarmonyImportDependency, new HarmonyImportDependencyConcatenatedTemplate(
- dependencyTemplates.get(HarmonyImportDependency),
- moduleToInfoMap
- ));
- innerDependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependencyConcatenatedTemplate(
- dependencyTemplates.get(HarmonyExportSpecifierDependency),
- this.rootModule
- ));
- innerDependencyTemplates.set(HarmonyExportExpressionDependency, new HarmonyExportExpressionDependencyConcatenatedTemplate(
- dependencyTemplates.get(HarmonyExportExpressionDependency),
- this.rootModule,
- moduleToInfoMap
- ));
- innerDependencyTemplates.set(HarmonyExportImportedSpecifierDependency, new HarmonyExportImportedSpecifierDependencyConcatenatedTemplate(
- dependencyTemplates.get(HarmonyExportImportedSpecifierDependency),
- this.rootModule,
- moduleToInfoMap
- ));
- innerDependencyTemplates.set(HarmonyCompatibilityDependency, new HarmonyCompatibilityDependencyConcatenatedTemplate(
- dependencyTemplates.get(HarmonyCompatibilityDependency),
- this.rootModule,
- moduleToInfoMap
- ));
- innerDependencyTemplates.set("hash", innerDependencyTemplates.get("hash") + this.rootModule.identifier());
-
- // Generate source code and analyse scopes
- // Prepare a ReplaceSource for the final source
- modulesWithInfo.forEach(info => {
- if(info.type === "concatenated") {
- const m = info.module;
- const source = m.source(innerDependencyTemplates, outputOptions, requestShortener);
- const code = source.source();
- let ast;
- try {
- ast = acorn.parse(code, {
- ranges: true,
- locations: true,
- ecmaVersion: Parser.ECMA_VERSION,
- sourceType: "module"
- });
- } catch(err) {
- if(err.loc && typeof err.loc === "object" && typeof err.loc.line === "number") {
- const lineNumber = err.loc.line;
- const lines = code.split("\n");
- err.message += "\n| " + lines.slice(Math.max(0, lineNumber - 3), lineNumber + 2).join("\n| ");
- }
- throw err;
- }
- const scopeManager = escope.analyze(ast, {
- ecmaVersion: 6,
- sourceType: "module",
- optimistic: true,
- ignoreEval: true,
- impliedStrict: true
- });
- const globalScope = scopeManager.acquire(ast);
- const moduleScope = globalScope.childScopes[0];
- const resultSource = new ReplaceSource(source);
- info.ast = ast;
- info.source = resultSource;
- info.globalScope = globalScope;
- info.moduleScope = moduleScope;
- }
- });
-
- // List of all used names to avoid conflicts
- const allUsedNames = new Set([
- "__WEBPACK_MODULE_DEFAULT_EXPORT__", // avoid using this internal name
-
- "abstract", "arguments", "async", "await", "boolean", "break", "byte", "case", "catch", "char", "class",
- "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval",
- "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if",
- "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new",
- "null", "package", "private", "protected", "public", "return", "short", "static", "super",
- "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof",
- "var", "void", "volatile", "while", "with", "yield",
-
- "module", "__dirname", "__filename", "exports",
-
- "Array", "Date", "eval", "function", "hasOwnProperty", "Infinity", "isFinite", "isNaN",
- "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String",
- "toString", "undefined", "valueOf",
-
- "alert", "all", "anchor", "anchors", "area", "assign", "blur", "button", "checkbox",
- "clearInterval", "clearTimeout", "clientInformation", "close", "closed", "confirm", "constructor",
- "crypto", "decodeURI", "decodeURIComponent", "defaultStatus", "document", "element", "elements",
- "embed", "embeds", "encodeURI", "encodeURIComponent", "escape", "event", "fileUpload", "focus",
- "form", "forms", "frame", "innerHeight", "innerWidth", "layer", "layers", "link", "location",
- "mimeTypes", "navigate", "navigator", "frames", "frameRate", "hidden", "history", "image",
- "images", "offscreenBuffering", "open", "opener", "option", "outerHeight", "outerWidth",
- "packages", "pageXOffset", "pageYOffset", "parent", "parseFloat", "parseInt", "password", "pkcs11",
- "plugin", "prompt", "propertyIsEnum", "radio", "reset", "screenX", "screenY", "scroll", "secure",
- "select", "self", "setInterval", "setTimeout", "status", "submit", "taint", "text", "textarea",
- "top", "unescape", "untaint", "window",
-
- "onblur", "onclick", "onerror", "onfocus", "onkeydown", "onkeypress", "onkeyup", "onmouseover",
- "onload", "onmouseup", "onmousedown", "onsubmit"
- ]);
-
- // get all global names
- modulesWithInfo.forEach(info => {
- if(info.globalScope) {
- info.globalScope.through.forEach(reference => {
- const name = reference.identifier.name;
- if(/^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?__$/.test(name)) {
- for(const s of getSymbolsFromScope(reference.from, info.moduleScope)) {
- allUsedNames.add(s);
- }
- } else {
- allUsedNames.add(name);
- }
- });
- }
- });
-
- // generate names for symbols
- modulesWithInfo.forEach(info => {
- switch(info.type) {
- case "concatenated":
- {
- const namespaceObjectName = this.findNewName("namespaceObject", allUsedNames, null, info.module.readableIdentifier(requestShortener));
- allUsedNames.add(namespaceObjectName);
- info.internalNames.set(namespaceObjectName, namespaceObjectName);
- info.exportMap.set(true, namespaceObjectName);
- info.moduleScope.variables.forEach(variable => {
- const name = variable.name;
- if(allUsedNames.has(name)) {
- const references = getAllReferences(variable);
- const symbolsInReferences = references.map(ref => getSymbolsFromScope(ref.from, info.moduleScope)).reduce(reduceSet, new Set());
- const newName = this.findNewName(name, allUsedNames, symbolsInReferences, info.module.readableIdentifier(requestShortener));
- allUsedNames.add(newName);
- info.internalNames.set(name, newName);
- const source = info.source;
- const allIdentifiers = new Set(references.map(r => r.identifier).concat(variable.identifiers));
- for(const identifier of allIdentifiers) {
- const r = identifier.range;
- const path = getPathInAst(info.ast, identifier);
- if(path && path.length > 1 && path[1].type === "Property" && path[1].shorthand) {
- source.insert(r[1], `: ${newName}`);
- } else {
- source.replace(r[0], r[1] - 1, newName);
- }
- }
- } else {
- allUsedNames.add(name);
- info.internalNames.set(name, name);
- }
- });
- break;
- }
- case "external":
- {
- info.interop = info.module.meta && !info.module.meta.harmonyModule;
- const externalName = this.findNewName("", allUsedNames, null, info.module.readableIdentifier(requestShortener));
- allUsedNames.add(externalName);
- info.name = externalName;
- if(info.interop) {
- const externalNameInterop = this.findNewName("default", allUsedNames, null, info.module.readableIdentifier(requestShortener));
- allUsedNames.add(externalNameInterop);
- info.interopName = externalNameInterop;
- }
- break;
- }
- }
- });
-
- // Find and replace referenced to modules
- modulesWithInfo.forEach(info => {
- if(info.type === "concatenated") {
- info.globalScope.through.forEach(reference => {
- const name = reference.identifier.name;
- const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?__$/.exec(name);
- if(match) {
- const referencedModule = modulesWithInfo[+match[1]];
- let exportName;
- if(match[2] === "ns") {
- exportName = true;
- } else {
- const exportData = match[2];
- exportName = new Buffer(exportData, "hex").toString("utf-8"); // eslint-disable-line node/no-deprecated-api
- }
- const asCall = !!match[3];
- const finalName = getFinalName(referencedModule, exportName, moduleToInfoMap, requestShortener, asCall);
- const r = reference.identifier.range;
- const source = info.source;
- source.replace(r[0], r[1] - 1, finalName);
- }
- });
- }
- });
-
- const result = new ConcatSource();
-
- // add harmony compatibility flag (must be first because of possible circular dependencies)
- const usedExports = this.rootModule.usedExports;
- if(usedExports === true) {
- result.add(`Object.defineProperty(${this.exportsArgument || "exports"}, "__esModule", { value: true });\n`);
- }
-
- // define required namespace objects (must be before evaluation modules)
- modulesWithInfo.forEach(info => {
- if(info.namespaceObjectSource) {
- result.add(info.namespaceObjectSource);
- }
- });
-
- // evaluate modules in order
- modulesWithInfo.forEach(info => {
- switch(info.type) {
- case "concatenated":
- result.add(`\n// CONCATENATED MODULE: ${info.module.readableIdentifier(requestShortener)}\n`);
- result.add(info.source);
- break;
- case "external":
- result.add(`\n// EXTERNAL MODULE: ${info.module.readableIdentifier(requestShortener)}\n`);
- result.add(`var ${info.name} = __webpack_require__(${JSON.stringify(info.module.id)});\n`);
- if(info.interop) {
- result.add(`var ${info.interopName} = /*#__PURE__*/__webpack_require__.n(${info.name});\n`);
- }
- break;
- default:
- throw new Error(`Unsupported concatenation entry type ${info.type}`);
- }
- });
-
- return result;
- }
-
- findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
- let name = oldName;
-
- if(name === "__WEBPACK_MODULE_DEFAULT_EXPORT__")
- name = "";
-
- // Remove uncool stuff
- extraInfo = extraInfo.replace(/\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, "");
-
- const splittedInfo = extraInfo.split("/");
- while(splittedInfo.length) {
- name = splittedInfo.pop() + (name ? "_" + name : "");
- const nameIdent = Template.toIdentifier(name);
- if(!usedNamed1.has(nameIdent) && (!usedNamed2 || !usedNamed2.has(nameIdent))) return nameIdent;
- }
-
- let i = 0;
- let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
- while(usedNamed1.has(nameWithNumber) || (usedNamed2 && usedNamed2.has(nameWithNumber))) {
- i++;
- nameWithNumber = Template.toIdentifier(`${name}_${i}`);
- }
- return nameWithNumber;
- }
-
- updateHash(hash) {
- for(const info of this._orderedConcatenationList) {
- switch(info.type) {
- case "concatenated":
- info.module.updateHash(hash);
- break;
- case "external":
- hash.update(`${info.module.id}`);
- break;
- }
- }
- super.updateHash(hash);
- }
-
-}
-
-class HarmonyImportSpecifierDependencyConcatenatedTemplate {
- constructor(originalTemplate, modulesMap) {
- this.originalTemplate = originalTemplate;
- this.modulesMap = modulesMap;
- }
-
- apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
- const module = dep.importDependency.module;
- const info = this.modulesMap.get(module);
- if(!info) {
- this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
- return;
- }
- let content;
- if(dep.id === null) {
- content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`;
- } else if(dep.namespaceObjectAsContext) {
- content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__[${JSON.stringify(dep.id)}]`;
- } else {
- const exportData = new Buffer(dep.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api
- content = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${dep.call ? "_call" : ""}__`;
- }
- if(dep.shorthand) {
- content = dep.name + ": " + content;
- }
- source.replace(dep.range[0], dep.range[1] - 1, content);
- }
-}
-
-class HarmonyImportDependencyConcatenatedTemplate {
- constructor(originalTemplate, modulesMap) {
- this.originalTemplate = originalTemplate;
- this.modulesMap = modulesMap;
- }
-
- apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
- const module = dep.module;
- const info = this.modulesMap.get(module);
- if(!info) {
- this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
- return;
- }
- source.replace(dep.range[0], dep.range[1] - 1, "");
- }
-}
-
-class HarmonyExportSpecifierDependencyConcatenatedTemplate {
- constructor(originalTemplate, rootModule) {
- this.originalTemplate = originalTemplate;
- this.rootModule = rootModule;
- }
-
- apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
- if(dep.originModule === this.rootModule) {
- this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
- }
- }
-}
-
-class HarmonyExportExpressionDependencyConcatenatedTemplate {
- constructor(originalTemplate, rootModule) {
- this.originalTemplate = originalTemplate;
- this.rootModule = rootModule;
- }
-
- apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
- let content = "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = ";
- if(dep.originModule === this.rootModule) {
- const used = dep.originModule.isUsed("default");
- const exportsName = dep.originModule.exportsArgument || "exports";
- if(used) content += `${exportsName}[${JSON.stringify(used)}] = `;
- }
-
- if(dep.range) {
- source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "(");
- source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");");
- return;
- }
-
- source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content);
- }
-}
-
-class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate {
- constructor(originalTemplate, rootModule, modulesMap) {
- this.originalTemplate = originalTemplate;
- this.rootModule = rootModule;
- this.modulesMap = modulesMap;
- }
-
- getExports(dep) {
- const importModule = dep.importDependency.module;
- if(dep.id) {
- // export { named } from "module"
- return [{
- name: dep.name,
- id: dep.id,
- module: importModule
- }];
- }
- if(dep.name) {
- // export * as abc from "module"
- return [{
- name: dep.name,
- id: true,
- module: importModule
- }];
- }
- // export * from "module"
- return importModule.providedExports.filter(exp => exp !== "default" && !dep.activeExports.has(exp)).map(exp => {
- return {
- name: exp,
- id: exp,
- module: importModule
- };
- });
- }
-
- apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
- if(dep.originModule === this.rootModule) {
- if(this.modulesMap.get(dep.importDependency.module)) {
- const exportDefs = this.getExports(dep);
- exportDefs.forEach(def => {
- const info = this.modulesMap.get(def.module);
- const used = dep.originModule.isUsed(def.name);
- if(!used) {
- source.insert(-1, `/* unused concated harmony import ${dep.name} */\n`);
- }
- let finalName;
- if(def.id === true) {
- finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns__`;
- } else {
- const exportData = new Buffer(def.id, "utf-8").toString("hex"); // eslint-disable-line node/no-deprecated-api
- finalName = `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}__`;
- }
- const exportsName = this.rootModule.exportsArgument || "exports";
- const content = `/* concated harmony reexport */__webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${finalName}; });\n`;
- source.insert(-1, content);
- });
- } else {
- this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
- }
- }
- }
-}
-
-class HarmonyCompatibilityDependencyConcatenatedTemplate {
- constructor(originalTemplate, rootModule, modulesMap) {
- this.originalTemplate = originalTemplate;
- this.rootModule = rootModule;
- this.modulesMap = modulesMap;
- }
-
- apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
- // do nothing
- }
-}
-
-module.exports = ConcatenatedModule;
+/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +"use strict"; + +const Module = require("../Module"); +const Template = require("../Template"); +const Parser = require("../Parser"); +const eslintScope = require("eslint-scope"); +const { ConcatSource, ReplaceSource } = require("webpack-sources"); +const DependencyReference = require("../dependencies/DependencyReference"); +const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); +const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency"); +const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency"); +const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency"); +const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency"); +const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency"); +const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency"); +const createHash = require("../util/createHash"); + +/** @typedef {import("../Dependency")} Dependency */ +/** @typedef {import("../Compilation")} Compilation */ +/** @typedef {import("../util/createHash").Hash} Hash */ + +/** + * @typedef {Object} ConcatenationEntry + * @property {"concatenated" | "external"} type + * @property {Module} module + */ + +const ensureNsObjSource = ( + info, + moduleToInfoMap, + requestShortener, + strictHarmonyModule +) => { + if (!info.hasNamespaceObject) { + info.hasNamespaceObject = true; + const name = info.exportMap.get(true); + const nsObj = [`var ${name} = {};`, `__webpack_require__.r(${name});`]; + for (const exportName of info.module.buildMeta.providedExports) { + const finalName = getFinalName( + info, + exportName, + moduleToInfoMap, + requestShortener, + false, + strictHarmonyModule + ); + nsObj.push( + `__webpack_require__.d(${name}, ${JSON.stringify( + exportName + )}, function() { return ${finalName}; });` + ); + } + info.namespaceObjectSource = nsObj.join("\n") + "\n"; + } +}; + +const getExternalImport = ( + importedModule, + info, + exportName, + asCall, + strictHarmonyModule +) => { + const used = importedModule.isUsed(exportName); + if (!used) return "/* unused reexport */undefined"; + const comment = + used !== exportName ? ` ${Template.toNormalComment(exportName)}` : ""; + switch (importedModule.buildMeta.exportsType) { + case "named": + if (exportName === "default") { + return info.name; + } else if (exportName === true) { + info.interopNamespaceObjectUsed = true; + return info.interopNamespaceObjectName; + } else { + break; + } + case "namespace": + if (exportName === true) { + return info.name; + } else { + break; + } + default: + if (strictHarmonyModule) { + if (exportName === "default") { + return info.name; + } else if (exportName === true) { + info.interopNamespaceObjectUsed = true; + return info.interopNamespaceObjectName; + } else { + return "/* non-default import from non-esm module */undefined"; + } + } else { + if (exportName === "default") { + info.interopDefaultAccessUsed = true; + return asCall + ? `${info.interopDefaultAccessName}()` + : `${info.interopDefaultAccessName}.a`; + } else if (exportName === true) { + return info.name; + } else { + break; + } + } + } + const reference = `${info.name}[${JSON.stringify(used)}${comment}]`; + if (asCall) return `Object(${reference})`; + return reference; +}; + +const getFinalName = ( + info, + exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule, + alreadyVisited = new Set() +) => { + switch (info.type) { + case "concatenated": { + const directExport = info.exportMap.get(exportName); + if (directExport) { + if (exportName === true) { + ensureNsObjSource( + info, + moduleToInfoMap, + requestShortener, + strictHarmonyModule + ); + } else if (!info.module.isUsed(exportName)) { + return "/* unused export */ undefined"; + } + if (info.globalExports.has(directExport)) { + return directExport; + } + const name = info.internalNames.get(directExport); + if (!name) { + throw new Error( + `The export "${directExport}" in "${info.module.readableIdentifier( + requestShortener + )}" has no internal name` + ); + } + return name; + } + const reexport = info.reexportMap.get(exportName); + if (reexport) { + if (alreadyVisited.has(reexport)) { + throw new Error( + `Circular reexports ${Array.from( + alreadyVisited, + e => + `"${e.module.readableIdentifier(requestShortener)}".${ + e.exportName + }` + ).join( + " --> " + )} -(circular)-> "${reexport.module.readableIdentifier( + requestShortener + )}".${reexport.exportName}` + ); + } + alreadyVisited.add(reexport); + const refInfo = moduleToInfoMap.get(reexport.module); + if (refInfo) { + // module is in the concatenation + return getFinalName( + refInfo, + reexport.exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule, + alreadyVisited + ); + } + } + const problem = + `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier( + requestShortener + )}"` + + ` (known exports: ${Array.from(info.exportMap.keys()) + .filter(name => name !== true) + .join(" ")}, ` + + `known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; + return `${Template.toNormalComment(problem)} undefined`; + } + case "external": { + const importedModule = info.module; + return getExternalImport( + importedModule, + info, + exportName, + asCall, + strictHarmonyModule + ); + } + } +}; + +const addScopeSymbols1 = (s, nameSet, scopeSet) => { + let scope = s; + while (scope) { + if (scopeSet.has(scope)) break; + scopeSet.add(scope); + for (const variable of scope.variables) { + nameSet.add(variable.name); + } + scope = scope.upper; + } +}; + +const addScopeSymbols2 = (s, nameSet, scopeSet1, scopeSet2) => { + let scope = s; + while (scope) { + if (scopeSet1.has(scope)) break; + if (scopeSet2.has(scope)) break; + scopeSet1.add(scope); + for (const variable of scope.variables) { + nameSet.add(variable.name); + } + scope = scope.upper; + } +}; + +const getAllReferences = variable => { + let set = variable.references; + // Look for inner scope variables too (like in class Foo { t() { Foo } }) + const identifiers = new Set(variable.identifiers); + for (const scope of variable.scope.childScopes) { + for (const innerVar of scope.variables) { + if (innerVar.identifiers.some(id => identifiers.has(id))) { + set = set.concat(innerVar.references); + break; + } + } + } + return set; +}; + +const getPathInAst = (ast, node) => { + if (ast === node) { + return []; + } + + const nr = node.range; + + const enterNode = n => { + if (!n) return undefined; + const r = n.range; + if (r) { + if (r[0] <= nr[0] && r[1] >= nr[1]) { + const path = getPathInAst(n, node); + if (path) { + path.push(n); + return path; + } + } + } + return undefined; + }; + + var i; + if (Array.isArray(ast)) { + for (i = 0; i < ast.length; i++) { + const enterResult = enterNode(ast[i]); + if (enterResult !== undefined) return enterResult; + } + } else if (ast && typeof ast === "object") { + const keys = Object.keys(ast); + for (i = 0; i < keys.length; i++) { + const value = ast[keys[i]]; + if (Array.isArray(value)) { + const pathResult = getPathInAst(value, node); + if (pathResult !== undefined) return pathResult; + } else if (value && typeof value === "object") { + const enterResult = enterNode(value); + if (enterResult !== undefined) return enterResult; + } + } + } +}; + +class ConcatenatedModule extends Module { + constructor(rootModule, modules, concatenationList) { + super("javascript/esm", null); + super.setChunks(rootModule._chunks); + + // Info from Factory + this.rootModule = rootModule; + this.factoryMeta = rootModule.factoryMeta; + + // Info from Compilation + this.index = rootModule.index; + this.index2 = rootModule.index2; + this.depth = rootModule.depth; + + // Info from Optimization + this.used = rootModule.used; + this.usedExports = rootModule.usedExports; + + // Info from Build + this.buildInfo = { + strict: true, + cacheable: modules.every(m => m.buildInfo.cacheable), + moduleArgument: rootModule.buildInfo.moduleArgument, + exportsArgument: rootModule.buildInfo.exportsArgument, + fileDependencies: new Set(), + contextDependencies: new Set(), + assets: undefined + }; + this.built = modules.some(m => m.built); + this.buildMeta = rootModule.buildMeta; + + // Caching + this._numberOfConcatenatedModules = modules.length; + + // Graph + const modulesSet = new Set(modules); + this.reasons = rootModule.reasons.filter( + reason => + !(reason.dependency instanceof HarmonyImportDependency) || + !modulesSet.has(reason.module) + ); + + this.dependencies = []; + + this.warnings = []; + this.errors = []; + this._orderedConcatenationList = + concatenationList || + ConcatenatedModule.createConcatenationList(rootModule, modulesSet, null); + for (const info of this._orderedConcatenationList) { + if (info.type === "concatenated") { + const m = info.module; + + // populate dependencies + for (const d of m.dependencies.filter( + dep => + !(dep instanceof HarmonyImportDependency) || + !modulesSet.has(dep._module) + )) { + this.dependencies.push(d); + } + // populate file dependencies + if (m.buildInfo.fileDependencies) { + for (const file of m.buildInfo.fileDependencies) { + this.buildInfo.fileDependencies.add(file); + } + } + // populate context dependencies + if (m.buildInfo.contextDependencies) { + for (const context of m.buildInfo.contextDependencies) { + this.buildInfo.contextDependencies.add(context); + } + } + // populate warnings + for (const warning of m.warnings) { + this.warnings.push(warning); + } + // populate errors + for (const error of m.errors) { + this.errors.push(error); + } + + if (m.buildInfo.assets) { + if (this.buildInfo.assets === undefined) { + this.buildInfo.assets = Object.create(null); + } + Object.assign(this.buildInfo.assets, m.buildInfo.assets); + } + } + } + this._identifier = this._createIdentifier(); + } + + get modules() { + return this._orderedConcatenationList + .filter(info => info.type === "concatenated") + .map(info => info.module); + } + + identifier() { + return this._identifier; + } + + readableIdentifier(requestShortener) { + return ( + this.rootModule.readableIdentifier(requestShortener) + + ` + ${this._numberOfConcatenatedModules - 1} modules` + ); + } + + libIdent(options) { + return this.rootModule.libIdent(options); + } + + nameForCondition() { + return this.rootModule.nameForCondition(); + } + + build(options, compilation, resolver, fs, callback) { + throw new Error("Cannot build this module. It should be already built."); + } + + size() { + // Guess size from embedded modules + return this._orderedConcatenationList.reduce((sum, info) => { + switch (info.type) { + case "concatenated": + return sum + info.module.size(); + case "external": + return sum + 5; + } + return sum; + }, 0); + } + + /** + * @param {Module} rootModule the root of the concatenation + * @param {Set<Module>} modulesSet a set of modules which should be concatenated + * @param {Compilation} compilation the compilation context + * @returns {ConcatenationEntry[]} concatenation list + */ + static createConcatenationList(rootModule, modulesSet, compilation) { + const list = []; + const set = new Set(); + + /** + * @param {Module} module a module + * @returns {(function(): Module)[]} imported modules in order + */ + const getConcatenatedImports = module => { + /** @type {WeakMap<DependencyReference, Dependency>} */ + const map = new WeakMap(); + const references = module.dependencies + .filter(dep => dep instanceof HarmonyImportDependency) + .map(dep => { + const ref = compilation.getDependencyReference(module, dep); + if (ref) map.set(ref, dep); + return ref; + }) + .filter(ref => ref); + DependencyReference.sort(references); + // TODO webpack 5: remove this hack, see also DependencyReference + return references.map(ref => { + const dep = map.get(ref); + return () => compilation.getDependencyReference(module, dep).module; + }); + }; + + const enterModule = getModule => { + const module = getModule(); + if (!module) return; + if (set.has(module)) return; + set.add(module); + if (modulesSet.has(module)) { + const imports = getConcatenatedImports(module); + imports.forEach(enterModule); + list.push({ + type: "concatenated", + module + }); + } else { + list.push({ + type: "external", + get module() { + // We need to use a getter here, because the module in the dependency + // could be replaced by some other process (i. e. also replaced with a + // concatenated module) + return getModule(); + } + }); + } + }; + + enterModule(() => rootModule); + + return list; + } + + _createIdentifier() { + let orderedConcatenationListIdentifiers = ""; + for (let i = 0; i < this._orderedConcatenationList.length; i++) { + if (this._orderedConcatenationList[i].type === "concatenated") { + orderedConcatenationListIdentifiers += this._orderedConcatenationList[ + i + ].module.identifier(); + orderedConcatenationListIdentifiers += " "; + } + } + const hash = createHash("md4"); + hash.update(orderedConcatenationListIdentifiers); + return this.rootModule.identifier() + " " + hash.digest("hex"); + } + + source(dependencyTemplates, runtimeTemplate) { + const requestShortener = runtimeTemplate.requestShortener; + // Metainfo for each module + const modulesWithInfo = this._orderedConcatenationList.map((info, idx) => { + switch (info.type) { + case "concatenated": { + const exportMap = new Map(); + const reexportMap = new Map(); + for (const dep of info.module.dependencies) { + if (dep instanceof HarmonyExportSpecifierDependency) { + if (!exportMap.has(dep.name)) { + exportMap.set(dep.name, dep.id); + } + } else if (dep instanceof HarmonyExportExpressionDependency) { + if (!exportMap.has("default")) { + exportMap.set("default", "__WEBPACK_MODULE_DEFAULT_EXPORT__"); + } + } else if ( + dep instanceof HarmonyExportImportedSpecifierDependency + ) { + const exportName = dep.name; + const importName = dep.id; + const importedModule = dep._module; + if (exportName && importName) { + if (!reexportMap.has(exportName)) { + reexportMap.set(exportName, { + module: importedModule, + exportName: importName, + dependency: dep + }); + } + } else if (exportName) { + if (!reexportMap.has(exportName)) { + reexportMap.set(exportName, { + module: importedModule, + exportName: true, + dependency: dep + }); + } + } else if (importedModule) { + for (const name of importedModule.buildMeta.providedExports) { + if (dep.activeExports.has(name) || name === "default") { + continue; + } + if (!reexportMap.has(name)) { + reexportMap.set(name, { + module: importedModule, + exportName: name, + dependency: dep + }); + } + } + } + } + } + return { + type: "concatenated", + module: info.module, + index: idx, + ast: undefined, + internalSource: undefined, + source: undefined, + globalScope: undefined, + moduleScope: undefined, + internalNames: new Map(), + globalExports: new Set(), + exportMap: exportMap, + reexportMap: reexportMap, + hasNamespaceObject: false, + namespaceObjectSource: null + }; + } + case "external": + return { + type: "external", + module: info.module, + index: idx, + name: undefined, + interopNamespaceObjectUsed: false, + interopNamespaceObjectName: undefined, + interopDefaultAccessUsed: false, + interopDefaultAccessName: undefined + }; + default: + throw new Error(`Unsupported concatenation entry type ${info.type}`); + } + }); + + // Create mapping from module to info + const moduleToInfoMap = new Map(); + for (const m of modulesWithInfo) { + moduleToInfoMap.set(m.module, m); + } + + // Configure template decorators for dependencies + const innerDependencyTemplates = new Map(dependencyTemplates); + + innerDependencyTemplates.set( + HarmonyImportSpecifierDependency, + new HarmonyImportSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyImportSpecifierDependency), + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyImportSideEffectDependency, + new HarmonyImportSideEffectDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyImportSideEffectDependency), + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyExportSpecifierDependency, + new HarmonyExportSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportSpecifierDependency), + this.rootModule + ) + ); + innerDependencyTemplates.set( + HarmonyExportExpressionDependency, + new HarmonyExportExpressionDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportExpressionDependency), + this.rootModule + ) + ); + innerDependencyTemplates.set( + HarmonyExportImportedSpecifierDependency, + new HarmonyExportImportedSpecifierDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyExportImportedSpecifierDependency), + this.rootModule, + moduleToInfoMap + ) + ); + innerDependencyTemplates.set( + HarmonyCompatibilityDependency, + new HarmonyCompatibilityDependencyConcatenatedTemplate( + dependencyTemplates.get(HarmonyCompatibilityDependency), + this.rootModule, + moduleToInfoMap + ) + ); + + // Must use full identifier in our cache here to ensure that the source + // is updated should our dependencies list change. + // TODO webpack 5 refactor + innerDependencyTemplates.set( + "hash", + innerDependencyTemplates.get("hash") + this.identifier() + ); + + // Generate source code and analyse scopes + // Prepare a ReplaceSource for the final source + for (const info of modulesWithInfo) { + if (info.type === "concatenated") { + const m = info.module; + const source = m.source(innerDependencyTemplates, runtimeTemplate); + const code = source.source(); + let ast; + try { + ast = Parser.parse(code, { + sourceType: "module" + }); + } catch (err) { + if ( + err.loc && + typeof err.loc === "object" && + typeof err.loc.line === "number" + ) { + const lineNumber = err.loc.line; + const lines = code.split("\n"); + err.message += + "\n| " + + lines + .slice(Math.max(0, lineNumber - 3), lineNumber + 2) + .join("\n| "); + } + throw err; + } + const scopeManager = eslintScope.analyze(ast, { + ecmaVersion: 6, + sourceType: "module", + optimistic: true, + ignoreEval: true, + impliedStrict: true + }); + const globalScope = scopeManager.acquire(ast); + const moduleScope = globalScope.childScopes[0]; + const resultSource = new ReplaceSource(source); + info.ast = ast; + info.internalSource = source; + info.source = resultSource; + info.globalScope = globalScope; + info.moduleScope = moduleScope; + } + } + + // List of all used names to avoid conflicts + const allUsedNames = new Set([ + "__WEBPACK_MODULE_DEFAULT_EXPORT__", // avoid using this internal name + + "abstract", + "arguments", + "async", + "await", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "double", + "else", + "enum", + "eval", + "export", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "let", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "typeof", + "var", + "void", + "volatile", + "while", + "with", + "yield", + + "module", + "__dirname", + "__filename", + "exports", + + "Array", + "Date", + "eval", + "function", + "hasOwnProperty", + "Infinity", + "isFinite", + "isNaN", + "isPrototypeOf", + "length", + "Math", + "NaN", + "name", + "Number", + "Object", + "prototype", + "String", + "toString", + "undefined", + "valueOf", + + "alert", + "all", + "anchor", + "anchors", + "area", + "assign", + "blur", + "button", + "checkbox", + "clearInterval", + "clearTimeout", + "clientInformation", + "close", + "closed", + "confirm", + "constructor", + "crypto", + "decodeURI", + "decodeURIComponent", + "defaultStatus", + "document", + "element", + "elements", + "embed", + "embeds", + "encodeURI", + "encodeURIComponent", + "escape", + "event", + "fileUpload", + "focus", + "form", + "forms", + "frame", + "innerHeight", + "innerWidth", + "layer", + "layers", + "link", + "location", + "mimeTypes", + "navigate", + "navigator", + "frames", + "frameRate", + "hidden", + "history", + "image", + "images", + "offscreenBuffering", + "open", + "opener", + "option", + "outerHeight", + "outerWidth", + "packages", + "pageXOffset", + "pageYOffset", + "parent", + "parseFloat", + "parseInt", + "password", + "pkcs11", + "plugin", + "prompt", + "propertyIsEnum", + "radio", + "reset", + "screenX", + "screenY", + "scroll", + "secure", + "select", + "self", + "setInterval", + "setTimeout", + "status", + "submit", + "taint", + "text", + "textarea", + "top", + "unescape", + "untaint", + "window", + + "onblur", + "onclick", + "onerror", + "onfocus", + "onkeydown", + "onkeypress", + "onkeyup", + "onmouseover", + "onload", + "onmouseup", + "onmousedown", + "onsubmit" + ]); + + // Set of already checked scopes + const alreadyCheckedScopes = new Set(); + + // get all global names + for (const info of modulesWithInfo) { + const superClassExpressions = []; + + // ignore symbols from moduleScope + if (info.moduleScope) { + alreadyCheckedScopes.add(info.moduleScope); + + // The super class expression in class scopes behaves weird + // We store ranges of all super class expressions to make + // renaming to work correctly + for (const childScope of info.moduleScope.childScopes) { + if (childScope.type !== "class") continue; + if (!childScope.block.superClass) continue; + superClassExpressions.push({ + range: childScope.block.superClass.range, + variables: childScope.variables + }); + } + } + + // add global symbols + if (info.globalScope) { + for (const reference of info.globalScope.through) { + const name = reference.identifier.name; + if ( + /^__WEBPACK_MODULE_REFERENCE__\d+_([\da-f]+|ns)(_call)?(_strict)?__$/.test( + name + ) + ) { + for (const expr of superClassExpressions) { + if ( + expr.range[0] <= reference.identifier.range[0] && + expr.range[1] >= reference.identifier.range[1] + ) { + for (const variable of expr.variables) { + allUsedNames.add(variable.name); + } + } + } + addScopeSymbols1( + reference.from, + allUsedNames, + alreadyCheckedScopes + ); + } else { + allUsedNames.add(name); + } + } + } + + // add exported globals + if (info.type === "concatenated") { + const variables = new Set(); + for (const variable of info.moduleScope.variables) { + variables.add(variable.name); + } + for (const [, variable] of info.exportMap) { + if (!variables.has(variable)) { + info.globalExports.add(variable); + } + } + } + } + + // generate names for symbols + for (const info of modulesWithInfo) { + switch (info.type) { + case "concatenated": { + const namespaceObjectName = this.findNewName( + "namespaceObject", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(namespaceObjectName); + info.internalNames.set(namespaceObjectName, namespaceObjectName); + info.exportMap.set(true, namespaceObjectName); + for (const variable of info.moduleScope.variables) { + const name = variable.name; + if (allUsedNames.has(name)) { + const references = getAllReferences(variable); + const symbolsInReferences = new Set(); + const alreadyCheckedInnerScopes = new Set(); + for (const ref of references) { + addScopeSymbols2( + ref.from, + symbolsInReferences, + alreadyCheckedInnerScopes, + alreadyCheckedScopes + ); + } + const newName = this.findNewName( + name, + allUsedNames, + symbolsInReferences, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(newName); + info.internalNames.set(name, newName); + const source = info.source; + const allIdentifiers = new Set( + references.map(r => r.identifier).concat(variable.identifiers) + ); + for (const identifier of allIdentifiers) { + const r = identifier.range; + const path = getPathInAst(info.ast, identifier); + if ( + path && + path.length > 1 && + path[1].type === "Property" && + path[1].shorthand + ) { + source.insert(r[1], `: ${newName}`); + } else { + source.replace(r[0], r[1] - 1, newName); + } + } + } else { + allUsedNames.add(name); + info.internalNames.set(name, name); + } + } + break; + } + case "external": { + const externalName = this.findNewName( + "", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalName); + info.name = externalName; + if ( + info.module.buildMeta.exportsType === "named" || + !info.module.buildMeta.exportsType + ) { + const externalNameInterop = this.findNewName( + "namespaceObject", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalNameInterop); + info.interopNamespaceObjectName = externalNameInterop; + } + if (!info.module.buildMeta.exportsType) { + const externalNameInterop = this.findNewName( + "default", + allUsedNames, + null, + info.module.readableIdentifier(requestShortener) + ); + allUsedNames.add(externalNameInterop); + info.interopDefaultAccessName = externalNameInterop; + } + break; + } + } + } + + // Find and replace referenced to modules + for (const info of modulesWithInfo) { + if (info.type === "concatenated") { + for (const reference of info.globalScope.through) { + const name = reference.identifier.name; + const match = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?(_strict)?__$/.exec( + name + ); + if (match) { + const referencedModule = modulesWithInfo[+match[1]]; + let exportName; + if (match[2] === "ns") { + exportName = true; + } else { + const exportData = match[2]; + exportName = Buffer.from(exportData, "hex").toString("utf-8"); + } + const asCall = !!match[3]; + const strictHarmonyModule = !!match[4]; + const finalName = getFinalName( + referencedModule, + exportName, + moduleToInfoMap, + requestShortener, + asCall, + strictHarmonyModule + ); + const r = reference.identifier.range; + const source = info.source; + source.replace(r[0], r[1] - 1, finalName); + } + } + } + } + + const result = new ConcatSource(); + + // add harmony compatibility flag (must be first because of possible circular dependencies) + const usedExports = this.rootModule.usedExports; + if (usedExports === true) { + result.add( + runtimeTemplate.defineEsModuleFlagStatement({ + exportsArgument: this.exportsArgument + }) + ); + } + + // define required namespace objects (must be before evaluation modules) + for (const info of modulesWithInfo) { + if (info.namespaceObjectSource) { + result.add(info.namespaceObjectSource); + } + } + + // evaluate modules in order + for (const info of modulesWithInfo) { + switch (info.type) { + case "concatenated": + result.add( + `\n// CONCATENATED MODULE: ${info.module.readableIdentifier( + requestShortener + )}\n` + ); + result.add(info.source); + break; + case "external": + result.add( + `\n// EXTERNAL MODULE: ${info.module.readableIdentifier( + requestShortener + )}\n` + ); + result.add( + `var ${info.name} = __webpack_require__(${JSON.stringify( + info.module.id + )});\n` + ); + if (info.interopNamespaceObjectUsed) { + if (info.module.buildMeta.exportsType === "named") { + result.add( + `var ${ + info.interopNamespaceObjectName + } = /*#__PURE__*/__webpack_require__.t(${info.name}, 2);\n` + ); + } else if (!info.module.buildMeta.exportsType) { + result.add( + `var ${ + info.interopNamespaceObjectName + } = /*#__PURE__*/__webpack_require__.t(${info.name});\n` + ); + } + } + if (info.interopDefaultAccessUsed) { + result.add( + `var ${ + info.interopDefaultAccessName + } = /*#__PURE__*/__webpack_require__.n(${info.name});\n` + ); + } + break; + default: + throw new Error(`Unsupported concatenation entry type ${info.type}`); + } + } + + return result; + } + + findNewName(oldName, usedNamed1, usedNamed2, extraInfo) { + let name = oldName; + + if (name === "__WEBPACK_MODULE_DEFAULT_EXPORT__") name = ""; + + // Remove uncool stuff + extraInfo = extraInfo.replace( + /\.+\/|(\/index)?\.([a-zA-Z0-9]{1,4})($|\s|\?)|\s*\+\s*\d+\s*modules/g, + "" + ); + + const splittedInfo = extraInfo.split("/"); + while (splittedInfo.length) { + name = splittedInfo.pop() + (name ? "_" + name : ""); + const nameIdent = Template.toIdentifier(name); + if ( + !usedNamed1.has(nameIdent) && + (!usedNamed2 || !usedNamed2.has(nameIdent)) + ) + return nameIdent; + } + + let i = 0; + let nameWithNumber = Template.toIdentifier(`${name}_${i}`); + while ( + usedNamed1.has(nameWithNumber) || + (usedNamed2 && usedNamed2.has(nameWithNumber)) + ) { + i++; + nameWithNumber = Template.toIdentifier(`${name}_${i}`); + } + return nameWithNumber; + } + + /** + * @param {Hash} hash the hash used to track dependencies + * @returns {void} + */ + updateHash(hash) { + for (const info of this._orderedConcatenationList) { + switch (info.type) { + case "concatenated": + info.module.updateHash(hash); + break; + case "external": + hash.update(`${info.module.id}`); + break; + } + } + super.updateHash(hash); + } +} + +class HarmonyImportSpecifierDependencyConcatenatedTemplate { + constructor(originalTemplate, modulesMap) { + this.originalTemplate = originalTemplate; + this.modulesMap = modulesMap; + } + + getHarmonyInitOrder(dep) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtimeTemplate, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtimeTemplate, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + return; + } + let content; + const callFlag = dep.call ? "_call" : ""; + const strictFlag = dep.originModule.buildMeta.strictHarmonyModule + ? "_strict" + : ""; + if (dep._id === null) { + content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__`; + } else if (dep.namespaceObjectAsContext) { + content = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_ns${strictFlag}__[${JSON.stringify(dep._id)}]`; + } else { + const exportData = Buffer.from(dep._id, "utf-8").toString("hex"); + content = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_${exportData}${callFlag}${strictFlag}__`; + } + if (dep.shorthand) { + content = dep.name + ": " + content; + } + source.replace(dep.range[0], dep.range[1] - 1, content); + } +} + +class HarmonyImportSideEffectDependencyConcatenatedTemplate { + constructor(originalTemplate, modulesMap) { + this.originalTemplate = originalTemplate; + this.modulesMap = modulesMap; + } + + getHarmonyInitOrder(dep) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + return; + } + } +} + +class HarmonyExportSpecifierDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + } + + getHarmonyInitOrder(dep) { + if (dep.originModule === this.rootModule) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtime, dependencyTemplates) { + if (dep.originModule === this.rootModule) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + if (dep.originModule === this.rootModule) { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + } + } +} + +class HarmonyExportExpressionDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + } + + apply(dep, source, runtime, dependencyTemplates) { + let content = + "/* harmony default export */ var __WEBPACK_MODULE_DEFAULT_EXPORT__ = "; + if (dep.originModule === this.rootModule) { + const used = dep.originModule.isUsed("default"); + const exportsName = dep.originModule.exportsArgument; + if (used) content += `${exportsName}[${JSON.stringify(used)}] = `; + } + + if (dep.range) { + source.replace(dep.rangeStatement[0], dep.range[0] - 1, content + "("); + source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");"); + return; + } + + source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content); + } +} + +class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule, modulesMap) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + this.modulesMap = modulesMap; + } + + getExports(dep) { + const importModule = dep._module; + if (dep.id) { + // export { named } from "module" + return [ + { + name: dep.name, + id: dep.id, + module: importModule + } + ]; + } + if (dep.name) { + // export * as abc from "module" + return [ + { + name: dep.name, + id: true, + module: importModule + } + ]; + } + // export * from "module" + return importModule.buildMeta.providedExports + .filter(exp => exp !== "default" && !dep.activeExports.has(exp)) + .map(exp => { + return { + name: exp, + id: exp, + module: importModule + }; + }); + } + + getHarmonyInitOrder(dep) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + return this.originalTemplate.getHarmonyInitOrder(dep); + } + return NaN; + } + + harmonyInit(dep, source, runtime, dependencyTemplates) { + const module = dep._module; + const info = this.modulesMap.get(module); + if (!info) { + this.originalTemplate.harmonyInit( + dep, + source, + runtime, + dependencyTemplates + ); + return; + } + } + + apply(dep, source, runtime, dependencyTemplates) { + if (dep.originModule === this.rootModule) { + if (this.modulesMap.get(dep._module)) { + const exportDefs = this.getExports(dep); + for (const def of exportDefs) { + const info = this.modulesMap.get(def.module); + const used = dep.originModule.isUsed(def.name); + if (!used) { + source.insert( + -1, + `/* unused concated harmony import ${def.name} */\n` + ); + continue; + } + let finalName; + const strictFlag = dep.originModule.buildMeta.strictHarmonyModule + ? "_strict" + : ""; + if (def.id === true) { + finalName = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_ns${strictFlag}__`; + } else { + const exportData = Buffer.from(def.id, "utf-8").toString("hex"); + finalName = `__WEBPACK_MODULE_REFERENCE__${ + info.index + }_${exportData}${strictFlag}__`; + } + const exportsName = this.rootModule.exportsArgument; + const content = + `/* concated harmony reexport ${def.name} */` + + `__webpack_require__.d(${exportsName}, ` + + `${JSON.stringify(used)}, ` + + `function() { return ${finalName}; });\n`; + source.insert(-1, content); + } + } else { + this.originalTemplate.apply(dep, source, runtime, dependencyTemplates); + } + } + } +} + +class HarmonyCompatibilityDependencyConcatenatedTemplate { + constructor(originalTemplate, rootModule, modulesMap) { + this.originalTemplate = originalTemplate; + this.rootModule = rootModule; + this.modulesMap = modulesMap; + } + + apply(dep, source, runtime, dependencyTemplates) { + // do nothing + } +} + +module.exports = ConcatenatedModule; |