Skip to content

Add last_var_atom for better error messages#1382

Open
speedskater1610 wants to merge 8 commits intoquickjs-ng:masterfrom
speedskater1610:master
Open

Add last_var_atom for better error messages#1382
speedskater1610 wants to merge 8 commits intoquickjs-ng:masterfrom
speedskater1610:master

Conversation

@speedskater1610
Copy link
Contributor

This is related to #1231, I have tested these changes on linux and they work according to the 'repro' provided in the linked issue (e.g., "TypeError: a is not a function" instead of "TypeError: not a function"). For optimized cases where the value is pushed as a constant, it falls back to the generic message.

key changes made:

  • Added rt->last_var_atom tracking in OP_get_loc*, OP_get_var, OP_get_var_ref*, and OP_get_var_ref opcodes
  • Modified the not_a_function handler in JS_CallInternal to use rt->last_var_atom for atom-based error messages.
  • Updated JS_ThrowTypeErrorNotAFunctionAtom to generate messages with variable names.

quickjs.c Outdated
}
char buf[ATOM_GET_STR_BUF_SIZE];
JS_AtomGetStr(ctx, buf, sizeof(buf), atom);
return JS_ThrowTypeError(ctx, "[SUCCESS] %s is not a function", buf);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return JS_ThrowTypeError(ctx, "[SUCCESS] %s is not a function", buf);
return JS_ThrowTypeError(ctx, "%s is not a function", buf);

pc += 4;
sf->cur_pc = pc;
/* only store atom if it looks valid */
if (atom != JS_ATOM_NULL && atom < JS_ATOM_END) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JS_ATOM_END is the end of the static/named atoms (i.e., the ones from quickjs-atom.h) but many more are created at runtime so this won't work, or at least be very limiting.

On the flip side, atoms >= JS_ATOM_END are reference-counted so you have to be very careful not to introduce use-after-free bugs. In particular, one problem I see is:

  1. atom is assigned to rt->last_var_atom
  2. the corresponding JSFunctionDef object is freed
  3. Sometime later rt->last_var_atom is accessed

rt->last_var_atom is now either invalid (use-after-free) or, if the atom's slot in the runtime atom table has been reused, points to the wrong atom.

In JS_CallInternal you can maybe avoid that by caching rt->last_var_atom in a local variable at function entry, then restoring it at function exit.

CASE(OP_get_loc1): *sp++ = js_dup(var_buf[1]); BREAK;
CASE(OP_get_loc2): *sp++ = js_dup(var_buf[2]); BREAK;
CASE(OP_get_loc3): *sp++ = js_dup(var_buf[3]); BREAK;
CASE(OP_get_loc0): if (b && b->vardefs) { JSAtom a = b->vardefs[0].var_name; if (a != JS_ATOM_NULL && a < JS_ATOM_END) rt->last_var_atom = a; } *sp++ = js_dup(var_buf[0]); BREAK;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OP_get_loc opcodes are very performance sensitive and adding conditionals likely introduces performance regressions. Can you check with https://github.com/quickjs-ng/web-tooling-benchmark?

There's also a func_call benchmark in tests/microbench.js but it doesn't really exercise these code paths. You're welcome to add one that does though.

quickjs.c Outdated
}
}
if (is_be())
lre_byte_swap(str8(bc), bc->len, /*is_byte_swapped*/false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you undo these changes? They're undoing recent commits to master.

@Vangelis66
Copy link

Vangelis66 commented Mar 5, 2026

Apologies for barging in, as I'm not a coder, but just a user of quickjs-ng instead 😉 ...

My main/unique use case of quickjs-ng is in the context of yt-dlp, as a JS runtime to solve YouTube's complex JS challenges (YT-player's n/sig); the recent implementation of rope strings in #1324 has made the app very appealing under that scenario and, practically, one of only two choices of a JS runtime in the case of "legacy" 32-bit WinOSes (apart from "upstream", by bellard; hasn't been updated since Sep 2025) ...

In that context, I routinely check quickjs-ng binary artifacts from here:

https://github.com/quickjs-ng/quickjs/actions/workflows/release.yml

in the hope recent PRs improve even more the performance in solving YT's JS challenges; while testing the latest artifact corresponding to this very PR (#1382):

https://github.com/quickjs-ng/quickjs/actions/runs/22729171576?pr=1382

https://github.com/quickjs-ng/quickjs/actions/runs/22729171576/artifacts/5783931130
(32-bit Win EXE)

, I found out, much to my dismay, that it's broken when used with yt-dlp:

