0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-12-22 09:21:52 +00:00

Implement property_exists()/isset()/empty() on wrapped JavaScript objects.

Fixes issue #32.
This commit is contained in:
C. Scott Ananian 2013-10-05 11:55:59 -04:00
parent ba3fe2e27a
commit 035e6faa8b
2 changed files with 171 additions and 1 deletions

107
tests/property_exists.phpt Normal file
View 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
View File

@ -111,6 +111,69 @@ ZEND_GET_MODULE(v8js)
/* 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) /* {{{ */
{
zval *retval = NULL;
@ -1300,7 +1363,7 @@ static PHP_MINIT_FUNCTION(v8js)
v8_object_handlers.cast_object = NULL;
v8_object_handlers.get_constructor = 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.write_property = php_v8js_v8_write_property;
v8_object_handlers.unset_property = php_v8js_v8_unset_property;