nx_yt_basejs.nx source
↩ module page · 111 lines · 4953 B
1// nx_yt_basejs.nx -- NATIVE (no JS engine) name-finder for YouTube's base.js n-throttle function. This is the
2// fragile arms-race parse yt-dlp needs, done in NishiLang: locate the n-function's NAME from the player code so
3// nx_yt_nsolve can then RUN it (that run is the last-mile JS; THIS locate is native text analysis). Real shape,
4// minified: `...a.get("n"))&&(b=Wma[0](b)...` where the function is referenced through an ARRAY (`Wma[0]`) whose
5// element list is defined elsewhere (`var Wma=[Xdec,Yfoo]`), OR referenced directly (`&&(c=lha(c)`). Layered so
6// a shape change that breaks one pattern still resolves via another -- and a total miss is a LEARN signal for
7// the self-heal table (name-location is itself a learnable pattern). license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_media_signal.nx" // xt_find (native substring)
10
11// JS identifier char: 0-9 A-Z a-z _ $
12func bjs_identc(c: i64) -> i64 {
13 if c >= 48 { if c <= 57 { return 1 } }
14 if c >= 65 { if c <= 90 { return 1 } }
15 if c >= 97 { if c <= 122 { return 1 } }
16 if c == 95 { return 1 }
17 if c == 36 { return 1 }
18 return 0
19}
20// read a JS identifier starting at `from`; copy into out (NUL-terminated); return its length (0 if none).
21func bjs_read_ident(js: *u8, jl: i64, from: i64, out: *u8, cap: i64) -> i64 {
22 var i: i64 = from
23 var w: i64 = 0
24 var go: i64 = 1
25 while go == 1 {
26 if i >= jl { go = 0 }
27 else { let c: i64 = js[i] & 0xff
28 if bjs_identc(c) == 1 { if w < (cap - 1) { out[w] = c as u8; w = w + 1 } i = i + 1 }
29 else { go = 0 } }
30 }
31 out[w] = 0 as u8
32 return w
33}
34// resolve `<arrname>[idx]` -> the idx-th comma-separated identifier in `<arrname>=[e0,e1,...]`. Returns len or 0.
35func bjs_resolve_array_elem(js: *u8, jl: i64, arrname: *u8, arrnamelen: i64, idx: i64, out: *u8, cap: i64) -> i64 {
36 let nd: *u8 = sys_mmap(256)
37 var o: i64 = 0
38 while o < arrnamelen { nd[o] = arrname[o]; o = o + 1 }
39 nd[o] = 61 as u8; o = o + 1 // '='
40 nd[o] = 91 as u8; o = o + 1 // '['
41 let p: i64 = xt_find(js, jl, nd, o, 0)
42 if p < 0 { return 0 }
43 var i: i64 = p + o // just past "arrname=["
44 var elem: i64 = 0
45 var go: i64 = 1
46 while go == 1 {
47 if i >= jl { go = 0; out[0] = 0 as u8; return 0 }
48 else {
49 let c: i64 = js[i] & 0xff
50 if c == 93 { go = 0; out[0] = 0 as u8; return 0 } // ']' before reaching idx
51 else {
52 if bjs_identc(c) == 1 {
53 if elem == idx { return bjs_read_ident(js, jl, i, out, cap) }
54 // skip this element's identifier
55 let sk: i64 = bjs_read_ident(js, jl, i, out, cap)
56 i = i + sk
57 } else {
58 if c == 44 { elem = elem + 1 } // ',' -> next element
59 i = i + 1
60 }
61 }
62 }
63 }
64 out[0] = 0 as u8
65 return 0
66}
67// FIND the n-function name in base.js. Returns resolved name length in `out` (0 = not found = a LEARN signal).
68func bjs_find_nfunc_name(js: *u8, jl: i64, out: *u8, cap: i64) -> i64 {
69 // anchor: the n-param read `.get("n")`
70 let p: i64 = xt_find(js, jl, ".get(\"n\")" as *u8, 9, 0)
71 if p < 0 { out[0] = 0 as u8; return 0 }
72 // the near `&&(` that opens the transform assignment (bounded search so we don't grab a distant one)
73 let a: i64 = xt_find(js, jl, "&&(" as *u8, 3, p)
74 if a < 0 { out[0] = 0 as u8; return 0 }
75 if (a - p) > 64 { out[0] = 0 as u8; return 0 }
76 // skip the assignment target `<v>=`
77 var i: i64 = a + 3
78 let tmp: *u8 = sys_mmap(256)
79 let vlen: i64 = bjs_read_ident(js, jl, i, tmp, 256)
80 i = i + vlen
81 if i >= jl { out[0] = 0 as u8; return 0 }
82 if (js[i] & 0xff) != 61 { out[0] = 0 as u8; return 0 } // expect '='
83 i = i + 1
84 // read the function reference identifier
85 let reflen: i64 = bjs_read_ident(js, jl, i, out, cap)
86 if reflen == 0 { out[0] = 0 as u8; return 0 }
87 i = i + reflen
88 // array-indexed? `<ref>[<digits>]` -> resolve via the array literal
89 if i < jl { if (js[i] & 0xff) == 91 { // '['
90 var j: i64 = i + 1
91 var idx: i64 = 0
92 var got: i64 = 0
93 var g2: i64 = 1
94 while g2 == 1 {
95 if j >= jl { g2 = 0 }
96 else { let d: i64 = js[j] & 0xff
97 if d >= 48 { if d <= 57 { idx = idx * 10 + (d - 48); got = 1; j = j + 1 } else { g2 = 0 } }
98 if d < 48 { g2 = 0 }
99 if d > 57 { g2 = 0 } }
100 }
101 if got == 1 {
102 let arrname: *u8 = sys_mmap(256)
103 var k: i64 = 0
104 while k < reflen { arrname[k] = out[k]; k = k + 1 }
105 arrname[reflen] = 0 as u8
106 let rl: i64 = bjs_resolve_array_elem(js, jl, arrname, reflen, idx, out, cap)
107 return rl
108 }
109 } }
110 return reflen
111}