mirror of https://github.com/webpack/webpack.git
parent
d6a669ee18
commit
4cf676386f
|
@ -1669,21 +1669,17 @@ class JavascriptModulesPlugin {
|
|||
|
||||
if (!moduleSource) continue;
|
||||
const code = /** @type {string} */ (moduleSource.source());
|
||||
|
||||
/** @type {Program} */
|
||||
let ast;
|
||||
let moduleParser;
|
||||
|
||||
if (
|
||||
m instanceof NormalModule &&
|
||||
(moduleParser = JavascriptParser.getModuleParser(m))
|
||||
) {
|
||||
({ ast } = moduleParser.clone("auto")._innerParse(code));
|
||||
} else {
|
||||
ast = JavascriptParser._parse(code, {
|
||||
sourceType: "auto"
|
||||
});
|
||||
}
|
||||
const { ast } = JavascriptParser._parse(
|
||||
code,
|
||||
{
|
||||
sourceType: "auto",
|
||||
ranges: true
|
||||
},
|
||||
JavascriptParser._getParse(
|
||||
"auto",
|
||||
renderContext.runtimeTemplate.compilation
|
||||
)
|
||||
);
|
||||
|
||||
const scopeManager = eslintScope.analyze(ast, {
|
||||
ecmaVersion: 6,
|
||||
|
|
|
@ -98,7 +98,6 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
|||
*/
|
||||
/** @typedef {import("../Parser").ParserState} ParserState */
|
||||
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
||||
/** @typedef {import("../NormalModule")} NormalModule */
|
||||
|
||||
/** @typedef {{ name: string | VariableInfo, rootInfo: string | VariableInfo, getMembers: () => Members, getMembersOptionals: () => MembersOptionals, getMemberRanges: () => MemberRanges }} GetInfoResult */
|
||||
/** @typedef {Statement | ModuleDeclaration | Expression | MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration} StatementPathItem */
|
||||
|
@ -301,19 +300,29 @@ class VariableInfo {
|
|||
/** @typedef {string | ScopeInfo | VariableInfo} ExportedVariableInfo */
|
||||
/** @typedef {Literal | string | null | undefined} ImportSource */
|
||||
|
||||
/** @typedef {Omit<AcornOptions, "sourceType" | "ecmaVersion"> & { sourceType: "module" | "script" | "auto", ecmaVersion?: AcornOptions["ecmaVersion"] }} ParseOptions */
|
||||
|
||||
/**
|
||||
* @typedef {(code: string, options: Pick<AcornOptions, "onComment" | "onInsertedSemicolon">) => Program} ParseFunction
|
||||
* @typedef {object} ParseOptions
|
||||
* @property {"module" | "script" | "auto"} sourceType
|
||||
* @property {EcmaVersion=} ecmaVersion
|
||||
* @property {boolean=} locations
|
||||
* @property {boolean=} comments
|
||||
* @property {boolean=} ranges
|
||||
* @property {boolean=} semicolons
|
||||
* @property {boolean=} allowHashBang
|
||||
* @property {boolean=} allowReturnOutsideFunction
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {object} InnerParseResult
|
||||
* @typedef {object} ParseResult
|
||||
* @property {Program} ast
|
||||
* @property {Comment[]} comments
|
||||
* @property {Set<number>} semicolons
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {(code: string, options: ParseOptions) => ParseResult} ParseFunction
|
||||
*/
|
||||
|
||||
/** @typedef {symbol} Tag */
|
||||
|
||||
/** @typedef {import("../dependencies/HarmonyImportDependencyParserPlugin").HarmonySettings} HarmonySettings */
|
||||
|
@ -426,15 +435,15 @@ const getRootName = (expression) => {
|
|||
}
|
||||
};
|
||||
|
||||
/** @type {AcornOptions} */
|
||||
/** @type {ParseOptions} */
|
||||
const defaultParserOptions = {
|
||||
ranges: true,
|
||||
locations: true,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
ecmaVersion: "latest",
|
||||
ranges: false,
|
||||
locations: false,
|
||||
comments: false,
|
||||
// https://github.com/tc39/proposal-hashbang
|
||||
allowHashBang: true,
|
||||
onComment: undefined
|
||||
allowHashBang: true
|
||||
};
|
||||
|
||||
const EMPTY_COMMENT_OPTIONS = {
|
||||
|
@ -4593,35 +4602,6 @@ class JavascriptParser extends Parser {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} source the source to parse
|
||||
* @returns {InnerParseResult} parsing result
|
||||
*/
|
||||
_innerParse(source) {
|
||||
/** @type {Comment[]} */
|
||||
const comments = [];
|
||||
const semicolons = new Set();
|
||||
|
||||
/** @type {Program} */
|
||||
const ast =
|
||||
typeof this.options.parse !== "undefined"
|
||||
? this.options.parse(source, {
|
||||
onComment: comments,
|
||||
onInsertedSemicolon: (pos) => semicolons.add(pos)
|
||||
})
|
||||
: JavascriptParser._parse(source, {
|
||||
sourceType: this.sourceType,
|
||||
onComment: comments,
|
||||
onInsertedSemicolon: (pos) => semicolons.add(pos)
|
||||
});
|
||||
|
||||
return {
|
||||
ast,
|
||||
comments,
|
||||
semicolons
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | Buffer | PreparsedAst} source the source to parse
|
||||
* @param {ParserState} state the parser state
|
||||
|
@ -4636,16 +4616,17 @@ class JavascriptParser extends Parser {
|
|||
source = source.toString("utf8");
|
||||
}
|
||||
|
||||
/** @type {Program} */
|
||||
let ast;
|
||||
/** @type {Comment[]} */
|
||||
let comments;
|
||||
/** @type {Set<number>} */
|
||||
let semicolons;
|
||||
|
||||
if (typeof source === "object") {
|
||||
semicolons = new Set();
|
||||
|
||||
ast = /** @type {Program} */ (source);
|
||||
comments = source.comments;
|
||||
semicolons = new Set();
|
||||
if (source.semicolons) {
|
||||
// Forward semicolon information from the preparsed AST if present
|
||||
// This ensures the output is consistent with that of a fresh AST
|
||||
|
@ -4654,7 +4635,17 @@ class JavascriptParser extends Parser {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
({ ast, comments, semicolons } = this._innerParse(source));
|
||||
({ ast, comments, semicolons } = JavascriptParser._parse(
|
||||
source,
|
||||
{
|
||||
sourceType: this.sourceType,
|
||||
locations: true,
|
||||
ranges: true,
|
||||
comments: true,
|
||||
semicolons: true
|
||||
},
|
||||
this.options.parse
|
||||
));
|
||||
}
|
||||
|
||||
const oldScope = this.scope;
|
||||
|
@ -4704,10 +4695,11 @@ class JavascriptParser extends Parser {
|
|||
* @returns {BasicEvaluatedExpression} evaluation result
|
||||
*/
|
||||
evaluate(source) {
|
||||
const ast = JavascriptParser._parse(`(${source})`, {
|
||||
sourceType: this.sourceType,
|
||||
locations: false
|
||||
});
|
||||
const { ast } = JavascriptParser._parse(
|
||||
`(${source})`,
|
||||
{ sourceType: this.sourceType },
|
||||
this.options.parse
|
||||
);
|
||||
if (ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") {
|
||||
throw new Error("evaluate: Source is not a expression");
|
||||
}
|
||||
|
@ -5258,36 +5250,84 @@ class JavascriptParser extends Parser {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {"module" | "script" | "auto"=} sourceType default source type
|
||||
* @returns {JavascriptParser} parser
|
||||
* @param {"module" | "script" | "auto"} sourceType default source type
|
||||
* @param {import("../Compilation")} compilation compilation
|
||||
* @returns {ParseFunction | undefined} parse function
|
||||
*/
|
||||
clone(sourceType = "auto") {
|
||||
const Ctor = /** @type {typeof JavascriptParser} */ (this.constructor);
|
||||
const cloned = new Ctor(sourceType || this.sourceType, this.options);
|
||||
return cloned;
|
||||
static _getParse(sourceType, compilation) {
|
||||
const moduleType =
|
||||
sourceType === "auto"
|
||||
? "javascript/auto"
|
||||
: sourceType === "module"
|
||||
? "javascript/esm"
|
||||
: "javascript/dynamic";
|
||||
const parser =
|
||||
compilation.options.module.parser[moduleType] ||
|
||||
compilation.options.module.parser.javascript;
|
||||
|
||||
if (parser && typeof parser.parse === "function") {
|
||||
return parser.parse;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} code source code
|
||||
* @param {ParseOptions} options parsing options
|
||||
* @returns {Program} parsed ast
|
||||
* @param {ParseFunction=} parse custom function to parse
|
||||
* @returns {ParseResult} parse result
|
||||
*/
|
||||
static _parse(code, options) {
|
||||
static _parse(code, options, parse) {
|
||||
const type = options ? options.sourceType : "module";
|
||||
/** @type {AcornOptions} */
|
||||
/** @type {ParseOptions} */
|
||||
const parserOptions = {
|
||||
...defaultParserOptions,
|
||||
allowReturnOutsideFunction: type === "script",
|
||||
...options,
|
||||
sourceType: type === "auto" ? "module" : type
|
||||
};
|
||||
/**
|
||||
* @param {string} code source code
|
||||
* @param {ParseOptions} options parsing options
|
||||
* @returns {ParseResult} parse result
|
||||
*/
|
||||
const internalParse = (code, options) => {
|
||||
if (typeof parse !== "undefined") {
|
||||
return parse(code, options);
|
||||
}
|
||||
|
||||
/** @type {import("acorn").Program | undefined} */
|
||||
/** @type {Comment[]} */
|
||||
const comments = [];
|
||||
|
||||
if (options.comments) {
|
||||
/** @type {AcornOptions} */
|
||||
(options).onComment = comments;
|
||||
}
|
||||
|
||||
/** @type {Set<number>} */
|
||||
const semicolons = new Set();
|
||||
|
||||
if (options.semicolons) {
|
||||
/** @type {AcornOptions} */
|
||||
(options).onInsertedSemicolon = (pos) => semicolons.add(pos);
|
||||
}
|
||||
|
||||
const ast =
|
||||
/** @type {Program} */
|
||||
(parser.parse(code, /** @type {AcornOptions} */ (options)));
|
||||
|
||||
return { ast, comments, semicolons };
|
||||
};
|
||||
|
||||
/** @type {Program | undefined} */
|
||||
let ast;
|
||||
/** @type {Comment[] | undefined} */
|
||||
let comments;
|
||||
/** @type {Set<number> | undefined} */
|
||||
let semicolons;
|
||||
let error;
|
||||
let threw = false;
|
||||
try {
|
||||
ast = parser.parse(code, parserOptions);
|
||||
({ ast, comments, semicolons } = internalParse(code, parserOptions));
|
||||
} catch (err) {
|
||||
error = err;
|
||||
threw = true;
|
||||
|
@ -5295,14 +5335,10 @@ class JavascriptParser extends Parser {
|
|||
|
||||
if (threw && type === "auto") {
|
||||
parserOptions.sourceType = "script";
|
||||
if (!("allowReturnOutsideFunction" in options)) {
|
||||
parserOptions.allowReturnOutsideFunction = true;
|
||||
}
|
||||
if (Array.isArray(parserOptions.onComment)) {
|
||||
parserOptions.onComment.length = 0;
|
||||
}
|
||||
parserOptions.allowReturnOutsideFunction = true;
|
||||
|
||||
try {
|
||||
ast = parser.parse(code, parserOptions);
|
||||
({ ast, comments, semicolons } = internalParse(code, parserOptions));
|
||||
threw = false;
|
||||
} catch (_err) {
|
||||
// we use the error from first parse try
|
||||
|
@ -5314,7 +5350,7 @@ class JavascriptParser extends Parser {
|
|||
throw error;
|
||||
}
|
||||
|
||||
return /** @type {Program} */ (ast);
|
||||
return /** @type {ParseResult} */ ({ ast, comments, semicolons });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5325,17 +5361,6 @@ class JavascriptParser extends Parser {
|
|||
parser = parser.extend(...plugins);
|
||||
return JavascriptParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NormalModule} module module
|
||||
* @returns {JavascriptParser | null} parser
|
||||
*/
|
||||
static getModuleParser(module) {
|
||||
if (module.parser instanceof JavascriptParser) {
|
||||
return module.parser;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = JavascriptParser;
|
||||
|
|
|
@ -18,7 +18,6 @@ const { UsageState } = require("../ExportsInfo");
|
|||
const Module = require("../Module");
|
||||
const { JS_TYPES } = require("../ModuleSourceTypesConstants");
|
||||
const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants");
|
||||
const NormalModule = require("../NormalModule");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const Template = require("../Template");
|
||||
const { DEFAULTS } = require("../config/defaults");
|
||||
|
@ -2050,21 +2049,16 @@ ${defineGetters}`
|
|||
const data = codeGenResult.data;
|
||||
const chunkInitFragments = data && data.get("chunkInitFragments");
|
||||
const code = source.source().toString();
|
||||
|
||||
/** @type {Program} */
|
||||
let ast;
|
||||
try {
|
||||
let moduleParser;
|
||||
if (
|
||||
m instanceof NormalModule &&
|
||||
(moduleParser = JavascriptParser.getModuleParser(m))
|
||||
) {
|
||||
({ ast } = moduleParser.clone("module")._innerParse(code));
|
||||
} else {
|
||||
ast = JavascriptParser._parse(code, {
|
||||
sourceType: "module"
|
||||
});
|
||||
}
|
||||
({ ast } = JavascriptParser._parse(
|
||||
code,
|
||||
{
|
||||
sourceType: "module",
|
||||
ranges: true
|
||||
},
|
||||
JavascriptParser._getParse("module", this.compilation)
|
||||
));
|
||||
} catch (_err) {
|
||||
const err =
|
||||
/** @type {Error & { loc?: { line: number, column: number } }} */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
require("./helpers/warmup-webpack");
|
||||
|
||||
/** @typedef {Record<string, EXPECTED_ANY>} Env */
|
||||
/** @typedef { testPath: string } TestOptions */
|
||||
/** @typedef {{ testPath: string } TestOptions */
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("graceful-fs");
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Run `yarn fix:special` to update
|
||||
*/
|
||||
|
||||
import { Options as OptionsImport, Parser as ParserImport } from "acorn";
|
||||
import { Parser as ParserImport } from "acorn";
|
||||
import { Buffer } from "buffer";
|
||||
import { Scope } from "eslint-scope";
|
||||
import {
|
||||
|
@ -3801,8 +3801,8 @@ declare class DefinePlugin {
|
|||
): RuntimeValue;
|
||||
}
|
||||
declare class DelegatedPlugin {
|
||||
constructor(options: OptionsDelegatedModuleFactoryPlugin);
|
||||
options: OptionsDelegatedModuleFactoryPlugin;
|
||||
constructor(options: Options);
|
||||
options: Options;
|
||||
|
||||
/**
|
||||
* Apply the plugin
|
||||
|
@ -6674,12 +6674,7 @@ declare class JavascriptModulesPlugin {
|
|||
declare class JavascriptParser extends ParserClass {
|
||||
constructor(
|
||||
sourceType?: "module" | "auto" | "script",
|
||||
options?: {
|
||||
parse?: (
|
||||
code: string,
|
||||
options: Pick<OptionsImport, "onComment" | "onInsertedSemicolon">
|
||||
) => Program;
|
||||
}
|
||||
options?: { parse?: (code: string, options: ParseOptions) => ParseResult }
|
||||
);
|
||||
hooks: Readonly<{
|
||||
evaluateTypeof: HookMap<
|
||||
|
@ -7116,12 +7111,7 @@ declare class JavascriptParser extends ParserClass {
|
|||
unusedStatement: SyncBailHook<[Statement], boolean | void>;
|
||||
}>;
|
||||
sourceType: "module" | "auto" | "script";
|
||||
options: {
|
||||
parse?: (
|
||||
code: string,
|
||||
options: Pick<OptionsImport, "onComment" | "onInsertedSemicolon">
|
||||
) => Program;
|
||||
};
|
||||
options: { parse?: (code: string, options: ParseOptions) => ParseResult };
|
||||
scope: ScopeInfo;
|
||||
state: ParserState;
|
||||
comments?: CommentJavascriptParser[];
|
||||
|
@ -8097,11 +8087,9 @@ declare class JavascriptParser extends ParserClass {
|
|||
rootInfo: ExportedVariableInfo;
|
||||
getMembers: () => string[];
|
||||
};
|
||||
clone(sourceType?: "module" | "auto" | "script"): JavascriptParser;
|
||||
static extend(
|
||||
...plugins: ((BaseParser: typeof ParserImport) => typeof ParserImport)[]
|
||||
): typeof JavascriptParser;
|
||||
static getModuleParser(module: NormalModule): null | JavascriptParser;
|
||||
static ALLOWED_MEMBER_TYPES_ALL: 3;
|
||||
static ALLOWED_MEMBER_TYPES_CALL_EXPRESSION: 1;
|
||||
static ALLOWED_MEMBER_TYPES_EXPRESSION: 2;
|
||||
|
@ -8245,10 +8233,7 @@ declare interface JavascriptParserOptions {
|
|||
/**
|
||||
* Function to parser source code.
|
||||
*/
|
||||
parse?: (
|
||||
code: string,
|
||||
options: Pick<OptionsImport, "onComment" | "onInsertedSemicolon">
|
||||
) => Program;
|
||||
parse?: (code: string, options: ParseOptions) => ParseResult;
|
||||
|
||||
/**
|
||||
* Specifies the behavior of invalid export names in "export ... from ...". This might be useful to disable during the migration from "export ... from ..." to "export type ... from ..." when reexporting types in TypeScript.
|
||||
|
@ -12187,13 +12172,7 @@ declare interface OptimizationSplitChunksOptions {
|
|||
*/
|
||||
usedExports?: boolean;
|
||||
}
|
||||
declare abstract class OptionsApply {
|
||||
process(
|
||||
options: WebpackOptionsNormalizedWithDefaults,
|
||||
compiler: Compiler
|
||||
): WebpackOptionsNormalizedWithDefaults;
|
||||
}
|
||||
declare interface OptionsDelegatedModuleFactoryPlugin {
|
||||
declare interface Options {
|
||||
/**
|
||||
* source
|
||||
*/
|
||||
|
@ -12229,6 +12208,12 @@ declare interface OptionsDelegatedModuleFactoryPlugin {
|
|||
*/
|
||||
associatedObjectForCache?: object;
|
||||
}
|
||||
declare abstract class OptionsApply {
|
||||
process(
|
||||
options: WebpackOptionsNormalizedWithDefaults,
|
||||
compiler: Compiler
|
||||
): WebpackOptionsNormalizedWithDefaults;
|
||||
}
|
||||
declare interface OriginRecord {
|
||||
module: null | Module;
|
||||
loc: DependencyLocation;
|
||||
|
@ -12906,6 +12891,48 @@ type OutputNormalizedWithDefaults = OutputNormalized & {
|
|||
declare interface ParameterizedComparator<TArg extends object, T> {
|
||||
(tArg: TArg): Comparator<T>;
|
||||
}
|
||||
declare interface ParseOptions {
|
||||
sourceType: "module" | "auto" | "script";
|
||||
ecmaVersion?:
|
||||
| 3
|
||||
| 5
|
||||
| 6
|
||||
| 7
|
||||
| 8
|
||||
| 9
|
||||
| 10
|
||||
| 11
|
||||
| 12
|
||||
| 13
|
||||
| 14
|
||||
| 15
|
||||
| 16
|
||||
| 17
|
||||
| 2015
|
||||
| 2016
|
||||
| 2017
|
||||
| 2018
|
||||
| 2019
|
||||
| 2020
|
||||
| 2021
|
||||
| 2022
|
||||
| 2023
|
||||
| 2024
|
||||
| 2025
|
||||
| 2026
|
||||
| "latest";
|
||||
locations?: boolean;
|
||||
comments?: boolean;
|
||||
ranges?: boolean;
|
||||
semicolons?: boolean;
|
||||
allowHashBang?: boolean;
|
||||
allowReturnOutsideFunction?: boolean;
|
||||
}
|
||||
declare interface ParseResult {
|
||||
ast: Program;
|
||||
comments: CommentJavascriptParser[];
|
||||
semicolons: Set<number>;
|
||||
}
|
||||
declare interface ParsedIdentifier {
|
||||
/**
|
||||
* request
|
||||
|
|
Loading…
Reference in New Issue