mirror of
https://github.com/ytdl-org/youtube-dl
synced 2024-12-16 06:27:00 +00:00
[jsinterp] Fix and improve "methods"
* push, unshift return new length * impove edge cases for push/pop, shift/unshift, forEach, indexOf, charCodeAt * increase test coverage
This commit is contained in:
parent
57b0e045d4
commit
8e172670f4
@ -542,6 +542,40 @@ class TestJSInterpreter(unittest.TestCase):
|
|||||||
self._test('function f(){return "012345678".slice(-1, 1)}', '')
|
self._test('function f(){return "012345678".slice(-1, 1)}', '')
|
||||||
self._test('function f(){return "012345678".slice(-3, -1)}', '67')
|
self._test('function f(){return "012345678".slice(-3, -1)}', '67')
|
||||||
|
|
||||||
|
def test_pop(self):
|
||||||
|
# pop
|
||||||
|
self._test('function f(){var a = [0, 1, 2, 3, 4, 5, 6, 7, 8]; return [a.pop(), a]}',
|
||||||
|
[8, [0, 1, 2, 3, 4, 5, 6, 7]])
|
||||||
|
self._test('function f(){return [].pop()}', JS_Undefined)
|
||||||
|
# push
|
||||||
|
self._test('function f(){var a = [0, 1, 2]; return [a.push(3, 4), a]}',
|
||||||
|
[5, [0, 1, 2, 3, 4]])
|
||||||
|
self._test('function f(){var a = [0, 1, 2]; return [a.push(), a]}',
|
||||||
|
[3, [0, 1, 2]])
|
||||||
|
|
||||||
|
def test_shift(self):
|
||||||
|
# shift
|
||||||
|
self._test('function f(){var a = [0, 1, 2, 3, 4, 5, 6, 7, 8]; return [a.shift(), a]}',
|
||||||
|
[0, [1, 2, 3, 4, 5, 6, 7, 8]])
|
||||||
|
self._test('function f(){return [].shift()}', JS_Undefined)
|
||||||
|
# unshift
|
||||||
|
self._test('function f(){var a = [0, 1, 2]; return [a.unshift(3, 4), a]}',
|
||||||
|
[5, [3, 4, 0, 1, 2]])
|
||||||
|
self._test('function f(){var a = [0, 1, 2]; return [a.unshift(), a]}',
|
||||||
|
[3, [0, 1, 2]])
|
||||||
|
|
||||||
|
def test_forEach(self):
|
||||||
|
self._test('function f(){var ret = []; var l = [4, 2]; '
|
||||||
|
'var log = function(e,i,a){ret.push([e,i,a]);}; '
|
||||||
|
'l.forEach(log); '
|
||||||
|
'return [ret.length, ret[0][0], ret[1][1], ret[0][2]]}',
|
||||||
|
[2, 4, 1, [4, 2]])
|
||||||
|
self._test('function f(){var ret = []; var l = [4, 2]; '
|
||||||
|
'var log = function(e,i,a){this.push([e,i,a]);}; '
|
||||||
|
'l.forEach(log, ret); '
|
||||||
|
'return [ret.length, ret[0][0], ret[1][1], ret[0][2]]}',
|
||||||
|
[2, 4, 1, [4, 2]])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -1113,37 +1113,31 @@ class JSInterpreter(object):
|
|||||||
index, how_many = map(int, (argvals + [len(obj)])[:2])
|
index, how_many = map(int, (argvals + [len(obj)])[:2])
|
||||||
if index < 0:
|
if index < 0:
|
||||||
index += len(obj)
|
index += len(obj)
|
||||||
add_items = argvals[2:]
|
res = [obj.pop(index)
|
||||||
res = []
|
for _ in range(index, min(index + how_many, len(obj)))]
|
||||||
for _ in range(index, min(index + how_many, len(obj))):
|
obj[index:index] = argvals[2:]
|
||||||
res.append(obj.pop(index))
|
|
||||||
for i, item in enumerate(add_items):
|
|
||||||
obj.insert(index + i, item)
|
|
||||||
return res
|
return res
|
||||||
elif member == 'unshift':
|
elif member in ('shift', 'pop'):
|
||||||
assertion(isinstance(obj, list), 'must be applied on a list')
|
|
||||||
assertion(argvals, 'takes one or more arguments')
|
|
||||||
for item in reversed(argvals):
|
|
||||||
obj.insert(0, item)
|
|
||||||
return obj
|
|
||||||
elif member == 'pop':
|
|
||||||
assertion(isinstance(obj, list), 'must be applied on a list')
|
assertion(isinstance(obj, list), 'must be applied on a list')
|
||||||
assertion(not argvals, 'does not take any arguments')
|
assertion(not argvals, 'does not take any arguments')
|
||||||
if not obj:
|
return obj.pop(0 if member == 'shift' else -1) if len(obj) > 0 else JS_Undefined
|
||||||
return
|
elif member == 'unshift':
|
||||||
return obj.pop()
|
assertion(isinstance(obj, list), 'must be applied on a list')
|
||||||
|
# not enforced: assertion(argvals, 'takes one or more arguments')
|
||||||
|
obj[0:0] = argvals
|
||||||
|
return len(obj)
|
||||||
elif member == 'push':
|
elif member == 'push':
|
||||||
assertion(argvals, 'takes one or more arguments')
|
# not enforced: assertion(argvals, 'takes one or more arguments')
|
||||||
obj.extend(argvals)
|
obj.extend(argvals)
|
||||||
return obj
|
return len(obj)
|
||||||
elif member == 'forEach':
|
elif member == 'forEach':
|
||||||
assertion(argvals, 'takes one or more arguments')
|
assertion(argvals, 'takes one or more arguments')
|
||||||
assertion(len(argvals) <= 2, 'takes at-most 2 arguments')
|
assertion(len(argvals) <= 2, 'takes at most 2 arguments')
|
||||||
f, this = (argvals + [''])[:2]
|
f, this = (argvals + [''])[:2]
|
||||||
return [f((item, idx, obj), {'this': this}, allow_recursion) for idx, item in enumerate(obj)]
|
return [f((item, idx, obj), {'this': this}, allow_recursion) for idx, item in enumerate(obj)]
|
||||||
elif member == 'indexOf':
|
elif member == 'indexOf':
|
||||||
assertion(argvals, 'takes one or more arguments')
|
assertion(argvals, 'takes one or more arguments')
|
||||||
assertion(len(argvals) <= 2, 'takes at-most 2 arguments')
|
assertion(len(argvals) <= 2, 'takes at most 2 arguments')
|
||||||
idx, start = (argvals + [0])[:2]
|
idx, start = (argvals + [0])[:2]
|
||||||
try:
|
try:
|
||||||
return obj.index(idx, start)
|
return obj.index(idx, start)
|
||||||
@ -1152,7 +1146,7 @@ class JSInterpreter(object):
|
|||||||
elif member == 'charCodeAt':
|
elif member == 'charCodeAt':
|
||||||
assertion(isinstance(obj, compat_str), 'must be applied on a string')
|
assertion(isinstance(obj, compat_str), 'must be applied on a string')
|
||||||
# assertion(len(argvals) == 1, 'takes exactly one argument') # but not enforced
|
# assertion(len(argvals) == 1, 'takes exactly one argument') # but not enforced
|
||||||
idx = argvals[0] if isinstance(argvals[0], int) else 0
|
idx = argvals[0] if len(argvals) > 0 and isinstance(argvals[0], int) else 0
|
||||||
if idx >= len(obj):
|
if idx >= len(obj):
|
||||||
return None
|
return None
|
||||||
return ord(obj[idx])
|
return ord(obj[idx])
|
||||||
|
Loading…
Reference in New Issue
Block a user