Skip to content

Commit a926a19

Browse files
committed
create better namespace objects
avoid using Object.assign (fixes webpack#7162)
1 parent 00f77fd commit a926a19

File tree

33 files changed

+322
-245
lines changed

33 files changed

+322
-245
lines changed

lib/ContextModule.js

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ class ContextModule extends Module {
253253
}
254254

255255
getFakeMap(dependencies) {
256-
if (!this.options.namespaceObject) return 1;
256+
if (!this.options.namespaceObject) return 9;
257257
// if we filter first we get a new array
258258
// therefor we dont need to create a clone of dependencies explicitly
259259
// therefore the order of this is !important!
@@ -268,20 +268,24 @@ class ContextModule extends Module {
268268
.reduce((map, dep) => {
269269
const exportsType =
270270
dep.module.buildMeta && dep.module.buildMeta.exportsType;
271-
if (!exportsType) hasNonHarmony = true;
272-
if (exportsType === "namespace") hasNamespace = true;
273-
if (exportsType === "named") hasNamed = true;
274-
map[dep.module.id] =
275-
{
276-
namespace: 1,
277-
named: 2
278-
}[exportsType] || 0;
271+
const id = dep.module.id;
272+
if (!exportsType) {
273+
map[id] = this.options.namespaceObject === "strict" ? 1 : 7;
274+
hasNonHarmony = true;
275+
} else if (exportsType === "namespace") {
276+
map[id] = 9;
277+
hasNamespace = true;
278+
} else if (exportsType === "named") {
279+
map[id] = 3;
280+
hasNamed = true;
281+
}
279282
return map;
280283
}, Object.create(null));
281-
if (!hasNamespace && hasNonHarmony && !hasNamed) return 0;
282-
if (hasNamespace && !hasNonHarmony && !hasNamed) return 1;
283-
if (!hasNamespace && !hasNonHarmony && hasNamed) return 2;
284-
if (!hasNamespace && !hasNonHarmony && !hasNamed) return 1;
284+
if (!hasNamespace && hasNonHarmony && !hasNamed)
285+
return this.options.namespaceObject === "strict" ? 1 : 7;
286+
if (hasNamespace && !hasNonHarmony && !hasNamed) return 9;
287+
if (!hasNamespace && !hasNonHarmony && hasNamed) return 3;
288+
if (!hasNamespace && !hasNonHarmony && !hasNamed) return 9;
285289
return fakeMap;
286290
}
287291

@@ -292,26 +296,14 @@ class ContextModule extends Module {
292296
}
293297

294298
getReturn(type) {
295-
if (type === 1) return "module";
296-
if (type === 2)
297-
return 'Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module })';
298-
if (type === 0) {
299-
if (this.options.namespaceObject === "strict") {
300-
return '/* fake namespace object */ { "default": module }';
301-
} else {
302-
return '(typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }))';
303-
}
304-
}
299+
if (type === 9) return "__webpack_require__(id)";
300+
return `__webpack_require__.t(id, ${type})`;
305301
}
306302

307303
getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
308304
if (typeof fakeMap === "number")
309305
return `return ${this.getReturn(fakeMap)};`;
310-
return `return ${fakeMapDataExpression} === 1 ? ${this.getReturn(
311-
1
312-
)} : ${fakeMapDataExpression} ? ${this.getReturn(2)} : ${this.getReturn(
313-
0
314-
)};`;
306+
return `return __webpack_require__.t(id, ${fakeMapDataExpression})`;
315307
}
316308

317309
getSyncSource(dependencies, id) {
@@ -324,7 +316,6 @@ ${this.getFakeMapInitStatement(fakeMap)}
324316
325317
function webpackContext(req) {
326318
var id = webpackContextResolve(req);
327-
var module = __webpack_require__(id);
328319
${returnModuleObject}
329320
}
330321
function webpackContextResolve(req) {
@@ -359,7 +350,6 @@ function webpackContext(req) {
359350
e.code = 'MODULE_NOT_FOUND';
360351
throw e;
361352
}
362-
var module = __webpack_require__(id);
363353
${returnModuleObject}
364354
}
365355
function webpackContextResolve(req) {
@@ -394,7 +384,6 @@ function webpackAsyncContext(req) {
394384
e.code = 'MODULE_NOT_FOUND';
395385
throw e;
396386
}
397-
var module = __webpack_require__(id);
398387
${returnModuleObject}
399388
});
400389
}
@@ -423,11 +412,10 @@ module.exports = webpackAsyncContext;`;
423412
const map = this.getUserRequestMap(dependencies);
424413
const fakeMap = this.getFakeMap(dependencies);
425414
const thenFunction =
426-
fakeMap !== 1
415+
fakeMap !== 9
427416
? `function(id) {
428-
var module = __webpack_require__(id);
429-
${this.getReturnModuleObjectSource(fakeMap)}
430-
}`
417+
${this.getReturnModuleObjectSource(fakeMap)}
418+
}`
431419
: "__webpack_require__";
432420
return `var map = ${JSON.stringify(map, null, "\t")};
433421
${this.getFakeMapInitStatement(fakeMap)}
@@ -464,9 +452,8 @@ module.exports = webpackAsyncContext;`;
464452
const map = this.getUserRequestMap(dependencies);
465453
const fakeMap = this.getFakeMap(dependencies);
466454
const thenFunction =
467-
fakeMap !== 1
455+
fakeMap !== 9
468456
? `function(id) {
469-
var module = __webpack_require__(id);
470457
${this.getReturnModuleObjectSource(fakeMap)};
471458
}`
472459
: "__webpack_require__";
@@ -546,7 +533,7 @@ function webpackAsyncContext(req) {
546533
});
547534
}
548535
return ${requestPrefix}.then(function() {
549-
var module = __webpack_require__(ids[0]);
536+
var id = ids[0];
550537
${returnModuleObject}
551538
});
552539
}

