This makes _extract_js_function a true “last-resort” parser while the normal path keeps depending on JSInterpreter.extract_function_code.
- _fixup_n_function_code now tries to extract helper signatures with JSInterpreter(jscode).extract_function_code(...) first; only when that raises JSInterpreter.Exception do we fall back to the legacy _extract_js_function(...) string parser. Successful inlines keep the existing debug and caching behaviour (yt_dlp/extractor/youtube/_video.py:2416-2440).
- _extract_js_function is reduced to a pure fallback: it parses var|let|const foo = function(...) {...} with a regex and no longer re-enters JSInterpreter, avoiding duplicated work (yt_dlp/extractor/youtube/_video.py around line 2449).
Global Helper Inline Loop
We also rely on the while True retry loop inside _fixup_n_function_code to progressively inline missing dependencies:
1. Execute the candidate nsig implementation via JSInterpreter. If nothing is missing, the loop exits immediately.
2. When execution raises errors such as “Could not find object CI”, we capture the helper name from the message, extract that helper (CI, OB5, nq5, …), and prepend var helper = function(...) { ... }; to fixed_code.
3. With the helper injected we retry the interpreter; if another dependency is missing we repeat this process until no more Could not find … errors occur (or an unhandled exception surfaces).
4. After the loop, any residual names collected in jsi._undefined_varnames are handled by the follow-up for func_name in global_funcnames: pass, which inlines whatever helpers the interpreter still flagged.
Together these steps guarantee that all global functions referenced by the nsig routine are made available before execution, giving the interpreter a stable environment even when YouTube reshuffles helper definitions.