mirror of https://github.com/webpack/webpack.git
Merge pull request #14291 from webpack/feature/eval-bailouzt
avoid bailout of unused eval
This commit is contained in:
commit
aa83e463c5
|
@ -28,7 +28,12 @@ class JavascriptMetaInfoPlugin {
|
|||
parser.hooks.call.for("eval").tap("JavascriptMetaInfoPlugin", () => {
|
||||
parser.state.module.buildInfo.moduleConcatenationBailout = "eval()";
|
||||
parser.state.module.buildInfo.usingEval = true;
|
||||
InnerGraph.bailout(parser.state);
|
||||
const currentSymbol = InnerGraph.getTopLevelSymbol(parser.state);
|
||||
if (currentSymbol) {
|
||||
InnerGraph.addUsage(parser.state, null, currentSymbol);
|
||||
} else {
|
||||
InnerGraph.bailout(parser.state);
|
||||
}
|
||||
});
|
||||
parser.hooks.finish.tap("JavascriptMetaInfoPlugin", () => {
|
||||
let topLevelDeclarations =
|
||||
|
|
|
@ -394,6 +394,9 @@ module.exports = mergeExports(fn, {
|
|||
"DEP_WEBPACK_AGGRESSIVE_SPLITTING_PLUGIN"
|
||||
)();
|
||||
},
|
||||
get InnerGraph() {
|
||||
return require("./optimize/InnerGraph");
|
||||
},
|
||||
get LimitChunkCountPlugin() {
|
||||
return require("./optimize/LimitChunkCountPlugin");
|
||||
},
|
||||
|
@ -535,6 +538,9 @@ module.exports = mergeExports(fn, {
|
|||
get comparators() {
|
||||
return require("./util/comparators");
|
||||
},
|
||||
get runtime() {
|
||||
return require("./util/runtime");
|
||||
},
|
||||
get serialization() {
|
||||
return require("./util/serialization");
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ const { UsageState } = require("../ExportsInfo");
|
|||
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
|
||||
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
|
||||
|
||||
/** @typedef {Map<TopLevelSymbol, Set<string | TopLevelSymbol> | true>} InnerGraph */
|
||||
/** @typedef {Map<TopLevelSymbol | null, Set<string | TopLevelSymbol> | true>} InnerGraph */
|
||||
/** @typedef {function(boolean | Set<string> | undefined): void} UsageCallback */
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@ exports.isEnabled = parserState => {
|
|||
|
||||
/**
|
||||
* @param {ParserState} state parser state
|
||||
* @param {TopLevelSymbol} symbol the symbol
|
||||
* @param {TopLevelSymbol | null} symbol the symbol, or null for all symbols
|
||||
* @param {string | TopLevelSymbol | true} usage usage data
|
||||
* @returns {void}
|
||||
*/
|
||||
|
@ -172,6 +172,26 @@ exports.inferDependencyUsage = state => {
|
|||
}
|
||||
if (isTerminal) {
|
||||
nonTerminal.delete(key);
|
||||
|
||||
// For the global key, merge with all other keys
|
||||
if (key === null) {
|
||||
const globalValue = innerGraph.get(null);
|
||||
if (globalValue) {
|
||||
for (const [key, value] of innerGraph) {
|
||||
if (key !== null && value !== true) {
|
||||
if (globalValue === true) {
|
||||
innerGraph.set(key, true);
|
||||
} else {
|
||||
const newSet = new Set(value);
|
||||
for (const item of globalValue) {
|
||||
newSet.add(item);
|
||||
}
|
||||
innerGraph.set(key, newSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { a, b, c } from "./test";
|
||||
|
||||
export function x() {
|
||||
a();
|
||||
}
|
||||
|
||||
export function y() {
|
||||
b();
|
||||
eval("x()");
|
||||
}
|
||||
|
||||
export function z() {
|
||||
c();
|
||||
y();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
const createTestCases = require("../_helpers/createTestCases");
|
||||
module.exports = createTestCases({
|
||||
nothing: {
|
||||
usedExports: [],
|
||||
expect: {
|
||||
"./test": []
|
||||
}
|
||||
},
|
||||
nonEval: {
|
||||
usedExports: ["x"],
|
||||
expect: {
|
||||
"./test": ["a"]
|
||||
}
|
||||
},
|
||||
directEval: {
|
||||
usedExports: ["y"],
|
||||
expect: {
|
||||
"./test": ["a", "b", "c"]
|
||||
}
|
||||
},
|
||||
indirectEval: {
|
||||
usedExports: ["z"],
|
||||
expect: {
|
||||
"./test": ["a", "b", "c"]
|
||||
}
|
||||
}
|
||||
});
|
|
@ -9783,6 +9783,7 @@ declare class RuntimeChunkPlugin {
|
|||
*/
|
||||
apply(compiler: Compiler): void;
|
||||
}
|
||||
type RuntimeCondition = undefined | string | boolean | SortableSet<string>;
|
||||
declare class RuntimeModule extends Module {
|
||||
constructor(name: string, stage?: number);
|
||||
name: string;
|
||||
|
@ -9829,7 +9830,8 @@ declare interface RuntimeRequirementsContext {
|
|||
codeGenerationResults: CodeGenerationResults;
|
||||
}
|
||||
type RuntimeSpec = undefined | string | SortableSet<string>;
|
||||
declare abstract class RuntimeSpecMap<T> {
|
||||
declare class RuntimeSpecMap<T> {
|
||||
constructor(clone?: RuntimeSpecMap<T>);
|
||||
get(runtime: RuntimeSpec): T;
|
||||
has(runtime: RuntimeSpec): boolean;
|
||||
set(runtime?: any, value?: any): void;
|
||||
|
@ -9840,7 +9842,8 @@ declare abstract class RuntimeSpecMap<T> {
|
|||
values(): IterableIterator<T>;
|
||||
readonly size?: number;
|
||||
}
|
||||
declare abstract class RuntimeSpecSet {
|
||||
declare class RuntimeSpecSet {
|
||||
constructor(iterable?: any);
|
||||
add(runtime?: any): void;
|
||||
has(runtime?: any): boolean;
|
||||
[Symbol.iterator](): IterableIterator<RuntimeSpec>;
|
||||
|
@ -11299,6 +11302,10 @@ declare interface TimestampAndHash {
|
|||
timestamp?: number;
|
||||
hash: string;
|
||||
}
|
||||
declare class TopLevelSymbol {
|
||||
constructor(name: string);
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a Trusted Types policy to create urls for chunks.
|
||||
|
@ -12155,6 +12162,52 @@ declare namespace exports {
|
|||
};
|
||||
}
|
||||
export namespace optimize {
|
||||
export namespace InnerGraph {
|
||||
export let bailout: (parserState: ParserState) => void;
|
||||
export let enable: (parserState: ParserState) => void;
|
||||
export let isEnabled: (parserState: ParserState) => boolean;
|
||||
export let addUsage: (
|
||||
state: ParserState,
|
||||
symbol: null | TopLevelSymbol,
|
||||
usage: string | true | TopLevelSymbol
|
||||
) => void;
|
||||
export let addVariableUsage: (
|
||||
parser: JavascriptParser,
|
||||
name: string,
|
||||
usage: string | true | TopLevelSymbol
|
||||
) => void;
|
||||
export let inferDependencyUsage: (state: ParserState) => void;
|
||||
export let onUsage: (
|
||||
state: ParserState,
|
||||
onUsageCallback: (arg0?: boolean | Set<string>) => void
|
||||
) => void;
|
||||
export let setTopLevelSymbol: (
|
||||
state: ParserState,
|
||||
symbol: TopLevelSymbol
|
||||
) => void;
|
||||
export let getTopLevelSymbol: (
|
||||
state: ParserState
|
||||
) => void | TopLevelSymbol;
|
||||
export let tagTopLevelSymbol: (
|
||||
parser: JavascriptParser,
|
||||
name: string
|
||||
) => TopLevelSymbol;
|
||||
export let isDependencyUsedByExports: (
|
||||
dependency: Dependency,
|
||||
usedByExports: boolean | Set<string>,
|
||||
moduleGraph: ModuleGraph,
|
||||
runtime: RuntimeSpec
|
||||
) => boolean;
|
||||
export let getDependencyUsedByExportsCondition: (
|
||||
dependency: Dependency,
|
||||
usedByExports: boolean | Set<string>,
|
||||
moduleGraph: ModuleGraph
|
||||
) =>
|
||||
| null
|
||||
| false
|
||||
| ((arg0: ModuleGraphConnection, arg1: RuntimeSpec) => ConnectionState);
|
||||
export { TopLevelSymbol, topLevelSymbolTag };
|
||||
}
|
||||
export {
|
||||
AggressiveMergingPlugin,
|
||||
AggressiveSplittingPlugin,
|
||||
|
@ -12280,6 +12333,59 @@ declare namespace exports {
|
|||
b: DependencyLocation
|
||||
) => 0 | 1 | -1;
|
||||
}
|
||||
export namespace runtime {
|
||||
export let getEntryRuntime: (
|
||||
compilation: Compilation,
|
||||
name: string,
|
||||
options?: EntryOptions
|
||||
) => RuntimeSpec;
|
||||
export let forEachRuntime: (
|
||||
runtime: RuntimeSpec,
|
||||
fn: (arg0: string) => void,
|
||||
deterministicOrder?: boolean
|
||||
) => void;
|
||||
export let getRuntimeKey: (runtime: RuntimeSpec) => string;
|
||||
export let keyToRuntime: (key: string) => RuntimeSpec;
|
||||
export let runtimeToString: (runtime: RuntimeSpec) => string;
|
||||
export let runtimeConditionToString: (
|
||||
runtimeCondition: RuntimeCondition
|
||||
) => string;
|
||||
export let runtimeEqual: (a: RuntimeSpec, b: RuntimeSpec) => boolean;
|
||||
export let compareRuntime: (a: RuntimeSpec, b: RuntimeSpec) => 0 | 1 | -1;
|
||||
export let mergeRuntime: (a: RuntimeSpec, b: RuntimeSpec) => RuntimeSpec;
|
||||
export let mergeRuntimeCondition: (
|
||||
a: RuntimeCondition,
|
||||
b: RuntimeCondition,
|
||||
runtime: RuntimeSpec
|
||||
) => RuntimeCondition;
|
||||
export let mergeRuntimeConditionNonFalse: (
|
||||
a: undefined | string | true | SortableSet<string>,
|
||||
b: undefined | string | true | SortableSet<string>,
|
||||
runtime: RuntimeSpec
|
||||
) => undefined | string | true | SortableSet<string>;
|
||||
export let mergeRuntimeOwned: (
|
||||
a: RuntimeSpec,
|
||||
b: RuntimeSpec
|
||||
) => RuntimeSpec;
|
||||
export let intersectRuntime: (
|
||||
a: RuntimeSpec,
|
||||
b: RuntimeSpec
|
||||
) => RuntimeSpec;
|
||||
export let subtractRuntime: (
|
||||
a: RuntimeSpec,
|
||||
b: RuntimeSpec
|
||||
) => RuntimeSpec;
|
||||
export let subtractRuntimeCondition: (
|
||||
a: RuntimeCondition,
|
||||
b: RuntimeCondition,
|
||||
runtime: RuntimeSpec
|
||||
) => RuntimeCondition;
|
||||
export let filterRuntime: (
|
||||
runtime: RuntimeSpec,
|
||||
filter: (arg0: RuntimeSpec) => boolean
|
||||
) => undefined | string | boolean | SortableSet<string>;
|
||||
export { RuntimeSpecMap, RuntimeSpecSet };
|
||||
}
|
||||
export namespace serialization {
|
||||
export const register: (
|
||||
Constructor: Constructor,
|
||||
|
@ -12425,5 +12531,6 @@ declare namespace exports {
|
|||
LoaderContext
|
||||
};
|
||||
}
|
||||
declare const topLevelSymbolTag: unique symbol;
|
||||
|
||||
export = exports;
|
||||
|
|
Loading…
Reference in New Issue