conflict-free handling of global in import-script

use destructuring when available
This commit is contained in:
Tobias Koppers 2020-08-28 01:44:56 +02:00
parent 3c94cad7f1
commit 6928a65911
7 changed files with 348 additions and 315 deletions

View File

@ -178,6 +178,7 @@
"boolish",
"analysing",
"etags",
"destructure",
"webassemblyjs",
"fsevents",

View File

@ -75,6 +75,10 @@ class RuntimeTemplate {
return this.outputOptions.ecmaVersion >= 6;
}
supportsDestructing() {
return this.outputOptions.ecmaVersion >= 6;
}
returningFunction(returnValue, args = "") {
return this.supportsArrowFunction()
? `(${args}) => ${returnValue}`
@ -87,6 +91,14 @@ class RuntimeTemplate {
: `function(${args}) {\n${Template.indent(body)}\n}`;
}
destructureArray(items, value) {
return this.supportsDestructing()
? `var [${items.join(", ")}] = ${value};`
: Template.asString(
items.map((item, i) => `var ${item} = ${value}[${i}];`)
);
}
iife(args, body) {
return `(${this.basicFunction(args, body)})()`;
}

View File

@ -424,50 +424,58 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
withDefer || withLoading
? Template.asString([
"// install a JSONP callback for chunk loading",
"function webpackJsonpCallback(data) {",
Template.indent([
"var chunkIds = data[0];",
"var moreModules = data[1];",
"var runtime = data[2];",
withDefer ? "var executeModules = data[3];" : "",
'// add "moreModules" to the modules object,',
'// then flag all "chunkIds" as loaded and fire callback',
"var moduleId, chunkId, i = 0, resolves = [];",
"for(;i < chunkIds.length; i++) {",
Template.indent([
"chunkId = chunkIds[i];",
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
Template.indent("resolves.push(installedChunks[chunkId][0]);"),
"}",
"installedChunks[chunkId] = 0;"
]),
"}",
"for(moduleId in moreModules) {",
Template.indent([
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent(
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
`var webpackJsonpCallback = ${runtimeTemplate.basicFunction(
"data",
[
runtimeTemplate.destructureArray(
[
"chunkIds",
"moreModules",
"runtime",
...(withDefer ? ["executeModules"] : [])
],
"data"
),
"}"
]),
"}",
"if(runtime) runtime(__webpack_require__);",
"if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);",
"while(resolves.length) {",
Template.indent("resolves.shift()();"),
"}",
withDefer
? Template.asString([
"",
"// add entry modules from loaded chunk to deferred list",
"if(executeModules) deferredModules.push.apply(deferredModules, executeModules);",
"",
"// run deferred modules when all chunks ready",
"return checkDeferredModules();"
])
: ""
]),
"};",
'// add "moreModules" to the modules object,',
'// then flag all "chunkIds" as loaded and fire callback',
"var moduleId, chunkId, i = 0, resolves = [];",
"for(;i < chunkIds.length; i++) {",
Template.indent([
"chunkId = chunkIds[i];",
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
Template.indent(
"resolves.push(installedChunks[chunkId][0]);"
),
"}",
"installedChunks[chunkId] = 0;"
]),
"}",
"for(moduleId in moreModules) {",
Template.indent([
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent(
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
),
"}"
]),
"}",
"if(runtime) runtime(__webpack_require__);",
"parentChunkLoadingFunction(data);",
"while(resolves.length) {",
Template.indent("resolves.shift()();"),
"}",
withDefer
? Template.asString([
"",
"// add entry modules from loaded chunk to deferred list",
"if(executeModules) deferredModules.push.apply(deferredModules, executeModules);",
"",
"// run deferred modules when all chunks ready",
"return checkDeferredModules();"
])
: ""
]
)}`,
"",
`var chunkLoadingGlobal = ${chunkLoadingGlobalExpr} = ${chunkLoadingGlobalExpr} || [];`,
"var parentChunkLoadingFunction = chunkLoadingGlobal.push.bind(chunkLoadingGlobal);",

View File

@ -39,6 +39,9 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
const withHmrManifest = this.runtimeRequirements.has(
RuntimeGlobals.hmrDownloadManifest
);
const chunkLoadingGlobalExpr = `${globalObject}[${JSON.stringify(
chunkLoadingGlobal
)}]`;
const outputName = this.compilation.getPath(
getChunkFilenameTemplate(chunk, this.compilation.outputOptions),
{
@ -59,25 +62,28 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
withLoading
? Template.asString([
"// importScripts chunk loading",
`${globalObject}[${JSON.stringify(
chunkLoadingGlobal
)}] = { push: ${runtimeTemplate.basicFunction("data", [
"var chunkIds = data[0];",
"var moreModules = data[1];",
"var runtime = data[2];",
"for(var moduleId in moreModules) {",
Template.indent([
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent(
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
`var chunkLoadingCallback = ${runtimeTemplate.basicFunction(
"data",
[
runtimeTemplate.destructureArray(
["chunkIds", "moreModules", "runtime"],
"data"
),
"}"
]),
"}",
"if(runtime) runtime(__webpack_require__);",
"while(chunkIds.length)",
Template.indent("installedChunks[chunkIds.pop()] = 1;")
])} };`,
"for(var moduleId in moreModules) {",
Template.indent([
`if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
Template.indent(
`${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
),
"}"
]),
"}",
"if(runtime) runtime(__webpack_require__);",
"while(chunkIds.length)",
Template.indent("installedChunks[chunkIds.pop()] = 1;"),
"parentChunkLoadingFunction(data);"
]
)};`,
`${fn}.i = ${runtimeTemplate.basicFunction("chunkId, promises", [
'// "1" is the signal for "already loaded"',
"if(!installedChunks[chunkId]) {",
@ -87,7 +93,11 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
}(chunkId));`
]),
"}"
])};`
])};`,
"",
`var chunkLoadingGlobal = ${chunkLoadingGlobalExpr} = ${chunkLoadingGlobalExpr} || [];`,
"var parentChunkLoadingFunction = chunkLoadingGlobal.push.bind(chunkLoadingGlobal);",
"chunkLoadingGlobal.push = chunkLoadingCallback;"
])
: "// no chunk loading",
"",

View File

@ -225,10 +225,10 @@ describe("Stats", () => {
"filteredRelated": undefined,
"info": Object {
"minimized": true,
"size": 2207,
"size": 2185,
},
"name": "entryB.js",
"size": 2207,
"size": 2185,
"type": "asset",
},
],

File diff suppressed because it is too large Load Diff

2
types.d.ts vendored
View File

@ -7406,8 +7406,10 @@ declare abstract class RuntimeTemplate {
supportsConst(): boolean;
supportsArrowFunction(): boolean;
supportsForOf(): boolean;
supportsDestructing(): boolean;
returningFunction(returnValue?: any, args?: string): string;
basicFunction(args?: any, body?: any): string;
destructureArray(items?: any, value?: any): string;
iife(args?: any, body?: any): string;
forEach(variable?: any, array?: any, body?: any): string;