def testMultiNamespace(self): isolate = JSIsolate.current self.assertTrue(not isolate.in_context) self.assertTrue(isolate.current_context is None) class Global(object): name = "global" global_scope = Global() with JSContext(global_scope) as global_ctxt: self.assertTrue(global_ctxt) self.assertTrue(isolate.in_context) self.assertTrue(isolate.current_context is global_ctxt) self.assertEqual(global_scope.name, isolate.current_context.locals.name) class Local(object): name = "local" local_scope = Local() with JSContext(local_scope) as local_ctxt: self.assertTrue(isolate.in_context) self.assertTrue(isolate.current_context is local_ctxt) self.assertEqual(local_scope.name, isolate.current_context.locals.name) self.assertTrue(isolate.in_context) self.assertEqual(global_scope.name, isolate.current_context.locals.name) self.assertTrue(not isolate.in_context) self.assertTrue(isolate.current_context is None)
def testIsolateContexts(self): with JSIsolate() as isolate: ctx1 = JSContext() ctx2 = JSContext() self.assertFalse(isolate.in_context) with ctx1: self.assertEqual(ctx1, isolate.entered_or_microtask_context) self.assertEqual(ctx1, isolate.current_context) self.assertTrue(isolate.in_context) with ctx2: self.assertEqual(ctx2, isolate.entered_or_microtask_context) self.assertEqual(ctx2, isolate.current_context) self.assertTrue(isolate.in_context) self.assertEqual(ctx1, isolate.entered_or_microtask_context) self.assertEqual(ctx1, isolate.current_context) self.assertTrue(isolate.in_context) self.assertFalse(isolate.in_context) self.assertEqual(JSNull, isolate.entered_or_microtask_context) self.assertEqual(JSNull, isolate.current_context)
def testSecurityChecks(self): with JSContext() as env1: env1.security_token = "foo" # Create a function in env1. env1.eval("spy = function(){return spy;}") spy = env1.locals.spy self.assertTrue(isinstance(spy, JSObject)) # Create another function accessing global objects. env1.eval("spy2 = function(){return 123;}") spy2 = env1.locals.spy2 self.assertTrue(isinstance(spy2, JSObject)) # Switch to env2 in the same domain and invoke spy on env2. env2 = JSContext() env2.security_token = "foo" with env2: result = toolkit.apply(spy, env2.locals) self.assertTrue(isinstance(result, JSObject)) env2.security_token = "bar"
def testConstructor(self): with JSContext() as ctx: ctx.eval(""" var Test = function() { this.trySomething(); }; Test.prototype.trySomething = function() { this.name = 'soirv8'; }; var Test2 = function(first_name, last_name) { this.name = first_name + ' ' + last_name; }; """) self.assertTrue(isinstance(ctx.locals.Test, JSObject)) test = toolkit.create(ctx.locals.Test) self.assertTrue(isinstance(ctx.locals.Test, JSObject)) self.assertEqual("soirv8", test.name) test2 = toolkit.create(ctx.locals.Test2, ('John', 'Doe')) self.assertEqual("John Doe", test2.name) test3 = toolkit.create(ctx.locals.Test2, ('John', 'Doe'), {'email': '*****@*****.**'}) self.assertEqual("*****@*****.**", test3.email)
def testFunction(self): with JSContext() as ctxt: func = ctxt.eval(""" (function () { function a() { return "abc"; } return a(); }) """) self.assertEqual("abc", str(func())) self.assertTrue(func is not None) self.assertFalse(func is None) func = ctxt.eval("(function test() {})") self.assertEqual("test", toolkit.get_name(func)) self.assertEqual("", toolkit.resource_name(func)) self.assertEqual(0, toolkit.line_number(func)) self.assertEqual(14, toolkit.column_number(func)) self.assertEqual(0, toolkit.line_offset(func)) self.assertEqual(0, toolkit.column_offset(func))
def testNamedSetter(self): class Obj(JSClass): def __init__(self): self._p = None @property def p(self): return self._p @p.setter def p(self, value): self._p = value class Global(JSClass): def __init__(self): self.obj = Obj() self.d = {} self.p = None with JSContext(Global()) as ctxt: ctxt.eval(""" x = obj; x.y = 10; x.p = 10; d.y = 10; """) self.assertEqual(10, ctxt.eval("obj.y")) self.assertEqual(10, ctxt.eval("obj.p")) self.assertEqual(10, ctxt.locals.d['y'])
def testPythonWrapper(self): with JSContext() as ctxt: typeof = ctxt.eval( "(function type(value) { return typeof value; })") protoof = ctxt.eval( "(function protoof(value) { return Object.prototype.toString.apply(value); })" ) self.assertEqual('[object Null]', protoof(None)) self.assertEqual('boolean', typeof(True)) self.assertEqual('number', typeof(123)) self.assertEqual('number', typeof(3.14)) self.assertEqual('string', typeof('test')) self.assertEqual('string', typeof(u'test')) self.assertEqual('[object Date]', protoof(datetime.datetime.now())) self.assertEqual('[object Date]', protoof(datetime.date.today())) self.assertEqual('[object Date]', protoof(datetime.time())) def test(): pass self.assertEqual('[object Function]', protoof(abs)) self.assertEqual('[object Function]', protoof(test)) self.assertEqual('[object Function]', protoof(self.testPythonWrapper)) self.assertEqual('[object Function]', protoof(int))
def testThis(self): class Global(JSClass): version = 1.0 with JSContext(Global()) as ctxt: self.assertEqual("[object Global]", str(ctxt.eval("this"))) self.assertEqual(1.0, float(ctxt.eval("this.version")))
def testStackLimit(self): with JSIsolate(): JSEngine.set_stack_limit(256 * 1024) with JSContext() as ctxt: old_stack_size = ctxt.eval( "var maxStackSize = function(i){try{(function m(){++i&&m()}())}catch(e){return i}}(0); maxStackSize") with JSIsolate(): JSEngine.set_stack_limit(512 * 1024) with JSContext() as ctxt: new_stack_size = ctxt.eval( "var maxStackSize = function(i){try{(function m(){++i&&m()}())}catch(e){return i}}(0); maxStackSize") self.assertTrue(new_stack_size > old_stack_size * 2)
def testRefCount(self): o = object() class Global(JSClass): po = o g = Global() g_refs = sys.getrefcount(g) count = sys.getrefcount(o) with JSContext(g) as ctxt: ctxt.eval(""" var hold = po; """) self.assertEqual(count + 1, sys.getrefcount(o)) ctxt.eval(""" var hold = po; """) self.assertEqual(count + 1, sys.getrefcount(o)) del ctxt aux.v8_request_gc_for_testing() self.assertEqual(g_refs, sys.getrefcount(g))
def testDict(self): with JSContext() as ctxt: obj = ctxt.eval("var r = { 'a' : 1, 'b' : 2 }; r") self.assertEqual(1, obj.a) self.assertEqual(2, obj.b) self.assertEqual({'a': 1, 'b': 2}, dict(obj)) self.assertEqual( { 'a': 1, 'b': [1, 2, 3], 'c': { 'str': 'goofy', 'float': 1.234, 'obj': { 'name': 'john doe' } }, 'd': True, 'e': JSNull, 'f': JSUndefined }, convert( ctxt.eval("""var x = { a: 1, b: [1, 2, 3], c: { str: 'goofy', float: 1.234, obj: { name: 'john doe' }}, d: true, e: null, f: undefined}; x""")))
def testExceptionMapping(self): class TestException(Exception): pass # noinspection PyPep8Naming,PyMethodMayBeStatic class Global(JSClass): def raiseIndexError(self): return [1, 2, 3][5] def raiseAttributeError(self): # noinspection PyUnresolvedReferences None.hello() def raiseSyntaxError(self): eval("???") def raiseTypeError(self): # noinspection PyTypeChecker int(sys) def raiseNotImplementedError(self): raise NotImplementedError("Not supported") def raiseExceptions(self): raise TestException() with JSContext(Global()) as ctxt: ctxt.eval("try { this.raiseIndexError(); } catch (e) { msg = e; }") self.assertEqual("RangeError: list index out of range", str(ctxt.locals.msg)) ctxt.eval( "try { this.raiseAttributeError(); } catch (e) { msg = e; }") self.assertEqual( "ReferenceError: 'NoneType' object has no attribute 'hello'", str(ctxt.locals.msg)) ctxt.eval( "try { this.raiseSyntaxError(); } catch (e) { msg = e; }") self.assertEqual( "SyntaxError: ('invalid syntax', ('<string>', 1, 1, '???'))", str(ctxt.locals.msg)) ctxt.eval("try { this.raiseTypeError(); } catch (e) { msg = e; }") self.assertEqual( "TypeError: int() argument must be a string, a bytes-like object or a number, not 'module'", str(ctxt.locals.msg)) ctxt.eval( "try { this.raiseNotImplementedError(); } catch (e) { msg = e; }" ) self.assertEqual("Error: Not supported", str(ctxt.locals.msg)) self.assertRaises(TestException, ctxt.eval, "this.raiseExceptions();")
def testNullAndUndefined(self): # noinspection PyPep8Naming,PyMethodMayBeStatic class Global(JSClass): def returnUndefined(self): return JSUndefined def returnNull(self): return JSNull def returnNone(self): return None with JSContext(Global()) as ctxt: # JSNull maps to None # JSUndefined maps to Py_JSUndefined (None-like) self.assertEqual(JSNull, None) self.assertEqual(JSNull, ctxt.eval("null")) self.assertEqual(JSUndefined, ctxt.eval("undefined")) self.assertFalse(bool(JSUndefined)) self.assertFalse(bool(JSNull)) self.assertEqual("JSUndefined", str(JSUndefined)) self.assertEqual("None", str(JSNull)) self.assertTrue(ctxt.eval('undefined == returnUndefined()')) self.assertTrue(ctxt.eval('null == returnNone()')) self.assertTrue(ctxt.eval('null == returnNull()'))
def testUnicode(self): with JSContext() as ctxt: self.assertEqual(u"人", ctxt.eval(u"\"人\"")) self.assertEqual(u"é", ctxt.eval(u"\"é\"")) func = ctxt.eval("(function (msg) { return msg.length; })") self.assertEqual(2, func(u"测试"))
def testJSError(self): with JSContext() as ctxt: # noinspection PyBroadException try: ctxt.eval('throw "test"') self.fail() except Exception: self.assertTrue(JSError, sys.exc_info()[0])
def testLivingObjectCache(self): class Global(JSClass): i = 1 b = True o = object() with JSContext(Global()) as ctxt: self.assertTrue(ctxt.eval("i == i")) self.assertTrue(ctxt.eval("b == b")) self.assertTrue(ctxt.eval("o == o"))
def testObject(self): with JSContext() as ctxt: o = ctxt.eval("new Object()") self.assertTrue(hash(o) > 0) o1 = toolkit.clone(o) self.assertEqual(hash(o1), hash(o)) self.assertTrue(o != o1)
def testMultiContext(self): with JSContext() as ctxt0: ctxt0.security_token = "password" global0 = ctxt0.locals global0.custom = 1234 self.assertEqual(1234, int(global0.custom)) with JSContext() as ctxt1: ctxt1.security_token = ctxt0.security_token global1 = ctxt1.locals global1.custom = 1234 with ctxt0: self.assertEqual(1234, int(global0.custom)) self.assertEqual(1234, int(global1.custom))
def testCall(self): class Hello(object): def __call__(self, name): return "hello " + name class Global(JSClass): hello = Hello() with JSContext(Global()) as ctxt: self.assertEqual("hello world", ctxt.eval("hello('world')"))
def testCompile(self): with JSContext(): with JSEngine() as engine: s = engine.compile("1+2") self.assertTrue(isinstance(s, JSScript)) self.assertEqual("1+2", s.source) self.assertEqual(3, int(s.run())) self.assertRaises(SyntaxError, engine.compile, "1+")
def testJavascriptWrapper(self): with JSContext() as ctxt: self.assertEqual(type(JSNull), type(ctxt.eval("null"))) self.assertEqual(type(JSUndefined), type(ctxt.eval("undefined"))) self.assertEqual(bool, type(ctxt.eval("true"))) self.assertEqual(str, type(ctxt.eval("'test'"))) self.assertEqual(int, type(ctxt.eval("123"))) self.assertEqual(float, type(ctxt.eval("3.14"))) self.assertEqual(datetime.datetime, type(ctxt.eval("new Date()"))) self.assertEqual(JSObject, type(ctxt.eval("[1, 2, 3]"))) self.assertEqual(JSObject, type(ctxt.eval("(function() {})"))) self.assertEqual(JSObject, type(ctxt.eval("new Object()")))
def testObjectBuiltInMethods(self): class Global(JSClass): version = 1.0 with JSContext(Global()) as ctxt: self.assertEqual("[object Global]", str(ctxt.eval("this.toString()"))) self.assertEqual("[object Global]", str(ctxt.eval("this.toLocaleString()"))) self.assertEqual(Global.version, float(ctxt.eval("this.valueOf()").version)) self.assertTrue(bool(ctxt.eval("this.hasOwnProperty(\"version\")"))) self.assertFalse(ctxt.eval("this.hasOwnProperty(\"nonexistent\")"))
def testClassicStyleObject(self): class FileSystemWrapper: @property def cwd(self): return os.getcwd() class Global: @property def fs(self): return FileSystemWrapper() with JSContext(Global()) as ctxt: self.assertEqual(os.getcwd(), ctxt.eval("fs.cwd"))
def test(): with JSContext() as ctxt: fn = ctxt.eval("(function (obj) { obj.say(); })") obj = Hello() self.assertEqual(2, sys.getrefcount(obj)) fn(obj) self.assertEqual(4, sys.getrefcount(obj)) del obj
def run(): with JSIsolate(): with JSContext(g) as ctxt: ctxt.eval(""" started.wait(); for (i=0; i<10; i++) { sleep(100); } finished.release(); """)
def testMultiDimArray(self): with JSContext() as ctxt: ret = ctxt.eval(""" ({ 'test': function(){ return [ [ 1, 'abla' ], [ 2, 'ajkss' ], ] } }) """).test() self.assertEqual([[1, 'abla'], [2, 'ajkss']], convert(ret))
def testUnicodeSource(self): class Global(JSClass): var = u'测试' def __getattr__(self, name): if name: return self.var return JSClass.__getattr__(self, name) g = Global() with JSContext(g) as ctxt: with JSEngine() as engine: src = u""" function 函数() { return 变量.length; } 函数(); var func = function () {}; """ s = engine.compile(src) self.assertTrue(isinstance(s, JSScript)) self.assertEqual(src, s.source) self.assertEqual(2, s.run()) func_name = u'函数' self.assertTrue(hasattr(ctxt.locals, func_name)) func = getattr(ctxt.locals, func_name) self.assertTrue(isinstance(func, JSObject)) self.assertEqual(func_name, toolkit.get_name(func)) self.assertEqual("", toolkit.resource_name(func)) self.assertEqual(1, toolkit.line_number(func)) self.assertEqual(0, toolkit.line_offset(func)) self.assertEqual(0, toolkit.column_offset(func)) var_name = u'变量' setattr(ctxt.locals, var_name, u'测试长字符串') self.assertEqual(6, func()) self.assertEqual("func", toolkit.inferred_name(ctxt.locals.func))
def _testOutOfMemory(self): with JSIsolate(): JSEngine.setMemoryLimit(max_young_space_size=16 * 1024, max_old_space_size=4 * 1024 * 1024) with JSContext() as ctxt: JSEngine.ignoreOutOfMemoryException() ctxt.eval("var a = new Array(); while(true) a.push(a);") self.assertTrue(ctxt.hasOutOfMemoryException) JSEngine.setMemoryLimit() JSEngine.collect()
def testReferenceError(self): class Global(JSClass): def __init__(self): self.s = self with JSContext(Global()) as ctxt: self.assertRaises(ReferenceError, ctxt.eval, 'x') self.assertTrue(ctxt.eval("typeof(x) === 'undefined'")) self.assertTrue(ctxt.eval("typeof(String) === 'function'")) self.assertTrue(ctxt.eval("typeof(s.String) === 'undefined'")) self.assertTrue(ctxt.eval("typeof(s.z) === 'undefined'"))
def testRaiseExceptionInGetter(self): class Document(JSClass): def __getattr__(self, name): if name == 'y': raise TypeError() return JSClass.__getattr__(self, name) class Global(JSClass): def __init__(self): self.document = Document() with JSContext(Global()) as ctxt: self.assertEqual(JSUndefined, ctxt.eval('document.x')) self.assertRaises(TypeError, ctxt.eval, 'document.y')