diff options
author | Simon Sawicki <contact@grub4k.xyz> | 2025-02-08 18:48:36 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-08 18:48:36 +0100 |
commit | 0d9f061d38c3a4da61972e2adad317079f2f1c84 (patch) | |
tree | 0ff1a9086dafda40ee62013aed2d19cd58017218 /yt_dlp/jsinterp.py | |
parent | 517ddf3c3f12560ab93e3d36244dc82db9f97818 (diff) |
[jsinterp] Add `js_number_to_string` (#12110)
Authored by: Grub4K
Diffstat (limited to 'yt_dlp/jsinterp.py')
-rw-r--r-- | yt_dlp/jsinterp.py | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/yt_dlp/jsinterp.py b/yt_dlp/jsinterp.py index ba059babb..bd6a47004 100644 --- a/yt_dlp/jsinterp.py +++ b/yt_dlp/jsinterp.py @@ -95,6 +95,61 @@ def _js_ternary(cndn, if_true=True, if_false=False): return if_true +# Ref: https://es5.github.io/#x9.8.1 +def js_number_to_string(val: float, radix: int = 10): + if radix in (JS_Undefined, None): + radix = 10 + assert radix in range(2, 37), 'radix must be an integer at least 2 and no greater than 36' + + if math.isnan(val): + return 'NaN' + if val == 0: + return '0' + if math.isinf(val): + return '-Infinity' if val < 0 else 'Infinity' + if radix == 10: + # TODO: implement special cases + ... + + ALPHABET = b'0123456789abcdefghijklmnopqrstuvwxyz.-' + + result = collections.deque() + sign = val < 0 + val = abs(val) + fraction, integer = math.modf(val) + delta = max(math.nextafter(.0, math.inf), math.ulp(val) / 2) + + if fraction >= delta: + result.append(-2) # `.` + while fraction >= delta: + delta *= radix + fraction, digit = math.modf(fraction * radix) + result.append(int(digit)) + # if we need to round, propagate potential carry through fractional part + needs_rounding = fraction > 0.5 or (fraction == 0.5 and int(digit) & 1) + if needs_rounding and fraction + delta > 1: + for index in reversed(range(1, len(result))): + if result[index] + 1 < radix: + result[index] += 1 + break + result.pop() + + else: + integer += 1 + break + + integer, digit = divmod(int(integer), radix) + result.appendleft(digit) + while integer > 0: + integer, digit = divmod(integer, radix) + result.appendleft(digit) + + if sign: + result.appendleft(-1) # `-` + + return bytes(ALPHABET[digit] for digit in result).decode('ascii') + + # Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence _OPERATORS = { # None => Defined in JSInterpreter._operator '?': None, |