2018-06-01 01:45:35 +02:00

111 lines
3.5 KiB
Python

from __future__ import unicode_literals
from .base import undefined, null
from .internals import to_string, throw_type_error
from .base import native_function, JSBase
from .utils import to_js
from .jsobject import JSObject, JSObjectPrototype
class JSFunctionPrototype(JSObjectPrototype):
def __init__(self, name, body, formal_args):
if name is None and body is None and formal_args is None:
# prototype
super(JSFunctionPrototype, self).__init__()
self.f_name = ''
self.body = ''
else:
if isinstance(body, JSBase):
super(JSFunctionPrototype, self).__init__(body.own)
self.body = '[native code]'
elif isinstance(body, native_function):
super(JSFunctionPrototype, self).__init__()
self.body = '[native code]'
else:
super(JSFunctionPrototype, self).__init__()
body = to_js(body)
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
# TODO set strict
# TODO throw strict mode exceptions
# (double argument, "eval" or "arguments" in arguments, function identifier is "eval" or "arguments")
@property
def _length(self):
return len(self.arguments)
@staticmethod
def _constructor(arguments=None):
return JSFunction.construct(arguments)
def _to_string(self):
if self.body is not None:
body = '\n'
body += '\t' + self.body if self.body else self.body
else:
body = ''
return 'function %s(%s) {%s\n}' % (
self.f_name,
', '.join(self.arguments),
body)
def _apply(self, this_arg, arg_array):
return 'function apply'
def _call(self, this_arg, *args):
return 'function call'
def _bind(self, this_arg, *args):
return 'function bind'
jsclass = 'Function'
own = {
'length': 0,
'constructor': _constructor,
'toString': _to_string,
'apply': _apply,
'call': _call,
'bind': _bind
}
class JSFunction(JSObject):
@staticmethod
def call(formal_args=None):
return JSFunction.construct(formal_args)
@staticmethod
def construct(formal_args=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 = []
return JSFunctionPrototype('anonymous', body, formal_args)
name = JSFunctionPrototype.jsclass
own = {
'length': 1,
'prototype': JSFunctionPrototype(None, None, None)
}