yt-dlp --ies youtube -vF "J3x_KSFtIM8" --js quickjs
[debug] Command-line config: ['--ffmpeg-location', 'FFmpeg', '--downloader-args', 'ffmpeg_i:-hide_banner -v 8 -stats', '--ies', 'youtube', '-vF', 'J3x_KSFtIM8', '--js', 'quickjs']
[debug] Encodings: locale cp1253, fs utf-8, pref cp1253, out utf-8 (No VT), error utf-8 (No VT), screen utf-8 (No VT)
[debug] yt-dlp version master@2026.03.03.162040 from yt-dlp/yt-dlp-master-builds [2ecc4c3bc] (zip)
[debug] Python 3.11.14 (CPython x86 32bit) - Windows-Vista-6.0.6003-SP2 (OpenSSL 3.6.1 27 Jan 2026)
[debug] exe versions: ffmpeg n8.1-dev-630-N-121254-g635cb45 (setts), ffprobe n8.1-dev-630-N-121254-g635cb45
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.02.25, mutagen-1.47.0, requests-2.32.5, sqlite3-3.51.2, urllib3-2.6.3, websockets-16.0, yt_dlp_ejs-0.5.0
[debug] JS runtimes: quickjs-ng-0.12.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Plugin directories: none
[debug] Loaded 1 extractors
[debug] [youtube] [pot] PO Token Providers: none
[debug] [youtube] [pot] PO Token Cache Providers: memory
[debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
[debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno (unavailable), node (unavailable), quickjs
[youtube] Extracting URL: J3x_KSFtIM8
[youtube] J3x_KSFtIM8: Downloading webpage
[debug] [youtube] Forcing player 9f4cc5e4 in place of player 6c5cb4f4
        Forcing "tv" player JS variant for player 9f4cc5e4
        original url = /s/player/6c5cb4f4/player_es6.vflset/en_US/base.js
[youtube] J3x_KSFtIM8: Downloading android vr player API JSON
[debug] [youtube] J3x_KSFtIM8: android_vr player response playability status: UNPLAYABLE
[youtube] J3x_KSFtIM8: Downloading web embedded client config
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web_embedded client
[youtube] J3x_KSFtIM8: Downloading web embedded player API JSON
[debug] [youtube] J3x_KSFtIM8: web_embedded player response playability status: ERROR
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web client
[youtube] J3x_KSFtIM8: Downloading web player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 6s ad for web
[youtube] J3x_KSFtIM8: Downloading web safari player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 6s ad for web_safari
[debug] Loading youtube-sigfuncs.9f4cc5e4-tv-105 from cache
[youtube] J3x_KSFtIM8: Downloading player 9f4cc5e4-tv
[youtube] [jsc:quickjs] Solving JS challenges using quickjs
[debug] [youtube] [jsc:quickjs] Using challenge solver lib script v0.5.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:quickjs] Using challenge solver core script v0.5.0 (source: python package, variant: minified)
WARNING: [youtube] [jsc:quickjs] QuickJS-NG is missing some optimizations making this very slow. Consider using upstream QuickJS instead.
[debug] [youtube] [jsc:quickjs] Running QuickJS: 'G:\Python\3.11.x\yt-dlp_on_py311\qjs.EXE' --script 'C:\Users\redacted\AppData\Local\Temp\tmpoiojhsxr.js'
WARNING: [youtube] [jsc] Error solving 2 challenge requests using "quickjs" provider: Error running QuickJS process (returncode: 1): TypeError: not a function
    at <anonymous> (C:\Users\redacted\AppData\Local\Temp\tmpoiojhsxr.js:52:17442)
    at <eval> (C:\Users\redacted\AppData\Local\Temp\tmpoiojhsxr.js:52:149149).
         requests = [JsChallengeRequest(type=<JsChallengeType.N: 'n'>, input=NChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=['ey8bvODmA1nx0LvLhuPc', 'I7esKdfELf39DNZJl0q8', 'dAa4Pw_lu1pB-vEk-ELu']), video_id='J3x_KSFtIM8'), JsChallengeRequest(type=<JsChallengeType.SIG: 'sig'>, input=SigChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=[]), video_id='J3x_KSFtIM8')]
         Please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
WARNING: [youtube] J3x_KSFtIM8: n challenge solving failed: Some formats may be missing. Ensure you have a supported JavaScript runtime and challenge solver script distribution installed. Review any warnings presented before this message. For more details, refer to  https://github.com/yt-dlp/yt-dlp/wiki/EJS
[debug] [youtube] J3x_KSFtIM8: Some web client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
[debug] [youtube] J3x_KSFtIM8: Some web_safari client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
ERROR: [youtube] J3x_KSFtIM8: This video is not available
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\common.py", line 765, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\youtube\_video.py", line 4026, in _real_extract
    self.raise_no_formats(reason, expected=True)
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\common.py", line 1277, in raise_no_formats
    raise ExtractorError(msg, expected=expected, video_id=video_id)

... with the error being:

