Skip to content

Commit

Permalink
Merge pull request #12002 from webpack/bugfix/ns-consistency
Browse files Browse the repository at this point in the history
make visible exports from non-harmony modules more consistent
  • Loading branch information
sokra committed Nov 17, 2020
2 parents 5f686b6 + ac15f06 commit a17ad8e
Show file tree
Hide file tree
Showing 15 changed files with 432 additions and 84 deletions.
23 changes: 16 additions & 7 deletions lib/ContextModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -553,18 +553,26 @@ class ContextModule extends Module {
: "";
}

getReturn(type) {
getReturn(type, asyncModule) {
if (type === 9) {
return "__webpack_require__(id)";
}
return `${RuntimeGlobals.createFakeNamespaceObject}(id, ${type})`;
return `${RuntimeGlobals.createFakeNamespaceObject}(id, ${type}${
asyncModule ? " | 16" : ""
})`;
}

getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
getReturnModuleObjectSource(
fakeMap,
asyncModule,
fakeMapDataExpression = "fakeMap[id]"
) {
if (typeof fakeMap === "number") {
return `return ${this.getReturn(fakeMap)};`;
}
return `return ${RuntimeGlobals.createFakeNamespaceObject}(id, ${fakeMapDataExpression})`;
return `return ${
RuntimeGlobals.createFakeNamespaceObject
}(id, ${fakeMapDataExpression}${asyncModule ? " | 16" : ""})`;
}

/**
Expand Down Expand Up @@ -652,7 +660,7 @@ module.exports = webpackContext;`;
const arrow = runtimeTemplate.supportsArrowFunction();
const map = this.getUserRequestMap(dependencies, chunkGraph);
const fakeMap = this.getFakeMap(dependencies, chunkGraph);
const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
const returnModuleObject = this.getReturnModuleObjectSource(fakeMap, true);

return `var map = ${JSON.stringify(map, null, "\t")};
${this.getFakeMapInitStatement(fakeMap)}
Expand Down Expand Up @@ -755,7 +763,7 @@ module.exports = webpackAsyncContext;`;
const thenFunction =
fakeMap !== 9
? `${arrow ? "id =>" : "function(id)"} {
${this.getReturnModuleObjectSource(fakeMap)};
${this.getReturnModuleObjectSource(fakeMap, true)};
}`
: "__webpack_require__";

Expand Down Expand Up @@ -853,12 +861,13 @@ module.exports = webpackAsyncContext;`;
: `${RuntimeGlobals.ensureChunk}(ids[${chunksStartPosition}])`;
const returnModuleObject = this.getReturnModuleObjectSource(
fakeMap,
true,
shortMode ? "invalid" : "ids[1]"
);

const webpackAsyncContext =
requestPrefix === "Promise.resolve()"
? `${shortMode ? "" : ""}
? `
function webpackAsyncContext(req) {
return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
Expand Down
7 changes: 6 additions & 1 deletion lib/RuntimeTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ class RuntimeTemplate {
weak
});
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
let fakeType = 0;
let fakeType = 16;
switch (exportsType) {
case "namespace":
if (header) {
Expand Down Expand Up @@ -745,6 +745,11 @@ class RuntimeTemplate {
"/* non-default import from non-esm module */undefined" +
propertyAccess(exportName, 1)
);
} else if (
exportsType !== "namespace" &&
exportName[0] === "__esModule"
) {
return "/* __esModule */true";
}
} else if (
exportsType === "default-only" ||
Expand Down
62 changes: 44 additions & 18 deletions lib/optimize/ConcatenatedModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,29 @@ const getFinalBinding = (
case "namespace":
break;
case "default-with-named":
if (exportName[0] === "default") {
exportName = exportName.slice(1);
switch (exportName[0]) {
case "default":
exportName = exportName.slice(1);
break;
case "__esModule":
return {
info,
rawName: "/* __esModule */true",
ids: exportName.slice(1),
exportName
};
}
break;
case "default-only": {
const exportId = exportName[0];
if (exportId === "__esModule") {
return {
info,
rawName: "/* __esModule */true",
ids: exportName.slice(1),
exportName
};
}
exportName = exportName.slice(1);
if (exportId !== "default") {
return {
Expand All @@ -290,22 +307,31 @@ const getFinalBinding = (
break;
}
case "dynamic":
if (exportName[0] === "default") {
exportName = exportName.slice(1);
info.interopDefaultAccessUsed = true;
const defaultExport = asCall
? `${info.interopDefaultAccessName}()`
: asiSafe
? `(${info.interopDefaultAccessName}())`
: asiSafe === false
? `;(${info.interopDefaultAccessName}())`
: `${info.interopDefaultAccessName}.a`;
return {
info,
rawName: defaultExport,
ids: exportName,
exportName
};
switch (exportName[0]) {
case "default": {
exportName = exportName.slice(1);
info.interopDefaultAccessUsed = true;
const defaultExport = asCall
? `${info.interopDefaultAccessName}()`
: asiSafe
? `(${info.interopDefaultAccessName}())`
: asiSafe === false
? `;(${info.interopDefaultAccessName}())`
: `${info.interopDefaultAccessName}.a`;
return {
info,
rawName: defaultExport,
ids: exportName,
exportName
};
}
case "__esModule":
return {
info,
rawName: "/* __esModule */true",
ids: exportName.slice(1),
exportName
};
}
break;
default:
Expand Down
20 changes: 16 additions & 4 deletions lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,37 @@ class CreateFakeNamespaceObjectRuntimeModule extends HelperRuntimeModule {
runtimeTemplate.supportsConst();
const fn = RuntimeGlobals.createFakeNamespaceObject;
return Template.asString([
`var getProto = Object.getPrototypeOf ? ${runtimeTemplate.returningFunction(
"Object.getPrototypeOf(obj)",
"obj"
)} : ${runtimeTemplate.returningFunction("obj.__proto__", "obj")};`,
"var leafPrototypes;",
"// create a fake namespace object",
"// mode & 1: value is a module id, require it",
"// mode & 2: merge all properties of value into the ns",
"// mode & 4: return value when already ns object",
"// mode & 16: return value when it's Promise-like",
"// mode & 8|1: behave like require",
// Note: must be a function (not arrow), because this is used in body!
`${fn} = function(value, mode) {`,
Template.indent([
`if(mode & 1) value = this(value);`,
`if(mode & 8) return value;`,
"if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;",
"if(typeof value === 'object' && value) {",
Template.indent([
"if((mode & 4) && value.__esModule) return value;",
"if((mode & 16) && typeof value.then === 'function') return value;"
]),
"}",
"var ns = Object.create(null);",
`${RuntimeGlobals.makeNamespaceObject}(ns);`,
"var def = {};",
"if(mode & 2 && typeof value == 'object' && value) {",
"leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];",
"for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {",
Template.indent([
modern
? `for(const key in value) def[key] = () => value[key];`
: `for(var key in value) def[key] = function(key) { return value[key]; }.bind(null, key);`
? `Object.getOwnPropertyNames(current).forEach(key => def[key] = () => value[key]);`
: `Object.getOwnPropertyNames(current).forEach(function(key) { def[key] = function() { return value[key]; }; });`
]),
"}",
modern
Expand Down
8 changes: 4 additions & 4 deletions test/Stats.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ describe("Stats", () => {
"assets": Array [
Object {
"name": "entryB.js",
"size": 2706,
"size": 2910,
},
],
"assetsSize": 2706,
"assetsSize": 2910,
"auxiliaryAssets": undefined,
"auxiliaryAssetsSize": 0,
"childAssets": undefined,
Expand Down Expand Up @@ -221,10 +221,10 @@ describe("Stats", () => {
"info": Object {
"javascriptModule": false,
"minimized": true,
"size": 2706,
"size": 2910,
},
"name": "entryB.js",
"size": 2706,
"size": 2910,
"type": "asset",
},
Object {
Expand Down

0 comments on commit a17ad8e

Please sign in to comment.