From 714ae87ab611797a4e0284b20073d49db820b551 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sat, 22 Jun 2019 20:25:13 +0200 Subject: [PATCH 1/9] (Vagrantfile) provide box w/ php 7.4 --- Vagrantfile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Vagrantfile b/Vagrantfile index 2cb5791..640d485 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -77,6 +77,30 @@ Vagrant.configure("2") do |config| end } + config.vm.define "php-7.4" do |i| + i.vm.synced_folder ".", "/data/v8js" + + i.vm.provision "shell", inline: <<-SHELL + gpg --keyserver keys.gnupg.net --recv 7F438280EF8D349F + gpg --armor --export 7F438280EF8D349F | apt-key add - + + apt-get update + apt-get install -y software-properties-common gdb tmux git tig curl apache2-utils lcov + + add-apt-repository ppa:stesie/libv8 + apt-get update + apt-get install -y libv8-7.5-dbg libv8-7.5-dev + + test -x /tmp/php-src || git clone https://github.com/php/php-src.git /tmp/php-src -b PHP-7.4 --depth 1 + cd /tmp/php-src + apt-get install -y build-essential bison re2c libreadline-dev + ./buildconf + ./configure --disable-all --with-readline + make -j4 + make install + SHELL + end + config.vm.provision "shell", privileged: false, inline: <<-SHELL sudo mkdir -p /data/build && sudo chown $USER:$USER /data/build SHELL From c2873fd8d39c5b0f7507468bd0f17cbc0e45558e Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sat, 22 Jun 2019 20:25:54 +0200 Subject: [PATCH 2/9] change retval of write_property handlers, refs #409 --- v8js_class.cc | 9 +++++---- v8js_v8object_class.cc | 10 ++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/v8js_class.cc b/v8js_class.cc index 9c27d15..d36aa6d 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -1307,9 +1307,10 @@ const zend_function_entry v8js_methods[] = { /* {{{ */ /* V8Js object handlers */ -static void v8js_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ +static zval* v8js_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ { - V8JS_BEGIN_CTX(c, object) + v8js_ctx *c = Z_V8JS_CTX_OBJ_P(object); + V8JS_CTX_PROLOGUE_EX(c, value); /* Check whether member is public, if so, export to V8. */ zend_property_info *property_info = zend_get_property_info(c->std.ce, Z_STR_P(member), 1); @@ -1323,7 +1324,7 @@ static void v8js_write_property(zval *object, zval *member, zval *value, void ** if (Z_STRLEN_P(member) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, "Property name exceeds maximum supported length", 0); - return; + return value; } /* Write value to PHP JS object */ @@ -1332,7 +1333,7 @@ static void v8js_write_property(zval *object, zval *member, zval *value, void ** } /* Write value to PHP object */ - std_object_handlers.write_property(object, member, value, NULL); + return std_object_handlers.write_property(object, member, value, NULL); } /* }}} */ diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index 9440e19..51b16f0 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -161,29 +161,31 @@ static zval *v8js_v8object_read_property(zval *object, zval *member, int type, v } /* }}} */ -static void v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot ) /* {{{ */ +static zval* v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot ) /* {{{ */ { v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); if (!obj->ctx) { zend_throw_exception(php_ce_v8js_exception, "Can't access V8Object after V8Js instance is destroyed!", 0); - return; + return value; } - V8JS_CTX_PROLOGUE(obj->ctx); + V8JS_CTX_PROLOGUE_EX(obj->ctx, value); v8::Local v8objHandle = v8::Local::New(isolate, obj->v8obj); if (Z_STRLEN_P(member) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, "Member name length exceeds maximum supported length", 0); - return; + return value; } v8::Local v8obj; if (v8objHandle->IsObject() && v8objHandle->ToObject(v8_context).ToLocal(&v8obj)) { v8obj->CreateDataProperty(v8_context, V8JS_ZSYM(Z_STR_P(member)), zval_to_v8js(value, isolate)); } + + return value; } /* }}} */ From 885ac6d249e843d6ce2314c90c5cda36282bc166 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sun, 23 Jun 2019 10:16:31 +0200 Subject: [PATCH 3/9] prove get_property_ptr_ptr handler for v8object --- v8js_v8object_class.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index 51b16f0..1c5c808 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -161,7 +161,13 @@ static zval *v8js_v8object_read_property(zval *object, zval *member, int type, v } /* }}} */ -static zval* v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot ) /* {{{ */ +static zval *v8js_v8object_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +{ + return NULL; +} +/* }}} */ + +static zval *v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot ) /* {{{ */ { v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); @@ -814,7 +820,7 @@ PHP_MINIT_FUNCTION(v8js_v8object_class) /* {{{ */ memcpy(&v8js_v8object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); v8js_v8object_handlers.clone_obj = NULL; v8js_v8object_handlers.cast_object = NULL; - v8js_v8object_handlers.get_property_ptr_ptr = NULL; + v8js_v8object_handlers.get_property_ptr_ptr = v8js_v8object_get_property_ptr_ptr; v8js_v8object_handlers.has_property = v8js_v8object_has_property; v8js_v8object_handlers.read_property = v8js_v8object_read_property; v8js_v8object_handlers.write_property = v8js_v8object_write_property; From fcd78f830ac29fdc4e48834e313383e3d15665e1 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sun, 23 Jun 2019 19:09:12 +0200 Subject: [PATCH 4/9] use EXPECTREGEX to handle different PHP version's output well --- tests/issue_250_001.phpt | 38 +-- tests/var_dump.phpt | 483 ++++++++++++++++++++------------------- tests/var_dump_73.phpt | 322 -------------------------- 3 files changed, 261 insertions(+), 582 deletions(-) delete mode 100644 tests/var_dump_73.phpt diff --git a/tests/issue_250_001.phpt b/tests/issue_250_001.phpt index ca6e6cd..dff9427 100644 --- a/tests/issue_250_001.phpt +++ b/tests/issue_250_001.phpt @@ -54,22 +54,22 @@ try { ?> ===EOF=== ---EXPECTF-- -Warning: Creating default object from empty value in %s%eissue_250_001.php on line 9 -object(TestObject)#%d (3) { - ["data":"TestObject":private]=> - object(V8Object)#%d (0) { - } - ["meta":"TestObject":private]=> - array(0) { - } - ["a"]=> - object(stdClass)#%d (1) { - ["b"]=> - object(stdClass)#%d (1) { - ["title"]=> - string(4) "ouch" - } - } -} -===EOF=== +--EXPECTREGEX-- +(?:Warning\: Creating default object from empty value in [^\r\n]+\/issue_250_001\.php on line 9\s*)+ +object\(TestObject\)\#\d+ \(3\) \{ + \["data"\:"TestObject"\:private\]\=\> + object\(V8Object\)\#\d+ \(0\) \{ + \} + \["meta"\:"TestObject"\:private\]\=\> + array\(0\) \{ + \} + \["a"\]\=\> + object\(stdClass\)\#\d+ \(1\) \{ + \["b"\]\=\> + object\(stdClass\)\#\d+ \(1\) \{ + \["title"\]\=\> + string\(4\) "ouch" + \} + \} +\} +\=\=\=EOF\=\=\= diff --git a/tests/var_dump.phpt b/tests/var_dump.phpt index 7a5d7d8..e1d232b 100644 --- a/tests/var_dump.phpt +++ b/tests/var_dump.phpt @@ -1,10 +1,7 @@ --TEST-- Test V8::executeString() : var_dump --SKIPIF-- -= 70300) die('skip Only for php version < 7.3'); -?> + --INI-- date.timezone=UTC --FILE-- @@ -73,246 +70,250 @@ try { } ?> ===EOF=== ---EXPECTF-- ----- PHP var_dump of PHP object ---- -array(11) { - ["null"]=> +--EXPECTREGEX-- +\-\-\-\- 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(%d) "1976-09-27 09:00:00%r(\.0+)?%r" - ["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) "" - } - } - ["phpobject"]=> - object(Foo)#%d (1) { - ["field"]=> - string(3) "php" - } -} ---- JS var_dump of PHP object ---- -array (11) { - ["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\(\d+\) "1976\-09\-27 09\:00\:00((\.0+)?)" + \["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\) "\" + \} + \} + \["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(%d) "1976-09-27 09:00:00%r(\.0+)?%r" - ["$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"] => + \["bool"\] \=\> + bool\(true\) + \["string"\] \=\> + string\(6\) "string" + \["uint"\] \=\> + int\(1\) + \["int"\] \=\> + int\(\-1\) + \["number"\] \=\> + float\(3\.141593\) + \["date"\] \=\> + object\(DateTime\)\#\d+ \(\d+\) \{(?: + \["createFromImmutable"\] \=\> + object\(Closure\)\#\d+ \{ + function \(\) \{ \[native code\] \} + \})? + \["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\] \} + \}(?:(?:the following block is missing from PHP 7.4 on){0} + \["\$date"\] \=\> + string\(\d+\) "1976\-09\-27 09\:00\:00((\.0+)?)" + \["\$timezone_type"\] \=\> + int\(3\) + \["\$timezone"\] \=\> + string\(3\) "UTC" + )?\s*\} + \["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"\] \=\> 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"]=> + \["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"\]\=\> 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=== + \["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\=\=\= diff --git a/tests/var_dump_73.phpt b/tests/var_dump_73.phpt deleted file mode 100644 index 553febb..0000000 --- a/tests/var_dump_73.phpt +++ /dev/null @@ -1,322 +0,0 @@ ---TEST-- -Test V8::executeString() : var_dump ---SKIPIF-- -= 7.3'); -?> ---INI-- -date.timezone=UTC ---FILE-- -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(%d) "1976-09-27 09:00:00%r(\.0+)?%r" - ["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) "" - } - } - ["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 (19) { - ["createFromImmutable"] => - object(Closure)#%d { - function () { [native code] } - } - ["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(%d) "1976-09-27 09:00:00%r(\.0+)?%r" - ["$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=== From 83c215d4b1ee84fa4340fe1cc93f03a9764d4a44 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Fri, 3 Apr 2020 09:18:59 +0200 Subject: [PATCH 5/9] don't define isnan/isfinite for PHP 7.4 --- php_v8js_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php_v8js_macros.h b/php_v8js_macros.h index ad7777b..fa7247c 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -29,7 +29,7 @@ #include #include -#ifndef isnan +#if PHP_VERSION_ID < 70400 && !defined(isnan) /* php.h requires the isnan() macro, which is removed by c++ header, * work around: re-define the macro to std::isnan function */ #define isnan(a) std::isnan(a) From e153ff16519eb3266dafd024a2d316d84f93fb96 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Fri, 3 Apr 2020 10:00:27 +0200 Subject: [PATCH 6/9] make it compile on PHP 7.3 and 7.4 --- php_v8js_macros.h | 17 +++++++++-------- v8js_class.cc | 8 ++++---- v8js_v8.h | 7 +++++++ v8js_v8object_class.cc | 10 +++++----- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/php_v8js_macros.h b/php_v8js_macros.h index fa7247c..1e4b966 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -29,16 +29,17 @@ #include #include -#if PHP_VERSION_ID < 70400 && !defined(isnan) -/* php.h requires the isnan() macro, which is removed by c++ header, - * work around: re-define the macro to std::isnan function */ -#define isnan(a) std::isnan(a) - -/* likewise isfinite */ -#define isfinite(a) std::isfinite(a) -#endif extern "C" { +#include "php_config.h" + +/* work around incompatibilities regarding isnan() and isfinite() macros, + * affecting PHP versions before 7.4. */ +#undef HAVE_DECL_ISFINITE +#undef HAVE_DECL_ISNAN +#define HAVE_DECL_ISFINITE 0 +#define HAVE_DECL_ISNAN 0 + #include "php.h" #include "php_v8js.h" } diff --git a/v8js_class.cc b/v8js_class.cc index d36aa6d..4e9be67 100644 --- a/v8js_class.cc +++ b/v8js_class.cc @@ -1307,10 +1307,10 @@ const zend_function_entry v8js_methods[] = { /* {{{ */ /* V8Js object handlers */ -static zval* v8js_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ +static SINCE74(zval*, void) v8js_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ { v8js_ctx *c = Z_V8JS_CTX_OBJ_P(object); - V8JS_CTX_PROLOGUE_EX(c, value); + V8JS_CTX_PROLOGUE_EX(c, SINCE74(value,)); /* Check whether member is public, if so, export to V8. */ zend_property_info *property_info = zend_get_property_info(c->std.ce, Z_STR_P(member), 1); @@ -1324,7 +1324,7 @@ static zval* v8js_write_property(zval *object, zval *member, zval *value, void * if (Z_STRLEN_P(member) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, "Property name exceeds maximum supported length", 0); - return value; + return SINCE74(value,); } /* Write value to PHP JS object */ @@ -1333,7 +1333,7 @@ static zval* v8js_write_property(zval *object, zval *member, zval *value, void * } /* Write value to PHP object */ - return std_object_handlers.write_property(object, member, value, NULL); + SINCE74(return,) std_object_handlers.write_property(object, member, value, NULL); } /* }}} */ diff --git a/v8js_v8.h b/v8js_v8.h index 22729f1..7292ac0 100644 --- a/v8js_v8.h +++ b/v8js_v8.h @@ -83,6 +83,13 @@ int v8js_get_properties_hash(v8::Local jsValue, HashTable *retval, in V8JS_CTX_PROLOGUE(ctx); +#if PHP_VERSION_ID < 70400 +#define SINCE74(x,y) y +#else +#define SINCE74(x,y) x +#endif + + #endif /* V8JS_V8_H */ /* diff --git a/v8js_v8object_class.cc b/v8js_v8object_class.cc index fc023ff..de17e26 100644 --- a/v8js_v8object_class.cc +++ b/v8js_v8object_class.cc @@ -167,23 +167,23 @@ static zval *v8js_v8object_get_property_ptr_ptr(zval *object, zval *member, int } /* }}} */ -static zval *v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot ) /* {{{ */ +static SINCE74(zval*, void) v8js_v8object_write_property(zval *object, zval *member, zval *value, void **cache_slot ) /* {{{ */ { v8js_v8object *obj = Z_V8JS_V8OBJECT_OBJ_P(object); if (!obj->ctx) { zend_throw_exception(php_ce_v8js_exception, "Can't access V8Object after V8Js instance is destroyed!", 0); - return value; + return SINCE74(value,); } - V8JS_CTX_PROLOGUE_EX(obj->ctx, value); + V8JS_CTX_PROLOGUE_EX(obj->ctx, SINCE74(value,)); v8::Local v8objHandle = v8::Local::New(isolate, obj->v8obj); if (Z_STRLEN_P(member) > std::numeric_limits::max()) { zend_throw_exception(php_ce_v8js_exception, "Member name length exceeds maximum supported length", 0); - return value; + return SINCE74(value,); } v8::Local v8obj; @@ -191,7 +191,7 @@ static zval *v8js_v8object_write_property(zval *object, zval *member, zval *valu v8obj->CreateDataProperty(v8_context, V8JS_ZSYM(Z_STR_P(member)), zval_to_v8js(value, isolate)); } - return value; + return SINCE74(value,); } /* }}} */ From ac784c797ac212ce66bf6bbd0eb1176e0d71e4c6 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Fri, 3 Apr 2020 14:20:08 +0200 Subject: [PATCH 7/9] run sanitize=address build on jenkins --- .dockerignore | 46 ++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile.jenkins | 22 ++++++++++++++++++++++ Jenkinsfile | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile.jenkins create mode 100644 Jenkinsfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6e46a23 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,46 @@ +*.lo +*.o +.deps +.libs +Dockerfile.tmp +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +acinclude.m4 +aclocal.m4 +autom4te.cache/* +build/* +config.guess +config.h +config.h.in +*.log +config.nice +config.status +config.sub +configure +configure.in +configure.ac +*~ +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +modules/* +v8js.la +v8js-*.tgz +run-tests.php +.*.sw[poq] + +tests/*.diff +tests/*.exp +tests/*.out +tests/*.php +tests/*.sh +tests/*.mem + +.vagrant +tmp-php.ini + +coverage_report/** diff --git a/Dockerfile.jenkins b/Dockerfile.jenkins new file mode 100644 index 0000000..e046dad --- /dev/null +++ b/Dockerfile.jenkins @@ -0,0 +1,22 @@ +ARG V8VER +FROM stesie/libv8-${V8VER}:latest + +ARG PHPVER + +ENV DEBIAN_FRONTEND=noninteractive +ENV LC_ALL=C.UTF-8 +ENV NO_INTERACTION=1 +ENV REPORT_EXIT_STATUS=1 + +RUN apt-get update -q +RUN apt-get install -y wget autoconf build-essential libxml2-dev libreadline-dev pkg-config + +RUN wget https://www.php.net/distributions/php-${PHPVER}.tar.gz && \ + tar xzf php-${PHPVER}.tar.gz +ADD . /php-${PHPVER}/ext/v8js +WORKDIR /php-${PHPVER} + +RUN ./buildconf --force +RUN ./configure --disable-all --with-readline --enable-cli --enable-json --enable-dom --enable-maintainer-zts --with-libxml --with-v8js=/opt/libv8-$V8VER/ CFLAGS="-fsanitize=address -g -O0" CXXFLAGS="-fsanitize=address -g -O0" +RUN sed -e "s/^EXTRA_LIBS.*/& -lv8_libplatform/" -i Makefile +RUN make -j5 diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..a0dffe7 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,34 @@ +pipeline { + agent none + stages { + stage('BuildAndTest') { + matrix { + agent any + axes { + axis { + name 'PHPVER' + values '7.3.16', '7.4.4' + } + axis { + name 'V8VER' + values '7.9' + } + } + stages { + stage('Build') { + steps { + echo "Building w/ V8 ${V8VER}, PHP ${PHPVER} as Docker image ${BUILD_TAG}-${V8VER}-${PHPVER}" + sh "docker build -f Dockerfile.jenkins --build-arg V8VER=${V8VER} --build-arg PHPVER=${PHPVER} -t ${BUILD_TAG}-${V8VER}-${PHPVER} ." + } + } + stage('Test') { + steps { + echo "Running test on ${BUILD_TAG}-${V8VER}-${PHPVER}" + sh "docker run --rm -t ${BUILD_TAG}-${V8VER}-${PHPVER} make test TESTS='ext/v8js/tests/*.phpt'" + } + } + } + } + } + } +} From 579f9c993fe1db29fb4e47c2804a6ccf27c8ce1a Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Fri, 3 Apr 2020 14:50:49 +0200 Subject: [PATCH 8/9] don't --with-libxml on Jenkins, since it's --enable-libxml on PHP < 7.3 --- Dockerfile.jenkins | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.jenkins b/Dockerfile.jenkins index e046dad..a98e384 100644 --- a/Dockerfile.jenkins +++ b/Dockerfile.jenkins @@ -9,7 +9,7 @@ ENV NO_INTERACTION=1 ENV REPORT_EXIT_STATUS=1 RUN apt-get update -q -RUN apt-get install -y wget autoconf build-essential libxml2-dev libreadline-dev pkg-config +RUN apt-get install -y wget autoconf build-essential libreadline-dev pkg-config RUN wget https://www.php.net/distributions/php-${PHPVER}.tar.gz && \ tar xzf php-${PHPVER}.tar.gz @@ -17,6 +17,6 @@ ADD . /php-${PHPVER}/ext/v8js WORKDIR /php-${PHPVER} RUN ./buildconf --force -RUN ./configure --disable-all --with-readline --enable-cli --enable-json --enable-dom --enable-maintainer-zts --with-libxml --with-v8js=/opt/libv8-$V8VER/ CFLAGS="-fsanitize=address -g -O0" CXXFLAGS="-fsanitize=address -g -O0" +RUN ./configure --disable-all --with-readline --enable-cli --enable-json --enable-maintainer-zts --with-v8js=/opt/libv8-$V8VER/ CFLAGS="-fsanitize=address -g -O0" CXXFLAGS="-fsanitize=address -g -O0" RUN sed -e "s/^EXTRA_LIBS.*/& -lv8_libplatform/" -i Makefile RUN make -j5 From 7670ded38e8d1ea1ed85d92dc220a680dbf302a8 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Fri, 3 Apr 2020 15:20:18 +0200 Subject: [PATCH 9/9] (jenkins) link against libdl (needed w/ php 7.3) --- Dockerfile.jenkins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.jenkins b/Dockerfile.jenkins index a98e384..cfca1a2 100644 --- a/Dockerfile.jenkins +++ b/Dockerfile.jenkins @@ -18,5 +18,5 @@ WORKDIR /php-${PHPVER} RUN ./buildconf --force RUN ./configure --disable-all --with-readline --enable-cli --enable-json --enable-maintainer-zts --with-v8js=/opt/libv8-$V8VER/ CFLAGS="-fsanitize=address -g -O0" CXXFLAGS="-fsanitize=address -g -O0" -RUN sed -e "s/^EXTRA_LIBS.*/& -lv8_libplatform/" -i Makefile +RUN sed -e "s/^EXTRA_LIBS.*/& -lv8_libplatform -ldl/" -i Makefile RUN make -j5