Browse Source

Implement direct iteration on JS generators

Stefan Siegl 9 years ago
parent
commit
e686603b89
2 changed files with 103 additions and 14 deletions
  1. 57 0
      tests/generators_from_v8_002.phpt
  2. 46 14
      v8js_v8object_class.cc

+ 57 - 0
tests/generators_from_v8_002.phpt

@@ -0,0 +1,57 @@
+--TEST--
+Test V8::executeString() : Generators V8 -> PHP (direct)
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--FILE--
+<?php
+
+$js = <<<EOJS
+function* TheGen() {
+  for(var i = 0; i < 4; i ++) {
+    yield i;
+  }
+}
+
+TheGen();
+EOJS;
+
+$v8 = new V8Js();
+$gen = $v8->executeString($js);
+
+var_dump($gen->current());
+
+// JS generators don't have the key concept (-> just "false")
+var_dump($gen->key());
+
+// fetching multiple times shouldn't leak
+var_dump($gen->current());
+var_dump($gen->current());
+
+$gen->next(); // 1
+var_dump($gen->current());
+
+$gen->next(); // 2
+var_dump($gen->current());
+
+$gen->next(); // 3
+var_dump($gen->current());
+var_dump($gen->valid());
+
+$gen->next(); // undef
+var_dump($gen->current());
+var_dump($gen->valid());
+
+?>
+===EOF===
+--EXPECTF--
+int(0)
+bool(false)
+int(0)
+int(0)
+int(1)
+int(2)
+int(3)
+bool(true)
+NULL
+bool(false)
+===EOF===

+ 46 - 14
v8js_v8object_class.cc

@@ -479,14 +479,14 @@ static void v8js_v8generator_free_storage(zend_object *object) /* {{{ */
 
 static zend_object *v8js_v8generator_new(zend_class_entry *ce) /* {{{ */
 {
-	v8js_v8object *c;
-	c = (v8js_v8object *) ecalloc(1, sizeof(v8js_v8generator) + zend_object_properties_size(ce));
+	v8js_v8generator *c;
+	c = (v8js_v8generator *) ecalloc(1, sizeof(v8js_v8generator) + zend_object_properties_size(ce));
 
-	zend_object_std_init(&c->std, ce);
-	c->std.handlers = &v8js_v8object_handlers;
-	new(&c->v8obj) v8::Persistent<v8::Value>();
+	zend_object_std_init(&c->v8obj.std, ce);
+	c->v8obj.std.handlers = &v8js_v8generator_handlers;
+	new(&c->v8obj.v8obj) v8::Persistent<v8::Value>();
 
-	return &c->std;
+	return &c->v8obj.std;
 }
 /* }}} */
 
@@ -539,6 +539,17 @@ static void v8js_v8generator_next(v8js_v8generator *g) /* {{{ */
 }
 /* }}} */
 
+static zend_function *v8js_v8generator_get_method(zend_object **object_ptr, zend_string *method, const zval *key) /* {{{ */
+{
+	zend_function *result = std_object_handlers.get_method(object_ptr, method, key);
+
+	if(!result) {
+		result = v8js_v8object_get_method(object_ptr, method, key);
+	}
+
+	return result;
+}
+/* }}} */
 
 /* {{{ proto V8Generator::__construct()
  */
@@ -575,6 +586,11 @@ PHP_METHOD(V8Generator, __wakeup)
 PHP_METHOD(V8Generator, current)
 {
 	v8js_v8generator *g = Z_V8JS_V8GENERATOR_OBJ_P(getThis());
+
+	if(!g->primed) {
+		v8js_v8generator_next(g);
+	}
+
 	RETVAL_ZVAL(&g->value, 1, 0);
 }
 /* }}} */
@@ -660,16 +676,31 @@ static const zend_function_entry v8js_v8function_methods[] = { /* {{{ */
 };
 /* }}} */
 
+ZEND_BEGIN_ARG_INFO(arginfo_v8generator_current, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_v8generator_key, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_v8generator_next, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_v8generator_rewind, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_v8generator_valid, 0)
+ZEND_END_ARG_INFO()
+
 static const zend_function_entry v8js_v8generator_methods[] = { /* {{{ */
-	PHP_ME(V8Generator,	__construct,			NULL,				ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
-	PHP_ME(V8Generator,	__sleep,				NULL,				ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
-	PHP_ME(V8Generator,	__wakeup,				NULL,				ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+	PHP_ME(V8Generator,	__construct,			NULL,							ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+	PHP_ME(V8Generator,	__sleep,				NULL,							ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+	PHP_ME(V8Generator,	__wakeup,				NULL,							ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
 
-	PHP_ME(V8Generator,	current,				NULL,				ZEND_ACC_PUBLIC)
-	PHP_ME(V8Generator,	key,					NULL,				ZEND_ACC_PUBLIC)
-	PHP_ME(V8Generator,	next,					NULL,				ZEND_ACC_PUBLIC)
-	PHP_ME(V8Generator,	rewind,					NULL,				ZEND_ACC_PUBLIC)
-	PHP_ME(V8Generator,	valid,					NULL,				ZEND_ACC_PUBLIC)
+	PHP_ME(V8Generator,	current,				arginfo_v8generator_current,	ZEND_ACC_PUBLIC)
+	PHP_ME(V8Generator,	key,					arginfo_v8generator_key,		ZEND_ACC_PUBLIC)
+	PHP_ME(V8Generator,	next,					arginfo_v8generator_next,		ZEND_ACC_PUBLIC)
+	PHP_ME(V8Generator,	rewind,					arginfo_v8generator_rewind,		ZEND_ACC_PUBLIC)
+	PHP_ME(V8Generator,	valid,					arginfo_v8generator_valid,		ZEND_ACC_PUBLIC)
 
 	{NULL, NULL, NULL}
 };
@@ -720,6 +751,7 @@ PHP_MINIT_FUNCTION(v8js_v8object_class) /* {{{ */
 
 	/* V8Generator handlers */
 	memcpy(&v8js_v8generator_handlers, &v8js_v8object_handlers, sizeof(zend_object_handlers));
+	v8js_v8generator_handlers.get_method = v8js_v8generator_get_method;
 	v8js_v8generator_handlers.offset = XtOffsetOf(struct v8js_v8generator, v8obj.std);
 	v8js_v8generator_handlers.free_obj = v8js_v8generator_free_storage;