improve target options

infer target properties from different targets and fill defaults from that

custom targets can now be created via `target: false` and a plugin (similar to the other options)

add stubs from universal chunk/wasm loading and module chunk format

add externalsPresets.electron and externalsPresets.electronRenderer

node.__file/dirname: "eval-only"
This commit is contained in:
Tobias Koppers 2020-09-10 10:42:29 +02:00
parent 48010fb955
commit 7e85649492
23 changed files with 796 additions and 541 deletions

View File

@ -180,6 +180,7 @@
"etags",
"destructure",
"onconnect",
"nwjs",
"webassemblyjs",
"fsevents",

View File

@ -544,20 +544,9 @@ export type StatsValue =
| boolean
| StatsOptions;
/**
* Environment to build for.
* Environment to build for. An array of environments to build for all of them when possible.
*/
export type Target =
| (
| "web"
| "webworker"
| "node"
| "async-node"
| "node-webkit"
| "electron-main"
| "electron-renderer"
| "electron-preload"
)
| ((compiler: import("../lib/Compiler")) => void);
export type Target = [string, ...string[]] | false | string;
/**
* Enter watch mode, which rebuilds on file change.
*/
@ -720,7 +709,7 @@ export interface WebpackOptions {
*/
stats?: StatsValue;
/**
* Environment to build for.
* Environment to build for. An array of environments to build for all of them when possible.
*/
target?: Target;
/**
@ -939,6 +928,10 @@ export interface Experiments {
* Enable presets of externals for specific targets.
*/
export interface ExternalsPresets {
/**
* Treat common electron built-in modules in main and preload context like 'electron', 'ipc' or 'shell' as external and load them via require() when used.
*/
electron?: boolean;
/**
* Treat electron built-in modules in the main context like 'app', 'ipc-main' or 'shell' as external and load them via require() when used.
*/
@ -947,14 +940,18 @@ export interface ExternalsPresets {
* Treat electron built-in modules in the preload context like 'web-frame', 'ipc-renderer' or 'shell' as external and load them via require() when used.
*/
electronPreload?: boolean;
/**
* Treat electron built-in modules in the renderer context like 'web-frame', 'ipc-renderer' or 'shell' as external and load them via require() when used.
*/
electronRenderer?: boolean;
/**
* Treat node.js built-in modules like fs, path or vm as external and load them via require() when used.
*/
node?: boolean;
/**
* Treat node-webkit legacy nw.gui module as external and load it via require() when used.
* Treat NW.js legacy nw.gui module as external and load it via require() when used.
*/
nodeWebkit?: boolean;
nwjs?: boolean;
/**
* Treat references to 'http(s)://...' and 'std:...' as external and load them via import when used (Note that this changes execution order as externals are executed before any other code in the chunk).
*/
@ -1308,11 +1305,11 @@ export interface NodeOptions {
/**
* Include a polyfill for the '__dirname' variable.
*/
__dirname?: false | true | "mock";
__dirname?: false | true | "mock" | "eval-only";
/**
* Include a polyfill for the '__filename' variable.
*/
__filename?: false | true | "mock";
__filename?: false | true | "mock" | "eval-only";
/**
* Include a polyfill for the 'global' variable.
*/
@ -1836,21 +1833,13 @@ export interface Environment {
*/
const?: boolean;
/**
* The environment supports destructing ('{ a, b } = obj').
* The environment supports destructuring ('{ a, b } = obj').
*/
destructing?: boolean;
destructuring?: boolean;
/**
* The environment supports 'for of' iteration ('for (const x of array) { ... }').
*/
forOf?: boolean;
/**
* The environment supports a global 'global' variable which points to the global context.
*/
global?: boolean;
/**
* The environment supports a global 'globalThis' variable which points to the global context.
*/
globalThis?: boolean;
/**
* The environment supports an async import() function to import EcmaScript modules.
*/
@ -2607,7 +2596,7 @@ export interface WebpackOptionsNormalized {
*/
stats: StatsValue;
/**
* Environment to build for.
* Environment to build for. An array of environments to build for all of them when possible.
*/
target?: Target;
/**

View File

@ -5,12 +5,15 @@
"use strict";
const RuntimeGlobals = require("./RuntimeGlobals");
const CachedConstDependency = require("./dependencies/CachedConstDependency");
const ConstDependency = require("./dependencies/ConstDependency");
const {
evaluateToString,
expressionIsUnsupported
} = require("./javascript/JavascriptParserHelpers");
const { relative } = require("./util/fs");
const { parseResource } = require("./util/identifier");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("./Compiler")} Compiler */
@ -41,6 +44,20 @@ class NodeStuffPlugin {
localOptions = { ...localOptions, ...parserOptions.node };
}
if (localOptions.global) {
parser.hooks.expression
.for("global")
.tap("NodeStuffPlugin", expr => {
const dep = new ConstDependency(
RuntimeGlobals.global,
expr.range,
[RuntimeGlobals.global]
);
dep.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep);
});
}
const setModuleConstant = (expressionName, fn) => {
parser.hooks.expression
.for(expressionName)
@ -63,7 +80,7 @@ class NodeStuffPlugin {
if (localOptions.__filename) {
if (localOptions.__filename === "mock") {
setConstant("__filename", "/index.js");
} else {
} else if (localOptions.__filename === true) {
setModuleConstant("__filename", module =>
relative(compiler.inputFileSystem, context, module.resource)
);
@ -72,17 +89,14 @@ class NodeStuffPlugin {
.for("__filename")
.tap("NodeStuffPlugin", expr => {
if (!parser.state.module) return;
const resource = parser.state.module.resource;
const i = resource.indexOf("?");
return evaluateToString(
i < 0 ? resource : resource.substr(0, i)
)(expr);
const resource = parseResource(parser.state.module.resource);
return evaluateToString(resource.path)(expr);
});
}
if (localOptions.__dirname) {
if (localOptions.__dirname === "mock") {
setConstant("__dirname", "/");
} else {
} else if (localOptions.__dirname === true) {
setModuleConstant("__dirname", module =>
relative(compiler.inputFileSystem, context, module.context)
);

View File

@ -75,8 +75,8 @@ class RuntimeTemplate {
return this.outputOptions.environment.forOf;
}
supportsDestructing() {
return this.outputOptions.environment.destructing;
supportsDestructuring() {
return this.outputOptions.environment.destructuring;
}
supportsBigIntLiteral() {
@ -104,7 +104,7 @@ class RuntimeTemplate {
}
destructureArray(items, value) {
return this.supportsDestructing()
return this.supportsDestructuring()
? `var [${items.join(", ")}] = ${value};`
: Template.asString(
items.map((item, i) => `var ${item} = ${value}[${i}];`)

View File

@ -70,18 +70,6 @@ class WebpackOptionsApply extends OptionsApply {
compiler.recordsInputPath = options.recordsInputPath || null;
compiler.recordsOutputPath = options.recordsOutputPath || null;
compiler.name = options.name;
if (typeof options.target === "string") {
switch (options.target) {
case "web":
case "webworker": {
const NodeSourcePlugin = require("./node/NodeSourcePlugin");
new NodeSourcePlugin(options.node).apply(compiler);
break;
}
}
} else {
options.target(compiler);
}
if (options.externalsPresets.node) {
const NodeTargetPlugin = require("./node/NodeTargetPlugin");
@ -89,13 +77,26 @@ class WebpackOptionsApply extends OptionsApply {
}
if (options.externalsPresets.electronMain) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin(true).apply(compiler);
new ElectronTargetPlugin("main").apply(compiler);
}
if (options.externalsPresets.electronPreload) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin(false).apply(compiler);
new ElectronTargetPlugin("preload").apply(compiler);
}
if (options.externalsPresets.nodeWebkit) {
if (options.externalsPresets.electronRenderer) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin("renderer").apply(compiler);
}
if (
options.externalsPresets.electron &&
!options.externalsPresets.electronMain &&
!options.externalsPresets.electronPreload &&
!options.externalsPresets.electronRenderer
) {
const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
new ElectronTargetPlugin().apply(compiler);
}
if (options.externalsPresets.nwjs) {
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin("commonjs", "nw.gui").apply(compiler);
}
@ -121,6 +122,10 @@ class WebpackOptionsApply extends OptionsApply {
new CommonJsChunkFormatPlugin().apply(compiler);
break;
}
case "module":
throw new Error(
"EcmaScript Module CHunk Format is not implemented yet"
);
default:
throw new Error(
"Unsupported chunk format '" + options.output.chunkFormat + "'."

View File

@ -8,6 +8,7 @@
const path = require("path");
const Template = require("../Template");
const { cleverMerge } = require("../util/cleverMerge");
const { getTargetsProperties, getTargetProperties } = require("./target");
/** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptions */
/** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
@ -30,6 +31,7 @@ const { cleverMerge } = require("../util/cleverMerge");
/** @typedef {import("../../declarations/WebpackOptions").SnapshotOptions} SnapshotOptions */
/** @typedef {import("../../declarations/WebpackOptions").Target} Target */
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("./target").TargetProperties} TargetProperties */
const NODE_MODULES_REGEXP = /[\\/]node_modules[\\/]/i;
@ -120,11 +122,13 @@ const applyWebpackOptionsDefaults = options => {
const { mode, name, target } = options;
const webTarget =
target === "web" ||
target === "webworker" ||
target === "electron-renderer" ||
target === "electron-preload";
let targetProperties =
target === false
? /** @type {false} */ (false)
: typeof target === "string"
? getTargetProperties(target)
: getTargetsProperties(target);
const development = mode === "development";
const production = mode === "production" || !mode;
@ -161,21 +165,20 @@ const applyWebpackOptionsDefaults = options => {
applyModuleDefaults(options.module, {
cache,
syncWebAssembly: options.experiments.syncWebAssembly,
asyncWebAssembly: options.experiments.asyncWebAssembly,
webTarget
asyncWebAssembly: options.experiments.asyncWebAssembly
});
applyOutputDefaults(options.output, {
context: options.context,
target,
targetProperties,
outputModule: options.experiments.outputModule,
development,
entry: options.entry
});
applyExternalsPresetsDefaults(options.externalsPresets, { target });
applyExternalsPresetsDefaults(options.externalsPresets, { targetProperties });
applyLoaderDefaults(options.loader, { target });
applyLoaderDefaults(options.loader, { targetProperties });
F(options, "externalsType", () => {
const validExternalTypes = require("../../schemas/WebpackOptions.json")
@ -188,9 +191,15 @@ const applyWebpackOptionsDefaults = options => {
: "var";
});
applyNodeDefaults(options.node, { target });
applyNodeDefaults(options.node, { targetProperties });
F(options, "performance", () => (production && webTarget ? {} : false));
F(options, "performance", () =>
production &&
targetProperties &&
(targetProperties.browser || targetProperties.browser === null)
? {}
: false
);
applyPerformanceDefaults(options.performance, {
production
});
@ -205,8 +214,7 @@ const applyWebpackOptionsDefaults = options => {
getResolveDefaults({
cache,
context: options.context,
webTarget,
target,
targetProperties,
mode: options.mode
}),
options.resolve
@ -335,12 +343,11 @@ const applySnapshotDefaults = (snapshot, { production }) => {
* @param {boolean} options.cache is caching enabled
* @param {boolean} options.syncWebAssembly is syncWebAssembly enabled
* @param {boolean} options.asyncWebAssembly is asyncWebAssembly enabled
* @param {boolean} options.webTarget is web target
* @returns {void}
*/
const applyModuleDefaults = (
module,
{ cache, syncWebAssembly, asyncWebAssembly, webTarget }
{ cache, syncWebAssembly, asyncWebAssembly }
) => {
D(module, "unknownContextRequest", ".");
D(module, "unknownContextRegExp", false);
@ -483,7 +490,7 @@ const applyModuleDefaults = (
* @param {Output} output options
* @param {Object} options options
* @param {string} options.context context
* @param {Target} options.target target
* @param {TargetProperties | false} options.targetProperties target properties
* @param {boolean} options.outputModule is outputModule experiment enabled
* @param {boolean} options.development is development mode
* @param {Entry} options.entry entry option
@ -491,7 +498,7 @@ const applyModuleDefaults = (
*/
const applyOutputDefaults = (
output,
{ context, target, outputModule, development, entry }
{ context, targetProperties: tp, outputModule, development, entry }
) => {
/**
* @param {Library=} library the library option
@ -560,82 +567,65 @@ const applyOutputDefaults = (
)
);
F(output, "globalObject", () => {
switch (target) {
case "web":
case "webworker":
case "electron-renderer":
case "node-webkit":
return "self";
case "node":
case "async-node":
case "electron-main":
case "electron-preload":
return "global";
default:
return "self";
if (tp) {
if (tp.global) return "global";
if (tp.globalThis) return "globalThis";
}
return "self";
});
F(output, "chunkFormat", () => {
switch (target) {
case "web":
case "webworker":
case "electron-renderer":
case "node-webkit":
return "array-push";
case "node":
case "async-node":
case "electron-main":
case "electron-preload":
return "commonjs";
default:
return false;
if (tp) {
if (tp.require) return "commonjs";
if (tp.nodeBuiltins) return "commonjs";
if (tp.document) return "array-push";
if (tp.importScripts) return "array-push";
if (tp.import && output.module) return "module";
}
return false;
});
F(output, "chunkLoading", () => {
switch (target) {
case "web":
case "electron-renderer":
case "node-webkit":
return "jsonp";
case "webworker":
return "import-scripts";
case "node":
case "electron-main":
case "electron-preload":
return "require";
case "async-node":
return "async-node";
default:
return false;
if (tp) {
if (tp.require) return "require";
if (tp.nodeBuiltins) return "async-node";
if (tp.document) return "jsonp";
if (tp.importScripts) return "import-scripts";
if (tp.import && output.module) return "import";
if (
tp.require === null ||
tp.nodeBuiltins === null ||
tp.document === null ||
tp.importScripts === null
) {
return "universal";
}
}
return false;
});
F(output, "workerChunkLoading", () => {
switch (output.chunkLoading) {
case "jsonp":
return "import-scripts";
case "require":
return "require";
case "async-node":
return "async-node";
default:
return false;
if (tp) {
if (tp.require) return "require";
if (tp.nodeBuiltins) return "async-node";
if (tp.importScriptsInWorker) return "import-scripts";
if (tp.importInWorker && output.module) return "import";
if (
tp.require === null ||
tp.nodeBuiltins === null ||
tp.importScriptsInWorker === null
) {
return "universal";
}
}
return false;
});
F(output, "wasmLoading", () => {
switch (target) {
case "web":
case "webworker":
case "electron-renderer":
case "node-webkit":
return "fetch";
case "node":
case "async-node":
case "electron-main":
case "electron-preload":
return "async-node";
default:
return false;
if (tp) {
if (tp.nodeBuiltins) return "async-node";
if (tp.fetchWasm) return "fetch";
if (tp.nodeBuiltins === null || tp.fetchWasm === null) {
return "universal";
}
}
return false;
});
F(output, "workerWasmLoading", () => output.wasmLoading);
F(output, "devtoolNamespace", () => output.uniqueName);
@ -655,28 +645,22 @@ const applyOutputDefaults = (
D(output, "hashDigestLength", 20);
D(output, "strictModuleExceptionHandling", false);
F(output.environment, "global", () => {
switch (target) {
case "web":
case "webworker":
case "electron-renderer":
return false;
case "node-webkit":
case "node":
case "async-node":
case "electron-main":
case "electron-preload":
return true;
default:
return undefined;
}
});
D(output.environment, "arrowFunction", true);
D(output.environment, "const", true);
D(output.environment, "destructing", true);
D(output.environment, "forOf", true);
D(output.environment, "import", true);
D(output.environment, "module", true);
const optimistic = v => v || v === undefined;
F(
output.environment,
"arrowFunction",
() => tp && optimistic(tp.arrowFunction)
);
F(output.environment, "const", () => tp && optimistic(tp.const));
F(
output.environment,
"destructuring",
() => tp && optimistic(tp.destructuring)
);
F(output.environment, "forOf", () => tp && optimistic(tp.forOf));
F(output.environment, "bigIntLiteral", () => tp && tp.bigIntLiteral);
F(output.environment, "import", () => tp && tp.import);
F(output.environment, "module", () => tp && tp.module);
A(output, "enabledLibraryTypes", () => {
const enabledLibraryTypes = [];
@ -730,64 +714,62 @@ const applyOutputDefaults = (
/**
* @param {ExternalsPresets} externalsPresets options
* @param {Object} options options
* @param {Target} options.target target
* @param {TargetProperties | false} options.targetProperties target properties
* @returns {void}
*/
const applyExternalsPresetsDefaults = (externalsPresets, { target }) => {
switch (target) {
case "web":
D(externalsPresets, "web", true);
break;
case "webworker":
D(externalsPresets, "web", true);
break;
case "async-node":
D(externalsPresets, "node", true);
break;
case "node":
D(externalsPresets, "node", true);
break;
case "node-webkit":
D(externalsPresets, "web", true);
D(externalsPresets, "node", true);
D(externalsPresets, "nodeWebkit", true);
break;
case "electron-main":
D(externalsPresets, "node", true);
D(externalsPresets, "electronMain", true);
break;
case "electron-preload":
case "electron-renderer":
D(externalsPresets, "web", true);
D(externalsPresets, "node", true);
D(externalsPresets, "electronPreload", true);
break;
}
const applyExternalsPresetsDefaults = (
externalsPresets,
{ targetProperties }
) => {
D(externalsPresets, "web", targetProperties && targetProperties.web);
D(externalsPresets, "node", targetProperties && targetProperties.node);
D(externalsPresets, "nwjs", targetProperties && targetProperties.nwjs);
D(
externalsPresets,
"electron",
targetProperties && targetProperties.electron
);
D(
externalsPresets,
"electronMain",
targetProperties &&
targetProperties.electron &&
targetProperties.electronMain
);
D(
externalsPresets,
"electronPreload",
targetProperties &&
targetProperties.electron &&
targetProperties.electronPreload
);
D(
externalsPresets,
"electronRenderer",
targetProperties &&
targetProperties.electron &&
targetProperties.electronRenderer
);
};
/**
* @param {Loader} loader options
* @param {Object} options options
* @param {Target} options.target target
* @param {TargetProperties | false} options.targetProperties target properties
* @returns {void}
*/
const applyLoaderDefaults = (loader, { target }) => {
const applyLoaderDefaults = (loader, { targetProperties }) => {
F(loader, "target", () => {
switch (target) {
case "web":
return "web";
case "webworker":
return "webworker";
case "async-node":
case "node":
return "node";
case "node-webkit":
return "node-webkit";
case "electron-main":
return "electron-main";
case "electron-preload":
case "electron-renderer":
return "electron-preload";
if (targetProperties) {
if (targetProperties.electron) {
if (targetProperties.electronMain) return "electron-main";
if (targetProperties.electronPreload) return "electron-preload";
if (targetProperties.electronRenderer) return "electron-renderer";
return "electron";
}
if (targetProperties.nwjs) return "nwjs";
if (targetProperties.node) return "node";
if (targetProperties.web) return "web";
}
});
};
@ -795,40 +777,22 @@ const applyLoaderDefaults = (loader, { target }) => {
/**
* @param {WebpackNode} node options
* @param {Object} options options
* @param {Target} options.target target
* @param {TargetProperties | false} options.targetProperties target properties
* @returns {void}
*/
const applyNodeDefaults = (node, { target }) => {
const applyNodeDefaults = (node, { targetProperties }) => {
if (node === false) return;
F(node, "global", () => {
switch (target) {
case "node":
case "async-node":
case "electron-main":
return false;
default:
return true;
}
if (targetProperties && targetProperties.global) return false;
return true;
});
F(node, "__filename", () => {
switch (target) {
case "node":
case "async-node":
case "electron-main":
return false;
default:
return "mock";
}
if (targetProperties && targetProperties.node) return "eval-only";
return "mock";
});
F(node, "__dirname", () => {
switch (target) {
case "node":
case "async-node":
case "electron-main":
return false;
default:
return "mock";
}
if (targetProperties && targetProperties.node) return "eval-only";
return "mock";
});
};
@ -936,54 +900,42 @@ const applyOptimizationDefaults = (
* @param {Object} options options
* @param {boolean} options.cache is cache enable
* @param {string} options.context build context
* @param {boolean} options.webTarget is a web-like target
* @param {Target} options.target target
* @param {TargetProperties | false} options.targetProperties target properties
* @param {Mode} options.mode mode
* @returns {ResolveOptions} resolve options
*/
const getResolveDefaults = ({ cache, context, webTarget, target, mode }) => {
const getResolveDefaults = ({ cache, context, targetProperties, mode }) => {
/** @type {string[]} */
const conditions = ["webpack"];
conditions.push(mode === "development" ? "development" : "production");
switch (target) {
case "webworker":
conditions.push("worker");
break;
case "node":
case "async-node":
case "node-webkit":
conditions.push("node");
break;
case "electron-main":
conditions.push("node");
conditions.push("electron");
break;
case "electron-preload":
case "electron-renderer":
conditions.push("electron");
break;
if (targetProperties) {
if (targetProperties.webworker) conditions.push("worker");
if (targetProperties.node) conditions.push("node");
if (targetProperties.web) conditions.push("browser");
if (targetProperties.electron) conditions.push("electron");
if (targetProperties.nwjs) conditions.push("nwjs");
}
const jsExtensions = [".js", ".json", ".wasm"];
const tp = targetProperties;
const browserField =
tp && tp.web && (!tp.node || (tp.electron && tp.electronRenderer));
/** @type {function(): ResolveOptions} */
const cjsDeps = () => ({
aliasFields: webTarget ? ["browser"] : [],
mainFields: webTarget ? ["browser", "module", "..."] : ["module", "..."],
conditionNames: webTarget
? ["require", "module", "browser", "..."]
: ["require", "module", "..."],
aliasFields: browserField ? ["browser"] : [],
mainFields: browserField ? ["browser", "module", "..."] : ["module", "..."],
conditionNames: ["require", "module", "..."],
extensions: [...jsExtensions]
});
/** @type {function(): ResolveOptions} */
const esmDeps = () => ({
aliasFields: webTarget ? ["browser"] : [],
mainFields: webTarget ? ["browser", "module", "..."] : ["module", "..."],
conditionNames: webTarget
? ["import", "module", "browser", "..."]
: ["import", "module", "..."],
aliasFields: browserField ? ["browser"] : [],
mainFields: browserField ? ["browser", "module", "..."] : ["module", "..."],
conditionNames: ["import", "module", "..."],
extensions: [...jsExtensions]
});

299
lib/config/target.js Normal file
View File

@ -0,0 +1,299 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/**
* @typedef {Object} PlatformTargetProperties
* @property {boolean | null} web web platform, importing of http(s) and std: is available
* @property {boolean | null} browser browser platform, running in a normal web browser
* @property {boolean | null} webworker (Web)Worker platform, running in a web/shared/service worker
* @property {boolean | null} node node platform, require of node built-in modules is available
* @property {boolean | null} nwjs nwjs platform, require of legacy nw.gui is available
* @property {boolean | null} electron electron platform, require of some electron built-in modules is available
*/
/**
* @typedef {Object} ElectronContextTargetProperties
* @property {boolean | null} electronMain in main context
* @property {boolean | null} electronPreload in preload context
* @property {boolean | null} electronRenderer in renderer context with node integration
*/
/**
* @typedef {Object} ApiTargetProperties
* @property {boolean | null} require has require function available
* @property {boolean | null} nodeBuiltins has node.js built-in modules available
* @property {boolean | null} document has document available (allows script tags)
* @property {boolean | null} importScripts has importScripts available
* @property {boolean | null} importScriptsInWorker has importScripts available when creating a worker
* @property {boolean | null} fetchWasm has fetch function available for WebAssembly
* @property {boolean | null} global has global variable available
*/
/**
* @typedef {Object} EcmaTargetProperties
* @property {boolean | null} globalThis has globalThis variable available
* @property {boolean | null} bigIntLiteral big int literal syntax is available
* @property {boolean | null} const const and let variable declarations are available
* @property {boolean | null} arrowFunction arrow functions are available
* @property {boolean | null} forOf for of iteration is available
* @property {boolean | null} destructuring destructuring is available
* @property {boolean | null} import async import() is available
* @property {boolean | null} importInWorker async import() is available when creating a worker
* @property {boolean | null} module ESM syntax is available (when in module)
*/
///** @typedef {PlatformTargetProperties | ApiTargetProperties | EcmaTargetProperties | PlatformTargetProperties & ApiTargetProperties | PlatformTargetProperties & EcmaTargetProperties | ApiTargetProperties & EcmaTargetProperties} TargetProperties */
/** @template T @typedef {{ [P in keyof T]?: never }} Never<T> */
/** @template A @template B @typedef {(A & Never<B>) | (Never<A> & B) | (A & B)} Mix<A,B> */
/** @typedef {Mix<Mix<PlatformTargetProperties, ElectronContextTargetProperties>, Mix<ApiTargetProperties, EcmaTargetProperties>>} TargetProperties */
const versionDependent = (major, minor) => {
if (!major) return () => /** @type {undefined} */ (undefined);
major = +major;
minor = minor ? +minor : 0;
return (vMajor, vMinor = 0) => {
return major > vMajor || (major === vMajor && minor >= vMinor);
};
};
/** @type {[string, string, RegExp, (...args: string[]) => TargetProperties][]} */
const TARGETS = [
[
"web",
"Web browser.",
/^web$/,
() => {
return {
web: true,
browser: true,
webworker: null,
node: false,
electron: false,
nwjs: false,
document: true,
importScriptsInWorker: true,
fetchWasm: true,
nodeBuiltins: false,
importScripts: false,
require: false,
global: false
};
}
],
[
"webworker",
"Web Worker, SharedWorker or Service Worker.",
/^webworker$/,
() => {
return {
web: true,
browser: true,
webworker: true,
node: false,
electron: false,
nwjs: false,
importScripts: true,
importScriptsInWorker: true,
fetchWasm: true,
nodeBuiltins: false,
require: false,
document: false,
global: false
};
}
],
[
"[async-]node[X[.Y]]",
"Node.js in version X.Y. The 'async-' prefix will load chunks asynchronously via 'fs' and 'vm' instead of 'require()'. Examples: node14.5, async-node10.",
/^(async-)?node(\d+(?:\.(\d+))?)?$/,
(asyncFlag, major, minor) => {
const v = versionDependent(major, minor);
// see https://node.green/
return {
node: true,
electron: false,
nwjs: false,
web: false,
webworker: false,
browser: false,
require: !asyncFlag,
nodeBuiltins: true,
global: true,
document: false,
fetchWasm: false,
importScripts: false,
importScriptsInWorker: false,
globalThis: v(12),
const: v(6),
arrowFunction: v(6),
forOf: v(5),
destructuring: v(6),
bigIntLiteral: v(10, 4),
import: v(12, 17),
importInWorker: major ? false : undefined,
module: v(12, 17)
};
}
],
[
"electron[X[.Y]]-main/preload/renderer",
"Electron in version X.Y. Script is running in main, preload resp. renderer context.",
/^electron(\d+(?:\.(\d+))?)?-(main|preload|renderer)$/,
(major, minor, context) => {
const v = versionDependent(major, minor);
// see https://node.green/ + https://github.com/electron/releases
return {
node: true,
electron: true,
web: context !== "main",
webworker: false,
browser: false,
nwjs: false,
electronMain: context === "main",
electronPreload: context === "preload",
electronRenderer: context === "renderer",
global: true,
nodeBuiltins: true,
require: true,
document: context === "renderer",
fetchWasm: context === "renderer",
importScripts: false,
importScriptsInWorker: false,
globalThis: v(5),
const: v(1, 1),
arrowFunction: v(1, 1),
forOf: v(0, 36),
destructuring: v(1, 1),
bigIntLiteral: v(4),
import: v(11),
importInWorker: major ? false : undefined,
module: v(11)
};
}
],
[
"nwjs[X[.Y]] / node-webkit[X[.Y]]",
"NW.js in version X.Y.",
/^(?:nwjs|node-webkit)(\d+(?:\.(\d+))?)?$/,
(major, minor) => {
const v = versionDependent(major, minor);
// see https://node.green/ + https://github.com/nwjs/nw.js/blob/nw48/CHANGELOG.md
return {
node: true,
web: true,
nwjs: true,
webworker: null,
browser: false,
electron: false,
global: true,
nodeBuiltins: true,
document: false,
importScriptsInWorker: false,
fetchWasm: false,
importScripts: false,
require: false,
globalThis: v(0, 43),
const: v(0, 15),
arrowFunction: v(0, 15),
forOf: v(0, 13),
destructuring: v(0, 15),
bigIntLiteral: v(0, 32),
import: v(0, 43),
importInWorker: major ? false : undefined,
module: v(0, 43)
};
}
],
[
"esX",
"EcmaScript in this version. Examples: es2020, es5.",
/^es(\d+)$/,
version => {
let v = +version;
if (v < 1000) v = v + 2009;
return {
const: v >= 2015,
arrowFunction: v >= 2015,
forOf: v >= 2015,
destructuring: v >= 2015,
module: v >= 2015,
globalThis: v >= 2020,
bigIntLiteral: v >= 2020,
import: v >= 2020,
importInWorker: v >= 2020
};
}
]
];
/**
* @param {string} target the target
* @returns {TargetProperties} target properties
*/
const getTargetProperties = target => {
for (const [, , regExp, handler] of TARGETS) {
const match = regExp.exec(target);
if (match) {
const [, ...args] = match;
const result = handler(...args);
if (result) return result;
}
}
throw new Error(
`Unknown target '${target}'. The following targets are supported:\n${TARGETS.map(
([name, description]) => `* ${name}: ${description}`
).join("\n")}`
);
};
const mergeTargetProperties = targetProperties => {
const keys = new Set();
for (const tp of targetProperties) {
for (const key of Object.keys(tp)) {
keys.add(key);
}
}
const result = {};
for (const key of keys) {
let hasTrue = false;
let hasFalse = false;
for (const tp of targetProperties) {
const value = tp[key];
switch (value) {
case true:
hasTrue = true;
break;
case false:
hasFalse = true;
break;
}
}
if (hasTrue || hasFalse)
result[key] = hasFalse && hasTrue ? null : hasTrue ? true : false;
}
return /** @type {TargetProperties} */ (result);
};
/**
* @param {string[]} targets the targets
* @returns {TargetProperties} target properties
*/
const getTargetsProperties = targets => {
return mergeTargetProperties(targets.map(getTargetProperties));
};
exports.getTargetProperties = getTargetProperties;
exports.getTargetsProperties = getTargetsProperties;

View File

@ -11,10 +11,10 @@ const ExternalsPlugin = require("../ExternalsPlugin");
class ElectronTargetPlugin {
/**
* @param {boolean} main in main scope?
* @param {"main" | "preload" | "renderer"=} context in main, preload or renderer context?
*/
constructor(main) {
this._main = main;
constructor(context) {
this._context = context;
}
/**
* Apply the plugin
@ -22,49 +22,46 @@ class ElectronTargetPlugin {
* @returns {void}
*/
apply(compiler) {
new ExternalsPlugin(
"commonjs",
this._main
? [
"app",
"auto-updater",
"browser-window",
"clipboard",
"content-tracing",
"crash-reporter",
"dialog",
"electron",
"global-shortcut",
"ipc",
"ipc-main",
"menu",
"menu-item",
"native-image",
"original-fs",
"power-monitor",
"power-save-blocker",
"protocol",
"screen",
"session",
"shell",
"tray",
"web-contents"
]
: [
"clipboard",
"crash-reporter",
"desktop-capturer",
"electron",
"ipc",
"ipc-renderer",
"native-image",
"original-fs",
"remote",
"screen",
"shell",
"web-frame"
]
).apply(compiler);
new ExternalsPlugin("commonjs", [
"clipboard",
"crash-reporter",
"electron",
"ipc",
"native-image",
"original-fs",
"screen",
"shell"
]);
switch (this._context) {
case "main":
new ExternalsPlugin("commonjs", [
"app",
"auto-updater",
"browser-window",
"content-tracing",
"dialog",
"global-shortcut",
"ipc-main",
"menu",
"menu-item",
"power-monitor",
"power-save-blocker",
"protocol",
"session",
"tray",
"web-contents"
]).apply(compiler);
break;
case "preload":
case "renderer":
new ExternalsPlugin("commonjs", [
"desktop-capturer",
"ipc-renderer",
"remote",
"web-frame"
]).apply(compiler);
break;
}
}
}

View File

@ -96,7 +96,10 @@ class EnableChunkLoadingPlugin {
}
case "import":
// TODO implement import chunk loading
break;
throw new Error("Chunk Loading via import() is not implemented yet");
case "universal":
// TODO implement universal chunk loading
throw new Error("Universal Chunk Loading is not implemented yet");
default:
throw new Error(`Unsupported chunk loading type ${type}.
Plugins which provide custom chunk loading types must call EnableChunkLoadingPlugin.setEnabled(compiler, type) to disable this error.`);

View File

@ -5,68 +5,15 @@
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const ConstDependency = require("../dependencies/ConstDependency");
/** @typedef {import("../../declarations/WebpackOptions").NodeOptions} NodeOptions */
/** @typedef {import("../Compiler")} Compiler */
module.exports = class NodeSourcePlugin {
/**
* @param {NodeOptions | false} options plugin options
*/
constructor(options) {
this._options = options;
}
class NodeSourcePlugin {
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const options = this._options;
if (options === false) {
// allow single kill switch to turn off this plugin
return;
}
apply(compiler) {}
}
compiler.hooks.compilation.tap(
"NodeSourcePlugin",
(compilation, { normalModuleFactory }) => {
const handler = (parser, parserOptions) => {
if (parserOptions.node === false) return;
let localOptions = options;
if (parserOptions.node) {
localOptions = { ...localOptions, ...parserOptions.node };
}
if (localOptions.global) {
parser.hooks.expression
.for("global")
.tap("NodeSourcePlugin", expr => {
const dep = new ConstDependency(
RuntimeGlobals.global,
expr.range,
[RuntimeGlobals.global]
);
dep.loc = expr.loc;
parser.state.module.addPresentationalDependency(dep);
});
}
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("NodeSourcePlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("NodeSourcePlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/esm")
.tap("NodeSourcePlugin", handler);
}
);
}
};
module.exports = NodeSourcePlugin;

View File

@ -90,6 +90,10 @@ class EnableWasmLoadingPlugin {
new ReadFileCompileAsyncWasmPlugin().apply(compiler);
break;
}
case "universal":
throw new Error(
"Universal WebAssembly Loading is not implemented yet"
);
default:
throw new Error(`Unsupported wasm loading type ${type}.
Plugins which provide custom wasm loading types must call EnableWasmLoadingPlugin.setEnabled(compiler, type) to disable this error.`);

View File

@ -417,22 +417,14 @@
"description": "The environment supports const and let for variable declarations.",
"type": "boolean"
},
"destructing": {
"description": "The environment supports destructing ('{ a, b } = obj').",
"destructuring": {
"description": "The environment supports destructuring ('{ a, b } = obj').",
"type": "boolean"
},
"forOf": {
"description": "The environment supports 'for of' iteration ('for (const x of array) { ... }').",
"type": "boolean"
},
"global": {
"description": "The environment supports a global 'global' variable which points to the global context.",
"type": "boolean"
},
"globalThis": {
"description": "The environment supports a global 'globalThis' variable which points to the global context.",
"type": "boolean"
},
"import": {
"description": "The environment supports an async import() function to import EcmaScript modules.",
"type": "boolean"
@ -536,6 +528,10 @@
"type": "object",
"additionalProperties": false,
"properties": {
"electron": {
"description": "Treat common electron built-in modules in main and preload context like 'electron', 'ipc' or 'shell' as external and load them via require() when used.",
"type": "boolean"
},
"electronMain": {
"description": "Treat electron built-in modules in the main context like 'app', 'ipc-main' or 'shell' as external and load them via require() when used.",
"type": "boolean"
@ -544,12 +540,16 @@
"description": "Treat electron built-in modules in the preload context like 'web-frame', 'ipc-renderer' or 'shell' as external and load them via require() when used.",
"type": "boolean"
},
"electronRenderer": {
"description": "Treat electron built-in modules in the renderer context like 'web-frame', 'ipc-renderer' or 'shell' as external and load them via require() when used.",
"type": "boolean"
},
"node": {
"description": "Treat node.js built-in modules like fs, path or vm as external and load them via require() when used.",
"type": "boolean"
},
"nodeWebkit": {
"description": "Treat node-webkit legacy nw.gui module as external and load it via require() when used.",
"nwjs": {
"description": "Treat NW.js legacy nw.gui module as external and load it via require() when used.",
"type": "boolean"
},
"web": {
@ -1150,11 +1150,11 @@
"properties": {
"__dirname": {
"description": "Include a polyfill for the '__dirname' variable.",
"enum": [false, true, "mock"]
"enum": [false, true, "mock", "eval-only"]
},
"__filename": {
"description": "Include a polyfill for the '__filename' variable.",
"enum": [false, true, "mock"]
"enum": [false, true, "mock", "eval-only"]
},
"global": {
"description": "Include a polyfill for the 'global' variable.",
@ -3435,23 +3435,23 @@
"type": "boolean"
},
"Target": {
"description": "Environment to build for.",
"description": "Environment to build for. An array of environments to build for all of them when possible.",
"anyOf": [
{
"enum": [
"web",
"webworker",
"node",
"async-node",
"node-webkit",
"electron-main",
"electron-renderer",
"electron-preload"
]
"type": "array",
"items": {
"description": "Environment to build for.",
"type": "string",
"minLength": 1
},
"minItems": 1
},
{
"instanceof": "Function",
"tsType": "((compiler: import('../lib/Compiler')) => void)"
"enum": [false]
},
{
"type": "string",
"minLength": 1
}
]
},

View File

@ -96,6 +96,12 @@ describe("Defaults", () => {
},
"externals": undefined,
"externalsPresets": Object {
"electron": false,
"electronMain": false,
"electronPreload": false,
"electronRenderer": false,
"node": false,
"nwjs": false,
"web": true,
},
"externalsType": "var",
@ -279,12 +285,12 @@ describe("Defaults", () => {
],
"environment": Object {
"arrowFunction": true,
"bigIntLiteral": undefined,
"const": true,
"destructing": true,
"destructuring": true,
"forOf": true,
"global": false,
"import": true,
"module": true,
"import": undefined,
"module": undefined,
},
"filename": "[name].js",
"globalObject": "self",
@ -328,7 +334,6 @@ describe("Defaults", () => {
"conditionNames": Array [
"require",
"module",
"browser",
"...",
],
"extensions": Array [
@ -349,7 +354,6 @@ describe("Defaults", () => {
"conditionNames": Array [
"require",
"module",
"browser",
"...",
],
"extensions": Array [
@ -370,7 +374,6 @@ describe("Defaults", () => {
"conditionNames": Array [
"import",
"module",
"browser",
"...",
],
"extensions": Array [
@ -391,7 +394,6 @@ describe("Defaults", () => {
"conditionNames": Array [
"require",
"module",
"browser",
"...",
],
"extensions": Array [
@ -412,7 +414,6 @@ describe("Defaults", () => {
"conditionNames": Array [
"require",
"module",
"browser",
"...",
],
"extensions": Array [
@ -433,7 +434,6 @@ describe("Defaults", () => {
"conditionNames": Array [
"require",
"module",
"browser",
"...",
],
"extensions": Array [
@ -454,7 +454,6 @@ describe("Defaults", () => {
"conditionNames": Array [
"import",
"module",
"browser",
"...",
],
"extensions": Array [
@ -473,6 +472,7 @@ describe("Defaults", () => {
"conditionNames": Array [
"webpack",
"production",
"browser",
],
"exportsFields": Array [
"exports",
@ -940,17 +940,20 @@ describe("Defaults", () => {
+ Received
@@ ... @@
- "web": true,
- "node": false,
+ "node": true,
@@ ... @@
- "web": true,
+ "web": false,
@@ ... @@
- "target": "web",
+ "target": "node",
@@ ... @@
- "__dirname": "mock",
- "__filename": "mock",
- "global": true,
+ "__dirname": false,
+ "__filename": false,
+ "__dirname": "eval-only",
+ "__filename": "eval-only",
+ "global": false,
@@ ... @@
- "chunkFormat": "array-push",
@ -966,9 +969,6 @@ describe("Defaults", () => {
- "fetch",
+ "async-node",
@@ ... @@
- "global": false,
+ "global": true,
@@ ... @@
- "globalObject": "self",
+ "globalObject": "global",
@@ ... @@
@ -987,8 +987,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -996,8 +994,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1005,8 +1001,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1014,8 +1008,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1023,8 +1015,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1032,8 +1022,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1041,8 +1029,7 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "browser",
+ "node",
@@ ... @@
- "target": "web",
@ -1054,18 +1041,12 @@ describe("Defaults", () => {
- Expected
+ Received
@@ ... @@
- "target": "web",
+ "target": "webworker",
@@ ... @@
- "chunkLoading": "jsonp",
+ "chunkLoading": "import-scripts",
@@ ... @@
- "jsonp",
@@ ... @@
- "workerChunkLoading": "import-scripts",
+ "workerChunkLoading": false,
@@ ... @@
+ "worker",
@@ ... @@
- "target": "web",
@ -1078,18 +1059,25 @@ describe("Defaults", () => {
+ Received
@@ ... @@
- "web": true,
- "electron": false,
- "electronMain": false,
+ "electron": true,
+ "electronMain": true,
@@ ... @@
- "node": false,
+ "node": true,
@@ ... @@
- "web": true,
+ "web": false,
@@ ... @@
- "target": "web",
+ "target": "electron-main",
@@ ... @@
- "__dirname": "mock",
- "__filename": "mock",
- "global": true,
+ "__dirname": false,
+ "__filename": false,
+ "__dirname": "eval-only",
+ "__filename": "eval-only",
+ "global": false,
@@ ... @@
- "chunkFormat": "array-push",
@ -1105,9 +1093,6 @@ describe("Defaults", () => {
- "fetch",
+ "async-node",
@@ ... @@
- "global": false,
+ "global": true,
@@ ... @@
- "globalObject": "self",
+ "globalObject": "global",
@@ ... @@
@ -1126,8 +1111,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1135,8 +1118,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1144,8 +1125,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1153,8 +1132,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1162,8 +1139,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1171,8 +1146,6 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
@ -1180,8 +1153,7 @@ describe("Defaults", () => {
@@ ... @@
- "browser",
@@ ... @@
- "browser",
@@ ... @@
- "browser",
+ "node",
+ "electron",
@@ ... @@
@ -1195,12 +1167,25 @@ describe("Defaults", () => {
+ Received
@@ ... @@
- "electron": false,
+ "electron": true,
@@ ... @@
- "electronPreload": false,
+ "electronPreload": true,
@@ ... @@
- "node": false,
+ "node": true,
@@ ... @@
- "target": "web",
+ "target": "electron-preload",
@@ ... @@
- "__dirname": "mock",
- "__filename": "mock",
- "global": true,
+ "__dirname": "eval-only",
+ "__filename": "eval-only",
+ "global": false,
@@ ... @@
- "chunkFormat": "array-push",
+ "chunkFormat": "commonjs",
@@ ... @@
@ -1214,9 +1199,6 @@ describe("Defaults", () => {
- "fetch",
+ "async-node",
@@ ... @@
- "global": false,
+ "global": true,
@@ ... @@
- "globalObject": "self",
+ "globalObject": "global",
@@ ... @@
@ -1228,6 +1210,57 @@ describe("Defaults", () => {
+ "workerChunkLoading": "require",
+ "workerWasmLoading": "async-node",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
+ "aliasFields": Array [],
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
+ "aliasFields": Array [],
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
+ "aliasFields": Array [],
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
+ "aliasFields": Array [],
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
+ "aliasFields": Array [],
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
+ "aliasFields": Array [],
@@ ... @@
- "browser",
@@ ... @@
- "aliasFields": Array [
- "browser",
- ],
+ "aliasFields": Array [],
@@ ... @@
- "browser",
@@ ... @@
+ "node",
@@ ... @@
+ "electron",
@@ ... @@
- "target": "web",

View File

@ -412,6 +412,19 @@ Object {
"multiple": true,
"simpleType": "string",
},
"externals-presets-electron": Object {
"configs": Array [
Object {
"description": "Treat common electron built-in modules in main and preload context like 'electron', 'ipc' or 'shell' as external and load them via require() when used.",
"multiple": false,
"path": "externalsPresets.electron",
"type": "boolean",
},
],
"description": "Treat common electron built-in modules in main and preload context like 'electron', 'ipc' or 'shell' as external and load them via require() when used.",
"multiple": false,
"simpleType": "boolean",
},
"externals-presets-electron-main": Object {
"configs": Array [
Object {
@ -438,6 +451,19 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"externals-presets-electron-renderer": Object {
"configs": Array [
Object {
"description": "Treat electron built-in modules in the renderer context like 'web-frame', 'ipc-renderer' or 'shell' as external and load them via require() when used.",
"multiple": false,
"path": "externalsPresets.electronRenderer",
"type": "boolean",
},
],
"description": "Treat electron built-in modules in the renderer context like 'web-frame', 'ipc-renderer' or 'shell' as external and load them via require() when used.",
"multiple": false,
"simpleType": "boolean",
},
"externals-presets-node": Object {
"configs": Array [
Object {
@ -451,16 +477,16 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"externals-presets-node-webkit": Object {
"externals-presets-nwjs": Object {
"configs": Array [
Object {
"description": "Treat node-webkit legacy nw.gui module as external and load it via require() when used.",
"description": "Treat NW.js legacy nw.gui module as external and load it via require() when used.",
"multiple": false,
"path": "externalsPresets.nodeWebkit",
"path": "externalsPresets.nwjs",
"type": "boolean",
},
],
"description": "Treat node-webkit legacy nw.gui module as external and load it via require() when used.",
"description": "Treat NW.js legacy nw.gui module as external and load it via require() when used.",
"multiple": false,
"simpleType": "boolean",
},
@ -1210,6 +1236,7 @@ Object {
false,
true,
"mock",
"eval-only",
],
},
],
@ -1228,6 +1255,7 @@ Object {
false,
true,
"mock",
"eval-only",
],
},
],
@ -2222,16 +2250,16 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"output-environment-destructing": Object {
"output-environment-destructuring": Object {
"configs": Array [
Object {
"description": "The environment supports destructing ('{ a, b } = obj').",
"description": "The environment supports destructuring ('{ a, b } = obj').",
"multiple": false,
"path": "output.environment.destructing",
"path": "output.environment.destructuring",
"type": "boolean",
},
],
"description": "The environment supports destructing ('{ a, b } = obj').",
"description": "The environment supports destructuring ('{ a, b } = obj').",
"multiple": false,
"simpleType": "boolean",
},
@ -2248,32 +2276,6 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"output-environment-global": Object {
"configs": Array [
Object {
"description": "The environment supports a global 'global' variable which points to the global context.",
"multiple": false,
"path": "output.environment.global",
"type": "boolean",
},
],
"description": "The environment supports a global 'global' variable which points to the global context.",
"multiple": false,
"simpleType": "boolean",
},
"output-environment-global-this": Object {
"configs": Array [
Object {
"description": "The environment supports a global 'globalThis' variable which points to the global context.",
"multiple": false,
"path": "output.environment.globalThis",
"type": "boolean",
},
],
"description": "The environment supports a global 'globalThis' variable which points to the global context.",
"multiple": false,
"simpleType": "boolean",
},
"output-environment-import": Object {
"configs": Array [
Object {
@ -5218,25 +5220,37 @@ Object {
"configs": Array [
Object {
"description": "Environment to build for.",
"multiple": true,
"path": "target[]",
"type": "string",
},
Object {
"description": "Environment to build for. An array of environments to build for all of them when possible.",
"multiple": false,
"path": "target",
"type": "enum",
"values": Array [
"web",
"webworker",
"node",
"async-node",
"node-webkit",
"electron-main",
"electron-renderer",
"electron-preload",
false,
],
},
],
"description": "Environment to build for.",
"multiple": false,
"description": "Environment to build for. Environment to build for. An array of environments to build for all of them when possible.",
"multiple": true,
"simpleType": "string",
},
"target-reset": Object {
"configs": Array [
Object {
"description": "Clear all items provided in configuration. Environment to build for. An array of environments to build for all of them when possible.",
"multiple": false,
"path": "target",
"type": "reset",
},
],
"description": "Clear all items provided in configuration. Environment to build for. An array of environments to build for all of them when possible.",
"multiple": false,
"simpleType": "boolean",
},
"watch": Object {
"configs": Array [
Object {

View File

@ -1,13 +1,13 @@
import { test } from "./file";
it("should allow import in array destructing", function() {
it("should allow import in array destructuring", function () {
var other;
[other = test] = [];
expect(other).toBe("test");
});
it("should allow import in object destructing", function() {
it("should allow import in object destructuring", function () {
var other;
({other = test} = {});
({ other = test } = {});
expect(other).toBe("test");
});

View File

@ -0,0 +1,4 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
target: ["node", "es2015"]
};

View File

@ -0,0 +1 @@
it("should compile and run the test", function() {});

View File

@ -0,0 +1,4 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
target: ["node", "es2020"]
};

View File

@ -1,11 +1,4 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
output: {
environment: {
arrowFunction: false,
const: false,
destructing: false,
forOf: false
}
}
target: ["node", "es5"]
};

View File

@ -0,0 +1 @@
it("should compile and run the test", function() {});

View File

@ -3,9 +3,12 @@ module.exports = {
output: {
environment: {
arrowFunction: true,
const: true,
destructing: true,
forOf: true
bigIntLiteral: false,
const: false,
destructuring: false,
forOf: false,
import: true,
module: false
}
}
};

53
types.d.ts vendored
View File

@ -1820,7 +1820,7 @@ declare interface Configuration {
stats?: StatsValue;
/**
* Environment to build for.
* Environment to build for. An array of environments to build for all of them when possible.
*/
target?: Target;
@ -2433,7 +2433,7 @@ declare interface Effect {
value: any;
}
declare class ElectronTargetPlugin {
constructor(main: boolean);
constructor(context?: "main" | "preload" | "renderer");
/**
* Apply the plugin
@ -2687,25 +2687,15 @@ declare interface Environment {
const?: boolean;
/**
* The environment supports destructing ('{ a, b } = obj').
* The environment supports destructuring ('{ a, b } = obj').
*/
destructing?: boolean;
destructuring?: boolean;
/**
* The environment supports 'for of' iteration ('for (const x of array) { ... }').
*/
forOf?: boolean;
/**
* The environment supports a global 'global' variable which points to the global context.
*/
global?: boolean;
/**
* The environment supports a global 'globalThis' variable which points to the global context.
*/
globalThis?: boolean;
/**
* The environment supports an async import() function to import EcmaScript modules.
*/
@ -3064,6 +3054,11 @@ declare class ExternalsPlugin {
* Enable presets of externals for specific targets.
*/
declare interface ExternalsPresets {
/**
* Treat common electron built-in modules in main and preload context like 'electron', 'ipc' or 'shell' as external and load them via require() when used.
*/
electron?: boolean;
/**
* Treat electron built-in modules in the main context like 'app', 'ipc-main' or 'shell' as external and load them via require() when used.
*/
@ -3074,15 +3069,20 @@ declare interface ExternalsPresets {
*/
electronPreload?: boolean;
/**
* Treat electron built-in modules in the renderer context like 'web-frame', 'ipc-renderer' or 'shell' as external and load them via require() when used.
*/
electronRenderer?: boolean;
/**
* Treat node.js built-in modules like fs, path or vm as external and load them via require() when used.
*/
node?: boolean;
/**
* Treat node-webkit legacy nw.gui module as external and load it via require() when used.
* Treat NW.js legacy nw.gui module as external and load it via require() when used.
*/
nodeWebkit?: boolean;
nwjs?: boolean;
/**
* Treat references to 'http(s)://...' and 'std:...' as external and load them via import when used (Note that this changes execution order as externals are executed before any other code in the chunk).
@ -5138,12 +5138,12 @@ declare interface NodeOptions {
/**
* Include a polyfill for the '__dirname' variable.
*/
__dirname?: boolean | "mock";
__dirname?: boolean | "mock" | "eval-only";
/**
* Include a polyfill for the '__filename' variable.
*/
__filename?: boolean | "mock";
__filename?: boolean | "mock" | "eval-only";
/**
* Include a polyfill for the 'global' variable.
@ -5151,7 +5151,7 @@ declare interface NodeOptions {
global?: boolean;
}
declare class NodeSourcePlugin {
constructor(options: NodeWebpackOptions);
constructor();
/**
* Apply the plugin
@ -7643,7 +7643,7 @@ declare abstract class RuntimeTemplate {
supportsConst(): boolean;
supportsArrowFunction(): boolean;
supportsForOf(): boolean;
supportsDestructing(): boolean;
supportsDestructuring(): boolean;
supportsBigIntLiteral(): boolean;
supportsAsyncImport(): boolean;
supportsEcmaScriptModuleSyntax(): boolean;
@ -8894,16 +8894,7 @@ declare interface TagInfo {
data: any;
next: TagInfo;
}
type Target =
| "web"
| "webworker"
| "node"
| "async-node"
| "node-webkit"
| "electron-main"
| "electron-renderer"
| "electron-preload"
| ((compiler: Compiler) => void);
type Target = string | false | [string, ...string[]];
declare class Template {
constructor();
static getFunctionContent(fn: Function): string;
@ -9419,7 +9410,7 @@ declare interface WebpackOptionsNormalized {
stats: StatsValue;
/**
* Environment to build for.
* Environment to build for. An array of environments to build for all of them when possible.
*/
target?: Target;