2015-10-22 03:05:01 +08:00
|
|
|
/*
|
|
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
|
|
Author Tobias Koppers @sokra
|
|
|
|
*/
|
2017-01-05 02:04:43 +08:00
|
|
|
"use strict";
|
2017-08-08 15:32:43 +08:00
|
|
|
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
|
|
|
const Template = require("../Template");
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
2017-10-10 03:13:18 +08:00
|
|
|
constructor(request, originModule, sourceOrder, parserScope, id, name, activeExports, otherStarExports) {
|
2017-08-08 15:32:43 +08:00
|
|
|
super(request, originModule, sourceOrder, parserScope);
|
2017-01-05 02:04:43 +08:00
|
|
|
this.id = id;
|
|
|
|
this.name = name;
|
2017-10-09 21:28:59 +08:00
|
|
|
this.activeExports = activeExports;
|
|
|
|
this.otherStarExports = otherStarExports;
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
get type() {
|
|
|
|
return "harmony export imported specifier";
|
|
|
|
}
|
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
getMode(ignoreUnused) {
|
2017-01-05 02:04:43 +08:00
|
|
|
const name = this.name;
|
2017-08-08 15:32:43 +08:00
|
|
|
const id = this.id;
|
2017-01-05 02:04:43 +08:00
|
|
|
const used = this.originModule.isUsed(name);
|
2017-08-08 15:32:43 +08:00
|
|
|
const importedModule = this.module;
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
if(!importedModule) {
|
|
|
|
return {
|
|
|
|
type: "missing",
|
|
|
|
userRequest: this.userRequest
|
|
|
|
};
|
|
|
|
}
|
2017-08-27 08:05:57 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
if(!ignoreUnused && (!used || !this.originModule.usedExports)) {
|
|
|
|
return {
|
|
|
|
type: "unused",
|
|
|
|
name: name || "*"
|
|
|
|
};
|
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
const isNotAHarmonyModule = importedModule.meta && !importedModule.meta.harmonyModule;
|
|
|
|
if(name && id === "default" && isNotAHarmonyModule) {
|
|
|
|
return {
|
|
|
|
type: "reexport-non-harmony-default",
|
|
|
|
module: importedModule,
|
|
|
|
name
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if(name) {
|
2017-01-05 02:04:43 +08:00
|
|
|
// export { name as name }
|
2017-08-08 15:32:43 +08:00
|
|
|
if(id) {
|
2017-01-05 02:04:43 +08:00
|
|
|
return {
|
2017-08-08 15:32:43 +08:00
|
|
|
type: "safe-reexport",
|
2017-01-05 02:04:43 +08:00
|
|
|
module: importedModule,
|
2017-08-08 15:32:43 +08:00
|
|
|
map: new Map([
|
|
|
|
[name, id]
|
|
|
|
])
|
2017-01-05 02:04:43 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// export { * as name }
|
|
|
|
return {
|
2017-08-08 15:32:43 +08:00
|
|
|
type: "reexport-namespace-object",
|
2017-01-05 02:04:43 +08:00
|
|
|
module: importedModule,
|
2017-08-08 15:32:43 +08:00
|
|
|
name
|
2017-01-05 02:04:43 +08:00
|
|
|
};
|
|
|
|
}
|
2015-10-22 03:05:01 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
const hasUsedExports = Array.isArray(this.originModule.usedExports);
|
2017-08-27 08:05:57 +08:00
|
|
|
const hasProvidedExports = Array.isArray(importedModule.providedExports);
|
2017-10-09 21:28:59 +08:00
|
|
|
const activeFromOtherStarExports = this._discoverActiveExportsFromOtherStartExports();
|
2017-08-27 08:05:57 +08:00
|
|
|
|
2016-08-17 17:24:35 +08:00
|
|
|
// export *
|
2017-08-27 08:05:57 +08:00
|
|
|
if(hasUsedExports) {
|
2016-08-17 17:24:35 +08:00
|
|
|
// reexport * with known used exports
|
2017-08-08 15:32:43 +08:00
|
|
|
if(hasProvidedExports) {
|
|
|
|
const map = new Map(this.originModule.usedExports.filter((id) => {
|
2017-10-10 03:13:18 +08:00
|
|
|
if(id === "default") return false;
|
|
|
|
if(this.activeExports.has(id)) return false;
|
|
|
|
if(activeFromOtherStarExports.has(id)) return false;
|
|
|
|
if(importedModule.providedExports.indexOf(id) < 0) return false;
|
|
|
|
|
|
|
|
return true;
|
2017-08-08 15:32:43 +08:00
|
|
|
}).map(item => [item, item]));
|
|
|
|
|
|
|
|
if(map.size === 0) {
|
|
|
|
return {
|
|
|
|
type: "empty-star"
|
|
|
|
};
|
2017-08-27 08:05:57 +08:00
|
|
|
}
|
2017-08-08 15:32:43 +08:00
|
|
|
|
|
|
|
return {
|
|
|
|
type: "safe-reexport",
|
|
|
|
module: importedModule,
|
|
|
|
map
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
const map = new Map(this.originModule.usedExports.filter(id => {
|
2017-10-09 21:28:59 +08:00
|
|
|
if(id === "default") return false;
|
|
|
|
if(this.activeExports.has(id)) return false;
|
|
|
|
if(activeFromOtherStarExports.has(id)) return false;
|
|
|
|
|
|
|
|
return true;
|
2017-08-08 15:32:43 +08:00
|
|
|
}).map(item => [item, item]));
|
|
|
|
|
|
|
|
if(map.size === 0) {
|
|
|
|
return {
|
|
|
|
type: "empty-star"
|
|
|
|
};
|
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2016-08-17 17:24:35 +08:00
|
|
|
return {
|
2017-08-08 15:32:43 +08:00
|
|
|
type: "checked-reexport",
|
2017-01-05 02:04:43 +08:00
|
|
|
module: importedModule,
|
2017-08-08 15:32:43 +08:00
|
|
|
map
|
2017-01-11 17:51:58 +08:00
|
|
|
};
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
2017-08-27 08:05:57 +08:00
|
|
|
if(hasProvidedExports) {
|
2017-08-08 15:32:43 +08:00
|
|
|
const map = new Map(importedModule.providedExports
|
2017-10-10 03:13:18 +08:00
|
|
|
.filter(id => {
|
2017-10-09 21:28:59 +08:00
|
|
|
if(id === "default") return false;
|
|
|
|
if(this.activeExports.has(id)) return false;
|
|
|
|
if(activeFromOtherStarExports.has(id)) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
})
|
2017-08-08 15:32:43 +08:00
|
|
|
.map(item => [item, item])
|
|
|
|
);
|
|
|
|
|
|
|
|
if(map.size === 0) {
|
|
|
|
return {
|
|
|
|
type: "empty-star"
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-08-17 17:24:35 +08:00
|
|
|
return {
|
2017-08-08 15:32:43 +08:00
|
|
|
type: "safe-reexport",
|
2017-01-05 02:04:43 +08:00
|
|
|
module: importedModule,
|
2017-08-08 15:32:43 +08:00
|
|
|
map
|
2017-01-11 17:51:58 +08:00
|
|
|
};
|
2016-08-17 17:24:35 +08:00
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
|
|
|
return {
|
2017-08-08 15:32:43 +08:00
|
|
|
type: "dynamic-reexport",
|
|
|
|
module: importedModule
|
2017-01-11 17:51:58 +08:00
|
|
|
};
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
getReference() {
|
|
|
|
const mode = this.getMode();
|
|
|
|
|
|
|
|
switch(mode.type) {
|
|
|
|
case "missing":
|
|
|
|
case "unused":
|
|
|
|
case "empty-star":
|
|
|
|
return null;
|
|
|
|
|
|
|
|
case "reexport-non-harmony-default":
|
|
|
|
return {
|
|
|
|
module: mode.module,
|
|
|
|
importedNames: ["default"]
|
|
|
|
};
|
|
|
|
|
|
|
|
case "reexport-namespace-object":
|
|
|
|
return {
|
|
|
|
module: mode.module,
|
|
|
|
importedNames: true
|
|
|
|
};
|
|
|
|
|
|
|
|
case "safe-reexport":
|
|
|
|
case "checked-reexport":
|
|
|
|
return {
|
|
|
|
module: mode.module,
|
|
|
|
importedNames: Array.from(mode.map.values())
|
|
|
|
};
|
|
|
|
|
|
|
|
case "dynamic-reexport":
|
|
|
|
return {
|
|
|
|
module: mode.module,
|
|
|
|
importedNames: true
|
|
|
|
};
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw new Error(`Unknown mode ${mode.type}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-09 21:28:59 +08:00
|
|
|
_discoverActiveExportsFromOtherStartExports() {
|
|
|
|
if(!this.otherStarExports)
|
|
|
|
return new Set();
|
|
|
|
const result = new Set();
|
|
|
|
// try to learn impossible exports from other star exports with provided exports
|
|
|
|
for(const otherStarExport of this.otherStarExports) {
|
2017-10-10 03:13:18 +08:00
|
|
|
const otherImportedModule = otherStarExport.module;
|
2017-10-09 21:28:59 +08:00
|
|
|
if(Array.isArray(otherImportedModule.providedExports)) {
|
|
|
|
for(const exportName of otherImportedModule.providedExports)
|
|
|
|
result.add(exportName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-01-05 02:04:43 +08:00
|
|
|
getExports() {
|
|
|
|
if(this.name) {
|
2016-08-17 17:24:35 +08:00
|
|
|
return {
|
2017-01-05 02:04:43 +08:00
|
|
|
exports: [this.name]
|
2017-01-11 17:51:58 +08:00
|
|
|
};
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
const importedModule = this.module;
|
2017-01-05 02:04:43 +08:00
|
|
|
|
|
|
|
if(!importedModule) {
|
|
|
|
// no imported module available
|
|
|
|
return {
|
|
|
|
exports: null
|
2016-08-17 17:24:35 +08:00
|
|
|
};
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if(Array.isArray(importedModule.providedExports)) {
|
2016-08-17 17:24:35 +08:00
|
|
|
return {
|
2017-01-05 02:04:43 +08:00
|
|
|
exports: importedModule.providedExports.filter(id => id !== "default"),
|
|
|
|
dependencies: [importedModule]
|
2016-08-17 17:24:35 +08:00
|
|
|
};
|
|
|
|
}
|
2015-12-23 23:24:45 +08:00
|
|
|
|
2017-01-05 02:04:43 +08:00
|
|
|
if(importedModule.providedExports) {
|
|
|
|
return {
|
|
|
|
exports: true
|
|
|
|
};
|
2016-09-06 05:41:03 +08:00
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2016-09-06 05:41:03 +08:00
|
|
|
return {
|
2017-01-05 02:04:43 +08:00
|
|
|
exports: null,
|
|
|
|
dependencies: [importedModule]
|
2016-09-06 05:41:03 +08:00
|
|
|
};
|
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
|
|
|
updateHash(hash) {
|
|
|
|
super.updateHash(hash);
|
2017-08-08 15:32:43 +08:00
|
|
|
const hashValue = this.getHashValue(this.module);
|
2017-01-05 02:04:43 +08:00
|
|
|
hash.update(hashValue);
|
2016-09-06 05:41:03 +08:00
|
|
|
}
|
|
|
|
|
2017-01-05 02:04:43 +08:00
|
|
|
getHashValue(importedModule) {
|
|
|
|
if(!importedModule) {
|
2017-02-24 06:57:49 +08:00
|
|
|
return "";
|
2016-12-05 06:16:33 +08:00
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
|
|
|
const stringifiedUsedExport = JSON.stringify(importedModule.usedExports);
|
|
|
|
const stringifiedProvidedExport = JSON.stringify(importedModule.providedExports);
|
|
|
|
return importedModule.used + stringifiedUsedExport + stringifiedProvidedExport;
|
2016-12-05 06:16:33 +08:00
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = HarmonyExportImportedSpecifierDependency;
|
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
|
|
|
|
harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
|
|
|
super.harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
|
|
|
const importVar = dep.getImportVar(requestShortener);
|
|
|
|
const content = this.getContent(dep, importVar);
|
2017-01-05 02:04:43 +08:00
|
|
|
source.insert(-1, content);
|
2016-02-17 05:31:12 +08:00
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
getHarmonyInitOrder(dep) {
|
2017-01-05 02:04:43 +08:00
|
|
|
const used = dep.originModule.isUsed(dep.name);
|
2017-08-08 15:32:43 +08:00
|
|
|
if(!used) return NaN;
|
|
|
|
if(!dep.name) {
|
|
|
|
const importedModule = dep.module;
|
|
|
|
|
|
|
|
if(Array.isArray(dep.originModule.usedExports)) {
|
|
|
|
// we know which exports are used
|
|
|
|
|
|
|
|
const unused = dep.originModule.usedExports.every(function(id) {
|
|
|
|
if(id === "default") return true;
|
2017-10-10 03:13:18 +08:00
|
|
|
if(dep.activeExports.has(id)) return true;
|
2017-08-08 15:32:43 +08:00
|
|
|
if(importedModule.isProvided(id) === false) return true;
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
if(unused) return NaN;
|
|
|
|
|
|
|
|
} else if(dep.originModule.usedExports && importedModule && Array.isArray(importedModule.providedExports)) {
|
|
|
|
// not sure which exports are used, but we know which are provided
|
|
|
|
|
|
|
|
const unused = importedModule.providedExports.every(function(id) {
|
|
|
|
if(id === "default") return true;
|
2017-10-10 03:13:18 +08:00
|
|
|
if(dep.activeExports.has(id)) return true;
|
2017-08-08 15:32:43 +08:00
|
|
|
return false;
|
|
|
|
});
|
|
|
|
if(unused) return NaN;
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
}
|
2017-08-08 15:32:43 +08:00
|
|
|
return super.getHarmonyInitOrder(dep);
|
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
getContent(dep, name) {
|
|
|
|
const mode = dep.getMode();
|
|
|
|
const module = dep.originModule;
|
|
|
|
const importedModule = dep.module;
|
|
|
|
const importVar = dep.getImportVar();
|
|
|
|
|
|
|
|
switch(mode.type) {
|
|
|
|
case "missing":
|
|
|
|
return `throw new Error(${JSON.stringify(`Cannot find module '${mode.userRequest}'`)});\n`;
|
|
|
|
|
|
|
|
case "unused":
|
|
|
|
return `${Template.toNormalComment(`unused harmony reexport ${mode.name}`)}\n`;
|
|
|
|
|
|
|
|
case "reexport-non-harmony-default":
|
|
|
|
return "/* harmony reexport (default from non-hamory) */ " + this.getReexportStatement(module, module.isUsed(mode.name), importVar, null);
|
|
|
|
|
|
|
|
case "reexport-namespace-object":
|
|
|
|
return "/* harmony reexport (module object) */ " + this.getReexportStatement(module, module.isUsed(mode.name), importVar, "");
|
|
|
|
|
|
|
|
case "empty-star":
|
|
|
|
return "/* empty/unused harmony star reexport */";
|
|
|
|
|
|
|
|
case "safe-reexport":
|
|
|
|
return Array.from(mode.map.entries()).map(item => {
|
|
|
|
return "/* harmony reexport (safe) */ " + this.getReexportStatement(module, module.isUsed(item[0]), importVar, importedModule.isUsed(item[1])) + "\n";
|
|
|
|
}).join("");
|
|
|
|
|
|
|
|
case "checked-reexport":
|
|
|
|
return Array.from(mode.map.entries()).map(item => {
|
|
|
|
return "/* harmony reexport (checked) */ " + this.getConditionalReexportStatement(module, item[0], importVar, item[1]) + "\n";
|
|
|
|
}).join("");
|
|
|
|
|
|
|
|
case "dynamic-reexport":
|
|
|
|
{
|
2017-10-10 03:13:18 +08:00
|
|
|
const activeExports = Array.from(dep.activeExports).concat(dep._discoverActiveExportsFromOtherStartExports());
|
2017-08-08 15:32:43 +08:00
|
|
|
let content = "/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " + importVar + ") ";
|
|
|
|
|
|
|
|
// Filter out exports which are defined by other exports
|
|
|
|
// and filter out default export because it cannot be reexported with *
|
|
|
|
if(activeExports.length > 0)
|
|
|
|
content += "if(" + JSON.stringify(activeExports.concat("default")) + ".indexOf(__WEBPACK_IMPORT_KEY__) < 0) ";
|
|
|
|
else
|
|
|
|
content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') ";
|
|
|
|
const exportsName = dep.originModule.exportsArgument || "exports";
|
|
|
|
return content + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${name}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`;
|
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
default:
|
|
|
|
throw new Error(`Unknown mode ${mode.type}`);
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
2015-10-22 03:05:01 +08:00
|
|
|
}
|
2017-01-05 02:04:43 +08:00
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
getReexportStatement(module, key, name, valueKey) {
|
2017-01-11 17:51:58 +08:00
|
|
|
const exportsName = module.exportsArgument || "exports";
|
2017-08-08 15:32:43 +08:00
|
|
|
const returnValue = this.getReturnValue(valueKey);
|
|
|
|
return `__webpack_require__.d(${exportsName}, ${JSON.stringify(key)}, function() { return ${name}${returnValue}; });\n`;
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
getConditionalReexportStatement(module, key, name, valueKey) {
|
|
|
|
const exportsName = module.exportsArgument || "exports";
|
|
|
|
const returnValue = this.getReturnValue(valueKey);
|
|
|
|
return `if(__webpack_require__.o(${name}, ${JSON.stringify(valueKey)})) __webpack_require__.d(${exportsName}, ${JSON.stringify(key)}, function() { return ${name}${returnValue}; });\n`;
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
getReturnValue(valueKey) {
|
|
|
|
if(valueKey === null) {
|
|
|
|
return "_default.a";
|
|
|
|
}
|
|
|
|
|
2017-08-08 15:32:43 +08:00
|
|
|
return valueKey && "[" + JSON.stringify(valueKey) + "]";
|
2017-01-05 02:04:43 +08:00
|
|
|
}
|
2017-01-11 17:51:58 +08:00
|
|
|
};
|