phpv8 / v8js

V8 Javascript Engine for PHP — This PHP extension embeds the Google V8 Javascript Engine
http://pecl.php.net/package/v8js
MIT License
1.83k stars 200 forks source link

Unexpected TypeError: Illegal invocation #262

Closed tahpot closed 7 years ago

tahpot commented 8 years ago

I have a strange problem, which unfortunately I can't isolate out of my actual code (sorry, I tried really hard!).

This code is being executed as Javascript within v8js:

// this works
var customer = r.getModel("customer", "65a704f8d138e4153e0044e7");
print(customer.name+"\n");

// this works
var office = customer.getRelated("office");
print(office.name+"\n");

// this doesn't work, it throws a TypeError: Illegal invocation
var address = office.getRelated("address");

Customer and office are both separate PHP objects that inherit from a common object that implements the getRelated() method.

Now, what doesn't make sense is office.getRelated is definitely an object with a getRelated() function:

var_dump(office.getRelated)

produces:

object(Closure)#1881690089 {
    function () { [native code] }
}

From my testing I can see the TypeError thrown in Javascript definitely halts execution as there is no debug tracing coming from the getRelated() method, eliminating a problem within the method.

The exact same code running on an old version of v8js (>6m old) and PHP5 works without any issue.

The code has another method getRelatedOne(). If I replace getRelated() in the code above with getRelatedOne(), the TypeError is still thrown however if I use getRelated() and then getRelatedOne(), the code works fine.

Is it possible there is some sort of memory issue with two objects sharing the same method definition?

stesie commented 8 years ago

Does your code run within the web browser or within PHP CLI SAPI? Generally debugging is easier with CLI interface.

I suppose you can't share the whole (or at least the required) code with us? :)

Are you running on GNU/Linux? If so I probably can drive you through a debugging session remotely.

If you can make it work with CLI SAPI a first simple step would be to run php within the GNU debugger (gdb) and simply have a first look at the stack trace. Maybe we can already get an idea what's going on from there.

If you suppose it's sort of a memory issue it might be helpful to compile PHP with V8Js statically and link against Address Sanitizer (libasan). I'd happily guide you through this, if needed. Maybe just elaborate a bit more on your setup.

tahpot commented 8 years ago

Thanks stesie.

I'll see what I can try to find with gdb first...

chrisbckr commented 5 years ago

I have this same issue and you can simply reproduce with this code:

class BaseClass {
    public function bla() {
        echo "print bla";
    }
}

class Foo extends BaseClass {

}

class Bar extends BaseClass {
}

$v8 = new V8Js('PHP');
$v8->Foo = new Foo();
$v8->Bar = new Bar();

$code = <<<EOT

var_dump(PHP.Foo);
var_dump(PHP.Bar);

var_dump(PHP.Foo.bla());
var_dump(PHP.Bar.bla());
EOT;

$v8->executeString($code, 'test');

Result:

object(Foo)#1792350 (1) {
  ["bla"] =>
  object(Closure)#914656 {
      function () { [native code] }
  }
}
object(Bar)#1323981 (1) {
  ["bla"] =>
  object(Closure)#914656 {
      function () { [native code] }
  }
}
print blaNULL
PHP Fatal error:  Uncaught V8JsScriptException: test:6: TypeError: Illegal invocation in /root/v8js/teste.php:28
Stack trace:
#0 /root/v8js/teste.php(28): V8Js->executeString('\nvar_dump(PHP.F...', 'test')
#1 {main}
  thrown in /root/v8js/teste.php on line 28

Fatal error: Uncaught V8JsScriptException: test:6: TypeError: Illegal invocation in /root/v8js/teste.php:28
Stack trace:
#0 /root/v8js/teste.php(28): V8Js->executeString('\nvar_dump(PHP.F...', 'test')
#1 {main}
  thrown in /root/v8js/teste.php on line 28

PHP 7.0.32-2+0 20181015120515.7+jessie~1.gbpa6b8cf (cli) (built: Oct 15 2018 19:38:45) ( NTS ) libv8 7.2.99