mirror of
https://github.com/phpv8/v8js.git
synced 2024-12-22 20:51:51 +00:00
Bug fixes for JavaScript var_dump implementation (make it match PHP).
This commit is contained in:
parent
c725a80674
commit
27a140c9fb
315
tests/var_dump.phpt
Normal file
315
tests/var_dump.phpt
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
--TEST--
|
||||||
|
Test V8::executeString() : var_dump
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
|
||||||
|
--INI--
|
||||||
|
date.timezone=UTC
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
# Test var_dump of various types
|
||||||
|
|
||||||
|
$JS = <<< EOT
|
||||||
|
|
||||||
|
print("--- JS var_dump of PHP object ----\\n");
|
||||||
|
var_dump(PHP.phptypes);
|
||||||
|
|
||||||
|
print("--- JS var_dump of JS object ----\\n");
|
||||||
|
var types = {
|
||||||
|
undefined: undefined,
|
||||||
|
null: null,
|
||||||
|
bool: true,
|
||||||
|
string: "string",
|
||||||
|
uint: 1,
|
||||||
|
int: -1,
|
||||||
|
number: 3.141592654,
|
||||||
|
// XXX this gets parsed with local timezone,
|
||||||
|
// which is bad for test repeatability.
|
||||||
|
//date: new Date('September 27, 1976 09:00:00 GMT'),
|
||||||
|
regexp: /regexp/,
|
||||||
|
array: [1,2,3],
|
||||||
|
object: { field: "foo" },
|
||||||
|
function: function id(x) { return x; },
|
||||||
|
phpobject: PHP.obj
|
||||||
|
};
|
||||||
|
|
||||||
|
var_dump(types);
|
||||||
|
print("--- PHP var_dump of JS object ----\\n");
|
||||||
|
types;
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
var $field = "php";
|
||||||
|
}
|
||||||
|
|
||||||
|
$v8 = new V8Js();
|
||||||
|
$v8->obj = new Foo;
|
||||||
|
|
||||||
|
$phptypes = $v8->phptypes = array(
|
||||||
|
"null" => NULL,
|
||||||
|
"bool" => true,
|
||||||
|
"string" => "string",
|
||||||
|
"uint" => 1,
|
||||||
|
"int" => -1,
|
||||||
|
"number" => 3.141592654,
|
||||||
|
"date" => new DateTime('September 27, 1976 09:00:00 UTC', new DateTimeZone('UTC')),
|
||||||
|
//"regexp" => new Regexp('/regexp/'), /* no native PHP regex type */
|
||||||
|
"array" => array(1,2,3),
|
||||||
|
"object" => array( "field" => "foo" ),
|
||||||
|
"function" => (function ($x) { return $x; }),
|
||||||
|
"phpobject" => new Foo
|
||||||
|
);
|
||||||
|
|
||||||
|
echo "---- PHP var_dump of PHP object ----\n";
|
||||||
|
var_dump($phptypes);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var_dump($v8->executeString($JS, 'var_dump.js'));
|
||||||
|
} catch (V8JsScriptException $e) {
|
||||||
|
echo "Error!\n";
|
||||||
|
var_dump($e);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
===EOF===
|
||||||
|
--EXPECTF--
|
||||||
|
---- PHP var_dump of PHP object ----
|
||||||
|
array(11) {
|
||||||
|
["null"]=>
|
||||||
|
NULL
|
||||||
|
["bool"]=>
|
||||||
|
bool(true)
|
||||||
|
["string"]=>
|
||||||
|
string(6) "string"
|
||||||
|
["uint"]=>
|
||||||
|
int(1)
|
||||||
|
["int"]=>
|
||||||
|
int(-1)
|
||||||
|
["number"]=>
|
||||||
|
float(3.141592654)
|
||||||
|
["date"]=>
|
||||||
|
object(DateTime)#%d (3) {
|
||||||
|
["date"]=>
|
||||||
|
string(19) "1976-09-27 09:00:00"
|
||||||
|
["timezone_type"]=>
|
||||||
|
int(3)
|
||||||
|
["timezone"]=>
|
||||||
|
string(3) "UTC"
|
||||||
|
}
|
||||||
|
["array"]=>
|
||||||
|
array(3) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
[2]=>
|
||||||
|
int(3)
|
||||||
|
}
|
||||||
|
["object"]=>
|
||||||
|
array(1) {
|
||||||
|
["field"]=>
|
||||||
|
string(3) "foo"
|
||||||
|
}
|
||||||
|
["function"]=>
|
||||||
|
object(Closure)#%d (1) {
|
||||||
|
["parameter"]=>
|
||||||
|
array(1) {
|
||||||
|
["$x"]=>
|
||||||
|
string(10) "<required>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
["phpobject"]=>
|
||||||
|
object(Foo)#%d (1) {
|
||||||
|
["field"]=>
|
||||||
|
string(3) "php"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--- JS var_dump of PHP object ----
|
||||||
|
array (11) {
|
||||||
|
["null"] =>
|
||||||
|
NULL
|
||||||
|
["bool"] =>
|
||||||
|
bool(true)
|
||||||
|
["string"] =>
|
||||||
|
string(6) "string"
|
||||||
|
["uint"] =>
|
||||||
|
int(1)
|
||||||
|
["int"] =>
|
||||||
|
int(-1)
|
||||||
|
["number"] =>
|
||||||
|
float(3.141593)
|
||||||
|
["date"] =>
|
||||||
|
object(DateTime)#%d (18) {
|
||||||
|
["createFromFormat"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["getLastErrors"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["format"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["modify"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["add"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["sub"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["getTimezone"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["setTimezone"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["getOffset"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["setTime"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["setDate"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["setISODate"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["setTimestamp"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["getTimestamp"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["diff"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function () { [native code] }
|
||||||
|
}
|
||||||
|
["date"] =>
|
||||||
|
string(19) "1976-09-27 09:00:00"
|
||||||
|
["timezone_type"] =>
|
||||||
|
int(3)
|
||||||
|
["timezone"] =>
|
||||||
|
string(3) "UTC"
|
||||||
|
}
|
||||||
|
["array"] =>
|
||||||
|
array(3) {
|
||||||
|
[0] =>
|
||||||
|
int(1)
|
||||||
|
[1] =>
|
||||||
|
int(2)
|
||||||
|
[2] =>
|
||||||
|
int(3)
|
||||||
|
}
|
||||||
|
["object"] =>
|
||||||
|
array (1) {
|
||||||
|
["field"] =>
|
||||||
|
string(3) "foo"
|
||||||
|
}
|
||||||
|
["function"] =>
|
||||||
|
object(Closure)#%d (0) {
|
||||||
|
}
|
||||||
|
["phpobject"] =>
|
||||||
|
object(Foo)#%d (1) {
|
||||||
|
["field"] =>
|
||||||
|
string(3) "php"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--- JS var_dump of JS object ----
|
||||||
|
object(Object)#%d (12) {
|
||||||
|
["undefined"] =>
|
||||||
|
NULL
|
||||||
|
["null"] =>
|
||||||
|
NULL
|
||||||
|
["bool"] =>
|
||||||
|
bool(true)
|
||||||
|
["string"] =>
|
||||||
|
string(6) "string"
|
||||||
|
["uint"] =>
|
||||||
|
int(1)
|
||||||
|
["int"] =>
|
||||||
|
int(-1)
|
||||||
|
["number"] =>
|
||||||
|
float(3.141593)
|
||||||
|
["regexp"] =>
|
||||||
|
regexp(/regexp/)
|
||||||
|
["array"] =>
|
||||||
|
array(3) {
|
||||||
|
[0] =>
|
||||||
|
int(1)
|
||||||
|
[1] =>
|
||||||
|
int(2)
|
||||||
|
[2] =>
|
||||||
|
int(3)
|
||||||
|
}
|
||||||
|
["object"] =>
|
||||||
|
object(Object)#%d (1) {
|
||||||
|
["field"] =>
|
||||||
|
string(3) "foo"
|
||||||
|
}
|
||||||
|
["function"] =>
|
||||||
|
object(Closure)#%d {
|
||||||
|
function id(x) { return x; }
|
||||||
|
}
|
||||||
|
["phpobject"] =>
|
||||||
|
object(Foo)#%d (1) {
|
||||||
|
["field"] =>
|
||||||
|
string(3) "php"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--- PHP var_dump of JS object ----
|
||||||
|
object(V8Object)#%d (12) {
|
||||||
|
["undefined"]=>
|
||||||
|
NULL
|
||||||
|
["null"]=>
|
||||||
|
NULL
|
||||||
|
["bool"]=>
|
||||||
|
bool(true)
|
||||||
|
["string"]=>
|
||||||
|
string(6) "string"
|
||||||
|
["uint"]=>
|
||||||
|
int(1)
|
||||||
|
["int"]=>
|
||||||
|
int(-1)
|
||||||
|
["number"]=>
|
||||||
|
float(3.141592654)
|
||||||
|
["regexp"]=>
|
||||||
|
object(V8Object)#%d (0) {
|
||||||
|
}
|
||||||
|
["array"]=>
|
||||||
|
array(3) {
|
||||||
|
[0]=>
|
||||||
|
int(1)
|
||||||
|
[1]=>
|
||||||
|
int(2)
|
||||||
|
[2]=>
|
||||||
|
int(3)
|
||||||
|
}
|
||||||
|
["object"]=>
|
||||||
|
object(V8Object)#%d (1) {
|
||||||
|
["field"]=>
|
||||||
|
string(3) "foo"
|
||||||
|
}
|
||||||
|
["function"]=>
|
||||||
|
object(V8Function)#%d (0) {
|
||||||
|
}
|
||||||
|
["phpobject"]=>
|
||||||
|
object(Foo)#%d (1) {
|
||||||
|
["field"]=>
|
||||||
|
string(3) "php"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
===EOF===
|
@ -61,13 +61,43 @@ static void _php_v8js_dumper(v8::Local<v8::Value> var, int level TSRMLS_DC) /* {
|
|||||||
php_printf("%*c", (level - 1) * 2, ' ');
|
php_printf("%*c", (level - 1) * 2, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var->IsNull())
|
if (var.IsEmpty())
|
||||||
|
{
|
||||||
|
php_printf("<empty>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (var->IsNull() || var->IsUndefined() /* PHP compat */)
|
||||||
{
|
{
|
||||||
php_printf("NULL\n");
|
php_printf("NULL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (var->IsInt32())
|
||||||
|
{
|
||||||
|
php_printf("int(%ld)\n", (long) var->IntegerValue());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (var->IsUint32())
|
||||||
|
{
|
||||||
|
php_printf("int(%lu)\n", (unsigned long) var->IntegerValue());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (var->IsNumber())
|
||||||
|
{
|
||||||
|
php_printf("float(%f)\n", var->NumberValue());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (var->IsBoolean())
|
||||||
|
{
|
||||||
|
php_printf("bool(%s)\n", var->BooleanValue() ? "true" : "false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
v8::String::Utf8Value str(var->ToDetailString());
|
v8::TryCatch try_catch; /* object.toString() can throw an exception */
|
||||||
|
v8::Local<v8::String> details = var->ToDetailString();
|
||||||
|
if (try_catch.HasCaught()) {
|
||||||
|
details = V8JS_SYM("<toString threw exception>");
|
||||||
|
}
|
||||||
|
v8::String::Utf8Value str(details);
|
||||||
const char *valstr = ToCString(str);
|
const char *valstr = ToCString(str);
|
||||||
size_t valstr_len = (valstr) ? strlen(valstr) : 0;
|
size_t valstr_len = (valstr) ? strlen(valstr) : 0;
|
||||||
|
|
||||||
@ -75,26 +105,15 @@ static void _php_v8js_dumper(v8::Local<v8::Value> var, int level TSRMLS_DC) /* {
|
|||||||
{
|
{
|
||||||
php_printf("string(%zu) \"%s\"\n", valstr_len, valstr);
|
php_printf("string(%zu) \"%s\"\n", valstr_len, valstr);
|
||||||
}
|
}
|
||||||
else if (var->IsBoolean())
|
|
||||||
{
|
|
||||||
php_printf("bool(%s)\n", valstr);
|
|
||||||
}
|
|
||||||
else if (var->IsInt32() || var->IsUint32())
|
|
||||||
{
|
|
||||||
php_printf("int(%s)\n", valstr);
|
|
||||||
}
|
|
||||||
else if (var->IsNumber())
|
|
||||||
{
|
|
||||||
php_printf("float(%s)\n", valstr);
|
|
||||||
}
|
|
||||||
else if (var->IsDate())
|
else if (var->IsDate())
|
||||||
{
|
{
|
||||||
|
// fake the fields of a PHP DateTime
|
||||||
php_printf("Date(%s)\n", valstr);
|
php_printf("Date(%s)\n", valstr);
|
||||||
}
|
}
|
||||||
#if PHP_V8_API_VERSION >= 2003007
|
#if PHP_V8_API_VERSION >= 2003007
|
||||||
else if (var->IsRegExp())
|
else if (var->IsRegExp())
|
||||||
{
|
{
|
||||||
php_printf("RegExp(%s)\n", valstr);
|
php_printf("regexp(%s)\n", valstr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (var->IsArray())
|
else if (var->IsArray())
|
||||||
@ -119,18 +138,25 @@ static void _php_v8js_dumper(v8::Local<v8::Value> var, int level TSRMLS_DC) /* {
|
|||||||
{
|
{
|
||||||
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(var);
|
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(var);
|
||||||
V8JS_GET_CLASS_NAME(cname, object);
|
V8JS_GET_CLASS_NAME(cname, object);
|
||||||
|
int hash = object->GetIdentityHash();
|
||||||
|
|
||||||
if (var->IsFunction())
|
if (var->IsFunction())
|
||||||
{
|
{
|
||||||
v8::String::Utf8Value csource(object->ToString());
|
v8::String::Utf8Value csource(object->ToString());
|
||||||
php_printf("object(%s)#%d {\n%*c%s\n", ToCString(cname), object->GetIdentityHash(), level * 2 + 2, ' ', ToCString(csource));
|
php_printf("object(Closure)#%d {\n%*c%s\n", hash, level * 2 + 2, ' ', ToCString(csource));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v8::Local<v8::Array> keys = object->GetPropertyNames();
|
v8::Local<v8::Array> keys = object->GetOwnPropertyNames();
|
||||||
uint32_t length = keys->Length();
|
uint32_t length = keys->Length();
|
||||||
|
|
||||||
php_printf("object(%s)#%d (%d) {\n", ToCString(cname), object->GetIdentityHash(), length);
|
if (strcmp(ToCString(cname), "Array") == 0 ||
|
||||||
|
strcmp(ToCString(cname), "V8Object") == 0) {
|
||||||
|
php_printf("array");
|
||||||
|
} else {
|
||||||
|
php_printf("object(%s)#%d", ToCString(cname), hash);
|
||||||
|
}
|
||||||
|
php_printf(" (%d) {\n", length);
|
||||||
|
|
||||||
for (unsigned i = 0; i < length; i++) {
|
for (unsigned i = 0; i < length; i++) {
|
||||||
v8::Local<v8::String> key = keys->Get(i)->ToString();
|
v8::Local<v8::String> key = keys->Get(i)->ToString();
|
||||||
|
Loading…
Reference in New Issue
Block a user