UNPKG

4.63 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8/** @typedef {import("./Module")} Module */
9
10const MODULE_REFERENCE_REGEXP = /^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?(_directImport)?(?:_asiSafe(\d))?__$/;
11
12const DEFAULT_EXPORT = "__WEBPACK_DEFAULT_EXPORT__";
13const NAMESPACE_OBJECT_EXPORT = "__WEBPACK_NAMESPACE_OBJECT__";
14
15/**
16 * @typedef {Object} ExternalModuleInfo
17 * @property {number} index
18 * @property {Module} module
19 */
20
21/**
22 * @typedef {Object} ConcatenatedModuleInfo
23 * @property {number} index
24 * @property {Module} module
25 * @property {Map<string, string>} exportMap mapping from export name to symbol
26 * @property {Map<string, string>} rawExportMap mapping from export name to symbol
27 * @property {string=} namespaceExportSymbol
28 */
29
30/** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo} ModuleInfo */
31
32/**
33 * @typedef {Object} ModuleReferenceOptions
34 * @property {string[]} ids the properties/exports of the module
35 * @property {boolean} call true, when this referenced export is called
36 * @property {boolean} directImport true, when this referenced export is directly imported (not via property access)
37 * @property {boolean | undefined} asiSafe if the position is ASI safe or unknown
38 */
39
40class ConcatenationScope {
41 /**
42 * @param {ModuleInfo[] | Map<Module, ModuleInfo>} modulesMap all module info by module
43 * @param {ConcatenatedModuleInfo} currentModule the current module info
44 */
45 constructor(modulesMap, currentModule) {
46 this._currentModule = currentModule;
47 if (Array.isArray(modulesMap)) {
48 const map = new Map();
49 for (const info of modulesMap) {
50 map.set(info.module, info);
51 }
52 modulesMap = map;
53 }
54 this._modulesMap = modulesMap;
55 }
56
57 /**
58 * @param {Module} module the referenced module
59 * @returns {boolean} true, when it's in the scope
60 */
61 isModuleInScope(module) {
62 return this._modulesMap.has(module);
63 }
64
65 /**
66 *
67 * @param {string} exportName name of the export
68 * @param {string} symbol identifier of the export in source code
69 */
70 registerExport(exportName, symbol) {
71 if (!this._currentModule.exportMap) {
72 this._currentModule.exportMap = new Map();
73 }
74 if (!this._currentModule.exportMap.has(exportName)) {
75 this._currentModule.exportMap.set(exportName, symbol);
76 }
77 }
78
79 /**
80 *
81 * @param {string} exportName name of the export
82 * @param {string} expression expression to be used
83 */
84 registerRawExport(exportName, expression) {
85 if (!this._currentModule.rawExportMap) {
86 this._currentModule.rawExportMap = new Map();
87 }
88 if (!this._currentModule.rawExportMap.has(exportName)) {
89 this._currentModule.rawExportMap.set(exportName, expression);
90 }
91 }
92
93 /**
94 * @param {string} symbol identifier of the export in source code
95 */
96 registerNamespaceExport(symbol) {
97 this._currentModule.namespaceExportSymbol = symbol;
98 }
99
100 /**
101 *
102 * @param {Module} module the referenced module
103 * @param {Partial<ModuleReferenceOptions>} options options
104 * @returns {string} the reference as identifier
105 */
106 createModuleReference(
107 module,
108 { ids = undefined, call = false, directImport = false, asiSafe = false }
109 ) {
110 const info = this._modulesMap.get(module);
111 const callFlag = call ? "_call" : "";
112 const directImportFlag = directImport ? "_directImport" : "";
113 const asiSafeFlag = asiSafe
114 ? "_asiSafe1"
115 : asiSafe === false
116 ? "_asiSafe0"
117 : "";
118 const exportData = ids
119 ? Buffer.from(JSON.stringify(ids), "utf-8").toString("hex")
120 : "ns";
121 // a "._" is appended to allow "delete ...", which would cause a SyntaxError in strict mode
122 return `__WEBPACK_MODULE_REFERENCE__${info.index}_${exportData}${callFlag}${directImportFlag}${asiSafeFlag}__._`;
123 }
124
125 /**
126 * @param {string} name the identifier
127 * @returns {boolean} true, when it's an module reference
128 */
129 static isModuleReference(name) {
130 return MODULE_REFERENCE_REGEXP.test(name);
131 }
132
133 /**
134 * @param {string} name the identifier
135 * @returns {ModuleReferenceOptions & { index: number }} parsed options and index
136 */
137 static matchModuleReference(name) {
138 const match = MODULE_REFERENCE_REGEXP.exec(name);
139 if (!match) return null;
140 const index = +match[1];
141 const asiSafe = match[5];
142 return {
143 index,
144 ids:
145 match[2] === "ns"
146 ? []
147 : JSON.parse(Buffer.from(match[2], "hex").toString("utf-8")),
148 call: !!match[3],
149 directImport: !!match[4],
150 asiSafe: asiSafe ? asiSafe === "1" : undefined
151 };
152 }
153}
154
155ConcatenationScope.DEFAULT_EXPORT = DEFAULT_EXPORT;
156ConcatenationScope.NAMESPACE_OBJECT_EXPORT = NAMESPACE_OBJECT_EXPORT;
157
158module.exports = ConcatenationScope;