Skip to content

Commit

Permalink
remove error for CommonJs/AMD in ESM
Browse files Browse the repository at this point in the history
there are too many weird modules

detect harmony modules before parsing
exports is now undefined in ESM
module.exports is now read-only in ESM and returns undefined
define is now undefined in ESM
webpack#3917
  • Loading branch information
sokra committed Jan 15, 2017
1 parent f745f02 commit a7a4184
Show file tree
Hide file tree
Showing 30 changed files with 178 additions and 181 deletions.
30 changes: 30 additions & 0 deletions buildin/harmony-module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = function(originalModule) {
if(!originalModule.webpackPolyfill) {
var module = Object.create(originalModule);
// module.parent = undefined by default
if(!module.children) module.children = [];
Object.defineProperty(module, "loaded", {
enumerable: true,
configurable: false,
get: function() {
return module.l;
}
});
Object.defineProperty(module, "id", {
enumerable: true,
configurable: false,
get: function() {
return module.i;
}
});
Object.defineProperty(module, "exports", {
enumerable: true,
configurable: false,
get: function() {
return undefined;
}
});
module.webpackPolyfill = 1;
}
return module;
};
2 changes: 1 addition & 1 deletion lib/FunctionModuleTemplatePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = FunctionModuleTemplatePlugin;
FunctionModuleTemplatePlugin.prototype.apply = function(moduleTemplate) {
moduleTemplate.plugin("render", function(moduleSource, module) {
var source = new ConcatSource();
var defaultArguments = ["module", "exports"];
var defaultArguments = [module.moduleArgument || "module", module.exportsArgument || "exports"];
if((module.arguments && module.arguments.length !== 0) || module.hasDependencies(d => d.requireWebpackRequire !== false)) {
defaultArguments.push("__webpack_require__");
}
Expand Down
17 changes: 10 additions & 7 deletions lib/NodeStuffPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ NodeStuffPlugin.prototype.apply = function(compiler) {
if(parserOptions.node)
localOptions = Object.assign({}, localOptions, parserOptions.node);

function ignore() {
return true;
}

function setConstant(expressionName, value) {
parser.plugin("expression " + expressionName, function() {
this.state.current.addVariable(expressionName, JSON.stringify(value));
Expand Down Expand Up @@ -98,13 +94,20 @@ NodeStuffPlugin.prototype.apply = function(compiler) {
this.state.current.addDependency(dep);
return true;
});
parser.plugin("expression module.exports", ignore);
parser.plugin("expression module.exports", function() {
var module = this.state.module;
var isHarmony = module.meta && module.meta.harmonyModule;
if(!isHarmony)
return true;
});
parser.plugin("evaluate Identifier module.hot", function(expr) {
return new BasicEvaluatedExpression().setBoolean(false).setRange(expr.range);
});
parser.plugin("expression module", function() {
var moduleJsPath = path.join(__dirname, "..", "buildin", "module.js");
if(this.state.module.context) {
var module = this.state.module;
var isHarmony = module.meta && module.meta.harmonyModule;
var moduleJsPath = path.join(__dirname, "..", "buildin", isHarmony ? "harmony-module.js" : "module.js");
if(module.context) {
moduleJsPath = path.relative(this.state.module.context, moduleJsPath);
if(!/^[A-Z]:/i.test(moduleJsPath)) {
moduleJsPath = "./" + moduleJsPath.replace(/\\/g, "/");
Expand Down
8 changes: 5 additions & 3 deletions lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ AMDRequireDependenciesBlockParserPlugin.prototype.apply = function(parser) {
} else if(param.isString()) {
var dep, localModule;
if(param.string === "require") {
dep = new ConstDependency("__webpack_require__", param.string);
} else if(["exports", "module"].indexOf(param.string) >= 0) {
dep = new ConstDependency(param.string, param.range);
dep = new ConstDependency("__webpack_require__", param.range);
} else if(param.string === "module") {
dep = new ConstDependency(this.state.module.moduleArgument || "module", param.range);
} else if(param.string === "exports") {
dep = new ConstDependency(this.state.module.exportsArgument || "exports", param.range);
} else if(localModule = LocalModulesHelpers.getLocalModule(this.state, param.string)) { // eslint-disable-line no-cond-assign
dep = new LocalModuleDependency(localModule, param.range);
} else {
Expand Down
36 changes: 0 additions & 36 deletions lib/dependencies/CommonJsInHarmonyDependency.js

This file was deleted.

37 changes: 0 additions & 37 deletions lib/dependencies/CommonJsInHarmonyDependencyParserPlugin.js

This file was deleted.

18 changes: 0 additions & 18 deletions lib/dependencies/CommonJsInHarmonyWarning.js

This file was deleted.

1 change: 1 addition & 0 deletions lib/dependencies/CommonJsPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Author Tobias Koppers @sokra
*/
"use strict";

var ConstDependency = require("./ConstDependency");
var CommonJsRequireDependency = require("./CommonJsRequireDependency");
var CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
Expand Down
3 changes: 2 additions & 1 deletion lib/dependencies/HarmonyCompatiblilityDependency.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ HarmonyCompatiblilityDependency.Template = class HarmonyExportDependencyTemplate
apply(dep, source) {
const usedExports = dep.originModule.usedExports;
if(usedExports && !Array.isArray(usedExports)) {
const content = "Object.defineProperty(exports, \"__esModule\", { value: true });\n";
const exportName = dep.originModule.exportsArgument || "exports";
const content = `Object.defineProperty(${exportName}, \"__esModule\", { value: true });\n`;
source.insert(-1, content);
}
}
Expand Down
56 changes: 56 additions & 0 deletions lib/dependencies/HarmonyDetectionParserPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";

const HarmonyCompatiblilityDependency = require("./HarmonyCompatiblilityDependency");

module.exports = class HarmonyDetectionParserPlugin {
apply(parser) {
parser.plugin("program", (ast) => {
var isHarmony = ast.body.some(statement => {
return /^(Import|Export).*Declaration$/.test(statement.type);
});
if(isHarmony) {
let module = parser.state.module;
const dep = new HarmonyCompatiblilityDependency(module);
dep.loc = {
start: {
line: -1,
column: 0
},
end: {
line: -1,
column: 0
},
index: -2
};
module.addDependency(dep);
module.meta.harmonyModule = true;
module.strict = true;
module.exportsArgument = "__webpack_exports__";
}
});
var nonHarmonyIdentifiers = ["define", "exports"];
nonHarmonyIdentifiers.forEach(identifer => {
parser.plugin(`evaluate typeof ${identifer}`, nullInHarmony);
parser.plugin(`typeof ${identifer}`, skipInHarmony);
parser.plugin(`evaluate ${identifer}`, nullInHarmony);
parser.plugin(`expression ${identifer}`, skipInHarmony);
parser.plugin(`call ${identifer}`, skipInHarmony);
});

function skipInHarmony() {
let module = this.state.module;
if(module && module.meta && module.meta.harmonyModule)
return true;
}

function nullInHarmony() {
let module = this.state.module;
if(module && module.meta && module.meta.harmonyModule)
return null;
}
}
};
15 changes: 0 additions & 15 deletions lib/dependencies/HarmonyExportDependencyParserPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,24 @@
*/
"use strict";

const HarmonyCompatiblilityDependency = require("./HarmonyCompatiblilityDependency");
const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
const HarmonyImportDependency = require("./HarmonyImportDependency");
const HarmonyModulesHelpers = require("./HarmonyModulesHelpers");

function makeHarmonyModule(module, loc) {
if(!module.meta.harmonyModule) {
const dep = new HarmonyCompatiblilityDependency(module);
dep.loc = Object.create(loc);
dep.loc.index = -2;
module.addDependency(dep);
module.meta.harmonyModule = true;
module.strict = true;
}
}

module.exports = class HarmonyExportDependencyParserPlugin {
apply(parser) {
parser.plugin("export", statement => {
const dep = new HarmonyExportHeaderDependency(statement.declaration && statement.declaration.range, statement.range);
makeHarmonyModule(parser.state.module, statement.loc);
dep.loc = Object.create(statement.loc);
dep.loc.index = -1;
parser.state.current.addDependency(dep);
return true;
});
parser.plugin("export import", (statement, source) => {
const dep = new HarmonyImportDependency(source, HarmonyModulesHelpers.getNewModuleVar(parser.state, source), statement.range);
makeHarmonyModule(parser.state.module, statement.loc);
dep.loc = Object.create(statement.loc);
dep.loc.index = -1;
parser.state.current.addDependency(dep);
Expand All @@ -47,7 +33,6 @@ module.exports = class HarmonyExportDependencyParserPlugin {
dep.loc = Object.create(statement.loc);
dep.loc.index = -1;
parser.state.current.addDependency(dep);
parser.state.module.strict = true;
return true;
});
parser.plugin("export declaration", statement => {});
Expand Down
7 changes: 4 additions & 3 deletions lib/dependencies/HarmonyExportExpressionDependency.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class HarmonyExportExpressionDependency extends NullDependency {
HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTemplate {
apply(dep, source) {
const used = dep.originModule.isUsed("default");
const content = this.getContent(used);
const content = this.getContent(dep.originModule, used);

if(dep.range) {
source.replace(dep.rangeStatement[0], dep.range[0] - 1, content);
Expand All @@ -45,9 +45,10 @@ HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTempla
source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content);
}

getContent(used) {
getContent(module, used) {
const exportsName = module.exportsArgument || "exports";
if(used) {
return `/* harmony default export */ exports[${JSON.stringify(used)}] = `;
return `/* harmony default export */ ${exportsName}[${JSON.stringify(used)}] = `;
}
return "/* unused harmony default export */ var _unused_webpack_default_export = ";
}
Expand Down
10 changes: 6 additions & 4 deletions lib/dependencies/HarmonyExportImportedSpecifierDependency.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
const active = HarmonyModulesHelpers.isActive(dep.originModule, dep);
const importsExportsUnknown = !importedModule || !Array.isArray(importedModule.providedExports);

const getReexportStatement = this.reexportStatementCreator(importsExportsUnknown, name);
const getReexportStatement = this.reexportStatementCreator(dep.originModule, importsExportsUnknown, name);

// we want to rexport something, but the export isn't used
if(!used) {
Expand Down Expand Up @@ -251,17 +251,19 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
content += "if(" + JSON.stringify(activeExports.concat("default")) + ".indexOf(__WEBPACK_IMPORT_KEY__) < 0) ";
else
content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') ";
return content + "(function(key) { __webpack_require__.d(exports, key, function() { return " + name + "[key]; }) }(__WEBPACK_IMPORT_KEY__));\n";
const exportsName = dep.originModule.exportsArgument || "exports";
return content + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${name}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`;
}

return "/* unused harmony reexport namespace */\n";
}

reexportStatementCreator(importsExportsUnknown, name) {
reexportStatementCreator(module, importsExportsUnknown, name) {
const exportsName = module.exportsArgument || "exports";
const getReexportStatement = (key, valueKey) => {
const conditional = this.getConditional(importsExportsUnknown, valueKey, name);
const returnValue = this.getReturnValue(valueKey);
return `${conditional}__webpack_require__.d(exports, ${key}, function() { return ${name}${returnValue}; });\n`;
return `${conditional}__webpack_require__.d(${exportsName}, ${key}, function() { return ${name}${returnValue}; });\n`;
};
return getReexportStatement;
}
Expand Down
5 changes: 3 additions & 2 deletions lib/dependencies/HarmonyExportSpecifierDependency.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependen
return `/* inactive harmony export ${(dep.name || "namespace")} */\n`;
}

const exportsName = dep.originModule.exportsArgument || "exports";
if(dep.immutable) {
return `/* harmony export (immutable) */ exports[${JSON.stringify(used)}] = ${dep.id};\n`;
return `/* harmony export (immutable) */ ${exportsName}[${JSON.stringify(used)}] = ${dep.id};\n`;
}

return `/* harmony export (binding) */ __webpack_require__.d(exports, ${JSON.stringify(used)}, function() { return ${dep.id}; });\n`;
return `/* harmony export (binding) */ __webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${dep.id}; });\n`;
}
};

Expand Down
Loading

0 comments on commit a7a4184

Please sign in to comment.