[youtube] [jsc:quickjs] Solving JS challenges using quickjs
[debug] [youtube] [jsc:quickjs] Using challenge solver lib script v0.5.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:quickjs] Using challenge solver core script v0.5.0 (source: python package, variant: minified)
WARNING: [youtube] [jsc:quickjs] QuickJS-NG is missing some optimizations making this very slow. Consider using upstream QuickJS instead.
[debug] [youtube] [jsc:quickjs] Running QuickJS: 'G:\Python\3.11.x\yt-dlp_on_py311\qjs.EXE' --script 'C:\Users\redacted\AppData\Local\Temp\tmpoiojhsxr.js'
WARNING: [youtube] [jsc] Error solving 2 challenge requests using "quickjs" provider: Error running QuickJS process (returncode: 1): TypeError: not a function
    at <anonymous> (C:\Users\redacted\AppData\Local\Temp\tmpoiojhsxr.js:52:17442)
    at <eval> (C:\Users\redacted\AppData\Local\Temp\tmpoiojhsxr.js:52:149149).
         requests = [JsChallengeRequest(type=<JsChallengeType.N: 'n'>, input=NChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=['ey8bvODmA1nx0LvLhuPc', 'I7esKdfELf39DNZJl0q8', 'dAa4Pw_lu1pB-vEk-ELu']), video_id='J3x_KSFtIM8'), JsChallengeRequest(type=<JsChallengeType.SIG: 'sig'>, input=SigChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=[]), video_id='J3x_KSFtIM8')]
         Please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
WARNING: [youtube] J3x_KSFtIM8: n challenge solving failed: Some formats may be missing. Ensure you have a supported JavaScript runtime and challenge solver script distribution installed. Review any warnings presented before this message. For more details, refer to  https://github.com/yt-dlp/yt-dlp/wiki/EJS
[debug] [youtube] J3x_KSFtIM8: Some web client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details

Is this breakage an immediate result of

Can you undo these changes? They're undoing recent commits to master.

? FTR, any other recent artifact, or even tag v0.12.1, works OK with yt-dlp:

yt-dlp --ies youtube -vF "J3x_KSFtIM8" --js quickjs
[debug] Command-line config: ['--ffmpeg-location', 'FFmpeg', '--downloader-args', 'ffmpeg_i:-hide_banner -v 8 -stats', '--ies', 'youtube', '-vF', 'J3x_KSFtIM8', '--js', 'quickjs']
[debug] Encodings: locale cp1253, fs utf-8, pref cp1253, out utf-8 (No VT), error utf-8 (No VT), screen utf-8 (No VT)
[debug] yt-dlp version master@2026.03.03.162040 from yt-dlp/yt-dlp-master-builds [2ecc4c3bc] (zip)
[debug] Python 3.11.14 (CPython x86 32bit) - Windows-Vista-6.0.6003-SP2 (OpenSSL 3.6.1 27 Jan 2026)
[debug] exe versions: ffmpeg n8.1-dev-630-N-121254-g635cb45 (setts), ffprobe n8.1-dev-630-N-121254-g635cb45
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.02.25, mutagen-1.47.0, requests-2.32.5, sqlite3-3.51.2, urllib3-2.6.3, websockets-16.0, yt_dlp_ejs-0.5.0
[debug] JS runtimes: quickjs-ng-0.12.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Plugin directories: none
[debug] Loaded 1 extractors
[debug] [youtube] [pot] PO Token Providers: none
[debug] [youtube] [pot] PO Token Cache Providers: memory
[debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
[debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno (unavailable), node (unavailable), quickjs
[youtube] Extracting URL: J3x_KSFtIM8
[youtube] J3x_KSFtIM8: Downloading webpage
[debug] [youtube] Forcing player 9f4cc5e4 in place of player 44899b31
        Forcing "tv" player JS variant for player 9f4cc5e4
        original url = /s/player/44899b31/player_es6.vflset/en_US/base.js
[youtube] J3x_KSFtIM8: Downloading android vr player API JSON
[debug] [youtube] J3x_KSFtIM8: android_vr player response playability status: UNPLAYABLE
[youtube] J3x_KSFtIM8: Downloading web embedded client config
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web_embedded client
[youtube] J3x_KSFtIM8: Downloading web embedded player API JSON
[debug] [youtube] J3x_KSFtIM8: web_embedded player response playability status: ERROR
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web client
[youtube] J3x_KSFtIM8: Downloading web player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 6s ad for web
[youtube] J3x_KSFtIM8: Downloading web safari player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 6s ad skippable after 5s for web_safari
[debug] Loading youtube-sigfuncs.9f4cc5e4-tv-105 from cache
[debug] Loading youtube-sigfuncs.9f4cc5e4-tv-101 from cache
[youtube] J3x_KSFtIM8: Downloading player 9f4cc5e4-tv
[youtube] [jsc:quickjs] Solving JS challenges using quickjs
[debug] [youtube] [jsc:quickjs] Using challenge solver lib script v0.5.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:quickjs] Using challenge solver core script v0.5.0 (source: python package, variant: minified)
WARNING: [youtube] [jsc:quickjs] QuickJS-NG is missing some optimizations making this very slow. Consider using upstream QuickJS instead.
[debug] [youtube] [jsc:quickjs] Running QuickJS: 'G:\Python\3.11.x\yt-dlp_on_py311\qjs.EXE' --script 'C:\Users\vaso\AppData\Local\Temp\tmpgei5g97c.js'
[debug] [youtube] J3x_KSFtIM8: Some web client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
[debug] [youtube] J3x_KSFtIM8: Some web_safari client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
[youtube] J3x_KSFtIM8: Downloading m3u8 information
[debug] [youtube] J3x_KSFtIM8: Some web client subtitles require a PO Token which was not provided. They will be discarded since they are not downloadable as-is. You can manually pass a Subtitles PO Token for this client with --extractor-args "youtube:po_token=web.subs+XXX" . For more information, refer to  https://github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide
[debug] Sort order given by extractor: quality, res, fps, hdr:12, source, vcodec, channels, acodec, lang, proto
[debug] Formats sorted by: hasvid, ie_pref, quality, res, fps, hdr:12(7), source, vcodec, channels, acodec, lang, proto, size, br, asr, vext, aext, hasaud, id
[info] Available formats for J3x_KSFtIM8:
ID  EXT   RESOLUTION FPS CH |    FILESIZE   TBR PROTO | VCODEC      ACODEC    ASR MORE INFO
------------------------------------------------------------------------------------------------
sb2 mhtml 48x27        0    |                   mhtml | images                    storyboard
sb1 mhtml 80x45        0    |                   mhtml | images                    storyboard
sb0 mhtml 160x90       0    |                   mhtml | images                    storyboard
91  mp4   256x144     30    | ~ 307.28MiB  213k m3u8  | avc1.4D400C mp4a.40.5     [en] WEB-S
92  mp4   426x240     30    | ~ 572.87MiB  396k m3u8  | avc1.4D4015 mp4a.40.5     [en] WEB-S
93  mp4   640x360     30    | ~   1.29GiB  912k m3u8  | avc1.4D401E mp4a.40.2     [en] WEB-S
18  mp4   640x360     30  2 | ≈1002.93MiB  694k https | avc1.42001E mp4a.40.2 44k [en] 360p, WEB
94  mp4   854x480     30    | ~   2.35GiB 1665k m3u8  | avc1.4D401F mp4a.40.2     [en] WEB-S
95  mp4   1280x720    30    | ~   4.07GiB 2885k m3u8  | avc1.64001F mp4a.40.2     [en] WEB-S
96  mp4   1920x1080   30    | ~   8.14GiB 5769k m3u8  | avc1.640028 mp4a.40.2     [en] WEB-S

In the hope this gets, eventually, fixed (before this PR is merged to master), thanks for your time and attention to this issue (which constitutes a deal-breaker here 😭 ) ...

Kind regards.

goto fail;
}
} else {
switch(ret) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please undo this change,

goto fail;
}
} else {
switch(rc) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please undo this change.

return JS_ThrowInternalError(ctx, "bad regexp bytecode");
}

