mirror of
https://github.com/yt-dlp/ejs.git
synced 2026-06-13 00:32:11 +00:00
More robust solver extraction
- Do not hard fail if a single extraction fails - Do not fail if multiple solutions exist but they are the same
This commit is contained in:
@@ -5,10 +5,41 @@ import { extract as extractN } from "./n.ts";
|
||||
import { setupNodes } from "./setup.ts";
|
||||
|
||||
export function preprocessPlayer(data: string): string {
|
||||
const ast = parse(data);
|
||||
const body = ast.body;
|
||||
const program = parse(data);
|
||||
const plainStatements = modifyPlayer(program);
|
||||
const solutions = getSolutions(plainStatements);
|
||||
for (const [name, options] of Object.entries(solutions)) {
|
||||
plainStatements.push({
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "AssignmentExpression",
|
||||
operator: "=",
|
||||
left: {
|
||||
type: "MemberExpression",
|
||||
computed: false,
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_result",
|
||||
},
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: name,
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
right: multiTry(options),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const block = (() => {
|
||||
program.body.splice(0, 0, ...setupNodes);
|
||||
return generate(program);
|
||||
}
|
||||
|
||||
export function modifyPlayer(program: ESTree.Program) {
|
||||
const body = program.body;
|
||||
|
||||
const block: ESTree.BlockStatement = (() => {
|
||||
switch (body.length) {
|
||||
case 1: {
|
||||
const func = body[0];
|
||||
@@ -40,19 +71,7 @@ export function preprocessPlayer(data: string): string {
|
||||
throw "unexpected structure";
|
||||
})();
|
||||
|
||||
const found = {
|
||||
n: [] as ESTree.ArrowFunctionExpression[],
|
||||
sig: [] as ESTree.ArrowFunctionExpression[],
|
||||
};
|
||||
const plainExpressions = block.body.filter((node: ESTree.Node) => {
|
||||
const n = extractN(node);
|
||||
if (n) {
|
||||
found.n.push(n);
|
||||
}
|
||||
const sig = extractSig(node);
|
||||
if (sig) {
|
||||
found.sig.push(sig);
|
||||
}
|
||||
block.body = block.body.filter((node: ESTree.Statement) => {
|
||||
if (node.type === "ExpressionStatement") {
|
||||
if (node.expression.type === "AssignmentExpression") {
|
||||
return true;
|
||||
@@ -61,43 +80,28 @@ export function preprocessPlayer(data: string): string {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
block.body = plainExpressions;
|
||||
|
||||
for (const [name, options] of Object.entries(found)) {
|
||||
// TODO: this is cringe fix plz
|
||||
const unique = new Set(options.map((x) => JSON.stringify(x)));
|
||||
if (unique.size !== 1) {
|
||||
const message = `found ${unique.size} ${name} function possibilities`;
|
||||
throw (
|
||||
message +
|
||||
(unique.size ? `: ${options.map((x) => generate(x)).join(", ")}` : "")
|
||||
);
|
||||
return block.body;
|
||||
}
|
||||
|
||||
export function getSolutions(
|
||||
statements: ESTree.Statement[],
|
||||
): Record<string, ESTree.ArrowFunctionExpression[]> {
|
||||
const found = {
|
||||
n: [] as ESTree.ArrowFunctionExpression[],
|
||||
sig: [] as ESTree.ArrowFunctionExpression[],
|
||||
};
|
||||
for (const statement of statements) {
|
||||
const n = extractN(statement);
|
||||
if (n) {
|
||||
found.n.push(n);
|
||||
}
|
||||
const sig = extractSig(statement);
|
||||
if (sig) {
|
||||
found.sig.push(sig);
|
||||
}
|
||||
plainExpressions.push({
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "AssignmentExpression",
|
||||
operator: "=",
|
||||
left: {
|
||||
type: "MemberExpression",
|
||||
computed: false,
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_result",
|
||||
},
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: name,
|
||||
},
|
||||
},
|
||||
right: options[0],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
ast.body.splice(0, 0, ...setupNodes);
|
||||
|
||||
return generate(ast);
|
||||
return found;
|
||||
}
|
||||
|
||||
export function getFromPrepared(code: string): {
|
||||
@@ -108,3 +112,293 @@ export function getFromPrepared(code: string): {
|
||||
Function("_result", code)(resultObj);
|
||||
return resultObj;
|
||||
}
|
||||
|
||||
function multiTry(
|
||||
generators: ESTree.ArrowFunctionExpression[],
|
||||
): ESTree.ArrowFunctionExpression {
|
||||
return {
|
||||
type: "ArrowFunctionExpression",
|
||||
params: [
|
||||
{
|
||||
type: "Identifier",
|
||||
name: "_input",
|
||||
},
|
||||
],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [
|
||||
{
|
||||
type: "VariableDeclaration",
|
||||
kind: "const",
|
||||
declarations: [
|
||||
{
|
||||
type: "VariableDeclarator",
|
||||
id: {
|
||||
type: "Identifier",
|
||||
name: "_results",
|
||||
},
|
||||
init: {
|
||||
type: "NewExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
name: "Set",
|
||||
},
|
||||
arguments: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "ForOfStatement",
|
||||
left: {
|
||||
type: "VariableDeclaration",
|
||||
kind: "const",
|
||||
declarations: [
|
||||
{
|
||||
type: "VariableDeclarator",
|
||||
id: {
|
||||
type: "Identifier",
|
||||
name: "_generator",
|
||||
},
|
||||
init: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
right: {
|
||||
type: "ArrayExpression",
|
||||
elements: generators,
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [
|
||||
{
|
||||
type: "TryStatement",
|
||||
block: {
|
||||
type: "BlockStatement",
|
||||
body: [
|
||||
{
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_results",
|
||||
},
|
||||
computed: false,
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: "add",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
arguments: [
|
||||
{
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
name: "_generator",
|
||||
},
|
||||
arguments: [
|
||||
{
|
||||
type: "Identifier",
|
||||
name: "_input",
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
handler: {
|
||||
type: "CatchClause",
|
||||
param: null,
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [],
|
||||
},
|
||||
},
|
||||
finalizer: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
await: false,
|
||||
},
|
||||
{
|
||||
type: "IfStatement",
|
||||
test: {
|
||||
type: "UnaryExpression",
|
||||
operator: "!",
|
||||
argument: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_results",
|
||||
},
|
||||
computed: false,
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: "size",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
prefix: true,
|
||||
},
|
||||
consequent: {
|
||||
type: "BlockStatement",
|
||||
body: [
|
||||
{
|
||||
type: "ThrowStatement",
|
||||
argument: {
|
||||
type: "TemplateLiteral",
|
||||
expressions: [],
|
||||
quasis: [
|
||||
{
|
||||
type: "TemplateElement",
|
||||
value: {
|
||||
cooked: "no solutions",
|
||||
raw: "no solutions",
|
||||
},
|
||||
tail: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
alternate: null,
|
||||
},
|
||||
{
|
||||
type: "IfStatement",
|
||||
test: {
|
||||
type: "BinaryExpression",
|
||||
left: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_results",
|
||||
},
|
||||
computed: false,
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: "size",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
right: {
|
||||
type: "Literal",
|
||||
value: 1,
|
||||
},
|
||||
operator: "!==",
|
||||
},
|
||||
consequent: {
|
||||
type: "BlockStatement",
|
||||
body: [
|
||||
{
|
||||
type: "ThrowStatement",
|
||||
argument: {
|
||||
type: "TemplateLiteral",
|
||||
expressions: [
|
||||
{
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_results",
|
||||
},
|
||||
computed: false,
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: "join",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
arguments: [
|
||||
{
|
||||
type: "Literal",
|
||||
value: ", ",
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
},
|
||||
],
|
||||
quasis: [
|
||||
{
|
||||
type: "TemplateElement",
|
||||
value: {
|
||||
cooked: "invalid solutions: ",
|
||||
raw: "invalid solutions: ",
|
||||
},
|
||||
tail: false,
|
||||
},
|
||||
{
|
||||
type: "TemplateElement",
|
||||
value: {
|
||||
cooked: "",
|
||||
raw: "",
|
||||
},
|
||||
tail: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
alternate: null,
|
||||
},
|
||||
{
|
||||
type: "ReturnStatement",
|
||||
argument: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_results",
|
||||
},
|
||||
computed: false,
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: "values",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
arguments: [],
|
||||
optional: false,
|
||||
},
|
||||
computed: false,
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: "next",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
arguments: [],
|
||||
optional: false,
|
||||
},
|
||||
computed: false,
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: "value",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
async: false,
|
||||
expression: false,
|
||||
generator: false,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user