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): | ||||
|     def __init__(self, name_idx, name): | ||||
|     def __init__(self, name_idx, name, static_properties=None): | ||||
|         self.name_idx = name_idx | ||||
|         self.name = name | ||||
|         self.method_names = {} | ||||
|         self.method_idxs = {} | ||||
|         self.methods = {} | ||||
|         self.method_pyfunctions = {} | ||||
|         self.static_properties = static_properties if static_properties else {} | ||||
|  | ||||
|         self.variables = _ScopeDict(self) | ||||
|         self.constants = {} | ||||
| @@ -151,15 +152,20 @@ def _read_byte(reader): | ||||
|  | ||||
| StringClass = _AVMClass('(no name idx)', 'String') | ||||
| ByteArrayClass = _AVMClass('(no name idx)', 'ByteArray') | ||||
| TimerClass = _AVMClass('(no name idx)', 'Timer') | ||||
| TimerEventClass = _AVMClass('(no name idx)', 'TimerEvent', {'TIMER': 'timer'}) | ||||
| _builtin_classes = { | ||||
|     StringClass.name: StringClass, | ||||
|     ByteArrayClass.name: ByteArrayClass, | ||||
|     TimerClass.name: TimerClass, | ||||
|     TimerEventClass.name: TimerEventClass, | ||||
| } | ||||
|  | ||||
|  | ||||
| class _Undefined(object): | ||||
|     def __boolean__(self): | ||||
|     def __bool__(self): | ||||
|         return False | ||||
|     __nonzero__ = __bool__ | ||||
|  | ||||
|     def __hash__(self): | ||||
|         return 0 | ||||
| @@ -169,7 +175,9 @@ undefined = _Undefined() | ||||
|  | ||||
| class SWFInterpreter(object): | ||||
|     def __init__(self, file_contents): | ||||
|         self._patched_functions = {} | ||||
|         self._patched_functions = { | ||||
|             (TimerClass, 'addEventListener'): lambda params: undefined, | ||||
|         } | ||||
|         code_tag = next(tag | ||||
|                         for tag_code, tag in _extract_tags(file_contents) | ||||
|                         if tag_code == 82) | ||||
| @@ -346,9 +354,10 @@ class SWFInterpreter(object): | ||||
|             u30()  # iinit | ||||
|             trait_count = u30() | ||||
|             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) | ||||
|                 assert constants is None | ||||
|                 if trait_constants: | ||||
|                     avm_class.constants.update(trait_constants) | ||||
|  | ||||
|         assert len(classes) == class_count | ||||
|         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 | ||||
|             stack = [] | ||||
|             scopes = collections.deque([ | ||||
|                 self._classes_by_name, avm_class.variables]) | ||||
|                 self._classes_by_name, avm_class.constants, avm_class.variables]) | ||||
|             while True: | ||||
|                 opcode = _read_byte(coder) | ||||
|                 if opcode == 9:  # label | ||||
| @@ -587,6 +596,12 @@ class SWFInterpreter(object): | ||||
|                 elif opcode == 72:  # returnvalue | ||||
|                     res = stack.pop() | ||||
|                     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 | ||||
|                     index = u30() | ||||
|                     arg_count = u30() | ||||
| @@ -667,8 +682,11 @@ class SWFInterpreter(object): | ||||
|  | ||||
|                     if mname in scope: | ||||
|                         res = scope[mname] | ||||
|                     elif mname in _builtin_classes: | ||||
|                         res = _builtin_classes[mname] | ||||
|                     else: | ||||
|                         res = avm_class.constants[mname] | ||||
|                         # Assume unitialized | ||||
|                         res = undefined | ||||
|                     stack.append(res) | ||||
|                 elif opcode == 97:  # setproperty | ||||
|                     index = u30() | ||||
| @@ -694,6 +712,11 @@ class SWFInterpreter(object): | ||||
|                         stack.append(len(obj)) | ||||
|                     elif isinstance(pname, compat_str):  # Member access | ||||
|                         obj = stack.pop() | ||||
|                         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) | ||||
|                         res = obj.get(pname, undefined) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Hagemeister
					Philipp Hagemeister