Skip to content

Commit c131e87

Browse files
author
laestrygonian
committed
Update solver 12 v2
1 parent 8d60e9a commit c131e87

1 file changed

Lines changed: 33 additions & 43 deletions

File tree

solver.js

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
21
// =============================================================================
3-
// YouTube N-Parameter Solver — Remote Module v12
2+
// YouTube N-Parameter Solver — Remote Module v13
43
// Hosted at: https://github.com/solarizeddev/firedown-solver
54
//
65
// Design principle: minimize structural assumptions about the player source.
@@ -14,45 +13,26 @@
1413
// v11: Runtime candidate enumeration, brace-walk IIFE detection, dual-quote
1514
// 'use strict', arithmetic-agnostic base scan.
1615
// v12: N-param architecture changed in player 1bb6ee63 (Apr 2026) — the
17-
// standalone `f(r, p, x)` n-transform is gone. The transform now lives
18-
// inside the URL parser class (historically `g.t_`). `TP(40, 1409, x)`
19-
// and similar multi-dispatch helpers pass the old XOR probe's shape
20-
// checks but return `"undefined" + x` when called with only 3 args,
21-
// producing garbage transforms that make videoplayback reject the URL.
22-
//
23-
// Three changes:
24-
//
25-
// 1. PRIMARY STRATEGY FOR N-PARAM — URL-class discovery. After the
26-
// player IIFE finishes initializing, walk runtime objects
27-
// (_yt_player, globalThis, nested namespaces up to depth 2) looking
28-
// for a 2-arg constructor whose instance has a `.get("n")` method
29-
// that deterministically transforms our test input into a valid-
30-
// looking n-value. No source pattern matching — pure behavioral
31-
// detection. Works regardless of what YouTube names the class
32-
// (g.t_, g.xY, _yt_player.Zz, whatever).
16+
// standalone `f(r, p, x)` n-transform is gone. URL-class discovery as
17+
// primary strategy. Call-site literal extraction for cipher.
18+
// v13: Stop the player from registering callbacks on the host's real event
19+
// loop. Previously SETUP_CODE used `if (typeof globalThis.setTimeout
20+
// === "undefined")` guards on its timer mocks. In Gecko's extension
21+
// sandbox setTimeout already exists, so the guards skipped installation
22+
// and the real timers were used. The player's IIFE registered callbacks
23+
// that fired AFTER our probe finished, generating code via new Function
24+
// / eval that referenced identifiers not present in our mocked env —
25+
// producing a SyntaxError every ~4ms, forever, in the host console.
3326
//
34-
// 2. CALL-SITE EXTRACTION FOR XOR DISPATCHERS — the cipher function on
35-
// this player is `kp(1, 7337, s)` (equivalently kp(10, 7330, s) —
36-
// same T = V^Y). Previous probes tried to derive Y from XOR constants
37-
// in the function body, but with Y never appearing inside kp's body
38-
// (only T does) that derivation is impossible. Instead, we scan the
39-
// player source once for `NAME(INT, INT, ...)` literal call sites
40-
// and test each pair. 21 distinct names × a handful of pairs each,
41-
// ~25ms scan. Replaces the 256×N-candidate bit-reversal for the
42-
// common case.
27+
// Fix: install no-op timer mocks unconditionally. The player can't
28+
// schedule anything, so no residual callbacks survive the probe.
4329
//
44-
// 3. XOR-PROBE VALIDATION HARDENING — both strategies above share new
45-
// validators that would have rejected the `TP` false positive:
46-
// a) input must not appear as a substring of output
47-
// b) output must not start with "undefined", "null", "NaN",
48-
// "[object", or other stringified-junk markers
49-
// c) cipher test inputs are now fully distinct (v11 shared the
50-
// middle and a cipher that scrambled the middle identically
51-
// produced _v1 === _v3, failing the validator)
52-
// Bit-reversal bit-scan remains as a fallback for older players
53-
// where call sites aren't literal.
30+
// Note: TypeError spam from URL-class probing (`y.U.call is not a
31+
// function` etc.) is NOT addressed here — those are caught inside
32+
// _testCtor but Gecko logs them anyway as a runtime behavior. Cannot
33+
// be suppressed from JS. They're cosmetic; the solver still works.
5434
// =============================================================================
55-
var SOLVER_VERSION = 12;
35+
var SOLVER_VERSION = 13;
5636

5737
var SETUP_CODE = [
5838
'if(typeof globalThis.XMLHttpRequest==="undefined"){globalThis.XMLHttpRequest={prototype:{}};}',
@@ -66,11 +46,21 @@ var SETUP_CODE = [
6646
'if(typeof globalThis.self==="undefined"){globalThis.self=globalThis;}',
6747
'if(typeof globalThis.addEventListener==="undefined"){globalThis.addEventListener=function(){};}',
6848
'if(typeof globalThis.removeEventListener==="undefined"){globalThis.removeEventListener=function(){};}',
69-
'if(typeof globalThis.setTimeout==="undefined"){globalThis.setTimeout=function(f){try{f();}catch(e){}};}',
70-
'if(typeof globalThis.clearTimeout==="undefined"){globalThis.clearTimeout=function(){};}',
71-
'if(typeof globalThis.setInterval==="undefined"){globalThis.setInterval=function(){return 0;};}',
72-
'if(typeof globalThis.clearInterval==="undefined"){globalThis.clearInterval=function(){};}',
73-
'if(typeof globalThis.requestAnimationFrame==="undefined"){globalThis.requestAnimationFrame=function(){};}',
49+
// Timer mocks: UNCONDITIONAL replacement (no `typeof === "undefined"` guard).
50+
// The host environment (Gecko extension sandbox) provides real timers, but
51+
// we don't want them — any callback the player schedules during IIFE
52+
// execution would fire on the host event loop AFTER our probe completes,
53+
// generating console-spamming SyntaxErrors as the player tries to JIT code
54+
// in our minimal mocked environment. Replacing with no-ops makes timer
55+
// registrations silently disappear.
56+
'globalThis.setTimeout=function(){return 0;};',
57+
'globalThis.clearTimeout=function(){};',
58+
'globalThis.setInterval=function(){return 0;};',
59+
'globalThis.clearInterval=function(){};',
60+
'globalThis.requestAnimationFrame=function(){return 0;};',
61+
'globalThis.cancelAnimationFrame=function(){};',
62+
// queueMicrotask also silently dropped — same rationale.
63+
'globalThis.queueMicrotask=function(){};',
7464
'if(typeof globalThis.getComputedStyle==="undefined"){globalThis.getComputedStyle=function(){return{opacity:"1"};};}',
7565
].join('\n');
7666

0 commit comments

Comments
 (0)