Skip to content

Compromise between FORCE_ARRAY and standard setup #511

Closed as not planned
Closed as not planned
@redbullmarky

Description

@redbullmarky

Hey!
I wonder if there is medium that could be added between the standard setup and the setup with FORCE_ARRAY?
We use FORCE_ARRAY mostly for legacy reasons (many years ago, it was easy to segfault standard mode from user code, whereas FORCE_ARRAY was mostly protected), but also because 99% of the time when passing back objects, associative arrays are want we want in PHP.

However, the benefit of standard mode is the use of 'this'. A basic example of how we sort of implement things:

// the main runner...
$v8js = new V8Js('cs');
$userCode = ...get user code...;
$result = $v8js->executeString('
   function userCode() {
      ' . $userCode . '
   }
   result = userCode();
', null, V8Js::FLAG_FORCE_ARRAY);

and some example 'userCode':

return {
   main: function (param1, param2) {
   }

  somefunc: function (param1) {
  }
}

This means the user can write 'hooks' that are called on the $result, e.g. $result['main']($someval, $otherVal); at various points. This works well, but as userCode gets more complex, you often want to use this to organise things better:

return {
   name: "foo",

   main: function (param1, param2) {
      return somevar = this.somefunc(param1) + param2;
   },

   somefunc: function (param1) {
      return this.name;
   }

   another: function () {
      return [
         "foo": "alice",
         "bar": "bob"
      ];
   }
}

or something like that. The problem though, is FORCE_ARRAY returns, well, an array and not a V8Object, so the concept of this doesn't exist.

On the flipside, if we use it as standard without FORCE_ARRAY, then (using the last example):

function someThingInPHP(array $array) {
}

someThingInPHP($result->another());

This will result in a fatal error because $result->another() will return a V8Object, not an array so the typehint will fatal.

So I guess I'm wondering if there is a halfway house, where BOTH could be used somewhat. MAYBE something like:

  1. Add an extra option, such as AUTO_CONVERT or whatever (doesn't matter what it's called at this point)
  2. This will essentially work 99% like FORCE_ARRAY entirely, with some exceptions:
  3. Date objects and some of the other clever things, those will remain - so anything not a V8Function or V8Object will remain as they are. PHP will get the object.
  4. Then - either a class can be instantiated in JS (and as its constructor.name is not V8Object, it will be left alone) - or an extra feature/special wrapper object can be utilised to wrap a JS object to 'protect' it from conversion to an array.
  5. Otherwise, any other associative array would be converted to a PHP associative array.
  6. This would apply to both assoc arrays returned from JS, as well as those passed in to extra custom functions attached to the V8Js instance (i.e. $v8js->someFunc = function (array $settings) { };)

TLDR: Introduce an option almost entirely like FORCE_ARRAY, but with a handful of exceptions and the ability to skip conversion at runtime for certain objects.

Any thoughts? @stesie

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions