1 line
26 KiB
Plaintext
1 line
26 KiB
Plaintext
|
{"version":3,"names":["VALID_CALLEES","INVALID_METHODS","isValidCallee","val","includes","isInvalidMethod","evaluateTruthy","res","evaluate","confident","value","deopt","path","state","deoptPath","evaluateCached","node","seen","has","existing","get","resolved","item","set","_evaluate","isSequenceExpression","exprs","length","isStringLiteral","isNumericLiteral","isBooleanLiteral","isNullLiteral","isTemplateLiteral","evaluateQuasis","quasis","isTaggedTemplateExpression","isMemberExpression","object","name","property","isIdentifier","scope","getBinding","quasi","isConditionalExpression","testResult","isExpressionWrapper","parentPath","isCallExpression","callee","isLiteral","type","key","computed","isReferencedIdentifier","binding","constantViolations","start","end","hasValue","undefined","Infinity","NaN","resolve","isUnaryExpression","prefix","operator","argument","isFunction","isClass","arg","isArrayExpression","arr","elems","elem","elemValue","push","isObjectExpression","obj","props","prop","isObjectMethod","isSpreadElement","keyPath","valuePath","isLogicalExpression","wasConfident","left","leftConfident","right","rightConfident","isBinaryExpression","context","func","global","args","map","apply","raw","str","i","cooked","expr","String","Map"],"sources":["../../src/path/evaluation.ts"],"sourcesContent":["import type NodePath from \"./index\";\nimport type * as t from \"@babel/types\";\n\n// This file contains Babels metainterpreter that can evaluate static code.\n\nconst VALID_CALLEES = [\"String\", \"Number\", \"Math\"] as const;\nconst INVALID_METHODS = [\"random\"] as const;\n\nfunction isValidCallee(val: string): val is typeof VALID_CALLEES[number] {\n return VALID_CALLEES.includes(\n // @ts-expect-error val is a string\n val,\n );\n}\n\nfunction isInvalidMethod(val: string): val is typeof INVALID_METHODS[number] {\n return INVALID_METHODS.includes(\n // @ts-expect-error val is a string\n val,\n );\n}\n\n/**\n * Walk the input `node` and statically evaluate if it's truthy.\n *\n * Returning `true` when we're sure that the expression will evaluate to a\n * truthy value, `false` if we're sure that it will evaluate to a falsy\n * value and `undefined` if we aren't sure. Because of this please do not\n * rely on coercion when using this method and check with === if it's false.\n *\n * For example do:\n *\n * if (t.evaluateTruthy(node) === false) falsyLogic();\n *\n * **AND NOT**\n *\n * if (!t.evaluateTruthy(node)) falsyLogic();\n *\n */\n\nexport function evaluateTruthy(this: NodePath): boolean {\n const res = this.evaluate();\n if (res.confident) return !!res.value;\n}\n\ntype State = {\n confident: boolean;\n deoptPath: NodePath | null;\n seen: Map<t.Node, Result>;\n};\n\ntype Result = {\n resolved: boolean;\n value?: any;\n};\n/**\n * Deopts the evaluation\n */\nfunction deopt(path: NodePath, state: State) {\n if (!state.confident) return;\n state.deoptPath = path;\n state.confident = false;\n}\n\n/**\n * We wrap the _evaluate method so we can track `seen` nodes, we push an item\n * to the map before we actually evaluate it so we can deopt on self recursive\n * nodes such as:\n *\n * var g = a ? 1 : 2,\n * a = g * this.foo\n */\nfunction evaluateCached(path: NodePath, state: State): any {\n const { node } = path;\n const { seen } = state;\n\n if (seen.has(node)) {\n const existing = seen.get(node);\n if (existing.resolved) {\n return existing.value;\n } else {\n deopt(path, state);\n return;\n }\n } else {\n const item: Result = { resolved: false };\n seen.set(node, item);\n\n const val = _evaluate(path, state);\n if (state.confident) {\n item.resolved = true;\n item.value = val;\n }\n return val;\n }\n}\n\nfunction _evaluate(path: NodePath, state: State): any {\n if (!state.confident) return;\n\n if (path.isSequenceExpression()) {\n const exprs = path.get(\"expressions\");\n return evaluateCached(exprs[exprs.length - 1], state);\n }\n\n if (\n path.isStringLiteral() ||\n path.isNumericLiteral() ||\n p
|