[jsbuilt-ins] fixing constructors

This commit is contained in:
sulyi 2017-03-02 21:22:11 +01:00
parent 4d386f0273
commit 0136be4a19
8 changed files with 65 additions and 23 deletions

View File

@ -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:

View File

@ -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

View File

@ -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'

View File

@ -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):

View File

@ -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

View File

@ -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)

View File

@ -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)):

View File

@ -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):