marsliteng / pyv8

Automatically exported from code.google.com/p/pyv8
0 stars 0 forks source link

JSFunction.apply is broken #218

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Run the following code:

#---------------

import PyV8

class PyObj(object):
    def __init__(self, js_func):
        self.foob = "Hello"
        self.js_func = js_func

    def call_func(self):
        self.js_func.call(self)
    def apply_func(self):
        self.js_func.apply(self, [])

class Global(object):
    Obj = PyObj

    def out(self, v):
        print "-- Script out: %s --" % (v,)

def run_case(js):
    ctxt = PyV8.JSContext(Global())
    with ctxt:
        ctxt.eval(js)

run_case("""
    o = Obj(function () { out("this.foob = " + this.foob); });
    o.call_func();
    o.apply_func();
    """)

#---------------

The output is:

-- Script out: this.foob = Hello --
Traceback (most recent call last):
  File "pyv8-218.py", line 31, in <module>
    """)
  File "pyv8-218.py", line 24, in run_case
    ctxt.eval(js)
TypeError: TypeError: <__main__.PyObj object at 0x105d83690> is not JSON 
serializable (  @ 4 : 6 )  ->     o.apply_func();

#---------------

The problem is in the JSFunction.apply shim in PyV8.py:

#---------------

def func_apply(self, thisArg, argArray=[]):
    if isinstance(thisArg, JSObject):
        return self.invoke(thisArg, argArray)

    this = JSContext.current.eval("(%s)" % json.dumps(thisArg))

    return self.invoke(this, argArray)

JSFunction.apply = func_apply

#---------------

Indeed, if I comment this code out, then the above code works as expected:

-- Script out: this.foob = Hello --
-- Script out: this.foob = Hello --

Original issue reported on code.google.com by csaft...@gmail.com on 18 Dec 2013 at 6:20

GoogleCodeExporter commented 9 years ago
In fact, the current Object.apply was implemented as Python script, which pass 
the arguments with JSON. 

So, we need a native Object.apply later to support your scenes

def func_apply(self, thisArg, argArray=[]):
    if isinstance(thisArg, JSObject):
        return self.invoke(thisArg, argArray)

    this = JSContext.current.eval("(%s)" % json.dumps(thisArg))

    return self.invoke(this, argArray)

JSFunction.apply = func_apply

Original comment by flier...@gmail.com on 24 Dec 2013 at 4:32

GoogleCodeExporter commented 9 years ago
I have implement function.apply with native support, please verify the fix with 
SVN trunk code after r565

Original comment by flier...@gmail.com on 24 Dec 2013 at 5:36