mirror of https://github.com/webpack/webpack.git
Merge pull request #7144 from webpack/next
Upgrade to the WASM toolchain
This commit is contained in:
commit
00b0364c8f
|
@ -29,6 +29,69 @@ declare module "chrome-trace-event" {
|
|||
}
|
||||
}
|
||||
|
||||
// There are no typings for @webassemblyjs/ast
|
||||
declare module "@webassemblyjs/ast" {
|
||||
export function traverse(
|
||||
ast: any,
|
||||
visitor: { [name: string]: (context: { node: Node }) => void }
|
||||
);
|
||||
export class Node {
|
||||
index: number;
|
||||
}
|
||||
export class Identifier extends Node {
|
||||
value: string;
|
||||
}
|
||||
export class ModuleImport extends Node {
|
||||
module: string;
|
||||
descr: {
|
||||
type: string;
|
||||
valtype: string;
|
||||
};
|
||||
name: string;
|
||||
}
|
||||
export class ModuleExport extends Node {
|
||||
name: string;
|
||||
}
|
||||
export class IndexLiteral extends Node {}
|
||||
export class NumberLiteral extends Node {}
|
||||
export class Global extends Node {}
|
||||
export class FuncParam extends Node {}
|
||||
export class Instruction extends Node {}
|
||||
export class CallInstruction extends Instruction {}
|
||||
export class ObjectInstruction extends Instruction {}
|
||||
export class Func extends Node {
|
||||
signature: Signature;
|
||||
}
|
||||
export class Signature {
|
||||
params: any;
|
||||
result: any;
|
||||
}
|
||||
export class TypeInstructionFunc extends Node {}
|
||||
export class IndexInFuncSection extends Node {}
|
||||
export function indexLiteral(index: number): IndexLiteral;
|
||||
export function numberLiteral(num: number): NumberLiteral;
|
||||
export function global(globalType: string, nodes: Node[]): Global;
|
||||
export function identifier(indentifier: string): Identifier;
|
||||
export function funcParam(valType: string, id: Identifier): FuncParam;
|
||||
export function instruction(inst: string, args: Node[]): Instruction;
|
||||
export function callInstruction(funcIndex: IndexLiteral): CallInstruction;
|
||||
export function objectInstruction(
|
||||
kind: string,
|
||||
type: string,
|
||||
init: Node[]
|
||||
): ObjectInstruction;
|
||||
export function func(initFuncId, funcParams, funcResults, funcBody): Func;
|
||||
export function typeInstructionFunc(params, result): TypeInstructionFunc;
|
||||
export function indexInFuncSection(index: IndexLiteral): IndexInFuncSection;
|
||||
export function moduleExport(
|
||||
identifier: string,
|
||||
type: string,
|
||||
index: IndexLiteral
|
||||
): ModuleExport;
|
||||
|
||||
export function getSectionMetadata(ast: any, section: string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Global variable declarations
|
||||
* @todo Once this issue is resolved, remove these globals and add JSDoc onsite instead
|
||||
|
|
|
@ -230,8 +230,8 @@ class Compilation extends Tapable {
|
|||
this.requestShortener
|
||||
);
|
||||
this.moduleTemplates = {
|
||||
javascript: new ModuleTemplate(this.runtimeTemplate),
|
||||
webassembly: new ModuleTemplate(this.runtimeTemplate)
|
||||
javascript: new ModuleTemplate(this.runtimeTemplate, "javascript"),
|
||||
webassembly: new ModuleTemplate(this.runtimeTemplate, "webassembly")
|
||||
};
|
||||
|
||||
this.semaphore = new Semaphore(options.parallelism || 100);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
/** @typedef {import("./Module")} Module */
|
||||
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Generator {
|
||||
static byType(map) {
|
||||
return new ByTypeGenerator(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Module} module module for which the code should be generated
|
||||
* @param {Map<Function, any>} dependencyTemplates mapping from dependencies to templates
|
||||
* @param {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @param {string} type which kind of code should be generated
|
||||
* @returns {Source} generated code
|
||||
*/
|
||||
generate(module, dependencyTemplates, runtimeTemplate, type) {
|
||||
throw new Error("Generator.generate: must be overriden");
|
||||
}
|
||||
}
|
||||
|
||||
class ByTypeGenerator extends Generator {
|
||||
constructor(map) {
|
||||
super();
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
generate(module, dependencyTemplates, runtimeTemplate, type) {
|
||||
const generator = this.map[type];
|
||||
if (!generator) {
|
||||
throw new Error(`Generator.byType: no generator specified for ${type}`);
|
||||
}
|
||||
return generator.generate(
|
||||
module,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
type
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Generator;
|
|
@ -7,9 +7,10 @@
|
|||
const { Tapable, SyncWaterfallHook, SyncHook } = require("tapable");
|
||||
|
||||
module.exports = class ModuleTemplate extends Tapable {
|
||||
constructor(runtimeTemplate) {
|
||||
constructor(runtimeTemplate, type) {
|
||||
super();
|
||||
this.runtimeTemplate = runtimeTemplate;
|
||||
this.type = type;
|
||||
this.hooks = {
|
||||
content: new SyncWaterfallHook([
|
||||
"source",
|
||||
|
@ -40,34 +41,40 @@ module.exports = class ModuleTemplate extends Tapable {
|
|||
}
|
||||
|
||||
render(module, dependencyTemplates, options) {
|
||||
const moduleSource = module.source(
|
||||
dependencyTemplates,
|
||||
this.runtimeTemplate
|
||||
);
|
||||
const moduleSourcePostContent = this.hooks.content.call(
|
||||
moduleSource,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
const moduleSourcePostModule = this.hooks.module.call(
|
||||
moduleSourcePostContent,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
const moduleSourcePostRender = this.hooks.render.call(
|
||||
moduleSourcePostModule,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
return this.hooks.package.call(
|
||||
moduleSourcePostRender,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
try {
|
||||
const moduleSource = module.source(
|
||||
dependencyTemplates,
|
||||
this.runtimeTemplate,
|
||||
this.type
|
||||
);
|
||||
const moduleSourcePostContent = this.hooks.content.call(
|
||||
moduleSource,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
const moduleSourcePostModule = this.hooks.module.call(
|
||||
moduleSourcePostContent,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
const moduleSourcePostRender = this.hooks.render.call(
|
||||
moduleSourcePostModule,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
return this.hooks.package.call(
|
||||
moduleSourcePostRender,
|
||||
module,
|
||||
options,
|
||||
dependencyTemplates
|
||||
);
|
||||
} catch (e) {
|
||||
e.message = `${module.identifier()}\n${e.message}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
updateHash(hash) {
|
||||
|
|
|
@ -62,6 +62,12 @@ class NonErrorEmittedError extends WebpackError {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CachedSourceEntry
|
||||
* @property {any} source the generated source
|
||||
* @property {string} hash the hash value
|
||||
*/
|
||||
|
||||
class NormalModule extends Module {
|
||||
constructor({
|
||||
type,
|
||||
|
@ -92,8 +98,8 @@ class NormalModule extends Module {
|
|||
this._source = null;
|
||||
this._buildHash = "";
|
||||
this.buildTimestamp = undefined;
|
||||
this._cachedSource = undefined;
|
||||
this._cachedSourceHash = undefined;
|
||||
/** @private @type {Map<string, CachedSourceEntry>} */
|
||||
this._cachedSources = new Map();
|
||||
|
||||
// Options for the NormalModule set by plugins
|
||||
// TODO refactor this -> options object filled from Factory
|
||||
|
@ -357,8 +363,7 @@ class NormalModule extends Module {
|
|||
};
|
||||
|
||||
return this.doBuild(options, compilation, resolver, fs, err => {
|
||||
this._cachedSource = undefined;
|
||||
this._cachedSourceHash = undefined;
|
||||
this._cachedSources.clear();
|
||||
|
||||
// if we have an error mark module as failed and exit
|
||||
if (err) {
|
||||
|
@ -421,22 +426,26 @@ class NormalModule extends Module {
|
|||
return `${this.hash}-${dtHash}`;
|
||||
}
|
||||
|
||||
source(dependencyTemplates, runtimeTemplate) {
|
||||
source(dependencyTemplates, runtimeTemplate, type = "javascript") {
|
||||
const hashDigest = this.getHashDigest(dependencyTemplates);
|
||||
if (this._cachedSourceHash === hashDigest) {
|
||||
const cacheEntry = this._cachedSources.get(type);
|
||||
if (cacheEntry !== undefined && cacheEntry.hash === hashDigest) {
|
||||
// We can reuse the cached source
|
||||
return this._cachedSource;
|
||||
return cacheEntry.source;
|
||||
}
|
||||
|
||||
const source = this.generator.generate(
|
||||
this,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate
|
||||
runtimeTemplate,
|
||||
type
|
||||
);
|
||||
|
||||
const cachedSource = new CachedSource(source);
|
||||
this._cachedSource = cachedSource;
|
||||
this._cachedSourceHash = hashDigest;
|
||||
this._cachedSources.set(type, {
|
||||
source: cachedSource,
|
||||
hash: hashDigest
|
||||
});
|
||||
return cachedSource;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
class WebAssemblyGenerator {
|
||||
generate(module) {
|
||||
return module.originalSource();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebAssemblyGenerator;
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
/* globals WebAssembly */
|
||||
"use strict";
|
||||
|
||||
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
|
||||
|
||||
const { Tapable } = require("tapable");
|
||||
const WebAssemblyImportDependency = require("./dependencies/WebAssemblyImportDependency");
|
||||
|
||||
class WebAssemblyParser extends Tapable {
|
||||
constructor(options) {
|
||||
super();
|
||||
this.hooks = {};
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
parse(source, state, callback) {
|
||||
// TODO parse WASM AST and walk it
|
||||
// TODO extract imports
|
||||
|
||||
// flag it as ESM
|
||||
state.module.buildMeta.exportsType = "namespace";
|
||||
|
||||
// extract exports
|
||||
// TODO find more efficient way doing it
|
||||
// TODO use Promises
|
||||
if (typeof WebAssembly !== "undefined") {
|
||||
WebAssembly.compile(source)
|
||||
.then(module => {
|
||||
state.module.buildMeta.providedExports = WebAssembly.Module.exports(
|
||||
module
|
||||
).map(exp => exp.name);
|
||||
for (const imp of WebAssembly.Module.imports(module)) {
|
||||
const dep = new WebAssemblyImportDependency(imp.module, imp.name);
|
||||
state.module.addDependency(dep);
|
||||
}
|
||||
})
|
||||
.then(() => callback(null, state), err => callback(err));
|
||||
} else {
|
||||
throw new Error(
|
||||
"Can't compile WebAssembly modules without WebAssembly support in current node.js version (Update to latest node.js version)"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebAssemblyParser;
|
|
@ -8,7 +8,7 @@ const OptionsApply = require("./OptionsApply");
|
|||
|
||||
const JavascriptModulesPlugin = require("./JavascriptModulesPlugin");
|
||||
const JsonModulesPlugin = require("./JsonModulesPlugin");
|
||||
const WebAssemblyModulesPlugin = require("./WebAssemblyModulesPlugin");
|
||||
const WebAssemblyModulesPlugin = require("./wasm/WebAssemblyModulesPlugin");
|
||||
|
||||
const LoaderTargetPlugin = require("./LoaderTargetPlugin");
|
||||
const FunctionModulePlugin = require("./FunctionModulePlugin");
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
|
||||
const DependencyReference = require("./DependencyReference");
|
||||
const ModuleDependency = require("./ModuleDependency");
|
||||
const UnsupportedWebAssemblyFeatureError = require("../wasm/UnsupportedWebAssemblyFeatureError");
|
||||
|
||||
class WebAssemblyImportDependency extends ModuleDependency {
|
||||
constructor(request, name) {
|
||||
constructor(request, name, description, onlyDirectImport) {
|
||||
super(request);
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.onlyDirectImport = onlyDirectImport;
|
||||
}
|
||||
|
||||
getReference() {
|
||||
|
@ -18,6 +21,21 @@ class WebAssemblyImportDependency extends ModuleDependency {
|
|||
return new DependencyReference(this.module, [this.name], false);
|
||||
}
|
||||
|
||||
getErrors() {
|
||||
if (
|
||||
this.onlyDirectImport &&
|
||||
this.module &&
|
||||
!this.module.type.startsWith("webassembly")
|
||||
) {
|
||||
const type = this.description.type;
|
||||
return [
|
||||
new UnsupportedWebAssemblyFeatureError(
|
||||
`${type} imports are only available for direct wasm to wasm dependencies`
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
get type() {
|
||||
return "wasm import";
|
||||
}
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
|
||||
class ReadFileCompileWasmMainTemplatePlugin {
|
||||
apply(mainTemplate) {
|
||||
mainTemplate.hooks.localVars.tap(
|
||||
"ReadFileCompileWasmMainTemplatePlugin",
|
||||
(source, chunk) => {
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// object to store loaded and loading wasm modules",
|
||||
"var installedWasmModules = {};"
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireEnsure.tap(
|
||||
"ReadFileCompileWasmMainTemplatePlugin",
|
||||
(source, chunk, hash) => {
|
||||
const webassemblyModuleFilename =
|
||||
mainTemplate.outputOptions.webassemblyModuleFilename;
|
||||
const chunkModuleMaps = chunk.getChunkModuleMaps(m =>
|
||||
m.type.startsWith("webassembly")
|
||||
);
|
||||
if (Object.keys(chunkModuleMaps.id).length === 0) return source;
|
||||
const wasmModuleSrcPath = mainTemplate.getAssetPath(
|
||||
JSON.stringify(webassemblyModuleFilename),
|
||||
{
|
||||
hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
|
||||
hashWithLength: length =>
|
||||
`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
|
||||
module: {
|
||||
id: '" + wasmModuleId + "',
|
||||
hash: `" + ${JSON.stringify(
|
||||
chunkModuleMaps.hash
|
||||
)}[wasmModuleId] + "`,
|
||||
hashWithLength(length) {
|
||||
const shortChunkHashMap = Object.create(null);
|
||||
for (const wasmModuleId of Object.keys(chunkModuleMaps.hash)) {
|
||||
if (typeof chunkModuleMaps.hash[wasmModuleId] === "string")
|
||||
shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[
|
||||
wasmModuleId
|
||||
].substr(0, length);
|
||||
}
|
||||
return `" + ${JSON.stringify(
|
||||
shortChunkHashMap
|
||||
)}[wasmModuleId] + "`;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// ReadFile + compile chunk loading for webassembly",
|
||||
"",
|
||||
`var wasmModules = ${JSON.stringify(
|
||||
chunkModuleMaps.id
|
||||
)}[chunkId] || [];`,
|
||||
"",
|
||||
"wasmModules.forEach(function(wasmModuleId) {",
|
||||
Template.indent([
|
||||
"var installedWasmModuleData = installedWasmModules[wasmModuleId];",
|
||||
"",
|
||||
'// a Promise means "currently loading" or "already loaded".',
|
||||
"promises.push(installedWasmModuleData ||",
|
||||
Template.indent([
|
||||
"(installedWasmModules[wasmModuleId] = new Promise(function(resolve, reject) {",
|
||||
Template.indent([
|
||||
`require('fs').readFile(require('path').resolve(__dirname, ${wasmModuleSrcPath}), function(err, buffer) {`,
|
||||
Template.indent([
|
||||
"if(err) return reject(err);",
|
||||
"resolve(WebAssembly.compile(buffer));"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
`}).then(function(module) { ${
|
||||
mainTemplate.requireFn
|
||||
}.w[wasmModuleId] = module; }))`
|
||||
]),
|
||||
");"
|
||||
]),
|
||||
"});"
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireExtensions.tap(
|
||||
"ReadFileCompileWasmMainTemplatePlugin",
|
||||
(source, chunk) => {
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// object with all compiled WebAssembly.Modules",
|
||||
`${mainTemplate.requireFn}.w = {};`
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.hash.tap(
|
||||
"ReadFileCompileWasmMainTemplatePlugin",
|
||||
hash => {
|
||||
hash.update("ReadFileCompileWasmMainTemplatePlugin");
|
||||
hash.update("1");
|
||||
hash.update(`${mainTemplate.outputOptions.webassemblyModuleFilename}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
module.exports = ReadFileCompileWasmMainTemplatePlugin;
|
|
@ -4,20 +4,46 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const ReadFileCompileWasmMainTemplatePlugin = require("./ReadFileCompileWasmMainTemplatePlugin");
|
||||
const WasmModuleTemplatePlugin = require("../wasm/WasmModuleTemplatePlugin");
|
||||
const Template = require("../Template");
|
||||
const WasmMainTemplatePlugin = require("../wasm/WasmMainTemplatePlugin");
|
||||
|
||||
class ReadFileCompileWasmTemplatePlugin {
|
||||
apply(compiler) {
|
||||
compiler.hooks.thisCompilation.tap(
|
||||
"ReadFileCompileWasmTemplatePlugin",
|
||||
compilation => {
|
||||
new ReadFileCompileWasmMainTemplatePlugin().apply(
|
||||
compilation.mainTemplate
|
||||
);
|
||||
new WasmModuleTemplatePlugin().apply(
|
||||
compilation.moduleTemplates.javascript
|
||||
const generateLoadBinaryCode = path =>
|
||||
Template.asString([
|
||||
"new Promise(function (resolve, reject) {",
|
||||
Template.indent([
|
||||
"var { readFile } = require('fs');",
|
||||
"var { join } = require('path');",
|
||||
"",
|
||||
"try {",
|
||||
Template.indent([
|
||||
`readFile(join(__dirname, ${path}), function(err, buffer){`,
|
||||
Template.indent([
|
||||
"if (err) return reject(err);",
|
||||
"",
|
||||
"// Fake fetch response",
|
||||
"resolve({",
|
||||
Template.indent([
|
||||
"arrayBuffer() { return Promise.resolve(buffer); }"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"} catch (err) { reject(err); }"
|
||||
]),
|
||||
"})"
|
||||
]);
|
||||
|
||||
const plugin = new WasmMainTemplatePlugin(
|
||||
generateLoadBinaryCode,
|
||||
false
|
||||
);
|
||||
plugin.apply(compilation.mainTemplate);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const WebpackError = require("../WebpackError");
|
||||
|
||||
module.exports = class UnsupportedWebAssemblyFeatureError extends WebpackError {
|
||||
/** @param {string} message Error message */
|
||||
constructor(message) {
|
||||
super();
|
||||
this.name = "UnsupportedWebAssemblyFeatureError";
|
||||
this.message = message;
|
||||
this.hideStack = true;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
|
||||
// Get all wasm modules
|
||||
function getAllWasmModules(chunk) {
|
||||
const wasmModules = chunk.getAllAsyncChunks();
|
||||
const array = [];
|
||||
for (const chunk of wasmModules) {
|
||||
for (const m of chunk.modulesIterable) {
|
||||
if (m.type.startsWith("webassembly")) {
|
||||
array.push(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
function generateImportObject(module) {
|
||||
const depsByRequest = new Map();
|
||||
for (const dep of module.dependencies) {
|
||||
if (dep instanceof WebAssemblyImportDependency) {
|
||||
// Ignore global they will be handled later
|
||||
if (dep.description.type === "GlobalType") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const request = dep.request;
|
||||
let array = depsByRequest.get(request);
|
||||
if (!array) {
|
||||
depsByRequest.set(request, (array = []));
|
||||
}
|
||||
const exportName = dep.name;
|
||||
const usedName = dep.module && dep.module.isUsed(exportName);
|
||||
|
||||
if (dep.module === null) {
|
||||
// Dependency was not found, an error will be thrown later
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usedName !== false) {
|
||||
array.push({
|
||||
exportName,
|
||||
usedName,
|
||||
module: dep.module,
|
||||
description: dep.description,
|
||||
direct: dep.onlyDirectImport
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const importsCode = [];
|
||||
const waitForPromises = new Map();
|
||||
for (const pair of depsByRequest) {
|
||||
const properties = [];
|
||||
for (const data of pair[1]) {
|
||||
if (data.direct) {
|
||||
const instanceVar = `m${waitForPromises.size}`;
|
||||
waitForPromises.set(
|
||||
instanceVar,
|
||||
`installedWasmModules[${JSON.stringify(data.module.id)}]`
|
||||
);
|
||||
properties.push(
|
||||
`${JSON.stringify(data.exportName)}: ${instanceVar}.exports` +
|
||||
`[${JSON.stringify(data.exportName)}]`
|
||||
);
|
||||
} else {
|
||||
const params = data.description.signature.params.map(
|
||||
(param, k) => "p" + k + param.valtype
|
||||
);
|
||||
|
||||
const result = `__webpack_require__(${JSON.stringify(
|
||||
data.module.id
|
||||
)})[${JSON.stringify(data.usedName)}](${params})`;
|
||||
|
||||
properties.push(
|
||||
Template.asString([
|
||||
`${JSON.stringify(data.exportName)}: function(${params}) {`,
|
||||
Template.indent([`return ${result};`]),
|
||||
"}"
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
importsCode.push(
|
||||
Template.asString([
|
||||
`${JSON.stringify(pair[0])}: {`,
|
||||
Template.indent([properties.join(",")]),
|
||||
"}"
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if (waitForPromises.size > 0) {
|
||||
const promises = Array.from(waitForPromises.values()).join(", ");
|
||||
const variables = Array.from(
|
||||
waitForPromises.keys(),
|
||||
(name, i) => `var ${name} = array[${i}];`
|
||||
).join("\n");
|
||||
return Template.asString([
|
||||
`${JSON.stringify(module.id)}: function() {`,
|
||||
Template.indent([
|
||||
`return Promise.resolve().then(function() { return Promise.all([${promises}]); }).then(function(array) {`,
|
||||
Template.indent([
|
||||
variables,
|
||||
"return {",
|
||||
Template.indent([importsCode.join(",")]),
|
||||
"};"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"},"
|
||||
]);
|
||||
} else {
|
||||
return Template.asString([
|
||||
`${JSON.stringify(module.id)}: function() {`,
|
||||
Template.indent([
|
||||
"return {",
|
||||
Template.indent([importsCode.join(",")]),
|
||||
"};"
|
||||
]),
|
||||
"},"
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
class WasmMainTemplatePlugin {
|
||||
constructor(generateLoadBinaryCode, supportsStreaming) {
|
||||
this.generateLoadBinaryCode = generateLoadBinaryCode;
|
||||
this.supportsStreaming = supportsStreaming;
|
||||
}
|
||||
apply(mainTemplate) {
|
||||
mainTemplate.hooks.localVars.tap(
|
||||
"WasmMainTemplatePlugin",
|
||||
(source, chunk) => {
|
||||
const wasmModules = getAllWasmModules(chunk);
|
||||
if (wasmModules.length === 0) return source;
|
||||
const importObjects = wasmModules.map(generateImportObject);
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// object to store loaded and loading wasm modules",
|
||||
"var installedWasmModules = {};",
|
||||
"",
|
||||
"var wasmImportObjects = {",
|
||||
Template.indent(importObjects),
|
||||
"};"
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireEnsure.tap(
|
||||
"WasmMainTemplatePlugin",
|
||||
(source, chunk, hash) => {
|
||||
const webassemblyModuleFilename =
|
||||
mainTemplate.outputOptions.webassemblyModuleFilename;
|
||||
|
||||
const chunkModuleMaps = chunk.getChunkModuleMaps(m =>
|
||||
m.type.startsWith("webassembly")
|
||||
);
|
||||
if (Object.keys(chunkModuleMaps.id).length === 0) return source;
|
||||
const wasmModuleSrcPath = mainTemplate.getAssetPath(
|
||||
JSON.stringify(webassemblyModuleFilename),
|
||||
{
|
||||
hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
|
||||
hashWithLength: length =>
|
||||
`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
|
||||
module: {
|
||||
id: '" + wasmModuleId + "',
|
||||
hash: `" + ${JSON.stringify(
|
||||
chunkModuleMaps.hash
|
||||
)}[wasmModuleId] + "`,
|
||||
hashWithLength(length) {
|
||||
const shortChunkHashMap = Object.create(null);
|
||||
for (const wasmModuleId of Object.keys(chunkModuleMaps.hash)) {
|
||||
if (typeof chunkModuleMaps.hash[wasmModuleId] === "string")
|
||||
shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[
|
||||
wasmModuleId
|
||||
].substr(0, length);
|
||||
}
|
||||
return `" + ${JSON.stringify(
|
||||
shortChunkHashMap
|
||||
)}[wasmModuleId] + "`;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// Fetch + compile chunk loading for webassembly",
|
||||
"",
|
||||
`var wasmModules = ${JSON.stringify(
|
||||
chunkModuleMaps.id
|
||||
)}[chunkId] || [];`,
|
||||
"",
|
||||
"wasmModules.forEach(function(wasmModuleId) {",
|
||||
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 instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {",
|
||||
Template.indent([
|
||||
"promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {",
|
||||
Template.indent([
|
||||
"return WebAssembly.instantiate(items[0], items[1]);"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"} else if(typeof WebAssembly.instantiateStreaming === 'function') {",
|
||||
Template.indent([
|
||||
"promise = WebAssembly.instantiateStreaming(req, importObject);"
|
||||
])
|
||||
])
|
||||
: Template.asString([
|
||||
"if(importObject instanceof Promise) {",
|
||||
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], 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, importObject);"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"}",
|
||||
"promises.push(installedWasmModules[wasmModuleId] = promise.then(function(res) {",
|
||||
Template.indent([
|
||||
`return ${
|
||||
mainTemplate.requireFn
|
||||
}.w[wasmModuleId] = res.instance || res;`
|
||||
]),
|
||||
"}));"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"});"
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireExtensions.tap(
|
||||
"WasmMainTemplatePlugin",
|
||||
(source, chunk) => {
|
||||
if (!chunk.hasModuleInGraph(m => m.type.startsWith("webassembly")))
|
||||
return source;
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// object with all WebAssembly.instance",
|
||||
`${mainTemplate.requireFn}.w = {};`
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.hash.tap("WasmMainTemplatePlugin", hash => {
|
||||
hash.update("WasmMainTemplatePlugin");
|
||||
hash.update("1");
|
||||
hash.update(`${mainTemplate.outputOptions.webassemblyModuleFilename}`);
|
||||
});
|
||||
mainTemplate.hooks.hashForChunk.tap(
|
||||
"WasmMainTemplatePlugin",
|
||||
(hash, chunk) => {
|
||||
const chunkModuleMaps = chunk.getChunkModuleMaps(m =>
|
||||
m.type.startsWith("webassembly")
|
||||
);
|
||||
hash.update(JSON.stringify(chunkModuleMaps.id));
|
||||
const wasmModules = getAllWasmModules(chunk);
|
||||
for (const module of wasmModules) {
|
||||
hash.update(module.hash);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WasmMainTemplatePlugin;
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const { RawSource } = require("webpack-sources");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
|
||||
class WasmModuleTemplatePlugin {
|
||||
apply(moduleTemplate) {
|
||||
moduleTemplate.hooks.content.tap(
|
||||
"WasmModuleTemplatePlugin",
|
||||
(moduleSource, module, { chunk }) => {
|
||||
if (module.type && module.type.startsWith("webassembly")) {
|
||||
if (chunk.canBeInitial())
|
||||
throw new Error(
|
||||
"Sync WebAssembly compilation is not yet implemented"
|
||||
);
|
||||
const generateExports = () => {
|
||||
if (
|
||||
Array.isArray(module.buildMeta.providedExports) &&
|
||||
Array.isArray(module.usedExports)
|
||||
) {
|
||||
// generate mangled exports
|
||||
return module.buildMeta.providedExports
|
||||
.map(exp => {
|
||||
const usedName = module.isUsed(exp);
|
||||
if (usedName) {
|
||||
return `${module.exportsArgument}[${JSON.stringify(
|
||||
usedName
|
||||
)}] = instance.exports[${JSON.stringify(exp)}];`;
|
||||
} else {
|
||||
return `// unused ${JSON.stringify(exp)} export`;
|
||||
}
|
||||
})
|
||||
.join("\n");
|
||||
} else {
|
||||
// generate simple export
|
||||
return `${module.moduleArgument}.exports = instance.exports;`;
|
||||
}
|
||||
};
|
||||
const generateImports = () => {
|
||||
const depsByRequest = new Map();
|
||||
for (const dep of module.dependencies) {
|
||||
if (dep instanceof WebAssemblyImportDependency) {
|
||||
const request = dep.request;
|
||||
let array = depsByRequest.get(request);
|
||||
if (!array) {
|
||||
depsByRequest.set(request, (array = []));
|
||||
}
|
||||
const exportName = dep.name;
|
||||
const usedName = dep.module && dep.module.isUsed(exportName);
|
||||
array.push({
|
||||
exportName,
|
||||
usedName,
|
||||
module: dep.module
|
||||
});
|
||||
}
|
||||
}
|
||||
const importsCode = [];
|
||||
for (const pair of depsByRequest) {
|
||||
const properties = [];
|
||||
for (const data of pair[1]) {
|
||||
properties.push(
|
||||
`\n\t\t${JSON.stringify(
|
||||
data.exportName
|
||||
)}: __webpack_require__(${JSON.stringify(
|
||||
data.module.id
|
||||
)})[${JSON.stringify(data.usedName)}]`
|
||||
);
|
||||
}
|
||||
importsCode.push(
|
||||
`\n\t${JSON.stringify(pair[0])}: {${properties.join(",")}\n\t}`
|
||||
);
|
||||
}
|
||||
return importsCode.join(",");
|
||||
};
|
||||
const source = new RawSource(
|
||||
[
|
||||
'"use strict";',
|
||||
"",
|
||||
"// Instantiate WebAssembly module",
|
||||
"var instance = new WebAssembly.Instance(__webpack_require__.w[module.i], {" +
|
||||
generateImports(),
|
||||
"});",
|
||||
"",
|
||||
"// export exports from WebAssembly module",
|
||||
// TODO rewrite this to getters depending on exports to support circular dependencies
|
||||
generateExports()
|
||||
].join("\n")
|
||||
);
|
||||
return source;
|
||||
} else {
|
||||
return moduleSource;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
moduleTemplate.hooks.hash.tap("WasmModuleTemplatePlugin", hash => {
|
||||
hash.update("WasmModuleTemplatePlugin");
|
||||
hash.update("1");
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = WasmModuleTemplatePlugin;
|
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const Generator = require("../Generator");
|
||||
const { RawSource } = require("webpack-sources");
|
||||
|
||||
const { edit, add } = require("@webassemblyjs/wasm-edit");
|
||||
const { decode } = require("@webassemblyjs/wasm-parser");
|
||||
const t = require("@webassemblyjs/ast");
|
||||
|
||||
function compose(...fns) {
|
||||
return fns.reverse().reduce((prevFn, nextFn) => {
|
||||
return value => nextFn(prevFn(value));
|
||||
}, value => value);
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
const isGlobalImport = moduleImport => moduleImport.descr.type === "GlobalType";
|
||||
const isFuncImport = moduleImport =>
|
||||
moduleImport.descr.type === "FuncImportDescr";
|
||||
const initFuncId = t.identifier("__webpack_init__");
|
||||
|
||||
// TODO replace with @callback
|
||||
/**
|
||||
* @typedef {(ArrayBuffer) => ArrayBuffer} ArrayBufferTransform
|
||||
*/
|
||||
|
||||
/**
|
||||
* Removes the start instruction
|
||||
*
|
||||
* @param {Object} state - unused state
|
||||
* @returns {ArrayBufferTransform} transform
|
||||
*/
|
||||
const removeStartFunc = state => bin => {
|
||||
return edit(bin, {
|
||||
Start(path) {
|
||||
path.remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the start function
|
||||
*
|
||||
* @param {Object} ast - Module's AST
|
||||
* @returns {t.Identifier | undefined} - node if any
|
||||
*/
|
||||
function getStartFuncIndex(ast) {
|
||||
let startAtFuncIndex;
|
||||
|
||||
t.traverse(ast, {
|
||||
Start({ node }) {
|
||||
startAtFuncIndex = node.index;
|
||||
}
|
||||
});
|
||||
|
||||
return startAtFuncIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get imported globals
|
||||
*
|
||||
* @param {Object} ast - Module's AST
|
||||
* @returns {Array<t.ModuleImport>} - nodes
|
||||
*/
|
||||
function getImportedGlobals(ast) {
|
||||
const importedGlobals = [];
|
||||
|
||||
t.traverse(ast, {
|
||||
ModuleImport({ node }) {
|
||||
if (isGlobalImport(node) === true) {
|
||||
importedGlobals.push(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return importedGlobals;
|
||||
}
|
||||
|
||||
function getCountImportedFunc(ast) {
|
||||
let count = 0;
|
||||
|
||||
t.traverse(ast, {
|
||||
ModuleImport({ node }) {
|
||||
if (isFuncImport(node) === true) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next type index
|
||||
*
|
||||
* @param {Object} ast - Module's AST
|
||||
* @returns {t.IndexLiteral} - index
|
||||
*/
|
||||
function getNextTypeIndex(ast) {
|
||||
const typeSectionMetadata = t.getSectionMetadata(ast, "type");
|
||||
|
||||
if (typeof typeSectionMetadata === "undefined") {
|
||||
return t.indexLiteral(0);
|
||||
}
|
||||
|
||||
return t.indexLiteral(typeSectionMetadata.vectorOfSize.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next func index
|
||||
*
|
||||
* The Func section metadata provide informations for implemented funcs
|
||||
* in order to have the correct index we shift the index by number of external
|
||||
* functions.
|
||||
*
|
||||
* @param {Object} ast - Module's AST
|
||||
* @param {Number} countImportedFunc - number of imported funcs
|
||||
* @returns {t.IndexLiteral} - index
|
||||
*/
|
||||
function getNextFuncIndex(ast, countImportedFunc) {
|
||||
const funcSectionMetadata = t.getSectionMetadata(ast, "func");
|
||||
|
||||
if (typeof funcSectionMetadata === "undefined") {
|
||||
return t.indexLiteral(0 + countImportedFunc);
|
||||
}
|
||||
|
||||
const vectorOfSize = funcSectionMetadata.vectorOfSize.value;
|
||||
|
||||
return t.indexLiteral(vectorOfSize + countImportedFunc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite the import globals:
|
||||
* - removes the ModuleImport instruction
|
||||
* - injects at the same offset a mutable global of the same time
|
||||
*
|
||||
* Since the imported globals are before the other global declarations, our
|
||||
* indices will be preserved.
|
||||
*
|
||||
* Note that globals will become mutable.
|
||||
*
|
||||
* @param {Object} state - unused state
|
||||
* @returns {ArrayBufferTransform} transform
|
||||
*/
|
||||
const rewriteImportedGlobals = state => bin => {
|
||||
const newGlobals = [];
|
||||
|
||||
bin = edit(bin, {
|
||||
ModuleImport(path) {
|
||||
if (isGlobalImport(path.node) === true) {
|
||||
const globalType = path.node.descr;
|
||||
|
||||
globalType.mutability = "var";
|
||||
|
||||
newGlobals.push(
|
||||
t.global(globalType, [
|
||||
t.objectInstruction("const", "i32", [t.numberLiteral(0)])
|
||||
])
|
||||
);
|
||||
|
||||
path.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add global declaration instructions
|
||||
return add(bin, newGlobals);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an init function.
|
||||
*
|
||||
* The init function fills the globals given input arguments.
|
||||
*
|
||||
* @param {Object} state transformation state
|
||||
* @param {t.IndexLiteral} state.startAtFuncIndex index of the start function
|
||||
* @param {t.ModuleImport[]} state.importedGlobals list of imported globals
|
||||
* @param {*} state.funcSectionMetadata ??
|
||||
* @param {t.IndexLiteral} state.nextFuncIndex index of the next function
|
||||
* @param {t.IndexLiteral} state.nextTypeIndex index of the next type
|
||||
* @returns {ArrayBufferTransform} transform
|
||||
*/
|
||||
const addInitFunction = ({
|
||||
startAtFuncIndex,
|
||||
importedGlobals,
|
||||
funcSectionMetadata,
|
||||
nextFuncIndex,
|
||||
nextTypeIndex
|
||||
}) => bin => {
|
||||
const funcParams = importedGlobals.map(importedGlobal => {
|
||||
// used for debugging
|
||||
const id = t.identifier(`${importedGlobal.module}.${importedGlobal.name}`);
|
||||
|
||||
return t.funcParam(importedGlobal.descr.valtype, id);
|
||||
});
|
||||
|
||||
const funcBody = importedGlobals.reduce((acc, importedGlobal, index) => {
|
||||
const args = [t.indexLiteral(index)];
|
||||
const body = [
|
||||
t.instruction("get_local", args),
|
||||
t.instruction("set_global", args)
|
||||
];
|
||||
|
||||
return [...acc, ...body];
|
||||
}, []);
|
||||
|
||||
if (typeof startAtFuncIndex !== "undefined") {
|
||||
funcBody.push(t.callInstruction(startAtFuncIndex));
|
||||
}
|
||||
|
||||
const funcResults = [];
|
||||
|
||||
// Code section
|
||||
const func = t.func(initFuncId, funcParams, funcResults, funcBody);
|
||||
|
||||
// Type section
|
||||
const functype = t.typeInstructionFunc(
|
||||
func.signature.params,
|
||||
func.signature.result
|
||||
);
|
||||
|
||||
// Func section
|
||||
const funcindex = t.indexInFuncSection(nextTypeIndex);
|
||||
|
||||
// Export section
|
||||
const moduleExport = t.moduleExport(initFuncId.value, "Func", nextFuncIndex);
|
||||
|
||||
return add(bin, [func, moduleExport, funcindex, functype]);
|
||||
};
|
||||
|
||||
class WebAssemblyGenerator extends Generator {
|
||||
generate(module) {
|
||||
const bin = module.originalSource().source();
|
||||
|
||||
// FIXME(sven): this module is parsed twice, we could preserve the AST
|
||||
// from wasm/WebAssemblyParser.js
|
||||
const ast = decode(bin, {
|
||||
ignoreDataSection: true,
|
||||
ignoreCodeSection: true
|
||||
});
|
||||
|
||||
const importedGlobals = getImportedGlobals(ast);
|
||||
const funcSectionMetadata = t.getSectionMetadata(ast, "func");
|
||||
const countImportedFunc = getCountImportedFunc(ast);
|
||||
const startAtFuncIndex = getStartFuncIndex(ast);
|
||||
const nextFuncIndex = getNextFuncIndex(ast, countImportedFunc);
|
||||
const nextTypeIndex = getNextTypeIndex(ast);
|
||||
|
||||
const transform = compose(
|
||||
removeStartFunc({}),
|
||||
|
||||
rewriteImportedGlobals({}),
|
||||
|
||||
addInitFunction({
|
||||
importedGlobals,
|
||||
funcSectionMetadata,
|
||||
startAtFuncIndex,
|
||||
nextFuncIndex,
|
||||
nextTypeIndex
|
||||
})
|
||||
);
|
||||
|
||||
const newBin = transform(bin);
|
||||
|
||||
return new RawSource(newBin);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebAssemblyGenerator;
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const Generator = require("../Generator");
|
||||
const Template = require("../Template");
|
||||
const { RawSource } = require("webpack-sources");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
|
||||
function generateInitParams(module) {
|
||||
const list = [];
|
||||
|
||||
for (const dep of module.dependencies) {
|
||||
if (dep instanceof WebAssemblyImportDependency) {
|
||||
if (dep.description.type === "GlobalType") {
|
||||
const exportName = dep.name;
|
||||
const usedName = dep.module && dep.module.isUsed(exportName);
|
||||
|
||||
if (dep.module === null) {
|
||||
// Dependency was not found, an error will be thrown later
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usedName !== false) {
|
||||
list.push(
|
||||
`__webpack_require__(${JSON.stringify(
|
||||
dep.module.id
|
||||
)})[${JSON.stringify(usedName)}]`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
class WebAssemblyJavascriptGenerator extends Generator {
|
||||
generate(module, dependencyTemplates, runtimeTemplate) {
|
||||
const generateExports = () => {
|
||||
if (
|
||||
Array.isArray(module.buildMeta.providedExports) &&
|
||||
Array.isArray(module.usedExports)
|
||||
) {
|
||||
// generate mangled exports
|
||||
return Template.asString(
|
||||
module.buildMeta.providedExports.map(exp => {
|
||||
const usedName = module.isUsed(exp);
|
||||
if (usedName) {
|
||||
return `${module.exportsArgument}[${JSON.stringify(
|
||||
usedName
|
||||
)}] = instance.exports[${JSON.stringify(exp)}];`;
|
||||
} else {
|
||||
return `// unused ${JSON.stringify(exp)} export`;
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// generate simple export
|
||||
return `${module.moduleArgument}.exports = instance.exports;`;
|
||||
}
|
||||
};
|
||||
|
||||
const generateImports = () => {
|
||||
const modules = new Map();
|
||||
for (const dep of module.dependencies) {
|
||||
if (dep.module) modules.set(dep.module, dep.userRequest);
|
||||
}
|
||||
return Template.asString(
|
||||
Array.from(modules, ([m, r]) => {
|
||||
return `${runtimeTemplate.moduleRaw({
|
||||
module: m,
|
||||
request: r
|
||||
})};`;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
// FIXME(sven): assert that the exports exists in the modules
|
||||
// otherwise it will default to i32 0
|
||||
const initParams = generateInitParams(module).join(",");
|
||||
|
||||
// create source
|
||||
const source = new RawSource(
|
||||
[
|
||||
'"use strict";',
|
||||
"// Instantiate WebAssembly module",
|
||||
"var instance = __webpack_require__.w[module.i];",
|
||||
|
||||
// this must be before import for circular dependencies
|
||||
"// export exports from WebAssembly module",
|
||||
generateExports(),
|
||||
|
||||
"// exec imports from WebAssembly module (for esm order)",
|
||||
generateImports(),
|
||||
|
||||
"// exec wasm module",
|
||||
`instance.exports.__webpack_init__(${initParams})`
|
||||
].join("\n")
|
||||
);
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebAssemblyJavascriptGenerator;
|
|
@ -4,9 +4,11 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const Generator = require("../Generator");
|
||||
const WebAssemblyParser = require("./WebAssemblyParser");
|
||||
const WebAssemblyGenerator = require("./WebAssemblyGenerator");
|
||||
const WebAssemblyImportDependency = require("./dependencies/WebAssemblyImportDependency");
|
||||
const WebAssemblyJavascriptGenerator = require("./WebAssemblyJavascriptGenerator");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
|
||||
class WebAssemblyModulesPlugin {
|
||||
apply(compiler) {
|
||||
|
@ -27,7 +29,10 @@ class WebAssemblyModulesPlugin {
|
|||
normalModuleFactory.hooks.createGenerator
|
||||
.for("webassembly/experimental")
|
||||
.tap("WebAssemblyModulesPlugin", () => {
|
||||
return new WebAssemblyGenerator();
|
||||
return Generator.byType({
|
||||
javascript: new WebAssemblyJavascriptGenerator(),
|
||||
webassembly: new WebAssemblyGenerator()
|
||||
});
|
||||
});
|
||||
|
||||
compilation.chunkTemplate.hooks.renderManifest.tap(
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const t = require("@webassemblyjs/ast");
|
||||
const { decode } = require("@webassemblyjs/wasm-parser");
|
||||
|
||||
const { Tapable } = require("tapable");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
|
||||
/**
|
||||
* @param {t.ModuleImport} moduleImport the import
|
||||
* @returns {boolean} true, if a memory was imported
|
||||
*/
|
||||
const isMemoryImport = moduleImport => moduleImport.descr.type === "Memory";
|
||||
|
||||
/**
|
||||
* @param {t.ModuleImport} moduleImport the import
|
||||
* @returns {boolean} true, if a table was imported
|
||||
*/
|
||||
const isTableImport = moduleImport => moduleImport.descr.type === "Table";
|
||||
|
||||
const decoderOpts = {
|
||||
ignoreCodeSection: true,
|
||||
ignoreDataSection: true
|
||||
};
|
||||
|
||||
class WebAssemblyParser extends Tapable {
|
||||
constructor(options) {
|
||||
super();
|
||||
this.hooks = {};
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
parse(binary, state) {
|
||||
// flag it as ESM
|
||||
state.module.buildMeta.exportsType = "namespace";
|
||||
|
||||
// parse it
|
||||
const ast = decode(binary, decoderOpts);
|
||||
|
||||
// extract imports and exports
|
||||
const exports = (state.module.buildMeta.providedExports = []);
|
||||
t.traverse(ast, {
|
||||
ModuleExport({ node }) {
|
||||
const moduleExport = /** @type {t.ModuleExport} */ (node);
|
||||
exports.push(moduleExport.name);
|
||||
},
|
||||
|
||||
ModuleImport({ node }) {
|
||||
const moduleImport = /** @type {t.ModuleImport} */ (node);
|
||||
|
||||
let onlyDirectImport = false;
|
||||
|
||||
if (isMemoryImport(moduleImport) === true) {
|
||||
onlyDirectImport = true;
|
||||
}
|
||||
|
||||
if (isTableImport(moduleImport) === true) {
|
||||
onlyDirectImport = true;
|
||||
}
|
||||
|
||||
const dep = new WebAssemblyImportDependency(
|
||||
moduleImport.module,
|
||||
moduleImport.name,
|
||||
moduleImport.descr,
|
||||
onlyDirectImport
|
||||
);
|
||||
|
||||
state.module.addDependency(dep);
|
||||
}
|
||||
});
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebAssemblyParser;
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
|
||||
class FetchCompileWasmMainTemplatePlugin {
|
||||
apply(mainTemplate) {
|
||||
mainTemplate.hooks.localVars.tap(
|
||||
"FetchCompileWasmMainTemplatePlugin",
|
||||
(source, chunk) => {
|
||||
if (!chunk.hasModuleInGraph(m => m.type.startsWith("webassembly")))
|
||||
return source;
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// object to store loaded and loading wasm modules",
|
||||
"var installedWasmModules = {};"
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireEnsure.tap(
|
||||
"FetchCompileWasmMainTemplatePlugin",
|
||||
(source, chunk, hash) => {
|
||||
const webassemblyModuleFilename =
|
||||
mainTemplate.outputOptions.webassemblyModuleFilename;
|
||||
const chunkModuleMaps = chunk.getChunkModuleMaps(m =>
|
||||
m.type.startsWith("webassembly")
|
||||
);
|
||||
if (Object.keys(chunkModuleMaps.id).length === 0) return source;
|
||||
const wasmModuleSrcPath = mainTemplate.getAssetPath(
|
||||
JSON.stringify(webassemblyModuleFilename),
|
||||
{
|
||||
hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
|
||||
hashWithLength: length =>
|
||||
`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
|
||||
module: {
|
||||
id: '" + wasmModuleId + "',
|
||||
hash: `" + ${JSON.stringify(
|
||||
chunkModuleMaps.hash
|
||||
)}[wasmModuleId] + "`,
|
||||
hashWithLength(length) {
|
||||
const shortChunkHashMap = Object.create(null);
|
||||
for (const wasmModuleId of Object.keys(chunkModuleMaps.hash)) {
|
||||
if (typeof chunkModuleMaps.hash[wasmModuleId] === "string")
|
||||
shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[
|
||||
wasmModuleId
|
||||
].substr(0, length);
|
||||
}
|
||||
return `" + ${JSON.stringify(
|
||||
shortChunkHashMap
|
||||
)}[wasmModuleId] + "`;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// Fetch + compile chunk loading for webassembly",
|
||||
"",
|
||||
`var wasmModules = ${JSON.stringify(
|
||||
chunkModuleMaps.id
|
||||
)}[chunkId] || [];`,
|
||||
"",
|
||||
"wasmModules.forEach(function(wasmModuleId) {",
|
||||
Template.indent([
|
||||
"var installedWasmModuleData = installedWasmModules[wasmModuleId];",
|
||||
"",
|
||||
'// a Promise means "currently loading" or "already loaded".',
|
||||
"promises.push(installedWasmModuleData ||",
|
||||
Template.indent([
|
||||
`(installedWasmModules[wasmModuleId] = fetch(${
|
||||
mainTemplate.requireFn
|
||||
}.p + ${wasmModuleSrcPath}).then(function(response) {`,
|
||||
Template.indent([
|
||||
"if(WebAssembly.compileStreaming) {",
|
||||
Template.indent([
|
||||
"return WebAssembly.compileStreaming(response);"
|
||||
]),
|
||||
"} else {",
|
||||
Template.indent([
|
||||
"return response.arrayBuffer().then(function(bytes) { return WebAssembly.compile(bytes); });"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
`}).then(function(module) { ${
|
||||
mainTemplate.requireFn
|
||||
}.w[wasmModuleId] = module; }))`
|
||||
]),
|
||||
");"
|
||||
]),
|
||||
"});"
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireExtensions.tap(
|
||||
"FetchCompileWasmMainTemplatePlugin",
|
||||
(source, chunk) => {
|
||||
if (!chunk.hasModuleInGraph(m => m.type.startsWith("webassembly")))
|
||||
return source;
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// object with all compiled WebAssembly.Modules",
|
||||
`${mainTemplate.requireFn}.w = {};`
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.hash.tap("FetchCompileWasmMainTemplatePlugin", hash => {
|
||||
hash.update("FetchCompileWasmMainTemplatePlugin");
|
||||
hash.update("1");
|
||||
hash.update(`${mainTemplate.outputOptions.webassemblyModuleFilename}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = FetchCompileWasmMainTemplatePlugin;
|
|
@ -4,20 +4,19 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const FetchCompileWasmMainTemplatePlugin = require("./FetchCompileWasmMainTemplatePlugin");
|
||||
const WasmModuleTemplatePlugin = require("../wasm/WasmModuleTemplatePlugin");
|
||||
const WasmMainTemplatePlugin = require("../wasm/WasmMainTemplatePlugin");
|
||||
|
||||
class FetchCompileWasmTemplatePlugin {
|
||||
apply(compiler) {
|
||||
compiler.hooks.thisCompilation.tap(
|
||||
"FetchCompileWasmTemplatePlugin",
|
||||
compilation => {
|
||||
new FetchCompileWasmMainTemplatePlugin().apply(
|
||||
compilation.mainTemplate
|
||||
);
|
||||
new WasmModuleTemplatePlugin().apply(
|
||||
compilation.moduleTemplates.javascript
|
||||
);
|
||||
const mainTemplate = compilation.mainTemplate;
|
||||
const generateLoadBinaryCode = path =>
|
||||
`fetch(${mainTemplate.requireFn}.p + ${path})`;
|
||||
|
||||
const plugin = new WasmMainTemplatePlugin(generateLoadBinaryCode, true);
|
||||
plugin.apply(mainTemplate);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.3.0",
|
||||
"@webassemblyjs/wasm-edit": "1.3.0",
|
||||
"@webassemblyjs/wasm-parser": "1.3.0",
|
||||
"acorn": "^5.0.0",
|
||||
"acorn-dynamic-import": "^3.0.0",
|
||||
"ajv": "^6.1.0",
|
||||
|
|
|
@ -55,6 +55,15 @@ describe("WatchTestCases", () => {
|
|||
tests: fs
|
||||
.readdirSync(path.join(casesPath, cat))
|
||||
.filter(folder => folder.indexOf("_") < 0)
|
||||
.filter(testName => {
|
||||
const testDirectory = path.join(casesPath, cat, testName);
|
||||
const filterPath = path.join(testDirectory, "test.filter.js");
|
||||
if (fs.existsSync(filterPath) && !require(filterPath)()) {
|
||||
describe.skip(testName, () => it("filtered"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.sort()
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`StatsTestCases should print correct stats for aggressive-splitting-entry 1`] = `
|
||||
"Hash: b907386938ff12cf9dbbb907386938ff12cf9dbb
|
||||
"Hash: 4fe9463156cb2a99f4a94fe9463156cb2a99f4a9
|
||||
Child fitting:
|
||||
Hash: b907386938ff12cf9dbb
|
||||
Hash: 4fe9463156cb2a99f4a9
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
9ac13fb7087e9ff1b93e.js 1.05 KiB 0 [emitted]
|
||||
077726e3805b482fd93e.js 10.2 KiB 1 [emitted]
|
||||
f2e891598128a57b072c.js 10.2 KiB 1 [emitted]
|
||||
d1ba53816ff760e185b0.js 1.94 KiB 2 [emitted]
|
||||
7b5b0a943e9362bc88c6.js 1.94 KiB 3 [emitted]
|
||||
Entrypoint main = d1ba53816ff760e185b0.js 7b5b0a943e9362bc88c6.js 077726e3805b482fd93e.js
|
||||
Entrypoint main = d1ba53816ff760e185b0.js 7b5b0a943e9362bc88c6.js f2e891598128a57b072c.js
|
||||
chunk {0} 9ac13fb7087e9ff1b93e.js 916 bytes <{1}> <{2}> <{3}>
|
||||
> ./g [4] ./index.js 7:0-13
|
||||
[7] ./g.js 916 bytes {0} [built]
|
||||
chunk {1} 077726e3805b482fd93e.js 1.87 KiB ={2}= ={3}= >{0}< [entry] [rendered]
|
||||
chunk {1} f2e891598128a57b072c.js 1.87 KiB ={2}= ={3}= >{0}< [entry] [rendered]
|
||||
> ./index main
|
||||
[3] ./e.js 899 bytes {1} [built]
|
||||
[4] ./index.js 111 bytes {1} [built]
|
||||
|
@ -29,19 +29,19 @@ Child fitting:
|
|||
[1] ./c.js 899 bytes {3} [built]
|
||||
[2] ./d.js 899 bytes {3} [built]
|
||||
Child content-change:
|
||||
Hash: b907386938ff12cf9dbb
|
||||
Hash: 4fe9463156cb2a99f4a9
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
9ac13fb7087e9ff1b93e.js 1.05 KiB 0 [emitted]
|
||||
077726e3805b482fd93e.js 10.2 KiB 1 [emitted]
|
||||
f2e891598128a57b072c.js 10.2 KiB 1 [emitted]
|
||||
d1ba53816ff760e185b0.js 1.94 KiB 2 [emitted]
|
||||
7b5b0a943e9362bc88c6.js 1.94 KiB 3 [emitted]
|
||||
Entrypoint main = d1ba53816ff760e185b0.js 7b5b0a943e9362bc88c6.js 077726e3805b482fd93e.js
|
||||
Entrypoint main = d1ba53816ff760e185b0.js 7b5b0a943e9362bc88c6.js f2e891598128a57b072c.js
|
||||
chunk {0} 9ac13fb7087e9ff1b93e.js 916 bytes <{1}> <{2}> <{3}>
|
||||
> ./g [4] ./index.js 7:0-13
|
||||
[7] ./g.js 916 bytes {0} [built]
|
||||
chunk {1} 077726e3805b482fd93e.js 1.87 KiB ={2}= ={3}= >{0}< [entry] [rendered]
|
||||
chunk {1} f2e891598128a57b072c.js 1.87 KiB ={2}= ={3}= >{0}< [entry] [rendered]
|
||||
> ./index main
|
||||
[3] ./e.js 899 bytes {1} [built]
|
||||
[4] ./index.js 111 bytes {1} [built]
|
||||
|
@ -57,7 +57,7 @@ Child content-change:
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for aggressive-splitting-on-demand 1`] = `
|
||||
"Hash: d1ec33892177d3771968
|
||||
"Hash: 84ad1d7e4c9cdd4b13e4
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -71,9 +71,9 @@ d6418937dfae4b3ee922.js 1 KiB 1 [emitted]
|
|||
685acdc95ff4af957f47.js 1 KiB 7 [emitted]
|
||||
606f48c13070850338b1.js 1.94 KiB 8 [emitted]
|
||||
c5a8eae840969538f450.js 1.94 KiB 9 [emitted]
|
||||
3bf16d513625c7c39e6f.js 8.68 KiB 10 [emitted] main
|
||||
c69b2f79fdf6e98907c4.js 8.68 KiB 10 [emitted] main
|
||||
fcdf398c8972e4dcf788.js 1.94 KiB 11 [emitted]
|
||||
Entrypoint main = 3bf16d513625c7c39e6f.js
|
||||
Entrypoint main = c69b2f79fdf6e98907c4.js
|
||||
chunk {0} fd868baa40dab4fc30fd.js 1.76 KiB <{10}> ={1}= ={2}= ={3}= ={7}= ={9}= [recorded] aggressive splitted
|
||||
> ./b ./d ./e ./f ./g [11] ./index.js 5:0-44
|
||||
> ./b ./d ./e ./f ./g ./h ./i ./j ./k [11] ./index.js 6:0-72
|
||||
|
@ -115,7 +115,7 @@ chunk {9} c5a8eae840969538f450.js 1.76 KiB <{10}> ={0}= ={2}= ={3}= ={7}= [re
|
|||
> ./b ./d ./e ./f ./g ./h ./i ./j ./k [11] ./index.js 6:0-72
|
||||
[7] ./i.js 899 bytes {9} {11} [built]
|
||||
[8] ./j.js 901 bytes {6} {9} [built]
|
||||
chunk {10} 3bf16d513625c7c39e6f.js (main) 248 bytes >{0}< >{1}< >{11}< >{2}< >{3}< >{4}< >{5}< >{6}< >{7}< >{8}< >{9}< [entry] [rendered]
|
||||
chunk {10} c69b2f79fdf6e98907c4.js (main) 248 bytes >{0}< >{1}< >{11}< >{2}< >{3}< >{4}< >{5}< >{6}< >{7}< >{8}< >{9}< [entry] [rendered]
|
||||
> ./index main
|
||||
[11] ./index.js 248 bytes {10} [built]
|
||||
chunk {11} fcdf398c8972e4dcf788.js 1.76 KiB <{10}> ={2}= ={6}= [rendered] [recorded] aggressive splitted
|
||||
|
@ -467,7 +467,7 @@ Child all:
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = `
|
||||
"Hash: 0bb3f504cf6cc3cbace1
|
||||
"Hash: bc5067cf597a5fece180
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -492,7 +492,7 @@ chunk {1} main1.js (main1) 136 bytes [entry] [rendered]
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for chunks 1`] = `
|
||||
"Hash: 41fab27e5669c037a625
|
||||
"Hash: 329edf3a78275c679fe4
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -530,7 +530,7 @@ chunk {3} 3.bundle.js 44 bytes <{1}> [rendered]
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for chunks-development 1`] = `
|
||||
"Hash: 7724565418b8b6c8467a
|
||||
"Hash: d9a9db28b39a3075bdb3
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -581,7 +581,7 @@ chunk {3} 3.bundle.js (c) 98 bytes <{0}> <{1}> >{0}< >{1}< [rendered]
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for color-disabled 1`] = `
|
||||
"Hash: a6779032127bc5f302b0
|
||||
"Hash: 259c9ad9aa282b7b9017
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 <CLR=BOLD>00:00:00</CLR> GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -591,7 +591,7 @@ Entrypoint main = main.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for color-enabled 1`] = `
|
||||
"Hash: <CLR=BOLD>a6779032127bc5f302b0</CLR>
|
||||
"Hash: <CLR=BOLD>259c9ad9aa282b7b9017</CLR>
|
||||
Time: <CLR=BOLD>X</CLR>ms
|
||||
Built at: Thu Jan 01 1970 <CLR=BOLD>00:00:00</CLR> GMT
|
||||
<CLR=BOLD>Asset</CLR> <CLR=BOLD>Size</CLR> <CLR=BOLD>Chunks</CLR> <CLR=39,BOLD><CLR=22> <CLR=39,BOLD><CLR=22><CLR=BOLD>Chunk Names</CLR>
|
||||
|
@ -601,7 +601,7 @@ Entrypoint <CLR=BOLD>main</CLR> = <CLR=32,BOLD>main.js</CLR>
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for color-enabled-custom 1`] = `
|
||||
"Hash: <CLR=BOLD>a6779032127bc5f302b0</CLR>
|
||||
"Hash: <CLR=BOLD>259c9ad9aa282b7b9017</CLR>
|
||||
Time: <CLR=BOLD>X</CLR>ms
|
||||
Built at: Thu Jan 01 1970 <CLR=BOLD>00:00:00</CLR> GMT
|
||||
<CLR=BOLD>Asset</CLR> <CLR=BOLD>Size</CLR> <CLR=BOLD>Chunks</CLR> <CLR=39,BOLD><CLR=22> <CLR=39,BOLD><CLR=22><CLR=BOLD>Chunk Names</CLR>
|
||||
|
@ -611,7 +611,7 @@ Entrypoint <CLR=BOLD>main</CLR> = <CLR=32>main.js</CLR>
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for commons-chunk-min-size-0 1`] = `
|
||||
"Hash: fe1218333b65ce9f8634
|
||||
"Hash: ba7c69f3acc19ed72f3f
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -628,7 +628,7 @@ Entrypoint entry-1 = vendor-1~entry-1.js entry-1.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for commons-chunk-min-size-Infinity 1`] = `
|
||||
"Hash: 795be68665d680b959bb
|
||||
"Hash: f8b8bebc8cf37cf02f7f
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -645,9 +645,9 @@ Entrypoint entry-1 = vendor-1.js entry-1.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for commons-plugin-issue-4980 1`] = `
|
||||
"Hash: 3da37f8a7e9d647c86531c172aabb881b93ba6be
|
||||
"Hash: b7026c887b1a4d42c4c08b5ecbff0d004a138881
|
||||
Child
|
||||
Hash: 3da37f8a7e9d647c8653
|
||||
Hash: b7026c887b1a4d42c4c0
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -660,7 +660,7 @@ Child
|
|||
| ./submodule-a.js 59 bytes [built]
|
||||
| ./submodule-b.js 59 bytes [built]
|
||||
Child
|
||||
Hash: 1c172aabb881b93ba6be
|
||||
Hash: 8b5ecbff0d004a138881
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -693,9 +693,9 @@ exports[`StatsTestCases should print correct stats for concat-and-sideeffects 1`
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for define-plugin 1`] = `
|
||||
"Hash: e7d8a913568c3242d80b39c3fe9ff20894943d05
|
||||
"Hash: efa53b4a8c763381d4296ac4ef4ab386e0e18a8c
|
||||
Child
|
||||
Hash: e7d8a913568c3242d80b
|
||||
Hash: efa53b4a8c763381d429
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -703,7 +703,7 @@ Child
|
|||
Entrypoint main = main.js
|
||||
[0] ./index.js 24 bytes {0} [built]
|
||||
Child
|
||||
Hash: 39c3fe9ff20894943d05
|
||||
Hash: 6ac4ef4ab386e0e18a8c
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -713,7 +713,7 @@ Child
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for exclude-with-loader 1`] = `
|
||||
"Hash: 0bfe3f933dc07ac74c68
|
||||
"Hash: 82110ff5e7d166cc4117
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -726,7 +726,7 @@ Entrypoint main = bundle.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for external 1`] = `
|
||||
"Hash: c978d13c314f28182daa
|
||||
"Hash: 447b77fa7bc9bbdfcf31
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -737,9 +737,9 @@ Entrypoint main = main.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for filter-warnings 1`] = `
|
||||
"Hash: 894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d894b7278b69dd6b1969d
|
||||
"Hash: a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25a128fafbc2b7d659de25
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -759,49 +759,49 @@ Child
|
|||
Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0]
|
||||
Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0]
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
bundle.js 2.19 KiB 0 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
bundle.js 2.19 KiB 0 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
bundle.js 2.19 KiB 0 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
bundle.js 2.19 KiB 0 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
bundle.js 2.19 KiB 0 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
bundle.js 2.19 KiB 0 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -821,7 +821,7 @@ Child
|
|||
Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0]
|
||||
Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0]
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -841,7 +841,7 @@ Child
|
|||
Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0]
|
||||
Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0]
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -861,7 +861,7 @@ Child
|
|||
Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0]
|
||||
Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0]
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -881,7 +881,7 @@ Child
|
|||
Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0]
|
||||
Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0]
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -901,7 +901,7 @@ Child
|
|||
Dropping unused function someRemoteUnUsedFunction4 [./a.js:6,0]
|
||||
Dropping unused function someRemoteUnUsedFunction5 [./a.js:7,0]
|
||||
Child
|
||||
Hash: 894b7278b69dd6b1969d
|
||||
Hash: a128fafbc2b7d659de25
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -978,7 +978,7 @@ chunk {5} b.js (b) 179 bytes <{2}> >{1}< [rendered]
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for import-context-filter 1`] = `
|
||||
"Hash: e08ae3f7bf8b895ac342
|
||||
"Hash: f249efcc0232c180bf68
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -995,7 +995,7 @@ Entrypoint entry = entry.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for import-weak 1`] = `
|
||||
"Hash: 59a0e9590a7c1754c76d
|
||||
"Hash: 9cccc27b7625bd171c12
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1008,9 +1008,9 @@ Entrypoint entry = entry.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for limit-chunk-count-plugin 1`] = `
|
||||
"Hash: fbf4374d5e6774f1f5763193fa6cb748ec53112f17662c5c606c0e127c765794818a8074e5c164c7
|
||||
"Hash: 3c127dca42ce1c13b8eae6c0ceac1aa3be512946a5969fc94d792cce5364503bf42779f704747e2d
|
||||
Child 1 chunks:
|
||||
Hash: fbf4374d5e6774f1f576
|
||||
Hash: 3c127dca42ce1c13b8ea
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1024,7 +1024,7 @@ Child 1 chunks:
|
|||
[4] ./d.js 22 bytes {0} [built]
|
||||
[5] ./e.js 22 bytes {0} [built]
|
||||
Child 2 chunks:
|
||||
Hash: 3193fa6cb748ec53112f
|
||||
Hash: e6c0ceac1aa3be512946
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1040,7 +1040,7 @@ Child 2 chunks:
|
|||
chunk {1} bundle.js (main) 73 bytes >{0}< [entry] [rendered]
|
||||
[5] ./index.js 73 bytes {1} [built]
|
||||
Child 3 chunks:
|
||||
Hash: 17662c5c606c0e127c76
|
||||
Hash: a5969fc94d792cce5364
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1058,7 +1058,7 @@ Child 3 chunks:
|
|||
chunk {2} bundle.js (main) 73 bytes >{0}< >{1}< [entry] [rendered]
|
||||
[5] ./index.js 73 bytes {2} [built]
|
||||
Child 4 chunks:
|
||||
Hash: 5794818a8074e5c164c7
|
||||
Hash: 503bf42779f704747e2d
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1080,7 +1080,7 @@ Child 4 chunks:
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for max-modules 1`] = `
|
||||
"Hash: 75aa9fbfda2cb79419d8
|
||||
"Hash: 528955f6d280625ce14d
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1110,7 +1110,7 @@ Entrypoint main = main.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for max-modules-default 1`] = `
|
||||
"Hash: 75aa9fbfda2cb79419d8
|
||||
"Hash: 528955f6d280625ce14d
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1135,7 +1135,7 @@ Entrypoint main = main.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for module-assets 1`] = `
|
||||
"Hash: 50b073bf8c481825a488
|
||||
"Hash: f544bcf110bd1cf43d65
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Entrypoint main = main.js
|
||||
|
@ -1317,7 +1317,7 @@ Child
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for named-chunks-plugin 1`] = `
|
||||
"Hash: bda0a8a2c2ad3a4d41bd
|
||||
"Hash: 4d266c3680a506e31e7e
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1331,7 +1331,7 @@ Entrypoint entry = vendor.js entry.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for named-chunks-plugin-async 1`] = `
|
||||
"Hash: b07ae41580240259728a
|
||||
"Hash: b54cb3a3bc63561b46b3
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1345,7 +1345,7 @@ Entrypoint entry = entry.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for no-emit-on-errors-plugin-with-child-error 1`] = `
|
||||
"Hash: 30e651c30e081df7d6fb
|
||||
"Hash: 6c219bd2ffa7d0ba8efb
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1367,7 +1367,7 @@ Child child:
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for optimize-chunks 1`] = `
|
||||
"Hash: 72023c7499b4b25526da
|
||||
"Hash: 5d3814f1fdaba61ed71c
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1438,9 +1438,9 @@ You may need an appropriate loader to handle this file type.
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for performance-different-mode-and-target 1`] = `
|
||||
"Hash: 1600ea0c15704981d2afb76a49f4a3d86abe6cece7a6e8bbef9e93fb375f94f7ccc27c401fad35731592704355cc413e2afcf8bdd2c0c7cffce662a97f3b443bb4363f92335d
|
||||
"Hash: 36ef9589e3f3c206907d131fd32b3ce1bbf1fb07e0ec393717b117b253ba7bd80de90c69fbe1699ff5afc47fa7eaf1e7303afe2ff2a34c467b43c85c513ab90423c98ca17f51
|
||||
Child
|
||||
Hash: 1600ea0c15704981d2af
|
||||
Hash: 36ef9589e3f3c206907d
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1463,7 +1463,7 @@ Child
|
|||
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
|
||||
For more info visit https://webpack.js.org/guides/code-splitting/
|
||||
Child
|
||||
Hash: b76a49f4a3d86abe6cec
|
||||
Hash: 131fd32b3ce1bbf1fb07
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1486,7 +1486,7 @@ Child
|
|||
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
|
||||
For more info visit https://webpack.js.org/guides/code-splitting/
|
||||
Child
|
||||
Hash: e7a6e8bbef9e93fb375f
|
||||
Hash: e0ec393717b117b253ba
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1494,7 +1494,7 @@ Child
|
|||
Entrypoint main = no-warning.pro-node.js
|
||||
[0] ./index.js 293 KiB {0} [built]
|
||||
Child
|
||||
Hash: 94f7ccc27c401fad3573
|
||||
Hash: 7bd80de90c69fbe1699f
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1502,7 +1502,7 @@ Child
|
|||
Entrypoint main = no-warning.dev-web.js
|
||||
[./index.js] 293 KiB {main} [built]
|
||||
Child
|
||||
Hash: 1592704355cc413e2afc
|
||||
Hash: f5afc47fa7eaf1e7303a
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1510,7 +1510,7 @@ Child
|
|||
Entrypoint main = no-warning.dev-node.js
|
||||
[./index.js] 293 KiB {main} [built]
|
||||
Child
|
||||
Hash: f8bdd2c0c7cffce662a9
|
||||
Hash: fe2ff2a34c467b43c85c
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1518,7 +1518,7 @@ Child
|
|||
Entrypoint main [big] = no-warning.dev-web-with-limit-set.js
|
||||
[./index.js] 293 KiB {main} [built]
|
||||
Child
|
||||
Hash: 7f3b443bb4363f92335d
|
||||
Hash: 513ab90423c98ca17f51
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1719,7 +1719,7 @@ chunk {6} inner2.js (inner2) 0 bytes <{0}> [rendered]"
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for preset-detailed 1`] = `
|
||||
"Hash: 633de649e1fd60300acb
|
||||
"Hash: 8abc26856f4ca9b61679
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1778,7 +1778,7 @@ exports[`StatsTestCases should print correct stats for preset-none-array 1`] = `
|
|||
exports[`StatsTestCases should print correct stats for preset-none-error 1`] = `""`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for preset-normal 1`] = `
|
||||
"Hash: 633de649e1fd60300acb
|
||||
"Hash: 8abc26856f4ca9b61679
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1856,7 +1856,7 @@ Entrypoints:
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for preset-verbose 1`] = `
|
||||
"Hash: 633de649e1fd60300acb
|
||||
"Hash: 8abc26856f4ca9b61679
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1900,7 +1900,7 @@ chunk {3} 3.js 44 bytes <{1}> [rendered]
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for resolve-plugin-context 1`] = `
|
||||
"Hash: b03156e9d530e0fdde16
|
||||
"Hash: 11a1659e0148f10e3a15
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1914,7 +1914,7 @@ Entrypoint main = bundle.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for reverse-sort-modules 1`] = `
|
||||
"Hash: 75aa9fbfda2cb79419d8
|
||||
"Hash: 528955f6d280625ce14d
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -1979,7 +1979,7 @@ Entrypoint e2 = runtime.js e2.js"
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for scope-hoisting-bailouts 1`] = `
|
||||
"Hash: eca97dadc365a5ea9495
|
||||
"Hash: 6c000e1efebf892a7639
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Entrypoint index = index.js
|
||||
|
@ -2011,9 +2011,9 @@ Entrypoint entry = entry.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = `
|
||||
"Hash: 649bc82f0ddfa78bf8265487d50fbccae514909d
|
||||
"Hash: 3354b6776c2bb6b558f4c9101316bd6316bf5251
|
||||
Child
|
||||
Hash: 649bc82f0ddfa78bf826
|
||||
Hash: 3354b6776c2bb6b558f4
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Entrypoint first = vendor.js first.js
|
||||
|
@ -2030,7 +2030,7 @@ Child
|
|||
[9] ./module_first.js 31 bytes {4} [built]
|
||||
[10] ./second.js 177 bytes {5} [built]
|
||||
Child
|
||||
Hash: 5487d50fbccae514909d
|
||||
Hash: c9101316bd6316bf5251
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Entrypoint first = vendor.js first.js
|
||||
|
@ -2058,7 +2058,7 @@ Child
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for simple 1`] = `
|
||||
"Hash: 85e288d6fa103903dde9
|
||||
"Hash: 1843cc9aed8366594774
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -2068,7 +2068,7 @@ Entrypoint main = bundle.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for simple-more-info 1`] = `
|
||||
"Hash: f252a9e1a2892c292e8e
|
||||
"Hash: c4097b5edb272ec4b73c
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -2574,7 +2574,7 @@ chunk {4} default/main.js (main) 147 bytes >{0}< >{1}< >{2}< >{3}< [entry] [r
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for tree-shaking 1`] = `
|
||||
"Hash: 268985187bb6f35a0709
|
||||
"Hash: 9470b99b4586c4006572
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
@ -2611,7 +2611,7 @@ Entrypoint main = bundle.js
|
|||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for warnings-uglifyjs 1`] = `
|
||||
"Hash: c9585261f508c0a85e1b
|
||||
"Hash: c0402129c5c14a0d4a19
|
||||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
it("should support wasm compiled from c++", function() {
|
||||
return import("./memory3.wasm").then(function(wasm) {
|
||||
expect(wasm._Z3getv()).toBe(0);
|
||||
wasm._Z3seti(42);
|
||||
expect(wasm._Z3getv()).toBe(42);
|
||||
});
|
||||
});
|
||||
|
||||
it("should raw memory export without data", function() {
|
||||
return import("./memory2.wasm").then(function(wasm) {
|
||||
expect(wasm.memory).toBeInstanceOf(WebAssembly.Memory);
|
||||
expect(wasm.memory.buffer).toBeInstanceOf(ArrayBuffer);
|
||||
expect(wasm.memory.buffer.byteLength).toBe(1 << 16);
|
||||
});
|
||||
});
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||
|
||||
module.exports = function(config) {
|
||||
return supportsWebAssembly();
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
it("should allow direct memory connection between wasm modules", function() {
|
||||
return import("./run").then(function(module) {
|
||||
expect(module.x1).toBe(42);
|
||||
expect(module.x2).toBe(42);
|
||||
expect(module.y1).toBe(11);
|
||||
expect(module.y2).toBe(11);
|
||||
});
|
||||
});
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,9 @@
|
|||
import * as a1 from "./mem-access.wasm?1";
|
||||
import * as a2 from "./mem-access.wasm?2";
|
||||
|
||||
a1.set(42);
|
||||
export const x1 = a1.get();
|
||||
export const x2 = a2.get();
|
||||
a2.set(11);
|
||||
export const y1 = a1.get();
|
||||
export const y2 = a2.get();
|
|
@ -0,0 +1,5 @@
|
|||
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||
|
||||
module.exports = function(config) {
|
||||
return supportsWebAssembly();
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
// the message is inconsistency between some nodejs versions
|
||||
const UNKNOWN_FUNCTION_TABLE = /invalid index into function table|invalid function/;
|
||||
|
||||
it("should support tables", function() {
|
||||
return import("./wasm-table.wasm").then(function(wasm) {
|
||||
expect(wasm.callByIndex(0)).toEqual(42);
|
||||
expect(wasm.callByIndex(1)).toEqual(13);
|
||||
expect(() => wasm.callByIndex(2)).toThrow(UNKNOWN_FUNCTION_TABLE);
|
||||
});
|
||||
});
|
||||
|
||||
it("should support exported tables", function() {
|
||||
return import("./wasm-table-export.wasm").then(function(wasm) {
|
||||
expect(wasm.table).toBeInstanceOf(WebAssembly.Table);
|
||||
expect(wasm.table.length).toBe(2);
|
||||
const e0 = wasm.table.get(0);
|
||||
const e1 = wasm.table.get(1);
|
||||
expect(e0).toBeInstanceOf(Function);
|
||||
expect(e1).toBeInstanceOf(Function);
|
||||
expect(e0()).toEqual(42);
|
||||
expect(e1()).toEqual(13);
|
||||
});
|
||||
});
|
||||
|
||||
it("should support imported tables", function() {
|
||||
return import("./wasm-table-imported.wasm").then(function(wasm) {
|
||||
expect(wasm.callByIndex(0)).toEqual(42);
|
||||
expect(wasm.callByIndex(1)).toEqual(13);
|
||||
expect(() => wasm.callByIndex(2)).toThrow(UNKNOWN_FUNCTION_TABLE);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||
|
||||
module.exports = function(config) {
|
||||
return supportsWebAssembly();
|
||||
};
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,18 @@
|
|||
it("should allow to run a WebAssembly module with imports", function() {
|
||||
return import("./wasm.wasm").then(function(wasm) {
|
||||
const result = wasm.get();
|
||||
switch(WATCH_STEP) {
|
||||
case "0":
|
||||
expect(result).toEqual(9);
|
||||
break;
|
||||
case "1":
|
||||
expect(result).toEqual(10);
|
||||
break;
|
||||
case "2":
|
||||
expect(result).toEqual(42);
|
||||
break;
|
||||
default:
|
||||
throw new Error("should not happen");
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
export function getNumber() {
|
||||
return 8;
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
export function getNumber() {
|
||||
return 40;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||
|
||||
module.exports = function(config) {
|
||||
return supportsWebAssembly();
|
||||
};
|
133
yarn.lock
133
yarn.lock
|
@ -18,6 +18,117 @@
|
|||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd"
|
||||
|
||||
"@webassemblyjs/ast@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.3.0.tgz#524246cd578c30ff792d0c7b49bb0a0f89191dd2"
|
||||
dependencies:
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.3.0"
|
||||
"@webassemblyjs/wast-parser" "1.3.0"
|
||||
webassemblyjs "1.3.0"
|
||||
|
||||
"@webassemblyjs/floating-point-hex-parser@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.3.0.tgz#a32574e1327a946c78711179fda8bcc808285913"
|
||||
|
||||
"@webassemblyjs/helper-buffer@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.3.0.tgz#790599218673099863b6f5f84d36cc8caab861b2"
|
||||
|
||||
"@webassemblyjs/helper-code-frame@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.3.0.tgz#8f7d4cd9a2aed3c633cdd79aa660e96279a349bf"
|
||||
dependencies:
|
||||
"@webassemblyjs/wast-printer" "1.3.0"
|
||||
|
||||
"@webassemblyjs/helper-fsm@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.3.0.tgz#515141ec51c47b892def606dfc706e7708d4398a"
|
||||
|
||||
"@webassemblyjs/helper-wasm-bytecode@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.3.0.tgz#d23d55fcef04e4f24d6728e31bda8f1257293f91"
|
||||
|
||||
"@webassemblyjs/helper-wasm-section@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.3.0.tgz#a8c9435faca44734fc67dfaee4911ac8e6627bd7"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/helper-buffer" "1.3.0"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.3.0"
|
||||
"@webassemblyjs/wasm-gen" "1.3.0"
|
||||
|
||||
"@webassemblyjs/leb128@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.3.0.tgz#b9995160f0f94d785579a149716bb2cb0d102f08"
|
||||
dependencies:
|
||||
leb "^0.3.0"
|
||||
|
||||
"@webassemblyjs/validation@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/validation/-/validation-1.3.0.tgz#0a1261f414607a04e2ffebb1b3ea9777b35c97af"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
|
||||
"@webassemblyjs/wasm-edit@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.3.0.tgz#48551c391aebb07e82634cd4ecf257456208a0d3"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/helper-buffer" "1.3.0"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.3.0"
|
||||
"@webassemblyjs/helper-wasm-section" "1.3.0"
|
||||
"@webassemblyjs/wasm-gen" "1.3.0"
|
||||
"@webassemblyjs/wasm-opt" "1.3.0"
|
||||
"@webassemblyjs/wasm-parser" "1.3.0"
|
||||
"@webassemblyjs/wast-printer" "1.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
"@webassemblyjs/wasm-gen@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.3.0.tgz#acf45b38159f351178aa14135e5efa4172931e9a"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.3.0"
|
||||
"@webassemblyjs/leb128" "1.3.0"
|
||||
|
||||
"@webassemblyjs/wasm-opt@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.3.0.tgz#958150b0d631eb407fc9b85b9a852526c849c015"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/helper-buffer" "1.3.0"
|
||||
"@webassemblyjs/wasm-gen" "1.3.0"
|
||||
"@webassemblyjs/wasm-parser" "1.3.0"
|
||||
|
||||
"@webassemblyjs/wasm-parser@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.3.0.tgz#66dd5ac632e0f938b1656bd46f01fe5f5f9488d0"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.3.0"
|
||||
"@webassemblyjs/leb128" "1.3.0"
|
||||
"@webassemblyjs/wasm-parser" "1.3.0"
|
||||
webassemblyjs "1.3.0"
|
||||
|
||||
"@webassemblyjs/wast-parser@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.3.0.tgz#bfc692d8a159d5fde7c1fee0f4e6d848d5bbcb71"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/floating-point-hex-parser" "1.3.0"
|
||||
"@webassemblyjs/helper-code-frame" "1.3.0"
|
||||
"@webassemblyjs/helper-fsm" "1.3.0"
|
||||
long "^3.2.0"
|
||||
webassemblyjs "1.3.0"
|
||||
|
||||
"@webassemblyjs/wast-printer@1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.3.0.tgz#b4ed84f0fea9f222d540e25b262cd5eabfee84d4"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/wast-parser" "1.3.0"
|
||||
long "^3.2.0"
|
||||
|
||||
abab@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"
|
||||
|
@ -795,7 +906,7 @@ chalk@^1.1.1, chalk@^1.1.3:
|
|||
strip-ansi "^3.0.0"
|
||||
supports-color "^2.0.0"
|
||||
|
||||
chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.2:
|
||||
chalk@^2.0.0, chalk@^2.3.2:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
|
||||
dependencies:
|
||||
|
@ -803,7 +914,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.2:
|
|||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^2.0.1:
|
||||
chalk@^2.0.1, chalk@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
|
||||
dependencies:
|
||||
|
@ -3468,6 +3579,10 @@ lcov-parse@^1.x:
|
|||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0"
|
||||
|
||||
leb@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/leb/-/leb-0.3.0.tgz#32bee9fad168328d6aea8522d833f4180eed1da3"
|
||||
|
||||
left-pad@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee"
|
||||
|
@ -3578,6 +3693,10 @@ lolex@^1.6.0:
|
|||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
|
||||
|
||||
long@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
|
||||
|
||||
longest@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
|
||||
|
@ -6035,6 +6154,16 @@ watchpack@^1.5.0:
|
|||
graceful-fs "^4.1.2"
|
||||
neo-async "^2.5.0"
|
||||
|
||||
webassemblyjs@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/webassemblyjs/-/webassemblyjs-1.3.0.tgz#970ca465d5ee45ebe611c5c6f7d461900c3e10b2"
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.3.0"
|
||||
"@webassemblyjs/validation" "1.3.0"
|
||||
"@webassemblyjs/wasm-parser" "1.3.0"
|
||||
"@webassemblyjs/wast-parser" "1.3.0"
|
||||
long "^3.2.0"
|
||||
|
||||
webidl-conversions@^4.0.1, webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
|
|
Loading…
Reference in New Issue