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

Segfault on object construction in JS (on PHP object) #15

Closed stesie closed 11 years ago

stesie commented 11 years ago

Hi again :-)

got another one, inspired by the function template thing ... the objects passed back to from PHP to JavaScript have a constructor attribute pointing to the constructor function (i.e. function template from before). If you call that one in JavaScript you get fresh extra objects, ... however if you call back to PHP everything crashes since v8js relies on the internal fields, which are not initialized however.

Example code, first showing use of constructor attribute in JavaScript, then with PHP & JavaScript in combination:

$v8 = new V8Js();

class Greeter {
    function sayHello($a) {
        echo "Hello $a\n";
    }   
}

$v8->greeter = new Greeter();
$v8->executeString('
    function JsGreeter() { };
    JsGreeter.prototype.sayHello = function(a) {
        print("Hello " + a + "\n");
    };

    jsGreeter = new JsGreeter();
    jsGreeter.sayHello("Paul");

    jsGreeterNg = new jsGreeter.constructor();
    jsGreeterNg.sayHello("George");

    // -----  now the same using v8Js  -----

    PHP.greeter.sayHello("John");       // prints "Hello John" as expected

    print(PHP.greeter);                 // prints "[object Greeter]" as expected
    print("\n");

    // What about the constructor function of greeter?
    print(PHP.greeter.constructor);
    // ... yields "function Greeter() { [native code] }"

    // ... super, so let me create more greeters
    var ngGreeter = new PHP.greeter.constructor();
    ngGreeter.sayHello("Ringo");        // well, segfaults
');

cheers, stesie

beest commented 11 years ago

@stesie this is an interesting one!

I'm not sure what the mechanism is to expose a constructor to JS via the V8 engine. I'd guess this hasn't been covered in the current V8JS code, so this is likely to be a feature that isn't covered yet rather than a bug.

stesie commented 11 years ago

Actually I don't mind if we call this a bug or feature or just issue. After all I stumbled over it, I actually don't need it, but for the moment just wanted to write it down since it crashes the process ...

I guess we can't directly expose the constructor of the PHP class. The v8::FunctionTemplate however has a SetCallHandler method, which according to the API reference

Set the call-handler callback for a FunctionTemplate. This callback is called whenever the function created from this FunctionTemplate is called.

The v8::Arguments passed to the callback function then has a boolean property IsConstructCall, ... which probably is set to true. But haven't done any testing on that.

In that particular case we probably have to create a PHP class instance from v8js, running the PHP class'es __construct function and attach a pointer to the newly allocated PHP class instance to v8's internal field.

I think I'll have a go to implement that the upcoming days, but will concentrate on issue #13 before, as that's more of a show-stopper to me :-)

stesie commented 11 years ago

hey there,

just wanted to let you know that I've started working on a fix to this issue. I already got it working basically, current version at https://github.com/stesie/v8js/commits/fix-constructor-call

cheers, stesie