partially fix test cases

This commit is contained in:
Tobias Koppers 2021-06-24 10:05:37 +02:00
parent 4da99d8254
commit 15408018cb
13 changed files with 300 additions and 177 deletions

View File

@ -67,7 +67,7 @@ const getSourceForGlobalVariableExternal = (variableName, type) => {
const getSourceForCommonJsExternal = moduleAndSpecifiers => {
if (!Array.isArray(moduleAndSpecifiers)) {
return {
expression: `require(${JSON.stringify(moduleAndSpecifiers)});`
expression: `require(${JSON.stringify(moduleAndSpecifiers)})`
};
}
const moduleName = moduleAndSpecifiers[0];
@ -75,7 +75,7 @@ const getSourceForCommonJsExternal = moduleAndSpecifiers => {
expression: `require(${JSON.stringify(moduleName)})${propertyAccess(
moduleAndSpecifiers,
1
)};`
)}`
};
};

View File

@ -729,7 +729,8 @@ const applyOutputDefaults = (
F(output, "wasmLoading", () => {
if (tp) {
if (tp.fetchWasm) return "fetch";
if (tp.nodeBuiltins) return "async-node";
if (tp.nodeBuiltins)
return output.module ? "async-node-module" : "async-node";
if (tp.nodeBuiltins === null || tp.fetchWasm === null) {
return "universal";
}

View File

@ -12,6 +12,10 @@ const AsyncWasmChunkLoadingRuntimeModule = require("../wasm-async/AsyncWasmChunk
/** @typedef {import("../Compiler")} Compiler */
class ReadFileCompileAsyncWasmPlugin {
constructor({ type = "async-node", import: useImport = false } = {}) {
this._type = type;
this._import = useImport;
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
@ -28,32 +32,50 @@ class ReadFileCompileAsyncWasmPlugin {
options && options.wasmLoading !== undefined
? options.wasmLoading
: globalWasmLoading;
return wasmLoading === "async-node";
return wasmLoading === this._type;
};
const generateLoadBinaryCode = path =>
Template.asString([
"new Promise(function (resolve, reject) {",
Template.indent([
"var { readFile } = require('fs');",
"var { join } = require('path');",
"",
"try {",
Template.indent([
`readFile(join(__dirname, ${path}), function(err, buffer){`,
const generateLoadBinaryCode = this._import
? path =>
Template.asString([
"Promise.all([import('fs'), import('url')]).then(([{ readFile }, { URL }]) => new Promise((resolve, reject) => {",
Template.indent([
"if (err) return reject(err);",
"",
"// Fake fetch response",
"resolve({",
Template.indent(["arrayBuffer() { return buffer; }"]),
`readFile(new URL(${path}, import.meta.url), (err, buffer) => {`,
Template.indent([
"if (err) return reject(err);",
"",
"// Fake fetch response",
"resolve({",
Template.indent(["arrayBuffer() { return buffer; }"]),
"});"
]),
"});"
]),
"});"
]),
"} catch (err) { reject(err); }"
]),
"})"
]);
"}))"
])
: path =>
Template.asString([
"new Promise(function (resolve, reject) {",
Template.indent([
"try {",
Template.indent([
"var { readFile } = require('fs');",
"var { join } = require('path');",
"",
`readFile(join(__dirname, ${path}), function(err, buffer){`,
Template.indent([
"if (err) return reject(err);",
"",
"// Fake fetch response",
"resolve({",
Template.indent(["arrayBuffer() { return buffer; }"]),
"});"
]),
"});"
]),
"} catch (err) { reject(err); }"
]),
"})"
]);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.instantiateWasm)

View File

@ -84,11 +84,20 @@ class EnableWasmLoadingPlugin {
case "async-node": {
// TODO webpack 6 remove ReadFileCompileWasmPlugin
const ReadFileCompileWasmPlugin = require("../node/ReadFileCompileWasmPlugin");
// @ts-expect-error typescript bug for duplicate require
const ReadFileCompileAsyncWasmPlugin = require("../node/ReadFileCompileAsyncWasmPlugin");
new ReadFileCompileWasmPlugin({
mangleImports: compiler.options.optimization.mangleWasmImports
}).apply(compiler);
new ReadFileCompileAsyncWasmPlugin().apply(compiler);
new ReadFileCompileAsyncWasmPlugin({ type }).apply(compiler);
break;
}
case "async-node-module": {
// @ts-expect-error typescript bug for duplicate require
const ReadFileCompileAsyncWasmPlugin = require("../node/ReadFileCompileAsyncWasmPlugin");
new ReadFileCompileAsyncWasmPlugin({ type, import: true }).apply(
compiler
);
break;
}
case "universal":

View File

@ -3,7 +3,7 @@
const path = require("path");
const fs = require("graceful-fs");
const vm = require("vm");
const { URL } = require("url");
const { URL, pathToFileURL } = require("url");
const rimraf = require("rimraf");
const webpack = require("..");
const TerserPlugin = require("terser-webpack-plugin");
@ -304,7 +304,7 @@ const describeCases = config => {
currentDirectory,
options,
module,
esmModule
esmMode
) => {
if (Array.isArray(module) || /^\.\.?\//.test(module)) {
let content;
@ -420,6 +420,9 @@ const describeCases = config => {
context: vm.createContext(moduleScope, {
name: `context for ${p}`
}),
initializeImportMeta: (meta, module) => {
meta.url = pathToFileURL(p).href;
},
importModuleDynamically: async (
specifier,
module
@ -438,7 +441,7 @@ const describeCases = config => {
return result;
}
if (!vm.SyntheticModule) return result;
return new vm.SyntheticModule(
const m = new vm.SyntheticModule(
[
...new Set([
"default",
@ -452,9 +455,13 @@ const describeCases = config => {
this.setExport("default", result);
}
);
await m.link(() => {});
if (m.instantiate) m.instantiate();
await m.evaluate();
return m;
}
});
if (esmModule === "unlinked") return esm;
if (esmMode === "unlinked") return esm;
return (async () => {
await esm.link(
async (specifier, referencingModule) => {
@ -469,7 +476,7 @@ const describeCases = config => {
// node.js 10 needs instantiate
if (esm.instantiate) esm.instantiate();
await esm.evaluate();
if (esmModule === "evaluated") return esm;
if (esmMode === "evaluated") return esm;
const ns = esm.namespace;
return ns.default && ns.default instanceof Promise
? ns.default

View File

@ -3,7 +3,7 @@
const path = require("path");
const fs = require("graceful-fs");
const vm = require("vm");
const { pathToFileURL } = require("url");
const { pathToFileURL, URL } = require("url");
const rimraf = require("rimraf");
const webpack = require("..");
const TerserPlugin = require("terser-webpack-plugin");
@ -97,7 +97,7 @@ const describeCases = config => {
const options = {
context: casesPath,
entry: "./" + category.name + "/" + testName + "/",
target: "async-node",
target: config.target || "async-node",
devtool: config.devtool,
mode: config.mode || "none",
optimization: config.mode
@ -308,46 +308,96 @@ const describeCases = config => {
it(
testName + " should load the compiled tests",
done => {
function _require(module) {
const esmContext = vm.createContext({
it: _it,
expect,
process,
global,
URL,
Buffer,
setTimeout,
setImmediate,
nsObj: function (m) {
Object.defineProperty(m, Symbol.toStringTag, {
value: "Module"
});
return m;
}
});
function _require(module, esmMode) {
if (module.substr(0, 2) === "./") {
const p = path.join(outputDirectory, module);
const content = fs.readFileSync(p, "utf-8");
if (p.endsWith(".mjs")) {
const module = new vm.SourceTextModule(
`import { it, expect } from "TEST_ENV";
function nsObj(m) { Object.defineProperty(m, Symbol.toStringTag, { value: "Module" }); return m; }
${fs.readFileSync(p, "utf-8")}`,
{
let esm;
try {
esm = new vm.SourceTextModule(content, {
identifier: p,
lineOffset: 1,
context: esmContext,
initializeImportMeta: (meta, module) => {
meta.url = pathToFileURL(p);
meta.url = pathToFileURL(p).href;
},
importModuleDynamically: (specifier, module) => {
return _require(specifier);
}
}
);
return module
.link((specifier, module) => {
if (specifier === "TEST_ENV") {
importModuleDynamically: async (
specifier,
module
) => {
const result = await _require(
specifier,
"evaluated"
);
if (
result instanceof
(vm.Module ||
/* node.js 10 */ vm.SourceTextModule)
) {
return result;
}
if (!vm.SyntheticModule) return result;
const m = new vm.SyntheticModule(
["it", "expect"],
[
...new Set([
"default",
...Object.keys(result)
])
],
function () {
this.setExport("it", _it);
this.setExport("expect", expect);
for (const key in result) {
this.setExport(key, result[key]);
}
this.setExport("default", result);
}
);
await m.link(() => {});
if (m.instantiate) m.instantiate();
await m.evaluate();
return m;
}
})
.then(() => module.evaluate())
.then(() => module.namespace);
});
} catch (e) {
console.log(e);
e.message += `\nwhile parsing ${p}`;
throw e;
}
if (esmMode === "unlinked") return esm;
return (async () => {
await esm.link((specifier, module) => {
return _require(specifier, "unlinked");
});
// node.js 10 needs instantiate
if (esm.instantiate) esm.instantiate();
await esm.evaluate();
if (esmMode === "evaluated") return esm;
const ns = esm.namespace;
return ns.default && ns.default instanceof Promise
? ns.default
: ns;
})();
} else {
const fn = vm.runInThisContext(
"(function(require, module, exports, __dirname, __filename, it, expect) {" +
"global.expect = expect;" +
'function nsObj(m) { Object.defineProperty(m, Symbol.toStringTag, { value: "Module" }); return m; }' +
fs.readFileSync(p, "utf-8") +
content +
"\n})",
p
);
@ -370,14 +420,15 @@ ${fs.readFileSync(p, "utf-8")}`,
} else return require(module);
}
_require.webpackTestSuiteRequire = true;
const promise = _require("./" + options.output.filename);
if (promise && promise.then) promise.then(finish);
else finish();
function finish() {
if (getNumberOfTests() === 0)
return done(new Error("No tests exported by test case"));
done();
}
Promise.resolve()
.then(() => _require("./" + options.output.filename))
.then(() => {
if (getNumberOfTests() === 0)
return done(
new Error("No tests exported by test case")
);
done();
}, done);
},
10000
);

View File

@ -3,11 +3,13 @@ const vm = require("vm");
describe("TestCases", () => {
if (!vm.SourceTextModule) {
it("module can't run without --experimental-vm-modules");
return;
throw new Error(
"Running this test requires '--experimental-vm-modules'.\nRun with 'node --experimental-vm-modules node_modules/jest-cli/bin/jest'."
);
}
describeCases({
name: "module",
target: "node14",
module: true
});
});

View File

@ -0,0 +1,31 @@
it("should find var declaration in control statements", function () {
var f = function (x) {
expect(x).toBe("fail");
};
(function () {
with ({ a: 1 }) {
var require = f;
}
require("fail");
})();
});
it("should find var declaration in control statements after usage", function () {
var f = function (x) {
expect(x).toBe("fail");
};
(function () {
var test = function () {
require("fail");
};
with ({ a: 1 }) {
var require = f;
}
test();
})();
});

View File

@ -0,0 +1,3 @@
module.exports = function (config) {
return !config.module;
};

View File

@ -1,149 +1,142 @@
it("should find var declaration later in code", function() {
expect((typeof require)).toBe("undefined");
it("should find var declaration later in code", function () {
expect(typeof require).toBe("undefined");
var require;
});
it("should find var declaration in same statement", function() {
var fn = (function() {
require("fail");
}), require;
it("should find var declaration in same statement", function () {
var fn = function () {
require("fail");
},
require;
require = (function(x) {
require = function (x) {
expect(x).toBe("fail");
});
};
fn();
});
it("should find a catch block declaration", function() {
it("should find a catch block declaration", function () {
try {
var f = (function(x) {
var f = function (x) {
expect(x).toBe("fail");
});
};
throw f;
} catch(require) {
} catch (require) {
require("fail");
}
});
it("should find var declaration in control statements", function() {
var f = (function(x) {
it("should find var declaration in control statements", function () {
var f = function (x) {
expect(x).toBe("fail");
});
};
(function() {
(function () {
{
var require = f;
}
require("fail");
}());
})();
(function() {
(function () {
var i = 1;
while(i--) {
while (i--) {
var require = f;
}
require("fail");
}());
})();
(function() {
(function () {
do {
var require = f;
} while(false);
} while (false);
require("fail");
}());
})();
(function() {
for(var i = 0; i < 1; i++) {
(function () {
for (var i = 0; i < 1; i++) {
var require = f;
}
require("fail");
}());
})();
(function() {
for(var i in {a:1}) {
(function () {
for (var i in { a: 1 }) {
var require = f;
}
require("fail");
}());
(function() {
with({ a: 1 }) {
var require = f;
}
require("fail");
}());
})();
});
it("should find var declaration in control statements after usage", function() {
var f = (function(x) {
it("should find var declaration in control statements after usage", function () {
var f = function (x) {
expect(x).toBe("fail");
});
};
(function() {
var test = (function() { require("fail"); });
(function () {
var test = function () {
require("fail");
};
{
var require = f;
}
test();
}());
})();
(function() {
var test = (function() { require("fail"); });
(function () {
var test = function () {
require("fail");
};
var i = 1;
while(i--) {
while (i--) {
var require = f;
}
test();
}());
})();
(function() {
var test = (function() { require("fail"); });
(function () {
var test = function () {
require("fail");
};
do {
var require = f;
} while(false);
} while (false);
test();
}());
})();
(function() {
var test = (function() { require("fail"); });
(function () {
var test = function () {
require("fail");
};
for(var i = 0; i < 1; i++) {
for (var i = 0; i < 1; i++) {
var require = f;
}
test();
}());
})();
(function() {
var test = (function() { require("fail"); });
(function () {
var test = function () {
require("fail");
};
for(var i in {a:1}) {
for (var i in { a: 1 }) {
var require = f;
}
test();
}());
(function() {
var test = (function() { require("fail"); });
with({ a: 1 }) {
var require = f;
}
test();
}());
})();
});

View File

@ -0,0 +1,9 @@
it("should answer typeof __non_webpack_require__ correctly", function () {
var oldValue;
eval("oldValue = require;");
expect(typeof __non_webpack_require__).toBe("function");
eval("require = undefined;");
expect(typeof __non_webpack_require__).toBe("undefined");
eval("require = oldValue;");
expect(typeof __non_webpack_require__).toBe("function");
});

View File

@ -0,0 +1,3 @@
module.exports = function (config) {
return !config.module;
};

View File

@ -1,56 +1,48 @@
it("should not create a context for typeof require", function() {
it("should not create a context for typeof require", function () {
expect(require("./typeof")).toBe("function");
});
it("should answer typeof require correctly", function() {
expect((typeof require)).toBe("function");
it("should answer typeof require correctly", function () {
expect(typeof require).toBe("function");
});
it("should answer typeof define correctly", function() {
expect((typeof define)).toBe("function");
it("should answer typeof define correctly", function () {
expect(typeof define).toBe("function");
});
it("should answer typeof require.amd correctly", function() {
expect((typeof require.amd)).toBe("object");
it("should answer typeof require.amd correctly", function () {
expect(typeof require.amd).toBe("object");
});
it("should answer typeof define.amd correctly", function() {
expect((typeof define.amd)).toBe("object");
it("should answer typeof define.amd correctly", function () {
expect(typeof define.amd).toBe("object");
});
it("should answer typeof module correctly", function() {
expect((typeof module)).toBe("object");
it("should answer typeof module correctly", function () {
expect(typeof module).toBe("object");
});
it("should answer typeof exports correctly", function() {
expect((typeof exports)).toBe("object");
it("should answer typeof exports correctly", function () {
expect(typeof exports).toBe("object");
});
it("should answer typeof require.include correctly", function() {
expect((typeof require.include)).toBe("function");
it("should answer typeof require.include correctly", function () {
expect(typeof require.include).toBe("function");
});
it("should answer typeof require.ensure correctly", function() {
expect((typeof require.ensure)).toBe("function");
it("should answer typeof require.ensure correctly", function () {
expect(typeof require.ensure).toBe("function");
});
it("should answer typeof require.resolve correctly", function() {
expect((typeof require.resolve)).toBe("function");
});
it("should answer typeof __non_webpack_require__ correctly", function() {
var oldValue;
eval("oldValue = require;");
expect((typeof __non_webpack_require__)).toBe("function");
eval("require = undefined;");
expect((typeof __non_webpack_require__)).toBe("undefined");
eval("require = oldValue;");
expect((typeof __non_webpack_require__)).toBe("function");
it("should answer typeof require.resolve correctly", function () {
expect(typeof require.resolve).toBe("function");
});
it("should not parse filtered stuff", function() {
if(typeof require != "function") require("fail");
if(typeof require !== "function") require("fail");
if(!(typeof require == "function")) require("fail");
if(!(typeof require === "function")) require("fail");
if(typeof require == "undefined") require = require("fail");
if(typeof require === "undefined") require = require("fail");
if(typeof require.resolve !== "function") require("fail");
if(typeof module == "undefined") module = require("fail");
if(typeof module === "undefined") module = require("fail");
if(typeof module != "object") module = require("fail");
if(typeof exports == "undefined") exports = require("fail");
if(typeof require.include !== "function") require.include("fail");
if(typeof require.ensure !== "function") require.ensure(["fail"], function(){});
it("should not parse filtered stuff", function () {
if (typeof require != "function") require("fail");
if (typeof require !== "function") require("fail");
if (!(typeof require == "function")) require("fail");
if (!(typeof require === "function")) require("fail");
if (typeof require == "undefined") require = require("fail");
if (typeof require === "undefined") require = require("fail");
if (typeof require.resolve !== "function") require("fail");
if (typeof module == "undefined") module = require("fail");
if (typeof module === "undefined") module = require("fail");
if (typeof module != "object") module = require("fail");
if (typeof exports == "undefined") exports = require("fail");
if (typeof require.include !== "function") require.include("fail");
if (typeof require.ensure !== "function")
require.ensure(["fail"], function () {});
});