aboutsummaryrefslogtreecommitdiffhomepage
path: root/youtube_dl
diff options
context:
space:
mode:
authordirkf <[email protected]>2024-12-12 00:15:31 +0000
committerdirkf <[email protected]>2024-12-16 12:38:51 +0000
commit81e64cacf2b8c144ec1e9d3258db792f0eb8443e (patch)
tree57c76ed55d4a17fa607fc84f279d25fc7b2c2836 /youtube_dl
parentc1a03b1ac3a453508b358b6d1bc5d158cc80a0ce (diff)
downloadyoutube-dl-81e64cacf2b8c144ec1e9d3258db792f0eb8443e.tar.gz
youtube-dl-81e64cacf2b8c144ec1e9d3258db792f0eb8443e.zip
[jsinterp] Support multiple indexing (eg a[1][2])
* extend single indexing with improved RE (should probably use/have used _separate_at_paren()) * fix some cases that should have given undefined, not throwing * standardise RE group names * support length of objects, like {1: 2, 3: 4, length: 42}
Diffstat (limited to 'youtube_dl')
-rw-r--r--youtube_dl/jsinterp.py37
1 files changed, 22 insertions, 15 deletions
diff --git a/youtube_dl/jsinterp.py b/youtube_dl/jsinterp.py
index b7a3ef69a..248210ce4 100644
--- a/youtube_dl/jsinterp.py
+++ b/youtube_dl/jsinterp.py
@@ -549,13 +549,14 @@ class JSInterpreter(object):
except Exception as e:
raise self.Exception('Failed to evaluate {left_val!r:.50} {op} {right_val!r:.50}'.format(**locals()), expr, cause=e)
- def _index(self, obj, idx, allow_undefined=False):
- if idx == 'length':
+ def _index(self, obj, idx, allow_undefined=True):
+ if idx == 'length' and isinstance(obj, list):
return len(obj)
try:
- return obj[int(idx)] if isinstance(obj, list) else obj[idx]
- except Exception as e:
+ return obj[int(idx)] if isinstance(obj, list) else obj[compat_str(idx)]
+ except (TypeError, KeyError, IndexError) as e:
if allow_undefined:
+ # when is not allowed?
return JS_Undefined
raise self.Exception('Cannot get index {idx!r:.100}'.format(**locals()), expr=repr(obj), cause=e)
@@ -882,13 +883,13 @@ class JSInterpreter(object):
m = re.match(r'''(?x)
(?P<assign>
- (?P<out>{_NAME_RE})(?:\[(?P<index>[^\]]+?)\])?\s*
+ (?P<out>{_NAME_RE})(?:\[(?P<out_idx>(?:.+?\]\s*\[)*.+?)\])?\s*
(?P<op>{_OPERATOR_RE})?
=(?!=)(?P<expr>.*)$
)|(?P<return>
(?!if|return|true|false|null|undefined|NaN|Infinity)(?P<name>{_NAME_RE})$
)|(?P<indexing>
- (?P<in>{_NAME_RE})\[(?P<idx>.+)\]$
+ (?P<in>{_NAME_RE})\[(?P<in_idx>(?:.+?\]\s*\[)*.+?)\]$
)|(?P<attribute>
(?P<var>{_NAME_RE})(?:(?P<nullish>\?)?\.(?P<member>[^(]+)|\[(?P<member2>[^\]]+)\])\s*
)|(?P<function>
@@ -898,19 +899,23 @@ class JSInterpreter(object):
if md.get('assign'):
left_val = local_vars.get(m.group('out'))
- if not m.group('index'):
+ if not m.group('out_idx'):
local_vars[m.group('out')] = self._operator(
m.group('op'), left_val, m.group('expr'), expr, local_vars, allow_recursion)
return local_vars[m.group('out')], should_return
elif left_val in (None, JS_Undefined):
raise self.Exception('Cannot index undefined variable ' + m.group('out'), expr=expr)
- idx = self.interpret_expression(m.group('index'), local_vars, allow_recursion)
- if not isinstance(idx, (int, float)):
- raise self.Exception('List index %s must be integer' % (idx, ), expr=expr)
- idx = int(idx)
+ indexes = re.split(r'\]\s*\[', m.group('out_idx'))
+ for i, idx in enumerate(indexes, 1):
+ idx = self.interpret_expression(idx, local_vars, allow_recursion)
+ if i < len(indexes):
+ left_val = self._index(left_val, idx)
+ if isinstance(idx, float):
+ idx = int(idx)
left_val[idx] = self._operator(
- m.group('op'), self._index(left_val, idx), m.group('expr'), expr, local_vars, allow_recursion)
+ m.group('op'), self._index(left_val, idx) if m.group('op') else None,
+ m.group('expr'), expr, local_vars, allow_recursion)
return left_val[idx], should_return
elif expr.isdigit():
@@ -939,8 +944,10 @@ class JSInterpreter(object):
if md.get('indexing'):
val = local_vars[m.group('in')]
- idx = self.interpret_expression(m.group('idx'), local_vars, allow_recursion)
- return self._index(val, idx), should_return
+ for idx in re.split(r'\]\s*\[', m.group('in_idx')):
+ idx = self.interpret_expression(idx, local_vars, allow_recursion)
+ val = self._index(val, idx)
+ return val, should_return
op_result = self.handle_operators(expr, local_vars, allow_recursion)
if op_result:
@@ -989,7 +996,7 @@ class JSInterpreter(object):
# Member access
if arg_str is None:
- return self._index(obj, member, nullish)
+ return self._index(obj, member)
# Function call
argvals = [