if (is_be()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please undo this change.


JS_WriteString(s, regexp.pattern);

if (is_be()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please undo this change.

@saghul
Copy link
Contributor

saghul commented Mar 7, 2026

@Vangelis66 this PR has nothing to do with that. Please open a new issue.

@Vangelis66
Copy link

this PR has nothing to do with that.

With great respect, I beg to differ; it is only artifacts associated with/generated as tests for this specific PR (#1382) that are failing when used in conjunction with latest (master) yt-dlp code/binaries; for your convenience, below is a link to the latest yt-dlp master builds (for various OS and architectures), so you could test yourself and hopefully reconsider 😜 :

https://github.com/yt-dlp/yt-dlp-master-builds/releases/tag/2026.03.03.162040

I do wonder, though, whether this issue is specific to Windows and/or 32-bits...

Again, below several of my exhaustive tests:

  1. artifact https://github.com/quickjs-ng/quickjs/actions/runs/22729171576/artifacts/5783931130

corresponding to code snapshot quickjs-ng-v0.12.1-29-git-20260305-g75f7bbf (PR1382) :

yt-dlp --ies youtube -vF "J3x_KSFtIM8" --js quickjs
[debug] Command-line config: ['--ffmpeg-location', 'FFmpeg', '--downloader-args', 'ffmpeg_i:-hide_banner -v 8 -stats', '-vF', 'J3x_KSFtIM8', '--js', 'quickjs']
[debug] Encodings: locale cp1253, fs utf-8, pref cp1253, out utf-8 (No VT), error utf-8 (No VT), screen utf-8 (No VT)
[debug] yt-dlp version master@2026.03.03.162040 from yt-dlp/yt-dlp-master-builds [2ecc4c3bc] (zip)
[debug] Python 3.11.14 (CPython x86 32bit) - Windows-Vista-6.0.6003-SP2 (OpenSSL 3.6.1 27 Jan 2026)
[debug] exe versions: ffmpeg n8.1-dev-630-N-121254-g635cb45 (setts), ffprobe n8.1-dev-630-N-121254-g635cb45
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.02.25, mutagen-1.47.0, requests-2.32.5, sqlite3-3.52.0, urllib3-2.6.3, websockets-16.0, yt_dlp_ejs-0.5.0
[debug] JS runtimes: quickjs-ng-0.12.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Plugin directories: none
[debug] Loaded 1864 extractors
[debug] [youtube] [pot] PO Token Providers: none
[debug] [youtube] [pot] PO Token Cache Providers: memory
[debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
[debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno (unavailable), node (unavailable), quickjs
[youtube] Extracting URL: J3x_KSFtIM8
[youtube] J3x_KSFtIM8: Downloading webpage
[debug] [youtube] Forcing player 9f4cc5e4 in place of player 6c5cb4f4
        Forcing "tv" player JS variant for player 9f4cc5e4
        original url = /s/player/6c5cb4f4/player_es6.vflset/en_US/base.js
[youtube] J3x_KSFtIM8: Downloading android vr player API JSON
[debug] [youtube] J3x_KSFtIM8: android_vr player response playability status: UNPLAYABLE
[youtube] J3x_KSFtIM8: Downloading web embedded client config
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web_embedded client
[youtube] J3x_KSFtIM8: Downloading web embedded player API JSON
[debug] [youtube] J3x_KSFtIM8: web_embedded player response playability status: ERROR
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web client
[youtube] J3x_KSFtIM8: Downloading web player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 6s ad skippable after 5s for web
[youtube] J3x_KSFtIM8: Downloading web safari player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 10s ad skippable after 5s for web_safari
[debug] Loading youtube-sigfuncs.9f4cc5e4-tv-105 from cache
[debug] Loading youtube-sigfuncs.9f4cc5e4-tv-101 from cache
[youtube] J3x_KSFtIM8: Downloading player 9f4cc5e4-tv
[youtube] [jsc:quickjs] Solving JS challenges using quickjs
[debug] [youtube] [jsc:quickjs] Using challenge solver lib script v0.5.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:quickjs] Using challenge solver core script v0.5.0 (source: python package, variant: minified)
WARNING: [youtube] [jsc:quickjs] QuickJS-NG is missing some optimizations making this very slow. Consider using upstream QuickJS instead.
[debug] [youtube] [jsc:quickjs] Running QuickJS: 'G:\Python\3.11.x\yt-dlp_on_py311\qjs.EXE' --script 'C:\Users\<redacted>\AppData\Local\Temp\tmpxr2_9q3r.js'
WARNING: [youtube] [jsc] Error solving 2 challenge requests using "quickjs" provider: Error running QuickJS process (returncode: 1): TypeError: not a function
    at <anonymous> (C:\Users\<redacted>\AppData\Local\Temp\tmpxr2_9q3r.js:52:17442)
    at <eval> (C:\Users\<redacted>\AppData\Local\Temp\tmpxr2_9q3r.js:52:149149).
         requests = [JsChallengeRequest(type=<JsChallengeType.N: 'n'>, input=NChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=['ZtsCrTsRX0Pf1WhX4Uxe', 'enrC6ermp-LsEY82vB3d', 'n2O-SxnLSEPPpmZcatd2']), video_id='J3x_KSFtIM8'), JsChallengeRequest(type=<JsChallengeType.SIG: 'sig'>, input=SigChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=[]), video_id='J3x_KSFtIM8')]
         Please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
WARNING: [youtube] J3x_KSFtIM8: n challenge solving failed: Some formats may be missing. Ensure you have a supported JavaScript runtime and challenge solver script distribution installed. Review any warnings presented before this message. For more details, refer to  https://github.com/yt-dlp/yt-dlp/wiki/EJS
[debug] [youtube] J3x_KSFtIM8: Some web client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
[debug] [youtube] J3x_KSFtIM8: Some web_safari client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
ERROR: [youtube] J3x_KSFtIM8: This video is not available
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\common.py", line 765, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\youtube\_video.py", line 4026, in _real_extract
    self.raise_no_formats(reason, expected=True)
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\common.py", line 1277, in raise_no_formats
    raise ExtractorError(msg, expected=expected, video_id=video_id)
  1. Latest artifact from PR1382, which is

https://github.com/quickjs-ng/quickjs/actions/runs/22801151615/artifacts/5811738416

corresponding to code snapshot:

quickjs-ng-v0.12.1-31-git-20260307-g3b3bb60:

yt-dlp --ies youtube -vF "J3x_KSFtIM8" --js quickjs
[debug] Command-line config: ['--ffmpeg-location', 'FFmpeg', '--downloader-args', 'ffmpeg_i:-hide_banner -v 8 -stats', '--ies', 'youtube', '-vF', 'J3x_KSFtIM8', '--js', 'quickjs']
[debug] Encodings: locale cp1253, fs utf-8, pref cp1253, out utf-8 (No VT), error utf-8 (No VT), screen utf-8 (No VT)
[debug] yt-dlp version master@2026.03.03.162040 from yt-dlp/yt-dlp-master-builds [2ecc4c3bc] (zip)
[debug] Python 3.11.14 (CPython x86 32bit) - Windows-Vista-6.0.6003-SP2 (OpenSSL 3.6.1 27 Jan 2026)
[debug] exe versions: ffmpeg n8.1-dev-630-N-121254-g635cb45 (setts), ffprobe n8.1-dev-630-N-121254-g635cb45
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.02.25, mutagen-1.47.0, requests-2.32.5, sqlite3-3.52.0, urllib3-2.6.3, websockets-16.0, yt_dlp_ejs-0.5.0
[debug] JS runtimes: quickjs-ng-0.12.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Plugin directories: none
[debug] Loaded 1 extractors
[debug] [youtube] [pot] PO Token Providers: none
[debug] [youtube] [pot] PO Token Cache Providers: memory
[debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
[debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno (unavailable), node (unavailable), quickjs
[youtube] Extracting URL: J3x_KSFtIM8
[youtube] J3x_KSFtIM8: Downloading webpage
[debug] [youtube] Forcing player 9f4cc5e4 in place of player 6c5cb4f4
        Forcing "tv" player JS variant for player 9f4cc5e4
        original url = /s/player/6c5cb4f4/player_es6.vflset/en_US/base.js
[youtube] J3x_KSFtIM8: Downloading android vr player API JSON
[debug] [youtube] J3x_KSFtIM8: android_vr player response playability status: UNPLAYABLE
[youtube] J3x_KSFtIM8: Downloading web embedded client config
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web_embedded client
[youtube] J3x_KSFtIM8: Downloading web embedded player API JSON
[debug] [youtube] J3x_KSFtIM8: web_embedded player response playability status: ERROR
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web client
[youtube] J3x_KSFtIM8: Downloading web player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 10s ad skippable after 5s for web
[youtube] J3x_KSFtIM8: Downloading web safari player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 6s ad skippable after 5s for web_safari
[debug] Loading youtube-sigfuncs.9f4cc5e4-tv-105 from cache
[youtube] J3x_KSFtIM8: Downloading player 9f4cc5e4-tv
[youtube] [jsc:quickjs] Solving JS challenges using quickjs
[debug] [youtube] [jsc:quickjs] Using challenge solver lib script v0.5.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:quickjs] Using challenge solver core script v0.5.0 (source: python package, variant: minified)
WARNING: [youtube] [jsc:quickjs] QuickJS-NG is missing some optimizations making this very slow. Consider using upstream QuickJS instead.
[debug] [youtube] [jsc:quickjs] Running QuickJS: 'G:\Python\3.11.x\yt-dlp_on_py311\qjs.EXE' --script 'C:\Users\<redacted>\AppData\Local\Temp\tmp1nw04pgw.js'
WARNING: [youtube] [jsc] Error solving 2 challenge requests using "quickjs" provider: Error running QuickJS process (returncode: 1): TypeError: not a function
    at <anonymous> (C:\Users\<redacted>\AppData\Local\Temp\tmp1nw04pgw.js:52:17442)
    at <eval> (C:\Users\<redacted>\AppData\Local\Temp\tmp1nw04pgw.js:52:149149).
         requests = [JsChallengeRequest(type=<JsChallengeType.N: 'n'>, input=NChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=['3eC0-y1exvx1xzI-nSJU', 'OKccBCLrddY4dfvkurmC', 'lUU_mMSMGFLQFuddFWyu']), video_id='J3x_KSFtIM8'), JsChallengeRequest(type=<JsChallengeType.SIG: 'sig'>, input=SigChallengeInput(player_url='https://www.youtube.com/s/player/9f4cc5e4/tv-player-ias.vflset/tv-player-ias.js', challenges=[]), video_id='J3x_KSFtIM8')]
         Please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
WARNING: [youtube] J3x_KSFtIM8: n challenge solving failed: Some formats may be missing. Ensure you have a supported JavaScript runtime and challenge solver script distribution installed. Review any warnings presented before this message. For more details, refer to  https://github.com/yt-dlp/yt-dlp/wiki/EJS
[debug] [youtube] J3x_KSFtIM8: Some web client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
[debug] [youtube] J3x_KSFtIM8: Some web_safari client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
ERROR: [youtube] J3x_KSFtIM8: This video is not available
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\common.py", line 765, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\youtube\_video.py", line 4026, in _real_extract
    self.raise_no_formats(reason, expected=True)
  File "G:\Python\3.11.x\yt-dlp_on_py311\\yt-dlp\yt_dlp\extractor\common.py", line 1277, in raise_no_formats
    raise ExtractorError(msg, expected=expected, video_id=video_id)
  1. Any other artifact NOT derived from PR1382, e.g. latest artifact

https://github.com/quickjs-ng/quickjs/actions/runs/22798525899/artifacts/5811060700

derived from your latest PR #1389, corresponding to code snapshot quickjs-ng-v0.12.1-29-git-20260307-gac7b389:

yt-dlp --ies youtube -vF "J3x_KSFtIM8" --js quickjs
[debug] Command-line config: ['--ffmpeg-location', 'FFmpeg', '--downloader-args', 'ffmpeg_i:-hide_banner -v 8 -stats', '--ies', 'youtube', '-vF', 'J3x_KSFtIM8', '--js', 'quickjs']
[debug] Encodings: locale cp1253, fs utf-8, pref cp1253, out utf-8 (No VT), error utf-8 (No VT), screen utf-8 (No VT)
[debug] yt-dlp version master@2026.03.03.162040 from yt-dlp/yt-dlp-master-builds [2ecc4c3bc] (zip)
[debug] Python 3.11.14 (CPython x86 32bit) - Windows-Vista-6.0.6003-SP2 (OpenSSL 3.6.1 27 Jan 2026)
[debug] exe versions: ffmpeg n8.1-dev-630-N-121254-g635cb45 (setts), ffprobe n8.1-dev-630-N-121254-g635cb45
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.02.25, mutagen-1.47.0, requests-2.32.5, sqlite3-3.52.0, urllib3-2.6.3, websockets-16.0, yt_dlp_ejs-0.5.0
[debug] JS runtimes: quickjs-ng-0.12.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Plugin directories: none
[debug] Loaded 1 extractors
[debug] [youtube] [pot] PO Token Providers: none
[debug] [youtube] [pot] PO Token Cache Providers: memory
[debug] [youtube] [pot] PO Token Cache Spec Providers: webpo
[debug] [youtube] [jsc] JS Challenge Providers: bun (unavailable), deno (unavailable), node (unavailable), quickjs
[youtube] Extracting URL: J3x_KSFtIM8
[youtube] J3x_KSFtIM8: Downloading webpage
[debug] [youtube] Forcing player 9f4cc5e4 in place of player 6c5cb4f4
        Forcing "tv" player JS variant for player 9f4cc5e4
        original url = /s/player/6c5cb4f4/player_es6.vflset/en_US/base.js
[youtube] J3x_KSFtIM8: Downloading android vr player API JSON
[debug] [youtube] J3x_KSFtIM8: android_vr player response playability status: UNPLAYABLE
[youtube] J3x_KSFtIM8: Downloading web embedded client config
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web_embedded client
[youtube] J3x_KSFtIM8: Downloading web embedded player API JSON
[debug] [youtube] J3x_KSFtIM8: web_embedded player response playability status: ERROR
[debug] [youtube] J3x_KSFtIM8: Detected experiment to bind GVS PO Token to video ID for web client
[youtube] J3x_KSFtIM8: Downloading web player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 15s ad skippable after 5s for web
[youtube] J3x_KSFtIM8: Downloading web safari player API JSON
[debug] [youtube] J3x_KSFtIM8: Detected a 6s ad skippable after 5s for web_safari
[debug] Loading youtube-sigfuncs.9f4cc5e4-tv-105 from cache
[youtube] J3x_KSFtIM8: Downloading player 9f4cc5e4-tv
[youtube] [jsc:quickjs] Solving JS challenges using quickjs
[debug] [youtube] [jsc:quickjs] Using challenge solver lib script v0.5.0 (source: python package, variant: minified)
[debug] [youtube] [jsc:quickjs] Using challenge solver core script v0.5.0 (source: python package, variant: minified)
WARNING: [youtube] [jsc:quickjs] QuickJS-NG is missing some optimizations making this very slow. Consider using upstream QuickJS instead.
[debug] [youtube] [jsc:quickjs] Running QuickJS: 'G:\Python\3.11.x\yt-dlp_on_py311\qjs.EXE' --script 'C:\Users\<redacted>\AppData\Local\Temp\tmp3cb9ykfs.js'
[debug] [youtube] J3x_KSFtIM8: Some web client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
[debug] [youtube] J3x_KSFtIM8: Some web_safari client https formats have been skipped as they are missing a URL. YouTube is forcing SABR streaming for this client. See  https://github.com/yt-dlp/yt-dlp/issues/12482  for more details
[youtube] J3x_KSFtIM8: Downloading m3u8 information
[debug] [youtube] J3x_KSFtIM8: Some web client subtitles require a PO Token which was not provided. They will be discarded since they are not downloadable as-is. You can manually pass a Subtitles PO Token for this client with --extractor-args "youtube:po_token=web.subs+XXX" . For more information, refer to  https://github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide
[debug] Sort order given by extractor: quality, res, fps, hdr:12, source, vcodec, channels, acodec, lang, proto
[debug] Formats sorted by: hasvid, ie_pref, quality, res, fps, hdr:12(7), source, vcodec, channels, acodec, lang, proto, size, br, asr, vext, aext, hasaud, id
[info] Available formats for J3x_KSFtIM8:
ID  EXT   RESOLUTION FPS CH |    FILESIZE   TBR PROTO | VCODEC      ACODEC    ASR MORE INFO
------------------------------------------------------------------------------------------------
sb2 mhtml 48x27        0    |                   mhtml | images                    storyboard
sb1 mhtml 80x45        0    |                   mhtml | images                    storyboard
sb0 mhtml 160x90       0    |                   mhtml | images                    storyboard
91  mp4   256x144     30    | ~ 307.28MiB  213k m3u8  | avc1.4D400C mp4a.40.5     [en] WEB-S
92  mp4   426x240     30    | ~ 572.87MiB  396k m3u8  | avc1.4D4015 mp4a.40.5     [en] WEB-S
93  mp4   640x360     30    | ~   1.29GiB  912k m3u8  | avc1.4D401E mp4a.40.2     [en] WEB-S
18  mp4   640x360     30  2 | ≈1002.93MiB  694k https | avc1.42001E mp4a.40.2 44k [en] 360p, WEB
94  mp4   854x480     30    | ~   2.35GiB 1665k m3u8  | avc1.4D401F mp4a.40.2     [en] WEB-S
95  mp4   1280x720    30    | ~   4.07GiB 2885k m3u8  | avc1.64001F mp4a.40.2     [en] WEB-S
96  mp4   1920x1080   30    | ~   8.14GiB 5769k m3u8  | avc1.640028 mp4a.40.2     [en] WEB-S

i.e. success...

So, to re-iterate, don't ask me why or how (can't code myself), but this PR is definitely behind quickjs-ng's failures (using the Win 32-bit binary here) when used as a JS runtime for yt-dlp purposes...

@MulverineX, can you please test on your side?

Thanks for your time and attention.

@bnoordhuis
Copy link
Contributor

Why are you testing yt-dlp against a pull request that hasn't been merged yet?

@saghul
Copy link
Contributor

saghul commented Mar 7, 2026

Not only that, but one that isn't event green in the CI.

@MulverineX
Copy link

@Vangelis66 it is very unlikely that any future optimizations will significantly impact the innertube JS challenge execution time. QuickJS is already a very well optimized engine for its size, most remaining possible optimizations are small and for specific code paths that are probably not hit by the JS challenge.

I don't recommend testing against every PR in hopes that it will magically improve, and you should avoid reporting issues on such a WIP PR. Wait until this gets merged, then test for regressions.

@Vangelis66
Copy link

Thank you all for your input, especially MulverineX 😄 ...

Some answers (again) and a couple of questions...

Why are you testing yt-dlp against a pull request that hasn't been merged yet?

As I already wrote:

My main/unique use case of quickjs-ng is in the context of yt-dlp, as a JS runtime to solve YouTube's complex JS challenges (YT-player's n/sig); ( ... )
In that context, I routinely check quickjs-ng binary artifacts from here:

