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.84k stars 200 forks source link

Allow extension of V8Object / V8Function #422

Open redbullmarky opened 5 years ago

redbullmarky commented 5 years ago

If i do something like the following:

class MyV8 extends V8Js {
    function foo($payload) {
        echo $payload['name']; // nope :-(
        echo $payload->name; // this is ok.
    }
}

$v8 = new MyV8('myv8');
$v8->executeString('myv8.foo({ name:"Testing" })')

then i'll get a "Cannot use object of type V8Object as array" error. This is unless I use FLAG_FORCE_ARRAY. If we were calling ::foo() via PHP, it'd be quite normal to be passing an array (e.g $this->foo(['name' => 'Testing']) ) and not an object instance - so I cannot share the function between the JS and PHP space without conditional conversions.

I don't use FLAG_FORCE_ARRAY as I find the default setup generally more useful, and because it just blanket applies to everything. Anyway... Would it be feasible to offer (at initialisation) PHP classes that would extend the default V8Object/V8Function, etc so that we could perhaps deal with these sorts of cases? Then this would be possible:

class MyV8Object extends V8Object implements ArrayAccess {
}

so the FLAG_FORCE_ARRAY-type functionality can be much more selective.

Cheers Mark

stesie commented 4 years ago

Uhhoh, the issue already is a bit dated :)

... anyways, I'd personally propose to have actual proxy objects that wrap V8Object itself and let php-v8js create those proxies automatically. php-v8js overrides the internal object callbacks so it can call back to V8/JS world as needed; so directly extending should theoretically still be possible but mix concerns.

So I would do something like this instead:

class MyV8Object implements ArrayAccess {
  private $ref;

  function __construct(\V8Object $v8obj) {
    $this->ref = $v8obj;
  }

  // do whatever ...
}

... on the C-side you'd have to add to v8js_v8object_create and let it modify res, i.e. trigger proxy object creation.

HTH