0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-11-09 15:18:41 +00:00

Implement JS-side wrapper around PHP Generator objects

This commit is contained in:
Stefan Siegl 2016-01-09 12:50:40 +01:00
parent 38b9c053a1
commit a18ae9e853
6 changed files with 163 additions and 3 deletions

View File

@ -180,6 +180,7 @@ int main ()
v8js_commonjs.cc \ v8js_commonjs.cc \
v8js_convert.cc \ v8js_convert.cc \
v8js_exceptions.cc \ v8js_exceptions.cc \
v8js_generator_export.cc \
v8js_methods.cc \ v8js_methods.cc \
v8js_object_export.cc \ v8js_object_export.cc \
v8js_timer.cc \ v8js_timer.cc \
@ -190,3 +191,10 @@ int main ()
PHP_ADD_MAKEFILE_FRAGMENT PHP_ADD_MAKEFILE_FRAGMENT
fi fi
dnl Local variables:
dnl tab-width: 4
dnl c-basic-offset: 4
dnl End:
dnl vim600: noet sw=4 ts=4 fdm=marker
dnl vim<600: noet sw=4 ts=4

View File

@ -17,11 +17,10 @@ if (PHP_V8JS != "no") {
AC_DEFINE("PHP_V8_API_VERSION", "4007075", "", false); AC_DEFINE("PHP_V8_API_VERSION", "4007075", "", false);
AC_DEFINE("PHP_V8_VERSION", "4.7.75", "", true); AC_DEFINE("PHP_V8_VERSION", "4.7.75", "", true);
EXTENSION("v8js", "v8js_array_access.cc v8js.cc v8js_class.cc v8js_commonjs.cc v8js_convert.cc v8js_exceptions.cc v8js_methods.cc v8js_object_export.cc v8js_timer.cc v8js_v8.cc v8js_v8object_class.cc v8js_variables.cc", "yes"); EXTENSION("v8js", "v8js_array_access.cc v8js.cc v8js_class.cc v8js_commonjs.cc v8js_convert.cc v8js_exceptions.cc v8js_generator_export.cc v8js_methods.cc v8js_object_export.cc v8js_timer.cc v8js_v8.cc v8js_v8object_class.cc v8js_variables.cc", "yes");
} else { } else {
WARNING("v8js not enabled, headers or libs not found"); WARNING("v8js not enabled, headers or libs not found");
} }
} }

View File

@ -0,0 +1,41 @@
--TEST--
Test V8::executeString() : Generators PHP -> V8
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
function TheGenerator()
{
for($i = 0; $i < 4; $i ++) {
yield $i;
}
}
foreach(TheGenerator() as $i) {
var_dump($i);
}
$js = <<<EOJS
for(var i of PHP.gen) {
var_dump(i);
}
EOJS;
$v8 = new V8Js();
$v8->gen = TheGenerator();
$gen = $v8->executeString($js);
?>
===EOF===
--EXPECTF--
int(0)
int(1)
int(2)
int(3)
int(0)
int(1)
int(2)
int(3)
===EOF===

73
v8js_generator_export.cc Normal file
View File

@ -0,0 +1,73 @@
/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 2016 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
| Author: Stefan Siegl <stesie@php.net> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include "php_v8js_macros.h"
v8::Local<v8::Value> v8js_wrap_generator(v8js_ctx *ctx, v8::Local<v8::Value> wrapped_object) /* {{{ */
{
v8::Local<v8::Value> result;
V8JS_CTX_PROLOGUE_EX(ctx, result);
assert(!wrapped_object.IsEmpty());
assert(wrapped_object->IsObject());
v8::TryCatch try_catch;
v8::Local<v8::String> source = v8::String::NewFromUtf8(ctx->isolate, "(\
function(wrapped_object) { \
return (function*() { \
for(;;) { \
if(!wrapped_object.valid()) { \
return; \
} \
yield wrapped_object.current(); \
wrapped_object.next(); \
} \
})(); \
})");
v8::Local<v8::Script> script = v8::Script::Compile(source);
if(script.IsEmpty()) {
zend_error(E_ERROR, "Failed to compile Generator object wrapper");
return result;
}
v8::Local<v8::Value> wrapper_fn_val = script->Run();
if(wrapper_fn_val.IsEmpty() || !wrapper_fn_val->IsFunction()) {
zend_error(E_ERROR, "Failed to create Generator object wrapper function");
return result;
}
v8::Local<v8::Function> wrapper_fn = v8::Local<v8::Function>::Cast(wrapper_fn_val);
v8::Local<v8::Value> *jsArgv = static_cast<v8::Local<v8::Value> *>(alloca(sizeof(v8::Local<v8::Value>)));
new(&jsArgv[0]) v8::Local<v8::Value>;
jsArgv[0] = v8::Local<v8::Value>::New(isolate, wrapped_object);
result = wrapper_fn->Call(V8JS_GLOBAL(isolate), 1, jsArgv);
return result;
}
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

28
v8js_generator_export.h Normal file
View File

@ -0,0 +1,28 @@
/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 2016 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
| Author: Stefan Siegl <stesie@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef V8JS_GENERATOR_EXPORT_H
#define V8JS_GENERATOR_EXPORT_H
v8::Local<v8::Value> v8js_wrap_generator(v8js_ctx *ctx, v8::Local<v8::Value> wrapped_object);
#endif /* V8JS_GENERATOR_EXPORT_H */
/*
* Local variables:
* mode: c++
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

View File

@ -17,6 +17,7 @@
#include "php_v8js_macros.h" #include "php_v8js_macros.h"
#include "v8js_array_access.h" #include "v8js_array_access.h"
#include "v8js_generator_export.h"
#include "v8js_object_export.h" #include "v8js_object_export.h"
#include "v8js_v8object_class.h" #include "v8js_v8object_class.h"
@ -26,6 +27,7 @@ extern "C" {
#include "zend_interfaces.h" #include "zend_interfaces.h"
#include "zend_closures.h" #include "zend_closures.h"
#include "zend_exceptions.h" #include "zend_exceptions.h"
#include "zend_generators.h"
} }
static void v8js_weak_object_callback(const v8::WeakCallbackData<v8::Object, zend_object> &data); static void v8js_weak_object_callback(const v8::WeakCallbackData<v8::Object, zend_object> &data);
@ -955,7 +957,16 @@ v8::Handle<v8::Value> v8js_hash_to_jsobj(zval *value, v8::Isolate *isolate TSRML
/* If it's a PHP object, wrap it */ /* If it's a PHP object, wrap it */
if (ce) { if (ce) {
return v8js_wrap_object(isolate, ce, value TSRMLS_CC); v8::Local<v8::Value> wrapped_object = v8js_wrap_object(isolate, ce, value TSRMLS_CC);
if (ce == zend_ce_generator) {
/* Wrap PHP Generator object in a wrapper function that provides
* ES6 style behaviour. */
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
wrapped_object = v8js_wrap_generator(ctx, wrapped_object);
}
return wrapped_object;
} }
/* Associative PHP arrays cannot be wrapped to JS arrays, convert them to /* Associative PHP arrays cannot be wrapped to JS arrays, convert them to