mirror of https://github.com/webpack/webpack.git
Merge branch 'master' into feature/module-build-error-with-loader-name
# Conflicts: # lib/ModuleBuildError.js # lib/ModuleError.js # lib/ModuleWarning.js
This commit is contained in:
commit
9fbe914078
|
|
@ -36,6 +36,7 @@ declare module "@webassemblyjs/ast" {
|
|||
ModuleImport?: (p: NodePath<ModuleImport>) => void;
|
||||
ModuleExport?: (p: NodePath<ModuleExport>) => void;
|
||||
Start?: (p: NodePath<Start>) => void;
|
||||
Global?: (p: NodePath<Global>) => void;
|
||||
}
|
||||
);
|
||||
export class NodePath<T> {
|
||||
|
|
@ -60,28 +61,46 @@ declare module "@webassemblyjs/ast" {
|
|||
}
|
||||
export class ModuleExport extends Node {
|
||||
name: string;
|
||||
descr: ModuleExportDescr;
|
||||
}
|
||||
type Index = Identifier | NumberLiteral;
|
||||
export class ModuleExportDescr extends Node {
|
||||
type: string;
|
||||
exportType: string;
|
||||
id: Index;
|
||||
}
|
||||
export class NumberLiteral extends Node {
|
||||
value: number;
|
||||
raw: string;
|
||||
}
|
||||
export class ModuleExportDescr extends Node {}
|
||||
export class IndexLiteral extends Node {}
|
||||
export class NumberLiteral extends Node {}
|
||||
export class FloatLiteral extends Node {}
|
||||
export class Global extends Node {}
|
||||
export class GlobalType extends Node {
|
||||
valtype: string;
|
||||
}
|
||||
export class Global extends Node {
|
||||
init: Instruction[];
|
||||
globalType: GlobalType;
|
||||
}
|
||||
export class FuncParam extends Node {
|
||||
valtype: string;
|
||||
}
|
||||
export class Instruction extends Node {}
|
||||
export class Instruction extends Node {
|
||||
id: string;
|
||||
args: NumberLiteral[];
|
||||
}
|
||||
export class CallInstruction extends Instruction {}
|
||||
export class ObjectInstruction extends Instruction {}
|
||||
export class Func extends Node {
|
||||
signature: Signature;
|
||||
}
|
||||
export class Signature {
|
||||
type: "Signature";
|
||||
params: FuncParam[];
|
||||
results: string[];
|
||||
}
|
||||
export class TypeInstruction extends Node {}
|
||||
export class IndexInFuncSection extends Node {}
|
||||
export function indexLiteral(index: number): IndexLiteral;
|
||||
export function indexLiteral(index: number): Index;
|
||||
export function numberLiteralFromRaw(num: number): NumberLiteral;
|
||||
export function floatLiteral(
|
||||
value: number,
|
||||
|
|
@ -93,29 +112,33 @@ declare module "@webassemblyjs/ast" {
|
|||
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 callInstruction(funcIndex: Index): CallInstruction;
|
||||
export function objectInstruction(
|
||||
kind: string,
|
||||
type: string,
|
||||
init: Node[]
|
||||
): ObjectInstruction;
|
||||
export function signature(params: FuncParam[], results: string[]): Signature;
|
||||
export function func(initFuncId, Signature, funcBody): Func;
|
||||
export function func(initFuncId, signature: Signature, funcBody): Func;
|
||||
export function typeInstruction(
|
||||
id: Identifier,
|
||||
functype: Signature
|
||||
): TypeInstruction;
|
||||
export function indexInFuncSection(index: IndexLiteral): IndexInFuncSection;
|
||||
export function indexInFuncSection(index: Index): IndexInFuncSection;
|
||||
export function moduleExport(
|
||||
identifier: string,
|
||||
descr: ModuleExportDescr
|
||||
): ModuleExport;
|
||||
export function moduleExportDescr(
|
||||
type: string,
|
||||
index: ModuleExportDescr
|
||||
): ModuleExport;
|
||||
index: Index
|
||||
): ModuleExportDescr;
|
||||
|
||||
export function getSectionMetadata(ast: any, section: string);
|
||||
export class FuncSignature {
|
||||
args: string[];
|
||||
result: string[];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ class AsyncDependencyToInitialChunkError extends WebpackError {
|
|||
* @param {TODO} loc location of dependency
|
||||
*/
|
||||
constructor(chunkName, module, loc) {
|
||||
super();
|
||||
super(
|
||||
`It's not allowed to load an initial chunk on demand. The chunk name "${chunkName}" is already used by an entrypoint.`
|
||||
);
|
||||
|
||||
this.name = "AsyncDependencyToInitialChunkError";
|
||||
this.message = `It's not allowed to load an initial chunk on demand. The chunk name "${chunkName}" is already used by an entrypoint.`;
|
||||
this.module = module;
|
||||
this.origin = module;
|
||||
this.originLoc = loc;
|
||||
this.loc = loc;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,64 +8,60 @@ const WebpackError = require("./WebpackError");
|
|||
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
||||
/**
|
||||
* @param {Module[]} modules the modules to be sorted
|
||||
* @returns {Module[]} sorted version of original modules
|
||||
*/
|
||||
const sortModules = modules => {
|
||||
return modules.slice().sort((a, b) => {
|
||||
a = a.identifier();
|
||||
b = b.identifier();
|
||||
/* istanbul ignore next */
|
||||
if (a < b) return -1;
|
||||
/* istanbul ignore next */
|
||||
if (a > b) return 1;
|
||||
/* istanbul ignore next */
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Module[]} modules each module from throw
|
||||
* @returns {string} each message from provided moduels
|
||||
*/
|
||||
const createModulesListMessage = modules => {
|
||||
return modules
|
||||
.map(m => {
|
||||
let message = `* ${m.identifier()}`;
|
||||
const validReasons = m.reasons.filter(reason => reason.module);
|
||||
|
||||
if (validReasons.length > 0) {
|
||||
message += `\n Used by ${validReasons.length} module(s), i. e.`;
|
||||
message += `\n ${validReasons[0].module.identifier()}`;
|
||||
}
|
||||
return message;
|
||||
})
|
||||
.join("\n");
|
||||
};
|
||||
|
||||
class CaseSensitiveModulesWarning extends WebpackError {
|
||||
/**
|
||||
* Creates an instance of CaseSensitiveModulesWarning.
|
||||
* @param {Module[]} modules modules that were detected
|
||||
*/
|
||||
constructor(modules) {
|
||||
super();
|
||||
|
||||
this.name = "CaseSensitiveModulesWarning";
|
||||
const sortedModules = this._sort(modules);
|
||||
const modulesList = this._moduleMessages(sortedModules);
|
||||
this.message = `There are multiple modules with names that only differ in casing.
|
||||
const sortedModules = sortModules(modules);
|
||||
const modulesList = createModulesListMessage(sortedModules);
|
||||
super(`There are multiple modules with names that only differ in casing.
|
||||
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
|
||||
Use equal casing. Compare these module identifiers:
|
||||
${modulesList}`;
|
||||
${modulesList}`);
|
||||
|
||||
this.name = "CaseSensitiveModulesWarning";
|
||||
this.origin = this.module = sortedModules[0];
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Module[]} modules the modules to be sorted
|
||||
* @returns {Module[]} sorted version of original modules
|
||||
*/
|
||||
_sort(modules) {
|
||||
return modules.slice().sort((a, b) => {
|
||||
a = a.identifier();
|
||||
b = b.identifier();
|
||||
/* istanbul ignore next */
|
||||
if (a < b) return -1;
|
||||
/* istanbul ignore next */
|
||||
if (a > b) return 1;
|
||||
/* istanbul ignore next */
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Module[]} modules each module from throw
|
||||
* @returns {string} each message from provided moduels
|
||||
*/
|
||||
_moduleMessages(modules) {
|
||||
return modules
|
||||
.map(m => {
|
||||
let message = `* ${m.identifier()}`;
|
||||
const validReasons = m.reasons.filter(reason => reason.module);
|
||||
|
||||
if (validReasons.length > 0) {
|
||||
message += `\n Used by ${validReasons.length} module(s), i. e.`;
|
||||
message += `\n ${validReasons[0].module.identifier()}`;
|
||||
}
|
||||
return message;
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CaseSensitiveModulesWarning;
|
||||
|
|
|
|||
13
lib/Chunk.js
13
lib/Chunk.js
|
|
@ -607,10 +607,10 @@ class Chunk {
|
|||
return result;
|
||||
}
|
||||
|
||||
getChildIdsByOrdersMap() {
|
||||
getChildIdsByOrdersMap(includeDirectChildren) {
|
||||
const chunkMaps = Object.create(null);
|
||||
|
||||
for (const chunk of this.getAllAsyncChunks()) {
|
||||
const addChildIdsByOrdersToMap = chunk => {
|
||||
const data = chunk.getChildIdsByOrders();
|
||||
for (const key of Object.keys(data)) {
|
||||
let chunkMap = chunkMaps[key];
|
||||
|
|
@ -619,7 +619,16 @@ class Chunk {
|
|||
}
|
||||
chunkMap[chunk.id] = data[key];
|
||||
}
|
||||
};
|
||||
|
||||
if (includeDirectChildren) {
|
||||
addChildIdsByOrdersToMap(this);
|
||||
}
|
||||
|
||||
for (const chunk of this.getAllAsyncChunks()) {
|
||||
addChildIdsByOrdersToMap(chunk);
|
||||
}
|
||||
|
||||
return chunkMaps;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const WebpackError = require("./WebpackError");
|
||||
|
||||
class CommentCompilationWarning extends WebpackError {
|
||||
constructor(message, module, loc) {
|
||||
super(message);
|
||||
|
||||
this.name = "CommentCompilationWarning";
|
||||
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CommentCompilationWarning;
|
||||
|
|
@ -487,6 +487,7 @@ class Compilation extends Tapable {
|
|||
|
||||
const errorAndCallback = err => {
|
||||
err.origin = module;
|
||||
err.dependencies = dependencies;
|
||||
this.errors.push(err);
|
||||
if (bail) {
|
||||
callback(err);
|
||||
|
|
@ -531,7 +532,7 @@ class Compilation extends Tapable {
|
|||
if (err) {
|
||||
semaphore.release();
|
||||
return errorOrWarningAndCallback(
|
||||
new ModuleNotFoundError(module, err, dependencies)
|
||||
new ModuleNotFoundError(module, err)
|
||||
);
|
||||
}
|
||||
if (!dependentModule) {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,9 @@ const WebpackError = require("./WebpackError");
|
|||
|
||||
class EntryModuleNotFoundError extends WebpackError {
|
||||
constructor(err) {
|
||||
super();
|
||||
super("Entry module not found: " + err);
|
||||
|
||||
this.name = "EntryModuleNotFoundError";
|
||||
this.message = "Entry module not found: " + err;
|
||||
this.details = err.details;
|
||||
this.error = err;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ const WebpackError = require("./WebpackError");
|
|||
module.exports = class HarmonyLinkingError extends WebpackError {
|
||||
/** @param {string} message Error message */
|
||||
constructor(message) {
|
||||
super();
|
||||
super(message);
|
||||
this.name = "HarmonyLinkingError";
|
||||
this.message = message;
|
||||
this.hideStack = true;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
|
|
|||
|
|
@ -9,41 +9,38 @@ const { cutOffLoaderExecution } = require("./ErrorHelpers");
|
|||
|
||||
class ModuleBuildError extends WebpackError {
|
||||
constructor(module, err, { from = null } = {}) {
|
||||
super();
|
||||
|
||||
this.name = "ModuleBuildError";
|
||||
this.message = "Module build failed";
|
||||
let message = "Module build failed";
|
||||
let details = undefined;
|
||||
if (from) {
|
||||
this.message += ` (from ${from})`;
|
||||
message += ` (from ${from})`;
|
||||
}
|
||||
|
||||
let message;
|
||||
message += ": ";
|
||||
if (err !== null && typeof err === "object") {
|
||||
if (typeof err.stack === "string" && err.stack) {
|
||||
const stack = cutOffLoaderExecution(err.stack);
|
||||
if (!err.hideStack) {
|
||||
message = stack;
|
||||
message += stack;
|
||||
} else {
|
||||
this.details = stack;
|
||||
details = stack;
|
||||
if (typeof err.message === "string" && err.message) {
|
||||
message = err.message;
|
||||
message += err.message;
|
||||
} else {
|
||||
message = err;
|
||||
message += err;
|
||||
}
|
||||
}
|
||||
} else if (typeof err.message === "string" && err.message) {
|
||||
message = err.message;
|
||||
message += err.message;
|
||||
} else {
|
||||
message = err;
|
||||
message += err;
|
||||
}
|
||||
} else {
|
||||
message = err;
|
||||
}
|
||||
|
||||
if (message !== "") {
|
||||
this.message += `:\n${message}`;
|
||||
}
|
||||
super(message);
|
||||
|
||||
this.name = "ModuleBuildError";
|
||||
this.details = details;
|
||||
this.module = module;
|
||||
this.error = err;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
"use strict";
|
||||
|
||||
const WebpackError = require("./WebpackError");
|
||||
const formatLocation = require("./formatLocation");
|
||||
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
||||
|
|
@ -17,16 +16,17 @@ class ModuleDependencyError extends WebpackError {
|
|||
* @param {TODO} loc location of dependency
|
||||
*/
|
||||
constructor(module, err, loc) {
|
||||
super();
|
||||
super(err.message);
|
||||
|
||||
this.name = "ModuleDependencyError";
|
||||
this.message = `${formatLocation(loc)} ${err.message}`;
|
||||
this.details = err.stack
|
||||
.split("\n")
|
||||
.slice(1)
|
||||
.join("\n");
|
||||
this.origin = this.module = module;
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
this.error = err;
|
||||
this.origin = module.issuer;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,20 @@
|
|||
"use strict";
|
||||
|
||||
const WebpackError = require("./WebpackError");
|
||||
const formatLocation = require("./formatLocation");
|
||||
|
||||
module.exports = class ModuleDependencyWarning extends WebpackError {
|
||||
constructor(module, err, loc) {
|
||||
super();
|
||||
super(err.message);
|
||||
|
||||
this.name = "ModuleDependencyWarning";
|
||||
this.message = `${formatLocation(loc)} ${err.message}`;
|
||||
this.details = err.stack
|
||||
.split("\n")
|
||||
.slice(1)
|
||||
.join("\n");
|
||||
this.origin = this.module = module;
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
this.error = err;
|
||||
this.origin = module.issuer;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,19 +9,18 @@ const { cleanUp } = require("./ErrorHelpers");
|
|||
|
||||
class ModuleError extends WebpackError {
|
||||
constructor(module, err, { from = null } = {}) {
|
||||
super();
|
||||
|
||||
this.name = "ModuleError";
|
||||
this.module = module;
|
||||
this.message = "Module Error";
|
||||
let message = "Module Error";
|
||||
if (from) {
|
||||
this.message += ` (from ${from})`;
|
||||
message += ` (from ${from})`;
|
||||
}
|
||||
if (err && typeof err === "object" && err.message) {
|
||||
this.message += `:\n${err.message}`;
|
||||
message += `:\n${err.message}`;
|
||||
} else if (err) {
|
||||
this.message += `:\n${err}`;
|
||||
message += `:\n${err}`;
|
||||
}
|
||||
super(message);
|
||||
this.name = "ModuleError";
|
||||
this.module = module;
|
||||
this.error = err;
|
||||
this.details =
|
||||
err && typeof err === "object" && err.stack
|
||||
|
|
|
|||
|
|
@ -7,16 +7,13 @@
|
|||
const WebpackError = require("./WebpackError");
|
||||
|
||||
class ModuleNotFoundError extends WebpackError {
|
||||
constructor(module, err, dependencies) {
|
||||
super();
|
||||
constructor(module, err) {
|
||||
super("Module not found: " + err);
|
||||
|
||||
this.name = "ModuleNotFoundError";
|
||||
this.message = "Module not found: " + err;
|
||||
this.details = err.details;
|
||||
this.missing = err.missing;
|
||||
this.module = module;
|
||||
this.origin = module;
|
||||
this.dependencies = dependencies;
|
||||
this.error = err;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
|
|
|||
|
|
@ -6,14 +6,18 @@
|
|||
|
||||
const WebpackError = require("./WebpackError");
|
||||
|
||||
class ModuleParseError extends WebpackError {
|
||||
constructor(module, source, err) {
|
||||
super();
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
||||
this.name = "ModuleParseError";
|
||||
this.message = "Module parse failed: " + err.message;
|
||||
this.message +=
|
||||
"\nYou may need an appropriate loader to handle this file type.";
|
||||
class ModuleParseError extends WebpackError {
|
||||
/**
|
||||
* @param {Module} module the errored module
|
||||
* @param {string} source source code
|
||||
* @param {Error&any} err the parse error
|
||||
*/
|
||||
constructor(module, source, err) {
|
||||
let message = "Module parse failed: " + err.message;
|
||||
let loc = undefined;
|
||||
message += "\nYou may need an appropriate loader to handle this file type.";
|
||||
if (
|
||||
err.loc &&
|
||||
typeof err.loc === "object" &&
|
||||
|
|
@ -22,19 +26,28 @@ class ModuleParseError extends WebpackError {
|
|||
var lineNumber = err.loc.line;
|
||||
if (/[\0\u0001\u0002\u0003\u0004\u0005\u0006\u0007]/.test(source)) {
|
||||
// binary file
|
||||
this.message += "\n(Source code omitted for this binary file)";
|
||||
message += "\n(Source code omitted for this binary file)";
|
||||
} else {
|
||||
source = source.split("\n");
|
||||
this.message +=
|
||||
"\n| " +
|
||||
source
|
||||
.slice(Math.max(0, lineNumber - 3), lineNumber + 2)
|
||||
.join("\n| ");
|
||||
const sourceLines = source.split("\n");
|
||||
const start = Math.max(0, lineNumber - 3);
|
||||
const linesBefore = sourceLines.slice(start, lineNumber - 1);
|
||||
const theLine = sourceLines[lineNumber - 1];
|
||||
const linesAfter = sourceLines.slice(lineNumber, lineNumber + 2);
|
||||
message +=
|
||||
linesBefore.map(l => `\n| ${l}`).join("") +
|
||||
`\n> ${theLine}` +
|
||||
linesAfter.map(l => `\n| ${l}`).join("");
|
||||
}
|
||||
loc = err.loc;
|
||||
} else {
|
||||
this.message += "\n" + err.stack;
|
||||
message += "\n" + err.stack;
|
||||
}
|
||||
|
||||
super(message);
|
||||
|
||||
this.name = "ModuleParseError";
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
this.error = err;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
|
|
|||
|
|
@ -9,19 +9,18 @@ const { cleanUp } = require("./ErrorHelpers");
|
|||
|
||||
class ModuleWarning extends WebpackError {
|
||||
constructor(module, warning, { from = null } = {}) {
|
||||
super();
|
||||
|
||||
this.name = "ModuleWarning";
|
||||
this.module = module;
|
||||
this.message = "Module Warning";
|
||||
let message = "Module Warning";
|
||||
if (from) {
|
||||
this.message += ` (from ${from})`;
|
||||
message += ` (from ${from})`;
|
||||
}
|
||||
if (warning && typeof warning === "object" && warning.message) {
|
||||
this.message += `:\n${warning.message}`;
|
||||
message += `:\n${warning.message}`;
|
||||
} else if (warning) {
|
||||
this.message += `:\n${warning}`;
|
||||
message += `:\n${warning}`;
|
||||
}
|
||||
super(message);
|
||||
this.name = "ModuleWarning";
|
||||
this.module = module;
|
||||
this.warning = warning;
|
||||
this.details =
|
||||
warning && typeof warning === "object" && warning.stack
|
||||
|
|
|
|||
|
|
@ -43,9 +43,18 @@ const contextify = (context, request) => {
|
|||
.split("!")
|
||||
.map(r => {
|
||||
const splitPath = r.split("?");
|
||||
splitPath[0] = path.relative(context, splitPath[0]);
|
||||
if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/");
|
||||
if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0];
|
||||
if (/^[a-zA-Z]:\\/.test(splitPath[0])) {
|
||||
splitPath[0] = path.win32.relative(context, splitPath[0]);
|
||||
if (!/^[a-zA-Z]:\\/.test(splitPath[0])) {
|
||||
splitPath[0] = splitPath[0].replace(/\\/g, "/");
|
||||
}
|
||||
}
|
||||
if (/^\//.test(splitPath[0])) {
|
||||
splitPath[0] = path.posix.relative(context, splitPath[0]);
|
||||
}
|
||||
if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) {
|
||||
splitPath[0] = "./" + splitPath[0];
|
||||
}
|
||||
return splitPath.join("?");
|
||||
})
|
||||
.join("!");
|
||||
|
|
@ -76,6 +85,7 @@ class NormalModule extends Module {
|
|||
rawRequest,
|
||||
loaders,
|
||||
resource,
|
||||
matchResource,
|
||||
parser,
|
||||
generator,
|
||||
resolveOptions
|
||||
|
|
@ -90,6 +100,7 @@ class NormalModule extends Module {
|
|||
this.parser = parser;
|
||||
this.generator = generator;
|
||||
this.resource = resource;
|
||||
this.matchResource = matchResource;
|
||||
this.loaders = loaders;
|
||||
if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
|
||||
|
||||
|
|
@ -123,16 +134,21 @@ class NormalModule extends Module {
|
|||
}
|
||||
|
||||
nameForCondition() {
|
||||
const idx = this.resource.indexOf("?");
|
||||
if (idx >= 0) return this.resource.substr(0, idx);
|
||||
return this.resource;
|
||||
const resource = this.matchResource || this.resource;
|
||||
const idx = resource.indexOf("?");
|
||||
if (idx >= 0) return resource.substr(0, idx);
|
||||
return resource;
|
||||
}
|
||||
|
||||
updateCacheModule(module) {
|
||||
this.type = module.type;
|
||||
this.request = module.request;
|
||||
this.userRequest = module.userRequest;
|
||||
this.rawRequest = module.rawRequest;
|
||||
this.parser = module.parser;
|
||||
this.generator = module.generator;
|
||||
this.resource = module.resource;
|
||||
this.matchResource = module.matchResource;
|
||||
this.loaders = module.loaders;
|
||||
this.resolveOptions = module.resolveOptions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
const asyncLib = require("neo-async");
|
||||
const {
|
||||
Tapable,
|
||||
|
|
@ -20,6 +21,8 @@ const cachedMerge = require("./util/cachedMerge");
|
|||
|
||||
const EMPTY_RESOLVE_OPTIONS = {};
|
||||
|
||||
const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
|
||||
|
||||
const loaderToIdent = data => {
|
||||
if (!data.options) {
|
||||
return data.loader;
|
||||
|
|
@ -158,19 +161,33 @@ class NormalModuleFactory extends Tapable {
|
|||
const context = data.context;
|
||||
const request = data.request;
|
||||
|
||||
const noPreAutoLoaders = request.startsWith("-!");
|
||||
const noAutoLoaders = noPreAutoLoaders || request.startsWith("!");
|
||||
const noPrePostAutoLoaders = request.startsWith("!!");
|
||||
let elements = request
|
||||
const loaderResolver = this.getResolver("loader");
|
||||
const normalResolver = this.getResolver("normal", data.resolveOptions);
|
||||
|
||||
let matchResource = undefined;
|
||||
let requestWithoutMatchResource = request;
|
||||
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
|
||||
if (matchResourceMatch) {
|
||||
matchResource = matchResourceMatch[1];
|
||||
if (/^\.\.?\//.test(matchResource)) {
|
||||
matchResource = path.join(context, matchResource);
|
||||
}
|
||||
requestWithoutMatchResource = request.substr(
|
||||
matchResourceMatch[0].length
|
||||
);
|
||||
}
|
||||
|
||||
const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!");
|
||||
const noAutoLoaders =
|
||||
noPreAutoLoaders || requestWithoutMatchResource.startsWith("!");
|
||||
const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!");
|
||||
let elements = requestWithoutMatchResource
|
||||
.replace(/^-?!+/, "")
|
||||
.replace(/!!+/g, "!")
|
||||
.split("!");
|
||||
let resource = elements.pop();
|
||||
elements = elements.map(identToLoaderRequest);
|
||||
|
||||
const loaderResolver = this.getResolver("loader");
|
||||
const normalResolver = this.getResolver("normal", data.resolveOptions);
|
||||
|
||||
asyncLib.parallel(
|
||||
[
|
||||
callback =>
|
||||
|
|
@ -234,12 +251,15 @@ class NormalModuleFactory extends Tapable {
|
|||
);
|
||||
}
|
||||
|
||||
const userRequest = loaders
|
||||
.map(loaderToIdent)
|
||||
.concat([resource])
|
||||
.join("!");
|
||||
const userRequest =
|
||||
(matchResource !== undefined ? `${matchResource}!=!` : "") +
|
||||
loaders
|
||||
.map(loaderToIdent)
|
||||
.concat([resource])
|
||||
.join("!");
|
||||
|
||||
let resourcePath = resource;
|
||||
let resourcePath =
|
||||
matchResource !== undefined ? matchResource : resource;
|
||||
let resourceQuery = "";
|
||||
const queryIndex = resourcePath.indexOf("?");
|
||||
if (queryIndex >= 0) {
|
||||
|
|
@ -249,6 +269,10 @@ class NormalModuleFactory extends Tapable {
|
|||
|
||||
const result = this.ruleSet.exec({
|
||||
resource: resourcePath,
|
||||
realResource:
|
||||
matchResource !== undefined
|
||||
? resource.replace(/\?.*/, "")
|
||||
: resourcePath,
|
||||
resourceQuery,
|
||||
issuer: contextInfo.issuer,
|
||||
compiler: contextInfo.compiler
|
||||
|
|
@ -326,6 +350,7 @@ class NormalModuleFactory extends Tapable {
|
|||
rawRequest: request,
|
||||
loaders,
|
||||
resource,
|
||||
matchResource,
|
||||
resourceResolveData,
|
||||
settings,
|
||||
type,
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
|
||||
|
||||
const acorn = require("acorn-dynamic-import").default;
|
||||
const { Tapable, SyncBailHook } = require("tapable");
|
||||
const HookMap = require("tapable/lib/HookMap");
|
||||
const { Tapable, SyncBailHook, HookMap } = require("tapable");
|
||||
const util = require("util");
|
||||
const vm = require("vm");
|
||||
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
||||
const StackedSetMap = require("./util/StackedSetMap");
|
||||
|
|
@ -31,6 +31,14 @@ const defaultParserOptions = {
|
|||
}
|
||||
};
|
||||
|
||||
// regexp to match at lease one "magic comment"
|
||||
const webpackCommentRegExp = new RegExp(/(^|\W)webpack[A-Z]{1,}[A-Za-z]{1,}:/);
|
||||
|
||||
const EMPTY_COMMENT_OPTIONS = {
|
||||
options: null,
|
||||
errors: null
|
||||
};
|
||||
|
||||
class Parser extends Tapable {
|
||||
constructor(options, sourceType = "auto") {
|
||||
super();
|
||||
|
|
@ -2060,20 +2068,27 @@ class Parser extends Tapable {
|
|||
);
|
||||
}
|
||||
|
||||
getCommentOptions(range) {
|
||||
parseCommentOptions(range) {
|
||||
const comments = this.getComments(range);
|
||||
if (comments.length === 0) return null;
|
||||
const options = comments.map(comment => {
|
||||
try {
|
||||
let val = vm.runInNewContext(
|
||||
`(function(){return {${comment.value}};})()`
|
||||
);
|
||||
return val;
|
||||
} catch (e) {
|
||||
return {};
|
||||
if (comments.length === 0) {
|
||||
return EMPTY_COMMENT_OPTIONS;
|
||||
}
|
||||
let options = {};
|
||||
let errors = [];
|
||||
for (const comment of comments) {
|
||||
const { value } = comment;
|
||||
if (value && webpackCommentRegExp.test(value)) {
|
||||
// try compile only if webpack options comment is present
|
||||
try {
|
||||
const val = vm.runInNewContext(`(function(){return {${value}};})()`);
|
||||
Object.assign(options, val);
|
||||
} catch (e) {
|
||||
e.comment = comment;
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return options.reduce((o, i) => Object.assign(o, i), {});
|
||||
}
|
||||
return { options, errors };
|
||||
}
|
||||
|
||||
getNameForExpression(expression) {
|
||||
|
|
@ -2161,4 +2176,12 @@ class Parser extends Tapable {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO remove in webpack 5
|
||||
Object.defineProperty(Parser.prototype, "getCommentOptions", {
|
||||
configurable: false,
|
||||
value: util.deprecate(function(range) {
|
||||
return this.parseCommentOptions(range).options;
|
||||
}, "Parser.getCommentOptions: Use Parser.parseCommentOptions(range) instead")
|
||||
});
|
||||
|
||||
module.exports = Parser;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ ParserHelpers.expressionIsUnsupported = (parser, message) => {
|
|||
parser.state.current.addDependency(dep);
|
||||
if (!parser.state.module) return;
|
||||
parser.state.module.warnings.push(
|
||||
new UnsupportedFeatureWarning(parser.state.module, message)
|
||||
new UnsupportedFeatureWarning(parser.state.module, message, expr.loc)
|
||||
);
|
||||
return true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ const WebpackError = require("./WebpackError");
|
|||
|
||||
module.exports = class RemovedPluginError extends WebpackError {
|
||||
constructor(message) {
|
||||
super();
|
||||
|
||||
this.message = message;
|
||||
super(message);
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g;
|
|||
const SEPARATOR_REGEXP = /[/\\]$/;
|
||||
const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g;
|
||||
const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g;
|
||||
const MATCH_RESOURCE_REGEXP = /!=!/;
|
||||
|
||||
const normalizeBackSlashDirection = request => {
|
||||
return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/");
|
||||
|
|
@ -73,6 +74,7 @@ class RequestShortener {
|
|||
}
|
||||
result = result.replace(INDEX_JS_REGEXP, "$1");
|
||||
result = result.replace(FRONT_OR_BACK_BANG_REGEXP, "");
|
||||
result = result.replace(MATCH_RESOURCE_REGEXP, " = ");
|
||||
this.cache.set(request, result);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,6 +203,14 @@ module.exports = class RuleSet {
|
|||
}
|
||||
}
|
||||
|
||||
if (rule.realResource) {
|
||||
try {
|
||||
newRule.realResource = RuleSet.normalizeCondition(rule.realResource);
|
||||
} catch (error) {
|
||||
throw new Error(RuleSet.buildErrorMessage(rule.realResource, error));
|
||||
}
|
||||
}
|
||||
|
||||
if (rule.resourceQuery) {
|
||||
try {
|
||||
newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery);
|
||||
|
|
@ -477,10 +485,13 @@ module.exports = class RuleSet {
|
|||
_run(data, rule, result) {
|
||||
// test conditions
|
||||
if (rule.resource && !data.resource) return false;
|
||||
if (rule.realResource && !data.realResource) return false;
|
||||
if (rule.resourceQuery && !data.resourceQuery) return false;
|
||||
if (rule.compiler && !data.compiler) return false;
|
||||
if (rule.issuer && !data.issuer) return false;
|
||||
if (rule.resource && !rule.resource(data.resource)) return false;
|
||||
if (rule.realResource && !rule.realResource(data.realResource))
|
||||
return false;
|
||||
if (data.issuer && rule.issuer && !rule.issuer(data.issuer)) return false;
|
||||
if (
|
||||
data.resourceQuery &&
|
||||
|
|
@ -497,6 +508,7 @@ module.exports = class RuleSet {
|
|||
const keys = Object.keys(rule).filter(key => {
|
||||
return ![
|
||||
"resource",
|
||||
"realResource",
|
||||
"resourceQuery",
|
||||
"compiler",
|
||||
"issuer",
|
||||
|
|
|
|||
13
lib/Stats.js
13
lib/Stats.js
|
|
@ -56,8 +56,8 @@ class Stats {
|
|||
formatFilePath(filePath) {
|
||||
const OPTIONS_REGEXP = /^(\s|\S)*!/;
|
||||
return filePath.includes("!")
|
||||
? `${filePath.replace(OPTIONS_REGEXP, "")} (${filePath})\n`
|
||||
: `${filePath}\n`;
|
||||
? `${filePath.replace(OPTIONS_REGEXP, "")} (${filePath})`
|
||||
: `${filePath}`;
|
||||
}
|
||||
|
||||
hasWarnings() {
|
||||
|
|
@ -288,6 +288,11 @@ class Stats {
|
|||
text += this.formatFilePath(
|
||||
e.module.readableIdentifier(requestShortener)
|
||||
);
|
||||
if (typeof e.loc === "object") {
|
||||
const locInfo = formatLocation(e.loc);
|
||||
if (locInfo) text += ` ${locInfo}`;
|
||||
}
|
||||
text += "\n";
|
||||
}
|
||||
text += e.message;
|
||||
if (showErrorDetails && e.details) {
|
||||
|
|
@ -297,7 +302,9 @@ class Stats {
|
|||
text += e.missing.map(item => `\n[${item}]`).join("");
|
||||
}
|
||||
if (showModuleTrace && e.origin) {
|
||||
text += `\n @ ${e.origin.readableIdentifier(requestShortener)}`;
|
||||
text += `\n @ ${this.formatFilePath(
|
||||
e.origin.readableIdentifier(requestShortener)
|
||||
)}`;
|
||||
if (typeof e.originLoc === "object") {
|
||||
const locInfo = formatLocation(e.originLoc);
|
||||
if (locInfo) text += ` ${locInfo}`;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@
|
|||
const WebpackError = require("./WebpackError");
|
||||
|
||||
class UnsupportedFeatureWarning extends WebpackError {
|
||||
constructor(module, message) {
|
||||
super();
|
||||
constructor(module, message, loc) {
|
||||
super(message);
|
||||
|
||||
this.name = "UnsupportedFeatureWarning";
|
||||
this.message = message;
|
||||
this.origin = this.module = module;
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
this.hideStack = true;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ const NamedModulesPlugin = require("./NamedModulesPlugin");
|
|||
const NamedChunksPlugin = require("./NamedChunksPlugin");
|
||||
const DefinePlugin = require("./DefinePlugin");
|
||||
const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
|
||||
const WasmFinalizeExportsPlugin = require("./wasm/WasmFinalizeExportsPlugin");
|
||||
|
||||
class WebpackOptionsApply extends OptionsApply {
|
||||
constructor() {
|
||||
|
|
@ -339,6 +340,9 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
if (options.optimization.noEmitOnErrors) {
|
||||
new NoEmitOnErrorsPlugin().apply(compiler);
|
||||
}
|
||||
if (options.optimization.checkWasmTypes) {
|
||||
new WasmFinalizeExportsPlugin().apply(compiler);
|
||||
}
|
||||
if (options.optimization.namedModules) {
|
||||
new NamedModulesPlugin().apply(compiler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,6 +254,9 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
|
|||
this.set("optimization.noEmitOnErrors", "make", options =>
|
||||
isProductionLikeMode(options)
|
||||
);
|
||||
this.set("optimization.checkWasmTypes", "make", options =>
|
||||
isProductionLikeMode(options)
|
||||
);
|
||||
this.set(
|
||||
"optimization.namedModules",
|
||||
"make",
|
||||
|
|
@ -294,11 +297,10 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
|
|||
}
|
||||
}
|
||||
]);
|
||||
this.set(
|
||||
"optimization.nodeEnv",
|
||||
"make",
|
||||
options => options.mode || "production"
|
||||
);
|
||||
this.set("optimization.nodeEnv", "make", options => {
|
||||
// TODO: In webpack 5, it should return `false` when mode is `none`
|
||||
return options.mode || "production";
|
||||
});
|
||||
|
||||
this.set("resolve", "call", value => Object.assign({}, value));
|
||||
this.set("resolve.unsafeCache", true);
|
||||
|
|
|
|||
|
|
@ -69,23 +69,23 @@ const indent = (str, prefix, firstLine) => {
|
|||
|
||||
class WebpackOptionsValidationError extends WebpackError {
|
||||
constructor(validationErrors) {
|
||||
super();
|
||||
super(
|
||||
"Invalid configuration object. " +
|
||||
"Webpack has been initialised using a configuration object that does not match the API schema.\n" +
|
||||
validationErrors
|
||||
.map(
|
||||
err =>
|
||||
" - " +
|
||||
indent(
|
||||
WebpackOptionsValidationError.formatValidationError(err),
|
||||
" ",
|
||||
false
|
||||
)
|
||||
)
|
||||
.join("\n")
|
||||
);
|
||||
|
||||
this.name = "WebpackOptionsValidationError";
|
||||
this.message =
|
||||
"Invalid configuration object. " +
|
||||
"Webpack has been initialised using a configuration object that does not match the API schema.\n" +
|
||||
validationErrors
|
||||
.map(
|
||||
err =>
|
||||
" - " +
|
||||
indent(
|
||||
WebpackOptionsValidationError.formatValidationError(err),
|
||||
" ",
|
||||
false
|
||||
)
|
||||
)
|
||||
.join("\n");
|
||||
this.validationErrors = validationErrors;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
|
|
|||
|
|
@ -219,7 +219,8 @@ class AMDRequireDependenciesBlockParserPlugin {
|
|||
new UnsupportedFeatureWarning(
|
||||
parser.state.module,
|
||||
"Cannot statically analyse 'require(…, …)' in line " +
|
||||
expr.loc.start.line
|
||||
expr.loc.start.line,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const ImportDependenciesBlock = require("./ImportDependenciesBlock");
|
|||
const ImportEagerDependency = require("./ImportEagerDependency");
|
||||
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
|
||||
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
|
||||
const CommentCompilationWarning = require("../CommentCompilationWarning");
|
||||
|
||||
class ImportParserPlugin {
|
||||
constructor(options) {
|
||||
|
|
@ -32,7 +33,26 @@ class ImportParserPlugin {
|
|||
let exclude = null;
|
||||
const groupOptions = {};
|
||||
|
||||
const importOptions = parser.getCommentOptions(expr.range);
|
||||
const {
|
||||
options: importOptions,
|
||||
errors: commentErrors
|
||||
} = parser.parseCommentOptions(expr.range);
|
||||
|
||||
if (commentErrors) {
|
||||
for (const e of commentErrors) {
|
||||
const { comment } = e;
|
||||
parser.state.module.warnings.push(
|
||||
new CommentCompilationWarning(
|
||||
`Compilation error while processing magic comment(-s): /*${
|
||||
comment.value
|
||||
}*/: ${e.message}`,
|
||||
parser.state.module,
|
||||
comment.loc
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (importOptions) {
|
||||
if (typeof importOptions.webpackIgnore !== "undefined") {
|
||||
if (typeof importOptions.webpackIgnore !== "boolean") {
|
||||
|
|
@ -41,7 +61,8 @@ class ImportParserPlugin {
|
|||
parser.state.module,
|
||||
`\`webpackIgnore\` expected a boolean, but received: ${
|
||||
importOptions.webpackIgnore
|
||||
}.`
|
||||
}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
|
@ -58,7 +79,8 @@ class ImportParserPlugin {
|
|||
parser.state.module,
|
||||
`\`webpackChunkName\` expected a string, but received: ${
|
||||
importOptions.webpackChunkName
|
||||
}.`
|
||||
}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
|
@ -72,7 +94,8 @@ class ImportParserPlugin {
|
|||
parser.state.module,
|
||||
`\`webpackMode\` expected a string, but received: ${
|
||||
importOptions.webpackMode
|
||||
}.`
|
||||
}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
|
@ -90,7 +113,8 @@ class ImportParserPlugin {
|
|||
parser.state.module,
|
||||
`\`webpackPrefetch\` expected true or a number, but received: ${
|
||||
importOptions.webpackPrefetch
|
||||
}.`
|
||||
}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -106,7 +130,8 @@ class ImportParserPlugin {
|
|||
parser.state.module,
|
||||
`\`webpackPreload\` expected true or a number, but received: ${
|
||||
importOptions.webpackPreload
|
||||
}.`
|
||||
}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -121,7 +146,8 @@ class ImportParserPlugin {
|
|||
parser.state.module,
|
||||
`\`webpackInclude\` expected a regular expression, but received: ${
|
||||
importOptions.webpackInclude
|
||||
}.`
|
||||
}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
|
@ -138,7 +164,8 @@ class ImportParserPlugin {
|
|||
parser.state.module,
|
||||
`\`webpackExclude\` expected a regular expression, but received: ${
|
||||
importOptions.webpackExclude
|
||||
}.`
|
||||
}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
|
@ -152,7 +179,8 @@ class ImportParserPlugin {
|
|||
parser.state.module.warnings.push(
|
||||
new UnsupportedFeatureWarning(
|
||||
parser.state.module,
|
||||
`\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`
|
||||
`\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -195,7 +223,8 @@ class ImportParserPlugin {
|
|||
parser.state.module.warnings.push(
|
||||
new UnsupportedFeatureWarning(
|
||||
parser.state.module,
|
||||
`\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`
|
||||
`\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
|
||||
expr.loc
|
||||
)
|
||||
);
|
||||
mode = "lazy";
|
||||
|
|
@ -230,4 +259,5 @@ class ImportParserPlugin {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ImportParserPlugin;
|
||||
|
|
|
|||
|
|
@ -108,15 +108,15 @@ class SystemPlugin {
|
|||
|
||||
class SystemImportDeprecationWarning extends WebpackError {
|
||||
constructor(module, loc) {
|
||||
super();
|
||||
super(
|
||||
"System.import() is deprecated and will be removed soon. Use import() instead.\n" +
|
||||
"For more info visit https://webpack.js.org/guides/code-splitting/"
|
||||
);
|
||||
|
||||
this.name = "SystemImportDeprecationWarning";
|
||||
this.message =
|
||||
"System.import() is deprecated and will be removed soon. Use import() instead.\n" +
|
||||
"For more info visit https://webpack.js.org/guides/code-splitting/";
|
||||
|
||||
this.origin = this.module = module;
|
||||
this.originLoc = loc;
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const DependencyReference = require("./DependencyReference");
|
||||
const ModuleDependency = require("./ModuleDependency");
|
||||
|
||||
class WebAssemblyExportImportedDependency extends ModuleDependency {
|
||||
constructor(exportName, request, name) {
|
||||
super(request);
|
||||
/** @type {string} */
|
||||
this.exportName = exportName;
|
||||
/** @type {string} */
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
getReference() {
|
||||
if (!this.module) return null;
|
||||
return new DependencyReference(this.module, [this.name], false);
|
||||
}
|
||||
|
||||
get type() {
|
||||
return "wasm export import";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebAssemblyExportImportedDependency;
|
||||
|
|
@ -32,7 +32,7 @@ class WebAssemblyImportDependency extends ModuleDependency {
|
|||
) {
|
||||
return [
|
||||
new UnsupportedWebAssemblyFeatureError(
|
||||
`Import with ${
|
||||
`Import "${this.name}" from "${this.request}" with ${
|
||||
this.onlyDirectImport
|
||||
} can only be used for direct wasm to wasm dependencies`
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,21 +9,21 @@ const SizeFormatHelpers = require("../SizeFormatHelpers");
|
|||
|
||||
module.exports = class AssetsOverSizeLimitWarning extends WebpackError {
|
||||
constructor(assetsOverSizeLimit, assetLimit) {
|
||||
super();
|
||||
|
||||
this.name = "AssetsOverSizeLimitWarning";
|
||||
this.assets = assetsOverSizeLimit;
|
||||
const assetLists = this.assets
|
||||
const assetLists = assetsOverSizeLimit
|
||||
.map(
|
||||
asset =>
|
||||
`\n ${asset.name} (${SizeFormatHelpers.formatSize(asset.size)})`
|
||||
)
|
||||
.join("");
|
||||
this.message = `asset size limit: The following asset(s) exceed the recommended size limit (${SizeFormatHelpers.formatSize(
|
||||
|
||||
super(`asset size limit: The following asset(s) exceed the recommended size limit (${SizeFormatHelpers.formatSize(
|
||||
assetLimit
|
||||
)}).
|
||||
This can impact web performance.
|
||||
Assets: ${assetLists}`;
|
||||
Assets: ${assetLists}`);
|
||||
|
||||
this.name = "AssetsOverSizeLimitWarning";
|
||||
this.assets = assetsOverSizeLimit;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,7 @@ const SizeFormatHelpers = require("../SizeFormatHelpers");
|
|||
|
||||
module.exports = class EntrypointsOverSizeLimitWarning extends WebpackError {
|
||||
constructor(entrypoints, entrypointLimit) {
|
||||
super();
|
||||
|
||||
this.name = "EntrypointsOverSizeLimitWarning";
|
||||
this.entrypoints = entrypoints;
|
||||
const entrypointList = this.entrypoints
|
||||
const entrypointList = entrypoints
|
||||
.map(
|
||||
entrypoint =>
|
||||
`\n ${entrypoint.name} (${SizeFormatHelpers.formatSize(
|
||||
|
|
@ -21,10 +17,13 @@ module.exports = class EntrypointsOverSizeLimitWarning extends WebpackError {
|
|||
)})\n${entrypoint.files.map(asset => ` ${asset}`).join("\n")}`
|
||||
)
|
||||
.join("");
|
||||
this.message = `entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (${SizeFormatHelpers.formatSize(
|
||||
super(`entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (${SizeFormatHelpers.formatSize(
|
||||
entrypointLimit
|
||||
)}). This can impact web performance.
|
||||
Entrypoints:${entrypointList}\n`;
|
||||
Entrypoints:${entrypointList}\n`);
|
||||
|
||||
this.name = "EntrypointsOverSizeLimitWarning";
|
||||
this.entrypoints = entrypoints;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ const WebpackError = require("../WebpackError");
|
|||
|
||||
module.exports = class NoAsyncChunksWarning extends WebpackError {
|
||||
constructor() {
|
||||
super();
|
||||
super(
|
||||
"webpack performance recommendations: \n" +
|
||||
"You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.\n" +
|
||||
"For more info visit https://webpack.js.org/guides/code-splitting/"
|
||||
);
|
||||
|
||||
this.name = "NoAsyncChunksWarning";
|
||||
this.message =
|
||||
"webpack performance recommendations: \n" +
|
||||
"You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.\n" +
|
||||
"For more info visit https://webpack.js.org/guides/code-splitting/";
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ const WebpackError = require("../WebpackError");
|
|||
module.exports = class UnsupportedWebAssemblyFeatureError extends WebpackError {
|
||||
/** @param {string} message Error message */
|
||||
constructor(message) {
|
||||
super();
|
||||
super(message);
|
||||
this.name = "UnsupportedWebAssemblyFeatureError";
|
||||
this.message = message;
|
||||
this.hideStack = true;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const UnsupportedWebAssemblyFeatureError = require("../wasm/UnsupportedWebAssemblyFeatureError");
|
||||
|
||||
class WasmFinalizeExportsPlugin {
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap("WasmFinalizeExportsPlugin", compilation => {
|
||||
compilation.hooks.finishModules.tap(
|
||||
"WasmFinalizeExportsPlugin",
|
||||
modules => {
|
||||
for (const module of modules) {
|
||||
// 1. if a WebAssembly module
|
||||
if (module.type.startsWith("webassembly") === true) {
|
||||
const jsIncompatibleExports =
|
||||
module.buildMeta.jsIncompatibleExports;
|
||||
|
||||
if (jsIncompatibleExports === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const reason of module.reasons) {
|
||||
// 2. is referenced by a non-WebAssembly module
|
||||
if (reason.module.type.startsWith("webassembly") === false) {
|
||||
const ref = reason.dependency.getReference();
|
||||
|
||||
const importedNames = ref.importedNames;
|
||||
|
||||
if (Array.isArray(importedNames)) {
|
||||
importedNames.forEach(name => {
|
||||
// 3. and uses a func with an incompatible JS signature
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
jsIncompatibleExports,
|
||||
name
|
||||
)
|
||||
) {
|
||||
// 4. error
|
||||
/** @type {any} */
|
||||
const error = new UnsupportedWebAssemblyFeatureError(
|
||||
`Export "${name}" with ${
|
||||
jsIncompatibleExports[name]
|
||||
} can only be used for direct wasm to wasm dependencies`
|
||||
);
|
||||
error.module = module;
|
||||
error.origin = reason.module;
|
||||
error.originLoc = reason.dependency.loc;
|
||||
error.dependencies = [reason.dependency];
|
||||
compilation.errors.push(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WasmFinalizeExportsPlugin;
|
||||
|
|
@ -14,6 +14,8 @@ const { editWithAST, addWithAST } = require("@webassemblyjs/wasm-edit");
|
|||
const { decode } = require("@webassemblyjs/wasm-parser");
|
||||
const t = require("@webassemblyjs/ast");
|
||||
|
||||
const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
|
||||
|
||||
/** @typedef {import("../Module")} Module */
|
||||
/** @typedef {import("./WebAssemblyUtils").UsedWasmDependency} UsedWasmDependency */
|
||||
|
||||
|
|
@ -129,7 +131,7 @@ function getCountImportedFunc(ast) {
|
|||
* Get next type index
|
||||
*
|
||||
* @param {Object} ast - Module's AST
|
||||
* @returns {t.IndexLiteral} - index
|
||||
* @returns {t.Index} - index
|
||||
*/
|
||||
function getNextTypeIndex(ast) {
|
||||
const typeSectionMetadata = t.getSectionMetadata(ast, "type");
|
||||
|
|
@ -150,7 +152,7 @@ function getNextTypeIndex(ast) {
|
|||
*
|
||||
* @param {Object} ast - Module's AST
|
||||
* @param {Number} countImportedFunc - number of imported funcs
|
||||
* @returns {t.IndexLiteral} - index
|
||||
* @returns {t.Index} - index
|
||||
*/
|
||||
function getNextFuncIndex(ast, countImportedFunc) {
|
||||
const funcSectionMetadata = t.getSectionMetadata(ast, "func");
|
||||
|
|
@ -164,6 +166,27 @@ function getNextFuncIndex(ast, countImportedFunc) {
|
|||
return t.indexLiteral(vectorOfSize + countImportedFunc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a init instruction for a global
|
||||
* @param {t.GlobalType} globalType the global type
|
||||
* @returns {t.Instruction} init expression
|
||||
*/
|
||||
const createDefaultInitForGlobal = globalType => {
|
||||
if (globalType.valtype[0] === "i") {
|
||||
// create NumberLiteral global initializer
|
||||
return t.objectInstruction("const", globalType.valtype, [
|
||||
t.numberLiteralFromRaw(66)
|
||||
]);
|
||||
} else if (globalType.valtype[0] === "f") {
|
||||
// create FloatLiteral global initializer
|
||||
return t.objectInstruction("const", globalType.valtype, [
|
||||
t.floatLiteral(66, false, false, "66")
|
||||
]);
|
||||
} else {
|
||||
throw new Error("unknown type: " + globalType.valtype);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewrite the import globals:
|
||||
* - removes the ModuleImport instruction
|
||||
|
|
@ -188,21 +211,7 @@ const rewriteImportedGlobals = state => bin => {
|
|||
|
||||
globalType.mutability = "var";
|
||||
|
||||
let init;
|
||||
|
||||
if (globalType.valtype[0] === "i") {
|
||||
// create NumberLiteral global initializer
|
||||
init = t.objectInstruction("const", globalType.valtype, [
|
||||
t.numberLiteralFromRaw(0)
|
||||
]);
|
||||
} else if (globalType.valtype[0] === "f") {
|
||||
// create FloatLiteral global initializer
|
||||
init = t.objectInstruction("const", globalType.valtype, [
|
||||
t.floatLiteral(0, false, false, "0")
|
||||
]);
|
||||
} else {
|
||||
throw new Error("unknown type: " + globalType.valtype);
|
||||
}
|
||||
const init = createDefaultInitForGlobal(globalType);
|
||||
|
||||
newGlobals.push(t.global(globalType, [init]));
|
||||
|
||||
|
|
@ -221,12 +230,7 @@ const rewriteImportedGlobals = state => bin => {
|
|||
|
||||
const initialGlobalidx = init.args[0];
|
||||
|
||||
const valtype = node.globalType.valtype;
|
||||
|
||||
node.init = [
|
||||
// Poisong globals, they are meant to be rewritten
|
||||
t.objectInstruction("const", valtype, [t.numberLiteralFromRaw(666)])
|
||||
];
|
||||
node.init = [createDefaultInitForGlobal(node.globalType)];
|
||||
|
||||
additionalInitCode.push(
|
||||
/**
|
||||
|
|
@ -253,18 +257,24 @@ const rewriteImportedGlobals = state => bin => {
|
|||
* Rewrite the export names
|
||||
* @param {Object} state state
|
||||
* @param {Object} state.ast Module's ast
|
||||
* @param {Object} state.module Module
|
||||
* @param {Module} state.module Module
|
||||
* @param {Set<string>} state.externalExports Module
|
||||
* @returns {ArrayBufferTransform} transform
|
||||
*/
|
||||
const rewriteExportNames = ({ ast, module }) => bin => {
|
||||
const rewriteExportNames = ({ ast, module, externalExports }) => bin => {
|
||||
return editWithAST(ast, bin, {
|
||||
ModuleExport(path) {
|
||||
const usedName = module.isUsed(path.node.name);
|
||||
if (usedName) {
|
||||
path.node.name = usedName;
|
||||
} else {
|
||||
const isExternal = externalExports.has(path.node.name);
|
||||
if (isExternal) {
|
||||
path.remove();
|
||||
return;
|
||||
}
|
||||
const usedName = module.isUsed(path.node.name);
|
||||
if (!usedName) {
|
||||
path.remove();
|
||||
return;
|
||||
}
|
||||
path.node.name = usedName;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -282,9 +292,8 @@ const rewriteImports = ({ ast, usedDependencyMap }) => bin => {
|
|||
const result = usedDependencyMap.get(
|
||||
path.node.module + ":" + path.node.name
|
||||
);
|
||||
if (result === undefined) {
|
||||
path.remove();
|
||||
} else {
|
||||
|
||||
if (typeof result !== "undefined") {
|
||||
path.node.module = WebAssemblyUtils.MANGLED_MODULE;
|
||||
path.node.name = result.name;
|
||||
}
|
||||
|
|
@ -300,11 +309,11 @@ const rewriteImports = ({ ast, usedDependencyMap }) => bin => {
|
|||
* @param {Object} state transformation state
|
||||
* @param {Object} state.ast - Module's ast
|
||||
* @param {t.Identifier} state.initFuncId identifier of the init function
|
||||
* @param {t.IndexLiteral} state.startAtFuncIndex index of the start function
|
||||
* @param {t.Index} state.startAtFuncIndex index of the start function
|
||||
* @param {t.ModuleImport[]} state.importedGlobals list of imported globals
|
||||
* @param {t.Instruction[]} state.additionalInitCode list of addition instructions for the init function
|
||||
* @param {t.IndexLiteral} state.nextFuncIndex index of the next function
|
||||
* @param {t.IndexLiteral} state.nextTypeIndex index of the next type
|
||||
* @param {t.Index} state.nextFuncIndex index of the next function
|
||||
* @param {t.Index} state.nextTypeIndex index of the next type
|
||||
* @returns {ArrayBufferTransform} transform
|
||||
*/
|
||||
const addInitFunction = ({
|
||||
|
|
@ -403,6 +412,11 @@ class WebAssemblyGenerator extends Generator {
|
|||
const nextTypeIndex = getNextTypeIndex(ast);
|
||||
|
||||
const usedDependencyMap = getUsedDependencyMap(module);
|
||||
const externalExports = new Set(
|
||||
module.dependencies
|
||||
.filter(d => d instanceof WebAssemblyExportImportedDependency)
|
||||
.map(d => d.exportName)
|
||||
);
|
||||
|
||||
/** @type {t.Instruction[]} */
|
||||
const additionalInitCode = [];
|
||||
|
|
@ -410,7 +424,8 @@ class WebAssemblyGenerator extends Generator {
|
|||
const transform = compose(
|
||||
rewriteExportNames({
|
||||
ast,
|
||||
module
|
||||
module,
|
||||
externalExports
|
||||
}),
|
||||
|
||||
removeStartFunc({ ast }),
|
||||
|
|
|
|||
|
|
@ -8,34 +8,7 @@ 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;
|
||||
}
|
||||
const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
|
||||
|
||||
class WebAssemblyJavascriptGenerator extends Generator {
|
||||
generate(module, dependencyTemplates, runtimeTemplate) {
|
||||
|
|
@ -43,24 +16,88 @@ class WebAssemblyJavascriptGenerator extends Generator {
|
|||
? Template.numberToIdentifer(module.usedExports.length)
|
||||
: "__webpack_init__";
|
||||
|
||||
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
|
||||
})};`;
|
||||
})
|
||||
);
|
||||
};
|
||||
let needExportsCopy = false;
|
||||
const importedModules = new Map();
|
||||
const initParams = [];
|
||||
let index = 0;
|
||||
for (const dep of module.dependencies) {
|
||||
if (dep.module) {
|
||||
let importData = importedModules.get(dep.module);
|
||||
if (importData === undefined) {
|
||||
importedModules.set(
|
||||
dep.module,
|
||||
(importData = {
|
||||
importVar: `m${index}`,
|
||||
index,
|
||||
request: dep.userRequest,
|
||||
names: new Set(),
|
||||
reexports: []
|
||||
})
|
||||
);
|
||||
index++;
|
||||
}
|
||||
if (dep instanceof WebAssemblyImportDependency) {
|
||||
importData.names.add(dep.name);
|
||||
if (dep.description.type === "GlobalType") {
|
||||
const exportName = dep.name;
|
||||
const usedName = dep.module && dep.module.isUsed(exportName);
|
||||
|
||||
// FIXME(sven): assert that the exports exists in the modules
|
||||
// otherwise it will default to i32 0
|
||||
const initParams = generateInitParams(module).join(",");
|
||||
if (dep.module) {
|
||||
if (usedName) {
|
||||
initParams.push(
|
||||
runtimeTemplate.exportFromImport({
|
||||
module: dep.module,
|
||||
request: dep.request,
|
||||
importVar: importData.importVar,
|
||||
originModule: module,
|
||||
exportName: dep.name,
|
||||
asiSafe: true,
|
||||
isCall: false,
|
||||
callContext: null
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dep instanceof WebAssemblyExportImportedDependency) {
|
||||
importData.names.add(dep.name);
|
||||
const usedName = module.isUsed(dep.exportName);
|
||||
if (usedName) {
|
||||
const defineStatement = Template.asString([
|
||||
`${module.exportsArgument}[${JSON.stringify(
|
||||
usedName
|
||||
)}] = ${runtimeTemplate.exportFromImport({
|
||||
module: dep.module,
|
||||
request: dep.request,
|
||||
importVar: importData.importVar,
|
||||
originModule: module,
|
||||
exportName: dep.name,
|
||||
asiSafe: true,
|
||||
isCall: false,
|
||||
callContext: null
|
||||
})};`
|
||||
]);
|
||||
importData.reexports.push(defineStatement);
|
||||
needExportsCopy = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const importsCode = Template.asString(
|
||||
Array.from(
|
||||
importedModules,
|
||||
([module, { importVar, request, reexports }]) => {
|
||||
const importStatement = runtimeTemplate.importStatement({
|
||||
module,
|
||||
request,
|
||||
importVar,
|
||||
originModule: module
|
||||
});
|
||||
return importStatement + reexports.join("\n");
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// create source
|
||||
const source = new RawSource(
|
||||
|
|
@ -69,18 +106,24 @@ class WebAssemblyJavascriptGenerator extends Generator {
|
|||
"// Instantiate WebAssembly module",
|
||||
"var wasmExports = __webpack_require__.w[module.i];",
|
||||
|
||||
!Array.isArray(module.usedExports)
|
||||
? `__webpack_require__.r(${module.exportsArgument});`
|
||||
: "",
|
||||
|
||||
// this must be before import for circular dependencies
|
||||
"// export exports from WebAssembly module",
|
||||
Array.isArray(module.usedExports)
|
||||
Array.isArray(module.usedExports) && !needExportsCopy
|
||||
? `${module.moduleArgument}.exports = wasmExports;`
|
||||
: "for(var name in wasmExports) " +
|
||||
`if(name != ${JSON.stringify(initIdentifer)}) ` +
|
||||
`${module.exportsArgument}[name] = wasmExports[name];`,
|
||||
"// exec imports from WebAssembly module (for esm order)",
|
||||
generateImports(),
|
||||
|
||||
importsCode,
|
||||
"",
|
||||
"// exec wasm module",
|
||||
`wasmExports[${JSON.stringify(initIdentifer)}](${initParams})`
|
||||
`wasmExports[${JSON.stringify(initIdentifer)}](${initParams.join(
|
||||
", "
|
||||
)})`
|
||||
].join("\n")
|
||||
);
|
||||
return source;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const WebAssemblyParser = require("./WebAssemblyParser");
|
|||
const WebAssemblyGenerator = require("./WebAssemblyGenerator");
|
||||
const WebAssemblyJavascriptGenerator = require("./WebAssemblyJavascriptGenerator");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
|
||||
|
||||
class WebAssemblyModulesPlugin {
|
||||
apply(compiler) {
|
||||
|
|
@ -20,6 +21,11 @@ class WebAssemblyModulesPlugin {
|
|||
normalModuleFactory
|
||||
);
|
||||
|
||||
compilation.dependencyFactories.set(
|
||||
WebAssemblyExportImportedDependency,
|
||||
normalModuleFactory
|
||||
);
|
||||
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for("webassembly/experimental")
|
||||
.tap("WebAssemblyModulesPlugin", () => {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,13 @@
|
|||
|
||||
const t = require("@webassemblyjs/ast");
|
||||
const { decode } = require("@webassemblyjs/wasm-parser");
|
||||
const {
|
||||
moduleContextFromModuleAST
|
||||
} = require("@webassemblyjs/helper-module-context");
|
||||
|
||||
const { Tapable } = require("tapable");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
|
||||
|
||||
/** @typedef {import("../Module")} Module */
|
||||
|
||||
|
|
@ -24,18 +28,29 @@ const isMemoryImport = n => n.descr.type === "Memory";
|
|||
*/
|
||||
const isTableImport = n => n.descr.type === "Table";
|
||||
|
||||
/**
|
||||
* @param {t.ModuleImport} n the import
|
||||
* @returns {boolean} true, if a func was imported
|
||||
*/
|
||||
const isFuncImport = n => n.descr.type === "FuncImportDescr";
|
||||
|
||||
/**
|
||||
* @param {t.ModuleImport} n the import
|
||||
* @returns {boolean} true, if a global was imported
|
||||
*/
|
||||
const isGlobalImport = n => n.descr.type === "GlobalType";
|
||||
|
||||
const JS_COMPAT_TYPES = new Set(["i32", "f32", "f64"]);
|
||||
|
||||
/**
|
||||
* @param {t.ModuleImport} moduleImport the import
|
||||
* @param {t.Signature} signature the func signature
|
||||
* @returns {null | string} the type incompatible with js types
|
||||
*/
|
||||
const getJsIncompatibleType = moduleImport => {
|
||||
if (moduleImport.descr.type !== "FuncImportDescr") return null;
|
||||
const signature = moduleImport.descr.signature;
|
||||
const getJsIncompatibleType = signature => {
|
||||
for (const param of signature.params) {
|
||||
if (!JS_COMPAT_TYPES.has(param.valtype))
|
||||
if (!JS_COMPAT_TYPES.has(param.valtype)) {
|
||||
return `${param.valtype} as parameter`;
|
||||
}
|
||||
}
|
||||
for (const type of signature.results) {
|
||||
if (!JS_COMPAT_TYPES.has(type)) return `${type} as result`;
|
||||
|
|
@ -43,9 +58,29 @@ const getJsIncompatibleType = moduleImport => {
|
|||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO why are there two different Signature types?
|
||||
* @param {t.FuncSignature} signature the func signature
|
||||
* @returns {null | string} the type incompatible with js types
|
||||
*/
|
||||
const getJsIncompatibleTypeOfFuncSignature = signature => {
|
||||
for (const param of signature.args) {
|
||||
if (!JS_COMPAT_TYPES.has(param)) {
|
||||
return `${param} as parameter`;
|
||||
}
|
||||
}
|
||||
for (const type of signature.result) {
|
||||
if (!JS_COMPAT_TYPES.has(type)) return `${type} as result`;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const decoderOpts = {
|
||||
ignoreCodeSection: true,
|
||||
ignoreDataSection: true
|
||||
ignoreDataSection: true,
|
||||
|
||||
// this will avoid having to lookup with identifiers in the ModuleContext
|
||||
ignoreCustomNameSection: true
|
||||
};
|
||||
|
||||
class WebAssemblyParser extends Tapable {
|
||||
|
|
@ -60,13 +95,65 @@ class WebAssemblyParser extends Tapable {
|
|||
state.module.buildMeta.exportsType = "namespace";
|
||||
|
||||
// parse it
|
||||
const ast = decode(binary, decoderOpts);
|
||||
const program = decode(binary, decoderOpts);
|
||||
const module = program.body[0];
|
||||
|
||||
const moduleContext = moduleContextFromModuleAST(module);
|
||||
|
||||
// extract imports and exports
|
||||
const exports = (state.module.buildMeta.providedExports = []);
|
||||
t.traverse(ast, {
|
||||
const jsIncompatibleExports = (state.module.buildMeta.jsIncompatibleExports = []);
|
||||
|
||||
const importedGlobals = [];
|
||||
t.traverse(module, {
|
||||
ModuleExport({ node }) {
|
||||
const descriptor = node.descr;
|
||||
|
||||
if (descriptor.exportType === "Func") {
|
||||
const funcidx = descriptor.id.value;
|
||||
|
||||
/** @type {t.FuncSignature} */
|
||||
const funcSignature = moduleContext.getFunction(funcidx);
|
||||
|
||||
const incompatibleType = getJsIncompatibleTypeOfFuncSignature(
|
||||
funcSignature
|
||||
);
|
||||
|
||||
if (incompatibleType) {
|
||||
jsIncompatibleExports[node.name] = incompatibleType;
|
||||
}
|
||||
}
|
||||
|
||||
exports.push(node.name);
|
||||
|
||||
if (node.descr && node.descr.exportType === "Global") {
|
||||
const refNode = importedGlobals[node.descr.id.value];
|
||||
if (refNode) {
|
||||
const dep = new WebAssemblyExportImportedDependency(
|
||||
node.name,
|
||||
refNode.module,
|
||||
refNode.name
|
||||
);
|
||||
|
||||
state.module.addDependency(dep);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Global({ node }) {
|
||||
const init = node.init[0];
|
||||
|
||||
let importNode = null;
|
||||
|
||||
if (init.id === "get_global") {
|
||||
const globalIdx = init.args[0].value;
|
||||
|
||||
if (globalIdx < importedGlobals.length) {
|
||||
importNode = importedGlobals[globalIdx];
|
||||
}
|
||||
}
|
||||
|
||||
importedGlobals.push(importNode);
|
||||
},
|
||||
|
||||
ModuleImport({ node }) {
|
||||
|
|
@ -77,11 +164,16 @@ class WebAssemblyParser extends Tapable {
|
|||
onlyDirectImport = "Memory";
|
||||
} else if (isTableImport(node) === true) {
|
||||
onlyDirectImport = "Table";
|
||||
} else {
|
||||
const incompatibleType = getJsIncompatibleType(node);
|
||||
} else if (isFuncImport(node) === true) {
|
||||
const incompatibleType = getJsIncompatibleType(node.descr.signature);
|
||||
if (incompatibleType) {
|
||||
onlyDirectImport = `Non-JS-compatible Func Sigurature (${incompatibleType})`;
|
||||
}
|
||||
} else if (isGlobalImport(node) === true) {
|
||||
const type = node.descr.valtype;
|
||||
if (!JS_COMPAT_TYPES.has(type)) {
|
||||
onlyDirectImport = `Non-JS-compatible Global Type (${type})`;
|
||||
}
|
||||
}
|
||||
|
||||
const dep = new WebAssemblyImportDependency(
|
||||
|
|
@ -92,6 +184,10 @@ class WebAssemblyParser extends Tapable {
|
|||
);
|
||||
|
||||
state.module.addDependency(dep);
|
||||
|
||||
if (isGlobalImport(node)) {
|
||||
importedGlobals.push(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class JsonpChunkTemplatePlugin {
|
|||
const jsonpFunction = chunkTemplate.outputOptions.jsonpFunction;
|
||||
const globalObject = chunkTemplate.outputOptions.globalObject;
|
||||
const source = new ConcatSource();
|
||||
const prefetchChunks = chunk.getChildIdsByOrders().prefetch;
|
||||
source.add(
|
||||
`(${globalObject}[${JSON.stringify(
|
||||
jsonpFunction
|
||||
|
|
@ -31,6 +32,12 @@ class JsonpChunkTemplatePlugin {
|
|||
);
|
||||
if (entries.length > 0) {
|
||||
source.add(`,${JSON.stringify(entries)}`);
|
||||
} else if (prefetchChunks && prefetchChunks.length) {
|
||||
source.add(`,0`);
|
||||
}
|
||||
|
||||
if (prefetchChunks && prefetchChunks.length) {
|
||||
source.add(`,${JSON.stringify(prefetchChunks)}`);
|
||||
}
|
||||
source.add("])");
|
||||
return source;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ class JsonpMainTemplatePlugin {
|
|||
}
|
||||
return false;
|
||||
};
|
||||
const needPrefetchingCode = chunk => {
|
||||
const allPrefetchChunks = chunk.getChildIdsByOrdersMap(true).prefetch;
|
||||
return allPrefetchChunks && Object.keys(allPrefetchChunks).length;
|
||||
};
|
||||
// TODO refactor this
|
||||
if (!mainTemplate.hooks.jsonpScript) {
|
||||
mainTemplate.hooks.jsonpScript = new SyncWaterfallHook([
|
||||
|
|
@ -232,9 +236,21 @@ class JsonpMainTemplatePlugin {
|
|||
mainTemplate.hooks.linkPrefetch.tap(
|
||||
"JsonpMainTemplatePlugin",
|
||||
(_, chunk, hash) => {
|
||||
const crossOriginLoading =
|
||||
mainTemplate.outputOptions.crossOriginLoading;
|
||||
|
||||
return Template.asString([
|
||||
"var link = document.createElement('link');",
|
||||
crossOriginLoading
|
||||
? `link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
|
||||
: "",
|
||||
`if (${mainTemplate.requireFn}.nc) {`,
|
||||
Template.indent(
|
||||
`link.setAttribute("nonce", ${mainTemplate.requireFn}.nc);`
|
||||
),
|
||||
"}",
|
||||
'link.rel = "prefetch";',
|
||||
'link.as = "script";',
|
||||
"link.href = jsonpScriptSrc(chunkId);"
|
||||
]);
|
||||
}
|
||||
|
|
@ -288,7 +304,7 @@ class JsonpMainTemplatePlugin {
|
|||
"",
|
||||
"// chunk preloadng for javascript",
|
||||
"",
|
||||
`var chunkPreloadMap = ${JSON.stringify(chunkMap, null, "\t")}`,
|
||||
`var chunkPreloadMap = ${JSON.stringify(chunkMap, null, "\t")};`,
|
||||
"",
|
||||
"var chunkPreloadData = chunkPreloadMap[chunkId];",
|
||||
"if(chunkPreloadData) {",
|
||||
|
|
@ -310,45 +326,6 @@ class JsonpMainTemplatePlugin {
|
|||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireEnsure.tap(
|
||||
{
|
||||
name: "JsonpMainTemplatePlugin prefetch",
|
||||
stage: 20
|
||||
},
|
||||
(source, chunk, hash) => {
|
||||
const chunkMap = chunk.getChildIdsByOrdersMap().prefetch;
|
||||
if (!chunkMap || Object.keys(chunkMap).length === 0) return source;
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
"// chunk prefetching for javascript",
|
||||
"",
|
||||
`var chunkPrefetchMap = ${JSON.stringify(chunkMap, null, "\t")}`,
|
||||
"",
|
||||
"var chunkPrefetchData = chunkPrefetchMap[chunkId];",
|
||||
"if(chunkPrefetchData) {",
|
||||
Template.indent([
|
||||
"Promise.all(promises).then(function() {",
|
||||
Template.indent([
|
||||
"var head = document.getElementsByTagName('head')[0];",
|
||||
"chunkPrefetchData.forEach(function(chunkId) {",
|
||||
Template.indent([
|
||||
"if(installedChunks[chunkId] === undefined) {",
|
||||
Template.indent([
|
||||
"installedChunks[chunkId] = null;",
|
||||
mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
|
||||
"head.appendChild(link);"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"});"
|
||||
]),
|
||||
"})"
|
||||
]),
|
||||
"}"
|
||||
]);
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.requireExtensions.tap(
|
||||
"JsonpMainTemplatePlugin",
|
||||
(source, chunk) => {
|
||||
|
|
@ -369,6 +346,7 @@ class JsonpMainTemplatePlugin {
|
|||
(source, chunk, hash) => {
|
||||
if (needChunkLoadingCode(chunk)) {
|
||||
const withDefer = needEntryDeferringCode(chunk);
|
||||
const withPrefetch = needPrefetchingCode(chunk);
|
||||
return Template.asString([
|
||||
source,
|
||||
"",
|
||||
|
|
@ -378,6 +356,7 @@ class JsonpMainTemplatePlugin {
|
|||
"var chunkIds = data[0];",
|
||||
"var moreModules = data[1];",
|
||||
withDefer ? "var executeModules = data[2];" : "",
|
||||
withPrefetch ? "var prefetchChunks = data[3] || [];" : "",
|
||||
'// add "moreModules" to the modules object,',
|
||||
'// then flag all "chunkIds" as loaded and fire callback',
|
||||
"var moduleId, chunkId, i = 0, resolves = [];",
|
||||
|
|
@ -405,6 +384,23 @@ class JsonpMainTemplatePlugin {
|
|||
]),
|
||||
"}",
|
||||
"if(parentJsonpFunction) parentJsonpFunction(data);",
|
||||
withPrefetch
|
||||
? Template.asString([
|
||||
"// chunk prefetching for javascript",
|
||||
"var head = document.getElementsByTagName('head')[0];",
|
||||
"prefetchChunks.forEach(function(chunkId) {",
|
||||
Template.indent([
|
||||
"if(installedChunks[chunkId] === undefined) {",
|
||||
Template.indent([
|
||||
"installedChunks[chunkId] = null;",
|
||||
mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
|
||||
"head.appendChild(link);"
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"});"
|
||||
])
|
||||
: "",
|
||||
"while(resolves.length) {",
|
||||
Template.indent("resolves.shift()();"),
|
||||
"}",
|
||||
|
|
@ -479,6 +475,25 @@ class JsonpMainTemplatePlugin {
|
|||
return source;
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.beforeStartup.tap(
|
||||
"JsonpMainTemplatePlugin",
|
||||
(source, chunk, hash) => {
|
||||
const prefetchChunks = chunk.getChildIdsByOrders().prefetch;
|
||||
if (
|
||||
needChunkLoadingCode(chunk) &&
|
||||
prefetchChunks &&
|
||||
prefetchChunks.length
|
||||
) {
|
||||
return Template.asString([
|
||||
source,
|
||||
`webpackJsonpCallback([[], {}, 0, ${JSON.stringify(
|
||||
prefetchChunks
|
||||
)}]);`
|
||||
]);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
);
|
||||
mainTemplate.hooks.startup.tap(
|
||||
"JsonpMainTemplatePlugin",
|
||||
(source, chunk, hash) => {
|
||||
|
|
|
|||
|
|
@ -77,25 +77,32 @@ rules:
|
|||
id: logResult
|
||||
value: "{{{fetch}}}"
|
||||
remove:
|
||||
- ".\\[2K.\\[1G|.\\[999D.\\[K"
|
||||
- "^[\\s\\S]+?\\$ yarn travis:\\$JOB_PART.*\n"
|
||||
- "\\$ node --max-old-space-size=4096.*\n"
|
||||
- "^yarn run.+\n"
|
||||
- "\\(node:\\d+\\) \\[DEP0005\\].+\n"
|
||||
- ".+rimraf coverage"
|
||||
- "yarn run.+\n"
|
||||
- "\\(node:\\d+\\) (\\[DEP0005\\]|DeprecationWarning).+\n"
|
||||
- "\\$ yarn (cover|test):.+\n"
|
||||
- "Ran all test suites.\n[\\s\\S]*"
|
||||
- "PASS test/.*\n"
|
||||
- "error Command failed with exit code \\d+.\n"
|
||||
- "info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\n"
|
||||
- "Force exiting Jest\n\nHave you considered.+"
|
||||
- "=============================== Coverage summary ===============================[\\s\\S]+?================================================================================"
|
||||
- " *PASS *test/.*\n"
|
||||
- "^\\s+\n|\\s+$"
|
||||
string_cleanup_1:
|
||||
id: firstError
|
||||
value: "{{{logResult}}}"
|
||||
remove:
|
||||
- "\n\n ●[\\s\\S]*"
|
||||
- "\n\n( ●| FAIL)[\\s\\S]*"
|
||||
- "Test Suites:[\\s\\S]*"
|
||||
- "\\s+$"
|
||||
string_cleanup_2:
|
||||
id: remainingErrors
|
||||
value: "{{{logResult}}}"
|
||||
remove:
|
||||
- "^[\\s\\S]+?(?=\n\n ●|$)"
|
||||
- "^[\\s\\S]+?(?=\n\n( ●| FAIL)|$)"
|
||||
- "^\n+"
|
||||
- "Test Suites:[\\s\\S]*"
|
||||
- "\\s+$"
|
||||
|
|
@ -155,25 +162,33 @@ rules:
|
|||
id: logResult
|
||||
value: "{{{fetch}}}"
|
||||
remove:
|
||||
- ".\\[2K.\\[1G|.\\[999D.\\[K"
|
||||
- "^[\\s\\S]+?\\$ yarn travis:\\$JOB_PART.*\n"
|
||||
- "\\$ node --max-old-space-size=4096.*\n"
|
||||
- "^yarn run.+\n"
|
||||
- "\\(node:\\d+\\) \\[DEP0005\\].+\n"
|
||||
- ".+rimraf coverage"
|
||||
- "yarn run.+\n"
|
||||
- "\\(node:\\d+\\) (\\[DEP0005\\]|DeprecationWarning).+\n"
|
||||
- "\\$ yarn (cover|test):.+\n"
|
||||
- "The command \"yarn travis:\\$JOB_PART\" exited[\\s\\S]*"
|
||||
- "PASS test/.*\n"
|
||||
- "Ran all test suites.+\n"
|
||||
- "error Command failed with exit code \\d+.\n"
|
||||
- "info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\n"
|
||||
- "Force exiting Jest\n\nHave you considered.+"
|
||||
- "=============================== Coverage summary ===============================[\\s\\S]+?================================================================================"
|
||||
- " *PASS *test/.*\n"
|
||||
- "^\\s+\n|\\s+$"
|
||||
string_cleanup_1:
|
||||
id: firstError
|
||||
value: "{{{logResult}}}"
|
||||
remove:
|
||||
- "\n\n ●[\\s\\S]*"
|
||||
- "\n\n( ●| FAIL)[\\s\\S]*"
|
||||
- "Test Suites:[\\s\\S]*"
|
||||
- "\\s+$"
|
||||
string_cleanup_2:
|
||||
id: remainingErrors
|
||||
value: "{{{logResult}}}"
|
||||
remove:
|
||||
- "^[\\s\\S]+?(?=\n\n ●|$)"
|
||||
- "^[\\s\\S]+?(?=\n\n( ●| FAIL)|$)"
|
||||
- "^\n+"
|
||||
- "Test Suites:[\\s\\S]*"
|
||||
- "\\s+$"
|
||||
|
|
@ -233,13 +248,21 @@ rules:
|
|||
id: logResult
|
||||
value: "{{{fetch}}}"
|
||||
remove:
|
||||
- ".\\[2K.\\[1G|.\\[999D.\\[K"
|
||||
- "^[\\s\\S]+?\\$ yarn travis:\\$JOB_PART.*\n"
|
||||
- "\\$ node --max-old-space-size=4096.*\n"
|
||||
- "^yarn run.+\n"
|
||||
- "\\(node:\\d+\\) \\[DEP0005\\].+\n"
|
||||
- ".+rimraf coverage"
|
||||
- "yarn run.+\n"
|
||||
- "\\(node:\\d+\\) (\\[DEP0005\\]|DeprecationWarning).+\n"
|
||||
- "\\$ yarn (unit|lint).+\n"
|
||||
- "The command \"yarn travis:\\$JOB_PART\" exited[\\s\\S]*"
|
||||
- "PASS test/.*\n"
|
||||
- "Ran all test suites.+\n"
|
||||
- "error Command failed with exit code \\d+.\n"
|
||||
- "info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.\n"
|
||||
- "Force exiting Jest\n\nHave you considered.+"
|
||||
- "=============================== Coverage summary ===============================[\\s\\S]+?================================================================================"
|
||||
- " *PASS *test/.*\n"
|
||||
- "^\\s+\n|\\s+$"
|
||||
actions:
|
||||
comment:
|
||||
identifier: "ci-result"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.5.10",
|
||||
"@webassemblyjs/helper-module-context": "1.5.10",
|
||||
"@webassemblyjs/wasm-edit": "1.5.10",
|
||||
"@webassemblyjs/wasm-opt": "1.5.10",
|
||||
"@webassemblyjs/wasm-parser": "1.5.10",
|
||||
|
|
|
|||
|
|
@ -1542,6 +1542,10 @@
|
|||
"description": "Avoid emitting assets when errors occur",
|
||||
"type": "boolean"
|
||||
},
|
||||
"checkWasmTypes": {
|
||||
"description": "Check for incompatible wasm types when importing/exporting from/to ESM",
|
||||
"type": "boolean"
|
||||
},
|
||||
"namedModules": {
|
||||
"description": "Use readable module identifiers for better debugging",
|
||||
"type": "boolean"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ const vm = require("vm");
|
|||
const mkdirp = require("mkdirp");
|
||||
const rimraf = require("rimraf");
|
||||
const checkArrayExpectation = require("./checkArrayExpectation");
|
||||
const FakeDocument = require("./helpers/FakeDocument");
|
||||
|
||||
const Stats = require("../lib/Stats");
|
||||
const webpack = require("../lib/webpack");
|
||||
|
|
@ -176,7 +177,8 @@ describe("ConfigTestCases", () => {
|
|||
console: console,
|
||||
expect: expect,
|
||||
setTimeout: setTimeout,
|
||||
clearTimeout: clearTimeout
|
||||
clearTimeout: clearTimeout,
|
||||
document: new FakeDocument()
|
||||
};
|
||||
|
||||
function _require(currentDirectory, module) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ describe("ModuleDependencyError", () => {
|
|||
});
|
||||
|
||||
it("has a message property", () => {
|
||||
expect(env.moduleDependencyError.message).toBe("Location Error Message");
|
||||
expect(env.moduleDependencyError.message).toBe("Error Message");
|
||||
});
|
||||
|
||||
it("has a loc property", () => {
|
||||
expect(env.moduleDependencyError.loc).toBe("Location");
|
||||
});
|
||||
|
||||
it("has a details property", () => {
|
||||
|
|
@ -38,8 +42,8 @@ describe("ModuleDependencyError", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("has an origin property", () => {
|
||||
expect(env.moduleDependencyError.origin).toBe("myModule");
|
||||
it("has an module property", () => {
|
||||
expect(env.moduleDependencyError.module).toBe("myModule");
|
||||
});
|
||||
|
||||
it("has an error property", () => {
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ describe("NormalModule", () => {
|
|||
let resource;
|
||||
let parser;
|
||||
beforeEach(() => {
|
||||
request = "some/request";
|
||||
userRequest = "some/userRequest";
|
||||
request = "/some/request";
|
||||
userRequest = "/some/userRequest";
|
||||
rawRequest = "some/rawRequest";
|
||||
loaders = [];
|
||||
resource = "some/resource";
|
||||
resource = "/some/resource";
|
||||
parser = {
|
||||
parse() {}
|
||||
};
|
||||
|
|
@ -66,14 +66,14 @@ describe("NormalModule", () => {
|
|||
it("contextifies the userRequest of the module", () => {
|
||||
expect(
|
||||
normalModule.libIdent({
|
||||
context: "some/context"
|
||||
context: "/some/context"
|
||||
})
|
||||
).toBe("../userRequest");
|
||||
});
|
||||
describe("given a userRequest containing loaders", () => {
|
||||
beforeEach(() => {
|
||||
userRequest =
|
||||
"some/userRequest!some/other/userRequest!some/thing/is/off/here";
|
||||
"/some/userRequest!/some/other/userRequest!/some/thing/is/off/here";
|
||||
normalModule = new NormalModule({
|
||||
type: "javascript/auto",
|
||||
request,
|
||||
|
|
@ -87,7 +87,7 @@ describe("NormalModule", () => {
|
|||
it("contextifies every path in the userRequest", () => {
|
||||
expect(
|
||||
normalModule.libIdent({
|
||||
context: "some/context"
|
||||
context: "/some/context"
|
||||
})
|
||||
).toBe("../userRequest!../other/userRequest!../thing/is/off/here");
|
||||
});
|
||||
|
|
@ -95,7 +95,7 @@ describe("NormalModule", () => {
|
|||
describe("given a userRequest containing query parameters", () => {
|
||||
it("ignores paths in query parameters", () => {
|
||||
userRequest =
|
||||
"some/context/loader?query=foo\\bar&otherPath=testpath/other";
|
||||
"F:\\some\\context\\loader?query=foo\\bar&otherPath=testpath/other";
|
||||
normalModule = new NormalModule({
|
||||
type: "javascript/auto",
|
||||
request,
|
||||
|
|
@ -107,7 +107,7 @@ describe("NormalModule", () => {
|
|||
});
|
||||
expect(
|
||||
normalModule.libIdent({
|
||||
context: "some/context"
|
||||
context: "F:\\some\\context"
|
||||
})
|
||||
).toBe("./loader?query=foo\\bar&otherPath=testpath/other");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ describe(
|
|||
});
|
||||
const inputPath =
|
||||
"./node_modules/ts-loader!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/app.vue";
|
||||
const expectPath = `./src/app.vue (${inputPath})\n`;
|
||||
const expectPath = `./src/app.vue (${inputPath})`;
|
||||
|
||||
expect(mockStats.formatFilePath(inputPath)).toBe(expectPath);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Child fitting:
|
|||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
9ac13fb7087e9ff1b93e.js 1.05 KiB 0 [emitted]
|
||||
f2e891598128a57b072c.js 11 KiB 1 [emitted]
|
||||
f2e891598128a57b072c.js 11.1 KiB 1 [emitted]
|
||||
d1ba53816ff760e185b0.js 1.94 KiB 2 [emitted]
|
||||
7b5b0a943e9362bc88c6.js 1.94 KiB 3 [emitted]
|
||||
Entrypoint main = d1ba53816ff760e185b0.js 7b5b0a943e9362bc88c6.js f2e891598128a57b072c.js
|
||||
|
|
@ -34,7 +34,7 @@ Child content-change:
|
|||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
9ac13fb7087e9ff1b93e.js 1.05 KiB 0 [emitted]
|
||||
f2e891598128a57b072c.js 11 KiB 1 [emitted]
|
||||
f2e891598128a57b072c.js 11.1 KiB 1 [emitted]
|
||||
d1ba53816ff760e185b0.js 1.94 KiB 2 [emitted]
|
||||
7b5b0a943e9362bc88c6.js 1.94 KiB 3 [emitted]
|
||||
Entrypoint main = d1ba53816ff760e185b0.js 7b5b0a943e9362bc88c6.js f2e891598128a57b072c.js
|
||||
|
|
@ -71,7 +71,7 @@ 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]
|
||||
c69b2f79fdf6e98907c4.js 9.68 KiB 10 [emitted] main
|
||||
c69b2f79fdf6e98907c4.js 9.7 KiB 10 [emitted] main
|
||||
fcdf398c8972e4dcf788.js 1.94 KiB 11 [emitted]
|
||||
Entrypoint main = c69b2f79fdf6e98907c4.js
|
||||
chunk {0} fd868baa40dab4fc30fd.js 1.76 KiB <{10}> ={1}= ={2}= ={3}= ={7}= ={9}= [recorded] aggressive splitted
|
||||
|
|
@ -498,7 +498,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
Asset Size Chunks Chunk Names
|
||||
0.bundle.js 152 bytes 0 [emitted]
|
||||
1.bundle.js 289 bytes 1 [emitted]
|
||||
bundle.js 8.27 KiB 2 [emitted] main
|
||||
bundle.js 8.29 KiB 2 [emitted] main
|
||||
3.bundle.js 227 bytes 3 [emitted]
|
||||
Entrypoint main = bundle.js
|
||||
chunk {0} 0.bundle.js 22 bytes <{2}> [rendered]
|
||||
|
|
@ -537,7 +537,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
0.bundle.js 433 bytes 0 [emitted]
|
||||
1.bundle.js 297 bytes 1 [emitted]
|
||||
2.bundle.js 588 bytes 2 [emitted]
|
||||
bundle.js 8.65 KiB main [emitted] main
|
||||
bundle.js 8.67 KiB main [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
chunk {main} bundle.js (main) 73 bytes >{0}< >{1}< [entry] [rendered]
|
||||
> ./index main
|
||||
|
|
@ -615,7 +615,7 @@ exports[`StatsTestCases should print correct stats for commons-chunk-min-size-0
|
|||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
entry-1.js 6.58 KiB 0 [emitted] entry-1
|
||||
entry-1.js 6.6 KiB 0 [emitted] entry-1
|
||||
vendor-1~entry-1.js 314 bytes 1 [emitted] vendor-1~entry-1
|
||||
Entrypoint entry-1 = vendor-1~entry-1.js entry-1.js
|
||||
[0] ./entry-1.js 145 bytes {0} [built]
|
||||
|
|
@ -632,7 +632,7 @@ exports[`StatsTestCases should print correct stats for commons-chunk-min-size-In
|
|||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
entry-1.js 6.58 KiB 0 [emitted] entry-1
|
||||
entry-1.js 6.6 KiB 0 [emitted] entry-1
|
||||
vendor-1.js 314 bytes 1 [emitted] vendor-1
|
||||
Entrypoint entry-1 = vendor-1.js entry-1.js
|
||||
[0] ./entry-1.js 145 bytes {0} [built]
|
||||
|
|
@ -651,7 +651,7 @@ Child
|
|||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
app.js 6.67 KiB 0 [emitted] app
|
||||
app.js 6.69 KiB 0 [emitted] app
|
||||
vendor.6a3bdffda9f0de672978.js 619 bytes 1 [emitted] vendor
|
||||
Entrypoint app = vendor.6a3bdffda9f0de672978.js app.js
|
||||
[./constants.js] 87 bytes {1} [built]
|
||||
|
|
@ -664,7 +664,7 @@ Child
|
|||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
app.js 6.69 KiB 0 [emitted] app
|
||||
app.js 6.7 KiB 0 [emitted] app
|
||||
vendor.6a3bdffda9f0de672978.js 619 bytes 1 [emitted] vendor
|
||||
Entrypoint app = vendor.6a3bdffda9f0de672978.js app.js
|
||||
[./constants.js] 87 bytes {1} [built]
|
||||
|
|
@ -985,7 +985,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
0.js 305 bytes 0 [emitted]
|
||||
1.js 314 bytes 1 [emitted]
|
||||
2.js 308 bytes 2 [emitted]
|
||||
entry.js 9.06 KiB 3 [emitted] entry
|
||||
entry.js 9.08 KiB 3 [emitted] entry
|
||||
Entrypoint entry = entry.js
|
||||
[0] ./templates/bar.js 38 bytes {0} [optional] [built]
|
||||
[1] ./templates/baz.js 38 bytes {1} [optional] [built]
|
||||
|
|
@ -1000,13 +1000,35 @@ Time: Xms
|
|||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
0.js 149 bytes 0 [emitted]
|
||||
entry.js 8.51 KiB 1 [emitted] entry
|
||||
entry.js 8.53 KiB 1 [emitted] entry
|
||||
Entrypoint entry = entry.js
|
||||
[0] ./modules/b.js 22 bytes {0} [built]
|
||||
[1] ./entry.js 120 bytes {1} [built]
|
||||
[2] ./modules/a.js 37 bytes [built]"
|
||||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for import-with-invalid-options-comments 1`] = `
|
||||
"Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
[0] ./chunk-a.js 27 bytes {2} [built]
|
||||
[1] ./chunk-b.js 27 bytes {3} [built]
|
||||
[2] ./chunk-c.js 27 bytes {4} [built]
|
||||
[3] ./chunk-d.js 27 bytes {5} [built]
|
||||
[4] ./chunk.js 401 bytes {0} [built] [3 warnings]
|
||||
[5] ./index.js 50 bytes {1} [built]
|
||||
|
||||
WARNING in ./chunk.js 4:11-77
|
||||
Compilation error while processing magic comment(-s): /* webpack Prefetch: 0, webpackChunkName: \\"notGoingToCompile-c\\" */: Unexpected identifier
|
||||
@ ./index.js 1:0-49
|
||||
|
||||
WARNING in ./chunk.js 5:11-38
|
||||
Compilation error while processing magic comment(-s): /* webpackPrefetch: nope */: nope is not defined
|
||||
@ ./index.js 1:0-49
|
||||
|
||||
WARNING in ./chunk.js 2:11-84
|
||||
Compilation error while processing magic comment(-s): /* webpackPrefetch: true, webpackChunkName: notGoingToCompileChunkName */: notGoingToCompileChunkName is not defined
|
||||
@ ./index.js 1:0-49"
|
||||
`;
|
||||
|
||||
exports[`StatsTestCases should print correct stats for limit-chunk-count-plugin 1`] = `
|
||||
"Hash: 3c127dca42ce1c13b8eae6c0ceac1aa3be512946a5969fc94d792cce5364503bf42779f704747e2d
|
||||
Child 1 chunks:
|
||||
|
|
@ -1014,7 +1036,7 @@ Child 1 chunks:
|
|||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
bundle.js 6.37 KiB 0 [emitted] main
|
||||
bundle.js 6.39 KiB 0 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
chunk {0} bundle.js (main) 191 bytes <{0}> >{0}< [entry] [rendered]
|
||||
[0] ./index.js 73 bytes {0} [built]
|
||||
|
|
@ -1029,7 +1051,7 @@ Child 2 chunks:
|
|||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
0.bundle.js 632 bytes 0 [emitted]
|
||||
bundle.js 8.26 KiB 1 [emitted] main
|
||||
bundle.js 8.28 KiB 1 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
chunk {0} 0.bundle.js 118 bytes <{0}> <{1}> >{0}< [rendered]
|
||||
[0] ./d.js 22 bytes {0} [built]
|
||||
|
|
@ -1046,7 +1068,7 @@ Child 3 chunks:
|
|||
Asset Size Chunks Chunk Names
|
||||
0.bundle.js 494 bytes 0 [emitted]
|
||||
1.bundle.js 245 bytes 1 [emitted]
|
||||
bundle.js 8.26 KiB 2 [emitted] main
|
||||
bundle.js 8.28 KiB 2 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
chunk {0} 0.bundle.js 74 bytes <{0}> <{2}> >{0}< >{1}< [rendered]
|
||||
[0] ./d.js 22 bytes {0} [built]
|
||||
|
|
@ -1065,7 +1087,7 @@ Child 4 chunks:
|
|||
0.bundle.js 236 bytes 0 [emitted]
|
||||
1.bundle.js 245 bytes 1 [emitted]
|
||||
2.bundle.js 323 bytes 2 [emitted]
|
||||
bundle.js 8.26 KiB 3 [emitted] main
|
||||
bundle.js 8.28 KiB 3 [emitted] main
|
||||
Entrypoint main = bundle.js
|
||||
chunk {0} 0.bundle.js 44 bytes <{2}> <{3}> [rendered]
|
||||
[0] ./d.js 22 bytes {0} [built]
|
||||
|
|
@ -1157,9 +1179,9 @@ exports[`StatsTestCases should print correct stats for module-deduplication 1`]
|
|||
3.js 661 bytes 3 [emitted]
|
||||
4.js 661 bytes 4 [emitted]
|
||||
5.js 661 bytes 5 [emitted]
|
||||
e1.js 9.4 KiB 6 [emitted] e1
|
||||
e2.js 9.43 KiB 7 [emitted] e2
|
||||
e3.js 9.45 KiB 8 [emitted] e3
|
||||
e1.js 9.42 KiB 6 [emitted] e1
|
||||
e2.js 9.44 KiB 7 [emitted] e2
|
||||
e3.js 9.46 KiB 8 [emitted] e3
|
||||
Entrypoint e1 = e1.js
|
||||
Entrypoint e2 = e2.js
|
||||
Entrypoint e3 = e3.js
|
||||
|
|
@ -1203,9 +1225,9 @@ exports[`StatsTestCases should print correct stats for module-deduplication-name
|
|||
async3.js 818 bytes 0 [emitted] async3
|
||||
async1.js 818 bytes 1 [emitted] async1
|
||||
async2.js 818 bytes 2 [emitted] async2
|
||||
e1.js 9.29 KiB 3 [emitted] e1
|
||||
e2.js 9.31 KiB 4 [emitted] e2
|
||||
e3.js 9.33 KiB 5 [emitted] e3
|
||||
e1.js 9.31 KiB 3 [emitted] e1
|
||||
e2.js 9.33 KiB 4 [emitted] e2
|
||||
e3.js 9.35 KiB 5 [emitted] e3
|
||||
Entrypoint e1 = e1.js
|
||||
Entrypoint e2 = e2.js
|
||||
Entrypoint e3 = e3.js
|
||||
|
|
@ -1321,7 +1343,7 @@ exports[`StatsTestCases should print correct stats for named-chunks-plugin 1`] =
|
|||
Time: Xms
|
||||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
entry.js 6.43 KiB entry [emitted] entry
|
||||
entry.js 6.45 KiB entry [emitted] entry
|
||||
vendor.js 269 bytes vendor [emitted] vendor
|
||||
Entrypoint entry = vendor.js entry.js
|
||||
[./entry.js] 72 bytes {entry} [built]
|
||||
|
|
@ -1337,7 +1359,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
Asset Size Chunks Chunk Names
|
||||
chunk-containing-__a_js.js 313 bytes chunk-containing-__a_js [emitted]
|
||||
chunk-containing-__b_js.js 173 bytes chunk-containing-__b_js [emitted]
|
||||
entry.js 8.17 KiB entry [emitted] entry
|
||||
entry.js 8.18 KiB entry [emitted] entry
|
||||
Entrypoint entry = entry.js
|
||||
[0] ./modules/b.js 22 bytes {chunk-containing-__b_js} [built]
|
||||
[1] ./modules/a.js 37 bytes {chunk-containing-__a_js} [built]
|
||||
|
|
@ -1375,7 +1397,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
ab.js 183 bytes 1 [emitted] ab
|
||||
abd.js 277 bytes 2, 1 [emitted] abd
|
||||
cir2.js 299 bytes 3 [emitted] cir2
|
||||
main.js 9.07 KiB 4 [emitted] main
|
||||
main.js 9.09 KiB 4 [emitted] main
|
||||
cir2 from cir1.js 359 bytes 5, 3 [emitted] cir2 from cir1
|
||||
chunk.js 190 bytes 6, 7 [emitted] chunk
|
||||
ac in ab.js 130 bytes 7 [emitted] ac in ab
|
||||
|
|
@ -1425,12 +1447,12 @@ Entrypoint main = main.js
|
|||
| ./index.js 15 bytes [built]
|
||||
| ./a.js 15 bytes [built]
|
||||
|
||||
ERROR in ./b.js
|
||||
ERROR in ./b.js 6:7
|
||||
Module parse failed: Unexpected token (6:7)
|
||||
You may need an appropriate loader to handle this file type.
|
||||
| includes
|
||||
| a
|
||||
| parser )
|
||||
> parser )
|
||||
| error
|
||||
| in
|
||||
@ ./a.js 2:0-13
|
||||
|
|
@ -1668,11 +1690,11 @@ For more info visit https://webpack.js.org/guides/code-splitting/</CLR>"
|
|||
|
||||
exports[`StatsTestCases should print correct stats for prefetch 1`] = `
|
||||
" Asset Size Chunks Chunk Names
|
||||
prefetched.js 467 bytes 0 [emitted] prefetched
|
||||
prefetched.js 475 bytes 0 [emitted] prefetched
|
||||
normal.js 130 bytes 1 [emitted] normal
|
||||
prefetched2.js 127 bytes 2 [emitted] prefetched2
|
||||
prefetched3.js 130 bytes 3 [emitted] prefetched3
|
||||
main.js 9.73 KiB 4 [emitted] main
|
||||
main.js 9.66 KiB 4 [emitted] main
|
||||
inner.js 136 bytes 5 [emitted] inner
|
||||
inner2.js 201 bytes 6 [emitted] inner2
|
||||
Entrypoint main = main.js (prefetch: prefetched2.js prefetched.js prefetched3.js)
|
||||
|
|
@ -1705,7 +1727,7 @@ exports[`StatsTestCases should print correct stats for preload 1`] = `
|
|||
normal.js 130 bytes 1 [emitted] normal
|
||||
preloaded2.js 127 bytes 2 [emitted] preloaded2
|
||||
preloaded3.js 130 bytes 3 [emitted] preloaded3
|
||||
main.js 9.85 KiB 4 [emitted] main
|
||||
main.js 9.87 KiB 4 [emitted] main
|
||||
inner.js 136 bytes 5 [emitted] inner
|
||||
inner2.js 201 bytes 6 [emitted] inner2
|
||||
Entrypoint main = main.js (preload: preloaded2.js preloaded.js preloaded3.js)
|
||||
|
|
@ -1725,7 +1747,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
Asset Size Chunks Chunk Names
|
||||
0.js 152 bytes 0 [emitted]
|
||||
1.js 289 bytes 1 [emitted]
|
||||
main.js 8.28 KiB 2 [emitted] main
|
||||
main.js 8.29 KiB 2 [emitted] main
|
||||
3.js 227 bytes 3 [emitted]
|
||||
Entrypoint main = main.js
|
||||
chunk {0} 0.js 22 bytes <{2}> [rendered]
|
||||
|
|
@ -1784,7 +1806,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
Asset Size Chunks Chunk Names
|
||||
0.js 152 bytes 0 [emitted]
|
||||
1.js 289 bytes 1 [emitted]
|
||||
main.js 8.28 KiB 2 [emitted] main
|
||||
main.js 8.29 KiB 2 [emitted] main
|
||||
3.js 227 bytes 3 [emitted]
|
||||
Entrypoint main = main.js
|
||||
[0] ./d.js 22 bytes {3} [built]
|
||||
|
|
@ -1862,7 +1884,7 @@ Built at: Thu Jan 01 1970 00:00:00 GMT
|
|||
Asset Size Chunks Chunk Names
|
||||
0.js 152 bytes 0 [emitted]
|
||||
1.js 289 bytes 1 [emitted]
|
||||
main.js 8.28 KiB 2 [emitted] main
|
||||
main.js 8.29 KiB 2 [emitted] main
|
||||
3.js 227 bytes 3 [emitted]
|
||||
Entrypoint main = main.js
|
||||
chunk {0} 0.js 22 bytes <{2}> [rendered]
|
||||
|
|
@ -1953,7 +1975,7 @@ exports[`StatsTestCases should print correct stats for runtime-chunk-integration
|
|||
Asset Size Chunks Chunk Names
|
||||
0.js 719 bytes 0 [emitted]
|
||||
main1.js 542 bytes 1 [emitted] main1
|
||||
runtime.js 8.73 KiB 2 [emitted] runtime
|
||||
runtime.js 8.75 KiB 2 [emitted] runtime
|
||||
Entrypoint main1 = runtime.js main1.js
|
||||
[0] ./b.js 20 bytes {0} [built]
|
||||
[1] ./c.js 20 bytes {0} [built]
|
||||
|
|
@ -1962,7 +1984,7 @@ exports[`StatsTestCases should print correct stats for runtime-chunk-integration
|
|||
Child manifest is named entry:
|
||||
Asset Size Chunks Chunk Names
|
||||
0.js 719 bytes 0 [emitted]
|
||||
manifest.js 9.04 KiB 1 [emitted] manifest
|
||||
manifest.js 9.06 KiB 1 [emitted] manifest
|
||||
main1.js 542 bytes 2 [emitted] main1
|
||||
Entrypoint main1 = manifest.js main1.js
|
||||
Entrypoint manifest = manifest.js
|
||||
|
|
@ -2068,7 +2090,7 @@ Time: Xms
|
|||
Built at: Thu Jan 01 1970 00:00:00 GMT
|
||||
Asset Size Chunks Chunk Names
|
||||
0.js 481 bytes 0 [emitted]
|
||||
main.js 9.31 KiB 1 [emitted] main
|
||||
main.js 9.32 KiB 1 [emitted] main
|
||||
Entrypoint main = main.js
|
||||
[0] ./components/src/CompAB/utils.js 97 bytes {1} [built]
|
||||
harmony side effect evaluation ./utils [1] ./main.js + 1 modules 1:0-30
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = [
|
||||
[/System.get is not supported by webpack/],
|
||||
[/System.register is not supported by webpack/],
|
||||
[/System.get is not supported by webpack/],
|
||||
[/System.set is not supported by webpack/],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
export const n = 1;
|
||||
export const m = 1.25
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
it("should export imported global", function() {
|
||||
return import("./module").then(function({ v, w, x, test }) {
|
||||
expect(v).toBe(1);
|
||||
expect(w).toBe(1);
|
||||
expect(x).toBe(1.25);
|
||||
expect(test()).toBe(2);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from "./module.wat";
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
(module
|
||||
(import "./env.js" "n" (global i32))
|
||||
(import "./env.js" "m" (global $g2 f64))
|
||||
(export "v" (global 0))
|
||||
(global $g i32 (get_global 0))
|
||||
(export "w" (global $g))
|
||||
(export "x" (global $g2))
|
||||
(func (export "test") (result i32)
|
||||
get_global $g2
|
||||
get_global $g2
|
||||
f64.add
|
||||
drop
|
||||
get_global 0
|
||||
get_global $g
|
||||
i32.add
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||
|
||||
module.exports = function(config) {
|
||||
return supportsWebAssembly();
|
||||
};
|
||||
|
|
@ -0,0 +1 @@
|
|||
export const n = 1;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
module.exports = [
|
||||
[
|
||||
/export-i64-param\.wat/,
|
||||
/Export "a" with i64 as parameter can only be used for direct wasm to wasm dependencies/,
|
||||
/export-i64-param\.js/
|
||||
],
|
||||
[
|
||||
/export-i64-result\.wat/,
|
||||
/Export "a" with i64 as result can only be used for direct wasm to wasm dependencies/,
|
||||
/export-i64-result\.js/
|
||||
],
|
||||
[
|
||||
/import-i64\.wat/,
|
||||
/Import "n" from "\.\/env.js" with Non-JS-compatible Global Type \(i64\) can only be used for direct wasm to wasm dependencies/,
|
||||
/index\.js/
|
||||
]
|
||||
]
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { a } from "./export-i64-param.wat";
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
(module
|
||||
(func (export "a") (param i64) (nop))
|
||||
)
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { a } from "./export-i64-result.wat";
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
(module
|
||||
(func (export "a") (result i64)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
(module
|
||||
(import "./env.js" "n" (global i64))
|
||||
)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
const errorRegex = /wasm function signature contains illegal type|invalid type/;
|
||||
|
||||
it("should disallow exporting a func signature with result i64", function() {
|
||||
return import("./export-i64-result").then(({a}) => {
|
||||
expect(() => a()).toThrow(errorRegex);
|
||||
});
|
||||
});
|
||||
|
||||
it("should disallow exporting a func signature with param i64", function() {
|
||||
return import("./export-i64-param").then(({a}) => {
|
||||
expect(() => a()).toThrow(errorRegex);
|
||||
});
|
||||
});
|
||||
|
||||
it("should disallow importing a value type of i64", function() {
|
||||
return expect(import("./import-i64.wat")).rejects.toThrow(errorRegex);
|
||||
});
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||
|
||||
module.exports = function(config) {
|
||||
return supportsWebAssembly() && config.mode === "production";
|
||||
};
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
it("should be able to create two modules from loader", function() {
|
||||
return import("./wrapper-loader!./src/wasm.dat").then(function(wasm) {
|
||||
expect(wasm.getString()).toEqual("Hello World");
|
||||
});
|
||||
});
|
||||
|
||||
it("should be able to create two modules from loader with remaining request", function() {
|
||||
return import("./wrapper-loader2!./src/wasm.dat?2").then(function(wasm) {
|
||||
expect(wasm.getString()).toEqual("Hello World");
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
(module
|
||||
(memory (export "memory") 1)
|
||||
(data (i32.const 16) "Hello World\00")
|
||||
(func (export "getString") (result i32)
|
||||
(i32.const 16)
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||
|
||||
module.exports = function(config) {
|
||||
return supportsWebAssembly();
|
||||
};
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
const stringifyRequest = require("loader-utils").stringifyRequest;
|
||||
|
||||
module.exports.pitch = function(remainingRequest) {
|
||||
return `
|
||||
import { getString as _getString, memory } from ${stringifyRequest(this,
|
||||
`${this.resourcePath}.wat!=!${remainingRequest}`
|
||||
)};
|
||||
|
||||
export function getString() {
|
||||
const strBuf = new Uint8Array(memory.buffer, _getString());
|
||||
const idx = strBuf.indexOf(0);
|
||||
const strBuf2 = strBuf.slice(0, idx);
|
||||
const str = Buffer.from(strBuf2).toString("utf-8");
|
||||
return str;
|
||||
};
|
||||
`;
|
||||
};
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
const stringifyRequest = require("loader-utils").stringifyRequest;
|
||||
|
||||
module.exports.pitch = function(remainingRequest) {
|
||||
return `
|
||||
import { getString as _getString, memory } from ${stringifyRequest(
|
||||
this,
|
||||
`${this.resourcePath}.wasm!=!wast-loader!${remainingRequest}`
|
||||
)};
|
||||
|
||||
export function getString() {
|
||||
const strBuf = new Uint8Array(memory.buffer, _getString());
|
||||
const idx = strBuf.indexOf(0);
|
||||
const strBuf2 = strBuf.slice(0, idx);
|
||||
const str = Buffer.from(strBuf2).toString("utf-8");
|
||||
return str;
|
||||
};
|
||||
`;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
it("should set NODE_ENV according to mode", () => {
|
||||
expect(process.env.NODE_ENV).toBe(__MODE__);
|
||||
});
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
"use strict";
|
||||
|
||||
const DefinePlugin = require("../../../../lib/DefinePlugin");
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
name: "development",
|
||||
mode: "development",
|
||||
plugins: [new DefinePlugin({ __MODE__: `"development"` })]
|
||||
},
|
||||
{
|
||||
name: "production",
|
||||
mode: "production",
|
||||
plugins: [new DefinePlugin({ __MODE__: `"production"` })]
|
||||
},
|
||||
{
|
||||
name: "none",
|
||||
mode: "none",
|
||||
plugins: [new DefinePlugin({ __MODE__: `"none"` })]
|
||||
}
|
||||
];
|
||||
|
|
@ -1,18 +1,10 @@
|
|||
const FakeDocument = require("../../../helpers/FakeDocument");
|
||||
|
||||
beforeEach(() => {
|
||||
global.document = new FakeDocument();
|
||||
global.window = {};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete global.document;
|
||||
delete global.window;
|
||||
});
|
||||
|
||||
it("should be able to load the split chunk on demand", () => {
|
||||
const promise = import(/* webpackChunkName: "shared" */ "./shared");
|
||||
|
||||
const script = document.head._children[0];
|
||||
expect(script.src).toBe("dep~b~shared.js");
|
||||
|
||||
__non_webpack_require__("./dep~b~shared.js");
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
export default function() {
|
||||
import(/* webpackPrefetch: true, webpackChunkName: "chunk1-a" */ "./chunk1-a");
|
||||
import(/* webpackPreload: true, webpackChunkName: "chunk1-b" */ "./chunk1-b");
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
const FakeDocument = require("../../../helpers/FakeDocument");
|
||||
|
||||
let oldNonce;
|
||||
let oldPublicPath;
|
||||
|
|
@ -6,54 +5,95 @@ let oldPublicPath;
|
|||
beforeEach(() => {
|
||||
oldNonce = __webpack_nonce__;
|
||||
oldPublicPath = __webpack_public_path__;
|
||||
global.document = new FakeDocument(undefined, false);
|
||||
global.window = {};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete global.document;
|
||||
delete global.window;
|
||||
__webpack_nonce__ = oldNonce;
|
||||
__webpack_public_path__ = oldPublicPath;
|
||||
})
|
||||
|
||||
it("should prefetch and preload child chunks on chunk load", (done) => {
|
||||
it("should prefetch and preload child chunks on chunk load", () => {
|
||||
__webpack_nonce__ = "nonce";
|
||||
__webpack_public_path__ = "/public/path/";
|
||||
|
||||
const promise = import(/* webpackChunkName: "chunk1" */ "./chunk1");
|
||||
expect(document.head._children).toHaveLength(2);
|
||||
const script = document.head._children[0];
|
||||
let link, script;
|
||||
|
||||
expect(document.head._children).toHaveLength(1);
|
||||
|
||||
// Test prefetch from entry chunk
|
||||
link = document.head._children[0];
|
||||
expect(link._type).toBe("link");
|
||||
expect(link.rel).toBe("prefetch");
|
||||
expect(link.href).toMatch(/chunk1\.js$/);
|
||||
|
||||
const promise = import(/* webpackChunkName: "chunk1", webpackPrefetch: true */ "./chunk1");
|
||||
|
||||
expect(document.head._children).toHaveLength(3);
|
||||
|
||||
// Test normal script loading
|
||||
script = document.head._children[1];
|
||||
expect(script._type).toBe("script");
|
||||
expect(script.src).toBe("/public/path/chunk1.js")
|
||||
expect(script.src).toMatch(/chunk1\.js$/);
|
||||
expect(script.getAttribute("nonce")).toBe("nonce")
|
||||
expect(script.crossOrigin).toBe("anonymous");
|
||||
expect(script.onload).toBeTypeOf("function");
|
||||
|
||||
let link = document.head._children[1];
|
||||
// Test preload of chunk1-b
|
||||
link = document.head._children[2];
|
||||
expect(link._type).toBe("link");
|
||||
expect(link.rel).toBe("preload");
|
||||
expect(link.as).toBe("script");
|
||||
expect(link.href).toBe("/public/path/chunk1-b.js");
|
||||
expect(link.href).toMatch(/chunk1-b\.js$/);
|
||||
expect(link.charset).toBe("utf-8");
|
||||
expect(link.getAttribute("nonce")).toBe("nonce");
|
||||
expect(link.crossOrigin).toBe("anonymous");
|
||||
|
||||
// Run the script
|
||||
__non_webpack_require__("./chunk1.js");
|
||||
|
||||
script.onload();
|
||||
|
||||
return promise.then((ex) => {
|
||||
expect(document.head._children).toHaveLength(4);
|
||||
|
||||
let link = document.head._children[2];
|
||||
expect(link._type).toBe("link");
|
||||
expect(link.rel).toBe("prefetch");
|
||||
expect(link.href).toBe("/public/path/chunk1-c.js");
|
||||
return promise.then(() => {
|
||||
expect(document.head._children).toHaveLength(5);
|
||||
|
||||
// Test prefetching for chunk1-c and chunk1-a in this order
|
||||
link = document.head._children[3];
|
||||
expect(link._type).toBe("link");
|
||||
expect(link.rel).toBe("prefetch");
|
||||
expect(link.href).toBe("/public/path/chunk1-a.js");
|
||||
done();
|
||||
}, done);
|
||||
expect(link.href).toMatch(/chunk1-c\.js$/);
|
||||
expect(link.crossOrigin).toBe("anonymous");
|
||||
|
||||
link = document.head._children[4];
|
||||
expect(link._type).toBe("link");
|
||||
expect(link.rel).toBe("prefetch");
|
||||
expect(link.href).toMatch(/chunk1-a\.js$/);
|
||||
expect(link.crossOrigin).toBe("anonymous");
|
||||
|
||||
const promise2 = import(/* webpackChunkName: "chunk1", webpackPrefetch: true */ "./chunk1");
|
||||
|
||||
// Loading chunk1 again should not trigger prefetch/preload
|
||||
expect(document.head._children).toHaveLength(5);
|
||||
|
||||
const promise3 = import(/* webpackChunkName: "chunk2" */ "./chunk2");
|
||||
|
||||
expect(document.head._children).toHaveLength(6);
|
||||
|
||||
// Test normal script loading
|
||||
script = document.head._children[5];
|
||||
expect(script._type).toBe("script");
|
||||
expect(script.src).toMatch(/chunk2\.js$/);
|
||||
expect(script.getAttribute("nonce")).toBe("nonce")
|
||||
expect(script.crossOrigin).toBe("anonymous");
|
||||
expect(script.onload).toBeTypeOf("function");
|
||||
|
||||
// Run the script
|
||||
__non_webpack_require__("./chunk2.js");
|
||||
|
||||
script.onload();
|
||||
|
||||
return promise3.then(() => {
|
||||
// Loading chunk2 again should not trigger prefetch/preload as it's already prefetch/preloaded
|
||||
expect(document.head._children).toHaveLength(6);
|
||||
});
|
||||
});
|
||||
})
|
||||
|
|
|
|||
|
|
@ -16,9 +16,8 @@ module.exports = class FakeDocument {
|
|||
};
|
||||
|
||||
class FakeElement {
|
||||
constructor(type, autoload = true) {
|
||||
constructor(type) {
|
||||
this._type = type;
|
||||
this._autoload = autoload;
|
||||
this._children = [];
|
||||
this._attributes = Object.create(null);
|
||||
}
|
||||
|
|
@ -34,33 +33,4 @@ class FakeElement {
|
|||
getAttribute(name) {
|
||||
return this._attributes[name];
|
||||
}
|
||||
|
||||
get onload() {
|
||||
return this._onload;
|
||||
}
|
||||
|
||||
set onload(script) {
|
||||
if (this._autoload === true && typeof script === "function") {
|
||||
script();
|
||||
}
|
||||
this._onload = script;
|
||||
}
|
||||
|
||||
get src() {
|
||||
return this._src;
|
||||
}
|
||||
|
||||
set src(src) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const publicPath = __webpack_public_path__;
|
||||
eval(`
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const content = fs.readFileSync(
|
||||
path.join(__dirname, '${src}'.replace('${publicPath}', '')), "utf-8"
|
||||
)
|
||||
eval(content);
|
||||
`);
|
||||
this._src = src;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
module.exports = "chunk-a";
|
||||
|
|
@ -0,0 +1 @@
|
|||
module.exports = "chunk-b";
|
||||
|
|
@ -0,0 +1 @@
|
|||
module.exports = "chunk-c";
|
||||
|
|
@ -0,0 +1 @@
|
|||
module.exports = "chunk-d";
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export default function() {
|
||||
import(/* webpackPrefetch: true, webpackChunkName: notGoingToCompileChunkName */ "./chunk-a");
|
||||
import(/* webpackPrefetch: 0, webpackChunkName: "goingToCompileChunkName-b" */ "./chunk-b");
|
||||
import(/* webpack Prefetch: 0, webpackChunkName: "notGoingToCompile-c" */ "./chunk-c");
|
||||
import(/* webpackPrefetch: nope */ /* webpackChunkName: "yep" */ "./chunk-d");
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
import(/* webpackChunkName: "chunk" */ "./chunk");
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
module.exports = {
|
||||
mode: "production",
|
||||
entry: "./index",
|
||||
output: {
|
||||
chunkFilename: "[name].js"
|
||||
},
|
||||
stats: {
|
||||
timings: false,
|
||||
hash: false,
|
||||
entrypoints: false,
|
||||
assets: false,
|
||||
errorDetails: true,
|
||||
moduleTrace: true
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue