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.
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
5737var 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