chore(types): more

This commit is contained in:
alexander.akait 2024-01-26 20:38:18 +03:00
parent 3295f6c36f
commit ca2fe13c8a
6 changed files with 265 additions and 89 deletions

View File

@ -108,10 +108,10 @@ const DEFINITIONS = {
class AMDDefineDependency extends NullDependency {
/**
* @param {Range} range range
* @param {Range} arrayRange array range
* @param {Range} functionRange function range
* @param {Range} objectRange object range
* @param {boolean} namedModule true, when define is called with a name
* @param {Range | null} arrayRange array range
* @param {Range | null} functionRange function range
* @param {Range | null} objectRange object range
* @param {boolean | null} namedModule true, when define is called with a name
*/
constructor(range, arrayRange, functionRange, objectRange, namedModule) {
super();

View File

@ -16,11 +16,20 @@ const DynamicExports = require("./DynamicExports");
const LocalModuleDependency = require("./LocalModuleDependency");
const { addLocalModule, getLocalModule } = require("./LocalModulesHelpers");
/** @typedef {import("estree").ArrowFunctionExpression} ArrowFunctionExpression */
/** @typedef {import("estree").CallExpression} CallExpression */
/** @typedef {import("estree").Expression} Expression */
/** @typedef {import("estree").FunctionExpression} FunctionExpression */
/** @typedef {import("estree").Literal} Literal */
/** @typedef {import("estree").SpreadElement} SpreadElement */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
/**
* @param {CallExpression} expr expression
* @param {Expression | SpreadElement} expr expression
* @returns {boolean} true if it's a bound function expression
*/
const isBoundFunctionExpression = expr => {
@ -33,12 +42,22 @@ const isBoundFunctionExpression = expr => {
return true;
};
/** @typedef {FunctionExpression | ArrowFunctionExpression} UnboundFunctionExpression */
/**
* @param {Expression | SpreadElement} expr expression
* @returns {boolean} true when unbound function expression
*/
const isUnboundFunctionExpression = expr => {
if (expr.type === "FunctionExpression") return true;
if (expr.type === "ArrowFunctionExpression") return true;
return false;
};
/**
* @param {Expression | SpreadElement} expr expression
* @returns {boolean} true when callable
*/
const isCallable = expr => {
if (isUnboundFunctionExpression(expr)) return true;
if (isBoundFunctionExpression(expr)) return true;
@ -46,6 +65,9 @@ const isCallable = expr => {
};
class AMDDefineDependencyParserPlugin {
/**
* @param {JavascriptParserOptions} options parserOptions
*/
constructor(options) {
this.options = options;
}
@ -63,12 +85,23 @@ class AMDDefineDependencyParserPlugin {
);
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @param {BasicEvaluatedExpression} param param
* @param {Record<number, string>} identifiers identifiers
* @param {string=} namedModule named module
* @returns {boolean | undefined} result
*/
processArray(parser, expr, param, identifiers, namedModule) {
if (param.isArray()) {
param.items.forEach((param, idx) => {
/** @type {BasicEvaluatedExpression[]} */
(param.items).forEach((param, idx) => {
if (
param.isString() &&
["require", "module", "exports"].includes(param.string)
["require", "module", "exports"].includes(
/** @type {string} */ (param.string)
)
)
identifiers[idx] = param.string;
const result = this.processItem(parser, expr, param, namedModule);
@ -78,6 +111,7 @@ class AMDDefineDependencyParserPlugin {
});
return true;
} else if (param.isConstArray()) {
/** @type {(string | LocalModuleDependency | AMDRequireItemDependency)[]} */
const deps = [];
param.array.forEach((request, idx) => {
let dep;
@ -91,26 +125,38 @@ class AMDDefineDependencyParserPlugin {
} else if ((localModule = getLocalModule(parser.state, request))) {
localModule.flagUsed();
dep = new LocalModuleDependency(localModule, undefined, false);
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
parser.state.module.addPresentationalDependency(dep);
} else {
dep = this.newRequireItemDependency(request);
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
}
deps.push(dep);
});
const dep = this.newRequireArrayDependency(deps, param.range);
dep.loc = expr.loc;
const dep = this.newRequireArrayDependency(
deps,
/** @type {Range} */ (param.range)
);
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.module.addPresentationalDependency(dep);
return true;
}
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @param {BasicEvaluatedExpression} param param
* @param {string=} namedModule named module
* @returns {boolean} result
*/
processItem(parser, expr, param, namedModule) {
if (param.isConditional()) {
param.options.forEach(param => {
/** @type {BasicEvaluatedExpression[]} */
(param.options).forEach(param => {
const result = this.processItem(parser, expr, param);
if (result === undefined) {
this.processContext(parser, expr, param);
@ -120,19 +166,29 @@ class AMDDefineDependencyParserPlugin {
} else if (param.isString()) {
let dep, localModule;
if (param.string === "require") {
dep = new ConstDependency(RuntimeGlobals.require, param.range, [
RuntimeGlobals.require
]);
dep = new ConstDependency(
RuntimeGlobals.require,
/** @type {Range} */ (param.range),
[RuntimeGlobals.require]
);
} else if (param.string === "exports") {
dep = new ConstDependency("exports", param.range, [
RuntimeGlobals.exports
]);
dep = new ConstDependency(
"exports",
/** @type {Range} */ (param.range),
[RuntimeGlobals.exports]
);
} else if (param.string === "module") {
dep = new ConstDependency("module", param.range, [
RuntimeGlobals.module
]);
dep = new ConstDependency(
"module",
/** @type {Range} */ (param.range),
[RuntimeGlobals.module]
);
} else if (
(localModule = getLocalModule(parser.state, param.string, namedModule))
(localModule = getLocalModule(
parser.state,
/** @type {string} */ (param.string),
namedModule
))
) {
localModule.flagUsed();
dep = new LocalModuleDependency(localModule, param.range, false);
@ -142,15 +198,22 @@ class AMDDefineDependencyParserPlugin {
parser.state.current.addDependency(dep);
return true;
}
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
parser.state.module.addPresentationalDependency(dep);
return true;
}
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @param {BasicEvaluatedExpression} param param
* @returns {boolean | undefined} result
*/
processContext(parser, expr, param) {
const dep = ContextDependencyHelpers.create(
AMDRequireContextDependency,
param.range,
/** @type {Range} */ (param.range),
param,
expr,
this.options,
@ -160,12 +223,17 @@ class AMDDefineDependencyParserPlugin {
parser
);
if (!dep) return;
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @returns {boolean | undefined} result
*/
processCallDefine(parser, expr) {
let array, fn, obj, namedModule;
switch (expr.arguments.length) {
@ -214,7 +282,7 @@ class AMDDefineDependencyParserPlugin {
break;
case 3:
// define("…", […], f() {…})
namedModule = expr.arguments[0].value;
namedModule = /** @type {TODO} */ (expr).arguments[0].value;
array = expr.arguments[1];
if (isCallable(expr.arguments[2])) {
// define("…", […], f() {})
@ -236,10 +304,10 @@ class AMDDefineDependencyParserPlugin {
let fnParamsOffset = 0;
if (fn) {
if (isUnboundFunctionExpression(fn)) {
fnParams = fn.params;
fnParams = /** @type {UnboundFunctionExpression} */ (fn).params;
} else if (isBoundFunctionExpression(fn)) {
fnParams = fn.callee.object.params;
fnParamsOffset = fn.arguments.length - 1;
fnParams = /** @type {TODO} */ (fn).callee.object.params;
fnParamsOffset = /** @type {TODO} */ (fn).arguments.length - 1;
if (fnParamsOffset < 0) {
fnParamsOffset = 0;
}
@ -247,6 +315,7 @@ class AMDDefineDependencyParserPlugin {
}
let fnRenames = new Map();
if (array) {
/** @type {Record<number, string>} */
const identifiers = {};
const param = parser.evaluateExpression(array);
const result = this.processArray(
@ -278,6 +347,7 @@ class AMDDefineDependencyParserPlugin {
});
}
}
/** @type {boolean | undefined} */
let inTry;
if (fn && isUnboundFunctionExpression(fn)) {
inTry = parser.scope.inTry;
@ -285,7 +355,7 @@ class AMDDefineDependencyParserPlugin {
for (const [name, varInfo] of fnRenames) {
parser.setVariable(name, varInfo);
}
parser.scope.inTry = inTry;
parser.scope.inTry = /** @type {boolean} */ (inTry);
if (fn.body.type === "BlockStatement") {
parser.detectMode(fn.body.body);
const prev = parser.prevStatement;
@ -299,7 +369,8 @@ class AMDDefineDependencyParserPlugin {
} else if (fn && isBoundFunctionExpression(fn)) {
inTry = parser.scope.inTry;
parser.inScope(
fn.callee.object.params.filter(
/** @type {TODO} */
(fn).callee.object.params.filter(
i => !["require", "module", "exports"].includes(i.name)
),
() => {
@ -318,21 +389,21 @@ class AMDDefineDependencyParserPlugin {
}
}
);
if (fn.arguments) {
parser.walkExpressions(fn.arguments);
if (/** @type {TODO} */ (fn).arguments) {
parser.walkExpressions(/** @type {TODO} */ (fn).arguments);
}
} else if (fn || obj) {
parser.walkExpression(fn || obj);
}
const dep = this.newDefineDependency(
expr.range,
array ? array.range : null,
fn ? fn.range : null,
obj ? obj.range : null,
/** @type {Range} */ (expr.range),
array ? /** @type {Range} */ (array.range) : null,
fn ? /** @type {Range} */ (fn.range) : null,
obj ? /** @type {Range} */ (obj.range) : null,
namedModule ? namedModule : null
);
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
if (namedModule) {
dep.localModule = addLocalModule(parser.state, namedModule);
}
@ -340,6 +411,14 @@ class AMDDefineDependencyParserPlugin {
return true;
}
/**
* @param {Range} range range
* @param {Range | null} arrayRange array range
* @param {Range | null} functionRange function range
* @param {Range | null} objectRange object range
* @param {boolean | null} namedModule true, when define is called with a name
* @returns {AMDDefineDependency} AMDDefineDependency
*/
newDefineDependency(
range,
arrayRange,
@ -355,11 +434,24 @@ class AMDDefineDependencyParserPlugin {
namedModule
);
}
/**
* @param {TODO[]} depsArray deps array
* @param {Range} range range
* @returns {AMDRequireArrayDependency} AMDRequireArrayDependency
*/
newRequireArrayDependency(depsArray, range) {
return new AMDRequireArrayDependency(depsArray, range);
}
/**
* @param {string} request request
* @param {Range=} range range
* @returns {AMDRequireItemDependency} AMDRequireItemDependency
*/
newRequireItemDependency(request, range) {
return new AMDRequireItemDependency(request, range);
}
}
module.exports = AMDDefineDependencyParserPlugin;

View File

@ -15,10 +15,12 @@ const NullDependency = require("./NullDependency");
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {import("./AMDRequireItemDependency")} AMDRequireItemDependency */
/** @typedef {import("./LocalModuleDependency")} LocalModuleDependency */
class AMDRequireArrayDependency extends NullDependency {
/**
* @param {TODO[]} depsArray deps array
* @param {(string | LocalModuleDependency | AMDRequireItemDependency)[]} depsArray deps array
* @param {Range} range range
*/
constructor(depsArray, range) {

View File

@ -19,20 +19,28 @@ const { getLocalModule } = require("./LocalModulesHelpers");
const UnsupportedDependency = require("./UnsupportedDependency");
const getFunctionExpression = require("./getFunctionExpression");
/** @typedef {import("estree").CallExpression} CallExpression */
/** @typedef {import("estree").Expression} Expression */
/** @typedef {import("estree").SourceLocation} SourceLocation */
/** @typedef {import("estree").SpreadElement} SpreadElement */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("../Module").BuildInfo} BuildInfo */
/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
class AMDRequireDependenciesBlockParserPlugin {
/**
* @param {JavascriptParserOptions} options parserOptions
*/
constructor(options) {
this.options = options;
}
/**
* @param {JavascriptParser} parser the parser
* @param {Expression} expression expression
* @param {Expression | SpreadElement} expression expression
* @returns {boolean} need bind this
*/
processFunctionArgument(parser, expression) {
@ -74,9 +82,15 @@ class AMDRequireDependenciesBlockParserPlugin {
);
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @param {BasicEvaluatedExpression} param param
* @returns {boolean | undefined} result
*/
processArray(parser, expr, param) {
if (param.isArray()) {
for (const p of param.items) {
for (const p of /** @type {BasicEvaluatedExpression[]} */ (param.items)) {
const result = this.processItem(parser, expr, p);
if (result === undefined) {
this.processContext(parser, expr, p);
@ -84,8 +98,9 @@ class AMDRequireDependenciesBlockParserPlugin {
}
return true;
} else if (param.isConstArray()) {
/** @type {(string | LocalModuleDependency | AMDRequireItemDependency)[]} */
const deps = [];
for (const request of param.array) {
for (const request of /** @type {any[]} */ (param.array)) {
let dep, localModule;
if (request === "require") {
dep = RuntimeGlobals.require;
@ -94,26 +109,38 @@ class AMDRequireDependenciesBlockParserPlugin {
} else if ((localModule = getLocalModule(parser.state, request))) {
localModule.flagUsed();
dep = new LocalModuleDependency(localModule, undefined, false);
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
parser.state.module.addPresentationalDependency(dep);
} else {
dep = this.newRequireItemDependency(request);
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
}
deps.push(dep);
}
const dep = this.newRequireArrayDependency(deps, param.range);
dep.loc = expr.loc;
const dep = this.newRequireArrayDependency(
deps,
/** @type {Range} */ (param.range)
);
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.module.addPresentationalDependency(dep);
return true;
}
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @param {BasicEvaluatedExpression} param param
* @returns {boolean | undefined} result
*/
processItem(parser, expr, param) {
if (param.isConditional()) {
for (const p of param.options) {
for (const p of /** @type {BasicEvaluatedExpression[]} */ (
param.options
)) {
const result = this.processItem(parser, expr, p);
if (result === undefined) {
this.processContext(parser, expr, p);
@ -123,40 +150,59 @@ class AMDRequireDependenciesBlockParserPlugin {
} else if (param.isString()) {
let dep, localModule;
if (param.string === "require") {
dep = new ConstDependency(RuntimeGlobals.require, param.string, [
RuntimeGlobals.require
]);
dep = new ConstDependency(
RuntimeGlobals.require,
/** @type {TODO} */ (param.string),
[RuntimeGlobals.require]
);
} else if (param.string === "module") {
dep = new ConstDependency(
parser.state.module.buildInfo.moduleArgument,
param.range,
/** @type {BuildInfo} */
(parser.state.module.buildInfo).moduleArgument,
/** @type {Range} */ (param.range),
[RuntimeGlobals.module]
);
} else if (param.string === "exports") {
dep = new ConstDependency(
parser.state.module.buildInfo.exportsArgument,
param.range,
/** @type {BuildInfo} */
(parser.state.module.buildInfo).exportsArgument,
/** @type {Range} */ (param.range),
[RuntimeGlobals.exports]
);
} else if ((localModule = getLocalModule(parser.state, param.string))) {
} else if (
(localModule = getLocalModule(
parser.state,
/** @type {string} */ (param.string)
))
) {
localModule.flagUsed();
dep = new LocalModuleDependency(localModule, param.range, false);
} else {
dep = this.newRequireItemDependency(param.string, param.range);
dep.loc = expr.loc;
dep = this.newRequireItemDependency(
/** @type {string} */ (param.string),
param.range
);
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
parser.state.module.addPresentationalDependency(dep);
return true;
}
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @param {BasicEvaluatedExpression} param param
* @returns {boolean | undefined} result
*/
processContext(parser, expr, param) {
const dep = ContextDependencyHelpers.create(
AMDRequireContextDependency,
param.range,
/** @type {Range} */ (param.range),
param,
expr,
this.options,
@ -166,38 +212,55 @@ class AMDRequireDependenciesBlockParserPlugin {
parser
);
if (!dep) return;
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
/**
* @param {BasicEvaluatedExpression} param param
* @returns {string | undefined} result
*/
processArrayForRequestString(param) {
if (param.isArray()) {
const result = param.items.map(item =>
this.processItemForRequestString(item)
);
const result =
/** @type {BasicEvaluatedExpression[]} */
(param.items).map(item => this.processItemForRequestString(item));
if (result.every(Boolean)) return result.join(" ");
} else if (param.isConstArray()) {
return param.array.join(" ");
return /** @type {string[]} */ (param.array).join(" ");
}
}
/**
* @param {BasicEvaluatedExpression} param param
* @returns {string | undefined} result
*/
processItemForRequestString(param) {
if (param.isConditional()) {
const result = param.options.map(item =>
this.processItemForRequestString(item)
);
const result =
/** @type {BasicEvaluatedExpression[]} */
(param.options).map(item => this.processItemForRequestString(item));
if (result.every(Boolean)) return result.join("|");
} else if (param.isString()) {
return param.string;
}
}
/**
* @param {JavascriptParser} parser the parser
* @param {CallExpression} expr call expression
* @returns {boolean | undefined} result
*/
processCallRequire(parser, expr) {
/** @type {BasicEvaluatedExpression | undefined} */
let param;
/** @type {AMDRequireDependenciesBlock | undefined | null} */
let depBlock;
/** @type {AMDRequireDependency | undefined} */
let dep;
/** @type {boolean | undefined} */
let result;
const old = parser.state.current;
@ -205,57 +268,76 @@ class AMDRequireDependenciesBlockParserPlugin {
if (expr.arguments.length >= 1) {
param = parser.evaluateExpression(expr.arguments[0]);
depBlock = this.newRequireDependenciesBlock(
expr.loc,
this.processArrayForRequestString(param)
/** @type {DependencyLocation} */ (expr.loc),
/** @type {string} */ (this.processArrayForRequestString(param))
);
dep = this.newRequireDependency(
expr.range,
param.range,
expr.arguments.length > 1 ? expr.arguments[1].range : null,
expr.arguments.length > 2 ? expr.arguments[2].range : null
/** @type {Range} */ (expr.range),
/** @type {Range} */ (param.range),
expr.arguments.length > 1
? /** @type {Range} */ (expr.arguments[1].range)
: null,
expr.arguments.length > 2
? /** @type {Range} */ (expr.arguments[2].range)
: null
);
dep.loc = expr.loc;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
depBlock.addDependency(dep);
parser.state.current = depBlock;
parser.state.current = /** @type {TODO} */ (depBlock);
}
if (expr.arguments.length === 1) {
parser.inScope([], () => {
result = this.processArray(parser, expr, param);
result = this.processArray(
parser,
expr,
/** @type {BasicEvaluatedExpression} */ (param)
);
});
parser.state.current = old;
if (!result) return;
parser.state.current.addBlock(depBlock);
parser.state.current.addBlock(
/** @type {AMDRequireDependenciesBlock} */ (depBlock)
);
return true;
}
if (expr.arguments.length === 2 || expr.arguments.length === 3) {
try {
parser.inScope([], () => {
result = this.processArray(parser, expr, param);
result = this.processArray(
parser,
expr,
/** @type {BasicEvaluatedExpression} */ (param)
);
});
if (!result) {
const dep = new UnsupportedDependency("unsupported", expr.range);
const dep = new UnsupportedDependency(
"unsupported",
/** @type {Range} */ (expr.range)
);
old.addPresentationalDependency(dep);
if (parser.state.module) {
parser.state.module.addError(
new UnsupportedFeatureWarning(
"Cannot statically analyse 'require(…, …)' in line " +
expr.loc.start.line,
expr.loc
/** @type {SourceLocation} */ (expr.loc).start.line,
/** @type {DependencyLocation} */ (expr.loc)
)
);
}
depBlock = null;
return true;
}
dep.functionBindThis = this.processFunctionArgument(
/** @type {AMDRequireDependency} */
(dep).functionBindThis = this.processFunctionArgument(
parser,
expr.arguments[1]
);
if (expr.arguments.length === 3) {
dep.errorCallbackBindThis = this.processFunctionArgument(
/** @type {AMDRequireDependency} */
(dep).errorCallbackBindThis = this.processFunctionArgument(
parser,
expr.arguments[2]
);
@ -280,8 +362,8 @@ class AMDRequireDependenciesBlockParserPlugin {
/**
* @param {Range} outerRange outer range
* @param {Range} arrayRange array range
* @param {Range} functionRange function range
* @param {Range} errorCallbackRange error callback range
* @param {Range | null} functionRange function range
* @param {Range | null} errorCallbackRange error callback range
* @returns {AMDRequireDependency} dependency
*/
newRequireDependency(
@ -308,7 +390,7 @@ class AMDRequireDependenciesBlockParserPlugin {
}
/**
* @param {TODO[]} depsArray deps array
* @param {(string | LocalModuleDependency | AMDRequireItemDependency)[]} depsArray deps array
* @param {Range} range range
* @returns {AMDRequireArrayDependency} AMDRequireArrayDependency
*/

View File

@ -21,8 +21,8 @@ class AMDRequireDependency extends NullDependency {
/**
* @param {Range} outerRange outer range
* @param {Range} arrayRange array range
* @param {Range} functionRange function range
* @param {Range} errorCallbackRange error callback range
* @param {Range | null} functionRange function range
* @param {Range | null} errorCallbackRange error callback range
*/
constructor(outerRange, arrayRange, functionRange, errorCallbackRange) {
super();

View File

@ -9,7 +9,7 @@
/** @typedef {import("estree").SpreadElement} SpreadElement */
/**
* @param {Expression} expr expressions
* @param {Expression | SpreadElement} expr expressions
* @returns {{fn: TODO, expressions: (Expression | SpreadElement)[], needThis: boolean | undefined } | undefined} function expression with additional information
*/
module.exports = expr => {