12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027 |
- import { getKeys, KEYS } from 'eslint-visitor-keys';
- function getInnermostScope(initialScope, node) {
- const location = node.range[0];
- let scope = initialScope;
- let found = false;
- do {
- found = false;
- for (const childScope of scope.childScopes) {
- const range = childScope.block.range;
- if (range[0] <= location && location < range[1]) {
- scope = childScope;
- found = true;
- break
- }
- }
- } while (found)
- return scope
- }
- function findVariable(initialScope, nameOrNode) {
- let name = "";
- let scope = initialScope;
- if (typeof nameOrNode === "string") {
- name = nameOrNode;
- } else {
- name = nameOrNode.name;
- scope = getInnermostScope(scope, nameOrNode);
- }
- while (scope != null) {
- const variable = scope.set.get(name);
- if (variable != null) {
- return variable
- }
- scope = scope.upper;
- }
- return null
- }
- function negate0(token) {
- return !this(token)
- }
- function negate(f) {
- return negate0.bind(f)
- }
- function isPunctuatorTokenWithValue(token, value) {
- return token.type === "Punctuator" && token.value === value
- }
- function isArrowToken(token) {
- return isPunctuatorTokenWithValue(token, "=>")
- }
- function isCommaToken(token) {
- return isPunctuatorTokenWithValue(token, ",")
- }
- function isSemicolonToken(token) {
- return isPunctuatorTokenWithValue(token, ";")
- }
- function isColonToken(token) {
- return isPunctuatorTokenWithValue(token, ":")
- }
- function isOpeningParenToken(token) {
- return isPunctuatorTokenWithValue(token, "(")
- }
- function isClosingParenToken(token) {
- return isPunctuatorTokenWithValue(token, ")")
- }
- function isOpeningBracketToken(token) {
- return isPunctuatorTokenWithValue(token, "[")
- }
- function isClosingBracketToken(token) {
- return isPunctuatorTokenWithValue(token, "]")
- }
- function isOpeningBraceToken(token) {
- return isPunctuatorTokenWithValue(token, "{")
- }
- function isClosingBraceToken(token) {
- return isPunctuatorTokenWithValue(token, "}")
- }
- function isCommentToken(token) {
- return ["Block", "Line", "Shebang"].includes(token.type)
- }
- const isNotArrowToken = negate(isArrowToken);
- const isNotCommaToken = negate(isCommaToken);
- const isNotSemicolonToken = negate(isSemicolonToken);
- const isNotColonToken = negate(isColonToken);
- const isNotOpeningParenToken = negate(isOpeningParenToken);
- const isNotClosingParenToken = negate(isClosingParenToken);
- const isNotOpeningBracketToken = negate(isOpeningBracketToken);
- const isNotClosingBracketToken = negate(isClosingBracketToken);
- const isNotOpeningBraceToken = negate(isOpeningBraceToken);
- const isNotClosingBraceToken = negate(isClosingBraceToken);
- const isNotCommentToken = negate(isCommentToken);
- function getOpeningParenOfParams(node, sourceCode) {
- return node.id
- ? sourceCode.getTokenAfter(node.id, isOpeningParenToken)
- : sourceCode.getFirstToken(node, isOpeningParenToken)
- }
- function getFunctionHeadLocation(node, sourceCode) {
- const parent = node.parent;
- let start = null;
- let end = null;
- if (node.type === "ArrowFunctionExpression") {
- const arrowToken = sourceCode.getTokenBefore(node.body, isArrowToken);
- start = arrowToken.loc.start;
- end = arrowToken.loc.end;
- } else if (
- parent.type === "Property" ||
- parent.type === "MethodDefinition" ||
- parent.type === "PropertyDefinition"
- ) {
- start = parent.loc.start;
- end = getOpeningParenOfParams(node, sourceCode).loc.start;
- } else {
- start = node.loc.start;
- end = getOpeningParenOfParams(node, sourceCode).loc.start;
- }
- return {
- start: { ...start },
- end: { ...end },
- }
- }
- const globalObject =
- typeof globalThis !== "undefined"
- ? globalThis
- : typeof self !== "undefined"
- ? self
- : typeof window !== "undefined"
- ? window
- : typeof global !== "undefined"
- ? global
- : {};
- const builtinNames = Object.freeze(
- new Set([
- "Array",
- "ArrayBuffer",
- "BigInt",
- "BigInt64Array",
- "BigUint64Array",
- "Boolean",
- "DataView",
- "Date",
- "decodeURI",
- "decodeURIComponent",
- "encodeURI",
- "encodeURIComponent",
- "escape",
- "Float32Array",
- "Float64Array",
- "Function",
- "Infinity",
- "Int16Array",
- "Int32Array",
- "Int8Array",
- "isFinite",
- "isNaN",
- "isPrototypeOf",
- "JSON",
- "Map",
- "Math",
- "NaN",
- "Number",
- "Object",
- "parseFloat",
- "parseInt",
- "Promise",
- "Proxy",
- "Reflect",
- "RegExp",
- "Set",
- "String",
- "Symbol",
- "Uint16Array",
- "Uint32Array",
- "Uint8Array",
- "Uint8ClampedArray",
- "undefined",
- "unescape",
- "WeakMap",
- "WeakSet",
- ]),
- );
- const callAllowed = new Set(
- [
- Array.isArray,
- Array.of,
- Array.prototype.at,
- Array.prototype.concat,
- Array.prototype.entries,
- Array.prototype.every,
- Array.prototype.filter,
- Array.prototype.find,
- Array.prototype.findIndex,
- Array.prototype.flat,
- Array.prototype.includes,
- Array.prototype.indexOf,
- Array.prototype.join,
- Array.prototype.keys,
- Array.prototype.lastIndexOf,
- Array.prototype.slice,
- Array.prototype.some,
- Array.prototype.toString,
- Array.prototype.values,
- typeof BigInt === "function" ? BigInt : undefined,
- Boolean,
- Date,
- Date.parse,
- decodeURI,
- decodeURIComponent,
- encodeURI,
- encodeURIComponent,
- escape,
- isFinite,
- isNaN,
- isPrototypeOf,
- Map,
- Map.prototype.entries,
- Map.prototype.get,
- Map.prototype.has,
- Map.prototype.keys,
- Map.prototype.values,
- ...Object.getOwnPropertyNames(Math)
- .filter((k) => k !== "random")
- .map((k) => Math[k])
- .filter((f) => typeof f === "function"),
- Number,
- Number.isFinite,
- Number.isNaN,
- Number.parseFloat,
- Number.parseInt,
- Number.prototype.toExponential,
- Number.prototype.toFixed,
- Number.prototype.toPrecision,
- Number.prototype.toString,
- Object,
- Object.entries,
- Object.is,
- Object.isExtensible,
- Object.isFrozen,
- Object.isSealed,
- Object.keys,
- Object.values,
- parseFloat,
- parseInt,
- RegExp,
- Set,
- Set.prototype.entries,
- Set.prototype.has,
- Set.prototype.keys,
- Set.prototype.values,
- String,
- String.fromCharCode,
- String.fromCodePoint,
- String.raw,
- String.prototype.at,
- String.prototype.charAt,
- String.prototype.charCodeAt,
- String.prototype.codePointAt,
- String.prototype.concat,
- String.prototype.endsWith,
- String.prototype.includes,
- String.prototype.indexOf,
- String.prototype.lastIndexOf,
- String.prototype.normalize,
- String.prototype.padEnd,
- String.prototype.padStart,
- String.prototype.slice,
- String.prototype.startsWith,
- String.prototype.substr,
- String.prototype.substring,
- String.prototype.toLowerCase,
- String.prototype.toString,
- String.prototype.toUpperCase,
- String.prototype.trim,
- String.prototype.trimEnd,
- String.prototype.trimLeft,
- String.prototype.trimRight,
- String.prototype.trimStart,
- Symbol.for,
- Symbol.keyFor,
- unescape,
- ].filter((f) => typeof f === "function"),
- );
- const callPassThrough = new Set([
- Object.freeze,
- Object.preventExtensions,
- Object.seal,
- ]);
- const getterAllowed = [
- [Map, new Set(["size"])],
- [
- RegExp,
- new Set([
- "dotAll",
- "flags",
- "global",
- "hasIndices",
- "ignoreCase",
- "multiline",
- "source",
- "sticky",
- "unicode",
- ]),
- ],
- [Set, new Set(["size"])],
- ];
- function getPropertyDescriptor(object, name) {
- let x = object;
- while ((typeof x === "object" || typeof x === "function") && x !== null) {
- const d = Object.getOwnPropertyDescriptor(x, name);
- if (d) {
- return d
- }
- x = Object.getPrototypeOf(x);
- }
- return null
- }
- function isGetter(object, name) {
- const d = getPropertyDescriptor(object, name);
- return d != null && d.get != null
- }
- function getElementValues(nodeList, initialScope) {
- const valueList = [];
- for (let i = 0; i < nodeList.length; ++i) {
- const elementNode = nodeList[i];
- if (elementNode == null) {
- valueList.length = i + 1;
- } else if (elementNode.type === "SpreadElement") {
- const argument = getStaticValueR(elementNode.argument, initialScope);
- if (argument == null) {
- return null
- }
- valueList.push(...argument.value);
- } else {
- const element = getStaticValueR(elementNode, initialScope);
- if (element == null) {
- return null
- }
- valueList.push(element.value);
- }
- }
- return valueList
- }
- function isEffectivelyConst(variable) {
- const refs = variable.references;
- const inits = refs.filter((r) => r.init).length;
- const reads = refs.filter((r) => r.isReadOnly()).length;
- if (inits === 1 && reads + inits === refs.length) {
-
- return true
- }
- return false
- }
- const operations = Object.freeze({
- ArrayExpression(node, initialScope) {
- const elements = getElementValues(node.elements, initialScope);
- return elements != null ? { value: elements } : null
- },
- AssignmentExpression(node, initialScope) {
- if (node.operator === "=") {
- return getStaticValueR(node.right, initialScope)
- }
- return null
- },
-
- BinaryExpression(node, initialScope) {
- if (node.operator === "in" || node.operator === "instanceof") {
-
- return null
- }
- const left = getStaticValueR(node.left, initialScope);
- const right = getStaticValueR(node.right, initialScope);
- if (left != null && right != null) {
- switch (node.operator) {
- case "==":
- return { value: left.value == right.value }
- case "!=":
- return { value: left.value != right.value }
- case "===":
- return { value: left.value === right.value }
- case "!==":
- return { value: left.value !== right.value }
- case "<":
- return { value: left.value < right.value }
- case "<=":
- return { value: left.value <= right.value }
- case ">":
- return { value: left.value > right.value }
- case ">=":
- return { value: left.value >= right.value }
- case "<<":
- return { value: left.value << right.value }
- case ">>":
- return { value: left.value >> right.value }
- case ">>>":
- return { value: left.value >>> right.value }
- case "+":
- return { value: left.value + right.value }
- case "-":
- return { value: left.value - right.value }
- case "*":
- return { value: left.value * right.value }
- case "/":
- return { value: left.value / right.value }
- case "%":
- return { value: left.value % right.value }
- case "**":
- return { value: left.value ** right.value }
- case "|":
- return { value: left.value | right.value }
- case "^":
- return { value: left.value ^ right.value }
- case "&":
- return { value: left.value & right.value }
-
- }
- }
- return null
- },
- CallExpression(node, initialScope) {
- const calleeNode = node.callee;
- const args = getElementValues(node.arguments, initialScope);
- if (args != null) {
- if (calleeNode.type === "MemberExpression") {
- if (calleeNode.property.type === "PrivateIdentifier") {
- return null
- }
- const object = getStaticValueR(calleeNode.object, initialScope);
- if (object != null) {
- if (
- object.value == null &&
- (object.optional || node.optional)
- ) {
- return { value: undefined, optional: true }
- }
- const property = getStaticPropertyNameValue(
- calleeNode,
- initialScope,
- );
- if (property != null) {
- const receiver = object.value;
- const methodName = property.value;
- if (callAllowed.has(receiver[methodName])) {
- return { value: receiver[methodName](...args) }
- }
- if (callPassThrough.has(receiver[methodName])) {
- return { value: args[0] }
- }
- }
- }
- } else {
- const callee = getStaticValueR(calleeNode, initialScope);
- if (callee != null) {
- if (callee.value == null && node.optional) {
- return { value: undefined, optional: true }
- }
- const func = callee.value;
- if (callAllowed.has(func)) {
- return { value: func(...args) }
- }
- if (callPassThrough.has(func)) {
- return { value: args[0] }
- }
- }
- }
- }
- return null
- },
- ConditionalExpression(node, initialScope) {
- const test = getStaticValueR(node.test, initialScope);
- if (test != null) {
- return test.value
- ? getStaticValueR(node.consequent, initialScope)
- : getStaticValueR(node.alternate, initialScope)
- }
- return null
- },
- ExpressionStatement(node, initialScope) {
- return getStaticValueR(node.expression, initialScope)
- },
- Identifier(node, initialScope) {
- if (initialScope != null) {
- const variable = findVariable(initialScope, node);
-
- if (
- variable != null &&
- variable.defs.length === 0 &&
- builtinNames.has(variable.name) &&
- variable.name in globalObject
- ) {
- return { value: globalObject[variable.name] }
- }
-
- if (variable != null && variable.defs.length === 1) {
- const def = variable.defs[0];
- if (
- def.parent &&
- def.type === "Variable" &&
- (def.parent.kind === "const" ||
- isEffectivelyConst(variable)) &&
-
- def.node.id.type === "Identifier"
- ) {
- return getStaticValueR(def.node.init, initialScope)
- }
- }
- }
- return null
- },
- Literal(node) {
-
- if ((node.regex != null || node.bigint != null) && node.value == null) {
-
- return null
- }
- return { value: node.value }
- },
- LogicalExpression(node, initialScope) {
- const left = getStaticValueR(node.left, initialScope);
- if (left != null) {
- if (
- (node.operator === "||" && Boolean(left.value) === true) ||
- (node.operator === "&&" && Boolean(left.value) === false) ||
- (node.operator === "??" && left.value != null)
- ) {
- return left
- }
- const right = getStaticValueR(node.right, initialScope);
- if (right != null) {
- return right
- }
- }
- return null
- },
- MemberExpression(node, initialScope) {
- if (node.property.type === "PrivateIdentifier") {
- return null
- }
- const object = getStaticValueR(node.object, initialScope);
- if (object != null) {
- if (object.value == null && (object.optional || node.optional)) {
- return { value: undefined, optional: true }
- }
- const property = getStaticPropertyNameValue(node, initialScope);
- if (property != null) {
- if (!isGetter(object.value, property.value)) {
- return { value: object.value[property.value] }
- }
- for (const [classFn, allowed] of getterAllowed) {
- if (
- object.value instanceof classFn &&
- allowed.has(property.value)
- ) {
- return { value: object.value[property.value] }
- }
- }
- }
- }
- return null
- },
- ChainExpression(node, initialScope) {
- const expression = getStaticValueR(node.expression, initialScope);
- if (expression != null) {
- return { value: expression.value }
- }
- return null
- },
- NewExpression(node, initialScope) {
- const callee = getStaticValueR(node.callee, initialScope);
- const args = getElementValues(node.arguments, initialScope);
- if (callee != null && args != null) {
- const Func = callee.value;
- if (callAllowed.has(Func)) {
- return { value: new Func(...args) }
- }
- }
- return null
- },
- ObjectExpression(node, initialScope) {
- const object = {};
- for (const propertyNode of node.properties) {
- if (propertyNode.type === "Property") {
- if (propertyNode.kind !== "init") {
- return null
- }
- const key = getStaticPropertyNameValue(
- propertyNode,
- initialScope,
- );
- const value = getStaticValueR(propertyNode.value, initialScope);
- if (key == null || value == null) {
- return null
- }
- object[key.value] = value.value;
- } else if (
- propertyNode.type === "SpreadElement" ||
- propertyNode.type === "ExperimentalSpreadProperty"
- ) {
- const argument = getStaticValueR(
- propertyNode.argument,
- initialScope,
- );
- if (argument == null) {
- return null
- }
- Object.assign(object, argument.value);
- } else {
- return null
- }
- }
- return { value: object }
- },
- SequenceExpression(node, initialScope) {
- const last = node.expressions[node.expressions.length - 1];
- return getStaticValueR(last, initialScope)
- },
- TaggedTemplateExpression(node, initialScope) {
- const tag = getStaticValueR(node.tag, initialScope);
- const expressions = getElementValues(
- node.quasi.expressions,
- initialScope,
- );
- if (tag != null && expressions != null) {
- const func = tag.value;
- const strings = node.quasi.quasis.map((q) => q.value.cooked);
- strings.raw = node.quasi.quasis.map((q) => q.value.raw);
- if (func === String.raw) {
- return { value: func(strings, ...expressions) }
- }
- }
- return null
- },
- TemplateLiteral(node, initialScope) {
- const expressions = getElementValues(node.expressions, initialScope);
- if (expressions != null) {
- let value = node.quasis[0].value.cooked;
- for (let i = 0; i < expressions.length; ++i) {
- value += expressions[i];
- value += node.quasis[i + 1].value.cooked;
- }
- return { value }
- }
- return null
- },
- UnaryExpression(node, initialScope) {
- if (node.operator === "delete") {
-
- return null
- }
- if (node.operator === "void") {
- return { value: undefined }
- }
- const arg = getStaticValueR(node.argument, initialScope);
- if (arg != null) {
- switch (node.operator) {
- case "-":
- return { value: -arg.value }
- case "+":
- return { value: +arg.value }
- case "!":
- return { value: !arg.value }
- case "~":
- return { value: ~arg.value }
- case "typeof":
- return { value: typeof arg.value }
-
- }
- }
- return null
- },
- });
- function getStaticValueR(node, initialScope) {
- if (node != null && Object.hasOwnProperty.call(operations, node.type)) {
- return operations[node.type](node, initialScope)
- }
- return null
- }
- function getStaticPropertyNameValue(node, initialScope) {
- const nameNode = node.type === "Property" ? node.key : node.property;
- if (node.computed) {
- return getStaticValueR(nameNode, initialScope)
- }
- if (nameNode.type === "Identifier") {
- return { value: nameNode.name }
- }
- if (nameNode.type === "Literal") {
- if (nameNode.bigint) {
- return { value: nameNode.bigint }
- }
- return { value: String(nameNode.value) }
- }
- return null
- }
- function getStaticValue(node, initialScope = null) {
- try {
- return getStaticValueR(node, initialScope)
- } catch (_error) {
- return null
- }
- }
- function getStringIfConstant(node, initialScope = null) {
-
- if (node && node.type === "Literal" && node.value === null) {
- if (node.regex) {
- return `/${node.regex.pattern}/${node.regex.flags}`
- }
- if (node.bigint) {
- return node.bigint
- }
- }
- const evaluated = getStaticValue(node, initialScope);
- return evaluated && String(evaluated.value)
- }
- function getPropertyName(node, initialScope) {
- switch (node.type) {
- case "MemberExpression":
- if (node.computed) {
- return getStringIfConstant(node.property, initialScope)
- }
- if (node.property.type === "PrivateIdentifier") {
- return null
- }
- return node.property.name
- case "Property":
- case "MethodDefinition":
- case "PropertyDefinition":
- if (node.computed) {
- return getStringIfConstant(node.key, initialScope)
- }
- if (node.key.type === "Literal") {
- return String(node.key.value)
- }
- if (node.key.type === "PrivateIdentifier") {
- return null
- }
- return node.key.name
-
- }
- return null
- }
- function getFunctionNameWithKind(node, sourceCode) {
- const parent = node.parent;
- const tokens = [];
- const isObjectMethod = parent.type === "Property" && parent.value === node;
- const isClassMethod =
- parent.type === "MethodDefinition" && parent.value === node;
- const isClassFieldMethod =
- parent.type === "PropertyDefinition" && parent.value === node;
-
- if (isClassMethod || isClassFieldMethod) {
- if (parent.static) {
- tokens.push("static");
- }
- if (parent.key.type === "PrivateIdentifier") {
- tokens.push("private");
- }
- }
- if (node.async) {
- tokens.push("async");
- }
- if (node.generator) {
- tokens.push("generator");
- }
-
- if (isObjectMethod || isClassMethod) {
- if (parent.kind === "constructor") {
- return "constructor"
- }
- if (parent.kind === "get") {
- tokens.push("getter");
- } else if (parent.kind === "set") {
- tokens.push("setter");
- } else {
- tokens.push("method");
- }
- } else if (isClassFieldMethod) {
- tokens.push("method");
- } else {
- if (node.type === "ArrowFunctionExpression") {
- tokens.push("arrow");
- }
- tokens.push("function");
- }
-
- if (isObjectMethod || isClassMethod || isClassFieldMethod) {
- if (parent.key.type === "PrivateIdentifier") {
- tokens.push(`#${parent.key.name}`);
- } else {
- const name = getPropertyName(parent);
- if (name) {
- tokens.push(`'${name}'`);
- } else if (sourceCode) {
- const keyText = sourceCode.getText(parent.key);
- if (!keyText.includes("\n")) {
- tokens.push(`[${keyText}]`);
- }
- }
- }
- } else if (node.id) {
- tokens.push(`'${node.id.name}'`);
- } else if (
- parent.type === "VariableDeclarator" &&
- parent.id &&
- parent.id.type === "Identifier"
- ) {
- tokens.push(`'${parent.id.name}'`);
- } else if (
- (parent.type === "AssignmentExpression" ||
- parent.type === "AssignmentPattern") &&
- parent.left &&
- parent.left.type === "Identifier"
- ) {
- tokens.push(`'${parent.left.name}'`);
- } else if (
- parent.type === "ExportDefaultDeclaration" &&
- parent.declaration === node
- ) {
- tokens.push("'default'");
- }
- return tokens.join(" ")
- }
- const typeConversionBinaryOps = Object.freeze(
- new Set([
- "==",
- "!=",
- "<",
- "<=",
- ">",
- ">=",
- "<<",
- ">>",
- ">>>",
- "+",
- "-",
- "*",
- "/",
- "%",
- "|",
- "^",
- "&",
- "in",
- ]),
- );
- const typeConversionUnaryOps = Object.freeze(new Set(["-", "+", "!", "~"]));
- function isNode(x) {
- return x !== null && typeof x === "object" && typeof x.type === "string"
- }
- const visitor = Object.freeze(
- Object.assign(Object.create(null), {
- $visit(node, options, visitorKeys) {
- const { type } = node;
- if (typeof this[type] === "function") {
- return this[type](node, options, visitorKeys)
- }
- return this.$visitChildren(node, options, visitorKeys)
- },
- $visitChildren(node, options, visitorKeys) {
- const { type } = node;
- for (const key of visitorKeys[type] || getKeys(node)) {
- const value = node[key];
- if (Array.isArray(value)) {
- for (const element of value) {
- if (
- isNode(element) &&
- this.$visit(element, options, visitorKeys)
- ) {
- return true
- }
- }
- } else if (
- isNode(value) &&
- this.$visit(value, options, visitorKeys)
- ) {
- return true
- }
- }
- return false
- },
- ArrowFunctionExpression() {
- return false
- },
- AssignmentExpression() {
- return true
- },
- AwaitExpression() {
- return true
- },
- BinaryExpression(node, options, visitorKeys) {
- if (
- options.considerImplicitTypeConversion &&
- typeConversionBinaryOps.has(node.operator) &&
- (node.left.type !== "Literal" || node.right.type !== "Literal")
- ) {
- return true
- }
- return this.$visitChildren(node, options, visitorKeys)
- },
- CallExpression() {
- return true
- },
- FunctionExpression() {
- return false
- },
- ImportExpression() {
- return true
- },
- MemberExpression(node, options, visitorKeys) {
- if (options.considerGetters) {
- return true
- }
- if (
- options.considerImplicitTypeConversion &&
- node.computed &&
- node.property.type !== "Literal"
- ) {
- return true
- }
- return this.$visitChildren(node, options, visitorKeys)
- },
- MethodDefinition(node, options, visitorKeys) {
- if (
- options.considerImplicitTypeConversion &&
- node.computed &&
- node.key.type !== "Literal"
- ) {
- return true
- }
- return this.$visitChildren(node, options, visitorKeys)
- },
- NewExpression() {
- return true
- },
- Property(node, options, visitorKeys) {
- if (
- options.considerImplicitTypeConversion &&
- node.computed &&
- node.key.type !== "Literal"
- ) {
- return true
- }
- return this.$visitChildren(node, options, visitorKeys)
- },
- PropertyDefinition(node, options, visitorKeys) {
- if (
- options.considerImplicitTypeConversion &&
- node.computed &&
- node.key.type !== "Literal"
- ) {
- return true
- }
- return this.$visitChildren(node, options, visitorKeys)
- },
- UnaryExpression(node, options, visitorKeys) {
- if (node.operator === "delete") {
- return true
- }
- if (
- options.considerImplicitTypeConversion &&
- typeConversionUnaryOps.has(node.operator) &&
- node.argument.type !== "Literal"
- ) {
- return true
- }
- return this.$visitChildren(node, options, visitorKeys)
- },
- UpdateExpression() {
- return true
- },
- YieldExpression() {
- return true
- },
- }),
- );
- function hasSideEffect(
- node,
- sourceCode,
- { considerGetters = false, considerImplicitTypeConversion = false } = {},
- ) {
- return visitor.$visit(
- node,
- { considerGetters, considerImplicitTypeConversion },
- sourceCode.visitorKeys || KEYS,
- )
- }
- function getParentSyntaxParen(node, sourceCode) {
- const parent = node.parent;
- switch (parent.type) {
- case "CallExpression":
- case "NewExpression":
- if (parent.arguments.length === 1 && parent.arguments[0] === node) {
- return sourceCode.getTokenAfter(
- parent.callee,
- isOpeningParenToken,
- )
- }
- return null
- case "DoWhileStatement":
- if (parent.test === node) {
- return sourceCode.getTokenAfter(
- parent.body,
- isOpeningParenToken,
- )
- }
- return null
- case "IfStatement":
- case "WhileStatement":
- if (parent.test === node) {
- return sourceCode.getFirstToken(parent, 1)
- }
- return null
- case "ImportExpression":
- if (parent.source === node) {
- return sourceCode.getFirstToken(parent, 1)
- }
- return null
- case "SwitchStatement":
- if (parent.discriminant === node) {
- return sourceCode.getFirstToken(parent, 1)
- }
- return null
- case "WithStatement":
- if (parent.object === node) {
- return sourceCode.getFirstToken(parent, 1)
- }
- return null
- default:
- return null
- }
- }
- function isParenthesized(
- timesOrNode,
- nodeOrSourceCode,
- optionalSourceCode,
- ) {
- let times, node, sourceCode, maybeLeftParen, maybeRightParen;
- if (typeof timesOrNode === "number") {
- times = timesOrNode | 0;
- node = nodeOrSourceCode;
- sourceCode = optionalSourceCode;
- if (!(times >= 1)) {
- throw new TypeError("'times' should be a positive integer.")
- }
- } else {
- times = 1;
- node = timesOrNode;
- sourceCode = nodeOrSourceCode;
- }
- if (
- node == null ||
-
- node.parent == null ||
-
- (node.parent.type === "CatchClause" && node.parent.param === node)
- ) {
- return false
- }
- maybeLeftParen = maybeRightParen = node;
- do {
- maybeLeftParen = sourceCode.getTokenBefore(maybeLeftParen);
- maybeRightParen = sourceCode.getTokenAfter(maybeRightParen);
- } while (
- maybeLeftParen != null &&
- maybeRightParen != null &&
- isOpeningParenToken(maybeLeftParen) &&
- isClosingParenToken(maybeRightParen) &&
-
- maybeLeftParen !== getParentSyntaxParen(node, sourceCode) &&
- --times > 0
- )
- return times === 0
- }
- const placeholder = /\$(?:[$&`']|[1-9][0-9]?)/gu;
- const internal = new WeakMap();
- function isEscaped(str, index) {
- let escaped = false;
- for (let i = index - 1; i >= 0 && str.charCodeAt(i) === 0x5c; --i) {
- escaped = !escaped;
- }
- return escaped
- }
- function replaceS(matcher, str, replacement) {
- const chunks = [];
- let index = 0;
-
- let match = null;
-
- function replacer(key) {
- switch (key) {
- case "$$":
- return "$"
- case "$&":
- return match[0]
- case "$`":
- return str.slice(0, match.index)
- case "$'":
- return str.slice(match.index + match[0].length)
- default: {
- const i = key.slice(1);
- if (i in match) {
- return match[i]
- }
- return key
- }
- }
- }
- for (match of matcher.execAll(str)) {
- chunks.push(str.slice(index, match.index));
- chunks.push(replacement.replace(placeholder, replacer));
- index = match.index + match[0].length;
- }
- chunks.push(str.slice(index));
- return chunks.join("")
- }
- function replaceF(matcher, str, replace) {
- const chunks = [];
- let index = 0;
- for (const match of matcher.execAll(str)) {
- chunks.push(str.slice(index, match.index));
- chunks.push(String(replace(...match, match.index, match.input)));
- index = match.index + match[0].length;
- }
- chunks.push(str.slice(index));
- return chunks.join("")
- }
- class PatternMatcher {
-
- constructor(pattern, { escaped = false } = {}) {
- if (!(pattern instanceof RegExp)) {
- throw new TypeError("'pattern' should be a RegExp instance.")
- }
- if (!pattern.flags.includes("g")) {
- throw new Error("'pattern' should contains 'g' flag.")
- }
- internal.set(this, {
- pattern: new RegExp(pattern.source, pattern.flags),
- escaped: Boolean(escaped),
- });
- }
-
- *execAll(str) {
- const { pattern, escaped } = internal.get(this);
- let match = null;
- let lastIndex = 0;
- pattern.lastIndex = 0;
- while ((match = pattern.exec(str)) != null) {
- if (escaped || !isEscaped(str, match.index)) {
- lastIndex = pattern.lastIndex;
- yield match;
- pattern.lastIndex = lastIndex;
- }
- }
- }
-
- test(str) {
- const it = this.execAll(str);
- const ret = it.next();
- return !ret.done
- }
-
- [Symbol.replace](str, replacer) {
- return typeof replacer === "function"
- ? replaceF(this, String(str), replacer)
- : replaceS(this, String(str), String(replacer))
- }
- }
- const IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/u;
- const has = Function.call.bind(Object.hasOwnProperty);
- const READ = Symbol("read");
- const CALL = Symbol("call");
- const CONSTRUCT = Symbol("construct");
- const ESM = Symbol("esm");
- const requireCall = { require: { [CALL]: true } };
- function isModifiedGlobal(variable) {
- return (
- variable == null ||
- variable.defs.length !== 0 ||
- variable.references.some((r) => r.isWrite())
- )
- }
- function isPassThrough(node) {
- const parent = node.parent;
- switch (parent && parent.type) {
- case "ConditionalExpression":
- return parent.consequent === node || parent.alternate === node
- case "LogicalExpression":
- return true
- case "SequenceExpression":
- return parent.expressions[parent.expressions.length - 1] === node
- case "ChainExpression":
- return true
- default:
- return false
- }
- }
- class ReferenceTracker {
-
- constructor(
- globalScope,
- {
- mode = "strict",
- globalObjectNames = ["global", "globalThis", "self", "window"],
- } = {},
- ) {
- this.variableStack = [];
- this.globalScope = globalScope;
- this.mode = mode;
- this.globalObjectNames = globalObjectNames.slice(0);
- }
-
- *iterateGlobalReferences(traceMap) {
- for (const key of Object.keys(traceMap)) {
- const nextTraceMap = traceMap[key];
- const path = [key];
- const variable = this.globalScope.set.get(key);
- if (isModifiedGlobal(variable)) {
- continue
- }
- yield* this._iterateVariableReferences(
- variable,
- path,
- nextTraceMap,
- true,
- );
- }
- for (const key of this.globalObjectNames) {
- const path = [];
- const variable = this.globalScope.set.get(key);
- if (isModifiedGlobal(variable)) {
- continue
- }
- yield* this._iterateVariableReferences(
- variable,
- path,
- traceMap,
- false,
- );
- }
- }
-
- *iterateCjsReferences(traceMap) {
- for (const { node } of this.iterateGlobalReferences(requireCall)) {
- const key = getStringIfConstant(node.arguments[0]);
- if (key == null || !has(traceMap, key)) {
- continue
- }
- const nextTraceMap = traceMap[key];
- const path = [key];
- if (nextTraceMap[READ]) {
- yield {
- node,
- path,
- type: READ,
- info: nextTraceMap[READ],
- };
- }
- yield* this._iteratePropertyReferences(node, path, nextTraceMap);
- }
- }
-
- *iterateEsmReferences(traceMap) {
- const programNode = this.globalScope.block;
- for (const node of programNode.body) {
- if (!IMPORT_TYPE.test(node.type) || node.source == null) {
- continue
- }
- const moduleId = node.source.value;
- if (!has(traceMap, moduleId)) {
- continue
- }
- const nextTraceMap = traceMap[moduleId];
- const path = [moduleId];
- if (nextTraceMap[READ]) {
- yield { node, path, type: READ, info: nextTraceMap[READ] };
- }
- if (node.type === "ExportAllDeclaration") {
- for (const key of Object.keys(nextTraceMap)) {
- const exportTraceMap = nextTraceMap[key];
- if (exportTraceMap[READ]) {
- yield {
- node,
- path: path.concat(key),
- type: READ,
- info: exportTraceMap[READ],
- };
- }
- }
- } else {
- for (const specifier of node.specifiers) {
- const esm = has(nextTraceMap, ESM);
- const it = this._iterateImportReferences(
- specifier,
- path,
- esm
- ? nextTraceMap
- : this.mode === "legacy"
- ? { default: nextTraceMap, ...nextTraceMap }
- : { default: nextTraceMap },
- );
- if (esm) {
- yield* it;
- } else {
- for (const report of it) {
- report.path = report.path.filter(exceptDefault);
- if (
- report.path.length >= 2 ||
- report.type !== READ
- ) {
- yield report;
- }
- }
- }
- }
- }
- }
- }
-
- *_iterateVariableReferences(variable, path, traceMap, shouldReport) {
- if (this.variableStack.includes(variable)) {
- return
- }
- this.variableStack.push(variable);
- try {
- for (const reference of variable.references) {
- if (!reference.isRead()) {
- continue
- }
- const node = reference.identifier;
- if (shouldReport && traceMap[READ]) {
- yield { node, path, type: READ, info: traceMap[READ] };
- }
- yield* this._iteratePropertyReferences(node, path, traceMap);
- }
- } finally {
- this.variableStack.pop();
- }
- }
-
-
- *_iteratePropertyReferences(rootNode, path, traceMap) {
- let node = rootNode;
- while (isPassThrough(node)) {
- node = node.parent;
- }
- const parent = node.parent;
- if (parent.type === "MemberExpression") {
- if (parent.object === node) {
- const key = getPropertyName(parent);
- if (key == null || !has(traceMap, key)) {
- return
- }
- path = path.concat(key);
- const nextTraceMap = traceMap[key];
- if (nextTraceMap[READ]) {
- yield {
- node: parent,
- path,
- type: READ,
- info: nextTraceMap[READ],
- };
- }
- yield* this._iteratePropertyReferences(
- parent,
- path,
- nextTraceMap,
- );
- }
- return
- }
- if (parent.type === "CallExpression") {
- if (parent.callee === node && traceMap[CALL]) {
- yield { node: parent, path, type: CALL, info: traceMap[CALL] };
- }
- return
- }
- if (parent.type === "NewExpression") {
- if (parent.callee === node && traceMap[CONSTRUCT]) {
- yield {
- node: parent,
- path,
- type: CONSTRUCT,
- info: traceMap[CONSTRUCT],
- };
- }
- return
- }
- if (parent.type === "AssignmentExpression") {
- if (parent.right === node) {
- yield* this._iterateLhsReferences(parent.left, path, traceMap);
- yield* this._iteratePropertyReferences(parent, path, traceMap);
- }
- return
- }
- if (parent.type === "AssignmentPattern") {
- if (parent.right === node) {
- yield* this._iterateLhsReferences(parent.left, path, traceMap);
- }
- return
- }
- if (parent.type === "VariableDeclarator") {
- if (parent.init === node) {
- yield* this._iterateLhsReferences(parent.id, path, traceMap);
- }
- }
- }
-
- *_iterateLhsReferences(patternNode, path, traceMap) {
- if (patternNode.type === "Identifier") {
- const variable = findVariable(this.globalScope, patternNode);
- if (variable != null) {
- yield* this._iterateVariableReferences(
- variable,
- path,
- traceMap,
- false,
- );
- }
- return
- }
- if (patternNode.type === "ObjectPattern") {
- for (const property of patternNode.properties) {
- const key = getPropertyName(property);
- if (key == null || !has(traceMap, key)) {
- continue
- }
- const nextPath = path.concat(key);
- const nextTraceMap = traceMap[key];
- if (nextTraceMap[READ]) {
- yield {
- node: property,
- path: nextPath,
- type: READ,
- info: nextTraceMap[READ],
- };
- }
- yield* this._iterateLhsReferences(
- property.value,
- nextPath,
- nextTraceMap,
- );
- }
- return
- }
- if (patternNode.type === "AssignmentPattern") {
- yield* this._iterateLhsReferences(patternNode.left, path, traceMap);
- }
- }
-
- *_iterateImportReferences(specifierNode, path, traceMap) {
- const type = specifierNode.type;
- if (type === "ImportSpecifier" || type === "ImportDefaultSpecifier") {
- const key =
- type === "ImportDefaultSpecifier"
- ? "default"
- : specifierNode.imported.name;
- if (!has(traceMap, key)) {
- return
- }
- path = path.concat(key);
- const nextTraceMap = traceMap[key];
- if (nextTraceMap[READ]) {
- yield {
- node: specifierNode,
- path,
- type: READ,
- info: nextTraceMap[READ],
- };
- }
- yield* this._iterateVariableReferences(
- findVariable(this.globalScope, specifierNode.local),
- path,
- nextTraceMap,
- false,
- );
- return
- }
- if (type === "ImportNamespaceSpecifier") {
- yield* this._iterateVariableReferences(
- findVariable(this.globalScope, specifierNode.local),
- path,
- traceMap,
- false,
- );
- return
- }
- if (type === "ExportSpecifier") {
- const key = specifierNode.local.name;
- if (!has(traceMap, key)) {
- return
- }
- path = path.concat(key);
- const nextTraceMap = traceMap[key];
- if (nextTraceMap[READ]) {
- yield {
- node: specifierNode,
- path,
- type: READ,
- info: nextTraceMap[READ],
- };
- }
- }
- }
- }
- ReferenceTracker.READ = READ;
- ReferenceTracker.CALL = CALL;
- ReferenceTracker.CONSTRUCT = CONSTRUCT;
- ReferenceTracker.ESM = ESM;
- function exceptDefault(name, index) {
- return !(index === 1 && name === "default")
- }
- var index = {
- CALL,
- CONSTRUCT,
- ESM,
- findVariable,
- getFunctionHeadLocation,
- getFunctionNameWithKind,
- getInnermostScope,
- getPropertyName,
- getStaticValue,
- getStringIfConstant,
- hasSideEffect,
- isArrowToken,
- isClosingBraceToken,
- isClosingBracketToken,
- isClosingParenToken,
- isColonToken,
- isCommaToken,
- isCommentToken,
- isNotArrowToken,
- isNotClosingBraceToken,
- isNotClosingBracketToken,
- isNotClosingParenToken,
- isNotColonToken,
- isNotCommaToken,
- isNotCommentToken,
- isNotOpeningBraceToken,
- isNotOpeningBracketToken,
- isNotOpeningParenToken,
- isNotSemicolonToken,
- isOpeningBraceToken,
- isOpeningBracketToken,
- isOpeningParenToken,
- isParenthesized,
- isSemicolonToken,
- PatternMatcher,
- READ,
- ReferenceTracker,
- };
- export { CALL, CONSTRUCT, ESM, PatternMatcher, READ, ReferenceTracker, index as default, findVariable, getFunctionHeadLocation, getFunctionNameWithKind, getInnermostScope, getPropertyName, getStaticValue, getStringIfConstant, hasSideEffect, isArrowToken, isClosingBraceToken, isClosingBracketToken, isClosingParenToken, isColonToken, isCommaToken, isCommentToken, isNotArrowToken, isNotClosingBraceToken, isNotClosingBracketToken, isNotClosingParenToken, isNotColonToken, isNotCommaToken, isNotCommentToken, isNotOpeningBraceToken, isNotOpeningBracketToken, isNotOpeningParenToken, isNotSemicolonToken, isOpeningBraceToken, isOpeningBracketToken, isOpeningParenToken, isParenthesized, isSemicolonToken };
|