first commit
This commit is contained in:
413
app_vue/node_modules/webpack/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js
generated
vendored
Normal file
413
app_vue/node_modules/webpack/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js
generated
vendored
Normal file
@ -0,0 +1,413 @@
|
||||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const RuntimeModule = require("../RuntimeModule");
|
||||
const Template = require("../Template");
|
||||
const { compareModulesByIdentifier } = require("../util/comparators");
|
||||
const WebAssemblyUtils = require("./WebAssemblyUtils");
|
||||
|
||||
/** @typedef {import("@webassemblyjs/ast").Signature} Signature */
|
||||
/** @typedef {import("../Chunk")} Chunk */
|
||||
/** @typedef {import("../ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("../ChunkGraph").ModuleId} ModuleId */
|
||||
/** @typedef {import("../Compilation")} Compilation */
|
||||
/** @typedef {import("../Module")} Module */
|
||||
/** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
|
||||
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
||||
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
|
||||
|
||||
// TODO webpack 6 remove the whole folder
|
||||
|
||||
// Get all wasm modules
|
||||
/**
|
||||
* @param {ModuleGraph} moduleGraph the module graph
|
||||
* @param {ChunkGraph} chunkGraph the chunk graph
|
||||
* @param {Chunk} chunk the chunk
|
||||
* @returns {Module[]} all wasm modules
|
||||
*/
|
||||
const getAllWasmModules = (moduleGraph, chunkGraph, chunk) => {
|
||||
const wasmModules = chunk.getAllAsyncChunks();
|
||||
const array = [];
|
||||
for (const chunk of wasmModules) {
|
||||
for (const m of chunkGraph.getOrderedChunkModulesIterable(
|
||||
chunk,
|
||||
compareModulesByIdentifier
|
||||
)) {
|
||||
if (m.type.startsWith("webassembly")) {
|
||||
array.push(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
/**
|
||||
* generates the import object function for a module
|
||||
* @param {ChunkGraph} chunkGraph the chunk graph
|
||||
* @param {Module} module the module
|
||||
* @param {boolean | undefined} mangle mangle imports
|
||||
* @param {string[]} declarations array where declarations are pushed to
|
||||
* @param {RuntimeSpec} runtime the runtime
|
||||
* @returns {string} source code
|
||||
*/
|
||||
const generateImportObject = (
|
||||
chunkGraph,
|
||||
module,
|
||||
mangle,
|
||||
declarations,
|
||||
runtime
|
||||
) => {
|
||||
const moduleGraph = chunkGraph.moduleGraph;
|
||||
/** @type {Map<string, string | number>} */
|
||||
const waitForInstances = new Map();
|
||||
const properties = [];
|
||||
const usedWasmDependencies = WebAssemblyUtils.getUsedDependencies(
|
||||
moduleGraph,
|
||||
module,
|
||||
mangle
|
||||
);
|
||||
for (const usedDep of usedWasmDependencies) {
|
||||
const dep = usedDep.dependency;
|
||||
const importedModule = moduleGraph.getModule(dep);
|
||||
const exportName = dep.name;
|
||||
const usedName =
|
||||
importedModule &&
|
||||
moduleGraph
|
||||
.getExportsInfo(importedModule)
|
||||
.getUsedName(exportName, runtime);
|
||||
const description = dep.description;
|
||||
const direct = dep.onlyDirectImport;
|
||||
|
||||
const module = usedDep.module;
|
||||
const name = usedDep.name;
|
||||
|
||||
if (direct) {
|
||||
const instanceVar = `m${waitForInstances.size}`;
|
||||
waitForInstances.set(
|
||||
instanceVar,
|
||||
/** @type {ModuleId} */
|
||||
(chunkGraph.getModuleId(/** @type {Module} */ (importedModule)))
|
||||
);
|
||||
properties.push({
|
||||
module,
|
||||
name,
|
||||
value: `${instanceVar}[${JSON.stringify(usedName)}]`
|
||||
});
|
||||
} else {
|
||||
const params =
|
||||
/** @type {Signature} */
|
||||
(description.signature).params.map(
|
||||
(param, k) => `p${k}${param.valtype}`
|
||||
);
|
||||
|
||||
const mod = `${RuntimeGlobals.moduleCache}[${JSON.stringify(
|
||||
chunkGraph.getModuleId(/** @type {Module} */ (importedModule))
|
||||
)}]`;
|
||||
const modExports = `${mod}.exports`;
|
||||
|
||||
const cache = `wasmImportedFuncCache${declarations.length}`;
|
||||
declarations.push(`var ${cache};`);
|
||||
|
||||
const modCode =
|
||||
/** @type {Module} */
|
||||
(importedModule).type.startsWith("webassembly")
|
||||
? `${mod} ? ${modExports}[${JSON.stringify(usedName)}] : `
|
||||
: "";
|
||||
|
||||
properties.push({
|
||||
module,
|
||||
name,
|
||||
value: Template.asString([
|
||||
`${modCode}function(${params}) {`,
|
||||
Template.indent([
|
||||
`if(${cache} === undefined) ${cache} = ${modExports};`,
|
||||
`return ${cache}[${JSON.stringify(usedName)}](${params});`
|
||||
]),
|
||||
"}"
|
||||
])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let importObject;
|
||||
if (mangle) {
|
||||
importObject = [
|
||||
"return {",
|
||||
Template.indent([
|
||||
properties.map(p => `${JSON.stringify(p.name)}: ${p.value}`).join(",\n")
|
||||
]),
|
||||
"};"
|
||||
];
|
||||
} else {
|
||||
/** @type {Map<string, Array<{ name: string, value: string }>>} */
|
||||
const propertiesByModule = new Map();
|
||||
for (const p of properties) {
|
||||
let list = propertiesByModule.get(p.module);
|
||||
if (list === undefined) {
|
||||
propertiesByModule.set(p.module, (list = []));
|
||||
}
|
||||
list.push(p);
|
||||
}
|
||||
importObject = [
|
||||
"return {",
|
||||
Template.indent([
|
||||
Array.from(propertiesByModule, ([module, list]) =>
|
||||
Template.asString([
|
||||
`${JSON.stringify(module)}: {`,
|
||||
Template.indent([
|
||||
list.map(p => `${JSON.stringify(p.name)}: ${p.value}`).join(",\n")
|
||||
]),
|
||||
"}"
|
||||
])
|
||||
).join(",\n")
|
||||
]),
|
||||
"};"
|
||||
];
|
||||
}
|
||||
|
||||
const moduleIdStringified = JSON.stringify(chunkGraph.getModuleId(module));
|
||||
if (waitForInstances.size === 1) {
|
||||
const moduleId = Array.from(waitForInstances.values())[0];
|
||||
const promise = `installedWasmModules[${JSON.stringify(moduleId)}]`;
|
||||
const variable = Array.from(waitForInstances.keys())[0];
|
||||
return Template.asString([
|
||||
`${moduleIdStringified}: function() {`,
|
||||
Template.indent([
|
||||
`return promiseResolve().then(function() { return ${promise}; }).then(function(${variable}) {`,
|
||||
Template.indent(importObject),
|
||||
"});"
|
||||
]),
|
||||
"},"
|
||||
]);
|
||||
} else if (waitForInstances.size > 0) {
|
||||
const promises = Array.from(
|
||||
waitForInstances.values(),
|
||||
id => `installedWasmModules[${JSON.stringify(id)}]`
|
||||
).join(", ");
|
||||
const variables = Array.from(
|
||||
waitForInstances.keys(),
|
||||
(name, i) => `${name} = array[${i}]`
|
||||
).join(", ");
|
||||
return Template.asString([
|
||||
`${moduleIdStringified}: function() {`,
|
||||
Template.indent([
|
||||
`return promiseResolve().then(function() { return Promise.all([${promises}]); }).then(function(array) {`,
|
||||
Template.indent([`var ${variables};`, ...importObject]),
|
||||
"});"
|
||||
]),
|
||||
"},"
|
||||
]);
|
||||
}
|
||||
return Template.asString([
|
||||
`${moduleIdStringified}: function() {`,
|
||||
Template.indent(importObject),
|
||||
"},"
|
||||
]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {object} WasmChunkLoadingRuntimeModuleOptions
|
||||
* @property {(path: string) => string} generateLoadBinaryCode
|
||||
* @property {boolean=} supportsStreaming
|
||||
* @property {boolean=} mangleImports
|
||||
* @property {ReadOnlyRuntimeRequirements} runtimeRequirements
|
||||
*/
|
||||
|
||||
class WasmChunkLoadingRuntimeModule extends RuntimeModule {
|
||||
/**
|
||||
* @param {WasmChunkLoadingRuntimeModuleOptions} options options
|
||||
*/
|
||||
constructor({
|
||||
generateLoadBinaryCode,
|
||||
supportsStreaming,
|
||||
mangleImports,
|
||||
runtimeRequirements
|
||||
}) {
|
||||
super("wasm chunk loading", RuntimeModule.STAGE_ATTACH);
|
||||
this.generateLoadBinaryCode = generateLoadBinaryCode;
|
||||
this.supportsStreaming = supportsStreaming;
|
||||
this.mangleImports = mangleImports;
|
||||
this._runtimeRequirements = runtimeRequirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string | null} runtime code
|
||||
*/
|
||||
generate() {
|
||||
const fn = RuntimeGlobals.ensureChunkHandlers;
|
||||
const withHmr = this._runtimeRequirements.has(
|
||||
RuntimeGlobals.hmrDownloadUpdateHandlers
|
||||
);
|
||||
const compilation = /** @type {Compilation} */ (this.compilation);
|
||||
const { moduleGraph, outputOptions } = compilation;
|
||||
const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
|
||||
const chunk = /** @type {Chunk} */ (this.chunk);
|
||||
const wasmModules = getAllWasmModules(moduleGraph, chunkGraph, chunk);
|
||||
const { mangleImports } = this;
|
||||
/** @type {string[]} */
|
||||
const declarations = [];
|
||||
const importObjects = wasmModules.map(module =>
|
||||
generateImportObject(
|
||||
chunkGraph,
|
||||
module,
|
||||
mangleImports,
|
||||
declarations,
|
||||
chunk.runtime
|
||||
)
|
||||
);
|
||||
const chunkModuleIdMap = chunkGraph.getChunkModuleIdMap(chunk, m =>
|
||||
m.type.startsWith("webassembly")
|
||||
);
|
||||
/**
|
||||
* @param {string} content content
|
||||
* @returns {string} created import object
|
||||
*/
|
||||
const createImportObject = content =>
|
||||
mangleImports
|
||||
? `{ ${JSON.stringify(WebAssemblyUtils.MANGLED_MODULE)}: ${content} }`
|
||||
: content;
|
||||
const wasmModuleSrcPath = compilation.getPath(
|
||||
JSON.stringify(outputOptions.webassemblyModuleFilename),
|
||||
{
|
||||
hash: `" + ${RuntimeGlobals.getFullHash}() + "`,
|
||||
hashWithLength: length =>
|
||||
`" + ${RuntimeGlobals.getFullHash}}().slice(0, ${length}) + "`,
|
||||
module: {
|
||||
id: '" + wasmModuleId + "',
|
||||
hash: `" + ${JSON.stringify(
|
||||
chunkGraph.getChunkModuleRenderedHashMap(chunk, m =>
|
||||
m.type.startsWith("webassembly")
|
||||
)
|
||||
)}[chunkId][wasmModuleId] + "`,
|
||||
hashWithLength(length) {
|
||||
return `" + ${JSON.stringify(
|
||||
chunkGraph.getChunkModuleRenderedHashMap(
|
||||
chunk,
|
||||
m => m.type.startsWith("webassembly"),
|
||||
length
|
||||
)
|
||||
)}[chunkId][wasmModuleId] + "`;
|
||||
}
|
||||
},
|
||||
runtime: chunk.runtime
|
||||
}
|
||||
);
|
||||
|
||||
const stateExpression = withHmr
|
||||
? `${RuntimeGlobals.hmrRuntimeStatePrefix}_wasm`
|
||||
: undefined;
|
||||
|
||||
return Template.asString([
|
||||
"// object to store loaded and loading wasm modules",
|
||||
`var installedWasmModules = ${
|
||||
stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
|
||||
}{};`,
|
||||
"",
|
||||
// This function is used to delay reading the installed wasm module promises
|
||||
// by a microtask. Sorting them doesn't help because there are edge cases where
|
||||
// sorting is not possible (modules splitted into different chunks).
|
||||
// So we not even trying and solve this by a microtask delay.
|
||||
"function promiseResolve() { return Promise.resolve(); }",
|
||||
"",
|
||||
Template.asString(declarations),
|
||||
"var wasmImportObjects = {",
|
||||
Template.indent(importObjects),
|
||||
"};",
|
||||
"",
|
||||
`var wasmModuleMap = ${JSON.stringify(
|
||||
chunkModuleIdMap,
|
||||
undefined,
|
||||
"\t"
|
||||
)};`,
|
||||
"",
|
||||
"// object with all WebAssembly.instance exports",
|
||||
`${RuntimeGlobals.wasmInstances} = {};`,
|
||||
"",
|
||||
"// Fetch + compile chunk loading for webassembly",
|
||||
`${fn}.wasm = function(chunkId, promises) {`,
|
||||
Template.indent([
|
||||
"",
|
||||
"var wasmModules = wasmModuleMap[chunkId] || [];",
|
||||
"",
|
||||
"wasmModules.forEach(function(wasmModuleId, idx) {",
|
||||
Template.indent([
|
||||
"var installedWasmModuleData = installedWasmModules[wasmModuleId];",
|
||||
"",
|
||||
'// a Promise means "currently loading" or "already loaded".',
|
||||
"if(installedWasmModuleData)",
|
||||
Template.indent(["promises.push(installedWasmModuleData);"]),
|
||||
"else {",
|
||||
Template.indent([
|
||||
"var importObject = wasmImportObjects[wasmModuleId]();",
|
||||
`var req = ${this.generateLoadBinaryCode(wasmModuleSrcPath)};`,
|
||||
"var promise;",
|
||||
this.supportsStreaming
|
||||
? Template.asString([
|
||||
"if(importObject && typeof importObject.then === 'function' && typeof WebAssembly.compileStreaming === 'function') {",
|
||||
Template.indent([
|
||||
"promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {",
|
||||
Template.indent([
|
||||
`return WebAssembly.instantiate(items[0], ${createImportObject(
|
||||
"items[1]"
|
||||
)});`
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"} else if(typeof WebAssembly.instantiateStreaming === 'function') {",
|
||||
Template.indent([
|
||||
`promise = WebAssembly.instantiateStreaming(req, ${createImportObject(
|
||||
"importObject"
|
||||
)});`
|
||||
])
|
||||
])
|
||||
: Template.asString([
|
||||
"if(importObject && typeof importObject.then === 'function') {",
|
||||
Template.indent([
|
||||
"var bytesPromise = req.then(function(x) { return x.arrayBuffer(); });",
|
||||
"promise = Promise.all([",
|
||||
Template.indent([
|
||||
"bytesPromise.then(function(bytes) { return WebAssembly.compile(bytes); }),",
|
||||
"importObject"
|
||||
]),
|
||||
"]).then(function(items) {",
|
||||
Template.indent([
|
||||
`return WebAssembly.instantiate(items[0], ${createImportObject(
|
||||
"items[1]"
|
||||
)});`
|
||||
]),
|
||||
"});"
|
||||
])
|
||||
]),
|
||||
"} else {",
|
||||
Template.indent([
|
||||
"var bytesPromise = req.then(function(x) { return x.arrayBuffer(); });",
|
||||
"promise = bytesPromise.then(function(bytes) {",
|
||||
Template.indent([
|
||||
`return WebAssembly.instantiate(bytes, ${createImportObject(
|
||||
"importObject"
|
||||
)});`
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"}",
|
||||
"promises.push(installedWasmModules[wasmModuleId] = promise.then(function(res) {",
|
||||
Template.indent([
|
||||
`return ${RuntimeGlobals.wasmInstances}[wasmModuleId] = (res.instance || res).exports;`
|
||||
]),
|
||||
"}));"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"};"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WasmChunkLoadingRuntimeModule;
|
Reference in New Issue
Block a user