You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bazarr/libs/js2py/internals/fill_space.py

285 lines
8.9 KiB

from __future__ import unicode_literals
from base import Scope
from func_utils import *
from conversions import *
import six
from prototypes.jsboolean import BooleanPrototype
from prototypes.jserror import ErrorPrototype
from prototypes.jsfunction import FunctionPrototype
from prototypes.jsnumber import NumberPrototype
from prototypes.jsobject import ObjectPrototype
from prototypes.jsregexp import RegExpPrototype
from prototypes.jsstring import StringPrototype
from prototypes.jsarray import ArrayPrototype
import prototypes.jsjson as jsjson
import prototypes.jsutils as jsutils
from constructors import jsnumber
from constructors import jsstring
from constructors import jsarray
from constructors import jsboolean
from constructors import jsregexp
from constructors import jsmath
from constructors import jsobject
from constructors import jsfunction
from constructors import jsconsole
def fill_proto(proto, proto_class, space):
for i in dir(proto_class):
e = getattr(proto_class, i)
if six.PY2:
if hasattr(e, '__func__'):
meth = e.__func__
else:
continue
else:
if hasattr(e, '__call__') and not i.startswith('__'):
meth = e
else:
continue
meth_name = meth.__name__.strip('_') # RexExp._exec -> RegExp.exec
js_meth = space.NewFunction(meth, space.ctx, (), meth_name, False, ())
set_non_enumerable(proto, meth_name, js_meth)
return proto
def easy_func(f, space):
return space.NewFunction(f, space.ctx, (), f.__name__, False, ())
def Empty(this, args):
return undefined
def set_non_enumerable(obj, name, prop):
obj.define_own_property(
unicode(name), {
'value': prop,
'writable': True,
'enumerable': False,
'configurable': True
}, True)
def set_protected(obj, name, prop):
obj.define_own_property(
unicode(name), {
'value': prop,
'writable': False,
'enumerable': False,
'configurable': False
}, True)
def fill_space(space, byte_generator):
# set global scope
global_scope = Scope({}, space, parent=None)
global_scope.THIS_BINDING = global_scope
global_scope.registers(byte_generator.declared_vars)
space.GlobalObj = global_scope
space.byte_generator = byte_generator
# first init all protos, later take care of constructors and details
# Function must be first obviously, we have to use a small trick to do that...
function_proto = space.NewFunction(Empty, space.ctx, (), 'Empty', False,
())
space.FunctionPrototype = function_proto # this will fill the prototypes of the methods!
fill_proto(function_proto, FunctionPrototype, space)
# Object next
object_proto = space.NewObject() # no proto
fill_proto(object_proto, ObjectPrototype, space)
space.ObjectPrototype = object_proto
function_proto.prototype = object_proto
# Number
number_proto = space.NewObject()
number_proto.prototype = object_proto
fill_proto(number_proto, NumberPrototype, space)
number_proto.value = 0.
number_proto.Class = 'Number'
space.NumberPrototype = number_proto
# String
string_proto = space.NewObject()
string_proto.prototype = object_proto
fill_proto(string_proto, StringPrototype, space)
string_proto.value = u''
string_proto.Class = 'String'
space.StringPrototype = string_proto
# Boolean
boolean_proto = space.NewObject()
boolean_proto.prototype = object_proto
fill_proto(boolean_proto, BooleanPrototype, space)
boolean_proto.value = False
boolean_proto.Class = 'Boolean'
space.BooleanPrototype = boolean_proto
# Array
array_proto = space.NewArray(0)
array_proto.prototype = object_proto
fill_proto(array_proto, ArrayPrototype, space)
space.ArrayPrototype = array_proto
# JSON
json = space.NewObject()
json.put(u'stringify', easy_func(jsjson.stringify, space))
json.put(u'parse', easy_func(jsjson.parse, space))
# Utils
parseFloat = easy_func(jsutils.parseFloat, space)
parseInt = easy_func(jsutils.parseInt, space)
isNaN = easy_func(jsutils.isNaN, space)
isFinite = easy_func(jsutils.isFinite, space)
# Error
error_proto = space.NewError(u'Error', u'')
error_proto.prototype = object_proto
error_proto.put(u'name', u'Error')
fill_proto(error_proto, ErrorPrototype, space)
space.ErrorPrototype = error_proto
def construct_constructor(typ):
def creator(this, args):
message = get_arg(args, 0)
if not is_undefined(message):
msg = to_string(message)
else:
msg = u''
return space.NewError(typ, msg)
j = easy_func(creator, space)
j.name = unicode(typ)
j.prototype = space.ERROR_TYPES[typ]
def new_create(args, space):
message = get_arg(args, 0)
if not is_undefined(message):
msg = to_string(message)
else:
msg = u''
return space.NewError(typ, msg)
j.create = new_create
return j
# fill remaining error types
error_constructors = {}
for err_type_name in (u'Error', u'EvalError', u'RangeError',
u'ReferenceError', u'SyntaxError', u'TypeError',
u'URIError'):
extra_err = space.NewError(u'Error', u'')
extra_err.put(u'name', err_type_name)
setattr(space, err_type_name + u'Prototype', extra_err)
error_constructors[err_type_name] = construct_constructor(
err_type_name)
assert space.TypeErrorPrototype is not None
# RegExp
regexp_proto = space.NewRegExp(u'(?:)', u'')
regexp_proto.prototype = object_proto
fill_proto(regexp_proto, RegExpPrototype, space)
space.RegExpPrototype = regexp_proto
# Json
# now all these boring constructors...
# Number
number = easy_func(jsnumber.Number, space)
space.Number = number
number.create = jsnumber.NumberConstructor
set_non_enumerable(number_proto, 'constructor', number)
set_protected(number, 'prototype', number_proto)
# number has some extra constants
for k, v in jsnumber.CONSTS.items():
set_protected(number, k, v)
# String
string = easy_func(jsstring.String, space)
space.String = string
string.create = jsstring.StringConstructor
set_non_enumerable(string_proto, 'constructor', string)
set_protected(string, 'prototype', string_proto)
# string has an extra function
set_non_enumerable(string, 'fromCharCode',
easy_func(jsstring.fromCharCode, space))
# Boolean
boolean = easy_func(jsboolean.Boolean, space)
space.Boolean = boolean
boolean.create = jsboolean.BooleanConstructor
set_non_enumerable(boolean_proto, 'constructor', boolean)
set_protected(boolean, 'prototype', boolean_proto)
# Array
array = easy_func(jsarray.Array, space)
space.Array = array
array.create = jsarray.ArrayConstructor
set_non_enumerable(array_proto, 'constructor', array)
set_protected(array, 'prototype', array_proto)
array.put(u'isArray', easy_func(jsarray.isArray, space))
# RegExp
regexp = easy_func(jsregexp.RegExp, space)
space.RegExp = regexp
regexp.create = jsregexp.RegExpCreate
set_non_enumerable(regexp_proto, 'constructor', regexp)
set_protected(regexp, 'prototype', regexp_proto)
# Object
_object = easy_func(jsobject.Object, space)
space.Object = _object
_object.create = jsobject.ObjectCreate
set_non_enumerable(object_proto, 'constructor', _object)
set_protected(_object, 'prototype', object_proto)
fill_proto(_object, jsobject.ObjectMethods, space)
# Function
function = easy_func(jsfunction.Function, space)
space.Function = function
# Math
math = space.NewObject()
math.Class = 'Math'
fill_proto(math, jsmath.MathFunctions, space)
for k, v in jsmath.CONSTANTS.items():
set_protected(math, k, v)
console = space.NewObject()
fill_proto(console, jsconsole.ConsoleMethods, space)
# set global object
builtins = {
'String': string,
'Number': number,
'Boolean': boolean,
'RegExp': regexp,
'exports': convert_to_js_type({}, space),
'Math': math,
#'Date',
'Object': _object,
'Function': function,
'JSON': json,
'Array': array,
'parseFloat': parseFloat,
'parseInt': parseInt,
'isFinite': isFinite,
'isNaN': isNaN,
'eval': easy_func(jsfunction._eval, space),
'console': console,
'log': console.get(u'log'),
}
builtins.update(error_constructors)
set_protected(global_scope, 'NaN', NaN)
set_protected(global_scope, 'Infinity', Infinity)
for k, v in builtins.items():
set_non_enumerable(global_scope, k, v)