quickjs-ng/quickjs/actions/workflows/release.yml

in the hope recent PRs improve even more the performance in solving YT's JS challenges

But since I was told that:

it is very unlikely that any future optimizations will significantly impact the innertube JS challenge execution time

... it appears this is a moot point?

In any case, my "tests" are also "preemptive", in the sense I want(ed) to check whether new quickjs-ng code would break my only use case for the app (in the context of yt-dlp); and this is what happened here: every GH artifact so far related to #1382 has broken the app for me; and I refuse to believe this is just a coincidence; the error the app generates,

WARNING: [youtube] [jsc] Error solving 2 challenge requests using "quickjs" provider: Error running QuickJS process (returncode: 1): TypeError: not a function

(TypeError: not a function) is mentioned in this PR's first post...

and you should avoid reporting issues on such a WIP PR.

My thought was: "Why not catch (and hopefully fix) the error before this PR gets merged" ? But I see what you mean...

Wait until this gets merged, then test for regressions.

Well, let's just say I have strong indications already this PR, in its current form, breaks the app when used in yt-dlp; I personally hope it won't, but should the issue continue after this PR gets merged to master, when will it be a proper time to create a new ticket for it? I'm not in a position here to compile the master code into a 32-bit .exe binary, so I'm gonna have again to rely on some other future GH artifact that has #1382 already merged; will you accept that? Or should I wait for when a new release (after v0.12.1) has been published?

