[swfinterp] Add more builtins and improve static variables
This commit is contained in:
		
							parent
							
								
									1921b24551
								
							
						
					
					
						commit
						fbf94a7815
					
				
					 2 changed files with 49 additions and 8 deletions
				
			
		
							
								
								
									
										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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue