mirror of
https://github.com/phpv8/v8js.git
synced 2024-12-22 08:11:52 +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 */
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user