diff --git a/deno.jsonc b/deno.jsonc index 99fd6de..6e862b7 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -1,11 +1,10 @@ { "imports": { - "@babel/generator": "npm:@babel/generator@7.28.3", - "@babel/parser": "npm:@babel/parser@7.28.3", - "@babel/types": "npm:@babel/types@7.28.2", "@std/assert": "jsr:@std/assert@1", "@std/io": "jsr:@std/io", - "@std/fs/exists": "jsr:@std/fs/exists" + "@std/fs/exists": "jsr:@std/fs/exists", + "astring": "npm:astring@1.9.0", + "meriyah": "npm:meriyah@6.1.4" }, "test": { "exclude": ["./dist"] @@ -13,6 +12,7 @@ "tasks": { "download": "deno run --allow-read --allow-write --allow-net=www.youtube.com tests/download.ts", "test": "deno test --allow-read --allow-env=BABEL_TYPES_8_BREAKING --location 'https://www.youtube.com/watch?v=yt-dlp-wins'", + "ptest": "deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} main$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} tcc$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} tce$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} es5$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} es6$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} tv$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} tv_es6$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} phone$/\" & deno task --quiet test --quiet --reporter dot --hide-stacktraces --filter \"/^[a-f\\d]{8} tablet$/\"", "bundle": "deno bundle --output dist/jsc-deno.js src/main.ts" } } diff --git a/deno.lock b/deno.lock index 9f77cd2..73c7e41 100644 --- a/deno.lock +++ b/deno.lock @@ -3,11 +3,11 @@ "specifiers": { "jsr:@std/assert@1": "1.0.14", "jsr:@std/bytes@^1.0.5": "1.0.6", + "jsr:@std/fs@*": "1.0.18", "jsr:@std/internal@^1.0.10": "1.0.10", "jsr:@std/io@*": "0.225.2", - "npm:@babel/generator@7.28.3": "7.28.3", - "npm:@babel/parser@7.28.3": "7.28.3", - "npm:@babel/types@7.28.2": "7.28.2" + "npm:astring@1.9.0": "1.9.0", + "npm:meriyah@6.1.4": "6.1.4" }, "jsr": { "@std/assert@1.0.14": { @@ -19,6 +19,9 @@ "@std/bytes@1.0.6": { "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" }, + "@std/fs@1.0.18": { + "integrity": "24bcad99eab1af4fde75e05da6e9ed0e0dce5edb71b7e34baacf86ffe3969f3a" + }, "@std/internal@1.0.10": { "integrity": "e3be62ce42cab0e177c27698e5d9800122f67b766a0bea6ca4867886cbde8cf7" }, @@ -30,59 +33,12 @@ } }, "npm": { - "@babel/generator@7.28.3": { - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dependencies": [ - "@babel/parser", - "@babel/types", - "@jridgewell/gen-mapping", - "@jridgewell/trace-mapping", - "jsesc" - ] - }, - "@babel/helper-string-parser@7.27.1": { - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" - }, - "@babel/helper-validator-identifier@7.27.1": { - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==" - }, - "@babel/parser@7.28.3": { - "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", - "dependencies": [ - "@babel/types" - ], + "astring@1.9.0": { + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", "bin": true }, - "@babel/types@7.28.2": { - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", - "dependencies": [ - "@babel/helper-string-parser", - "@babel/helper-validator-identifier" - ] - }, - "@jridgewell/gen-mapping@0.3.13": { - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dependencies": [ - "@jridgewell/sourcemap-codec", - "@jridgewell/trace-mapping" - ] - }, - "@jridgewell/resolve-uri@3.1.2": { - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" - }, - "@jridgewell/sourcemap-codec@1.5.5": { - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" - }, - "@jridgewell/trace-mapping@0.3.30": { - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", - "dependencies": [ - "@jridgewell/resolve-uri", - "@jridgewell/sourcemap-codec" - ] - }, - "jsesc@3.1.0": { - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "bin": true + "meriyah@6.1.4": { + "integrity": "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==" } }, "workspace": { @@ -90,9 +46,8 @@ "jsr:@std/assert@1", "jsr:@std/fs@*", "jsr:@std/io@*", - "npm:@babel/generator@7.28.3", - "npm:@babel/parser@7.28.3", - "npm:@babel/types@7.28.2" + "npm:astring@1.9.0", + "npm:meriyah@6.1.4" ] } } diff --git a/src/nsig.ts b/src/nsig.ts index 3c28be7..0f73f0a 100644 --- a/src/nsig.ts +++ b/src/nsig.ts @@ -1,13 +1,10 @@ -import { - type ArrowFunctionExpression, - type BlockStatement, - type Node, -} from "@babel/types"; +import { type ESTree } from "meriyah"; import { matchesStructure } from "./utils.ts"; import { type DeepPartial } from "./types.ts"; -const identifier: DeepPartial = { +const identifier: DeepPartial = { type: "VariableDeclaration", + kind: "var", declarations: [ { type: "VariableDeclarator", @@ -24,35 +21,39 @@ const identifier: DeepPartial = { }, }, ], - kind: "var", }; + const catchBlockBody = [ { - "type": "ReturnStatement", - "argument": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "MemberExpression", - "object": { - "type": "Identifier", + type: "ReturnStatement", + argument: { + type: "BinaryExpression", + left: { + type: "MemberExpression", + object: { + type: "Identifier", }, - "property": { - "type": "NumericLiteral", + computed: true, + property: { + type: "Literal", }, + optional: false, }, - "right": { - "type": "Identifier", + right: { + type: "Identifier", }, + operator: "+", }, }, ] as const; -export function extract(node: Node): ArrowFunctionExpression | null { +export function extract( + node: ESTree.Node, +): ESTree.ArrowFunctionExpression | null { if (!matchesStructure(node, identifier)) { // Fallback search for try { } catch { return X[12] + Y } let name: string | undefined | null = null; - let block: BlockStatement | null = null; + let block: ESTree.BlockStatement | null | undefined = null; switch (node.type) { case "ExpressionStatement": { if ( @@ -109,17 +110,15 @@ export function extract(node: Node): ArrowFunctionExpression | null { return makeSolverFuncFromName(firstElement.name); } -function makeSolverFuncFromName(name: string): ArrowFunctionExpression { +function makeSolverFuncFromName(name: string): ESTree.ArrowFunctionExpression { return { type: "ArrowFunctionExpression", params: [ { type: "Identifier", - name: "x", + name: "nsig", }, ], - async: false, - expression: true, body: { type: "CallExpression", callee: { @@ -129,9 +128,13 @@ function makeSolverFuncFromName(name: string): ArrowFunctionExpression { arguments: [ { type: "Identifier", - name: "x", + name: "nsig", }, ], + optional: false, }, + async: false, + expression: false, + generator: false, }; } diff --git a/src/setup.ts b/src/setup.ts index 8ba27a9..ae59908 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -1,11 +1,14 @@ -import { type Node } from "@babel/types"; +import { parse } from "meriyah"; -export const setupNodes: Node[] = [ +export const setupNodes = parse(` +globalThis.XMLHttpRequest = { prototype: {} }; +const window = Object.assign(Object.create(null), globalThis); +const document = {}; +`).body || [ { type: "ExpressionStatement", expression: { type: "AssignmentExpression", - operator: "=", left: { type: "MemberExpression", object: { @@ -17,23 +20,26 @@ export const setupNodes: Node[] = [ type: "Identifier", name: "XMLHttpRequest", }, + optional: false, }, + operator: "=", right: { type: "ObjectExpression", properties: [ { - type: "ObjectProperty", - method: false, + type: "Property", key: { type: "Identifier", name: "prototype", }, - computed: false, - shorthand: false, value: { type: "ObjectExpression", properties: [], }, + kind: "init", + computed: false, + method: false, + shorthand: false, }, ], }, @@ -41,6 +47,7 @@ export const setupNodes: Node[] = [ }, { type: "VariableDeclaration", + kind: "const", declarations: [ { type: "VariableDeclarator", @@ -61,6 +68,7 @@ export const setupNodes: Node[] = [ type: "Identifier", name: "assign", }, + optional: false, }, arguments: [ { @@ -76,25 +84,29 @@ export const setupNodes: Node[] = [ type: "Identifier", name: "create", }, + optional: false, }, arguments: [ { - type: "NullLiteral", + type: "Literal", + value: null, }, ], + optional: false, }, { type: "Identifier", name: "globalThis", }, ], + optional: false, }, }, ], - kind: "const", }, { type: "VariableDeclaration", + kind: "const", declarations: [ { type: "VariableDeclarator", @@ -108,6 +120,5 @@ export const setupNodes: Node[] = [ }, }, ], - kind: "const", }, ]; diff --git a/src/sig.ts b/src/sig.ts index 32e78d8..b66e034 100644 --- a/src/sig.ts +++ b/src/sig.ts @@ -1,30 +1,23 @@ -import { - type ArrowFunctionExpression, - type Expression, - type ExpressionStatement, - type FunctionExpression, - type Node, -} from "@babel/types"; +import { type ESTree } from "meriyah"; import { matchesStructure } from "./utils.ts"; import { type DeepPartial } from "./types.ts"; -const logicalExpression: DeepPartial = { +const logicalExpression: DeepPartial = { type: "ExpressionStatement", expression: { type: "LogicalExpression", left: { type: "Identifier", }, - operator: "&&", right: { type: "SequenceExpression", expressions: [ { type: "AssignmentExpression", - operator: "=", left: { type: "Identifier", }, + operator: "=", right: { type: "CallExpression", callee: { @@ -33,7 +26,7 @@ const logicalExpression: DeepPartial = { arguments: { or: [ [ - { type: "NumericLiteral" }, + { type: "Literal" }, { type: "CallExpression", callee: { @@ -41,6 +34,7 @@ const logicalExpression: DeepPartial = { name: "decodeURIComponent", }, arguments: [{ type: "Identifier" }], + optional: false, }, ], [ @@ -51,20 +45,20 @@ const logicalExpression: DeepPartial = { name: "decodeURIComponent", }, arguments: [{ type: "Identifier" }], + optional: false, }, ], ], }, + optional: false, }, }, { type: "CallExpression", }, ], - extra: { - parenthesized: true, - }, }, + operator: "&&", }, }; @@ -88,8 +82,12 @@ const identifier = { }], } as const; -export function extract(node: Node): ArrowFunctionExpression | null { - if (!matchesStructure(node, identifier as unknown as DeepPartial)) { +export function extract( + node: ESTree.Node, +): ESTree.ArrowFunctionExpression | null { + if ( + !matchesStructure(node, identifier as unknown as DeepPartial) + ) { return null; } const block = (node.type === "ExpressionStatement" && @@ -127,8 +125,6 @@ export function extract(node: Node): ArrowFunctionExpression | null { name: "sig", }, ], - async: false, - expression: true, body: { type: "CallExpression", callee: { @@ -149,6 +145,10 @@ export function extract(node: Node): ArrowFunctionExpression | null { name: "sig", }, ], + optional: false, }, + async: false, + expression: false, + generator: false, }; } diff --git a/src/solvers.ts b/src/solvers.ts index 3410ab3..be72ae9 100755 --- a/src/solvers.ts +++ b/src/solvers.ts @@ -1,16 +1,12 @@ -import { parse } from "@babel/parser"; -import { generate } from "@babel/generator"; -import { type ArrowFunctionExpression } from "@babel/types"; -import { getFunctionNodes } from "./utils.ts"; +import { type ESTree, parse } from "meriyah"; +import { generate } from "astring"; import { extract as extractSig } from "./sig.ts"; import { extract as extractNsig } from "./nsig.ts"; import { setupNodes } from "./setup.ts"; export function preprocessPlayer(data: string): string { - const ast = parse(data, { - attachComment: false, - }); - const body = ast.program.body; + const ast = parse(data); + const body = ast.body; const block = (() => { switch (body.length) { @@ -45,10 +41,10 @@ export function preprocessPlayer(data: string): string { })(); const found = { - nsig: [] as ArrowFunctionExpression[], - sig: [] as ArrowFunctionExpression[], + nsig: [] as ESTree.ArrowFunctionExpression[], + sig: [] as ESTree.ArrowFunctionExpression[], }; - const plainExpressions = block.body.filter((node) => { + const plainExpressions = block.body.filter((node: ESTree.Node) => { const nsig = extractNsig(node); if (nsig) { found.nsig.push(nsig); @@ -61,7 +57,7 @@ export function preprocessPlayer(data: string): string { if (node.expression.type === "AssignmentExpression") { return true; } - return node.expression.type === "StringLiteral"; + return node.expression.type === "Literal"; } return true; }); @@ -74,9 +70,7 @@ export function preprocessPlayer(data: string): string { const message = `found ${unique.size} ${name} function possibilities`; throw ( message + - (unique.size - ? `: ${options.map((x) => generate(x)["code"]).join(", ")}` - : "") + (unique.size ? `: ${options.map((x) => generate(x)).join(", ")}` : "") ); } plainExpressions.push({ @@ -101,13 +95,9 @@ export function preprocessPlayer(data: string): string { }); } - ast.program.body.splice(0, 0, ...setupNodes); + ast.body.splice(0, 0, ...setupNodes); - const { code } = generate(ast, { - comments: false, - compact: false, - concise: false, - }); + const code = generate(ast); return code; } diff --git a/src/utils.ts b/src/utils.ts index 3213647..38e2d77 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,9 +1,8 @@ -import { parse } from "@babel/parser"; -import { type Node, type Statement } from "@babel/types"; +import { type ESTree } from "meriyah"; import { type DeepPartial } from "./types.ts"; -export function matchesStructure( - obj: Node | Node[], +export function matchesStructure( + obj: ESTree.Node | ESTree.Node[], structure: DeepPartial | readonly DeepPartial[], ): boolean { if (Array.isArray(structure)) { @@ -33,15 +32,6 @@ export function matchesStructure( return structure === obj; } -export function getFunctionNodes(f: (...a: unknown[]) => void): Statement[] { - const func = parse(f.toString()).program.body[0]; - if (func.type === "FunctionDeclaration") { - return func.body.body; - } - console.error("failed to parse function into nodes"); - return []; -} - export function isOneOf(value: unknown, ...of: readonly T[]): value is T { return of.includes(value as T); }