98 lines
3.1 KiB
Python
Raw Normal View History

2017-02-21 22:02:56 +01:00
from __future__ import unicode_literals
from . import undefined, null
from .internals import to_string
from .base import to_js, native_function, JSBase
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)
# 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):
# 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])
@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(arg if init is None else arg + '=' + init for arg, init in 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 None:
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
own = {
'length': 1,
'prototype': JSFunctionPrototype(None, None, None)
}