lib/MainTemplate.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const Template = require("./Template");
2828
// __webpack_require__.d = the exported property define getter function
2929
// __webpack_require__.o = Object.prototype.hasOwnProperty.call
3030
// __webpack_require__.r = define compatibility on export
31+
// __webpack_require__.t = create a fake namespace object
3132
// __webpack_require__.n = compatibility get default export
3233
// __webpack_require__.h = the webpack hash
3334
// __webpack_require__.w = an object containing all installed WebAssembly.Modules keys by module id
@@ -235,13 +236,7 @@ module.exports = class MainTemplate extends Tapable {
235236
Template.indent([
236237
`if(!${this.requireFn}.o(exports, name)) {`,
237238
Template.indent([
238-
"Object.defineProperty(exports, name, {",
239-
Template.indent([
240-
"configurable: false,",
241-
"enumerable: true,",
242-
"get: getter"
243-
]),
244-
"});"
239+
"Object.defineProperty(exports, name, { enumerable: true, get: getter });"
245240
]),
246241
"}"
247242
])
@@ -253,11 +248,40 @@ module.exports = class MainTemplate extends Tapable {
253248
buf.push(`${this.requireFn}.r = function(exports) {`);
254249
buf.push(
255250
Template.indent([
251+
"if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {",
252+
Template.indent([
253+
"Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });"
254+
]),
255+
"}",
256256
"Object.defineProperty(exports, '__esModule', { value: true });"
257257
])
258258
);
259259
buf.push("};");
260260

261+
buf.push("");
262+
buf.push("// create a fake namespace object");
263+
buf.push("// mode & 1: value is a module id, require it");
264+
buf.push("// mode & 2: merge all properties of value into the ns");
265+
buf.push("// mode & 4: return value when already ns object");
266+
buf.push("// mode & 8|1: behave like require");
267+
buf.push(`${this.requireFn}.t = function(value, mode) {`);
268+
buf.push(
269+
Template.indent([
270+
`if(mode & 1) value = ${this.requireFn}(value);`,
271+
`if(mode & 8) return value;`,
272+
"if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;",
273+
"var ns = Object.create(null);",
274+
`${this.requireFn}.r(ns);`,
275+
"Object.defineProperty(ns, 'default', { enumerable: true, value: value });",
276+
"if(mode & 2 && typeof value != 'string') for(var key in value) " +
277+
`${this.requireFn}.d(ns, key, function(key) { ` +
278+
"return value[key]; " +
279+
"}.bind(null, key));",
280+
"return ns;"
281+
])
282+
);
283+
buf.push("};");
284+
261285
buf.push("");
262286
buf.push(
263287
"// getDefaultExport function for compatibility with non-harmony modules"

lib/RuntimeTemplate.js

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,27 @@ module.exports = class RuntimeTemplate {
8888
}
8989

9090
moduleNamespace({ module, request, strict }) {
91-
const rawModule = this.moduleRaw({
91+
if (!module)
92+
return this.missingModule({
93+
request
94+
});
95+
const moduleId = this.moduleId({
9296
module,
9397
request
9498
});
9599
const exportsType = module.buildMeta && module.buildMeta.exportsType;
96100
if (exportsType === "namespace") {
101+
const rawModule = this.moduleRaw({
102+
module,
103+
request
104+
});
97105
return rawModule;
98106
} else if (exportsType === "named") {
99-
return `Object.assign({/* fake namespace object */}, ${rawModule}, { "default": ${rawModule} })`;
107+
return `__webpack_require__.t(${moduleId}, 3)`;
100108
} else if (strict) {
101-
return `Object({ /* fake namespace object */ "default": ${rawModule} })`;
109+
return `__webpack_require__.t(${moduleId}, 1)`;
102110
} else {
103-
return `Object(function() { var module = ${rawModule}; return typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }); }())`;
111+
return `__webpack_require__.t(${moduleId}, 7)`;
104112
}
105113
}
106114

@@ -128,23 +136,39 @@ module.exports = class RuntimeTemplate {
128136
}
129137
header += `if(!__webpack_require__.m[${idExpr}]) { var e = new Error("Module '" + ${idExpr} + "' is not available (weak dependency)"); e.code = 'MODULE_NOT_FOUND'; throw e; } `;
130138
}
131-
const rawModule = this.moduleRaw({
139+
const moduleId = this.moduleId({
132140
module,
133141
request
134142
});
135143
const exportsType = module.buildMeta && module.buildMeta.exportsType;
136144
if (exportsType === "namespace") {
137145
if (header) {
146+
const rawModule = this.moduleRaw({
147+
module,
148+
request
149+
});
138150
getModuleFunction = `function() { ${header}return ${rawModule}; }`;
139151
} else {
140152
getModuleFunction = `__webpack_require__.bind(null, ${comment}${idExpr})`;
141153
}
142154
} else if (exportsType === "named") {
143-
getModuleFunction = `function() { ${header}var module = ${rawModule}; return Object.assign({/* fake namespace object */}, module, { "default": module }); }`;
155+
if (header) {
156+
getModuleFunction = `function() { ${header}return __webpack_require__.t(${moduleId}, 3); }`;
157+
} else {
158+
getModuleFunction = `__webpack_require__.t.bind(null, ${comment}${idExpr}, 3)`;
159+
}
144160
} else if (strict) {
145-
getModuleFunction = `function() { ${header}return { /* fake namespace object */ "default": ${rawModule} }; }`;
161+
if (header) {
162+
getModuleFunction = `function() { ${header}return __webpack_require__.t(${moduleId}, 1); }`;
163+
} else {
164+
getModuleFunction = `__webpack_require__.t.bind(null, ${comment}${idExpr}, 1)`;
165+
}
146166
} else {
147-
getModuleFunction = `function() { ${header}var module = ${rawModule}; return typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }); }`;
167+
if (header) {
168+
getModuleFunction = `function() { ${header}return __webpack_require__.t(${moduleId}, 7); }`;
169+
} else {
170+
getModuleFunction = `__webpack_require__.t.bind(null, ${comment}${idExpr}, 7)`;
171+
}
148172
}
149173

150174
return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`;
@@ -155,24 +179,23 @@ module.exports = class RuntimeTemplate {
155179
return this.missingModuleStatement({
156180
request
157181
});
158-
const comment = this.comment({
182+
const moduleId = this.moduleId({
183+
module,
159184
request
160185
});
161186
const optDeclaration = update ? "" : "var ";
162187

163188
const exportsType = module.buildMeta && module.buildMeta.exportsType;
164-
let content = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${comment}${JSON.stringify(
165-
module.id
166-
)});\n`;
189+
let content = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${moduleId});\n`;
167190

168191
if (!exportsType && !originModule.buildMeta.strictHarmonyModule) {
169192
content += `/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/__webpack_require__.n(${importVar});\n`;
170193
}
171194
if (exportsType === "named") {
172195
if (Array.isArray(module.buildMeta.providedExports))
173-
content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/Object.assign({}, ${importVar}, {"default": ${importVar}});\n`;
196+
content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/__webpack_require__.t(${moduleId}, 1);\n`;
174197
else
175-
content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/{ /* fake namespace object */ "default": ${importVar} };\n`;
198+
content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/__webpack_require__.t(${moduleId});\n`;
176199
}
177200
return content;
178201
}
@@ -206,11 +229,7 @@ module.exports = class RuntimeTemplate {
206229
if (exportName) {
207230
return "/* non-default import from non-esm module */undefined";
208231
} else {
209-
if (asiSafe) {
210-
return `/*#__PURE__*/{ /* fake namespace object */ "default": ${importVar} }`;
211-
} else {
212-
return `/*#__PURE__*/Object({ /* fake namespace object */ "default": ${importVar} })`;
213-
}
232+
return `/*#__PURE__*/__webpack_require__.t(${importVar})`;
214233
}
215234
}
216235
}

lib/dependencies/HarmonyExportImportedSpecifierDependency.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
580580
const exportsName = module.exportsArgument;
581581
return `__webpack_require__.d(${exportsName}, ${JSON.stringify(
582582
key
583-
)}, function() { return { "default": ${name} }; });\n`;
583+
)}, function() { return __webpack_require__.t(${name}); });\n`;
584584
}
585585

586586
getConditionalReexportStatement(module, key, name, valueKey) {

lib/optimize/ConcatenatedModule.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const ensureNsObjSource = (
2727
if (!info.hasNamespaceObject) {
2828
info.hasNamespaceObject = true;
2929
const name = info.exportMap.get(true);
30-
const nsObj = [`var ${name} = {};`];
30+
const nsObj = [`var ${name} = {};`, `__webpack_require__.r(${name});`];
3131
for (const exportName of info.module.buildMeta.providedExports) {
3232
const finalName = getFinalName(
3333
info,
@@ -1059,17 +1059,13 @@ class ConcatenatedModule extends Module {
10591059
result.add(
10601060
`var ${
10611061
info.interopNamespaceObjectName
1062-
} = /*#__PURE__*/Object.assign({ /* fake namespace object */ }, ${
1063-
info.name
1064-
}, { "default": ${info.name} });\n`
1062+
} = /*#__PURE__*/__webpack_require__.t(${info.name}, 2);\n`
10651063
);
10661064
} else if (!info.module.buildMeta.exportsType) {
10671065
result.add(
10681066
`var ${
10691067
info.interopNamespaceObjectName
1070-
} = /*#__PURE__*/{ /* fake namespace object */ "default": ${
1071-
info.name
1072-
} };\n`
1068+
} = /*#__PURE__*/__webpack_require__.t(${info.name});\n`
10731069
);
10741070
}
10751071
}

0 commit comments

Comments
 (0)