[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):
 | 
			
		||||
    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,7 +712,12 @@ class SWFInterpreter(object):
 | 
			
		|||
                        stack.append(len(obj))
 | 
			
		||||
                    elif isinstance(pname, compat_str):  # Member access
 | 
			
		||||
                        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)
 | 
			
		||||
                        res = obj.get(pname, undefined)
 | 
			
		||||
                        stack.append(res)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue