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

Can't access V8Object after V8Js instance is destroyed #258

Closed tahpot closed 8 years ago

tahpot commented 8 years ago

See the code below which always causes an exception saying the V8Js instance has been destroyed.

If the v8->executeString() is unwrapped to not be within a function, it works fine.

Wrapped in a function (throws exception):

<?php

$widget = [];

$code = <<< EOT
server.widget.func = function(val) {
    return "Hello "+val;
}

server.widget;
EOT;

function test($widget, $code) {
    $v8 = new \V8Js("server");
    $v8->widget = $widget;
    $result = $v8->executeString($code);
    //return $result;
}

$result = test($widget, $code);
echo $result['func']("world");

?>

Commented out version (works):

<?php

$widget = [];

$code = <<< EOT
server.widget.func = function(val) {
    return "Hello "+val;
}

server.widget;
EOT;

//function test($widget, $code) {
    $v8 = new \V8Js("server");
    $v8->widget = $widget;
    $result = $v8->executeString($code);
    //return $result;
//}

//$result = test($widget, $code);
echo $result['func']("world");

?>
stesie commented 8 years ago

This is actually intentional behaviour, the destructor of V8Js class shuts down the V8 engine and releases all memory. As the V8Object doesn't store the object itself, but instead simply points to V8's actual object, access isn't possible once the engine is shut down.

tahpot commented 8 years ago

Ok, thanks @stesie

If there was some way to pass around a V8Function object (perhaps if it was cloneable?) that would be very useful.

However, I should be able to get around this by wrapping the v8 engine and the V8Object in a containing class to keep them together and have them destroyed together.

pinepain commented 8 years ago

@stesie It's a bit late, but it seems to be storing reference to v8js js (and increment it refcount) in V8Function/V8Object could potentially solve this sort of problems. This approach did a good job in my extension.

stesie commented 8 years ago

@pinepain yes, I actually considered this when I added the shutdown on V8Js object deconstruction (after all V8Js used to not handle the case at all when I more and more took over the maintainer role)

I think its far more transparent to think of the V8Js object as the "engine object" and if you let it die, the engine is also stopped (and then marking all V8Object/V8Function instances as dead). And TBH v8js already has a lot of "magic" :)

pinepain commented 8 years ago

@stesie But I see nothing wrong to prevent engine to die "accidentally" when it may be in use. Though, this is a controversial question how such cases should be handled. While v8js provider very convenient way to deal with v8, such small addition may even improve user experience with it. I'm pretty sure this is not the last issue reported, even if you put description of this behavior in bold in readme.

And don't worry about "magic", in php-v8 I have quite the same sort of magic, but in userland code. I have a plan to cleanup and finish it and publish to github to have more eyes on it, so you'll see what magic can mean.

P.S.: on Jul 17 I mailed you to email address specified on you github profile (stesie at broken pipe) at the time of publishing my ext with asking give it a look and probably to discuss some ideas and approaches. It could be lost in your inbox, but if you interested, it would be nice to get in touch and discuss some approaches we follow in our extensions and potential improvements and abstraction on top of them, sure, if you are interested and have time for such kind of activity.

stesie commented 8 years ago

@pinepain I've received that email, but haven't found much time since then. So I already started playing around with it -- and since yesterday there's a package for Nix(OS) of it ;-)

pinepain commented 8 years ago

@stesie I have some scripts for v8 and extensions packaging in https://github.com/pinepain/php-v8/tree/master/scripts/ppa-packaging, hope, you may find in interesting. There are also scripts and formulas for homebrew packaging - https://github.com/pinepain/php-v8/tree/master/scripts/homebrew. If you will

If v8js depend on one of libv8 version available from my PPAs (https://launchpad.net/~pinepain) I can package v8js for you or you can use my scripts to that yourself. I thinks if some libv8 version missed it can be added easily. FY, I build extension using PHP from Ondřej Surý PHP PPA, but it should not be a problem to build against default php package in ubuntu. I also was thinking about having some common PPA with various extension that are not in Odrej's PPA, like my php-ref and php-v8, third-party php-ds and maybe any other.