ソースを参照

Implement delete behaviour on ArrayAccess objects

Stefan Siegl 10 年 前
コミット
1b027a525f
4 ファイル変更104 行追加2 行削除
  1. 57 0
      tests/array_access_007.phpt
  2. 44 0
      v8js_array_access.cc
  3. 2 1
      v8js_array_access.h
  4. 1 1
      v8js_object_export.cc

+ 57 - 0
tests/array_access_007.phpt

@@ -0,0 +1,57 @@
+--TEST--
+Test V8::executeString() : Delete (unset) ArrayAccess keys
+--SKIPIF--
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
+--INI--
+v8js.use_array_access = 1
+--FILE--
+<?php
+
+class MyArray implements ArrayAccess, Countable {
+    private $data = Array('one', 'two', 'three');
+
+    public function offsetExists($offset) {
+	return isset($this->data[$offset]);
+    }
+
+    public function offsetGet($offset) {
+	if(!$this->offsetExists($offset)) {
+	    return null;
+	}
+	return $this->data[$offset];
+    }
+
+    public function offsetSet($offset, $value) {
+	$this->data[$offset] = $value;
+    }
+
+    public function offsetUnset($offset) {
+	unset($this->data[$offset]);
+    }
+
+    public function count() {
+        return max(array_keys($this->data)) + 1;
+    }
+}
+
+$v8 = new V8Js();
+$v8->myarr = new MyArray();
+
+$js = <<<EOF
+var jsarr = [ "one", "two", "three" ];
+delete jsarr[1];
+var_dump(jsarr.join(","));
+
+delete PHP.myarr[1];
+var_dump(PHP.myarr.join(","));
+
+EOF;
+
+$v8->executeString($js);
+
+?>
+===EOF===
+--EXPECT--
+string(10) "one,,three"
+string(10) "one,,three"
+===EOF===

+ 44 - 0
v8js_array_access.cc

@@ -229,6 +229,50 @@ void php_v8js_array_access_length(v8::Local<v8::String> property, const v8::Prop
 }
 /* }}} */
 
+void php_v8js_array_access_deleter(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) /* {{{ */
+{
+	v8::Isolate *isolate = info.GetIsolate();
+	v8::Local<v8::Object> self = info.Holder();
+
+	V8JS_TSRMLS_FETCH();
+
+	v8::Local<v8::Value> php_object = self->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY));
+	zval *object = reinterpret_cast<zval *>(v8::External::Cast(*php_object)->Value());
+	zend_class_entry *ce = Z_OBJCE_P(object);
+
+	/* Okay, let's call offsetUnset. */
+	zend_fcall_info fci;
+	zval *php_value;
+
+	zval fmember;
+	INIT_ZVAL(fmember);
+	ZVAL_STRING(&fmember, "offsetUnset", 0);
+
+	zval zindex;
+	INIT_ZVAL(zindex);
+	ZVAL_LONG(&zindex, index);
+
+	fci.size = sizeof(fci);
+	fci.function_table = &ce->function_table;
+	fci.function_name = &fmember;
+	fci.symbol_table = NULL;
+	fci.retval_ptr_ptr = &php_value;
+
+	zval *zindex_ptr = &zindex;
+	zval **zindex_ptr_ptr = &zindex_ptr;
+	fci.param_count = 1;
+	fci.params = &zindex_ptr_ptr;
+
+	fci.object_ptr = object;
+	fci.no_separation = 0;
+
+	zend_call_function(&fci, NULL TSRMLS_CC);
+	zval_ptr_dtor(&php_value);
+	info.GetReturnValue().Set(V8JS_BOOL(true));
+}
+/* }}} */
+
+
 void php_v8js_array_access_enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) /* {{{ */
 {
 	v8::Isolate *isolate = info.GetIsolate();

+ 2 - 1
v8js_array_access.h

@@ -21,7 +21,8 @@ void php_v8js_array_access_setter(uint32_t index, v8::Local<v8::Value> value,
 void php_v8js_array_access_length(v8::Local<v8::String> property,
 				  const v8::PropertyCallbackInfo<v8::Value>& info);
 void php_v8js_array_access_enumerator(const v8::PropertyCallbackInfo<v8::Array>& info);
-
+void php_v8js_array_access_deleter(uint32_t index,
+				   const v8::PropertyCallbackInfo<v8::Boolean>& info);
 
 /* Named Property Handlers */
 void php_v8js_array_access_named_getter(v8::Local<v8::String> property,

+ 1 - 1
v8js_object_export.cc

@@ -886,7 +886,7 @@ static v8::Handle<v8::Object> php_v8js_wrap_object(v8::Isolate *isolate, zend_cl
 					inst_tpl->SetIndexedPropertyHandler(php_v8js_array_access_getter,
 														php_v8js_array_access_setter,
 														0, /* query */
-														0, /* deleter */
+														php_v8js_array_access_deleter,
 														php_v8js_array_access_enumerator);
 
 					/* Switch to special ArrayAccess getter, which falls back to