1from __future__ import unicode_literals 2 3from .base import Scope 4from .func_utils import * 5from .conversions import * 6import six 7from .prototypes.jsboolean import BooleanPrototype 8from .prototypes.jserror import ErrorPrototype 9from .prototypes.jsfunction import FunctionPrototype 10from .prototypes.jsnumber import NumberPrototype 11from .prototypes.jsobject import ObjectPrototype 12from .prototypes.jsregexp import RegExpPrototype 13from .prototypes.jsstring import StringPrototype 14from .prototypes.jsarray import ArrayPrototype 15from .prototypes import jsjson 16from .prototypes import jsutils 17 18from .constructors import jsnumber, jsstring, jsarray, jsboolean, jsregexp, jsmath, jsobject, jsfunction, jsconsole 19 20 21 22def fill_proto(proto, proto_class, space): 23 for i in dir(proto_class): 24 e = getattr(proto_class, i) 25 if six.PY2: 26 if hasattr(e, '__func__'): 27 meth = e.__func__ 28 else: 29 continue 30 else: 31 if hasattr(e, '__call__') and not i.startswith('__'): 32 meth = e 33 else: 34 continue 35 meth_name = meth.__name__.strip('_') # RexExp._exec -> RegExp.exec 36 js_meth = space.NewFunction(meth, space.ctx, (), meth_name, False, ()) 37 set_non_enumerable(proto, meth_name, js_meth) 38 return proto 39 40 41def easy_func(f, space): 42 return space.NewFunction(f, space.ctx, (), f.__name__, False, ()) 43 44 45def Empty(this, args): 46 return undefined 47 48 49def set_non_enumerable(obj, name, prop): 50 obj.define_own_property( 51 unicode(name), { 52 'value': prop, 53 'writable': True, 54 'enumerable': False, 55 'configurable': True 56 }, True) 57 58 59def set_protected(obj, name, prop): 60 obj.define_own_property( 61 unicode(name), { 62 'value': prop, 63 'writable': False, 64 'enumerable': False, 65 'configurable': False 66 }, True) 67 68 69def fill_space(space, byte_generator): 70 # set global scope 71 global_scope = Scope({}, space, parent=None) 72 global_scope.THIS_BINDING = global_scope 73 global_scope.registers(byte_generator.declared_vars) 74 space.GlobalObj = global_scope 75 76 space.byte_generator = byte_generator 77 78 # first init all protos, later take care of constructors and details 79 80 # Function must be first obviously, we have to use a small trick to do that... 81 function_proto = space.NewFunction(Empty, space.ctx, (), 'Empty', False, 82 ()) 83 space.FunctionPrototype = function_proto # this will fill the prototypes of the methods! 84 fill_proto(function_proto, FunctionPrototype, space) 85 86 # Object next 87 object_proto = space.NewObject() # no proto 88 fill_proto(object_proto, ObjectPrototype, space) 89 space.ObjectPrototype = object_proto 90 function_proto.prototype = object_proto 91 92 # Number 93 number_proto = space.NewObject() 94 number_proto.prototype = object_proto 95 fill_proto(number_proto, NumberPrototype, space) 96 number_proto.value = 0. 97 number_proto.Class = 'Number' 98 space.NumberPrototype = number_proto 99 100 # String 101 string_proto = space.NewObject() 102 string_proto.prototype = object_proto 103 fill_proto(string_proto, StringPrototype, space) 104 string_proto.value = u'' 105 string_proto.Class = 'String' 106 space.StringPrototype = string_proto 107 108 # Boolean 109 boolean_proto = space.NewObject() 110 boolean_proto.prototype = object_proto 111 fill_proto(boolean_proto, BooleanPrototype, space) 112 boolean_proto.value = False 113 boolean_proto.Class = 'Boolean' 114 space.BooleanPrototype = boolean_proto 115 116 # Array 117 array_proto = space.NewArray(0) 118 array_proto.prototype = object_proto 119 fill_proto(array_proto, ArrayPrototype, space) 120 space.ArrayPrototype = array_proto 121 122 # JSON 123 json = space.NewObject() 124 json.put(u'stringify', easy_func(jsjson.stringify, space)) 125 json.put(u'parse', easy_func(jsjson.parse, space)) 126 127 # Utils 128 parseFloat = easy_func(jsutils.parseFloat, space) 129 parseInt = easy_func(jsutils.parseInt, space) 130 isNaN = easy_func(jsutils.isNaN, space) 131 isFinite = easy_func(jsutils.isFinite, space) 132 133 # Error 134 error_proto = space.NewError(u'Error', u'') 135 error_proto.prototype = object_proto 136 error_proto.put(u'name', u'Error') 137 fill_proto(error_proto, ErrorPrototype, space) 138 space.ErrorPrototype = error_proto 139 140 def construct_constructor(typ): 141 def creator(this, args): 142 message = get_arg(args, 0) 143 if not is_undefined(message): 144 msg = to_string(message) 145 else: 146 msg = u'' 147 return space.NewError(typ, msg) 148 149 j = easy_func(creator, space) 150 j.name = unicode(typ) 151 152 set_protected(j, 'prototype', space.ERROR_TYPES[typ]) 153 154 set_non_enumerable(space.ERROR_TYPES[typ], 'constructor', j) 155 156 def new_create(args, space): 157 message = get_arg(args, 0) 158 if not is_undefined(message): 159 msg = to_string(message) 160 else: 161 msg = u'' 162 return space.NewError(typ, msg) 163 164 j.create = new_create 165 return j 166 167 # fill remaining error types 168 error_constructors = {} 169 for err_type_name in (u'Error', u'EvalError', u'RangeError', 170 u'ReferenceError', u'SyntaxError', u'TypeError', 171 u'URIError'): 172 extra_err = space.NewError(u'Error', u'') 173 extra_err.put(u'name', err_type_name) 174 setattr(space, err_type_name + u'Prototype', extra_err) 175 error_constructors[err_type_name] = construct_constructor( 176 err_type_name) 177 178 assert space.TypeErrorPrototype is not None 179 180 # RegExp 181 regexp_proto = space.NewRegExp(u'(?:)', u'') 182 regexp_proto.prototype = object_proto 183 fill_proto(regexp_proto, RegExpPrototype, space) 184 space.RegExpPrototype = regexp_proto 185 186 # Json 187 188 # now all these boring constructors... 189 190 # Number 191 number = easy_func(jsnumber.Number, space) 192 space.Number = number 193 number.create = jsnumber.NumberConstructor 194 set_non_enumerable(number_proto, 'constructor', number) 195 set_protected(number, 'prototype', number_proto) 196 # number has some extra constants 197 for k, v in jsnumber.CONSTS.items(): 198 set_protected(number, k, v) 199 200 # String 201 string = easy_func(jsstring.String, space) 202 space.String = string 203 string.create = jsstring.StringConstructor 204 set_non_enumerable(string_proto, 'constructor', string) 205 set_protected(string, 'prototype', string_proto) 206 # string has an extra function 207 set_non_enumerable(string, 'fromCharCode', 208 easy_func(jsstring.fromCharCode, space)) 209 210 # Boolean 211 boolean = easy_func(jsboolean.Boolean, space) 212 space.Boolean = boolean 213 boolean.create = jsboolean.BooleanConstructor 214 set_non_enumerable(boolean_proto, 'constructor', boolean) 215 set_protected(boolean, 'prototype', boolean_proto) 216 217 # Array 218 array = easy_func(jsarray.Array, space) 219 space.Array = array 220 array.create = jsarray.ArrayConstructor 221 set_non_enumerable(array_proto, 'constructor', array) 222 set_protected(array, 'prototype', array_proto) 223 array.put(u'isArray', easy_func(jsarray.isArray, space)) 224 225 # RegExp 226 regexp = easy_func(jsregexp.RegExp, space) 227 space.RegExp = regexp 228 regexp.create = jsregexp.RegExpCreate 229 set_non_enumerable(regexp_proto, 'constructor', regexp) 230 set_protected(regexp, 'prototype', regexp_proto) 231 232 # Object 233 _object = easy_func(jsobject.Object, space) 234 space.Object = _object 235 _object.create = jsobject.ObjectCreate 236 set_non_enumerable(object_proto, 'constructor', _object) 237 set_protected(_object, 'prototype', object_proto) 238 fill_proto(_object, jsobject.ObjectMethods, space) 239 240 # Function 241 function = easy_func(jsfunction.Function, space) 242 space.Function = function 243 244 # Math 245 math = space.NewObject() 246 math.Class = 'Math' 247 fill_proto(math, jsmath.MathFunctions, space) 248 for k, v in jsmath.CONSTANTS.items(): 249 set_protected(math, k, v) 250 251 console = space.NewObject() 252 fill_proto(console, jsconsole.ConsoleMethods, space) 253 254 # set global object 255 builtins = { 256 'String': string, 257 'Number': number, 258 'Boolean': boolean, 259 'RegExp': regexp, 260 'exports': convert_to_js_type({}, space), 261 'Math': math, 262 #'Date', 263 'Object': _object, 264 'Function': function, 265 'JSON': json, 266 'Array': array, 267 'parseFloat': parseFloat, 268 'parseInt': parseInt, 269 'isFinite': isFinite, 270 'isNaN': isNaN, 271 'eval': easy_func(jsfunction._eval, space), 272 'console': console, 273 'log': console.get(u'log'), 274 } 275 276 builtins.update(error_constructors) 277 278 set_protected(global_scope, 'NaN', NaN) 279 set_protected(global_scope, 'Infinity', Infinity) 280 for k, v in builtins.items(): 281 set_non_enumerable(global_scope, k, v) 282