mirror of
https://github.com/yt-dlp/ejs.git
synced 2026-06-13 00:32:11 +00:00
Improve runtime speed
This commit is contained in:
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
69
deno.lock
generated
69
deno.lock
generated
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
55
src/nsig.ts
55
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<Node> = {
|
||||
const identifier: DeepPartial<ESTree.VariableDeclaration> = {
|
||||
type: "VariableDeclaration",
|
||||
kind: "var",
|
||||
declarations: [
|
||||
{
|
||||
type: "VariableDeclarator",
|
||||
@@ -24,35 +21,39 @@ const identifier: DeepPartial<Node> = {
|
||||
},
|
||||
},
|
||||
],
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
31
src/setup.ts
31
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",
|
||||
},
|
||||
];
|
||||
|
||||
36
src/sig.ts
36
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<ExpressionStatement> = {
|
||||
const logicalExpression: DeepPartial<ESTree.ExpressionStatement> = {
|
||||
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<ExpressionStatement> = {
|
||||
arguments: {
|
||||
or: [
|
||||
[
|
||||
{ type: "NumericLiteral" },
|
||||
{ type: "Literal" },
|
||||
{
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
@@ -41,6 +34,7 @@ const logicalExpression: DeepPartial<ExpressionStatement> = {
|
||||
name: "decodeURIComponent",
|
||||
},
|
||||
arguments: [{ type: "Identifier" }],
|
||||
optional: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -51,20 +45,20 @@ const logicalExpression: DeepPartial<ExpressionStatement> = {
|
||||
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<Node>)) {
|
||||
export function extract(
|
||||
node: ESTree.Node,
|
||||
): ESTree.ArrowFunctionExpression | null {
|
||||
if (
|
||||
!matchesStructure(node, identifier as unknown as DeepPartial<ESTree.Node>)
|
||||
) {
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
16
src/utils.ts
16
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<T extends Node>(
|
||||
obj: Node | Node[],
|
||||
export function matchesStructure<T extends ESTree.Node>(
|
||||
obj: ESTree.Node | ESTree.Node[],
|
||||
structure: DeepPartial<T> | readonly DeepPartial<T>[],
|
||||
): boolean {
|
||||
if (Array.isArray(structure)) {
|
||||
@@ -33,15 +32,6 @@ export function matchesStructure<T extends Node>(
|
||||
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<T>(value: unknown, ...of: readonly T[]): value is T {
|
||||
return of.includes(value as T);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user