@delance/builder 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +0 -2
- package/dist/index.js +2641 -596
- package/package.json +63 -41
- package/dist/cli.js.map +0 -18
- package/dist/index.js.map +0 -99
package/dist/index.js.map
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../transform/webcrack/index.ts", "../node_modules/webcrack/src/deobfuscate/index.ts", "../node_modules/webcrack/src/ast-utils/ast.ts", "../node_modules/webcrack/src/ast-utils/generator.ts", "../node_modules/webcrack/src/ast-utils/inline.ts", "../node_modules/webcrack/src/ast-utils/matcher.ts", "../node_modules/webcrack/src/ast-utils/matcher.ts", "../node_modules/webcrack/src/ast-utils/inline.ts", "../node_modules/webcrack/src/ast-utils/rename.ts", "../node_modules/webcrack/src/ast-utils/rename.ts", "../node_modules/webcrack/src/ast-utils/transform.ts", "../node_modules/webcrack/src/unminify/transforms/merge-strings.ts", "../node_modules/webcrack/src/deobfuscate/array-rotator.ts", "../node_modules/webcrack/src/deobfuscate/array-rotator.ts", "../node_modules/webcrack/src/deobfuscate/control-flow-object.ts", "../node_modules/webcrack/src/deobfuscate/control-flow-object.ts", "../node_modules/webcrack/src/deobfuscate/control-flow-switch.ts", "../node_modules/webcrack/src/deobfuscate/control-flow-switch.ts", "../node_modules/webcrack/src/deobfuscate/dead-code.ts", "../node_modules/webcrack/src/deobfuscate/dead-code.ts", "../node_modules/webcrack/src/deobfuscate/decoder.ts", "../node_modules/webcrack/src/deobfuscate/decoder.ts", "../node_modules/webcrack/src/deobfuscate/inline-decoded-strings.ts", "../node_modules/webcrack/src/deobfuscate/inline-decoder-wrappers.ts", "../node_modules/webcrack/src/deobfuscate/inline-object-props.ts", "../node_modules/webcrack/src/deobfuscate/inline-object-props.ts", "../node_modules/webcrack/src/deobfuscate/string-array.ts", "../node_modules/webcrack/src/deobfuscate/string-array.ts", "../node_modules/webcrack/src/deobfuscate/vm.ts", "../node_modules/webcrack/src/deobfuscate/vm.ts", "../node_modules/webcrack/src/deobfuscate/index.ts", "../node_modules/webcrack/src/deobfuscate/var-functions.ts", "../node_modules/webcrack/src/deobfuscate/merge-object-assignments.ts", "../node_modules/webcrack/src/deobfuscate/merge-object-assignments.ts", "../node_modules/webcrack/src/unminify/transforms/block-statements.ts", "../node_modules/webcrack/src/unminify/transforms/computed-properties.ts", "../node_modules/webcrack/src/unminify/transforms/for-to-while.ts", "../node_modules/webcrack/src/unminify/transforms/infinity.ts", "../node_modules/webcrack/src/unminify/transforms/invert-boolean-logic.ts", "../node_modules/webcrack/src/unminify/transforms/json-parse.ts", "../node_modules/webcrack/src/unminify/transforms/json-parse.ts", "../node_modules/webcrack/src/unminify/transforms/logical-to-if.ts", "../node_modules/webcrack/src/unminify/transforms/merge-else-if.ts", "../node_modules/webcrack/src/unminify/transforms/number-expressions.ts", "../node_modules/webcrack/src/unminify/transforms/raw-literals.ts", "../node_modules/webcrack/src/unminify/transforms/sequence.ts", "../node_modules/webcrack/src/unminify/transforms/split-variable-declarations.ts", "../node_modules/webcrack/src/unminify/transforms/ternary-to-if.ts", "../node_modules/webcrack/src/unminify/transforms/typeof-undefined.ts", "../node_modules/webcrack/src/unminify/transforms/unary-expressions.ts", "../node_modules/webcrack/src/unminify/transforms/unminify-booleans.ts", "../node_modules/webcrack/src/unminify/transforms/void-to-undefined.ts", "../node_modules/webcrack/src/unminify/transforms/yoda.ts", "../node_modules/webcrack/src/unminify/index.ts", "../transform/webcrack/index.ts", "../transform/esmodule/module-helper.ts", "../utils/matchers/chunk.ts", "../utils/matchers/createBinding.ts", "../utils/matchers/setModuleDefault.ts", "../utils/matchers/importStar.ts", "../utils/matchers/importDefault.ts", "../utils/matchers/exportStar.ts", "../transform/esmodule/module-helper.ts", "../transform/esmodule/indirect-call.ts", "../utils/ast.ts", "../utils/ast.ts", "../utils/ast.ts", "../transform/esmodule/index.ts", "../transform/syntactic/template-literal.ts", "../transform/syntactic/index.ts", "../node_modules/webcrack/src/transpile/transforms/logical-assignments.ts", "../node_modules/webcrack/src/transpile/transforms/logical-assignments.ts", "../node_modules/webcrack/src/transpile/transforms/nullish-coalescing.ts", "../node_modules/webcrack/src/transpile/transforms/nullish-coalescing.ts", "../node_modules/webcrack/src/transpile/transforms/nullish-coalescing-assignment.ts", "../node_modules/webcrack/src/transpile/transforms/nullish-coalescing-assignment.ts", "../node_modules/webcrack/src/transpile/transforms/optional-chaining.ts", "../node_modules/webcrack/src/transpile/transforms/optional-chaining.ts", "../node_modules/webcrack/src/transpile/transforms/template-literals.ts", "../node_modules/webcrack/src/transpile/transforms/template-literals.ts", "../node_modules/webcrack/src/transpile/index.ts", "../transform/delance/stringaes.ts", "../utils/crypto.ts", "../utils/crypto.ts", "../transform/delance/stringaes.ts", "../transform/delance/antifeature.ts", "../transform/delance/antifeature.ts", "../transform/delance/index.ts", "../transform/index.ts", "../index.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import type * as t from '@babel/types';\nimport {getQuickJS, shouldInterruptAfterDeadline} from 'quickjs-emscripten';\nimport deobfuscate from 'webcrack/deobfuscate';\nimport varFunctions from 'webcrack/deobfuscate/var-functions';\nimport mergeObjectAssignments from 'webcrack/deobfuscate/merge-object-assignments';\nimport unminify from 'webcrack/unminify';\nimport {blockStatements, sequence, splitVariableDeclarations} from 'webcrack/unminify/transforms';\nimport {applyTransform, applyTransformAsync, applyTransforms} from 'webcrack/ast-utils';\n\n/**\n * Run webcrack passes.\n */\nexport default async function transform(\n\tast: t.Node,\n) {\n\tapplyTransforms(\n\t\tast,\n\t\t[blockStatements, sequence, splitVariableDeclarations, varFunctions],\n\t\t{\n\t\t\tname: 'prepare',\n\t\t},\n\t);\n\n\tconst quickjs = await getQuickJS();\n\tawait applyTransformAsync(ast, deobfuscate, async (code: string) => quickjs.evalCode(code, {\n\t\tshouldInterrupt: shouldInterruptAfterDeadline(Date.now() + 2000),\n\t\tmemoryLimitBytes: 1024 * 1024,\n\t}));\n\n\tapplyTransform(ast, unminify);\n\tapplyTransform(ast, mergeObjectAssignments);\n\n\treturn ast;\n}\n",
|
|
6
|
-
"import debug from 'debug';\nimport {\n AsyncTransform,\n applyTransform,\n applyTransformAsync,\n applyTransforms,\n} from '../ast-utils';\nimport mergeStrings from '../unminify/transforms/merge-strings';\nimport { findArrayRotator } from './array-rotator';\nimport controlFlowObject from './control-flow-object';\nimport controlFlowSwitch from './control-flow-switch';\nimport deadCode from './dead-code';\nimport { findDecoders } from './decoder';\nimport inlineDecodedStrings from './inline-decoded-strings';\nimport inlineDecoderWrappers from './inline-decoder-wrappers';\nimport inlineObjectProps from './inline-object-props';\nimport { findStringArray } from './string-array';\nimport {\n Sandbox,\n VMDecoder,\n createBrowserSandbox,\n createNodeSandbox,\n} from './vm';\n\nexport { createBrowserSandbox, createNodeSandbox, type Sandbox };\n\n// https://astexplorer.net/#/gist/b1018df4a8daebfcb1daf9d61fe17557/4ff9ad0e9c40b9616956f17f59a2d9888cd62a4f\n\nexport default {\n name: 'deobfuscate',\n tags: ['unsafe'],\n scope: true,\n async run(ast, state, sandbox) {\n if (!sandbox) return;\n\n const logger = debug('webcrack:deobfuscate');\n const stringArray = findStringArray(ast);\n logger(\n stringArray\n ? `String Array: ${stringArray.length} strings`\n : 'String Array: no',\n );\n if (!stringArray) return;\n\n const rotator = findArrayRotator(stringArray);\n logger(`String Array Rotate: ${rotator ? 'yes' : 'no'}`);\n\n const decoders = findDecoders(stringArray);\n logger(`String Array Encodings: ${decoders.length}`);\n\n state.changes += applyTransform(ast, inlineObjectProps).changes;\n\n for (const decoder of decoders) {\n state.changes += applyTransform(\n ast,\n inlineDecoderWrappers,\n decoder.path,\n ).changes;\n }\n\n const vm = new VMDecoder(sandbox, stringArray, decoders, rotator);\n state.changes += (\n await applyTransformAsync(ast, inlineDecodedStrings, { vm })\n ).changes;\n\n stringArray.path.remove();\n rotator?.remove();\n decoders.forEach((decoder) => decoder.path.remove());\n state.changes += 2 + decoders.length;\n\n state.changes += applyTransforms(\n ast,\n [mergeStrings, deadCode, controlFlowObject, controlFlowSwitch],\n { noScope: true },\n ).changes;\n },\n} satisfies AsyncTransform<Sandbox>;\n",
|
|
7
|
-
"import * as t from '@babel/types';\n\nexport function getPropName(node: t.Node): string | undefined {\n if (t.isIdentifier(node)) {\n return node.name;\n }\n if (t.isStringLiteral(node)) {\n return node.value;\n }\n if (t.isNumericLiteral(node)) {\n return node.value.toString();\n }\n}\n",
|
|
8
|
-
"import babelGenerate, { GeneratorOptions } from '@babel/generator';\nimport * as t from '@babel/types';\n\nconst defaultOptions: GeneratorOptions = { jsescOption: { minimal: true } };\n\nexport function generate(\n ast: t.Node,\n options: GeneratorOptions = defaultOptions,\n): string {\n return babelGenerate(ast, options).code;\n}\n\nexport function codePreview(node: t.Node): string {\n const code = generate(node, {\n minified: true,\n shouldPrintComment: () => false,\n ...defaultOptions,\n });\n if (code.length > 100) {\n return code.slice(0, 70) + ' … ' + code.slice(-30);\n }\n return code;\n}\n",
|
|
9
|
-
"import traverse, { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { getPropName } from '.';\nimport { findParent } from './matcher';\n\n/**\n * Replace all references of a variable with the initializer.\n * Example:\n * `const a = 1; console.log(a);` -> `console.log(1);`\n *\n * Example with `unsafeAssignments` being `true`:\n * `let a; a = 2; console.log(a);` -> `console.log(2);`\n *\n * @param unsafeAssignments Also inline assignments to the variable (not guaranteed to be the final value)\n */\nexport function inlineVariable(\n binding: Binding,\n value = m.anyExpression(),\n unsafeAssignments = false,\n) {\n const varDeclarator = binding.path.node;\n const varMatcher = m.variableDeclarator(\n m.identifier(binding.identifier.name),\n value,\n );\n const assignmentMatcher = m.assignmentExpression(\n '=',\n m.identifier(binding.identifier.name),\n value,\n );\n\n if (binding.constant && varMatcher.match(varDeclarator)) {\n binding.referencePaths.forEach((ref) => {\n ref.replaceWith(varDeclarator.init!);\n });\n binding.path.remove();\n } else if (\n unsafeAssignments &&\n binding.constantViolations.length === 1 &&\n assignmentMatcher.match(binding.constantViolations[0]?.node)\n ) {\n const assignment = binding\n .constantViolations[0] as NodePath<t.AssignmentExpression>;\n binding.referencePaths.forEach((ref) => {\n ref.replaceWith(assignment.node.right);\n });\n assignment.remove();\n binding.path.remove();\n }\n}\n\n/**\n * Make sure the array is immutable and references are valid before using!\n *\n * Example:\n * `const arr = [\"foo\", \"bar\"]; console.log(arr[0]);` -> `console.log(\"foo\");`\n */\nexport function inlineArrayElements(\n array: t.ArrayExpression,\n references: NodePath[],\n): void {\n for (const reference of references) {\n const memberPath = reference.parentPath! as NodePath<t.MemberExpression>;\n const property = memberPath.node.property as t.NumericLiteral;\n const index = property.value;\n const replacement = array.elements[index]!;\n memberPath.replaceWith(replacement);\n }\n}\n\nexport function inlineObjectProperties(\n binding: Binding,\n property = m.objectProperty(),\n): void {\n const varDeclarator = binding.path.node;\n const objectProperties = m.capture(m.arrayOf(property));\n const varMatcher = m.variableDeclarator(\n m.identifier(binding.identifier.name),\n m.objectExpression(objectProperties),\n );\n if (!varMatcher.match(varDeclarator)) return;\n\n const propertyMap = new Map(\n objectProperties.current!.map((p) => [getPropName(p.key), p.value]),\n );\n if (\n !binding.referencePaths.every((ref) => {\n const member = ref.parent as t.MemberExpression;\n const propName = getPropName(member.property)!;\n return propertyMap.has(propName);\n })\n )\n return;\n\n binding.referencePaths.forEach((ref) => {\n const memberPath = ref.parentPath as NodePath<t.MemberExpression>;\n const propName = getPropName(memberPath.node.property)!;\n const value = propertyMap.get(propName)!;\n\n memberPath.replaceWith(value);\n });\n\n binding.path.remove();\n}\n\n/**\n * Inline function used in control flow flattening (that only returns an expression)\n * Example:\n * fn: `function (a, b) { return a(b) }`\n * caller: `fn(a, 1)`\n * ->\n * `a(1)`\n */\nexport function inlineFunction(\n fn: t.FunctionExpression | t.FunctionDeclaration,\n caller: NodePath<t.CallExpression>,\n): void {\n if (t.isRestElement(fn.params[1])) {\n caller.replaceWith(\n t.callExpression(\n caller.node.arguments[0] as t.Identifier,\n caller.node.arguments.slice(1),\n ),\n );\n return;\n }\n\n const returnedValue = (fn.body.body[0] as t.ReturnStatement).argument!;\n const clone = t.cloneNode(returnedValue, true);\n\n // Inline all arguments\n traverse(clone, {\n Identifier(path) {\n const paramIndex = fn.params.findIndex(\n (p) => (p as t.Identifier).name === path.node.name,\n );\n if (paramIndex !== -1) {\n path.replaceWith(caller.node.arguments[paramIndex]);\n path.skip();\n }\n },\n noScope: true,\n });\n\n caller.replaceWith(clone);\n}\n\n/**\n * Example:\n * `function alias(a, b) { return decode(b - 938, a); } alias(1071, 1077);`\n * ->\n * `decode(1077 - 938, 1071)`\n */\nexport function inlineFunctionAliases(binding: Binding): { changes: number } {\n const state = { changes: 0 };\n const refs = [...binding.referencePaths];\n for (const ref of refs) {\n const fn = findParent(ref, m.functionDeclaration());\n\n // E.g. alias\n const fnName = m.capture(m.anyString());\n // E.g. decode(b - 938, a)\n const returnedCall = m.capture(\n m.callExpression(\n m.identifier(binding.identifier.name),\n m.anyList(m.slice({ min: 2 })),\n ),\n );\n const matcher = m.functionDeclaration(\n m.identifier(fnName),\n m.anyList(m.slice({ min: 2 })),\n m.blockStatement([m.returnStatement(returnedCall)]),\n );\n\n if (fn && matcher.match(fn.node)) {\n // Avoid false positives of functions that return a string\n // It's only a wrapper if the function's params are used in the decode call\n const paramUsedInDecodeCall = fn.node.params.some((param) => {\n const binding = fn.scope.getBinding((param as t.Identifier).name);\n return binding?.referencePaths.some((ref) =>\n ref.findParent((p) => p.node === returnedCall.current),\n );\n });\n if (!paramUsedInDecodeCall) continue;\n\n const fnBinding = fn.scope.parent.getBinding(fnName.current!);\n if (!fnBinding) continue;\n // Check all further aliases (`function alias2(a, b) { return alias(a - 1, b + 3); }`)\n const fnRefs = fnBinding.referencePaths;\n refs.push(...fnRefs);\n\n // E.g. [alias(1071, 1077), alias(1, 2)]\n const callRefs = fnRefs\n .filter(\n (ref) =>\n t.isCallExpression(ref.parent) &&\n t.isIdentifier(ref.parent.callee, { name: fnName.current! }),\n )\n .map((ref) => ref.parentPath!) as NodePath<t.CallExpression>[];\n\n for (const callRef of callRefs) {\n inlineFunction(fn.node, callRef);\n state.changes++;\n }\n\n fn.remove();\n state.changes++;\n }\n }\n\n // Have to crawl again because renaming messed up the references\n binding.scope.crawl();\n return state;\n}\n\n/**\n * Recursively renames all references to the binding.\n * Make sure the binding name isn't shadowed anywhere!\n *\n * Example: `var alias = decoder; alias(1);` -> `decoder(1);`\n */\n\nexport function inlineVariableAliases(\n binding: Binding,\n targetName = binding.identifier.name,\n): { changes: number } {\n const state = { changes: 0 };\n const refs = [...binding.referencePaths];\n const varName = m.capture(m.anyString());\n const matcher = m.or(\n m.variableDeclarator(\n m.identifier(varName),\n m.identifier(binding.identifier.name),\n ),\n m.assignmentExpression(\n '=',\n m.identifier(varName),\n m.identifier(binding.identifier.name),\n ),\n );\n\n for (const ref of refs) {\n if (matcher.match(ref.parent)) {\n const varScope = ref.scope;\n const varBinding = varScope.getBinding(varName.current!);\n if (!varBinding) continue;\n\n // Check all further aliases (`var alias2 = alias;`)\n state.changes += inlineVariableAliases(varBinding, targetName).changes;\n\n if (ref.parentPath?.isAssignmentExpression()) {\n // Remove `var alias;` when the assignment happens separately\n varBinding.path.remove();\n\n if (t.isExpressionStatement(ref.parentPath.parent)) {\n // Remove `alias = decoder;`\n ref.parentPath.remove();\n } else {\n // Replace `(alias = decoder)(1);` with `decoder(1);`\n ref.parentPath.replaceWith(ref.parentPath.node.right);\n }\n } else if (ref.parentPath?.isVariableDeclarator()) {\n // Remove `alias = decoder;` of declarator\n ref.parentPath.remove();\n }\n state.changes++;\n } else {\n // Rename the reference\n ref.replaceWith(t.identifier(targetName));\n state.changes++;\n }\n }\n\n return state;\n}\n",
|
|
10
|
-
"import { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\n\nexport const anyLiteral: m.Matcher<t.Literal> = m.matcher(\n (node) =>\n t.isLiteral(node) &&\n (!t.isTemplateLiteral(node) || node.expressions.length === 0),\n);\n\nexport function infiniteLoop(\n body?: m.Matcher<t.Statement>,\n): m.Matcher<t.ForStatement | t.WhileStatement> {\n return m.or(\n m.forStatement(undefined, null, undefined, body),\n m.forStatement(undefined, truthyMatcher, undefined, body),\n m.whileStatement(truthyMatcher, body),\n );\n}\n\nexport function constKey(\n name?: string | m.Matcher<string>,\n): m.Matcher<t.Identifier | t.StringLiteral> {\n return m.or(m.identifier(name), m.stringLiteral(name));\n}\n\nexport function constObjectProperty(\n value?: m.Matcher<t.Expression>,\n): m.Matcher<t.ObjectProperty> {\n return m.or(\n m.objectProperty(m.identifier(), value, false),\n m.objectProperty(m.or(m.stringLiteral(), m.numericLiteral()), value),\n );\n}\n\nexport function matchIife(\n body?: m.Matcher<t.Statement[]> | m.Matcher<t.Statement>[],\n): m.Matcher<t.CallExpression> {\n return m.callExpression(\n m.functionExpression(null, [], body ? m.blockStatement(body) : undefined),\n [],\n );\n}\n\nexport const iife = matchIife();\nexport const emptyIife = matchIife([]);\n\n/**\n * Matches both identifier properties and string literal computed properties\n */\nexport function constMemberExpression(\n object: string | m.Matcher<t.Expression>,\n property?: string | m.Matcher<string>,\n): m.Matcher<t.MemberExpression> {\n if (typeof object === 'string') object = m.identifier(object);\n return m.or(\n m.memberExpression(object, m.identifier(property), false),\n m.memberExpression(object, m.stringLiteral(property), true),\n );\n}\n\nexport const trueMatcher = m.or(\n m.booleanLiteral(true),\n m.unaryExpression('!', m.numericLiteral(0)),\n m.unaryExpression('!', m.unaryExpression('!', m.numericLiteral(1))),\n m.unaryExpression('!', m.unaryExpression('!', m.arrayExpression([]))),\n);\n\nexport const falseMatcher = m.or(\n m.booleanLiteral(false),\n m.unaryExpression('!', m.arrayExpression([])),\n);\n\nexport const truthyMatcher = m.or(trueMatcher, m.arrayExpression([]));\n\n/**\n * Starting at the parent path of the current `NodePath` and going up the\n * tree, return the first `NodePath` that causes the provided `matcher`\n * to return true, or `null` if the `matcher` never returns true.\n */\nexport function findParent<T extends t.Node>(\n path: NodePath,\n matcher: m.Matcher<T>,\n): NodePath<T> | null {\n return path.findParent((path) =>\n matcher.match(path.node),\n ) as NodePath<T> | null;\n}\n\n/**\n * Starting at current `NodePath` and going up the tree, return the first\n * `NodePath` that causes the provided `matcher` to return true,\n * or `null` if the `matcher` never returns true.\n */\nexport function findPath<T extends t.Node>(\n path: NodePath,\n matcher: m.Matcher<T>,\n): NodePath<T> | null {\n return path.find((path) => matcher.match(path.node)) as NodePath<T> | null;\n}\n\n/**\n * Function expression matcher that captures the parameters\n * and allows them to be referenced in the body.\n */\nexport function createFunctionMatcher(\n params: number,\n body: (\n ...captures: m.Matcher<t.Identifier>[]\n ) => m.Matcher<t.Statement[]> | m.Matcher<t.Statement>[],\n): m.Matcher<t.FunctionExpression> {\n const captures = Array.from({ length: params }, () =>\n m.capture(m.anyString()),\n );\n\n return m.functionExpression(\n undefined,\n captures.map(m.identifier),\n m.blockStatement(\n body(...captures.map((c) => m.identifier(m.fromCapture(c)))),\n ),\n );\n}\n\n/**\n * Returns true if every reference is a member expression whose value is read\n */\nexport function isReadonlyObject(\n binding: Binding,\n memberAccess: m.Matcher<t.MemberExpression>,\n): boolean {\n // Workaround because sometimes babel treats the VariableDeclarator/binding itself as a violation\n if (!binding.constant && binding.constantViolations[0] !== binding.path)\n return false;\n\n function isPatternAssignment(member: NodePath<t.Node>) {\n return (\n // [obj.property] = [1];\n member.parentPath?.isArrayPattern() ||\n // ([obj.property = 1] = [])\n member.parentPath?.isAssignmentPattern() ||\n // ({ property: obj.property } = {})\n member.parentPath?.parentPath?.isObjectPattern() ||\n // ({ property: obj.property = 1 } = {})\n member.parentPath?.isAssignmentPattern()\n );\n }\n\n return binding.referencePaths.every(\n (path) =>\n // obj.property\n memberAccess.match(path.parent) &&\n // obj.property = 1\n !path.parentPath?.parentPath?.isAssignmentExpression({\n left: path.parent,\n }) &&\n // obj.property++\n !path.parentPath?.parentPath?.isUpdateExpression({\n argument: path.parent,\n }) &&\n // delete obj.property\n !path.parentPath?.parentPath?.isUnaryExpression({\n argument: path.parent,\n operator: 'delete',\n }) &&\n !isPatternAssignment(path.parentPath!),\n );\n}\n\n/**\n * Checks if the binding is a temporary variable that is only assigned\n * once and has limited references. Often created by transpilers.\n *\n * Example with 1 reference to `_tmp`:\n * ```js\n * var _tmp; x[_tmp = y] || (x[_tmp] = z);\n * ```\n */\nexport function isTemporaryVariable(\n binding: Binding | undefined,\n references: number,\n kind: 'var' | 'param' = 'var',\n): binding is Binding {\n return (\n binding !== undefined &&\n binding.references === references &&\n binding.constantViolations.length === 1 &&\n (kind === 'var'\n ? binding.path.isVariableDeclarator() && binding.path.node.init === null\n : binding.path.listKey === 'params' && binding.path.isIdentifier())\n );\n}\n",
|
|
11
|
-
"import { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\n\nexport const anyLiteral: m.Matcher<t.Literal> = m.matcher(\n (node) =>\n t.isLiteral(node) &&\n (!t.isTemplateLiteral(node) || node.expressions.length === 0),\n);\n\nexport function infiniteLoop(\n body?: m.Matcher<t.Statement>,\n): m.Matcher<t.ForStatement | t.WhileStatement> {\n return m.or(\n m.forStatement(undefined, null, undefined, body),\n m.forStatement(undefined, truthyMatcher, undefined, body),\n m.whileStatement(truthyMatcher, body),\n );\n}\n\nexport function constKey(\n name?: string | m.Matcher<string>,\n): m.Matcher<t.Identifier | t.StringLiteral> {\n return m.or(m.identifier(name), m.stringLiteral(name));\n}\n\nexport function constObjectProperty(\n value?: m.Matcher<t.Expression>,\n): m.Matcher<t.ObjectProperty> {\n return m.or(\n m.objectProperty(m.identifier(), value, false),\n m.objectProperty(m.or(m.stringLiteral(), m.numericLiteral()), value),\n );\n}\n\nexport function matchIife(\n body?: m.Matcher<t.Statement[]> | m.Matcher<t.Statement>[],\n): m.Matcher<t.CallExpression> {\n return m.callExpression(\n m.functionExpression(null, [], body ? m.blockStatement(body) : undefined),\n [],\n );\n}\n\nexport const iife = matchIife();\nexport const emptyIife = matchIife([]);\n\n/**\n * Matches both identifier properties and string literal computed properties\n */\nexport function constMemberExpression(\n object: string | m.Matcher<t.Expression>,\n property?: string | m.Matcher<string>,\n): m.Matcher<t.MemberExpression> {\n if (typeof object === 'string') object = m.identifier(object);\n return m.or(\n m.memberExpression(object, m.identifier(property), false),\n m.memberExpression(object, m.stringLiteral(property), true),\n );\n}\n\nexport const trueMatcher = m.or(\n m.booleanLiteral(true),\n m.unaryExpression('!', m.numericLiteral(0)),\n m.unaryExpression('!', m.unaryExpression('!', m.numericLiteral(1))),\n m.unaryExpression('!', m.unaryExpression('!', m.arrayExpression([]))),\n);\n\nexport const falseMatcher = m.or(\n m.booleanLiteral(false),\n m.unaryExpression('!', m.arrayExpression([])),\n);\n\nexport const truthyMatcher = m.or(trueMatcher, m.arrayExpression([]));\n\n/**\n * Starting at the parent path of the current `NodePath` and going up the\n * tree, return the first `NodePath` that causes the provided `matcher`\n * to return true, or `null` if the `matcher` never returns true.\n */\nexport function findParent<T extends t.Node>(\n path: NodePath,\n matcher: m.Matcher<T>,\n): NodePath<T> | null {\n return path.findParent((path) =>\n matcher.match(path.node),\n ) as NodePath<T> | null;\n}\n\n/**\n * Starting at current `NodePath` and going up the tree, return the first\n * `NodePath` that causes the provided `matcher` to return true,\n * or `null` if the `matcher` never returns true.\n */\nexport function findPath<T extends t.Node>(\n path: NodePath,\n matcher: m.Matcher<T>,\n): NodePath<T> | null {\n return path.find((path) => matcher.match(path.node)) as NodePath<T> | null;\n}\n\n/**\n * Function expression matcher that captures the parameters\n * and allows them to be referenced in the body.\n */\nexport function createFunctionMatcher(\n params: number,\n body: (\n ...captures: m.Matcher<t.Identifier>[]\n ) => m.Matcher<t.Statement[]> | m.Matcher<t.Statement>[],\n): m.Matcher<t.FunctionExpression> {\n const captures = Array.from({ length: params }, () =>\n m.capture(m.anyString()),\n );\n\n return m.functionExpression(\n undefined,\n captures.map(m.identifier),\n m.blockStatement(\n body(...captures.map((c) => m.identifier(m.fromCapture(c)))),\n ),\n );\n}\n\n/**\n * Returns true if every reference is a member expression whose value is read\n */\nexport function isReadonlyObject(\n binding: Binding,\n memberAccess: m.Matcher<t.MemberExpression>,\n): boolean {\n // Workaround because sometimes babel treats the VariableDeclarator/binding itself as a violation\n if (!binding.constant && binding.constantViolations[0] !== binding.path)\n return false;\n\n function isPatternAssignment(member: NodePath<t.Node>) {\n return (\n // [obj.property] = [1];\n member.parentPath?.isArrayPattern() ||\n // ([obj.property = 1] = [])\n member.parentPath?.isAssignmentPattern() ||\n // ({ property: obj.property } = {})\n member.parentPath?.parentPath?.isObjectPattern() ||\n // ({ property: obj.property = 1 } = {})\n member.parentPath?.isAssignmentPattern()\n );\n }\n\n return binding.referencePaths.every(\n (path) =>\n // obj.property\n memberAccess.match(path.parent) &&\n // obj.property = 1\n !path.parentPath?.parentPath?.isAssignmentExpression({\n left: path.parent,\n }) &&\n // obj.property++\n !path.parentPath?.parentPath?.isUpdateExpression({\n argument: path.parent,\n }) &&\n // delete obj.property\n !path.parentPath?.parentPath?.isUnaryExpression({\n argument: path.parent,\n operator: 'delete',\n }) &&\n !isPatternAssignment(path.parentPath!),\n );\n}\n\n/**\n * Checks if the binding is a temporary variable that is only assigned\n * once and has limited references. Often created by transpilers.\n *\n * Example with 1 reference to `_tmp`:\n * ```js\n * var _tmp; x[_tmp = y] || (x[_tmp] = z);\n * ```\n */\nexport function isTemporaryVariable(\n binding: Binding | undefined,\n references: number,\n kind: 'var' | 'param' = 'var',\n): binding is Binding {\n return (\n binding !== undefined &&\n binding.references === references &&\n binding.constantViolations.length === 1 &&\n (kind === 'var'\n ? binding.path.isVariableDeclarator() && binding.path.node.init === null\n : binding.path.listKey === 'params' && binding.path.isIdentifier())\n );\n}\n",
|
|
12
|
-
"import traverse, { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { getPropName } from '.';\nimport { findParent } from './matcher';\n\n/**\n * Replace all references of a variable with the initializer.\n * Example:\n * `const a = 1; console.log(a);` -> `console.log(1);`\n *\n * Example with `unsafeAssignments` being `true`:\n * `let a; a = 2; console.log(a);` -> `console.log(2);`\n *\n * @param unsafeAssignments Also inline assignments to the variable (not guaranteed to be the final value)\n */\nexport function inlineVariable(\n binding: Binding,\n value = m.anyExpression(),\n unsafeAssignments = false,\n) {\n const varDeclarator = binding.path.node;\n const varMatcher = m.variableDeclarator(\n m.identifier(binding.identifier.name),\n value,\n );\n const assignmentMatcher = m.assignmentExpression(\n '=',\n m.identifier(binding.identifier.name),\n value,\n );\n\n if (binding.constant && varMatcher.match(varDeclarator)) {\n binding.referencePaths.forEach((ref) => {\n ref.replaceWith(varDeclarator.init!);\n });\n binding.path.remove();\n } else if (\n unsafeAssignments &&\n binding.constantViolations.length === 1 &&\n assignmentMatcher.match(binding.constantViolations[0]?.node)\n ) {\n const assignment = binding\n .constantViolations[0] as NodePath<t.AssignmentExpression>;\n binding.referencePaths.forEach((ref) => {\n ref.replaceWith(assignment.node.right);\n });\n assignment.remove();\n binding.path.remove();\n }\n}\n\n/**\n * Make sure the array is immutable and references are valid before using!\n *\n * Example:\n * `const arr = [\"foo\", \"bar\"]; console.log(arr[0]);` -> `console.log(\"foo\");`\n */\nexport function inlineArrayElements(\n array: t.ArrayExpression,\n references: NodePath[],\n): void {\n for (const reference of references) {\n const memberPath = reference.parentPath! as NodePath<t.MemberExpression>;\n const property = memberPath.node.property as t.NumericLiteral;\n const index = property.value;\n const replacement = array.elements[index]!;\n memberPath.replaceWith(replacement);\n }\n}\n\nexport function inlineObjectProperties(\n binding: Binding,\n property = m.objectProperty(),\n): void {\n const varDeclarator = binding.path.node;\n const objectProperties = m.capture(m.arrayOf(property));\n const varMatcher = m.variableDeclarator(\n m.identifier(binding.identifier.name),\n m.objectExpression(objectProperties),\n );\n if (!varMatcher.match(varDeclarator)) return;\n\n const propertyMap = new Map(\n objectProperties.current!.map((p) => [getPropName(p.key), p.value]),\n );\n if (\n !binding.referencePaths.every((ref) => {\n const member = ref.parent as t.MemberExpression;\n const propName = getPropName(member.property)!;\n return propertyMap.has(propName);\n })\n )\n return;\n\n binding.referencePaths.forEach((ref) => {\n const memberPath = ref.parentPath as NodePath<t.MemberExpression>;\n const propName = getPropName(memberPath.node.property)!;\n const value = propertyMap.get(propName)!;\n\n memberPath.replaceWith(value);\n });\n\n binding.path.remove();\n}\n\n/**\n * Inline function used in control flow flattening (that only returns an expression)\n * Example:\n * fn: `function (a, b) { return a(b) }`\n * caller: `fn(a, 1)`\n * ->\n * `a(1)`\n */\nexport function inlineFunction(\n fn: t.FunctionExpression | t.FunctionDeclaration,\n caller: NodePath<t.CallExpression>,\n): void {\n if (t.isRestElement(fn.params[1])) {\n caller.replaceWith(\n t.callExpression(\n caller.node.arguments[0] as t.Identifier,\n caller.node.arguments.slice(1),\n ),\n );\n return;\n }\n\n const returnedValue = (fn.body.body[0] as t.ReturnStatement).argument!;\n const clone = t.cloneNode(returnedValue, true);\n\n // Inline all arguments\n traverse(clone, {\n Identifier(path) {\n const paramIndex = fn.params.findIndex(\n (p) => (p as t.Identifier).name === path.node.name,\n );\n if (paramIndex !== -1) {\n path.replaceWith(caller.node.arguments[paramIndex]);\n path.skip();\n }\n },\n noScope: true,\n });\n\n caller.replaceWith(clone);\n}\n\n/**\n * Example:\n * `function alias(a, b) { return decode(b - 938, a); } alias(1071, 1077);`\n * ->\n * `decode(1077 - 938, 1071)`\n */\nexport function inlineFunctionAliases(binding: Binding): { changes: number } {\n const state = { changes: 0 };\n const refs = [...binding.referencePaths];\n for (const ref of refs) {\n const fn = findParent(ref, m.functionDeclaration());\n\n // E.g. alias\n const fnName = m.capture(m.anyString());\n // E.g. decode(b - 938, a)\n const returnedCall = m.capture(\n m.callExpression(\n m.identifier(binding.identifier.name),\n m.anyList(m.slice({ min: 2 })),\n ),\n );\n const matcher = m.functionDeclaration(\n m.identifier(fnName),\n m.anyList(m.slice({ min: 2 })),\n m.blockStatement([m.returnStatement(returnedCall)]),\n );\n\n if (fn && matcher.match(fn.node)) {\n // Avoid false positives of functions that return a string\n // It's only a wrapper if the function's params are used in the decode call\n const paramUsedInDecodeCall = fn.node.params.some((param) => {\n const binding = fn.scope.getBinding((param as t.Identifier).name);\n return binding?.referencePaths.some((ref) =>\n ref.findParent((p) => p.node === returnedCall.current),\n );\n });\n if (!paramUsedInDecodeCall) continue;\n\n const fnBinding = fn.scope.parent.getBinding(fnName.current!);\n if (!fnBinding) continue;\n // Check all further aliases (`function alias2(a, b) { return alias(a - 1, b + 3); }`)\n const fnRefs = fnBinding.referencePaths;\n refs.push(...fnRefs);\n\n // E.g. [alias(1071, 1077), alias(1, 2)]\n const callRefs = fnRefs\n .filter(\n (ref) =>\n t.isCallExpression(ref.parent) &&\n t.isIdentifier(ref.parent.callee, { name: fnName.current! }),\n )\n .map((ref) => ref.parentPath!) as NodePath<t.CallExpression>[];\n\n for (const callRef of callRefs) {\n inlineFunction(fn.node, callRef);\n state.changes++;\n }\n\n fn.remove();\n state.changes++;\n }\n }\n\n // Have to crawl again because renaming messed up the references\n binding.scope.crawl();\n return state;\n}\n\n/**\n * Recursively renames all references to the binding.\n * Make sure the binding name isn't shadowed anywhere!\n *\n * Example: `var alias = decoder; alias(1);` -> `decoder(1);`\n */\n\nexport function inlineVariableAliases(\n binding: Binding,\n targetName = binding.identifier.name,\n): { changes: number } {\n const state = { changes: 0 };\n const refs = [...binding.referencePaths];\n const varName = m.capture(m.anyString());\n const matcher = m.or(\n m.variableDeclarator(\n m.identifier(varName),\n m.identifier(binding.identifier.name),\n ),\n m.assignmentExpression(\n '=',\n m.identifier(varName),\n m.identifier(binding.identifier.name),\n ),\n );\n\n for (const ref of refs) {\n if (matcher.match(ref.parent)) {\n const varScope = ref.scope;\n const varBinding = varScope.getBinding(varName.current!);\n if (!varBinding) continue;\n\n // Check all further aliases (`var alias2 = alias;`)\n state.changes += inlineVariableAliases(varBinding, targetName).changes;\n\n if (ref.parentPath?.isAssignmentExpression()) {\n // Remove `var alias;` when the assignment happens separately\n varBinding.path.remove();\n\n if (t.isExpressionStatement(ref.parentPath.parent)) {\n // Remove `alias = decoder;`\n ref.parentPath.remove();\n } else {\n // Replace `(alias = decoder)(1);` with `decoder(1);`\n ref.parentPath.replaceWith(ref.parentPath.node.right);\n }\n } else if (ref.parentPath?.isVariableDeclarator()) {\n // Remove `alias = decoder;` of declarator\n ref.parentPath.remove();\n }\n state.changes++;\n } else {\n // Rename the reference\n ref.replaceWith(t.identifier(targetName));\n state.changes++;\n }\n }\n\n return state;\n}\n",
|
|
13
|
-
"import traverse, { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { codePreview } from './generator';\n\nexport function renameFast(binding: Binding, newName: string): void {\n binding.referencePaths.forEach((ref) => {\n if (!ref.isIdentifier()) {\n throw new Error(\n `Unexpected reference (${ref.type}): ${codePreview(ref.node)}`,\n );\n }\n\n // To avoid conflicts with other bindings of the same name\n if (ref.scope.hasBinding(newName)) ref.scope.rename(newName);\n ref.node.name = newName;\n });\n\n // Also update assignments\n const patternMatcher = m.assignmentExpression(\n '=',\n m.or(m.arrayPattern(), m.objectPattern()),\n );\n binding.constantViolations.forEach((ref) => {\n // To avoid conflicts with other bindings of the same name\n if (ref.scope.hasBinding(newName)) ref.scope.rename(newName);\n\n if (ref.isAssignmentExpression() && t.isIdentifier(ref.node.left)) {\n ref.node.left.name = newName;\n } else if (ref.isUpdateExpression() && t.isIdentifier(ref.node.argument)) {\n ref.node.argument.name = newName;\n } else if (ref.isVariableDeclarator() && t.isIdentifier(ref.node.id)) {\n ref.node.id.name = newName;\n } else if (ref.isFor() || patternMatcher.match(ref.node)) {\n traverse(ref.node, {\n Identifier(path) {\n if (path.scope !== ref.scope) return path.skip();\n if (path.node.name === binding.identifier.name) {\n path.node.name = newName;\n }\n },\n noScope: true,\n });\n } else {\n throw new Error(\n `Unexpected constant violation (${ref.type}): ${codePreview(ref.node)}`,\n );\n }\n });\n\n binding.scope.removeOwnBinding(binding.identifier.name);\n binding.scope.bindings[newName] = binding;\n binding.identifier.name = newName;\n}\n\nexport function renameParameters(\n path: NodePath<t.Function>,\n newNames: string[],\n): void {\n const params = path.node.params as t.Identifier[];\n for (let i = 0; i < Math.min(params.length, newNames.length); i++) {\n const binding = path.scope.getBinding(params[i].name)!;\n renameFast(binding, newNames[i]);\n }\n}\n",
|
|
14
|
-
"import traverse, { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { codePreview } from './generator';\n\nexport function renameFast(binding: Binding, newName: string): void {\n binding.referencePaths.forEach((ref) => {\n if (!ref.isIdentifier()) {\n throw new Error(\n `Unexpected reference (${ref.type}): ${codePreview(ref.node)}`,\n );\n }\n\n // To avoid conflicts with other bindings of the same name\n if (ref.scope.hasBinding(newName)) ref.scope.rename(newName);\n ref.node.name = newName;\n });\n\n // Also update assignments\n const patternMatcher = m.assignmentExpression(\n '=',\n m.or(m.arrayPattern(), m.objectPattern()),\n );\n binding.constantViolations.forEach((ref) => {\n // To avoid conflicts with other bindings of the same name\n if (ref.scope.hasBinding(newName)) ref.scope.rename(newName);\n\n if (ref.isAssignmentExpression() && t.isIdentifier(ref.node.left)) {\n ref.node.left.name = newName;\n } else if (ref.isUpdateExpression() && t.isIdentifier(ref.node.argument)) {\n ref.node.argument.name = newName;\n } else if (ref.isVariableDeclarator() && t.isIdentifier(ref.node.id)) {\n ref.node.id.name = newName;\n } else if (ref.isFor() || patternMatcher.match(ref.node)) {\n traverse(ref.node, {\n Identifier(path) {\n if (path.scope !== ref.scope) return path.skip();\n if (path.node.name === binding.identifier.name) {\n path.node.name = newName;\n }\n },\n noScope: true,\n });\n } else {\n throw new Error(\n `Unexpected constant violation (${ref.type}): ${codePreview(ref.node)}`,\n );\n }\n });\n\n binding.scope.removeOwnBinding(binding.identifier.name);\n binding.scope.bindings[newName] = binding;\n binding.identifier.name = newName;\n}\n\nexport function renameParameters(\n path: NodePath<t.Function>,\n newNames: string[],\n): void {\n const params = path.node.params as t.Identifier[];\n for (let i = 0; i < Math.min(params.length, newNames.length); i++) {\n const binding = path.scope.getBinding(params[i].name)!;\n renameFast(binding, newNames[i]);\n }\n}\n",
|
|
15
|
-
"import traverse, {\n Node,\n TraverseOptions,\n Visitor,\n visitors,\n} from '@babel/traverse';\nimport debug from 'debug';\n\nconst logger = debug('webcrack:transforms');\n\nexport async function applyTransformAsync<TOptions>(\n ast: Node,\n transform: AsyncTransform<TOptions>,\n options?: TOptions,\n): Promise<TransformState> {\n logger(`${transform.name}: started`);\n const state: TransformState = { changes: 0 };\n\n await transform.run?.(ast, state, options);\n if (transform.visitor)\n traverse(ast, transform.visitor(options), undefined, state);\n\n logger(`${transform.name}: finished with ${state.changes} changes`);\n return state;\n}\n\nexport function applyTransform<TOptions>(\n ast: Node,\n transform: Transform<TOptions>,\n options?: TOptions,\n noScopeOverride?: boolean,\n): TransformState {\n logger(`${transform.name}: started`);\n const state: TransformState = { changes: 0 };\n transform.run?.(ast, state, options);\n\n if (transform.visitor) {\n const visitor = transform.visitor(\n options,\n ) as TraverseOptions<TransformState>;\n visitor.noScope = noScopeOverride || !transform.scope;\n traverse(ast, visitor, undefined, state);\n }\n\n logger(`${transform.name}: finished with ${state.changes} changes`);\n return state;\n}\n\nexport function applyTransforms(\n ast: Node,\n transforms: Transform[],\n options: { noScope?: boolean; name?: string; log?: boolean } = {},\n): TransformState {\n options.log ??= true;\n const name = options.name ?? transforms.map((t) => t.name).join(', ');\n if (options.log) logger(`${name}: started`);\n const state: TransformState = { changes: 0 };\n\n for (const transform of transforms) {\n transform.run?.(ast, state);\n }\n\n const traverseOptions = transforms.flatMap((t) => t.visitor?.() ?? []);\n if (traverseOptions.length > 0) {\n const visitor: TraverseOptions<TransformState> =\n visitors.merge(traverseOptions);\n visitor.noScope = options.noScope || transforms.every((t) => !t.scope);\n traverse(ast, visitor, undefined, state);\n }\n\n if (options.log) logger(`${name}: finished with ${state.changes} changes`);\n return state;\n}\n\nexport function mergeTransforms(options: {\n name: string;\n tags: Tag[];\n transforms: Transform[];\n}): Transform {\n return {\n name: options.name,\n tags: options.tags,\n scope: options.transforms.some((t) => t.scope),\n visitor() {\n return visitors.merge(\n options.transforms.flatMap((t) => t.visitor?.() ?? []),\n );\n }\n };\n}\n\nexport interface TransformState {\n changes: number;\n}\n\nexport interface Transform<TOptions = unknown> {\n name: string;\n tags: Tag[];\n scope?: boolean;\n run?: (ast: Node, state: TransformState, options?: TOptions) => void;\n visitor?: (options?: TOptions) => Visitor<TransformState>;\n}\n\nexport interface AsyncTransform<TOptions = unknown>\n extends Transform<TOptions> {\n run?: (ast: Node, state: TransformState, options?: TOptions) => Promise<void>;\n}\n\nexport type Tag = 'safe' | 'unsafe';\n",
|
|
16
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'merge-strings',\n tags: ['safe'],\n visitor() {\n const left = m.capture(m.stringLiteral(m.anyString()));\n const right = m.capture(m.stringLiteral(m.anyString()));\n\n const matcher = m.binaryExpression('+', left, right);\n const nestedMatcher = m.binaryExpression(\n '+',\n m.binaryExpression('+', m.anything(), left),\n right,\n );\n\n return {\n BinaryExpression: {\n exit(path) {\n if (matcher.match(path.node)) {\n // \"a\" + \"b\" -> \"ab\"\n path.replaceWith(\n t.stringLiteral(left.current!.value + right.current!.value),\n );\n this.changes++;\n }\n },\n },\n StringLiteral: {\n exit(path) {\n if (nestedMatcher.match(path.parent)) {\n // (a + \"b\") + \"c\" -> a + \"bc\"\n // left ^ ^ right (path)\n left.current!.value += right.current!.value;\n path.remove();\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
17
|
-
"import { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { callExpression } from '@codemod/matchers';\nimport { constMemberExpression, findParent, infiniteLoop } from '../ast-utils';\nimport { StringArray } from './string-array';\n\nexport type ArrayRotator = NodePath<t.ExpressionStatement>;\n\n/**\n * Structure:\n * ```\n * iife (>= 2 parameters, called with 0 or 2 arguments)\n * 2 variable declarations (array and decoder)\n * endless loop:\n * try:\n * if/break/parseInt/array.push(array.shift())\n * catch:\n * array.push(array.shift())\n * ```\n */\nexport function findArrayRotator(\n stringArray: StringArray,\n): ArrayRotator | undefined {\n // e.g. 'array'\n const arrayIdentifier = m.capture(m.identifier());\n\n // e.g. array.push(array.shift())\n const pushShift = m.callExpression(\n constMemberExpression(arrayIdentifier, 'push'),\n [\n m.callExpression(\n constMemberExpression(m.fromCapture(arrayIdentifier), 'shift'),\n ),\n ],\n );\n\n const callMatcher = m.callExpression(\n m.functionExpression(\n null,\n m.anything(),\n m.blockStatement(\n m.anyList(\n m.zeroOrMore(),\n infiniteLoop(\n m.matcher((node) => {\n return (\n m\n .containerOf(callExpression(m.identifier('parseInt')))\n .match(node) &&\n m\n .blockStatement([\n m.tryStatement(\n m.containerOf(pushShift),\n m.containerOf(pushShift),\n ),\n ])\n .match(node)\n );\n }),\n ),\n ),\n ),\n ),\n );\n\n const matcher = m.expressionStatement(\n m.or(callMatcher, m.unaryExpression('!', callMatcher)),\n );\n\n for (const ref of stringArray.references) {\n const rotator = findParent(ref, matcher);\n if (rotator) {\n return rotator;\n }\n }\n}\n",
|
|
18
|
-
"import { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { callExpression } from '@codemod/matchers';\nimport { constMemberExpression, findParent, infiniteLoop } from '../ast-utils';\nimport { StringArray } from './string-array';\n\nexport type ArrayRotator = NodePath<t.ExpressionStatement>;\n\n/**\n * Structure:\n * ```\n * iife (>= 2 parameters, called with 0 or 2 arguments)\n * 2 variable declarations (array and decoder)\n * endless loop:\n * try:\n * if/break/parseInt/array.push(array.shift())\n * catch:\n * array.push(array.shift())\n * ```\n */\nexport function findArrayRotator(\n stringArray: StringArray,\n): ArrayRotator | undefined {\n // e.g. 'array'\n const arrayIdentifier = m.capture(m.identifier());\n\n // e.g. array.push(array.shift())\n const pushShift = m.callExpression(\n constMemberExpression(arrayIdentifier, 'push'),\n [\n m.callExpression(\n constMemberExpression(m.fromCapture(arrayIdentifier), 'shift'),\n ),\n ],\n );\n\n const callMatcher = m.callExpression(\n m.functionExpression(\n null,\n m.anything(),\n m.blockStatement(\n m.anyList(\n m.zeroOrMore(),\n infiniteLoop(\n m.matcher((node) => {\n return (\n m\n .containerOf(callExpression(m.identifier('parseInt')))\n .match(node) &&\n m\n .blockStatement([\n m.tryStatement(\n m.containerOf(pushShift),\n m.containerOf(pushShift),\n ),\n ])\n .match(node)\n );\n }),\n ),\n ),\n ),\n ),\n );\n\n const matcher = m.expressionStatement(\n m.or(callMatcher, m.unaryExpression('!', callMatcher)),\n );\n\n for (const ref of stringArray.references) {\n const rotator = findParent(ref, matcher);\n if (rotator) {\n return rotator;\n }\n }\n}\n",
|
|
19
|
-
"import { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport { FunctionExpression } from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport {\n Transform,\n applyTransform,\n constKey,\n constMemberExpression,\n createFunctionMatcher,\n findParent,\n getPropName,\n inlineFunction,\n isReadonlyObject,\n} from '../ast-utils';\nimport mergeStrings from '../unminify/transforms/merge-strings';\n\n/**\n * Explanation: https://excalidraw.com/#json=0vehUdrfSS635CNPEQBXl,hDOd-UO9ETfSDWT9MxVX-A\n */\n\nexport default {\n name: 'control-flow-object',\n tags: ['safe'],\n scope: true,\n visitor() {\n const varId = m.capture(m.identifier());\n const propertyName = m.matcher<string>((name) => /^[a-z]{5}$/i.test(name));\n const propertyKey = constKey(propertyName);\n const propertyValue = m.or(\n // E.g. \"6|0|4|3|1|5|2\"\n m.stringLiteral(),\n // E.g. function (a, b) { return a + b }\n createFunctionMatcher(2, (left, right) => [\n m.returnStatement(\n m.or(\n m.binaryExpression(undefined, left, right),\n m.logicalExpression(undefined, left, right),\n m.binaryExpression(undefined, right, left),\n m.logicalExpression(undefined, right, left),\n ),\n ),\n ]),\n // E.g. function (a, b, c) { return a(b, c) } with an arbitrary number of arguments\n m.matcher<FunctionExpression>((node) => {\n return (\n t.isFunctionExpression(node) &&\n createFunctionMatcher(node.params.length, (...params) => [\n m.returnStatement(m.callExpression(params[0], params.slice(1))),\n ]).match(node)\n );\n }),\n // E.g. function (a, ...b) { return a(...b) }\n (() => {\n const fnName = m.capture(m.identifier());\n const restName = m.capture(m.identifier());\n\n return m.functionExpression(\n undefined,\n [fnName, m.restElement(restName)],\n m.blockStatement([\n m.returnStatement(\n m.callExpression(m.fromCapture(fnName), [\n m.spreadElement(m.fromCapture(restName)),\n ]),\n ),\n ]),\n );\n })(),\n );\n // E.g. \"rLxJs\": \"6|0|4|3|1|5|2\"\n const objectProperties = m.capture(\n m.arrayOf(m.objectProperty(propertyKey, propertyValue)),\n );\n const aliasId = m.capture(m.identifier());\n const aliasVar = m.variableDeclaration(m.anything(), [\n m.variableDeclarator(aliasId, m.fromCapture(varId)),\n ]);\n // E.g. \"rLxJs\"\n const assignedKey = m.capture(propertyName);\n // E.g. \"6|0|4|3|1|5|2\"\n const assignedValue = m.capture(propertyValue);\n // E.g. obj.rLxJs = \"6|0|4|3|1|5|2\"\n const assignment = m.expressionStatement(\n m.assignmentExpression(\n '=',\n constMemberExpression(m.fromCapture(varId), assignedKey),\n assignedValue,\n ),\n );\n const looseAssignment = m.expressionStatement(\n m.assignmentExpression(\n '=',\n constMemberExpression(m.fromCapture(varId), assignedKey),\n ),\n );\n // E.g. obj.rLxJs\n const memberAccess = constMemberExpression(\n m.or(m.fromCapture(varId), m.fromCapture(aliasId)),\n propertyName,\n );\n const varMatcher = m.variableDeclarator(\n varId,\n m.capture(m.objectExpression(objectProperties)),\n );\n\n function isConstantBinding(binding: Binding) {\n // Workaround because sometimes babel treats the VariableDeclarator/binding itself as a violation\n return binding.constant || binding.constantViolations[0] === binding.path;\n }\n\n function transform(path: NodePath<t.VariableDeclarator>) {\n let changes = 0;\n if (varMatcher.match(path.node)) {\n // Verify all references to make sure they match how the obfuscator\n // would have generated the code (no reassignments, etc.)\n const binding = path.scope.getBinding(varId.current!.name);\n if (!binding) return changes;\n if (!isConstantBinding(binding)) return changes;\n if (!transformObjectKeys(binding)) return changes;\n if (!isReadonlyObject(binding, memberAccess)) return changes;\n\n const props = new Map(\n objectProperties.current!.map((p) => [\n getPropName(p.key),\n p.value as t.FunctionExpression | t.StringLiteral,\n ]),\n );\n if (!props.size) return changes;\n\n const oldRefs = [...binding.referencePaths];\n\n // Have to loop backwards because we might replace a node that\n // contains another reference to the binding (https://github.com/babel/babel/issues/12943)\n [...binding.referencePaths].reverse().forEach((ref) => {\n const memberPath = ref.parentPath as NodePath<t.MemberExpression>;\n const propName = getPropName(memberPath.node.property)!;\n const value = props.get(propName)!;\n\n if (t.isStringLiteral(value)) {\n memberPath.replaceWith(value);\n } else {\n inlineFunction(\n value,\n memberPath.parentPath as NodePath<t.CallExpression>,\n );\n }\n changes++;\n });\n\n oldRefs.forEach((ref) => {\n const varDeclarator = findParent(ref, m.variableDeclarator());\n if (varDeclarator) changes += transform(varDeclarator);\n });\n\n path.remove();\n changes++;\n }\n return changes;\n }\n\n /**\n * When the `Transform Object Keys` option is enabled, the obfuscator generates an empty\n * object, assigns the properties later and adds an alias variable to the object.\n * This function undoes that by converting the assignments to inline object properties.\n *\n * In some forked versions of the obfuscator, some properties may be in the object\n * and others are assigned later.\n */\n function transformObjectKeys(objBinding: Binding): boolean {\n const container = objBinding.path.parentPath!.container as t.Statement[];\n const startIndex = (objBinding.path.parentPath!.key as number) + 1;\n const properties: t.ObjectProperty[] = [];\n\n for (let i = startIndex; i < container.length; i++) {\n const statement = container[i];\n\n // Example: _0x29d709[\"kHAOU\"] = \"5|1|2\" + \"|4|3|\" + \"0|6\";\n // For performance reasons, only traverse if it is a potential match (value doesn't matter)\n if (looseAssignment.match(statement)) {\n applyTransform(statement, mergeStrings);\n }\n\n if (assignment.match(statement)) {\n properties.push(\n t.objectProperty(\n t.identifier(assignedKey.current!),\n assignedValue.current!,\n ),\n );\n } else {\n break;\n }\n }\n\n // If all properties are in the object then there typically won't be an alias variable\n const aliasAssignment = container[startIndex + properties.length];\n if (!aliasVar.match(aliasAssignment)) return true;\n\n // Avoid false positives\n if (objBinding.references !== properties.length + 1) return false;\n\n const aliasBinding = objBinding.scope.getBinding(aliasId.current!.name)!;\n if (!isReadonlyObject(aliasBinding, memberAccess)) return false;\n\n objectProperties.current!.push(...properties);\n container.splice(startIndex, properties.length);\n objBinding.referencePaths = aliasBinding.referencePaths;\n objBinding.references = aliasBinding.references;\n objBinding.identifier.name = aliasBinding.identifier.name;\n aliasBinding.path.remove();\n return true;\n }\n\n return {\n VariableDeclarator: {\n exit(path) {\n this.changes += transform(path);\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
20
|
-
"import { Binding, NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport { FunctionExpression } from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport {\n Transform,\n applyTransform,\n constKey,\n constMemberExpression,\n createFunctionMatcher,\n findParent,\n getPropName,\n inlineFunction,\n isReadonlyObject,\n} from '../ast-utils';\nimport mergeStrings from '../unminify/transforms/merge-strings';\n\n/**\n * Explanation: https://excalidraw.com/#json=0vehUdrfSS635CNPEQBXl,hDOd-UO9ETfSDWT9MxVX-A\n */\n\nexport default {\n name: 'control-flow-object',\n tags: ['safe'],\n scope: true,\n visitor() {\n const varId = m.capture(m.identifier());\n const propertyName = m.matcher<string>((name) => /^[a-z]{5}$/i.test(name));\n const propertyKey = constKey(propertyName);\n const propertyValue = m.or(\n // E.g. \"6|0|4|3|1|5|2\"\n m.stringLiteral(),\n // E.g. function (a, b) { return a + b }\n createFunctionMatcher(2, (left, right) => [\n m.returnStatement(\n m.or(\n m.binaryExpression(undefined, left, right),\n m.logicalExpression(undefined, left, right),\n m.binaryExpression(undefined, right, left),\n m.logicalExpression(undefined, right, left),\n ),\n ),\n ]),\n // E.g. function (a, b, c) { return a(b, c) } with an arbitrary number of arguments\n m.matcher<FunctionExpression>((node) => {\n return (\n t.isFunctionExpression(node) &&\n createFunctionMatcher(node.params.length, (...params) => [\n m.returnStatement(m.callExpression(params[0], params.slice(1))),\n ]).match(node)\n );\n }),\n // E.g. function (a, ...b) { return a(...b) }\n (() => {\n const fnName = m.capture(m.identifier());\n const restName = m.capture(m.identifier());\n\n return m.functionExpression(\n undefined,\n [fnName, m.restElement(restName)],\n m.blockStatement([\n m.returnStatement(\n m.callExpression(m.fromCapture(fnName), [\n m.spreadElement(m.fromCapture(restName)),\n ]),\n ),\n ]),\n );\n })(),\n );\n // E.g. \"rLxJs\": \"6|0|4|3|1|5|2\"\n const objectProperties = m.capture(\n m.arrayOf(m.objectProperty(propertyKey, propertyValue)),\n );\n const aliasId = m.capture(m.identifier());\n const aliasVar = m.variableDeclaration(m.anything(), [\n m.variableDeclarator(aliasId, m.fromCapture(varId)),\n ]);\n // E.g. \"rLxJs\"\n const assignedKey = m.capture(propertyName);\n // E.g. \"6|0|4|3|1|5|2\"\n const assignedValue = m.capture(propertyValue);\n // E.g. obj.rLxJs = \"6|0|4|3|1|5|2\"\n const assignment = m.expressionStatement(\n m.assignmentExpression(\n '=',\n constMemberExpression(m.fromCapture(varId), assignedKey),\n assignedValue,\n ),\n );\n const looseAssignment = m.expressionStatement(\n m.assignmentExpression(\n '=',\n constMemberExpression(m.fromCapture(varId), assignedKey),\n ),\n );\n // E.g. obj.rLxJs\n const memberAccess = constMemberExpression(\n m.or(m.fromCapture(varId), m.fromCapture(aliasId)),\n propertyName,\n );\n const varMatcher = m.variableDeclarator(\n varId,\n m.capture(m.objectExpression(objectProperties)),\n );\n\n function isConstantBinding(binding: Binding) {\n // Workaround because sometimes babel treats the VariableDeclarator/binding itself as a violation\n return binding.constant || binding.constantViolations[0] === binding.path;\n }\n\n function transform(path: NodePath<t.VariableDeclarator>) {\n let changes = 0;\n if (varMatcher.match(path.node)) {\n // Verify all references to make sure they match how the obfuscator\n // would have generated the code (no reassignments, etc.)\n const binding = path.scope.getBinding(varId.current!.name);\n if (!binding) return changes;\n if (!isConstantBinding(binding)) return changes;\n if (!transformObjectKeys(binding)) return changes;\n if (!isReadonlyObject(binding, memberAccess)) return changes;\n\n const props = new Map(\n objectProperties.current!.map((p) => [\n getPropName(p.key),\n p.value as t.FunctionExpression | t.StringLiteral,\n ]),\n );\n if (!props.size) return changes;\n\n const oldRefs = [...binding.referencePaths];\n\n // Have to loop backwards because we might replace a node that\n // contains another reference to the binding (https://github.com/babel/babel/issues/12943)\n [...binding.referencePaths].reverse().forEach((ref) => {\n const memberPath = ref.parentPath as NodePath<t.MemberExpression>;\n const propName = getPropName(memberPath.node.property)!;\n const value = props.get(propName)!;\n\n if (t.isStringLiteral(value)) {\n memberPath.replaceWith(value);\n } else {\n inlineFunction(\n value,\n memberPath.parentPath as NodePath<t.CallExpression>,\n );\n }\n changes++;\n });\n\n oldRefs.forEach((ref) => {\n const varDeclarator = findParent(ref, m.variableDeclarator());\n if (varDeclarator) changes += transform(varDeclarator);\n });\n\n path.remove();\n changes++;\n }\n return changes;\n }\n\n /**\n * When the `Transform Object Keys` option is enabled, the obfuscator generates an empty\n * object, assigns the properties later and adds an alias variable to the object.\n * This function undoes that by converting the assignments to inline object properties.\n *\n * In some forked versions of the obfuscator, some properties may be in the object\n * and others are assigned later.\n */\n function transformObjectKeys(objBinding: Binding): boolean {\n const container = objBinding.path.parentPath!.container as t.Statement[];\n const startIndex = (objBinding.path.parentPath!.key as number) + 1;\n const properties: t.ObjectProperty[] = [];\n\n for (let i = startIndex; i < container.length; i++) {\n const statement = container[i];\n\n // Example: _0x29d709[\"kHAOU\"] = \"5|1|2\" + \"|4|3|\" + \"0|6\";\n // For performance reasons, only traverse if it is a potential match (value doesn't matter)\n if (looseAssignment.match(statement)) {\n applyTransform(statement, mergeStrings);\n }\n\n if (assignment.match(statement)) {\n properties.push(\n t.objectProperty(\n t.identifier(assignedKey.current!),\n assignedValue.current!,\n ),\n );\n } else {\n break;\n }\n }\n\n // If all properties are in the object then there typically won't be an alias variable\n const aliasAssignment = container[startIndex + properties.length];\n if (!aliasVar.match(aliasAssignment)) return true;\n\n // Avoid false positives\n if (objBinding.references !== properties.length + 1) return false;\n\n const aliasBinding = objBinding.scope.getBinding(aliasId.current!.name)!;\n if (!isReadonlyObject(aliasBinding, memberAccess)) return false;\n\n objectProperties.current!.push(...properties);\n container.splice(startIndex, properties.length);\n objBinding.referencePaths = aliasBinding.referencePaths;\n objBinding.references = aliasBinding.references;\n objBinding.identifier.name = aliasBinding.identifier.name;\n aliasBinding.path.remove();\n return true;\n }\n\n return {\n VariableDeclarator: {\n exit(path) {\n this.changes += transform(path);\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
21
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, constMemberExpression, infiniteLoop } from '../ast-utils';\n\nexport default {\n name: 'control-flow-switch',\n tags: ['safe'],\n visitor() {\n const sequenceName = m.capture(m.identifier());\n const sequenceString = m.capture(\n m.matcher<string>((s) => /^\\d+(\\|\\d+)*$/.test(s)),\n );\n const iterator = m.capture(m.identifier());\n\n const cases = m.capture(\n m.arrayOf(\n m.switchCase(\n m.stringLiteral(m.matcher((s) => /^\\d+$/.test(s))),\n m.anyList(\n m.zeroOrMore(),\n m.or(m.continueStatement(), m.returnStatement()),\n ),\n ),\n ),\n );\n\n const matcher = m.blockStatement(\n m.anyList<t.Statement>(\n // E.g. const sequence = \"2|4|3|0|1\".split(\"|\")\n m.variableDeclaration(undefined, [\n m.variableDeclarator(\n sequenceName,\n m.callExpression(\n constMemberExpression(m.stringLiteral(sequenceString), 'split'),\n [m.stringLiteral('|')],\n ),\n ),\n ]),\n // E.g. let iterator = 0 or -0x1a70 + 0x93d + 0x275 * 0x7\n m.variableDeclaration(undefined, [m.variableDeclarator(iterator)]),\n infiniteLoop(\n m.blockStatement([\n m.switchStatement(\n // E.g. switch (sequence[iterator++]) {\n m.memberExpression(\n m.fromCapture(sequenceName),\n m.updateExpression('++', m.fromCapture(iterator)),\n true,\n ),\n cases,\n ),\n m.breakStatement(),\n ]),\n ),\n m.zeroOrMore(),\n ),\n );\n\n return {\n BlockStatement: {\n exit(path) {\n if (!matcher.match(path.node)) return;\n\n const caseStatements = new Map(\n cases.current!.map((c) => [\n (c.test as t.StringLiteral).value,\n t.isContinueStatement(c.consequent.at(-1))\n ? c.consequent.slice(0, -1)\n : c.consequent,\n ]),\n );\n\n const sequence = sequenceString.current!.split('|');\n const newStatements = sequence.flatMap((s) => caseStatements.get(s)!);\n\n path.node.body.splice(0, 3, ...newStatements);\n this.changes += newStatements.length + 3;\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
22
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, constMemberExpression, infiniteLoop } from '../ast-utils';\n\nexport default {\n name: 'control-flow-switch',\n tags: ['safe'],\n visitor() {\n const sequenceName = m.capture(m.identifier());\n const sequenceString = m.capture(\n m.matcher<string>((s) => /^\\d+(\\|\\d+)*$/.test(s)),\n );\n const iterator = m.capture(m.identifier());\n\n const cases = m.capture(\n m.arrayOf(\n m.switchCase(\n m.stringLiteral(m.matcher((s) => /^\\d+$/.test(s))),\n m.anyList(\n m.zeroOrMore(),\n m.or(m.continueStatement(), m.returnStatement()),\n ),\n ),\n ),\n );\n\n const matcher = m.blockStatement(\n m.anyList<t.Statement>(\n // E.g. const sequence = \"2|4|3|0|1\".split(\"|\")\n m.variableDeclaration(undefined, [\n m.variableDeclarator(\n sequenceName,\n m.callExpression(\n constMemberExpression(m.stringLiteral(sequenceString), 'split'),\n [m.stringLiteral('|')],\n ),\n ),\n ]),\n // E.g. let iterator = 0 or -0x1a70 + 0x93d + 0x275 * 0x7\n m.variableDeclaration(undefined, [m.variableDeclarator(iterator)]),\n infiniteLoop(\n m.blockStatement([\n m.switchStatement(\n // E.g. switch (sequence[iterator++]) {\n m.memberExpression(\n m.fromCapture(sequenceName),\n m.updateExpression('++', m.fromCapture(iterator)),\n true,\n ),\n cases,\n ),\n m.breakStatement(),\n ]),\n ),\n m.zeroOrMore(),\n ),\n );\n\n return {\n BlockStatement: {\n exit(path) {\n if (!matcher.match(path.node)) return;\n\n const caseStatements = new Map(\n cases.current!.map((c) => [\n (c.test as t.StringLiteral).value,\n t.isContinueStatement(c.consequent.at(-1))\n ? c.consequent.slice(0, -1)\n : c.consequent,\n ]),\n );\n\n const sequence = sequenceString.current!.split('|');\n const newStatements = sequence.flatMap((s) => caseStatements.get(s)!);\n\n path.node.body.splice(0, 3, ...newStatements);\n this.changes += newStatements.length + 3;\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
23
|
-
"import { NodePath, Scope } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, renameFast } from '../ast-utils';\n\nexport default {\n name: 'dead-code',\n tags: ['unsafe'],\n scope: true,\n visitor() {\n const stringComparison = m.binaryExpression(\n m.or('===', '==', '!==', '!='),\n m.stringLiteral(),\n m.stringLiteral(),\n );\n const testMatcher = m.or(\n stringComparison,\n m.unaryExpression('!', stringComparison),\n );\n\n return {\n 'IfStatement|ConditionalExpression': {\n exit(_path) {\n const path = _path as NodePath<\n t.IfStatement | t.ConditionalExpression\n >;\n\n if (!testMatcher.match(path.node.test)) return;\n\n const { scope } = path;\n // If statements can contain variables that shadow variables in the parent scope.\n // Since the block scope is merged with the parent scope, we need to rename those\n // variables to avoid duplicate declarations.\n function renameShadowedVariables(localScope: Scope) {\n if (localScope === scope) return;\n for (const name in localScope.bindings) {\n if (scope.hasBinding(name)) {\n renameFast(localScope.bindings[name], scope.generateUid(name));\n }\n }\n }\n\n if (path.get('test').evaluateTruthy()) {\n renameShadowedVariables(path.get('consequent').scope);\n replace(path, path.node.consequent);\n } else if (path.node.alternate) {\n renameShadowedVariables(path.get('alternate').scope);\n replace(path, path.node.alternate);\n } else {\n path.remove();\n }\n\n this.changes++;\n },\n },\n };\n },\n} satisfies Transform;\n\nfunction replace(path: NodePath, node: t.Node) {\n if (t.isBlockStatement(node)) {\n path.replaceWithMultiple(node.body);\n } else {\n path.replaceWith(node);\n }\n}\n",
|
|
24
|
-
"import { NodePath, Scope } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, renameFast } from '../ast-utils';\n\nexport default {\n name: 'dead-code',\n tags: ['unsafe'],\n scope: true,\n visitor() {\n const stringComparison = m.binaryExpression(\n m.or('===', '==', '!==', '!='),\n m.stringLiteral(),\n m.stringLiteral(),\n );\n const testMatcher = m.or(\n stringComparison,\n m.unaryExpression('!', stringComparison),\n );\n\n return {\n 'IfStatement|ConditionalExpression': {\n exit(_path) {\n const path = _path as NodePath<\n t.IfStatement | t.ConditionalExpression\n >;\n\n if (!testMatcher.match(path.node.test)) return;\n\n const { scope } = path;\n // If statements can contain variables that shadow variables in the parent scope.\n // Since the block scope is merged with the parent scope, we need to rename those\n // variables to avoid duplicate declarations.\n function renameShadowedVariables(localScope: Scope) {\n if (localScope === scope) return;\n for (const name in localScope.bindings) {\n if (scope.hasBinding(name)) {\n renameFast(localScope.bindings[name], scope.generateUid(name));\n }\n }\n }\n\n if (path.get('test').evaluateTruthy()) {\n renameShadowedVariables(path.get('consequent').scope);\n replace(path, path.node.consequent);\n } else if (path.node.alternate) {\n renameShadowedVariables(path.get('alternate').scope);\n replace(path, path.node.alternate);\n } else {\n path.remove();\n }\n\n this.changes++;\n },\n },\n };\n },\n} satisfies Transform;\n\nfunction replace(path: NodePath, node: t.Node) {\n if (t.isBlockStatement(node)) {\n path.replaceWithMultiple(node.body);\n } else {\n path.replaceWith(node);\n }\n}\n",
|
|
25
|
-
"import { expression } from '@babel/template';\nimport { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { findParent, inlineVariable, renameFast } from '../ast-utils';\nimport { StringArray } from './string-array';\n\n/**\n * A function that is called with >= 1 numeric/string arguments\n * and returns a string from the string array. It may also decode\n * the string with Base64 or RC4.\n */\nexport class Decoder {\n name: string;\n path: NodePath<t.FunctionDeclaration>;\n\n constructor(name: string, path: NodePath<t.FunctionDeclaration>) {\n this.name = name;\n this.path = path;\n }\n\n collectCalls(): NodePath<t.CallExpression>[] {\n const calls: NodePath<t.CallExpression>[] = [];\n\n const literalArgument: m.Matcher<t.Expression> = m.or(\n m.binaryExpression(\n m.anything(),\n m.matcher((node) => literalArgument.match(node)),\n m.matcher((node) => literalArgument.match(node)),\n ),\n m.unaryExpression(\n '-',\n m.matcher((node) => literalArgument.match(node)),\n ),\n m.numericLiteral(),\n m.stringLiteral(),\n );\n\n const literalCall = m.callExpression(\n m.identifier(this.name),\n m.arrayOf(literalArgument),\n );\n const expressionCall = m.callExpression(\n m.identifier(this.name),\n m.arrayOf(m.anyExpression()),\n );\n\n const conditional = m.capture(m.conditionalExpression());\n const conditionalCall = m.callExpression(m.identifier(this.name), [\n conditional,\n ]);\n\n const buildExtractedConditional = expression`TEST ? CALLEE(CONSEQUENT) : CALLEE(ALTERNATE)`;\n\n const binding = this.path.scope.getBinding(this.name)!;\n for (const ref of binding.referencePaths) {\n if (conditionalCall.match(ref.parent)) {\n // decode(test ? 1 : 2) -> test ? decode(1) : decode(2)\n const [replacement] = ref.parentPath!.replaceWith(\n buildExtractedConditional({\n TEST: conditional.current!.test,\n CALLEE: ref.parent.callee,\n CONSEQUENT: conditional.current!.consequent,\n ALTERNATE: conditional.current!.alternate,\n }),\n );\n // some of the scope information is somehow lost after replacing\n replacement.scope.crawl();\n } else if (literalCall.match(ref.parent)) {\n calls.push(ref.parentPath as NodePath<t.CallExpression>);\n } else if (expressionCall.match(ref.parent)) {\n // var n = 1; decode(n); -> decode(1);\n ref.parentPath!.traverse({\n ReferencedIdentifier(path) {\n const varBinding = path.scope.getBinding(path.node.name)!;\n if (!varBinding) return;\n inlineVariable(varBinding, literalArgument, true);\n },\n });\n if (literalCall.match(ref.parent)) {\n calls.push(ref.parentPath as NodePath<t.CallExpression>);\n }\n }\n }\n\n return calls;\n }\n}\n\nexport function findDecoders(stringArray: StringArray): Decoder[] {\n const decoders: Decoder[] = [];\n\n const functionName = m.capture(m.anyString());\n const arrayIdentifier = m.capture(m.identifier());\n const matcher = m.functionDeclaration(\n m.identifier(functionName),\n m.anything(),\n m.blockStatement(\n m.anyList(\n // var array = getStringArray();\n m.variableDeclaration(undefined, [\n m.variableDeclarator(\n arrayIdentifier,\n m.callExpression(m.identifier(stringArray.name)),\n ),\n ]),\n m.zeroOrMore(),\n // var h = array[e]; return h;\n // or return array[e -= 254];\n m.containerOf(\n m.memberExpression(m.fromCapture(arrayIdentifier), undefined, true),\n ),\n m.zeroOrMore(),\n ),\n ),\n );\n\n for (const ref of stringArray.references) {\n const decoderFn = findParent(ref, matcher);\n\n if (decoderFn) {\n const oldName = functionName.current!;\n const newName = `__DECODE_${decoders.length}__`;\n const binding = decoderFn.scope.getBinding(oldName)!;\n renameFast(binding, newName);\n decoders.push(new Decoder(newName, decoderFn));\n }\n }\n\n return decoders;\n}\n",
|
|
26
|
-
"import { expression } from '@babel/template';\nimport { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { findParent, inlineVariable, renameFast } from '../ast-utils';\nimport { StringArray } from './string-array';\n\n/**\n * A function that is called with >= 1 numeric/string arguments\n * and returns a string from the string array. It may also decode\n * the string with Base64 or RC4.\n */\nexport class Decoder {\n name: string;\n path: NodePath<t.FunctionDeclaration>;\n\n constructor(name: string, path: NodePath<t.FunctionDeclaration>) {\n this.name = name;\n this.path = path;\n }\n\n collectCalls(): NodePath<t.CallExpression>[] {\n const calls: NodePath<t.CallExpression>[] = [];\n\n const literalArgument: m.Matcher<t.Expression> = m.or(\n m.binaryExpression(\n m.anything(),\n m.matcher((node) => literalArgument.match(node)),\n m.matcher((node) => literalArgument.match(node)),\n ),\n m.unaryExpression(\n '-',\n m.matcher((node) => literalArgument.match(node)),\n ),\n m.numericLiteral(),\n m.stringLiteral(),\n );\n\n const literalCall = m.callExpression(\n m.identifier(this.name),\n m.arrayOf(literalArgument),\n );\n const expressionCall = m.callExpression(\n m.identifier(this.name),\n m.arrayOf(m.anyExpression()),\n );\n\n const conditional = m.capture(m.conditionalExpression());\n const conditionalCall = m.callExpression(m.identifier(this.name), [\n conditional,\n ]);\n\n const buildExtractedConditional = expression`TEST ? CALLEE(CONSEQUENT) : CALLEE(ALTERNATE)`;\n\n const binding = this.path.scope.getBinding(this.name)!;\n for (const ref of binding.referencePaths) {\n if (conditionalCall.match(ref.parent)) {\n // decode(test ? 1 : 2) -> test ? decode(1) : decode(2)\n const [replacement] = ref.parentPath!.replaceWith(\n buildExtractedConditional({\n TEST: conditional.current!.test,\n CALLEE: ref.parent.callee,\n CONSEQUENT: conditional.current!.consequent,\n ALTERNATE: conditional.current!.alternate,\n }),\n );\n // some of the scope information is somehow lost after replacing\n replacement.scope.crawl();\n } else if (literalCall.match(ref.parent)) {\n calls.push(ref.parentPath as NodePath<t.CallExpression>);\n } else if (expressionCall.match(ref.parent)) {\n // var n = 1; decode(n); -> decode(1);\n ref.parentPath!.traverse({\n ReferencedIdentifier(path) {\n const varBinding = path.scope.getBinding(path.node.name)!;\n if (!varBinding) return;\n inlineVariable(varBinding, literalArgument, true);\n },\n });\n if (literalCall.match(ref.parent)) {\n calls.push(ref.parentPath as NodePath<t.CallExpression>);\n }\n }\n }\n\n return calls;\n }\n}\n\nexport function findDecoders(stringArray: StringArray): Decoder[] {\n const decoders: Decoder[] = [];\n\n const functionName = m.capture(m.anyString());\n const arrayIdentifier = m.capture(m.identifier());\n const matcher = m.functionDeclaration(\n m.identifier(functionName),\n m.anything(),\n m.blockStatement(\n m.anyList(\n // var array = getStringArray();\n m.variableDeclaration(undefined, [\n m.variableDeclarator(\n arrayIdentifier,\n m.callExpression(m.identifier(stringArray.name)),\n ),\n ]),\n m.zeroOrMore(),\n // var h = array[e]; return h;\n // or return array[e -= 254];\n m.containerOf(\n m.memberExpression(m.fromCapture(arrayIdentifier), undefined, true),\n ),\n m.zeroOrMore(),\n ),\n ),\n );\n\n for (const ref of stringArray.references) {\n const decoderFn = findParent(ref, matcher);\n\n if (decoderFn) {\n const oldName = functionName.current!;\n const newName = `__DECODE_${decoders.length}__`;\n const binding = decoderFn.scope.getBinding(oldName)!;\n renameFast(binding, newName);\n decoders.push(new Decoder(newName, decoderFn));\n }\n }\n\n return decoders;\n}\n",
|
|
27
|
-
"import * as t from '@babel/types';\nimport { AsyncTransform } from '../ast-utils';\nimport { VMDecoder } from './vm';\n\n/**\n * Replaces calls to decoder functions with the decoded string.\n * E.g. `m(199)` -> `'log'`\n */\nexport default {\n name: 'inline-decoded-strings',\n tags: ['unsafe'],\n scope: true,\n async run(ast, state, options) {\n if (!options) return;\n\n const calls = options.vm.decoders.flatMap((decoder) =>\n decoder.collectCalls(),\n );\n const decodedValues = await options.vm.decode(calls);\n\n for (let i = 0; i < calls.length; i++) {\n const call = calls[i];\n const value = decodedValues[i];\n\n call.replaceWith(t.valueToNode(value));\n if (typeof value !== 'string')\n call.addComment('leading', 'webcrack:decode_error');\n }\n\n state.changes += calls.length;\n },\n} satisfies AsyncTransform<{ vm: VMDecoder }>;\n",
|
|
28
|
-
"import { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport {\n Transform,\n inlineFunctionAliases,\n inlineVariableAliases,\n} from '../ast-utils';\n\n/**\n * Replaces all references to `var alias = decode;` with `decode`\n */\nexport default {\n name: 'inline-decoder-wrappers',\n tags: ['unsafe'],\n scope: true,\n run(ast, state, decoder) {\n if (!decoder?.node.id) return;\n\n const decoderName = decoder.node.id.name;\n const decoderBinding = decoder.parentPath.scope.getBinding(decoderName);\n if (decoderBinding) {\n state.changes += inlineVariableAliases(decoderBinding).changes;\n state.changes += inlineFunctionAliases(decoderBinding).changes;\n }\n },\n} satisfies Transform<NodePath<t.FunctionDeclaration>>;\n",
|
|
29
|
-
"import * as m from '@codemod/matchers';\nimport {\n Transform,\n constKey,\n constMemberExpression,\n inlineObjectProperties,\n isReadonlyObject,\n} from '../ast-utils';\n\n// TODO: move do decoder.ts collectCalls to avoid traversing the whole AST\n\n/**\n * Inline objects that only have string or numeric literal properties.\n * Used by the \"String Array Calls Transform\" option for moving the\n * decode call arguments into an object.\n * Example:\n * ```js\n * const obj = {\n * c: 0x2f2,\n * d: '0x396',\n * };\n * console.log(decode(obj.c, obj.d));\n * ```\n * ->\n * ```js\n * console.log(decode(0x2f2, '0x396'));\n * ```\n */\nexport default {\n name: 'inline-object-props',\n tags: ['safe'],\n scope: true,\n visitor() {\n const varId = m.capture(m.identifier());\n const propertyName = m.matcher<string>((name) => /^[\\w]+$/i.test(name));\n const propertyKey = constKey(propertyName);\n // E.g. \"_0x51b74a\": 0x80\n const objectProperties = m.capture(\n m.arrayOf(\n m.objectProperty(\n propertyKey,\n m.or(m.stringLiteral(), m.numericLiteral()),\n ),\n ),\n );\n // E.g. obj._0x51b74a\n const memberAccess = constMemberExpression(\n m.fromCapture(varId),\n propertyName,\n );\n const varMatcher = m.variableDeclarator(\n varId,\n m.objectExpression(objectProperties),\n );\n\n return {\n VariableDeclarator(path) {\n if (!varMatcher.match(path.node)) return;\n if (objectProperties.current!.length === 0) return;\n\n const binding = path.scope.getBinding(varId.current!.name);\n if (!binding || !isReadonlyObject(binding, memberAccess)) return;\n\n inlineObjectProperties(\n binding,\n m.objectProperty(\n propertyKey,\n m.or(m.stringLiteral(), m.numericLiteral()),\n ),\n );\n },\n };\n },\n} satisfies Transform;\n",
|
|
30
|
-
"import * as m from '@codemod/matchers';\nimport {\n Transform,\n constKey,\n constMemberExpression,\n inlineObjectProperties,\n isReadonlyObject,\n} from '../ast-utils';\n\n// TODO: move do decoder.ts collectCalls to avoid traversing the whole AST\n\n/**\n * Inline objects that only have string or numeric literal properties.\n * Used by the \"String Array Calls Transform\" option for moving the\n * decode call arguments into an object.\n * Example:\n * ```js\n * const obj = {\n * c: 0x2f2,\n * d: '0x396',\n * };\n * console.log(decode(obj.c, obj.d));\n * ```\n * ->\n * ```js\n * console.log(decode(0x2f2, '0x396'));\n * ```\n */\nexport default {\n name: 'inline-object-props',\n tags: ['safe'],\n scope: true,\n visitor() {\n const varId = m.capture(m.identifier());\n const propertyName = m.matcher<string>((name) => /^[\\w]+$/i.test(name));\n const propertyKey = constKey(propertyName);\n // E.g. \"_0x51b74a\": 0x80\n const objectProperties = m.capture(\n m.arrayOf(\n m.objectProperty(\n propertyKey,\n m.or(m.stringLiteral(), m.numericLiteral()),\n ),\n ),\n );\n // E.g. obj._0x51b74a\n const memberAccess = constMemberExpression(\n m.fromCapture(varId),\n propertyName,\n );\n const varMatcher = m.variableDeclarator(\n varId,\n m.objectExpression(objectProperties),\n );\n\n return {\n VariableDeclarator(path) {\n if (!varMatcher.match(path.node)) return;\n if (objectProperties.current!.length === 0) return;\n\n const binding = path.scope.getBinding(varId.current!.name);\n if (!binding || !isReadonlyObject(binding, memberAccess)) return;\n\n inlineObjectProperties(\n binding,\n m.objectProperty(\n propertyKey,\n m.or(m.stringLiteral(), m.numericLiteral()),\n ),\n );\n },\n };\n },\n} satisfies Transform;\n",
|
|
31
|
-
"import traverse, { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport {\n inlineArrayElements,\n isReadonlyObject,\n renameFast,\n} from '../ast-utils';\n\nexport interface StringArray {\n path: NodePath<t.FunctionDeclaration>;\n references: NodePath[];\n name: string;\n length: number;\n}\n\nexport function findStringArray(ast: t.Node): StringArray | undefined {\n let result: StringArray | undefined;\n const functionName = m.capture(m.anyString());\n const arrayIdentifier = m.capture(m.identifier());\n const arrayExpression = m.capture(\n m.arrayExpression(m.arrayOf(m.stringLiteral())),\n );\n // getStringArray = function () { return array; };\n const functionAssignment = m.assignmentExpression(\n '=',\n m.identifier(m.fromCapture(functionName)),\n m.functionExpression(\n undefined,\n [],\n m.blockStatement([m.returnStatement(m.fromCapture(arrayIdentifier))]),\n ),\n );\n const variableDeclaration = m.variableDeclaration(undefined, [\n m.variableDeclarator(arrayIdentifier, arrayExpression),\n ]);\n // function getStringArray() { ... }\n const matcher = m.functionDeclaration(\n m.identifier(functionName),\n [],\n m.or(\n // var array = [\"hello\", \"world\"];\n // return (getStringArray = function () { return array; })();\n m.blockStatement([\n variableDeclaration,\n m.returnStatement(m.callExpression(functionAssignment)),\n ]),\n // var array = [\"hello\", \"world\"];\n // getStringArray = function () { return array; });\n // return getStringArray();\n m.blockStatement([\n variableDeclaration,\n m.expressionStatement(functionAssignment),\n m.returnStatement(m.callExpression(m.identifier(functionName))),\n ]),\n ),\n );\n\n traverse(ast, {\n // Wrapped string array from later javascript-obfuscator versions\n FunctionDeclaration(path) {\n if (matcher.match(path.node)) {\n const length = arrayExpression.current!.elements.length;\n const name = functionName.current!;\n const binding = path.scope.getBinding(name)!;\n renameFast(binding, '__STRING_ARRAY__');\n\n result = {\n path,\n references: binding.referencePaths,\n name: '__STRING_ARRAY__',\n length,\n };\n path.stop();\n }\n },\n // Simple string array inlining (only `array[0]`, `array[1]` etc references, no rotating/decoding).\n // May be used by older or different obfuscators\n VariableDeclaration(path) {\n if (!variableDeclaration.match(path.node)) return;\n\n const length = arrayExpression.current!.elements.length;\n const binding = path.scope.getBinding(arrayIdentifier.current!.name)!;\n const memberAccess = m.memberExpression(\n m.fromCapture(arrayIdentifier),\n m.numericLiteral(m.matcher((value) => value < length)),\n );\n if (!isReadonlyObject(binding, memberAccess)) return;\n\n inlineArrayElements(arrayExpression.current!, binding.referencePaths);\n path.remove();\n },\n });\n\n return result;\n}\n",
|
|
32
|
-
"import traverse, { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport {\n inlineArrayElements,\n isReadonlyObject,\n renameFast,\n} from '../ast-utils';\n\nexport interface StringArray {\n path: NodePath<t.FunctionDeclaration>;\n references: NodePath[];\n name: string;\n length: number;\n}\n\nexport function findStringArray(ast: t.Node): StringArray | undefined {\n let result: StringArray | undefined;\n const functionName = m.capture(m.anyString());\n const arrayIdentifier = m.capture(m.identifier());\n const arrayExpression = m.capture(\n m.arrayExpression(m.arrayOf(m.stringLiteral())),\n );\n // getStringArray = function () { return array; };\n const functionAssignment = m.assignmentExpression(\n '=',\n m.identifier(m.fromCapture(functionName)),\n m.functionExpression(\n undefined,\n [],\n m.blockStatement([m.returnStatement(m.fromCapture(arrayIdentifier))]),\n ),\n );\n const variableDeclaration = m.variableDeclaration(undefined, [\n m.variableDeclarator(arrayIdentifier, arrayExpression),\n ]);\n // function getStringArray() { ... }\n const matcher = m.functionDeclaration(\n m.identifier(functionName),\n [],\n m.or(\n // var array = [\"hello\", \"world\"];\n // return (getStringArray = function () { return array; })();\n m.blockStatement([\n variableDeclaration,\n m.returnStatement(m.callExpression(functionAssignment)),\n ]),\n // var array = [\"hello\", \"world\"];\n // getStringArray = function () { return array; });\n // return getStringArray();\n m.blockStatement([\n variableDeclaration,\n m.expressionStatement(functionAssignment),\n m.returnStatement(m.callExpression(m.identifier(functionName))),\n ]),\n ),\n );\n\n traverse(ast, {\n // Wrapped string array from later javascript-obfuscator versions\n FunctionDeclaration(path) {\n if (matcher.match(path.node)) {\n const length = arrayExpression.current!.elements.length;\n const name = functionName.current!;\n const binding = path.scope.getBinding(name)!;\n renameFast(binding, '__STRING_ARRAY__');\n\n result = {\n path,\n references: binding.referencePaths,\n name: '__STRING_ARRAY__',\n length,\n };\n path.stop();\n }\n },\n // Simple string array inlining (only `array[0]`, `array[1]` etc references, no rotating/decoding).\n // May be used by older or different obfuscators\n VariableDeclaration(path) {\n if (!variableDeclaration.match(path.node)) return;\n\n const length = arrayExpression.current!.elements.length;\n const binding = path.scope.getBinding(arrayIdentifier.current!.name)!;\n const memberAccess = m.memberExpression(\n m.fromCapture(arrayIdentifier),\n m.numericLiteral(m.matcher((value) => value < length)),\n );\n if (!isReadonlyObject(binding, memberAccess)) return;\n\n inlineArrayElements(arrayExpression.current!, binding.referencePaths);\n path.remove();\n },\n });\n\n return result;\n}\n",
|
|
33
|
-
"import { NodePath } from '@babel/traverse';\nimport { CallExpression } from '@babel/types';\nimport debug from 'debug';\nimport { generate } from '../ast-utils';\nimport { ArrayRotator } from './array-rotator';\nimport { Decoder } from './decoder';\nimport { StringArray } from './string-array';\n\nexport type Sandbox = (code: string) => Promise<unknown>;\n\nexport function createNodeSandbox(): Sandbox {\n return async (code: string) => {\n const {\n default: { Isolate },\n } = await import('isolated-vm');\n const isolate = new Isolate();\n const context = await isolate.createContext();\n const result = (await context.eval(code, {\n timeout: 10_000,\n copy: true,\n filename: 'file:///obfuscated.js',\n })) as unknown;\n context.release();\n isolate.dispose();\n return result;\n };\n}\n\nexport function createBrowserSandbox(): Sandbox {\n return () => {\n // TODO: use sandybox (not available in web workers though)\n throw new Error('Custom Sandbox implementation required.');\n };\n}\n\nexport class VMDecoder {\n decoders: Decoder[];\n private setupCode: string;\n private sandbox: Sandbox;\n\n constructor(\n sandbox: Sandbox,\n stringArray: StringArray,\n decoders: Decoder[],\n rotator?: ArrayRotator,\n ) {\n this.sandbox = sandbox;\n this.decoders = decoders;\n\n // Generate as compact to bypass the self defense\n // (which tests someFunction.toString against a regex)\n const generateOptions = {\n compact: true,\n shouldPrintComment: () => false,\n };\n const stringArrayCode = generate(stringArray.path.node, generateOptions);\n const rotatorCode = rotator ? generate(rotator.node, generateOptions) : '';\n const decoderCode = decoders\n .map((decoder) => generate(decoder.path.node, generateOptions))\n .join(';\\n');\n\n this.setupCode = [stringArrayCode, rotatorCode, decoderCode].join(';\\n');\n }\n\n async decode(calls: NodePath<CallExpression>[]): Promise<unknown[]> {\n const code = `(() => {\n ${this.setupCode}\n return [${calls.join(',')}]\n })()`;\n\n try {\n const result = await this.sandbox(code);\n return result as unknown[];\n } catch (error) {\n debug('webcrack:deobfuscate')('vm code:', code);\n if (\n error instanceof Error &&\n (error.message.includes('undefined symbol') ||\n error.message.includes('Segmentation fault'))\n ) {\n throw new Error(\n 'isolated-vm version mismatch. Check https://webcrack.netlify.app/docs/guide/common-errors.html#isolated-vm',\n { cause: error },\n );\n }\n throw error;\n }\n }\n}\n",
|
|
34
|
-
"import { NodePath } from '@babel/traverse';\nimport { CallExpression } from '@babel/types';\nimport debug from 'debug';\nimport { generate } from '../ast-utils';\nimport { ArrayRotator } from './array-rotator';\nimport { Decoder } from './decoder';\nimport { StringArray } from './string-array';\n\nexport type Sandbox = (code: string) => Promise<unknown>;\n\nexport function createNodeSandbox(): Sandbox {\n return async (code: string) => {\n const {\n default: { Isolate },\n } = await import('isolated-vm');\n const isolate = new Isolate();\n const context = await isolate.createContext();\n const result = (await context.eval(code, {\n timeout: 10_000,\n copy: true,\n filename: 'file:///obfuscated.js',\n })) as unknown;\n context.release();\n isolate.dispose();\n return result;\n };\n}\n\nexport function createBrowserSandbox(): Sandbox {\n return () => {\n // TODO: use sandybox (not available in web workers though)\n throw new Error('Custom Sandbox implementation required.');\n };\n}\n\nexport class VMDecoder {\n decoders: Decoder[];\n private setupCode: string;\n private sandbox: Sandbox;\n\n constructor(\n sandbox: Sandbox,\n stringArray: StringArray,\n decoders: Decoder[],\n rotator?: ArrayRotator,\n ) {\n this.sandbox = sandbox;\n this.decoders = decoders;\n\n // Generate as compact to bypass the self defense\n // (which tests someFunction.toString against a regex)\n const generateOptions = {\n compact: true,\n shouldPrintComment: () => false,\n };\n const stringArrayCode = generate(stringArray.path.node, generateOptions);\n const rotatorCode = rotator ? generate(rotator.node, generateOptions) : '';\n const decoderCode = decoders\n .map((decoder) => generate(decoder.path.node, generateOptions))\n .join(';\\n');\n\n this.setupCode = [stringArrayCode, rotatorCode, decoderCode].join(';\\n');\n }\n\n async decode(calls: NodePath<CallExpression>[]): Promise<unknown[]> {\n const code = `(() => {\n ${this.setupCode}\n return [${calls.join(',')}]\n })()`;\n\n try {\n const result = await this.sandbox(code);\n return result as unknown[];\n } catch (error) {\n debug('webcrack:deobfuscate')('vm code:', code);\n if (\n error instanceof Error &&\n (error.message.includes('undefined symbol') ||\n error.message.includes('Segmentation fault'))\n ) {\n throw new Error(\n 'isolated-vm version mismatch. Check https://webcrack.netlify.app/docs/guide/common-errors.html#isolated-vm',\n { cause: error },\n );\n }\n throw error;\n }\n }\n}\n",
|
|
35
|
-
"import debug from 'debug';\nimport {\n AsyncTransform,\n applyTransform,\n applyTransformAsync,\n applyTransforms,\n} from '../ast-utils';\nimport mergeStrings from '../unminify/transforms/merge-strings';\nimport { findArrayRotator } from './array-rotator';\nimport controlFlowObject from './control-flow-object';\nimport controlFlowSwitch from './control-flow-switch';\nimport deadCode from './dead-code';\nimport { findDecoders } from './decoder';\nimport inlineDecodedStrings from './inline-decoded-strings';\nimport inlineDecoderWrappers from './inline-decoder-wrappers';\nimport inlineObjectProps from './inline-object-props';\nimport { findStringArray } from './string-array';\nimport {\n Sandbox,\n VMDecoder,\n createBrowserSandbox,\n createNodeSandbox,\n} from './vm';\n\nexport { createBrowserSandbox, createNodeSandbox, type Sandbox };\n\n// https://astexplorer.net/#/gist/b1018df4a8daebfcb1daf9d61fe17557/4ff9ad0e9c40b9616956f17f59a2d9888cd62a4f\n\nexport default {\n name: 'deobfuscate',\n tags: ['unsafe'],\n scope: true,\n async run(ast, state, sandbox) {\n if (!sandbox) return;\n\n const logger = debug('webcrack:deobfuscate');\n const stringArray = findStringArray(ast);\n logger(\n stringArray\n ? `String Array: ${stringArray.length} strings`\n : 'String Array: no',\n );\n if (!stringArray) return;\n\n const rotator = findArrayRotator(stringArray);\n logger(`String Array Rotate: ${rotator ? 'yes' : 'no'}`);\n\n const decoders = findDecoders(stringArray);\n logger(`String Array Encodings: ${decoders.length}`);\n\n state.changes += applyTransform(ast, inlineObjectProps).changes;\n\n for (const decoder of decoders) {\n state.changes += applyTransform(\n ast,\n inlineDecoderWrappers,\n decoder.path,\n ).changes;\n }\n\n const vm = new VMDecoder(sandbox, stringArray, decoders, rotator);\n state.changes += (\n await applyTransformAsync(ast, inlineDecodedStrings, { vm })\n ).changes;\n\n stringArray.path.remove();\n rotator?.remove();\n decoders.forEach((decoder) => decoder.path.remove());\n state.changes += 2 + decoders.length;\n\n state.changes += applyTransforms(\n ast,\n [mergeStrings, deadCode, controlFlowObject, controlFlowSwitch],\n { noScope: true },\n ).changes;\n },\n} satisfies AsyncTransform<Sandbox>;\n",
|
|
36
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../ast-utils';\n\n// Unsafe because variables may be used before they are declared, but functions are hoisted\n// Example: `console.log(a); var a = function() {}` logs `undefined`\n// `console.log(a); function a() {}` logs the function\nexport default {\n name: 'var-functions',\n tags: ['unsafe'],\n visitor() {\n const name = m.capture(m.identifier());\n const fn = m.capture(m.functionExpression(null));\n const matcher = m.variableDeclaration('var', [\n m.variableDeclarator(name, fn),\n ]);\n\n return {\n VariableDeclaration: {\n exit(path) {\n if (matcher.match(path.node) && path.key !== 'init') {\n path.replaceWith(\n t.functionDeclaration(\n name.current,\n fn.current!.params,\n fn.current!.body,\n fn.current!.generator,\n fn.current!.async,\n ),\n );\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
37
|
-
"import { Binding } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, anyLiteral, constObjectProperty } from '../ast-utils';\n\n/**\n * Merges object assignments into the object expression.\n * Example:\n * ```js\n * const obj = {};\n * obj.foo = 'bar';\n * ```\n * ->\n * ```js\n * const obj = { foo: 'bar' };\n * ```\n */\nexport default {\n name: 'merge-object-assignments',\n tags: ['safe'],\n scope: true,\n visitor: () => {\n const id = m.capture(m.identifier());\n const object = m.capture(m.objectExpression([]));\n // Example: const obj = {};\n const varMatcher = m.variableDeclaration(undefined, [\n m.variableDeclarator(id, object),\n ]);\n const key = m.capture(m.anyExpression());\n const computed = m.capture<boolean>(m.anything());\n const value = m.capture(m.anyExpression());\n // Example: obj.foo = 'bar';\n const assignmentMatcher = m.expressionStatement(\n m.assignmentExpression(\n '=',\n m.memberExpression(m.fromCapture(id), key, computed),\n value,\n ),\n );\n\n return {\n Program(path) {\n // No idea why this is needed, crashes otherwise.\n path.scope.crawl();\n },\n VariableDeclaration: {\n exit(path) {\n if (!path.inList || !varMatcher.match(path.node)) return;\n\n const binding = path.scope.getBinding(id.current!.name)!;\n const container = path.container as t.Statement[];\n const siblingIndex = (path.key as number) + 1;\n\n while (siblingIndex < container.length) {\n const sibling = path.getSibling(siblingIndex);\n if (\n !assignmentMatcher.match(sibling.node) ||\n hasCircularReference(value.current!, binding)\n )\n return;\n\n // { [1]: value, \"foo bar\": value } can be simplified to { 1: value, \"foo bar\": value }\n const isComputed =\n computed.current! &&\n key.current!.type !== 'NumericLiteral' &&\n key.current!.type !== 'StringLiteral';\n\n // Example: const obj = { x: 1 }; obj.foo = 'bar'; -> const obj = { x: 1, foo: 'bar' };\n object.current!.properties.push(\n t.objectProperty(key.current!, value.current!, isComputed),\n );\n\n sibling.remove();\n binding.dereference();\n binding.referencePaths.shift();\n\n // Example: const obj = { foo: 'bar' }; return obj; -> return { foo: 'bar' };\n if (\n binding.references === 1 &&\n inlineableObject.match(object.current)\n ) {\n binding.referencePaths[0].replaceWith(object.current);\n path.remove();\n this.changes++;\n }\n }\n },\n },\n };\n },\n} satisfies Transform;\n\n/**\n * Used to avoid \"Cannot access 'obj' before initialization\" errors.\n */\nfunction hasCircularReference(node: t.Node, binding: Binding) {\n return (\n // obj.foo = obj;\n binding.referencePaths.some((path) => path.find((p) => p.node === node)) ||\n // obj.foo = fn(); where fn could reference the binding or not, for simplicity we assume it does.\n m.containerOf(m.callExpression()).match(node)\n );\n}\n\n/**\n * Only literals, arrays and objects are allowed because variable values\n * might be different in the place the object will be inlined.\n */\nconst inlineableObject: m.Matcher<t.Expression> = m.matcher((node) =>\n m\n .or(\n anyLiteral,\n m.arrayExpression(m.arrayOf(inlineableObject)),\n m.objectExpression(m.arrayOf(constObjectProperty(inlineableObject))),\n )\n .match(node),\n);\n",
|
|
38
|
-
"import { Binding } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, anyLiteral, constObjectProperty } from '../ast-utils';\n\n/**\n * Merges object assignments into the object expression.\n * Example:\n * ```js\n * const obj = {};\n * obj.foo = 'bar';\n * ```\n * ->\n * ```js\n * const obj = { foo: 'bar' };\n * ```\n */\nexport default {\n name: 'merge-object-assignments',\n tags: ['safe'],\n scope: true,\n visitor: () => {\n const id = m.capture(m.identifier());\n const object = m.capture(m.objectExpression([]));\n // Example: const obj = {};\n const varMatcher = m.variableDeclaration(undefined, [\n m.variableDeclarator(id, object),\n ]);\n const key = m.capture(m.anyExpression());\n const computed = m.capture<boolean>(m.anything());\n const value = m.capture(m.anyExpression());\n // Example: obj.foo = 'bar';\n const assignmentMatcher = m.expressionStatement(\n m.assignmentExpression(\n '=',\n m.memberExpression(m.fromCapture(id), key, computed),\n value,\n ),\n );\n\n return {\n Program(path) {\n // No idea why this is needed, crashes otherwise.\n path.scope.crawl();\n },\n VariableDeclaration: {\n exit(path) {\n if (!path.inList || !varMatcher.match(path.node)) return;\n\n const binding = path.scope.getBinding(id.current!.name)!;\n const container = path.container as t.Statement[];\n const siblingIndex = (path.key as number) + 1;\n\n while (siblingIndex < container.length) {\n const sibling = path.getSibling(siblingIndex);\n if (\n !assignmentMatcher.match(sibling.node) ||\n hasCircularReference(value.current!, binding)\n )\n return;\n\n // { [1]: value, \"foo bar\": value } can be simplified to { 1: value, \"foo bar\": value }\n const isComputed =\n computed.current! &&\n key.current!.type !== 'NumericLiteral' &&\n key.current!.type !== 'StringLiteral';\n\n // Example: const obj = { x: 1 }; obj.foo = 'bar'; -> const obj = { x: 1, foo: 'bar' };\n object.current!.properties.push(\n t.objectProperty(key.current!, value.current!, isComputed),\n );\n\n sibling.remove();\n binding.dereference();\n binding.referencePaths.shift();\n\n // Example: const obj = { foo: 'bar' }; return obj; -> return { foo: 'bar' };\n if (\n binding.references === 1 &&\n inlineableObject.match(object.current)\n ) {\n binding.referencePaths[0].replaceWith(object.current);\n path.remove();\n this.changes++;\n }\n }\n },\n },\n };\n },\n} satisfies Transform;\n\n/**\n * Used to avoid \"Cannot access 'obj' before initialization\" errors.\n */\nfunction hasCircularReference(node: t.Node, binding: Binding) {\n return (\n // obj.foo = obj;\n binding.referencePaths.some((path) => path.find((p) => p.node === node)) ||\n // obj.foo = fn(); where fn could reference the binding or not, for simplicity we assume it does.\n m.containerOf(m.callExpression()).match(node)\n );\n}\n\n/**\n * Only literals, arrays and objects are allowed because variable values\n * might be different in the place the object will be inlined.\n */\nconst inlineableObject: m.Matcher<t.Expression> = m.matcher((node) =>\n m\n .or(\n anyLiteral,\n m.arrayExpression(m.arrayOf(inlineableObject)),\n m.objectExpression(m.arrayOf(constObjectProperty(inlineableObject))),\n )\n .match(node),\n);\n",
|
|
39
|
-
"import * as t from '@babel/types';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'block-statements',\n tags: ['safe'],\n visitor: () => ({\n IfStatement: {\n exit(path) {\n if (\n !t.isBlockStatement(path.node.consequent) &&\n !t.isEmptyStatement(path.node.consequent)\n ) {\n path.node.consequent = t.blockStatement([path.node.consequent]);\n\n this.changes++;\n }\n if (path.node.alternate && !t.isBlockStatement(path.node.alternate)) {\n path.node.alternate = t.blockStatement([path.node.alternate]);\n this.changes++;\n }\n },\n },\n Loop: {\n exit(path) {\n if (\n !t.isBlockStatement(path.node.body) &&\n !t.isEmptyStatement(path.node.body)\n ) {\n path.node.body = t.blockStatement([path.node.body]);\n\n this.changes++;\n }\n },\n },\n ArrowFunctionExpression: {\n exit(path) {\n if (t.isSequenceExpression(path.node.body)) {\n path.node.body = t.blockStatement([\n t.returnStatement(path.node.body),\n ]);\n\n this.changes++;\n }\n },\n },\n }),\n} satisfies Transform;\n",
|
|
40
|
-
"import { isIdentifierName } from '@babel/helper-validator-identifier';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'computed-properties',\n tags: ['safe'],\n visitor() {\n const stringMatcher = m.capture(\n m.stringLiteral(m.matcher((value) => isIdentifierName(value))),\n );\n const propertyMatcher = m.or(\n m.memberExpression(m.anything(), stringMatcher, true),\n m.optionalMemberExpression(m.anything(), stringMatcher, true),\n );\n const keyMatcher = m.or(\n m.objectProperty(stringMatcher),\n m.classProperty(stringMatcher),\n m.objectMethod(undefined, stringMatcher),\n m.classMethod(undefined, stringMatcher),\n );\n\n return {\n 'MemberExpression|OptionalMemberExpression': {\n exit(path) {\n if (!propertyMatcher.match(path.node)) return;\n path.node.computed = false;\n path.node.property = t.identifier(stringMatcher.current!.value);\n this.changes++;\n },\n },\n 'ObjectProperty|ClassProperty|ObjectMethod|ClassMethod': {\n exit(path) {\n if (!keyMatcher.match(path.node)) return;\n if (\n (path.type === 'ClassMethod' &&\n stringMatcher.current!.value === 'constructor') ||\n (path.type === 'ObjectProperty' &&\n stringMatcher.current!.value === '__proto__')\n )\n return;\n\n path.node.computed = false;\n path.node.key = t.identifier(stringMatcher.current!.value);\n this.changes++;\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
41
|
-
"import * as t from '@babel/types';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'for-to-while',\n tags: ['safe'],\n visitor() {\n return {\n ForStatement: {\n exit(path) {\n const { test, body, init, update } = path.node;\n if (init || update) return;\n path.replaceWith(\n test\n ? t.whileStatement(test, body)\n : t.whileStatement(t.booleanLiteral(true), body),\n );\n this.changes++;\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
42
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'infinity',\n tags: ['safe'],\n scope: true,\n visitor: () => {\n const infinityMatcher = m.binaryExpression(\n '/',\n m.numericLiteral(1),\n m.numericLiteral(0),\n );\n const negativeInfinityMatcher = m.binaryExpression(\n '/',\n m.unaryExpression('-', m.numericLiteral(1)),\n m.numericLiteral(0),\n );\n\n return {\n BinaryExpression: {\n exit(path) {\n if (path.scope.hasBinding('Infinity', { noGlobals: true })) return;\n\n if (infinityMatcher.match(path.node)) {\n path.replaceWith(t.identifier('Infinity'));\n this.changes++;\n } else if (negativeInfinityMatcher.match(path.node)) {\n path.replaceWith(t.unaryExpression('-', t.identifier('Infinity')));\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
43
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nconst INVERTED_BINARY_OPERATORS = {\n '==': '!=',\n '===': '!==',\n '!=': '==',\n '!==': '===',\n '>': '<=',\n '<': '>=',\n '>=': '<',\n '<=': '>',\n} as const;\n\nconst INVERTED_LOGICAL_OPERATORS = {\n '||': '&&',\n '&&': '||',\n} as const;\n\nexport default {\n name: 'invert-boolean-logic',\n tags: ['safe'],\n visitor: () => {\n const logicalExpression = m.logicalExpression(\n m.or(...Object.values(INVERTED_LOGICAL_OPERATORS)),\n );\n const logicalMatcher = m.unaryExpression('!', logicalExpression);\n\n const binaryExpression = m.capture(\n m.binaryExpression(m.or(...Object.values(INVERTED_BINARY_OPERATORS))),\n );\n const binaryMatcher = m.unaryExpression('!', binaryExpression);\n\n return {\n UnaryExpression: {\n exit(path) {\n const { argument } = path.node;\n\n if (binaryMatcher.match(path.node)) {\n binaryExpression.current!.operator =\n INVERTED_BINARY_OPERATORS[\n binaryExpression.current!\n .operator as keyof typeof INVERTED_BINARY_OPERATORS\n ];\n\n path.replaceWith(binaryExpression.current!);\n this.changes++;\n } else if (logicalMatcher.match(path.node)) {\n let current = argument;\n while (logicalExpression.match(current)) {\n current.operator =\n INVERTED_LOGICAL_OPERATORS[\n current.operator as keyof typeof INVERTED_LOGICAL_OPERATORS\n ];\n\n current.right = t.unaryExpression('!', current.right);\n if (!logicalExpression.match(current.left)) {\n current.left = t.unaryExpression('!', current.left);\n }\n current = current.left;\n }\n\n path.replaceWith(argument);\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
44
|
-
"import { parseExpression } from '@babel/parser';\nimport * as m from '@codemod/matchers';\nimport { Transform, constMemberExpression } from '../../ast-utils';\n\nexport default {\n name: 'json-parse',\n tags: ['safe'],\n scope: true,\n visitor: () => {\n const string = m.capture(m.anyString());\n const matcher = m.callExpression(constMemberExpression('JSON', 'parse'), [\n m.stringLiteral(string),\n ]);\n\n return {\n CallExpression: {\n exit(path) {\n if (\n matcher.match(path.node) &&\n !path.scope.hasBinding('JSON', { noGlobals: true })\n ) {\n try {\n JSON.parse(string.current!);\n const parsed = parseExpression(string.current!);\n path.replaceWith(parsed);\n this.changes++;\n } catch (error) {\n // ignore\n }\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
45
|
-
"import { parseExpression } from '@babel/parser';\nimport * as m from '@codemod/matchers';\nimport { Transform, constMemberExpression } from '../../ast-utils';\n\nexport default {\n name: 'json-parse',\n tags: ['safe'],\n scope: true,\n visitor: () => {\n const string = m.capture(m.anyString());\n const matcher = m.callExpression(constMemberExpression('JSON', 'parse'), [\n m.stringLiteral(string),\n ]);\n\n return {\n CallExpression: {\n exit(path) {\n if (\n matcher.match(path.node) &&\n !path.scope.hasBinding('JSON', { noGlobals: true })\n ) {\n try {\n JSON.parse(string.current!);\n const parsed = parseExpression(string.current!);\n path.replaceWith(parsed);\n this.changes++;\n } catch (error) {\n // ignore\n }\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
46
|
-
"import { statement } from '@babel/template';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'logical-to-if',\n tags: ['safe'],\n visitor: () => {\n const andMatcher = m.expressionStatement(m.logicalExpression('&&'));\n const orMatcher = m.expressionStatement(m.logicalExpression('||'));\n\n const buildIf = statement`if (TEST) { BODY; }`;\n const buildIfNot = statement`if (!TEST) { BODY; }`;\n\n return {\n ExpressionStatement: {\n exit(path) {\n const expression = path.node.expression as t.LogicalExpression;\n if (andMatcher.match(path.node)) {\n path.replaceWith(\n buildIf({\n TEST: expression.left,\n BODY: expression.right,\n }),\n );\n this.changes++;\n } else if (orMatcher.match(path.node)) {\n path.replaceWith(\n buildIfNot({\n TEST: expression.left,\n BODY: expression.right,\n }),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
47
|
-
"import * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'merge-else-if',\n tags: ['safe'],\n visitor() {\n const nestedIf = m.capture(m.ifStatement());\n const matcher = m.ifStatement(\n m.anything(),\n m.anything(),\n m.blockStatement([nestedIf]),\n );\n\n return {\n IfStatement: {\n exit(path) {\n if (matcher.match(path.node)) {\n path.node.alternate = nestedIf.current;\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
48
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'number-expressions',\n tags: ['safe'],\n visitor: () => ({\n 'BinaryExpression|UnaryExpression': {\n exit(path) {\n if (matcher.match(path.node)) {\n const evaluated = path.evaluate();\n if (evaluated.confident) {\n // Heuristic: Simplifying a division that results in a non-integer probably doesn't increase readability\n if (\n path.node.type === 'BinaryExpression' &&\n path.node.operator === '/' &&\n !Number.isInteger(evaluated.value)\n ) {\n return;\n }\n\n path.replaceWith(t.valueToNode(evaluated.value));\n path.skip();\n this.changes++;\n }\n }\n },\n },\n }),\n} satisfies Transform;\n\nconst matcher: m.Matcher<t.Expression> = m.or(\n m.binaryExpression(\n m.or('+', '-', '*', '/'),\n m.matcher((node) => matcher.match(node)),\n m.matcher((node) => matcher.match(node)),\n ),\n m.binaryExpression(\n '-',\n m.or(\n m.stringLiteral(),\n m.matcher((node) => matcher.match(node)),\n ),\n m.or(\n m.stringLiteral(),\n m.matcher((node) => matcher.match(node)),\n ),\n ),\n m.unaryExpression(\n '-',\n m.or(\n m.stringLiteral(),\n m.matcher((node) => matcher.match(node)),\n ),\n ),\n m.numericLiteral(),\n);\n",
|
|
49
|
-
"import { Transform } from '../../ast-utils';\n\nexport default {\n name: 'raw-literals',\n tags: ['safe'],\n visitor: () => ({\n StringLiteral(path) {\n if (path.node.extra) {\n path.node.extra = undefined;\n this.changes++;\n }\n },\n NumericLiteral(path) {\n if (path.node.extra) {\n path.node.extra = undefined;\n this.changes++;\n }\n },\n }),\n} satisfies Transform;\n",
|
|
50
|
-
"import { NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'sequence',\n tags: ['safe'],\n visitor() {\n // To retain the evaluation order of `<anything> = (x(), y());`, only identifiers and member expressions are allowed.\n // `obj.foo.bar = (x(), y());` would trigger the getter for `obj.foo` before `x()` is evaluated.\n const assignmentVariable = m.or(\n m.identifier(),\n m.memberExpression(m.identifier(), m.identifier()),\n );\n const assignedSequence = m.capture(m.sequenceExpression());\n const assignmentMatcher = m.expressionStatement(\n m.assignmentExpression(\n // \"||=\", \"&&=\", and \"??=\" have short-circuiting behavior\n m.or(\n '=',\n '+=',\n '-=',\n '*=',\n '/=',\n '%=',\n '**=',\n '<<=',\n '>>=',\n '>>>=',\n '|=',\n '^=',\n '&=',\n ),\n assignmentVariable,\n assignedSequence,\n ),\n );\n\n return {\n ExpressionStatement: {\n exit(path) {\n if (t.isSequenceExpression(path.node.expression)) {\n const statements = path.node.expression.expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.replaceWithMultiple(statements);\n this.changes++;\n } else if (assignmentMatcher.match(path.node)) {\n const value = assignedSequence.current!.expressions.pop()!;\n const statements = assignedSequence.current!.expressions.map(\n (expr) => t.expressionStatement(expr),\n );\n (path.get('expression.right') as NodePath<t.Node>).replaceWith(\n value,\n );\n path.insertBefore(statements);\n this.changes++;\n }\n },\n },\n ReturnStatement: {\n exit(path) {\n if (t.isSequenceExpression(path.node.argument)) {\n const expressions = path.node.argument.expressions;\n path.node.argument = expressions.pop();\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.insertBefore(statements);\n this.changes++;\n }\n },\n },\n IfStatement: {\n exit(path) {\n if (t.isSequenceExpression(path.node.test)) {\n const expressions = path.node.test.expressions;\n path.node.test = expressions.pop()!;\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.insertBefore(statements);\n this.changes++;\n }\n },\n },\n SwitchStatement: {\n exit(path) {\n if (t.isSequenceExpression(path.node.discriminant)) {\n const expressions = path.node.discriminant.expressions;\n path.node.discriminant = expressions.pop()!;\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.insertBefore(statements);\n this.changes++;\n }\n },\n },\n ThrowStatement: {\n exit(path) {\n if (t.isSequenceExpression(path.node.argument)) {\n const expressions = path.node.argument.expressions;\n path.node.argument = expressions.pop()!;\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.insertBefore(statements);\n this.changes++;\n }\n },\n },\n ForInStatement: {\n exit(path) {\n const sequence = m.capture(m.sequenceExpression());\n const matcher = m.forInStatement(m.anything(), sequence);\n if (matcher.match(path.node)) {\n const expressions = sequence.current!.expressions;\n path.node.right = expressions.pop()!;\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.insertBefore(statements);\n this.changes++;\n }\n },\n },\n ForStatement: {\n exit(path) {\n if (t.isSequenceExpression(path.node.init)) {\n const statements = path.node.init.expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.insertBefore(statements);\n path.node.init = null;\n this.changes++;\n }\n if (\n t.isSequenceExpression(path.node.update) &&\n path.node.body.type === 'EmptyStatement'\n ) {\n const expressions = path.node.update.expressions;\n path.node.update = expressions.pop()!;\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.node.body = t.blockStatement(statements);\n this.changes++;\n }\n },\n },\n WhileStatement: {\n exit(path) {\n if (t.isSequenceExpression(path.node.test)) {\n const expressions = path.node.test.expressions;\n path.node.test = expressions.pop()!;\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n path.insertBefore(statements);\n this.changes++;\n }\n },\n },\n VariableDeclaration: {\n exit(path) {\n const sequence = m.capture(m.sequenceExpression());\n const matcher = m.variableDeclaration(undefined, [\n m.variableDeclarator(undefined, sequence),\n ]);\n if (matcher.match(path.node)) {\n const expressions = sequence.current!.expressions;\n path.node.declarations[0].init = expressions.pop();\n const statements = expressions.map((expr) =>\n t.expressionStatement(expr),\n );\n if (path.parentPath.isForStatement() && path.key === 'init') {\n path.parentPath.insertBefore(statements);\n } else {\n path.insertBefore(statements);\n }\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
51
|
-
"import * as t from '@babel/types';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'split-variable-declarations',\n tags: ['safe'],\n visitor: () => ({\n VariableDeclaration: {\n exit(path) {\n if (path.node.declarations.length > 1 && path.key !== 'init') {\n if (path.parentPath.isExportNamedDeclaration()) {\n path.parentPath.replaceWithMultiple(\n path.node.declarations.map((declaration) =>\n t.exportNamedDeclaration(\n t.variableDeclaration(path.node.kind, [declaration]),\n ),\n ),\n );\n } else {\n path.replaceWithMultiple(\n path.node.declarations.map((declaration) =>\n t.variableDeclaration(path.node.kind, [declaration]),\n ),\n );\n }\n this.changes++;\n }\n },\n },\n }),\n} satisfies Transform;\n",
|
|
52
|
-
"import { statement } from '@babel/template';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'ternary-to-if',\n tags: ['safe'],\n visitor() {\n const test = m.capture(m.anyExpression());\n const consequent = m.capture(m.anyExpression());\n const alternate = m.capture(m.anyExpression());\n const conditional = m.conditionalExpression(test, consequent, alternate);\n\n const buildIf = statement`if (TEST) { CONSEQUENT; } else { ALTERNATE; }`;\n const buildIfReturn = statement`if (TEST) { return CONSEQUENT; } else { return ALTERNATE; }`;\n\n return {\n ExpressionStatement: {\n exit(path) {\n if (conditional.match(path.node.expression)) {\n path.replaceWith(\n buildIf({\n TEST: test.current,\n CONSEQUENT: consequent.current,\n ALTERNATE: alternate.current,\n }),\n );\n this.changes++;\n }\n },\n },\n ReturnStatement: {\n exit(path) {\n if (conditional.match(path.node.argument)) {\n path.replaceWith(\n buildIfReturn({\n TEST: test.current,\n CONSEQUENT: consequent.current,\n ALTERNATE: alternate.current,\n }),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
53
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nconst OPERATOR_MAP = {\n '>': '===',\n '<': '!==',\n} as const;\n\nexport default {\n name: 'typeof-undefined',\n tags: ['safe'],\n visitor() {\n const operator = m.capture(m.or('>' as const, '<' as const));\n const argument = m.capture(m.anyExpression());\n const matcher = m.binaryExpression(\n operator,\n m.unaryExpression('typeof', argument),\n m.stringLiteral('u'),\n );\n return {\n BinaryExpression: {\n exit(path) {\n if (!matcher.match(path.node)) return;\n path.replaceWith(\n t.binaryExpression(\n OPERATOR_MAP[operator.current!],\n t.unaryExpression('typeof', argument.current!),\n t.stringLiteral('undefined'),\n ),\n );\n this.changes++;\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
54
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'unary-expressions',\n tags: ['safe'],\n visitor() {\n const argument = m.capture(m.anyExpression());\n const matcher = m.expressionStatement(\n m.unaryExpression(m.or('void', '!', 'typeof'), argument),\n );\n const returnVoid = m.returnStatement(m.unaryExpression('void', argument));\n return {\n ExpressionStatement: {\n exit(path) {\n if (!matcher.match(path.node)) return;\n path.replaceWith(argument.current!);\n this.changes++;\n },\n },\n ReturnStatement: {\n exit(path) {\n if (!returnVoid.match(path.node)) return;\n path.replaceWith(argument.current!);\n path.insertAfter(t.returnStatement());\n this.changes++;\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
55
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'unminify-booleans',\n tags: ['safe'],\n visitor: () => ({\n UnaryExpression(path) {\n if (trueMatcher.match(path.node)) {\n path.replaceWith(t.booleanLiteral(true));\n this.changes++;\n } else if (falseMatcher.match(path.node)) {\n path.replaceWith(t.booleanLiteral(false));\n this.changes++;\n }\n },\n }),\n} satisfies Transform;\n\nconst trueMatcher = m.or(\n m.unaryExpression('!', m.numericLiteral(0)),\n m.unaryExpression('!', m.unaryExpression('!', m.numericLiteral(1))),\n m.unaryExpression('!', m.unaryExpression('!', m.arrayExpression([]))),\n);\n\nconst falseMatcher = m.or(\n m.unaryExpression('!', m.numericLiteral(1)),\n m.unaryExpression('!', m.arrayExpression([])),\n);\n",
|
|
56
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\nexport default {\n name: 'void-to-undefined',\n tags: ['safe'],\n scope: true,\n visitor: () => {\n const matcher = m.unaryExpression('void', m.numericLiteral(0));\n return {\n UnaryExpression: {\n exit(path) {\n if (\n matcher.match(path.node) &&\n !path.scope.hasBinding('undefined', { noGlobals: true })\n ) {\n path.replaceWith(t.identifier('undefined'));\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
57
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform } from '../../ast-utils';\n\n// https://eslint.org/docs/latest/rules/yoda and https://babeljs.io/docs/en/babel-plugin-minify-flip-comparisons\n\nconst FLIPPED_OPERATORS = {\n '==': '==',\n '===': '===',\n '!=': '!=',\n '!==': '!==',\n '>': '<',\n '<': '>',\n '>=': '<=',\n '<=': '>=',\n '*': '*',\n '^': '^',\n '&': '&',\n '|': '|',\n} as const;\n\nexport default {\n name: 'yoda',\n tags: ['safe'],\n visitor: () => {\n const matcher = m.binaryExpression(\n m.or(...Object.values(FLIPPED_OPERATORS)),\n m.or(\n m.stringLiteral(),\n m.numericLiteral(),\n m.unaryExpression(\n '-',\n m.or(m.numericLiteral(), m.identifier('Infinity')),\n ),\n m.booleanLiteral(),\n m.nullLiteral(),\n m.identifier('undefined'),\n m.identifier('NaN'),\n m.identifier('Infinity'),\n ),\n m.matcher((node) => !t.isLiteral(node)),\n );\n\n return {\n BinaryExpression: {\n exit(path) {\n if (matcher.match(path.node)) {\n path.replaceWith(\n t.binaryExpression(\n FLIPPED_OPERATORS[\n path.node.operator as keyof typeof FLIPPED_OPERATORS\n ],\n path.node.right,\n path.node.left as t.Expression,\n ),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
58
|
-
"import { mergeTransforms } from '../ast-utils';\nimport * as transforms from './transforms';\n\nexport default mergeTransforms({\n name: 'unminify',\n tags: ['safe'],\n transforms: Object.values(transforms),\n});\n",
|
|
59
|
-
"import type * as t from '@babel/types';\nimport {getQuickJS, shouldInterruptAfterDeadline} from 'quickjs-emscripten';\nimport deobfuscate from 'webcrack/deobfuscate';\nimport varFunctions from 'webcrack/deobfuscate/var-functions';\nimport mergeObjectAssignments from 'webcrack/deobfuscate/merge-object-assignments';\nimport unminify from 'webcrack/unminify';\nimport {blockStatements, sequence, splitVariableDeclarations} from 'webcrack/unminify/transforms';\nimport {applyTransform, applyTransformAsync, applyTransforms} from 'webcrack/ast-utils';\n\n/**\n * Run webcrack passes.\n */\nexport default async function transform(\n\tast: t.Node,\n) {\n\tapplyTransforms(\n\t\tast,\n\t\t[blockStatements, sequence, splitVariableDeclarations, varFunctions],\n\t\t{\n\t\t\tname: 'prepare',\n\t\t},\n\t);\n\n\tconst quickjs = await getQuickJS();\n\tawait applyTransformAsync(ast, deobfuscate, async (code: string) => quickjs.evalCode(code, {\n\t\tshouldInterrupt: shouldInterruptAfterDeadline(Date.now() + 2000),\n\t\tmemoryLimitBytes: 1024 * 1024,\n\t}));\n\n\tapplyTransform(ast, unminify);\n\tapplyTransform(ast, mergeObjectAssignments);\n\n\treturn ast;\n}\n",
|
|
60
|
-
"import type {NodePath, TraverseOptions} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport type {TransformState, Transform} from 'webcrack/ast-utils';\nimport {chunks} from '~matchers/chunk';\nimport createBinding, {__createBinding} from '~matchers/createBinding';\nimport setModuleDefault, {__setModuleDefault} from '~matchers/setModuleDefault';\nimport importStar, {__importStar} from '~matchers/importStar';\nimport importDefault, {__importDefault} from '~matchers/importDefault';\nimport exportStar, {__exportStar} from '~matchers/exportStar';\n\nconst preExport = m.assignmentExpression(\n\t'=',\n\tm.memberExpression(\n\t\tm.identifier('exports'),\n\t\tm.identifier(),\n\t\tfalse,\n\t),\n\tm.identifier('undefined'),\n);\n\nconst undefinedExpr = m.expressionStatement(m.identifier('undefined'));\n\n/** Rename webpack RequireJS shims and tsc esmodule helpers.\n * @link <https://www.typescriptlang.org/tsconfig#esModuleInterop>\n */\nexport default {\n\tname: 'module-helper',\n\ttags: ['safe'],\n\tscope: true,\n\tvisitor: (): TraverseOptions<TransformState> => ({\n\t\tObjectExpression: {\n\t\t\tenter($) {\n\t\t\t\tif (!chunks.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst $chunks: NodePath[] = $.get('properties');\n\n\t\t\t\tfor (const $chunk of $chunks) {\n\t\t\t\t\t$chunk.assertObjectProperty();\n\n\t\t\t\t\tconst $func: NodePath = $chunk.get('value');\n\t\t\t\t\t$func.assertFunction();\n\n\t\t\t\t\tconst $p: NodePath[] = $func.get('params');\n\t\t\t\t\t// eslint-disable-next-line unicorn/no-array-for-each\n\t\t\t\t\t$p.forEach(($parameter: NodePath, i) => {\n\t\t\t\t\t\t$parameter.assertIdentifier();\n\n\t\t\t\t\t\tswitch (i) {\n\t\t\t\t\t\t\tcase 0: {\n\t\t\t\t\t\t\t\t$func.scope.rename($parameter.node.name, 'module');\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase 1: {\n\t\t\t\t\t\t\t\t$func.scope.rename($parameter.node.name, 'exports');\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase 2: {\n\t\t\t\t\t\t\t\t$func.scope.rename($parameter.node.name, 'require');\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t\tthrow new Error('Unexpected param');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t$func.traverse({\n\t\t\t\t\t\t// Find `esModuleInterop` helpers\n\t\t\t\t\t\tVariableDeclaration: {\n\t\t\t\t\t\t\texit(p) {\n\t\t\t\t\t\t\t\tconst $decl: NodePath = p.get('declarations.0') as NodePath;\n\t\t\t\t\t\t\t\t$decl.assertVariableDeclarator();\n\n\t\t\t\t\t\t\t\tconst $id: NodePath = $decl.get('id');\n\t\t\t\t\t\t\t\tif (!$id.isIdentifier()) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/** @link <https://github.com/microsoft/TypeScript/tree/main/src/compiler/factory/emitHelpers.ts> */\n\t\t\t\t\t\t\t\tif (importStar.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__importStar');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__importStar);\n\t\t\t\t\t\t\t\t} else if (setModuleDefault.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__setModuleDefault');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__setModuleDefault);\n\t\t\t\t\t\t\t\t} else if (importDefault.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__importDefault');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__importDefault);\n\t\t\t\t\t\t\t\t} else if (createBinding.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__createBinding');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__createBinding);\n\t\t\t\t\t\t\t\t} else if (exportStar.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__exportStar');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__exportStar);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tthis.changes++;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// Remove early export declarations\n\t\t\t\t\t\t/* In some cases, `exports` is a getter/setter, so disable for now.\n\t\t\t\t\t\tAssignmentExpression: {\n\t\t\t\t\t\t\texit(p) {\n\t\t\t\t\t\t\t\tif (!preExport.match(p.node)) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Why not `buildUndefinedNode`?\n\t\t\t\t\t\t\t\t// That method generates `void 0` instead of plain `undefined`,\n\t\t\t\t\t\t\t\t// which is not what we want.\n\t\t\t\t\t\t\t\tp.replaceWith(t.identifier('undefined'));\n\t\t\t\t\t\t\t\tif (undefinedExpr.match(p.parent)) {\n\t\t\t\t\t\t\t\t\tp.parentPath.remove();\n\t\t\t\t\t\t\t\t\tthis.changes++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t*/\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t}),\n} satisfies Transform;\n",
|
|
61
|
-
"import type * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\n\nconst mod = m.capture(m.identifier());\nconst exp = m.capture(m.identifier());\nconst req = m.capture(m.identifier());\n\n/** Required hack for typings to work. */\nconst functionExpr = (\n\targs: Array<m.Matcher<t.Identifier>>,\n) => m.or(\n\tm.functionExpression(\n\t\tnull,\n\t\targs,\n\t\tm.blockStatement(),\n\t\tfalse,\n\t\tfalse,\n\t),\n\tm.arrowFunctionExpression(\n\t\targs,\n\t\tm.blockStatement(),\n\t\tfalse,\n\t),\n);\n\n/** Match a module chunk, optionally by ID. */\nexport function chunk(id?: number) {\n\treturn m.objectProperty(\n\t\tm.numericLiteral(id), // Module ID\n\t\tm.or( // Module body\n\t\t\tfunctionExpr([]),\n\t\t\tfunctionExpr([mod]),\n\t\t\tfunctionExpr([mod, exp]),\n\t\t\tfunctionExpr([mod, exp, req]),\n\t\t),\n\t);\n}\n\n/** Match a list of module chunks. */\nexport const chunks = m.objectExpression(\n\tm.anyList(m.oneOrMore(chunk())),\n);\n\n/** Match any module chunk. */\nexport default chunk();\n",
|
|
62
|
-
"import * as m from '@codemod/matchers';\nimport tmpl from '@babel/template';\n\nexport const __createBinding = tmpl.expression.ast`\n(this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n\tif (k2 === undefined) k2 = k;\n\tvar desc = Object.getOwnPropertyDescriptor(m, k);\n\tif (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n\t\tdesc = { enumerable: true, get: function() { return m[k]; } };\n\t}\n\tObject.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n\tif (k2 === undefined) k2 = k;\n\to[k2] = m[k];\n}))\n`;\n\nconst obj = m.capture(m.identifier());\nconst mod = m.capture(m.identifier());\nconst k = m.capture(m.identifier());\nconst k2 = m.capture(m.identifier());\nconst desc = m.capture(m.identifier());\n\nconst descObj = m.objectExpression([\n\tm.objectProperty(\n\t\tm.identifier('enumerable'),\n\t\tm.booleanLiteral(true),\n\t),\n\tm.objectProperty(\n\t\tm.identifier('get'),\n\t\tm.functionExpression(\n\t\t\tnull,\n\t\t\t[],\n\t\t\tm.blockStatement([\n\t\t\t\tm.returnStatement(\n\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t]),\n\t\t),\n\t),\n]);\n\nconst cond = m.conditionalExpression(\n\tm.binaryExpression(\n\t\t'in',\n\t\tm.stringLiteral('get'),\n\t\tm.fromCapture(desc),\n\t),\n\tm.unaryExpression(\n\t\t'!',\n\t\tm.memberExpression(\n\t\t\tm.fromCapture(mod),\n\t\t\tm.identifier('__esModule'),\n\t\t\tfalse,\n\t\t),\n\t),\n\tm.logicalExpression(\n\t\t'||',\n\t\tm.memberExpression(\n\t\t\tm.fromCapture(desc),\n\t\t\tm.identifier('writable'),\n\t\t\tfalse,\n\t\t),\n\t\tm.memberExpression(\n\t\t\tm.fromCapture(desc),\n\t\t\tm.identifier('configurable'),\n\t\t\tfalse,\n\t\t),\n\t),\n);\n\n/** Match `__createBinding`.\n * @example\n * ```javascript\n * var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n * \tif (k2 === undefined) k2 = k;\n * \tvar desc = Object.getOwnPropertyDescriptor(m, k);\n * \tif (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n * \t\tdesc = { enumerable: true, get: function() { return m[k]; } };\n * \t}\n * \tObject.defineProperty(o, k2, desc);\n * }) : (function(o, m, k, k2) {\n * \tif (k2 === undefined) k2 = k;\n * \to[k2] = m[k];\n * }));\n * ```\n * @example\n * ```javascript\n * var _v183 = this && this.__createBinding || (Object.create ? function (_a171, _a172, _a173, _a174) {\n * \tif (_a174 === undefined) {\n * \t\t_a174 = _a173;\n * \t}\n * \tObject.defineProperty(_a171, _a174, {\n * \t\tenumerable: true,\n * \t\tget: function () {\n * \t\t\treturn _a172[_a173];\n * \t\t}\n * \t});\n * } : function (_a175, _a176, _a177, _a178) {\n * \tif (_a178 === undefined) {\n * \t\t_a178 = _a177;\n * \t}\n * \t_a175[_a178] = _a176[_a177];\n * });\n * ```\n */\nexport default m.variableDeclaration('var', [\n\tm.variableDeclarator(\n\t\tm.identifier(),\n\t\tm.logicalExpression(\n\t\t\t'||',\n\t\t\tm.logicalExpression(\n\t\t\t\t'&&',\n\t\t\t\tm.thisExpression(),\n\t\t\t\tm.memberExpression(\n\t\t\t\t\tm.thisExpression(),\n\t\t\t\t\tm.identifier('__createBinding'),\n\t\t\t\t),\n\t\t\t),\n\t\t\tm.conditionalExpression(\n\t\t\t\tm.memberExpression(\n\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\tm.identifier('create'),\n\t\t\t\t),\n\t\t\t\tm.functionExpression(\n\t\t\t\t\tnull,\n\t\t\t\t\t[obj, mod, k, k2],\n\t\t\t\t\tm.or(\n\t\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\t\tm.binaryExpression(\n\t\t\t\t\t\t\t\t\t'===',\n\t\t\t\t\t\t\t\t\tk2,\n\t\t\t\t\t\t\t\t\tm.identifier('undefined'),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\t\t\tm.assignmentExpression(\n\t\t\t\t\t\t\t\t\t\t\t'=',\n\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k2),\n\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tm.variableDeclaration('var', [\n\t\t\t\t\t\t\t\tm.variableDeclarator(\n\t\t\t\t\t\t\t\t\tdesc,\n\t\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\t\t\t\t\t\t\tm.identifier('getOwnPropertyDescriptor'),\n\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\t\tm.logicalExpression(\n\t\t\t\t\t\t\t\t\t'||',\n\t\t\t\t\t\t\t\t\tm.unaryExpression(\n\t\t\t\t\t\t\t\t\t\t'!',\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(desc),\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tm.or(\n\t\t\t\t\t\t\t\t\t\tcond,\n\t\t\t\t\t\t\t\t\t\tm.unaryExpression(\n\t\t\t\t\t\t\t\t\t\t\t'!',\n\t\t\t\t\t\t\t\t\t\t\tm.unaryExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t'!',\n\t\t\t\t\t\t\t\t\t\t\t\tcond,\n\t\t\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\t\t\tm.assignmentExpression(\n\t\t\t\t\t\t\t\t\t\t\t'=',\n\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(desc),\n\t\t\t\t\t\t\t\t\t\t\tdescObj,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\t\t\t\t\t\tm.identifier('defineProperty'),\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(obj),\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(k2),\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(desc),\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\t\tm.binaryExpression(\n\t\t\t\t\t\t\t\t\t'===',\n\t\t\t\t\t\t\t\t\tk2,\n\t\t\t\t\t\t\t\t\tm.identifier('undefined'),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\t\t\tm.assignmentExpression(\n\t\t\t\t\t\t\t\t\t\t\t'=',\n\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k2),\n\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\t\t\t\t\t\tm.identifier('defineProperty'),\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(obj),\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(k2),\n\t\t\t\t\t\t\t\t\t\tdescObj,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tm.functionExpression(\n\t\t\t\t\tnull,\n\t\t\t\t\t[obj, mod, k, k2],\n\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\tm.binaryExpression(\n\t\t\t\t\t\t\t\t'===',\n\t\t\t\t\t\t\t\tk2,\n\t\t\t\t\t\t\t\tm.identifier('undefined'),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\t\tm.assignmentExpression(\n\t\t\t\t\t\t\t\t\t\t'=',\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(k2),\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\tm.assignmentExpression(\n\t\t\t\t\t\t\t\t'=',\n\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\tm.fromCapture(obj),\n\t\t\t\t\t\t\t\t\tm.fromCapture(k2),\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t),\n]);\n",
|
|
63
|
-
"import * as m from '@codemod/matchers';\nimport tmpl from '@babel/template';\n\nexport const __setModuleDefault = tmpl.expression.ast`\n(this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n\tObject.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n\to[\"default\"] = v;\n})\n`;\n\nconst leftParamObj = m.capture(m.identifier());\nconst leftParamVal = m.capture(m.identifier());\nconst leftObjIdentifier = m.capture(m.identifier());\nconst leftObj = m.objectExpression(\n\t[\n\t\tm.objectProperty(\n\t\t\tm.identifier('enumerable'),\n\t\t\tm.booleanLiteral(true),\n\t\t),\n\t\tm.objectProperty(\n\t\t\tm.identifier('value'),\n\t\t\tleftParamVal,\n\t\t),\n\t],\n);\n\nconst rightParamObj = m.capture(m.identifier());\nconst rightParamVal = m.capture(m.identifier());\n\n/** Match `__setModuleDefault`.\n * @example\n * ```javascript\n * var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n * \t// this inline ObjectExpression could be emitted as an isolated VariableDeclarator in the scope\n * \tObject.defineProperty(o, \"default\", { enumerable: true, value: v });\n * }) : function(o, v) {\n * \to[\"default\"] = v;\n * });\n * ```\n */\nexport default m.variableDeclaration('var', [\n\tm.variableDeclarator(\n\t\tm.identifier(),\n\t\tm.logicalExpression(\n\t\t\t'||',\n\t\t\tm.logicalExpression(\n\t\t\t\t'&&',\n\t\t\t\tm.thisExpression(),\n\t\t\t\tm.memberExpression(\n\t\t\t\t\tm.thisExpression(),\n\t\t\t\t\tm.identifier('__setModuleDefault'),\n\t\t\t\t),\n\t\t\t),\n\t\t\tm.conditionalExpression(\n\t\t\t\tm.memberExpression(\n\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\tm.identifier('create'),\n\t\t\t\t),\n\t\t\t\tm.functionExpression(\n\t\t\t\t\tnull,\n\t\t\t\t\t[\n\t\t\t\t\t\tleftParamObj,\n\t\t\t\t\t\tleftParamVal,\n\t\t\t\t\t],\n\t\t\t\t\tm.or(\n\t\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\t\tm.variableDeclaration(\n\t\t\t\t\t\t\t\t'const',\n\t\t\t\t\t\t\t\t[m.variableDeclarator(\n\t\t\t\t\t\t\t\t\tleftObjIdentifier,\n\t\t\t\t\t\t\t\t\tleftObj,\n\t\t\t\t\t\t\t\t)],\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\t\t\t\t\t\tm.identifier('defineProperty'),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\tleftParamObj,\n\t\t\t\t\t\t\t\t\t\tm.stringLiteral('default'),\n\t\t\t\t\t\t\t\t\t\tleftObjIdentifier,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\t\t\t\t\t\tm.identifier('defineProperty'),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\tleftParamObj,\n\t\t\t\t\t\t\t\t\t\tm.stringLiteral('default'),\n\t\t\t\t\t\t\t\t\t\tleftObj,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]),\n\t\t\t\t\t),\n\t\t\t\t\tfalse,\n\t\t\t\t\tfalse,\n\t\t\t\t),\n\t\t\t\tm.functionExpression(\n\t\t\t\t\tnull,\n\t\t\t\t\t[\n\t\t\t\t\t\trightParamObj,\n\t\t\t\t\t\trightParamVal,\n\t\t\t\t\t],\n\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\tm.assignmentExpression(\n\t\t\t\t\t\t\t\t'=',\n\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\trightParamObj,\n\t\t\t\t\t\t\t\t\tm.identifier('default'),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\trightParamVal,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t),\n]);\n",
|
|
64
|
-
"import * as m from '@codemod/matchers';\nimport tmpl from '@babel/template';\n\nexport const __importStar = tmpl.expression.ast`\n(this && this.__importStar) || function (mod) {\n\tif (mod && mod.__esModule) return mod;\n\tvar result = {};\n\tif (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n\t__setModuleDefault(result, mod);\n\treturn result;\n}\n`;\n\nconst mod = m.capture(m.identifier());\nconst k = m.capture(m.identifier());\nconst result = m.capture(m.identifier());\n\n/** Match `__importStar`.\n * @example\n * ```javascript\n * var __importStar = (this && this.__importStar) || function (mod) {\n * \tif (mod && mod.__esModule) return mod;\n * \tvar result = {};\n * \tif (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n * \t__setModuleDefault(result, mod);\n * \treturn result;\n * };\n * ```\n */\nexport default m.variableDeclaration('var', [\n\tm.variableDeclarator(\n\t\tm.identifier(),\n\t\tm.logicalExpression(\n\t\t\t'||',\n\t\t\tm.logicalExpression(\n\t\t\t\t'&&',\n\t\t\t\tm.thisExpression(),\n\t\t\t\tm.memberExpression(\n\t\t\t\t\tm.thisExpression(),\n\t\t\t\t\tm.identifier('__importStar'),\n\t\t\t\t\tfalse,\n\t\t\t\t),\n\t\t\t),\n\t\t\tm.functionExpression(\n\t\t\t\tnull,\n\t\t\t\t[mod],\n\t\t\t\tm.or(\n\t\t\t\t\tm.blockStatement([\n\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\tm.logicalExpression(\n\t\t\t\t\t\t\t\t'&&',\n\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\tm.identifier('__esModule'),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\tm.returnStatement(\n\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tm.variableDeclaration('var', [\n\t\t\t\t\t\t\tm.variableDeclarator(\n\t\t\t\t\t\t\t\tresult,\n\t\t\t\t\t\t\t\tm.objectExpression([]),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\tm.binaryExpression('!=', m.fromCapture(mod), m.nullLiteral()),\n\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\tm.forInStatement(\n\t\t\t\t\t\t\t\t\tm.variableDeclaration(\n\t\t\t\t\t\t\t\t\t\t'var',\n\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\tm.variableDeclarator(\n\t\t\t\t\t\t\t\t\t\t\t\tk,\n\t\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\t\t\t\t\tm.logicalExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t'&&',\n\t\t\t\t\t\t\t\t\t\t\t\tm.binaryExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'!==',\n\t\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\t\t\t\t\tm.stringLiteral('default'),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('prototype'),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('hasOwnProperty'),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('call'),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(result),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(k),\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\tm.identifier(),\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\tm.fromCapture(result),\n\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tm.returnStatement(m.fromCapture(result)),\n\t\t\t\t\t]),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t),\n],\n);\n",
|
|
65
|
-
"import * as m from '@codemod/matchers';\nimport tmpl from '@babel/template';\n\nexport const __importDefault = tmpl.expression.ast`\n(this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n}\n`;\n\nconst mod = m.capture(m.identifier());\nconst isEsm = m.logicalExpression(\n\t'&&',\n\tm.fromCapture(mod),\n\tm.memberExpression(\n\t\tm.fromCapture(mod),\n\t\tm.identifier('__esModule'),\n\t\tfalse,\n\t),\n);\n\n/** Match `__importDefault`.\n * @example\n * ```javascript\n * var __importDefault = (this && this.__importDefault) || function (mod) {\n * \treturn (mod && mod.__esModule) ? mod : { \"default\": mod };\n * };\n * ```\n * @example\n * ```javascript\n * var data_55311B = this && this.__importDefault || function (_a1) {\n * \tif (_a1 && _a1.__esModule) {\n * \t\treturn _a1;\n * \t} else {\n * \t\treturn {\n * \t\t\tdefault: _a1\n * \t\t};\n * \t}\n * };\n * ```\n */\nexport default m.variableDeclaration('var', [\n\tm.variableDeclarator(\n\t\tm.identifier(),\n\t\tm.logicalExpression(\n\t\t\t'||',\n\t\t\tm.logicalExpression(\n\t\t\t\t'&&',\n\t\t\t\tm.thisExpression(),\n\t\t\t\tm.memberExpression(\n\t\t\t\t\tm.thisExpression(),\n\t\t\t\t\tm.identifier('__importDefault'),\n\t\t\t\t),\n\t\t\t),\n\t\t\tm.functionExpression(\n\t\t\t\tnull,\n\t\t\t\t[mod],\n\t\t\t\tm.blockStatement([\n\t\t\t\t\tm.or(\n\t\t\t\t\t\tm.returnStatement(\n\t\t\t\t\t\t\tm.conditionalExpression(\n\t\t\t\t\t\t\t\tisEsm,\n\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\tm.objectExpression([\n\t\t\t\t\t\t\t\t\tm.objectProperty(\n\t\t\t\t\t\t\t\t\t\tm.stringLiteral('default'),\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\tisEsm,\n\t\t\t\t\t\t\tm.containerOf(m.returnStatement(\n\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t)),\n\t\t\t\t\t\t\tm.containerOf(m.returnStatement(\n\t\t\t\t\t\t\t\tm.objectExpression([\n\t\t\t\t\t\t\t\t\tm.objectProperty(\n\t\t\t\t\t\t\t\t\t\tm.identifier('default'),\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t)),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t]),\n\t\t\t),\n\t\t),\n\t),\n]);\n",
|
|
66
|
-
"import * as m from '@codemod/matchers';\nimport tmpl from '@babel/template';\n\nexport const __exportStar = tmpl.expression.ast`\n(this && this.__exportStar) || function(m, exports) {\n\tfor (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n}\n`;\n\nconst mod = m.capture(m.identifier());\nconst exp = m.capture(m.identifier());\nconst p = m.capture(m.identifier());\n\n/** Match `__exportStar`.\n * @example\n * ```javascript\n * var __exportStar = (this && this.__exportStar) || function(m, exports) {\n * \tfor (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n * };\n * ```\n */\nexport default m.variableDeclaration('var', [\n\tm.variableDeclarator(\n\t\tm.identifier(),\n\t\tm.logicalExpression(\n\t\t\t'||',\n\t\t\tm.logicalExpression(\n\t\t\t\t'&&',\n\t\t\t\tm.thisExpression(),\n\t\t\t\tm.memberExpression(\n\t\t\t\t\tm.thisExpression(),\n\t\t\t\t\tm.identifier('__exportStar'),\n\t\t\t\t\tfalse,\n\t\t\t\t),\n\t\t\t),\n\t\t\tm.functionExpression(\n\t\t\t\tnull,\n\t\t\t\t[mod, exp],\n\t\t\t\tm.blockStatement([\n\t\t\t\t\tm.forInStatement(\n\t\t\t\t\t\tm.variableDeclaration('var', [\n\t\t\t\t\t\t\tm.variableDeclarator(\n\t\t\t\t\t\t\t\tp,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\tm.ifStatement(\n\t\t\t\t\t\t\t\tm.logicalExpression(\n\t\t\t\t\t\t\t\t\t'&&',\n\t\t\t\t\t\t\t\t\tm.binaryExpression(\n\t\t\t\t\t\t\t\t\t\t'!==',\n\t\t\t\t\t\t\t\t\t\tm.fromCapture(p),\n\t\t\t\t\t\t\t\t\t\tm.stringLiteral('default'),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tm.unaryExpression(\n\t\t\t\t\t\t\t\t\t\t'!',\n\t\t\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\tm.memberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('Object'),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('prototype'),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('hasOwnProperty'),\n\t\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tm.identifier('call'),\n\t\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(exp),\n\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(p),\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tm.containerOf(\n\t\t\t\t\t\t\t\t\tm.expressionStatement(\n\t\t\t\t\t\t\t\t\t\tm.callExpression(\n\t\t\t\t\t\t\t\t\t\t\tm.identifier(),\n\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(exp),\n\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(mod),\n\t\t\t\t\t\t\t\t\t\t\t\tm.fromCapture(p),\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t]),\n\t\t\t),\n\t\t),\n\t),\n]);\n",
|
|
67
|
-
"import type {NodePath, TraverseOptions} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport type {TransformState, Transform} from 'webcrack/ast-utils';\nimport {chunks} from '~matchers/chunk';\nimport createBinding, {__createBinding} from '~matchers/createBinding';\nimport setModuleDefault, {__setModuleDefault} from '~matchers/setModuleDefault';\nimport importStar, {__importStar} from '~matchers/importStar';\nimport importDefault, {__importDefault} from '~matchers/importDefault';\nimport exportStar, {__exportStar} from '~matchers/exportStar';\n\nconst preExport = m.assignmentExpression(\n\t'=',\n\tm.memberExpression(\n\t\tm.identifier('exports'),\n\t\tm.identifier(),\n\t\tfalse,\n\t),\n\tm.identifier('undefined'),\n);\n\nconst undefinedExpr = m.expressionStatement(m.identifier('undefined'));\n\n/** Rename webpack RequireJS shims and tsc esmodule helpers.\n * @link <https://www.typescriptlang.org/tsconfig#esModuleInterop>\n */\nexport default {\n\tname: 'module-helper',\n\ttags: ['safe'],\n\tscope: true,\n\tvisitor: (): TraverseOptions<TransformState> => ({\n\t\tObjectExpression: {\n\t\t\tenter($) {\n\t\t\t\tif (!chunks.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst $chunks: NodePath[] = $.get('properties');\n\n\t\t\t\tfor (const $chunk of $chunks) {\n\t\t\t\t\t$chunk.assertObjectProperty();\n\n\t\t\t\t\tconst $func: NodePath = $chunk.get('value');\n\t\t\t\t\t$func.assertFunction();\n\n\t\t\t\t\tconst $p: NodePath[] = $func.get('params');\n\t\t\t\t\t// eslint-disable-next-line unicorn/no-array-for-each\n\t\t\t\t\t$p.forEach(($parameter: NodePath, i) => {\n\t\t\t\t\t\t$parameter.assertIdentifier();\n\n\t\t\t\t\t\tswitch (i) {\n\t\t\t\t\t\t\tcase 0: {\n\t\t\t\t\t\t\t\t$func.scope.rename($parameter.node.name, 'module');\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase 1: {\n\t\t\t\t\t\t\t\t$func.scope.rename($parameter.node.name, 'exports');\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase 2: {\n\t\t\t\t\t\t\t\t$func.scope.rename($parameter.node.name, 'require');\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t\tthrow new Error('Unexpected param');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t$func.traverse({\n\t\t\t\t\t\t// Find `esModuleInterop` helpers\n\t\t\t\t\t\tVariableDeclaration: {\n\t\t\t\t\t\t\texit(p) {\n\t\t\t\t\t\t\t\tconst $decl: NodePath = p.get('declarations.0') as NodePath;\n\t\t\t\t\t\t\t\t$decl.assertVariableDeclarator();\n\n\t\t\t\t\t\t\t\tconst $id: NodePath = $decl.get('id');\n\t\t\t\t\t\t\t\tif (!$id.isIdentifier()) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/** @link <https://github.com/microsoft/TypeScript/tree/main/src/compiler/factory/emitHelpers.ts> */\n\t\t\t\t\t\t\t\tif (importStar.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__importStar');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__importStar);\n\t\t\t\t\t\t\t\t} else if (setModuleDefault.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__setModuleDefault');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__setModuleDefault);\n\t\t\t\t\t\t\t\t} else if (importDefault.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__importDefault');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__importDefault);\n\t\t\t\t\t\t\t\t} else if (createBinding.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__createBinding');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__createBinding);\n\t\t\t\t\t\t\t\t} else if (exportStar.match(t.cloneNode(p.node))) {\n\t\t\t\t\t\t\t\t\t$id.scope.rename($id.node.name, '__exportStar');\n\t\t\t\t\t\t\t\t\t$decl.get('init').replaceWith(__exportStar);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tthis.changes++;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// Remove early export declarations\n\t\t\t\t\t\t/* In some cases, `exports` is a getter/setter, so disable for now.\n\t\t\t\t\t\tAssignmentExpression: {\n\t\t\t\t\t\t\texit(p) {\n\t\t\t\t\t\t\t\tif (!preExport.match(p.node)) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Why not `buildUndefinedNode`?\n\t\t\t\t\t\t\t\t// That method generates `void 0` instead of plain `undefined`,\n\t\t\t\t\t\t\t\t// which is not what we want.\n\t\t\t\t\t\t\t\tp.replaceWith(t.identifier('undefined'));\n\t\t\t\t\t\t\t\tif (undefinedExpr.match(p.parent)) {\n\t\t\t\t\t\t\t\t\tp.parentPath.remove();\n\t\t\t\t\t\t\t\t\tthis.changes++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t*/\n\t\t\t\t\t}, this);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t}),\n} satisfies Transform;\n",
|
|
68
|
-
"import * as t from '@babel/types';\nimport type {Transform} from 'webcrack/ast-utils';\n\n/**\n * Simplify function calls between modules that discard reference bindings\n *\n * @example\n * `(0, someModule.someFunction)(args)` -> `someModule.someFunction(args)`\n *\n * @link <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_operator#discarding_reference_binding>\n * @link <https://github.com/pionxzh/wakaru/blob/main/packages/unminify/src/transformations/un-indirect-call.ts>\n */\nexport default {\n\tname: 'indirect-call',\n\ttags: ['unsafe'],\n\tvisitor: () => ({\n\n\t\tCallExpression: {\n\t\t\texit($) {\n\t\t\t\tconst {callee, arguments: args} = $.node;\n\t\t\t\tif (!t.isSequenceExpression(callee)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst exprs = [...callee.expressions];\n\t\t\t\tconst func = exprs.pop();\n\t\t\t\tif (!t.isMemberExpression(func)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Ensure no side effects in the sequence\n\t\t\t\tif (exprs.every(expr => t.isPureish(expr))) {\n\t\t\t\t\t$.replaceWith(t.callExpression(func, args));\n\t\t\t\t\tthis.changes++;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t}),\n} satisfies Transform;\n\n",
|
|
69
|
-
"import {parse as babelParse} from '@babel/parser';\nimport babelGenerate from '@babel/generator';\nimport type * as t from '@babel/types';\nimport debug from 'debug';\nimport traverse, {type Node, type TraverseOptions, visitors} from '@babel/traverse';\nimport type {TransformState, Transform, AsyncTransform} from 'webcrack/ast-utils';\n\nconst logger = debug('delance:transforms');\n\nexport function parse(code: string) {\n\treturn babelParse(code, {\n\t\tsourceType: 'script',\n\t\tallowReturnOutsideFunction: true,\n\t});\n}\n\nexport function generate(ast: t.Node): string {\n\treturn babelGenerate(ast, {jsescOption: {minimal: true, quotes: 'single'}}).code;\n}\n\nexport async function applyTransformAsync<TOptions>(\n\tast: Node,\n\ttransform: AsyncTransform<TOptions>,\n\toptions?: TOptions,\n): Promise<TransformState> {\n\tlogger(`${transform.name}: started`);\n\tconst state: TransformState = {changes: 0};\n\n\tawait transform.run?.(ast, state, options);\n\tif (transform.visitor) {\n\t\ttraverse(ast, transform.visitor(options), undefined, state);\n\t}\n\n\tlogger(`${transform.name}: finished with ${state.changes} changes`);\n\treturn state;\n}\n\nexport function applyTransform<TOptions>(\n\tast: Node,\n\ttransform: Transform<TOptions>,\n\toptions?: TOptions,\n\tnoScopeOverride?: boolean,\n): TransformState {\n\tlogger(`${transform.name}: started`);\n\tconst state: TransformState = {changes: 0};\n\ttransform.run?.(ast, state, options);\n\n\tif (transform.visitor) {\n\t\tconst visitor = transform.visitor(\n\t\t\toptions,\n\t\t) as TraverseOptions<TransformState>;\n\t\tvisitor.noScope = noScopeOverride ?? !transform.scope;\n\t\ttraverse(ast, visitor, undefined, state);\n\t}\n\n\tlogger(`${transform.name}: finished with ${state.changes} changes`);\n\treturn state;\n}\n\nexport function applyTransforms(\n\tast: Node,\n\ttransforms: Transform[],\n\toptions: {noScope?: boolean; name?: string; log?: boolean} = {},\n): TransformState {\n\toptions.log ??= true;\n\tconst name = options.name ?? transforms.map(t => t.name).join(', ');\n\tif (options.log) {\n\t\tlogger(`${name}: started`);\n\t}\n\n\tconst state: TransformState = {changes: 0};\n\n\tfor (const transform of transforms) {\n\t\ttransform.run?.(ast, state);\n\t}\n\n\tconst traverseOptions = transforms.flatMap(t => t.visitor?.() ?? []);\n\tif (traverseOptions.length > 0) {\n\t\tconst visitor: TraverseOptions<TransformState>\n\t\t\t= visitors.merge(traverseOptions);\n\t\tvisitor.noScope = options.noScope ?? transforms.every(t => !t.scope);\n\t\ttraverse(ast, visitor, undefined, state);\n\t}\n\n\tif (options.log) {\n\t\tlogger(`${name}: finished with ${state.changes} changes`);\n\t}\n\n\treturn state;\n}\n",
|
|
70
|
-
"import {parse as babelParse} from '@babel/parser';\nimport babelGenerate from '@babel/generator';\nimport type * as t from '@babel/types';\nimport debug from 'debug';\nimport traverse, {type Node, type TraverseOptions, visitors} from '@babel/traverse';\nimport type {TransformState, Transform, AsyncTransform} from 'webcrack/ast-utils';\n\nconst logger = debug('delance:transforms');\n\nexport function parse(code: string) {\n\treturn babelParse(code, {\n\t\tsourceType: 'script',\n\t\tallowReturnOutsideFunction: true,\n\t});\n}\n\nexport function generate(ast: t.Node): string {\n\treturn babelGenerate(ast, {jsescOption: {minimal: true, quotes: 'single'}}).code;\n}\n\nexport async function applyTransformAsync<TOptions>(\n\tast: Node,\n\ttransform: AsyncTransform<TOptions>,\n\toptions?: TOptions,\n): Promise<TransformState> {\n\tlogger(`${transform.name}: started`);\n\tconst state: TransformState = {changes: 0};\n\n\tawait transform.run?.(ast, state, options);\n\tif (transform.visitor) {\n\t\ttraverse(ast, transform.visitor(options), undefined, state);\n\t}\n\n\tlogger(`${transform.name}: finished with ${state.changes} changes`);\n\treturn state;\n}\n\nexport function applyTransform<TOptions>(\n\tast: Node,\n\ttransform: Transform<TOptions>,\n\toptions?: TOptions,\n\tnoScopeOverride?: boolean,\n): TransformState {\n\tlogger(`${transform.name}: started`);\n\tconst state: TransformState = {changes: 0};\n\ttransform.run?.(ast, state, options);\n\n\tif (transform.visitor) {\n\t\tconst visitor = transform.visitor(\n\t\t\toptions,\n\t\t) as TraverseOptions<TransformState>;\n\t\tvisitor.noScope = noScopeOverride ?? !transform.scope;\n\t\ttraverse(ast, visitor, undefined, state);\n\t}\n\n\tlogger(`${transform.name}: finished with ${state.changes} changes`);\n\treturn state;\n}\n\nexport function applyTransforms(\n\tast: Node,\n\ttransforms: Transform[],\n\toptions: {noScope?: boolean; name?: string; log?: boolean} = {},\n): TransformState {\n\toptions.log ??= true;\n\tconst name = options.name ?? transforms.map(t => t.name).join(', ');\n\tif (options.log) {\n\t\tlogger(`${name}: started`);\n\t}\n\n\tconst state: TransformState = {changes: 0};\n\n\tfor (const transform of transforms) {\n\t\ttransform.run?.(ast, state);\n\t}\n\n\tconst traverseOptions = transforms.flatMap(t => t.visitor?.() ?? []);\n\tif (traverseOptions.length > 0) {\n\t\tconst visitor: TraverseOptions<TransformState>\n\t\t\t= visitors.merge(traverseOptions);\n\t\tvisitor.noScope = options.noScope ?? transforms.every(t => !t.scope);\n\t\ttraverse(ast, visitor, undefined, state);\n\t}\n\n\tif (options.log) {\n\t\tlogger(`${name}: finished with ${state.changes} changes`);\n\t}\n\n\treturn state;\n}\n",
|
|
71
|
-
"import {parse as babelParse} from '@babel/parser';\nimport babelGenerate from '@babel/generator';\nimport type * as t from '@babel/types';\nimport debug from 'debug';\nimport traverse, {type Node, type TraverseOptions, visitors} from '@babel/traverse';\nimport type {TransformState, Transform, AsyncTransform} from 'webcrack/ast-utils';\n\nconst logger = debug('delance:transforms');\n\nexport function parse(code: string) {\n\treturn babelParse(code, {\n\t\tsourceType: 'script',\n\t\tallowReturnOutsideFunction: true,\n\t});\n}\n\nexport function generate(ast: t.Node): string {\n\treturn babelGenerate(ast, {jsescOption: {minimal: true, quotes: 'single'}}).code;\n}\n\nexport async function applyTransformAsync<TOptions>(\n\tast: Node,\n\ttransform: AsyncTransform<TOptions>,\n\toptions?: TOptions,\n): Promise<TransformState> {\n\tlogger(`${transform.name}: started`);\n\tconst state: TransformState = {changes: 0};\n\n\tawait transform.run?.(ast, state, options);\n\tif (transform.visitor) {\n\t\ttraverse(ast, transform.visitor(options), undefined, state);\n\t}\n\n\tlogger(`${transform.name}: finished with ${state.changes} changes`);\n\treturn state;\n}\n\nexport function applyTransform<TOptions>(\n\tast: Node,\n\ttransform: Transform<TOptions>,\n\toptions?: TOptions,\n\tnoScopeOverride?: boolean,\n): TransformState {\n\tlogger(`${transform.name}: started`);\n\tconst state: TransformState = {changes: 0};\n\ttransform.run?.(ast, state, options);\n\n\tif (transform.visitor) {\n\t\tconst visitor = transform.visitor(\n\t\t\toptions,\n\t\t) as TraverseOptions<TransformState>;\n\t\tvisitor.noScope = noScopeOverride ?? !transform.scope;\n\t\ttraverse(ast, visitor, undefined, state);\n\t}\n\n\tlogger(`${transform.name}: finished with ${state.changes} changes`);\n\treturn state;\n}\n\nexport function applyTransforms(\n\tast: Node,\n\ttransforms: Transform[],\n\toptions: {noScope?: boolean; name?: string; log?: boolean} = {},\n): TransformState {\n\toptions.log ??= true;\n\tconst name = options.name ?? transforms.map(t => t.name).join(', ');\n\tif (options.log) {\n\t\tlogger(`${name}: started`);\n\t}\n\n\tconst state: TransformState = {changes: 0};\n\n\tfor (const transform of transforms) {\n\t\ttransform.run?.(ast, state);\n\t}\n\n\tconst traverseOptions = transforms.flatMap(t => t.visitor?.() ?? []);\n\tif (traverseOptions.length > 0) {\n\t\tconst visitor: TraverseOptions<TransformState>\n\t\t\t= visitors.merge(traverseOptions);\n\t\tvisitor.noScope = options.noScope ?? transforms.every(t => !t.scope);\n\t\ttraverse(ast, visitor, undefined, state);\n\t}\n\n\tif (options.log) {\n\t\tlogger(`${name}: finished with ${state.changes} changes`);\n\t}\n\n\treturn state;\n}\n",
|
|
72
|
-
"import type * as t from '@babel/types';\nimport moduleHelper from './module-helper';\nimport indirectCall from './indirect-call';\nimport {applyTransform} from '~ast';\n\n/**\n * Restore minified webpack-style ESM helpers.\n */\nexport default function transform(ast: t.Node) {\n\tapplyTransform(ast, moduleHelper);\n\tapplyTransform(ast, indirectCall);\n\n\treturn ast;\n}\n\n",
|
|
73
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport type {Transform, TransformState} from 'webcrack/ast-utils';\nimport type {TraverseOptions} from '@babel/traverse';\n\nfunction escape(string: string) {\n\treturn string\n\t\t.replaceAll('\\\\', '\\\\\\\\')\n\t\t.replaceAll('`', '\\\\`')\n\t\t.replaceAll('$', '\\\\$')\n\t\t.replaceAll('\\t', '\\\\t')\n\t\t.replaceAll('\\r', '\\\\r')\n\t\t.replaceAll('\\0', '\\\\0');\n}\n\nexport default {\n\tname: 'template-literal',\n\ttags: ['safe'],\n\tvisitor(): TraverseOptions<TransformState> {\n\t\tconst concatExpr = m.binaryExpression(\n\t\t\t'+',\n\t\t\tm.or(\n\t\t\t\tm.stringLiteral(),\n\t\t\t\tm.templateLiteral(),\n\t\t\t),\n\t\t\tm.anyExpression(),\n\t\t);\n\n\t\treturn {\n\t\t\tBinaryExpression: {\n\t\t\t\texit($) {\n\t\t\t\t\tif (!concatExpr.match($.node)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $left = $.get('left');\n\t\t\t\t\tconst $right = $.get('right');\n\n\t\t\t\t\tif ($left.isTemplateLiteral()) {\n\t\t\t\t\t\tif ($right.isTemplateLiteral()) {\n\t\t\t\t\t\t\tconst last = $left.node.quasis.pop();\n\t\t\t\t\t\t\tif (!last) {\n\t\t\t\t\t\t\t\tthrow new Error('Unexpected empty template literal');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$left.node.quasis.push(\n\t\t\t\t\t\t\t\tt.templateElement({\n\t\t\t\t\t\t\t\t\traw: last.value.raw + $right.node.quasis[0].value.raw,\n\t\t\t\t\t\t\t\t}, false),\n\t\t\t\t\t\t\t\t...$right.node.quasis.slice(1),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t$.replaceWith(\n\t\t\t\t\t\t\t\tt.templateLiteral(\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t...$left.node.quasis,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t...$left.node.expressions,\n\t\t\t\t\t\t\t\t\t\t...$right.node.expressions,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else if ($right.isStringLiteral()) {\n\t\t\t\t\t\t\tconst last = $left.node.quasis.pop();\n\t\t\t\t\t\t\tif (!last) {\n\t\t\t\t\t\t\t\tthrow new Error('Unexpected empty template literal');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$left.node.quasis.push(\n\t\t\t\t\t\t\t\tt.templateElement({\n\t\t\t\t\t\t\t\t\traw: escape(last.value.raw + $right.node.value),\n\t\t\t\t\t\t\t\t}, true),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t$.replaceWith($left.node);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$.replaceWith(\n\t\t\t\t\t\t\t\tt.templateLiteral(\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t...$left.node.quasis.map(element => {\n\t\t\t\t\t\t\t\t\t\t\telement.tail = false;\n\t\t\t\t\t\t\t\t\t\t\treturn element;\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\tt.templateElement(\n\t\t\t\t\t\t\t\t\t\t\t{raw: ''},\n\t\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t...$left.node.expressions,\n\t\t\t\t\t\t\t\t\t\t$right.node,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ($left.isStringLiteral()) {\n\t\t\t\t\t\tif ($right.isStringLiteral()) {\n\t\t\t\t\t\t\t$left.node.value += $right.node.value;\n\t\t\t\t\t\t\t$.replaceWith($left);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t$right.isCallExpression()\n\t\t\t\t\t\t\t\t&& $right.get('callee').isFunctionExpression()\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$.replaceWith(\n\t\t\t\t\t\t\t\tt.templateLiteral(\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\tt.templateElement(\n\t\t\t\t\t\t\t\t\t\t\t{raw: escape($left.node.value)},\n\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tt.templateElement(\n\t\t\t\t\t\t\t\t\t\t\t{raw: ''},\n\t\t\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t$right.node,\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.changes++;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t},\n} satisfies Transform;\n",
|
|
74
|
-
"import type * as t from '@babel/types';\nimport templateLit from './template-literal';\nimport {applyTransform} from '~ast';\n\n/**\n * Restore common transpiled syntax sugar\n */\nexport default function transform(ast: t.Node) {\n\t/* FIXME: broken for now\n\tapplyTransform(ast, earlyInit);\n\t*/\n\tapplyTransform(ast, templateLit);\n\n\treturn ast;\n}\n\n",
|
|
75
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'logical-assignments',\n tags: ['safe'],\n scope: true,\n visitor() {\n const operator = m.capture(m.or('||' as const, '&&' as const));\n\n const left = m.capture(m.or(m.identifier(), m.memberExpression()));\n const right = m.capture(m.anyExpression());\n // Example: left || (left = right)\n const idMatcher = m.logicalExpression(\n operator,\n left,\n m.assignmentExpression('=', m.fromCapture(left), right),\n );\n\n const object = m.capture(m.anyExpression());\n const property = m.capture(m.anyExpression());\n const tmpVar = m.capture(m.identifier());\n const member = m.capture(\n m.memberExpression(m.fromCapture(tmpVar), m.fromCapture(property)),\n );\n // Example: var _tmp; (_tmp = x.y()).property || (_tmp.property = right);\n const memberMatcher = m.logicalExpression(\n operator,\n m.memberExpression(m.assignmentExpression('=', tmpVar, object), property),\n m.assignmentExpression('=', member, right),\n );\n\n // Example: var _tmp; x[_tmp = y()] || (x[_tmp] = z);\n const computedMemberMatcher = m.logicalExpression(\n operator,\n m.memberExpression(\n object,\n m.assignmentExpression('=', tmpVar, property),\n true,\n ),\n m.assignmentExpression(\n '=',\n m.memberExpression(m.fromCapture(object), m.fromCapture(tmpVar), true),\n right,\n ),\n );\n\n const tmpVar2 = m.capture(m.identifier());\n // Example: var _tmp, _tmp2; (_tmp = x)[_tmp2 = y] || (_tmp[_tmp2] = z);\n const multiComputedMemberMatcher = m.logicalExpression(\n operator,\n m.memberExpression(\n m.assignmentExpression('=', tmpVar, object),\n m.assignmentExpression('=', tmpVar2, property),\n true,\n ),\n m.assignmentExpression(\n '=',\n m.memberExpression(m.fromCapture(tmpVar), m.fromCapture(tmpVar2), true),\n right,\n ),\n );\n\n return {\n LogicalExpression: {\n exit(path) {\n if (idMatcher.match(path.node)) {\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n left.current!,\n right.current!,\n ),\n );\n this.changes++;\n } else if (memberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n member.current!.object = object.current!;\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n member.current!,\n right.current!,\n ),\n );\n this.changes++;\n } else if (computedMemberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n t.memberExpression(object.current!, property.current!, true),\n right.current!,\n ),\n );\n this.changes++;\n } else if (multiComputedMemberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n const binding2 = path.scope.getBinding(tmpVar2.current!.name);\n if (\n !isTemporaryVariable(binding, 1) ||\n !isTemporaryVariable(binding2, 1)\n )\n return;\n\n binding.path.remove();\n binding2.path.remove();\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n t.memberExpression(object.current!, property.current!, true),\n right.current!,\n ),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
76
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'logical-assignments',\n tags: ['safe'],\n scope: true,\n visitor() {\n const operator = m.capture(m.or('||' as const, '&&' as const));\n\n const left = m.capture(m.or(m.identifier(), m.memberExpression()));\n const right = m.capture(m.anyExpression());\n // Example: left || (left = right)\n const idMatcher = m.logicalExpression(\n operator,\n left,\n m.assignmentExpression('=', m.fromCapture(left), right),\n );\n\n const object = m.capture(m.anyExpression());\n const property = m.capture(m.anyExpression());\n const tmpVar = m.capture(m.identifier());\n const member = m.capture(\n m.memberExpression(m.fromCapture(tmpVar), m.fromCapture(property)),\n );\n // Example: var _tmp; (_tmp = x.y()).property || (_tmp.property = right);\n const memberMatcher = m.logicalExpression(\n operator,\n m.memberExpression(m.assignmentExpression('=', tmpVar, object), property),\n m.assignmentExpression('=', member, right),\n );\n\n // Example: var _tmp; x[_tmp = y()] || (x[_tmp] = z);\n const computedMemberMatcher = m.logicalExpression(\n operator,\n m.memberExpression(\n object,\n m.assignmentExpression('=', tmpVar, property),\n true,\n ),\n m.assignmentExpression(\n '=',\n m.memberExpression(m.fromCapture(object), m.fromCapture(tmpVar), true),\n right,\n ),\n );\n\n const tmpVar2 = m.capture(m.identifier());\n // Example: var _tmp, _tmp2; (_tmp = x)[_tmp2 = y] || (_tmp[_tmp2] = z);\n const multiComputedMemberMatcher = m.logicalExpression(\n operator,\n m.memberExpression(\n m.assignmentExpression('=', tmpVar, object),\n m.assignmentExpression('=', tmpVar2, property),\n true,\n ),\n m.assignmentExpression(\n '=',\n m.memberExpression(m.fromCapture(tmpVar), m.fromCapture(tmpVar2), true),\n right,\n ),\n );\n\n return {\n LogicalExpression: {\n exit(path) {\n if (idMatcher.match(path.node)) {\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n left.current!,\n right.current!,\n ),\n );\n this.changes++;\n } else if (memberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n member.current!.object = object.current!;\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n member.current!,\n right.current!,\n ),\n );\n this.changes++;\n } else if (computedMemberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n t.memberExpression(object.current!, property.current!, true),\n right.current!,\n ),\n );\n this.changes++;\n } else if (multiComputedMemberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n const binding2 = path.scope.getBinding(tmpVar2.current!.name);\n if (\n !isTemporaryVariable(binding, 1) ||\n !isTemporaryVariable(binding2, 1)\n )\n return;\n\n binding.path.remove();\n binding2.path.remove();\n path.replaceWith(\n t.assignmentExpression(\n operator.current! + '=',\n t.memberExpression(object.current!, property.current!, true),\n right.current!,\n ),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
77
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'nullish-coalescing',\n tags: ['safe'],\n scope: true,\n visitor() {\n const tmpVar = m.capture(m.identifier());\n const left = m.capture(m.anyExpression());\n const right = m.capture(m.anyExpression());\n // Example (Babel): var _tmp; (_tmp = left) !== null && _tmp !== undefined ? _tmp : right;\n const idMatcher = m.conditionalExpression(\n m.logicalExpression(\n '&&',\n m.binaryExpression(\n '!==',\n m.assignmentExpression('=', tmpVar, left),\n m.nullLiteral(),\n ),\n m.binaryExpression(\n '!==',\n m.fromCapture(tmpVar),\n m.identifier('undefined'),\n ),\n ),\n m.fromCapture(tmpVar),\n right,\n );\n\n const idLooseMatcher = m.conditionalExpression(\n m.binaryExpression(\n '!=',\n m.assignmentExpression('=', tmpVar, left),\n m.nullLiteral(),\n ),\n m.fromCapture(tmpVar),\n right,\n );\n\n // Example (SWC/esbuild): left != null ? left : (left = right);\n // Example (TS): left !== null && left !== undefined ? left : (left = right);\n const simpleIdMatcher = m.conditionalExpression(\n m.or(\n m.logicalExpression(\n '&&',\n m.binaryExpression('!==', left, m.nullLiteral()),\n m.binaryExpression(\n '!==',\n m.fromCapture(left),\n m.identifier('undefined'),\n ),\n ),\n m.binaryExpression('!=', left, m.nullLiteral()),\n ),\n m.fromCapture(left),\n right,\n );\n\n const iifeMatcher = m.callExpression(\n m.arrowFunctionExpression(\n [m.fromCapture(tmpVar)],\n m.anyExpression(),\n false,\n ),\n [],\n );\n\n return {\n ConditionalExpression: {\n exit(path) {\n if (idMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n\n if (\n iifeMatcher.match(path.parentPath.parent) &&\n isTemporaryVariable(binding, 2, 'param')\n ) {\n path.parentPath.parentPath!.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n } else if (isTemporaryVariable(binding, 2, 'var')) {\n binding.path.remove();\n path.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n }\n } else if (idLooseMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n path.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n } else if (simpleIdMatcher.match(path.node)) {\n path.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
78
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'nullish-coalescing',\n tags: ['safe'],\n scope: true,\n visitor() {\n const tmpVar = m.capture(m.identifier());\n const left = m.capture(m.anyExpression());\n const right = m.capture(m.anyExpression());\n // Example (Babel): var _tmp; (_tmp = left) !== null && _tmp !== undefined ? _tmp : right;\n const idMatcher = m.conditionalExpression(\n m.logicalExpression(\n '&&',\n m.binaryExpression(\n '!==',\n m.assignmentExpression('=', tmpVar, left),\n m.nullLiteral(),\n ),\n m.binaryExpression(\n '!==',\n m.fromCapture(tmpVar),\n m.identifier('undefined'),\n ),\n ),\n m.fromCapture(tmpVar),\n right,\n );\n\n const idLooseMatcher = m.conditionalExpression(\n m.binaryExpression(\n '!=',\n m.assignmentExpression('=', tmpVar, left),\n m.nullLiteral(),\n ),\n m.fromCapture(tmpVar),\n right,\n );\n\n // Example (SWC/esbuild): left != null ? left : (left = right);\n // Example (TS): left !== null && left !== undefined ? left : (left = right);\n const simpleIdMatcher = m.conditionalExpression(\n m.or(\n m.logicalExpression(\n '&&',\n m.binaryExpression('!==', left, m.nullLiteral()),\n m.binaryExpression(\n '!==',\n m.fromCapture(left),\n m.identifier('undefined'),\n ),\n ),\n m.binaryExpression('!=', left, m.nullLiteral()),\n ),\n m.fromCapture(left),\n right,\n );\n\n const iifeMatcher = m.callExpression(\n m.arrowFunctionExpression(\n [m.fromCapture(tmpVar)],\n m.anyExpression(),\n false,\n ),\n [],\n );\n\n return {\n ConditionalExpression: {\n exit(path) {\n if (idMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n\n if (\n iifeMatcher.match(path.parentPath.parent) &&\n isTemporaryVariable(binding, 2, 'param')\n ) {\n path.parentPath.parentPath!.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n } else if (isTemporaryVariable(binding, 2, 'var')) {\n binding.path.remove();\n path.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n }\n } else if (idLooseMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n path.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n } else if (simpleIdMatcher.match(path.node)) {\n path.replaceWith(\n t.logicalExpression('??', left.current!, right.current!),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
79
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'nullish-coalescing-assignment',\n tags: ['safe'],\n scope: true,\n visitor() {\n const tmpVar = m.capture(m.identifier());\n const leftId = m.capture(m.identifier());\n const property = m.capture(m.identifier());\n const right = m.capture(m.anyExpression());\n const computed = m.capture<boolean>(m.anything());\n // Example (Babel): var tmp; (tmp = left).b ?? (tmp.b = c);\n const memberMatcher = m.logicalExpression(\n '??',\n m.memberExpression(\n m.assignmentExpression('=', tmpVar, leftId),\n property,\n computed,\n ),\n m.assignmentExpression(\n '=',\n m.memberExpression(\n m.fromCapture(tmpVar),\n m.fromCapture(property),\n computed,\n ),\n right,\n ),\n );\n\n // Example (Babel): left ?? (left = right);\n const left = m.capture(m.or(m.identifier(), m.memberExpression()));\n const simpleMatcher = m.logicalExpression(\n '??',\n left,\n m.assignmentExpression('=', m.fromCapture(left), right),\n );\n\n return {\n LogicalExpression: {\n exit(path) {\n if (memberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n path.replaceWith(\n t.assignmentExpression(\n '??=',\n t.memberExpression(\n leftId.current!,\n property.current!,\n computed.current,\n ),\n right.current!,\n ),\n );\n this.changes++;\n } else if (simpleMatcher.match(path.node)) {\n path.replaceWith(\n t.assignmentExpression('??=', left.current!, right.current!),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
80
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'nullish-coalescing-assignment',\n tags: ['safe'],\n scope: true,\n visitor() {\n const tmpVar = m.capture(m.identifier());\n const leftId = m.capture(m.identifier());\n const property = m.capture(m.identifier());\n const right = m.capture(m.anyExpression());\n const computed = m.capture<boolean>(m.anything());\n // Example (Babel): var tmp; (tmp = left).b ?? (tmp.b = c);\n const memberMatcher = m.logicalExpression(\n '??',\n m.memberExpression(\n m.assignmentExpression('=', tmpVar, leftId),\n property,\n computed,\n ),\n m.assignmentExpression(\n '=',\n m.memberExpression(\n m.fromCapture(tmpVar),\n m.fromCapture(property),\n computed,\n ),\n right,\n ),\n );\n\n // Example (Babel): left ?? (left = right);\n const left = m.capture(m.or(m.identifier(), m.memberExpression()));\n const simpleMatcher = m.logicalExpression(\n '??',\n left,\n m.assignmentExpression('=', m.fromCapture(left), right),\n );\n\n return {\n LogicalExpression: {\n exit(path) {\n if (memberMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 1)) return;\n\n binding.path.remove();\n path.replaceWith(\n t.assignmentExpression(\n '??=',\n t.memberExpression(\n leftId.current!,\n property.current!,\n computed.current,\n ),\n right.current!,\n ),\n );\n this.changes++;\n } else if (simpleMatcher.match(path.node)) {\n path.replaceWith(\n t.assignmentExpression('??=', left.current!, right.current!),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
81
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'optional-chaining',\n tags: ['safe'],\n scope: true,\n visitor() {\n const object = m.capture(m.anyExpression());\n const member = m.capture(m.memberExpression(m.fromCapture(object)));\n // Example (TS): object === null || object === undefined ? undefined : object.property;\n const simpleMatcher = m.conditionalExpression(\n m.logicalExpression(\n '||',\n m.binaryExpression('===', object, m.nullLiteral()),\n m.binaryExpression(\n '===',\n m.fromCapture(object),\n m.identifier('undefined'),\n ),\n ),\n m.identifier('undefined'),\n member,\n );\n\n const tmpVar = m.capture(m.identifier());\n const tmpMember = m.capture(m.memberExpression(m.fromCapture(tmpVar)));\n // Example (Babel): var _tmp; (_tmp = object) === null || _tmp === undefined ? undefined : _tmp.property;\n const tmpMatcher = m.conditionalExpression(\n m.logicalExpression(\n '||',\n m.binaryExpression(\n '===',\n m.assignmentExpression('=', tmpVar, object),\n m.nullLiteral(),\n ),\n m.binaryExpression(\n '===',\n m.fromCapture(tmpVar),\n m.identifier('undefined'),\n ),\n ),\n m.identifier('undefined'),\n tmpMember,\n );\n\n return {\n ConditionalExpression: {\n exit(path) {\n if (simpleMatcher.match(path.node)) {\n member.current!.optional = true;\n path.replaceWith(\n t.optionalMemberExpression(\n object.current!,\n member.current!.property as t.Expression,\n member.current!.computed,\n true,\n ),\n );\n this.changes++;\n } else if (tmpMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 2)) return;\n\n binding.path.remove();\n tmpMember.current!.optional = true;\n path.replaceWith(\n t.optionalMemberExpression(\n object.current!,\n tmpMember.current!.property as t.Expression,\n tmpMember.current!.computed,\n true,\n ),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
82
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, isTemporaryVariable } from '../../ast-utils';\n\nexport default {\n name: 'optional-chaining',\n tags: ['safe'],\n scope: true,\n visitor() {\n const object = m.capture(m.anyExpression());\n const member = m.capture(m.memberExpression(m.fromCapture(object)));\n // Example (TS): object === null || object === undefined ? undefined : object.property;\n const simpleMatcher = m.conditionalExpression(\n m.logicalExpression(\n '||',\n m.binaryExpression('===', object, m.nullLiteral()),\n m.binaryExpression(\n '===',\n m.fromCapture(object),\n m.identifier('undefined'),\n ),\n ),\n m.identifier('undefined'),\n member,\n );\n\n const tmpVar = m.capture(m.identifier());\n const tmpMember = m.capture(m.memberExpression(m.fromCapture(tmpVar)));\n // Example (Babel): var _tmp; (_tmp = object) === null || _tmp === undefined ? undefined : _tmp.property;\n const tmpMatcher = m.conditionalExpression(\n m.logicalExpression(\n '||',\n m.binaryExpression(\n '===',\n m.assignmentExpression('=', tmpVar, object),\n m.nullLiteral(),\n ),\n m.binaryExpression(\n '===',\n m.fromCapture(tmpVar),\n m.identifier('undefined'),\n ),\n ),\n m.identifier('undefined'),\n tmpMember,\n );\n\n return {\n ConditionalExpression: {\n exit(path) {\n if (simpleMatcher.match(path.node)) {\n member.current!.optional = true;\n path.replaceWith(\n t.optionalMemberExpression(\n object.current!,\n member.current!.property as t.Expression,\n member.current!.computed,\n true,\n ),\n );\n this.changes++;\n } else if (tmpMatcher.match(path.node)) {\n const binding = path.scope.getBinding(tmpVar.current!.name);\n if (!isTemporaryVariable(binding, 2)) return;\n\n binding.path.remove();\n tmpMember.current!.optional = true;\n path.replaceWith(\n t.optionalMemberExpression(\n object.current!,\n tmpMember.current!.property as t.Expression,\n tmpMember.current!.computed,\n true,\n ),\n );\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
83
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, constMemberExpression } from '../../ast-utils';\n\n// https://github.com/babel/babel/pull/5791\n// https://github.com/babel/babel/blob/cce807f1eb638ee3030112dc190cbee032760888/packages/babel-plugin-transform-template-literals/src/index.ts\n\n// TODO: option ignoreToPrimitiveHint (uses `+` instead of concat)\n\nfunction escape(str: string) {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/`/g, '\\\\`')\n .replace(/\\$/g, '\\\\$')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\r/g, '\\\\r');\n}\n\nfunction push(template: t.TemplateLiteral, value: t.Expression) {\n if (value.type === 'StringLiteral') {\n const lastQuasi = template.quasis.at(-1)!;\n lastQuasi.value.raw += escape(value.value);\n } else if (value.type === 'TemplateLiteral') {\n const lastQuasi = template.quasis.at(-1)!;\n const firstQuasi = value.quasis[0];\n lastQuasi.value.raw += firstQuasi.value.raw;\n template.expressions.push(...value.expressions);\n template.quasis.push(...value.quasis.slice(1));\n } else {\n template.expressions.push(value);\n template.quasis.push(t.templateElement({ raw: '' }));\n }\n}\n\nfunction unshift(template: t.TemplateLiteral, value: t.Expression) {\n if (value.type === 'StringLiteral') {\n const firstQuasi = template.quasis[0];\n firstQuasi.value.raw = escape(value.value) + firstQuasi.value.raw;\n } else if (value.type === 'TemplateLiteral') {\n const firstQuasi = template.quasis[0];\n firstQuasi.value.raw = value.quasis[0].value.raw + firstQuasi.value.raw;\n template.expressions.unshift(...value.expressions);\n template.quasis.unshift(...value.quasis.slice(0, -1));\n } else {\n template.expressions.unshift(value);\n template.quasis.unshift(t.templateElement({ raw: '' }));\n }\n}\n\nexport default {\n name: 'template-literals',\n tags: ['unsafe'],\n visitor() {\n const concatMatcher: m.Matcher<t.CallExpression> = m.or(\n m.callExpression(\n constMemberExpression(\n m.or(\n m.stringLiteral(),\n m.matcher((node) => concatMatcher.match(node)),\n ),\n 'concat',\n ),\n m.arrayOf(m.anyExpression()),\n ),\n );\n\n return {\n BinaryExpression: {\n exit(path) {\n if (path.node.operator !== '+') return;\n\n if (t.isTemplateLiteral(path.node.left)) {\n push(path.node.left, path.node.right);\n path.replaceWith(path.node.left);\n this.changes++;\n } else if (\n t.isTemplateLiteral(path.node.right) &&\n t.isExpression(path.node.left)\n ) {\n unshift(path.node.right, path.node.left);\n path.replaceWith(path.node.right);\n this.changes++;\n }\n },\n },\n CallExpression: {\n exit(path) {\n if (\n concatMatcher.match(path.node) &&\n !concatMatcher.match(path.parentPath.parent)\n ) {\n const template = t.templateLiteral(\n [t.templateElement({ raw: '' })],\n [],\n );\n let current: t.Expression = path.node;\n while (current.type === 'CallExpression') {\n for (const arg of current.arguments.reverse()) {\n unshift(template, arg as t.Expression);\n }\n current = (current.callee as t.MemberExpression).object;\n }\n unshift(template, current);\n path.replaceWith(template);\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
84
|
-
"import * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport { Transform, constMemberExpression } from '../../ast-utils';\n\n// https://github.com/babel/babel/pull/5791\n// https://github.com/babel/babel/blob/cce807f1eb638ee3030112dc190cbee032760888/packages/babel-plugin-transform-template-literals/src/index.ts\n\n// TODO: option ignoreToPrimitiveHint (uses `+` instead of concat)\n\nfunction escape(str: string) {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/`/g, '\\\\`')\n .replace(/\\$/g, '\\\\$')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\r/g, '\\\\r');\n}\n\nfunction push(template: t.TemplateLiteral, value: t.Expression) {\n if (value.type === 'StringLiteral') {\n const lastQuasi = template.quasis.at(-1)!;\n lastQuasi.value.raw += escape(value.value);\n } else if (value.type === 'TemplateLiteral') {\n const lastQuasi = template.quasis.at(-1)!;\n const firstQuasi = value.quasis[0];\n lastQuasi.value.raw += firstQuasi.value.raw;\n template.expressions.push(...value.expressions);\n template.quasis.push(...value.quasis.slice(1));\n } else {\n template.expressions.push(value);\n template.quasis.push(t.templateElement({ raw: '' }));\n }\n}\n\nfunction unshift(template: t.TemplateLiteral, value: t.Expression) {\n if (value.type === 'StringLiteral') {\n const firstQuasi = template.quasis[0];\n firstQuasi.value.raw = escape(value.value) + firstQuasi.value.raw;\n } else if (value.type === 'TemplateLiteral') {\n const firstQuasi = template.quasis[0];\n firstQuasi.value.raw = value.quasis[0].value.raw + firstQuasi.value.raw;\n template.expressions.unshift(...value.expressions);\n template.quasis.unshift(...value.quasis.slice(0, -1));\n } else {\n template.expressions.unshift(value);\n template.quasis.unshift(t.templateElement({ raw: '' }));\n }\n}\n\nexport default {\n name: 'template-literals',\n tags: ['unsafe'],\n visitor() {\n const concatMatcher: m.Matcher<t.CallExpression> = m.or(\n m.callExpression(\n constMemberExpression(\n m.or(\n m.stringLiteral(),\n m.matcher((node) => concatMatcher.match(node)),\n ),\n 'concat',\n ),\n m.arrayOf(m.anyExpression()),\n ),\n );\n\n return {\n BinaryExpression: {\n exit(path) {\n if (path.node.operator !== '+') return;\n\n if (t.isTemplateLiteral(path.node.left)) {\n push(path.node.left, path.node.right);\n path.replaceWith(path.node.left);\n this.changes++;\n } else if (\n t.isTemplateLiteral(path.node.right) &&\n t.isExpression(path.node.left)\n ) {\n unshift(path.node.right, path.node.left);\n path.replaceWith(path.node.right);\n this.changes++;\n }\n },\n },\n CallExpression: {\n exit(path) {\n if (\n concatMatcher.match(path.node) &&\n !concatMatcher.match(path.parentPath.parent)\n ) {\n const template = t.templateLiteral(\n [t.templateElement({ raw: '' })],\n [],\n );\n let current: t.Expression = path.node;\n while (current.type === 'CallExpression') {\n for (const arg of current.arguments.reverse()) {\n unshift(template, arg as t.Expression);\n }\n current = (current.callee as t.MemberExpression).object;\n }\n unshift(template, current);\n path.replaceWith(template);\n this.changes++;\n }\n },\n },\n };\n },\n} satisfies Transform;\n",
|
|
85
|
-
"import { mergeTransforms } from '../ast-utils';\nimport * as transforms from './transforms';\n\nexport default mergeTransforms({\n name: 'transpile',\n tags: ['safe'],\n transforms: Object.values(transforms),\n});\n",
|
|
86
|
-
"import type {NodePath, TraverseOptions} from '@babel/traverse';\nimport type {Transform, TransformState} from 'webcrack/ast-utils';\nimport traverse from '@babel/traverse';\nimport * as m from '@codemod/matchers';\nimport * as t from '@babel/types';\nimport {decrypt, lic, salt} from '~crypto';\n\n/** Find call to `scryptSync`. */\nconst scrypt = m.callExpression(\n\tm.memberExpression(\n\t\tm.identifier(),\n\t\tm.identifier('scryptSync'),\n\t\tfalse,\n\t),\n\t[\n\t\t// Password\n\t\tm.memberExpression(\n\t\t\tm.identifier(),\n\t\t\tm.identifier('licenseErrorText'),\n\t\t\tfalse,\n\t\t),\n\t\t// Salt\n\t\tm.identifier(),\n\t\tm.numericLiteral(24),\n\t],\n);\n\n/** Find `exports.licenseErrorText`. */\nconst licenseText = m.assignmentExpression(\n\t'=',\n\tm.memberExpression(\n\t\tm.identifier(),\n\t\tm.identifier('licenseErrorText'),\n\t),\n\tm.callExpression(\n\t\tm.memberExpression(\n\t\t\tm.arrayExpression(\n\t\t\t\tm.anyList(m.oneOrMore(m.stringLiteral())),\n\t\t\t),\n\t\t\tm.identifier('join'),\n\t\t\tfalse,\n\t\t),\n\t\t[m.stringLiteral(' ')],\n\t),\n);\n\nlet newSalt: string;\nlet newKey: string;\n/** Decrypt AES encrypted string constants. */\nexport default {\n\tname: 'string-aes',\n\ttags: ['safe'],\n\trun(ast) {\n\t\ttraverse(ast, {\n\t\t\tCallExpression: {\n\t\t\t\texit($) {\n\t\t\t\t\tif (newSalt || !scrypt.match($.node)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $id: NodePath = $.get('arguments.1') as NodePath;\n\t\t\t\t\t$id.assertIdentifier();\n\n\t\t\t\t\tconst _decl = $.scope.getBinding($id.node.name)?.path;\n\t\t\t\t\tif (!_decl) {\n\t\t\t\t\t\tthrow new Error('Could not find declaration');\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $decl: NodePath = _decl;\n\t\t\t\t\t$decl.assertVariableDeclarator();\n\n\t\t\t\t\tconst $salt = $decl.get('init');\n\t\t\t\t\tif (!$salt.isStringLiteral()) {\n\t\t\t\t\t\tthrow new Error('Salt not initialized');\n\t\t\t\t\t}\n\n\t\t\t\t\tnewSalt = $salt.node.value;\n\t\t\t\t},\n\t\t\t},\n\t\t\tAssignmentExpression: {\n\t\t\t\texit($) {\n\t\t\t\t\tif (newKey || !licenseText.match($.node)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $strs = $.get('right.callee.object.elements') as NodePath[];\n\t\t\t\t\tnewKey = $strs.map(($_: NodePath) => {\n\t\t\t\t\t\t$_.assertStringLiteral();\n\t\t\t\t\t\treturn $_.node.value;\n\t\t\t\t\t}).join(' ');\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\tif (newSalt && newKey) {\n\t\t\tsalt(newSalt);\n\t\t\tlic(newKey);\n\t\t}\n\t},\n\tvisitor(): TraverseOptions<TransformState> {\n\t\tconst encryptedString = m.callExpression(\n\t\t\tm.memberExpression(\n\t\t\t\tm.identifier(),\n\t\t\t\tm.identifier('decrypt'),\n\t\t\t\tfalse,\n\t\t\t),\n\t\t\t[m.stringLiteral()],\n\t\t);\n\n\t\treturn {\n\t\t\tCallExpression: {\n\t\t\t\texit($) {\n\t\t\t\t\tif (!encryptedString.match($.node)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $callee: NodePath = $.get('callee');\n\t\t\t\t\t$callee.assertMemberExpression();\n\n\t\t\t\t\tconst $id: NodePath = $callee.get('object');\n\t\t\t\t\t$id.assertIdentifier();\n\n\t\t\t\t\tconst $string: NodePath = $.get('arguments')[0];\n\t\t\t\t\t$string.assertStringLiteral();\n\n\t\t\t\t\t$.replaceWith(\n\t\t\t\t\t\tt.stringLiteral(\n\t\t\t\t\t\t\tdecrypt($string.node.value),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tthis.changes++;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t},\n} satisfies Transform;\n",
|
|
87
|
-
"import crypto from 'node:crypto';\nimport {Buffer} from 'node:buffer';\n\n/* 🥺 don't sue me\n ⠁⠒⠲⠤⠤⠀⢀⣀⣀⡀⠀⠀⠀⠀pwease…⠀⠀⢀⡠⠔⠈\n ⠀⠀⠀⠀⠀⣀⣠⣤⢤⣉⣛⣿⣿⣿⣿⣾⣧⣻⣻⠛⣁⣀⣦⠥⣀⡀\n ⠀⢀⣤⢶⣫⣵⣾⣶⣾⣭⣿⣿⣿⣿⣿⣿⢿⣿⣵⣿⣿⣿⣿⣿⣷⣮⣷\n ⡴⢟⣵⣿⣿⣿⣿⣿⢿⣍⣘⢿⣿⣿⣿⢫⣕⢮⡿⣿⣿⣿⣿⣿⣿⣿⢿\n ⣏⠻⢿⣿⣿⣿⣿⢇⣿⣿⣿⡾⣿⣿⣿⢿⣿⢸⣿⣸⣿⢻⡉⡉⠓⠛⠉\n ⠙⠳⢮⣭⣿⠟⣿⢸⣿⣏⠿⣣⡿⠿⣿⣜⣋⣾⣿⢛⢿⡟⣵⠁\n ⠀⠀⠀⠸⣦⡟⣿⣳⣻⣿⣿⣿⣿⠿⣿⢿⣿⣿⣿⣷⣿⠷⡛\n ⠀⠀⠀⠀⠻⣧⣭⣿⠽⠛⠿⠿⢾⣾⣿⡟⠛⠛⠉⠚⠉⢩⠁\n ⠀⠀⠀⠀⠀⠀⠀⠸⣦⠀⡐⠀⠺⠿⠿⠃⢀⠂⠄⠀⠁⠓⡄\n ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⡆👉⠀⠀👈⣰⣽⠐⠚⠁⠀ */\nlet _salt = 'SEE\\u0020\\u0020LICENSE.txt';\nlet _lic = [ // The \"etilqs\" trick\n\t',oidutS lausiV tfosorciM htiw ylno erawtfos eht fo seipoc fo rebmun yna esu dna llatsni yam uoY',\n\t'stcudorp tfosorciM rosseccus dna ,revreS noitadnuoF maeT ,spOveD eruzA ,edoC oidutS lausiV ,caM rof oidutS lausiV',\n\t'.snoitacilppa ruoy tset dna poleved ot )”secivreS dna stcudorP oidutS lausiV“ eht ,ylevitcelloc( secivres dna',\n\t'.sthgir rehto lla sevreser tfosorciM .erawtfos eht esu ot sthgir emos uoy sevig ylno tnemeerga sihT .dlos ton ,desnecil si erawtfos ehT',\n\t':ton yam uoY',\n\t';syaw niatrec ni ti esu ot uoy wolla ylno taht erawtfos eht ni snoitatimil lacinhcet yna dnuora krow',\n\t',erawtfos eht rof edoc ecruos eht evired ot tpmetta esiwrehto ro ,erawtfos eht elbmessasid ro elipmoced ,reenigne esrever',\n\t';erawtfos eht ni dedulcni eb yam taht stnenopmoc ecruos nepo niatrec fo esu gninrevog smret gnisnecil ytrap driht yb deriuqer tnetxe eht ot dna tpecxe',\n\t';erawtfos eht ni sreilppus sti ro tfosorciM fo seciton yna yfidom ro ,kcolb ,eziminim ,evomer',\n\t'ro ;erawlam etagaporp ro etaerc ot ro wal eht tsniaga si taht yaw yna ni erawtfos eht esu',\n\t',)evoba smret eht ot tcejbus ,edoc elbatubirtsid yna rof tpecxe( erawtfos eht esael ro ,etubirtsid ,hsilbup ,erahs',\n\t'.ytrap driht yna ot tnemeerga siht ro erawtfos eht refsnart ro ,esu ot srehto rof gnireffo enola-dnats a sa erawtfos eht edivorp',\n]\n\t.map(x => [...x].reverse().join(''))\n\t.join(' ');\n\nexport function salt(x = _salt) {\n\t_salt = x;\n\treturn _salt;\n}\n\nexport function lic(x = _lic) {\n\t_lic = x;\n\treturn _lic;\n}\n\nconst scrypt = () => crypto.scryptSync(lic(), salt(), 24);\nconst iv = () => Buffer.from(salt());\n\nexport function decrypt(m: string) {\n\tconst c = crypto.createDecipheriv('aes-192-cbc', scrypt(), iv());\n\tlet a = c.update(m, 'hex', 'utf8');\n\ta += c.final('utf8');\n\treturn a;\n}\n\nexport function encrypt(m: string) {\n\tconst c = crypto.createCipheriv('aes-192-cbc', scrypt(), iv());\n\tlet a = c.update(m, 'utf8', 'hex');\n\ta += c.final('hex');\n\treturn a;\n}\n",
|
|
88
|
-
"import crypto from 'node:crypto';\nimport {Buffer} from 'node:buffer';\n\n/* 🥺 don't sue me\n ⠁⠒⠲⠤⠤⠀⢀⣀⣀⡀⠀⠀⠀⠀pwease…⠀⠀⢀⡠⠔⠈\n ⠀⠀⠀⠀⠀⣀⣠⣤⢤⣉⣛⣿⣿⣿⣿⣾⣧⣻⣻⠛⣁⣀⣦⠥⣀⡀\n ⠀⢀⣤⢶⣫⣵⣾⣶⣾⣭⣿⣿⣿⣿⣿⣿⢿⣿⣵⣿⣿⣿⣿⣿⣷⣮⣷\n ⡴⢟⣵⣿⣿⣿⣿⣿⢿⣍⣘⢿⣿⣿⣿⢫⣕⢮⡿⣿⣿⣿⣿⣿⣿⣿⢿\n ⣏⠻⢿⣿⣿⣿⣿⢇⣿⣿⣿⡾⣿⣿⣿⢿⣿⢸⣿⣸⣿⢻⡉⡉⠓⠛⠉\n ⠙⠳⢮⣭⣿⠟⣿⢸⣿⣏⠿⣣⡿⠿⣿⣜⣋⣾⣿⢛⢿⡟⣵⠁\n ⠀⠀⠀⠸⣦⡟⣿⣳⣻⣿⣿⣿⣿⠿⣿⢿⣿⣿⣿⣷⣿⠷⡛\n ⠀⠀⠀⠀⠻⣧⣭⣿⠽⠛⠿⠿⢾⣾⣿⡟⠛⠛⠉⠚⠉⢩⠁\n ⠀⠀⠀⠀⠀⠀⠀⠸⣦⠀⡐⠀⠺⠿⠿⠃⢀⠂⠄⠀⠁⠓⡄\n ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⡆👉⠀⠀👈⣰⣽⠐⠚⠁⠀ */\nlet _salt = 'SEE\\u0020\\u0020LICENSE.txt';\nlet _lic = [ // The \"etilqs\" trick\n\t',oidutS lausiV tfosorciM htiw ylno erawtfos eht fo seipoc fo rebmun yna esu dna llatsni yam uoY',\n\t'stcudorp tfosorciM rosseccus dna ,revreS noitadnuoF maeT ,spOveD eruzA ,edoC oidutS lausiV ,caM rof oidutS lausiV',\n\t'.snoitacilppa ruoy tset dna poleved ot )”secivreS dna stcudorP oidutS lausiV“ eht ,ylevitcelloc( secivres dna',\n\t'.sthgir rehto lla sevreser tfosorciM .erawtfos eht esu ot sthgir emos uoy sevig ylno tnemeerga sihT .dlos ton ,desnecil si erawtfos ehT',\n\t':ton yam uoY',\n\t';syaw niatrec ni ti esu ot uoy wolla ylno taht erawtfos eht ni snoitatimil lacinhcet yna dnuora krow',\n\t',erawtfos eht rof edoc ecruos eht evired ot tpmetta esiwrehto ro ,erawtfos eht elbmessasid ro elipmoced ,reenigne esrever',\n\t';erawtfos eht ni dedulcni eb yam taht stnenopmoc ecruos nepo niatrec fo esu gninrevog smret gnisnecil ytrap driht yb deriuqer tnetxe eht ot dna tpecxe',\n\t';erawtfos eht ni sreilppus sti ro tfosorciM fo seciton yna yfidom ro ,kcolb ,eziminim ,evomer',\n\t'ro ;erawlam etagaporp ro etaerc ot ro wal eht tsniaga si taht yaw yna ni erawtfos eht esu',\n\t',)evoba smret eht ot tcejbus ,edoc elbatubirtsid yna rof tpecxe( erawtfos eht esael ro ,etubirtsid ,hsilbup ,erahs',\n\t'.ytrap driht yna ot tnemeerga siht ro erawtfos eht refsnart ro ,esu ot srehto rof gnireffo enola-dnats a sa erawtfos eht edivorp',\n]\n\t.map(x => [...x].reverse().join(''))\n\t.join(' ');\n\nexport function salt(x = _salt) {\n\t_salt = x;\n\treturn _salt;\n}\n\nexport function lic(x = _lic) {\n\t_lic = x;\n\treturn _lic;\n}\n\nconst scrypt = () => crypto.scryptSync(lic(), salt(), 24);\nconst iv = () => Buffer.from(salt());\n\nexport function decrypt(m: string) {\n\tconst c = crypto.createDecipheriv('aes-192-cbc', scrypt(), iv());\n\tlet a = c.update(m, 'hex', 'utf8');\n\ta += c.final('utf8');\n\treturn a;\n}\n\nexport function encrypt(m: string) {\n\tconst c = crypto.createCipheriv('aes-192-cbc', scrypt(), iv());\n\tlet a = c.update(m, 'utf8', 'hex');\n\ta += c.final('hex');\n\treturn a;\n}\n",
|
|
89
|
-
"import type {NodePath, TraverseOptions} from '@babel/traverse';\nimport type {Transform, TransformState} from 'webcrack/ast-utils';\nimport traverse from '@babel/traverse';\nimport * as m from '@codemod/matchers';\nimport * as t from '@babel/types';\nimport {decrypt, lic, salt} from '~crypto';\n\n/** Find call to `scryptSync`. */\nconst scrypt = m.callExpression(\n\tm.memberExpression(\n\t\tm.identifier(),\n\t\tm.identifier('scryptSync'),\n\t\tfalse,\n\t),\n\t[\n\t\t// Password\n\t\tm.memberExpression(\n\t\t\tm.identifier(),\n\t\t\tm.identifier('licenseErrorText'),\n\t\t\tfalse,\n\t\t),\n\t\t// Salt\n\t\tm.identifier(),\n\t\tm.numericLiteral(24),\n\t],\n);\n\n/** Find `exports.licenseErrorText`. */\nconst licenseText = m.assignmentExpression(\n\t'=',\n\tm.memberExpression(\n\t\tm.identifier(),\n\t\tm.identifier('licenseErrorText'),\n\t),\n\tm.callExpression(\n\t\tm.memberExpression(\n\t\t\tm.arrayExpression(\n\t\t\t\tm.anyList(m.oneOrMore(m.stringLiteral())),\n\t\t\t),\n\t\t\tm.identifier('join'),\n\t\t\tfalse,\n\t\t),\n\t\t[m.stringLiteral(' ')],\n\t),\n);\n\nlet newSalt: string;\nlet newKey: string;\n/** Decrypt AES encrypted string constants. */\nexport default {\n\tname: 'string-aes',\n\ttags: ['safe'],\n\trun(ast) {\n\t\ttraverse(ast, {\n\t\t\tCallExpression: {\n\t\t\t\texit($) {\n\t\t\t\t\tif (newSalt || !scrypt.match($.node)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $id: NodePath = $.get('arguments.1') as NodePath;\n\t\t\t\t\t$id.assertIdentifier();\n\n\t\t\t\t\tconst _decl = $.scope.getBinding($id.node.name)?.path;\n\t\t\t\t\tif (!_decl) {\n\t\t\t\t\t\tthrow new Error('Could not find declaration');\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $decl: NodePath = _decl;\n\t\t\t\t\t$decl.assertVariableDeclarator();\n\n\t\t\t\t\tconst $salt = $decl.get('init');\n\t\t\t\t\tif (!$salt.isStringLiteral()) {\n\t\t\t\t\t\tthrow new Error('Salt not initialized');\n\t\t\t\t\t}\n\n\t\t\t\t\tnewSalt = $salt.node.value;\n\t\t\t\t},\n\t\t\t},\n\t\t\tAssignmentExpression: {\n\t\t\t\texit($) {\n\t\t\t\t\tif (newKey || !licenseText.match($.node)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $strs = $.get('right.callee.object.elements') as NodePath[];\n\t\t\t\t\tnewKey = $strs.map(($_: NodePath) => {\n\t\t\t\t\t\t$_.assertStringLiteral();\n\t\t\t\t\t\treturn $_.node.value;\n\t\t\t\t\t}).join(' ');\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\tif (newSalt && newKey) {\n\t\t\tsalt(newSalt);\n\t\t\tlic(newKey);\n\t\t}\n\t},\n\tvisitor(): TraverseOptions<TransformState> {\n\t\tconst encryptedString = m.callExpression(\n\t\t\tm.memberExpression(\n\t\t\t\tm.identifier(),\n\t\t\t\tm.identifier('decrypt'),\n\t\t\t\tfalse,\n\t\t\t),\n\t\t\t[m.stringLiteral()],\n\t\t);\n\n\t\treturn {\n\t\t\tCallExpression: {\n\t\t\t\texit($) {\n\t\t\t\t\tif (!encryptedString.match($.node)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst $callee: NodePath = $.get('callee');\n\t\t\t\t\t$callee.assertMemberExpression();\n\n\t\t\t\t\tconst $id: NodePath = $callee.get('object');\n\t\t\t\t\t$id.assertIdentifier();\n\n\t\t\t\t\tconst $string: NodePath = $.get('arguments')[0];\n\t\t\t\t\t$string.assertStringLiteral();\n\n\t\t\t\t\t$.replaceWith(\n\t\t\t\t\t\tt.stringLiteral(\n\t\t\t\t\t\t\tdecrypt($string.node.value),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tthis.changes++;\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t},\n} satisfies Transform;\n",
|
|
90
|
-
"import type {NodePath} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport tmpl from '@babel/template';\nimport type {Transform} from 'webcrack/ast-utils';\nimport chunk from '~matchers/chunk';\n\nconst entry = m.capture(m.numericLiteral());\nconst main = m.callExpression(\n\tm.memberExpression(\n\t\tm.callExpression(\n\t\t\tm.identifier('require'),\n\t\t\t[entry],\n\t\t),\n\t\tm.identifier('main'),\n\t\tfalse,\n\t),\n\t[m.booleanLiteral(true)],\n);\nconst verifyClient = m.assignmentExpression(\n\t'=',\n\tm.memberExpression(\n\t\tm.identifier('exports'),\n\t\tm.identifier('verifyClient'),\n\t),\n\tm.functionExpression(\n\t\tnull,\n\t\t[m.identifier()],\n\t),\n);\nconst vsda = m.ifStatement(\n\tm.containerOf(\n\t\tm.stringLiteral('vsda'),\n\t),\n);\n\n// TODO: remove telemetry\n// See `vendor.bundle.js` & npm.im/applicationinsights\n/** Remove unwanted features e.g. License check and Telemetry */\nexport default {\n\tname: 'anti-feature',\n\ttags: ['unsafe'],\n\tvisitor: () => ({\n\t\tCallExpression: {\n\t\t\texit($) {\n\t\t\t\tif (!main.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tt.assertNumericLiteral(entry.current);\n\n\t\t\t\tconst _target = $.find(p => chunk.match(p.node));\n\t\t\t\tif (!_target) {\n\t\t\t\t\tthrow new Error('Could not find module chunk');\n\t\t\t\t}\n\n\t\t\t\tconst $target: NodePath = _target;\n\t\t\t\t$target.assertObjectProperty();\n\n\t\t\t\tconst $value: NodePath = $target.get('value');\n\t\t\t\t$value.assertFunction();\n\n\t\t\t\t$value.get('body').replaceWith(\n\t\t\t\t\ttmpl.statement.ast`{\n\t\t\t\t\t\trequire(${entry.current}).main(false);\n\t\t\t\t\t}`,\n\t\t\t\t);\n\n\t\t\t\t$.stop();\n\t\t\t\tthis.changes++;\n\t\t\t},\n\t\t},\n\t\tAssignmentExpression: {\n\t\t\texit($) {\n\t\t\t\tif (!verifyClient.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst $value: NodePath = $.get('right');\n\t\t\t\t$value.assertFunction();\n\n\t\t\t\t$value.get('body').replaceWith(\n\t\t\t\t\ttmpl.statement.ast`{\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}`,\n\t\t\t\t);\n\t\t\t\tthis.changes++;\n\t\t\t},\n\t\t},\n\t\tIfStatement: {\n\t\t\texit($) {\n\t\t\t\tif (!vsda.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t$.remove();\n\t\t\t\tthis.changes++;\n\t\t\t},\n\t\t},\n\t}),\n} satisfies Transform;\n",
|
|
91
|
-
"import type {NodePath} from '@babel/traverse';\nimport * as t from '@babel/types';\nimport * as m from '@codemod/matchers';\nimport tmpl from '@babel/template';\nimport type {Transform} from 'webcrack/ast-utils';\nimport chunk from '~matchers/chunk';\n\nconst entry = m.capture(m.numericLiteral());\nconst main = m.callExpression(\n\tm.memberExpression(\n\t\tm.callExpression(\n\t\t\tm.identifier('require'),\n\t\t\t[entry],\n\t\t),\n\t\tm.identifier('main'),\n\t\tfalse,\n\t),\n\t[m.booleanLiteral(true)],\n);\nconst verifyClient = m.assignmentExpression(\n\t'=',\n\tm.memberExpression(\n\t\tm.identifier('exports'),\n\t\tm.identifier('verifyClient'),\n\t),\n\tm.functionExpression(\n\t\tnull,\n\t\t[m.identifier()],\n\t),\n);\nconst vsda = m.ifStatement(\n\tm.containerOf(\n\t\tm.stringLiteral('vsda'),\n\t),\n);\n\n// TODO: remove telemetry\n// See `vendor.bundle.js` & npm.im/applicationinsights\n/** Remove unwanted features e.g. License check and Telemetry */\nexport default {\n\tname: 'anti-feature',\n\ttags: ['unsafe'],\n\tvisitor: () => ({\n\t\tCallExpression: {\n\t\t\texit($) {\n\t\t\t\tif (!main.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tt.assertNumericLiteral(entry.current);\n\n\t\t\t\tconst _target = $.find(p => chunk.match(p.node));\n\t\t\t\tif (!_target) {\n\t\t\t\t\tthrow new Error('Could not find module chunk');\n\t\t\t\t}\n\n\t\t\t\tconst $target: NodePath = _target;\n\t\t\t\t$target.assertObjectProperty();\n\n\t\t\t\tconst $value: NodePath = $target.get('value');\n\t\t\t\t$value.assertFunction();\n\n\t\t\t\t$value.get('body').replaceWith(\n\t\t\t\t\ttmpl.statement.ast`{\n\t\t\t\t\t\trequire(${entry.current}).main(false);\n\t\t\t\t\t}`,\n\t\t\t\t);\n\n\t\t\t\t$.stop();\n\t\t\t\tthis.changes++;\n\t\t\t},\n\t\t},\n\t\tAssignmentExpression: {\n\t\t\texit($) {\n\t\t\t\tif (!verifyClient.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst $value: NodePath = $.get('right');\n\t\t\t\t$value.assertFunction();\n\n\t\t\t\t$value.get('body').replaceWith(\n\t\t\t\t\ttmpl.statement.ast`{\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}`,\n\t\t\t\t);\n\t\t\t\tthis.changes++;\n\t\t\t},\n\t\t},\n\t\tIfStatement: {\n\t\t\texit($) {\n\t\t\t\tif (!vsda.match($.node)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t$.remove();\n\t\t\t\tthis.changes++;\n\t\t\t},\n\t\t},\n\t}),\n} satisfies Transform;\n",
|
|
92
|
-
"import type * as t from '@babel/types';\nimport {applyTransform as webcrackApplyTransform} from 'webcrack/ast-utils';\nimport transpile from 'webcrack/transpile';\nimport stringaes from './stringaes';\nimport antifeature from './antifeature';\nimport {applyTransform} from '~ast';\n\n/**\n * Delance specific transforms.\n */\nexport default function transform(ast: t.Node) {\n\tapplyTransform(ast, stringaes);\n\tapplyTransform(ast, antifeature);\n\twebcrackApplyTransform(ast, transpile);\n\n\treturn ast;\n}\n",
|
|
93
|
-
"import type * as t from '@babel/types';\nimport webcrack from './webcrack';\nimport esmodule from './esmodule';\nimport syntactic from './syntactic';\nimport delance from './delance';\n\nexport default async function transform(ast: t.Node) {\n\tawait webcrack(ast);\n\tsyntactic(ast);\n\tesmodule(ast);\n\tdelance(ast);\n\treturn ast;\n}\n",
|
|
94
|
-
"import transform from './transform';\nimport {generate, parse} from '~ast';\n\n// eslint-disable-next-line import/no-anonymous-default-export\nexport default async function (code: string) {\n\treturn generate(await transform(parse(code)));\n}\n\nexport {default as transform} from './transform';\n"
|
|
95
|
-
],
|
|
96
|
-
"mappings": "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BAAY,CAAC,CAChB,CACD,CACD,GACA,IACD;AAAA,IACE,wBAAoB,OAAO;AAAA,MAC1B,uBACD,MACE,mBACC,qBACC,eAAW,QAAQ,GACnB,eAAW,0BAA0B,GACvC,KACD,GACA;AAAA,QACG,gBAAY,IAAG;AAAA,QACf,gBAAY,CAAC;AAAA,MAChB,CACD,CACD;AAAA,IACD,CAAC;AAAA,IACC,gBACC,sBACD,MACE,oBACD,KACE,gBAAY,IAAI,GAClB,IACD,GACE,OACD,MACE,oBACD,KACE,oBACD,KACA,MACA,IACD,GACA,IACD,CACD,CACD,GACE,mBAAe;AAAA,MACd,wBACC,yBACD,KACE,gBAAY,IAAI,GAClB,OACD,CACD;AAAA,IACD,CAAC,GACD,IACD;AAAA,IACE,wBACC,mBACC,qBACC,eAAW,QAAQ,GACnB,eAAW,gBAAgB,GAC7B,KACD,GACA;AAAA,MACG,gBAAY,GAAG;AAAA,MACf,gBAAY,EAAE;AAAA,MACd,gBAAY,IAAI;AAAA,IACnB,CACD,CACD;AAAA,EACD,CAAC,GACC,mBAAe;AAAA,IACd,gBACC,qBACD,OACA,IACE,eAAW,WAAW,CACzB,GACE,gBACC,wBACC,yBACD,KACE,gBAAY,EAAE,GACd,gBAAY,CAAC,CAChB,CACD,CACD,GACA,IACD;AAAA,IACE,wBACC,mBACC,qBACC,eAAW,QAAQ,GACnB,eAAW,gBAAgB,GAC7B,KACD,GACA;AAAA,MACG,gBAAY,GAAG;AAAA,MACf,gBAAY,EAAE;AAAA,MAChB;AAAA,IACD,CACD,CACD;AAAA,EACD,CAAC,CACF,CACD,GACE,uBACD,MACA,CAAC,KAAK,MAAK,GAAG,EAAE,GACd,mBAAe;AAAA,IACd,gBACC,qBACD,OACA,IACE,eAAW,WAAW,CACzB,GACE,gBACC,wBACC,yBACD,KACE,gBAAY,EAAE,GACd,gBAAY,CAAC,CAChB,CACD,CACD,GACA,IACD;AAAA,IACE,wBACC,yBACD,KACE,qBACC,gBAAY,GAAG,GACf,gBAAY,EAAE,GAChB,IACD,GACE,qBACC,gBAAY,IAAG,GACf,gBAAY,CAA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",
|
|
97
|
-
"debugId": "623A8DAFD0C674AC64756e2164756e21",
|
|
98
|
-
"names": []
|
|
99
|
-
}
|