mirror of
https://github.com/phpv8/v8js.git
synced 2024-12-22 14:01:53 +00:00
Implement property_exists()/isset()/empty() on wrapped JavaScript objects.
Fixes issue #32.
This commit is contained in:
parent
ba3fe2e27a
commit
035e6faa8b
107
tests/property_exists.phpt
Normal file
107
tests/property_exists.phpt
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8::executeString() : property_exists/isset/empty on wrapped JS objects
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
(function(exports) {
|
||||||
|
// begin module code
|
||||||
|
exports.hello = function() { return 'hello'; };
|
||||||
|
exports.isnull = null;
|
||||||
|
exports.isundefined = undefined;
|
||||||
|
exports.isfalse = false;
|
||||||
|
exports.iszero = 0;
|
||||||
|
exports.isquotezero = '0';
|
||||||
|
exports.isemptyarray = [];
|
||||||
|
exports.isemptystring = '';
|
||||||
|
exports.istrue = true;
|
||||||
|
// end module code
|
||||||
|
return exports;
|
||||||
|
})({})
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$exports = $v8->executeString($JS, 'basic.js');
|
||||||
|
|
||||||
|
echo "= isset() =\n";
|
||||||
|
echo "bogus: "; var_dump(isset( $exports->bogus ));
|
||||||
|
echo "hello: "; var_dump(isset( $exports->hello ));
|
||||||
|
echo "isnull: "; var_dump(isset( $exports->isnull ));
|
||||||
|
echo "isundefined: "; var_dump(isset( $exports->isundefined ));
|
||||||
|
echo "isfalse: "; var_dump(isset( $exports->isfalse ));
|
||||||
|
echo "iszero: "; var_dump(isset( $exports->iszero ));
|
||||||
|
echo "isquotezero: "; var_dump(isset( $exports->isquotezero ));
|
||||||
|
echo "isemptyarray: "; var_dump(isset( $exports->isemptyarray ));
|
||||||
|
echo "isemptystring: "; var_dump(isset( $exports->isemptystring ));
|
||||||
|
echo "istrue: "; var_dump(isset( $exports->istrue ));
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
echo "= empty() =\n";
|
||||||
|
echo "bogus: "; var_dump(empty( $exports->bogus ));
|
||||||
|
echo "hello: "; var_dump(empty( $exports->hello ));
|
||||||
|
echo "isnull: "; var_dump(empty( $exports->isnull ));
|
||||||
|
echo "isundefined: "; var_dump(empty( $exports->isundefined ));
|
||||||
|
echo "isfalse: "; var_dump(empty( $exports->isfalse ));
|
||||||
|
echo "iszero: "; var_dump(empty( $exports->iszero ));
|
||||||
|
echo "isquotezero: "; var_dump(empty( $exports->isquotezero ));
|
||||||
|
echo "isemptyarray: "; var_dump(empty( $exports->isemptyarray ));
|
||||||
|
echo "isemptystring: "; var_dump(empty( $exports->isemptystring ));
|
||||||
|
echo "istrue: "; var_dump(empty( $exports->istrue ));
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
echo "= property_exists() =\n";
|
||||||
|
echo "bogus: "; var_dump(property_exists( $exports, 'bogus' ));
|
||||||
|
echo "hello: "; var_dump(property_exists( $exports, 'hello' ));
|
||||||
|
echo "isnull: "; var_dump(property_exists( $exports, 'isnull' ));
|
||||||
|
echo "isundefined: "; var_dump(property_exists( $exports, 'isundefined' ));
|
||||||
|
echo "isfalse: "; var_dump(property_exists( $exports, 'isfalse' ));
|
||||||
|
echo "iszero: "; var_dump(property_exists( $exports, 'iszero' ));
|
||||||
|
echo "isquotezero: "; var_dump(property_exists( $exports, 'isquotezero' ));
|
||||||
|
echo "isemptyarray: "; var_dump(property_exists( $exports, 'isemptyarray' ));
|
||||||
|
echo "isemptystring: "; var_dump(property_exists( $exports, 'isemptystring' ));
|
||||||
|
echo "istrue: "; var_dump(property_exists( $exports, 'istrue' ));
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECT--
|
||||||
|
= isset() =
|
||||||
|
bogus: bool(false)
|
||||||
|
hello: bool(true)
|
||||||
|
isnull: bool(false)
|
||||||
|
isundefined: bool(false)
|
||||||
|
isfalse: bool(true)
|
||||||
|
iszero: bool(true)
|
||||||
|
isquotezero: bool(true)
|
||||||
|
isemptyarray: bool(true)
|
||||||
|
isemptystring: bool(true)
|
||||||
|
istrue: bool(true)
|
||||||
|
|
||||||
|
= empty() =
|
||||||
|
bogus: bool(true)
|
||||||
|
hello: bool(false)
|
||||||
|
isnull: bool(true)
|
||||||
|
isundefined: bool(true)
|
||||||
|
isfalse: bool(true)
|
||||||
|
iszero: bool(true)
|
||||||
|
isquotezero: bool(true)
|
||||||
|
isemptyarray: bool(true)
|
||||||
|
isemptystring: bool(true)
|
||||||
|
istrue: bool(false)
|
||||||
|
|
||||||
|
= property_exists() =
|
||||||
|
bogus: bool(false)
|
||||||
|
hello: bool(true)
|
||||||
|
isnull: bool(true)
|
||||||
|
isundefined: bool(true)
|
||||||
|
isfalse: bool(true)
|
||||||
|
iszero: bool(true)
|
||||||
|
isquotezero: bool(true)
|
||||||
|
isemptyarray: bool(true)
|
||||||
|
isemptystring: bool(true)
|
||||||
|
istrue: bool(true)
|
||||||
|
|
||||||
|
===EOF===
|
65
v8js.cc
65
v8js.cc
@ -111,6 +111,69 @@ ZEND_GET_MODULE(v8js)
|
|||||||
|
|
||||||
/* V8 Object handlers */
|
/* V8 Object handlers */
|
||||||
|
|
||||||
|
static int php_v8js_v8_has_property(zval *object, zval *member, int has_set_exists ZEND_HASH_KEY_DC TSRMLS_DC) /* {{{ */
|
||||||
|
{
|
||||||
|
/* param has_set_exists:
|
||||||
|
* 0 (has) whether property exists and is not NULL - isset()
|
||||||
|
* 1 (set) whether property exists and is true-ish - empty()
|
||||||
|
* 2 (exists) whether property exists - property_exists()
|
||||||
|
*/
|
||||||
|
int retval = false;
|
||||||
|
php_v8js_object *obj = (php_v8js_object *) zend_object_store_get_object(object TSRMLS_CC);
|
||||||
|
|
||||||
|
v8::Locker locker(obj->isolate);
|
||||||
|
v8::Isolate::Scope isolate_scope(obj->isolate);
|
||||||
|
v8::HandleScope local_scope(obj->isolate);
|
||||||
|
v8::Local<v8::Context> temp_context = v8::Context::New(obj->isolate);
|
||||||
|
v8::Context::Scope temp_scope(temp_context);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(obj->isolate, obj->v8obj);
|
||||||
|
|
||||||
|
if (Z_TYPE_P(member) == IS_STRING && v8obj->IsObject() && !v8obj->IsFunction())
|
||||||
|
{
|
||||||
|
|
||||||
|
v8::Local<v8::Object> jsObj = v8obj->ToObject();
|
||||||
|
v8::Local<v8::String> jsKey = V8JS_STRL(Z_STRVAL_P(member), Z_STRLEN_P(member));
|
||||||
|
v8::Local<v8::Value> jsVal;
|
||||||
|
|
||||||
|
/* Skip any prototype properties */
|
||||||
|
if (jsObj->HasRealNamedProperty(jsKey) || jsObj->HasRealNamedCallbackProperty(jsKey)) {
|
||||||
|
if (has_set_exists == 2) {
|
||||||
|
/* property_exists(), that's enough! */
|
||||||
|
retval = true;
|
||||||
|
} else {
|
||||||
|
/* We need to look at the value. */
|
||||||
|
jsVal = jsObj->Get(jsKey);
|
||||||
|
if (has_set_exists == 0 ) {
|
||||||
|
/* isset(): We make 'undefined' equivalent to 'null' */
|
||||||
|
retval = !( jsVal->IsNull() || jsVal->IsUndefined() );
|
||||||
|
} else {
|
||||||
|
/* empty() */
|
||||||
|
retval = jsVal->BooleanValue();
|
||||||
|
/* for PHP compatibility, [] should also be empty */
|
||||||
|
if (jsVal->IsArray() && retval) {
|
||||||
|
v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(jsVal);
|
||||||
|
retval = (array->Length() != 0);
|
||||||
|
}
|
||||||
|
/* for PHP compatibility, '0' should also be empty */
|
||||||
|
if (jsVal->IsString() && retval) {
|
||||||
|
v8::Local<v8::String> str = jsVal->ToString();
|
||||||
|
if (str->Length() == 1) {
|
||||||
|
uint16_t c = 0;
|
||||||
|
str->Write(&c, 0, 1);
|
||||||
|
if (c == '0') {
|
||||||
|
retval = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
static zval *php_v8js_v8_read_property(zval *object, zval *member, int type ZEND_HASH_KEY_DC TSRMLS_DC) /* {{{ */
|
static zval *php_v8js_v8_read_property(zval *object, zval *member, int type ZEND_HASH_KEY_DC TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
zval *retval = NULL;
|
zval *retval = NULL;
|
||||||
@ -1300,7 +1363,7 @@ static PHP_MINIT_FUNCTION(v8js)
|
|||||||
v8_object_handlers.cast_object = NULL;
|
v8_object_handlers.cast_object = NULL;
|
||||||
v8_object_handlers.get_constructor = NULL;
|
v8_object_handlers.get_constructor = NULL;
|
||||||
v8_object_handlers.get_property_ptr_ptr = NULL;
|
v8_object_handlers.get_property_ptr_ptr = NULL;
|
||||||
// v8_object_handlers.has_property = php_v8js_v8_has_property; // Not implemented yet
|
v8_object_handlers.has_property = php_v8js_v8_has_property;
|
||||||
v8_object_handlers.read_property = php_v8js_v8_read_property;
|
v8_object_handlers.read_property = php_v8js_v8_read_property;
|
||||||
v8_object_handlers.write_property = php_v8js_v8_write_property;
|
v8_object_handlers.write_property = php_v8js_v8_write_property;
|
||||||
v8_object_handlers.unset_property = php_v8js_v8_unset_property;
|
v8_object_handlers.unset_property = php_v8js_v8_unset_property;
|
||||||
|
Loading…
Reference in New Issue
Block a user