소스 검색

Merge pull request #440 from stesie/php-7.4-support

PHP 7.4 support
Stefan Siegl 5 년 전
부모
커밋
c03cb4b345
11개의 변경된 파일421개의 추가작업 그리고 599개의 파일을 삭제
  1. 46 0
      .dockerignore
  2. 22 0
      Dockerfile.jenkins
  3. 34 0
      Jenkinsfile
  4. 24 0
      Vagrantfile
  5. 9 8
      php_v8js_macros.h
  6. 19 19
      tests/issue_250_001.phpt
  7. 242 241
      tests/var_dump.phpt
  8. 0 322
      tests/var_dump_73.phpt
  9. 5 4
      v8js_class.cc
  10. 7 0
      v8js_v8.h
  11. 13 5
      v8js_v8object_class.cc

+ 46 - 0
.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/**

+ 22 - 0
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 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-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 -ldl/" -i Makefile
+RUN make -j5

+ 34 - 0
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'"
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 24 - 0
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

+ 9 - 8
php_v8js_macros.h

@@ -29,16 +29,17 @@
 #include <mutex>
 
 #include <cmath>
-#ifndef isnan
-/* php.h requires the isnan() macro, which is removed by c++ <cmath> 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"
 }

+ 19 - 19
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\=\=\=

+ 242 - 241
tests/var_dump.phpt

@@ -1,10 +1,7 @@
 --TEST--
 Test V8::executeString() : var_dump
 --SKIPIF--
-<?php
-require_once(dirname(__FILE__) . '/skipif.inc');
-if (PHP_VERSION_ID >= 70300) die('skip Only for php version < 7.3');
-?>
+<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
 --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) "<required>"
-    }
-  }
-  ["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\) "\<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(%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\=\=\=

+ 0 - 322
tests/var_dump_73.phpt

@@ -1,322 +0,0 @@
---TEST--
-Test V8::executeString() : var_dump
---SKIPIF--
-<?php
-require_once(dirname(__FILE__) . '/skipif.inc');
-if (PHP_VERSION_ID < 70300) die('skip Only for php version >= 7.3');
-?>
---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(%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) "<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 (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===

+ 5 - 4
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 SINCE74(zval*, void) 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, 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);
@@ -1323,7 +1324,7 @@ static void v8js_write_property(zval *object, zval *member, zval *value, void **
 		if (Z_STRLEN_P(member) > std::numeric_limits<int>::max()) {
 				zend_throw_exception(php_ce_v8js_exception,
 						"Property name exceeds maximum supported length", 0);
-				return;
+				return SINCE74(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);
+	SINCE74(return,) std_object_handlers.write_property(object, member, value, NULL);
 }
 /* }}} */
 

+ 7 - 0
v8js_v8.h

@@ -83,6 +83,13 @@ int v8js_get_properties_hash(v8::Local<v8::Value> 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 */
 
 /*

+ 13 - 5
v8js_v8object_class.cc

@@ -161,29 +161,37 @@ 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_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */
+{
+	return NULL;
+}
+/* }}} */
+
+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;
+		return SINCE74(value,);
 	}
 
-	V8JS_CTX_PROLOGUE(obj->ctx);
+	V8JS_CTX_PROLOGUE_EX(obj->ctx, SINCE74(value,));
 	v8::Local<v8::Value> v8objHandle = v8::Local<v8::Value>::New(isolate, obj->v8obj);
 
 	if (Z_STRLEN_P(member) > std::numeric_limits<int>::max()) {
 		zend_throw_exception(php_ce_v8js_exception,
 			"Member name length exceeds maximum supported length", 0);
-		return;
+		return SINCE74(value,);
 	}
 
 	v8::Local<v8::Object> 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 SINCE74(value,);
 }
 /* }}} */
 
@@ -812,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;