Let me assure you all, and especially the main devs, that I'm not some kind of spammer/troll, I generally respect GH's netiquette and I again apologise if my presence here broke, in some way, your workflow; your coding efforts, as with every other open source project, are highly appreciated/treasured ❤️ ...

Kindest regards.

@MulverineX
Copy link

MulverineX commented Mar 8, 2026

@Vangelis66 once the PR is merged you can use the final PR build artifact to test

it appears this is a moot point?

no, because again, you are not helping the maintainers by commenting on this PR before it is done

@speedskater1610
Copy link
Contributor Author

@Vangelis66 I would use a PR that doesnt even have a passing CI isn't ready to be tested outside of the scope of the PR.

@speedskater1610
Copy link
Contributor Author

@saghul or @bnoordhuis I ma exremely confused on why the CI is failing, obviously the main issue is that test262 is failing, do I need to regenerate the gen/*.c files in order for it to pass? I have been slamming my head against my desk for some time now and finally decided to ask for some help.

@saghul
Copy link
Contributor

saghul commented Mar 10, 2026

Some merge went wrong in your tree and you are partially undoing some of the latest fixes, in master, which trip the CI. I'd suggest you rebase (not merge) with master, and check your diff, then undo any spurious changes not related to yours, and force-push.

Added last_var_atom to JSRuntime and JSClass structures to store the last accessed variable atom for improved error messages. Updated various functions to utilize last_var_atom for more informative error handling.
Added validity checks before storing atom for error messages.
…e [success] from debugging prints

ensures that any modifications to rt->last_var_atom during the function are temporary and don't leave dangling references after the function returns.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants