[jsbuilt-ins] fixing constructors
This commit is contained in:
parent
4d386f0273
commit
0136be4a19
@ -60,6 +60,10 @@ class JSProtoBase(JSBase):
|
||||
jsclass = ''
|
||||
|
||||
|
||||
def _get_formal_args(func):
|
||||
return func.__code__.co_varnames[func.__code__.co_argcount - len((func.__defaults__))]
|
||||
|
||||
|
||||
def to_js(o, name=None):
|
||||
if isinstance(o, JSProtoBase):
|
||||
return o
|
||||
@ -74,9 +78,9 @@ def to_js(o, name=None):
|
||||
elif isinstance(o, native_object):
|
||||
return JSObjectPrototype(o)
|
||||
elif isinstance(o, native_function):
|
||||
return JSFunctionPrototype(name, o, [])
|
||||
return JSFunctionPrototype(name, o, _get_formal_args(o))
|
||||
elif isinstance(o, JSBase) and hasattr(o, 'call'):
|
||||
return JSFunctionPrototype(o.name, o, [])
|
||||
return JSFunctionPrototype(o.name, o, _get_formal_args(o.call))
|
||||
elif isinstance(o, native_array):
|
||||
return JSArrayPrototype(o)
|
||||
else:
|
||||
|
@ -12,6 +12,13 @@ from .jsstring import JSStringPrototype
|
||||
from .jsnumber import JSNumberPrototype
|
||||
from ..jsgrammar import __HEXADECIMAL_RE
|
||||
|
||||
undefined_type = object()
|
||||
null_type = object()
|
||||
boolean_type = object()
|
||||
string_type = object()
|
||||
number_type = object()
|
||||
object_type = object()
|
||||
|
||||
|
||||
def jstype(o):
|
||||
if o is undefined:
|
||||
@ -189,9 +196,6 @@ def to_object(o):
|
||||
return o
|
||||
|
||||
|
||||
undefined_type = object()
|
||||
null_type = object()
|
||||
boolean_type = object()
|
||||
string_type = object()
|
||||
number_type = object()
|
||||
object_type = object()
|
||||
def throw_type_error():
|
||||
# TODO [[ThrowTypeError]] (13.2.3)
|
||||
pass
|
||||
|
@ -10,8 +10,13 @@ class JSArrayPrototype(JSObjectPrototype):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(JSArrayPrototype, self).__init__()
|
||||
self.value = [] if value is None else list(value)
|
||||
self.own = {'length': self._length}
|
||||
if value is None:
|
||||
# prototype
|
||||
self.value = []
|
||||
else:
|
||||
self.value = value
|
||||
self.own = dict((str(i), v) for i, v in enumerate(value))
|
||||
self.own['length'] = self._length
|
||||
|
||||
def __str__(self):
|
||||
return 'JSArrayPrototype: %s' % self.value
|
||||
@ -136,7 +141,7 @@ class JSArray(JSObject):
|
||||
if args:
|
||||
return JSArrayPrototype(args)
|
||||
else:
|
||||
return JSArrayPrototype()
|
||||
return JSArrayPrototype([])
|
||||
|
||||
def _is_array(self, arg):
|
||||
return 'array is array'
|
||||
|
@ -9,10 +9,13 @@ from .jsobject import JSObject, JSObjectPrototype
|
||||
class JSBooleanPrototype(JSObjectPrototype):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(JSBooleanPrototype, self).__init__()
|
||||
if value is None:
|
||||
# prototype
|
||||
value = False
|
||||
super(JSBooleanPrototype, self).__init__(value)
|
||||
else:
|
||||
self.value = value
|
||||
self.own = {}
|
||||
|
||||
@staticmethod
|
||||
def _constructor(value=None):
|
||||
|
@ -1,7 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from . import undefined, null
|
||||
from .internals import to_string
|
||||
from .internals import to_string, throw_type_error
|
||||
from .base import to_js, native_function, JSBase
|
||||
from .jsobject import JSObject, JSObjectPrototype
|
||||
|
||||
@ -27,6 +27,17 @@ class JSFunctionPrototype(JSObjectPrototype):
|
||||
self.body = to_string(body) if body is not undefined or body is not null else ''
|
||||
self.f_name = name
|
||||
self.arguments = list(formal_args)
|
||||
proto = JSObject.construct()
|
||||
proto.own['constructor'] = self
|
||||
self.own = {'length': self._length,
|
||||
'prototype': proto
|
||||
}
|
||||
# TODO Handle strict mode
|
||||
strict = True
|
||||
if strict:
|
||||
thrower = throw_type_error
|
||||
self.own['caller'] = thrower
|
||||
self.own['arguments'] = thrower
|
||||
# FIXME: JSProtoBase sets body to '' instead of None
|
||||
# TODO check if self._args can be parsed as formal parameter list
|
||||
# TODO check if self._body can be parsed as function body
|
||||
@ -36,8 +47,7 @@ class JSFunctionPrototype(JSObjectPrototype):
|
||||
|
||||
@property
|
||||
def _length(self):
|
||||
# Yeesh, I dare you to find anything like that in the python specification.
|
||||
return len([arg for arg, init in self.arguments if init is not None])
|
||||
return len(self.arguments)
|
||||
|
||||
@staticmethod
|
||||
def _constructor(arguments=None):
|
||||
@ -51,7 +61,7 @@ class JSFunctionPrototype(JSObjectPrototype):
|
||||
body = ''
|
||||
return 'function %s(%s) {%s\n}' % (
|
||||
self.f_name,
|
||||
', '.join(arg if init is None else arg + '=' + init for arg, init in self.arguments),
|
||||
', '.join(self.arguments),
|
||||
body)
|
||||
|
||||
def _apply(self, this_arg, arg_array):
|
||||
@ -82,12 +92,14 @@ class JSFunction(JSObject):
|
||||
|
||||
@staticmethod
|
||||
def construct(formal_args=None):
|
||||
if formal_args is None:
|
||||
if formal_args is not None and formal_args:
|
||||
body = formal_args[-1]
|
||||
formal_args = []
|
||||
for arg in formal_args[:-1]:
|
||||
formal_args.extend(a.strip() for a in arg.split(','))
|
||||
else:
|
||||
body = ''
|
||||
formal_args = []
|
||||
else:
|
||||
body = formal_args[-1] if formal_args else ''
|
||||
formal_args = formal_args[:-1]
|
||||
return JSFunctionPrototype('anonymous', body, formal_args)
|
||||
|
||||
name = JSFunctionPrototype.jsclass
|
||||
|
@ -7,6 +7,15 @@ from .jsobject import JSObject, JSObjectPrototype
|
||||
|
||||
class JSNumberPrototype(JSObjectPrototype):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(JSNumberPrototype, self).__init__()
|
||||
if value is None:
|
||||
# prototype
|
||||
value = 0
|
||||
else:
|
||||
self.value = value
|
||||
self.own = {}
|
||||
|
||||
@staticmethod
|
||||
def _constructor(value=None):
|
||||
return JSNumber.construct(value)
|
||||
|
@ -12,7 +12,9 @@ class JSObjectPrototype(JSProtoBase):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(JSObjectPrototype, self).__init__()
|
||||
self.value = {} if value is None else value
|
||||
if value is not None:
|
||||
self.props.update(self.own)
|
||||
self.own = self.value = value
|
||||
|
||||
@staticmethod
|
||||
def _constructor(value=None):
|
||||
@ -64,7 +66,7 @@ class JSObject(JSBase):
|
||||
value = to_js(value)
|
||||
# TODO set [[Prototype]], [[Class]], [[Extensible]], internal methods
|
||||
if value is undefined or value is null:
|
||||
return JSObjectPrototype()
|
||||
return JSObjectPrototype({})
|
||||
elif isinstance(value, JSObjectPrototype):
|
||||
return value
|
||||
elif isinstance(value, (JSStringPrototype, JSNumberPrototype, JSBooleanPrototype)):
|
||||
|
@ -7,10 +7,13 @@ from .jsobject import JSObject, JSObjectPrototype
|
||||
class JSStringPrototype(JSObjectPrototype):
|
||||
|
||||
def __init__(self, value=None):
|
||||
super(JSStringPrototype, self).__init__()
|
||||
if value is None:
|
||||
# prototype
|
||||
value = ''
|
||||
super(JSStringPrototype, self).__init__(value)
|
||||
else:
|
||||
self.value = value
|
||||
self.own = {'length': self._length}
|
||||
|
||||
@property
|
||||
def _length(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user