mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 14:45:14 +00:00 
			
		
		
		
	[swfinterp] Add more builtins and improve static variables
This commit is contained in:
		
							
								
								
									
										18
									
								
								test/swftests/ConstArrayAccess.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								test/swftests/ConstArrayAccess.as
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | // input: [] | ||||||
|  | // output: 4 | ||||||
|  |  | ||||||
|  | package { | ||||||
|  | public class ConstArrayAccess { | ||||||
|  | 	private static const x:int = 2; | ||||||
|  | 	private static const ar:Array = ["42", "3411"]; | ||||||
|  |  | ||||||
|  |     public static function main():int{ | ||||||
|  |         var c:ConstArrayAccess = new ConstArrayAccess(); | ||||||
|  |         return c.f(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function f(): int { | ||||||
|  |     	return ar[1].length; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | } | ||||||
| @@ -62,13 +62,14 @@ class _ScopeDict(dict): | |||||||
|  |  | ||||||
|  |  | ||||||
| class _AVMClass(object): | class _AVMClass(object): | ||||||
|     def __init__(self, name_idx, name): |     def __init__(self, name_idx, name, static_properties=None): | ||||||
|         self.name_idx = name_idx |         self.name_idx = name_idx | ||||||
|         self.name = name |         self.name = name | ||||||
|         self.method_names = {} |         self.method_names = {} | ||||||
|         self.method_idxs = {} |         self.method_idxs = {} | ||||||
|         self.methods = {} |         self.methods = {} | ||||||
|         self.method_pyfunctions = {} |         self.method_pyfunctions = {} | ||||||
|  |         self.static_properties = static_properties if static_properties else {} | ||||||
|  |  | ||||||
|         self.variables = _ScopeDict(self) |         self.variables = _ScopeDict(self) | ||||||
|         self.constants = {} |         self.constants = {} | ||||||
| @@ -151,15 +152,20 @@ def _read_byte(reader): | |||||||
|  |  | ||||||
| StringClass = _AVMClass('(no name idx)', 'String') | StringClass = _AVMClass('(no name idx)', 'String') | ||||||
| ByteArrayClass = _AVMClass('(no name idx)', 'ByteArray') | ByteArrayClass = _AVMClass('(no name idx)', 'ByteArray') | ||||||
|  | TimerClass = _AVMClass('(no name idx)', 'Timer') | ||||||
|  | TimerEventClass = _AVMClass('(no name idx)', 'TimerEvent', {'TIMER': 'timer'}) | ||||||
| _builtin_classes = { | _builtin_classes = { | ||||||
|     StringClass.name: StringClass, |     StringClass.name: StringClass, | ||||||
|     ByteArrayClass.name: ByteArrayClass, |     ByteArrayClass.name: ByteArrayClass, | ||||||
|  |     TimerClass.name: TimerClass, | ||||||
|  |     TimerEventClass.name: TimerEventClass, | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| class _Undefined(object): | class _Undefined(object): | ||||||
|     def __boolean__(self): |     def __bool__(self): | ||||||
|         return False |         return False | ||||||
|  |     __nonzero__ = __bool__ | ||||||
|  |  | ||||||
|     def __hash__(self): |     def __hash__(self): | ||||||
|         return 0 |         return 0 | ||||||
| @@ -169,7 +175,9 @@ undefined = _Undefined() | |||||||
|  |  | ||||||
| class SWFInterpreter(object): | class SWFInterpreter(object): | ||||||
|     def __init__(self, file_contents): |     def __init__(self, file_contents): | ||||||
|         self._patched_functions = {} |         self._patched_functions = { | ||||||
|  |             (TimerClass, 'addEventListener'): lambda params: undefined, | ||||||
|  |         } | ||||||
|         code_tag = next(tag |         code_tag = next(tag | ||||||
|                         for tag_code, tag in _extract_tags(file_contents) |                         for tag_code, tag in _extract_tags(file_contents) | ||||||
|                         if tag_code == 82) |                         if tag_code == 82) | ||||||
| @@ -346,9 +354,10 @@ class SWFInterpreter(object): | |||||||
|             u30()  # iinit |             u30()  # iinit | ||||||
|             trait_count = u30() |             trait_count = u30() | ||||||
|             for _c2 in range(trait_count): |             for _c2 in range(trait_count): | ||||||
|                 trait_methods, constants = parse_traits_info() |                 trait_methods, trait_constants = parse_traits_info() | ||||||
|                 avm_class.register_methods(trait_methods) |                 avm_class.register_methods(trait_methods) | ||||||
|                 assert constants is None |                 if trait_constants: | ||||||
|  |                     avm_class.constants.update(trait_constants) | ||||||
|  |  | ||||||
|         assert len(classes) == class_count |         assert len(classes) == class_count | ||||||
|         self._classes_by_name = dict((c.name, c) for c in classes) |         self._classes_by_name = dict((c.name, c) for c in classes) | ||||||
| @@ -439,7 +448,7 @@ class SWFInterpreter(object): | |||||||
|             registers = [avm_class.variables] + list(args) + [None] * m.local_count |             registers = [avm_class.variables] + list(args) + [None] * m.local_count | ||||||
|             stack = [] |             stack = [] | ||||||
|             scopes = collections.deque([ |             scopes = collections.deque([ | ||||||
|                 self._classes_by_name, avm_class.variables]) |                 self._classes_by_name, avm_class.constants, avm_class.variables]) | ||||||
|             while True: |             while True: | ||||||
|                 opcode = _read_byte(coder) |                 opcode = _read_byte(coder) | ||||||
|                 if opcode == 9:  # label |                 if opcode == 9:  # label | ||||||
| @@ -587,6 +596,12 @@ class SWFInterpreter(object): | |||||||
|                 elif opcode == 72:  # returnvalue |                 elif opcode == 72:  # returnvalue | ||||||
|                     res = stack.pop() |                     res = stack.pop() | ||||||
|                     return res |                     return res | ||||||
|  |                 elif opcode == 73:  # constructsuper | ||||||
|  |                     # Not yet implemented, just hope it works without it | ||||||
|  |                     arg_count = u30() | ||||||
|  |                     args = list(reversed( | ||||||
|  |                         [stack.pop() for _ in range(arg_count)])) | ||||||
|  |                     obj = stack.pop() | ||||||
|                 elif opcode == 74:  # constructproperty |                 elif opcode == 74:  # constructproperty | ||||||
|                     index = u30() |                     index = u30() | ||||||
|                     arg_count = u30() |                     arg_count = u30() | ||||||
| @@ -667,8 +682,11 @@ class SWFInterpreter(object): | |||||||
|  |  | ||||||
|                     if mname in scope: |                     if mname in scope: | ||||||
|                         res = scope[mname] |                         res = scope[mname] | ||||||
|  |                     elif mname in _builtin_classes: | ||||||
|  |                         res = _builtin_classes[mname] | ||||||
|                     else: |                     else: | ||||||
|                         res = avm_class.constants[mname] |                         # Assume unitialized | ||||||
|  |                         res = undefined | ||||||
|                     stack.append(res) |                     stack.append(res) | ||||||
|                 elif opcode == 97:  # setproperty |                 elif opcode == 97:  # setproperty | ||||||
|                     index = u30() |                     index = u30() | ||||||
| @@ -694,7 +712,12 @@ class SWFInterpreter(object): | |||||||
|                         stack.append(len(obj)) |                         stack.append(len(obj)) | ||||||
|                     elif isinstance(pname, compat_str):  # Member access |                     elif isinstance(pname, compat_str):  # Member access | ||||||
|                         obj = stack.pop() |                         obj = stack.pop() | ||||||
|                         assert isinstance(obj, (dict, _ScopeDict)), \ |                         if isinstance(obj, _AVMClass): | ||||||
|  |                             res = obj.static_properties[pname] | ||||||
|  |                             stack.append(res) | ||||||
|  |                             continue | ||||||
|  |  | ||||||
|  |                         assert isinstance(obj, (dict, _ScopeDict)),\ | ||||||
|                             'Accessing member %r on %r' % (pname, obj) |                             'Accessing member %r on %r' % (pname, obj) | ||||||
|                         res = obj.get(pname, undefined) |                         res = obj.get(pname, undefined) | ||||||
|                         stack.append(res) |                         stack.append(res) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Philipp Hagemeister
					Philipp Hagemeister