0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-11-09 16:28:41 +00:00

Merge remote-tracking branch 'origin/master' into php7

Conflicts:
	README.md
	v8js.cc
	v8js_class.cc
	v8js_exceptions.cc
	v8js_object_export.cc
	v8js_v8.cc
	v8js_v8object_class.cc
This commit is contained in:
Stefan Siegl 2015-10-11 02:09:59 +02:00
commit 5cba44ccd0
28 changed files with 932 additions and 212 deletions

View File

@ -3,6 +3,11 @@ ifneq (,$(realpath $(EXTENSION_DIR)/json.so))
PHP_TEST_SHARED_EXTENSIONS+=-d extension=$(EXTENSION_DIR)/json.so
endif
# add pthreads extension, if available
ifneq (,$(realpath $(EXTENSION_DIR)/pthreads.so))
PHP_TEST_SHARED_EXTENSIONS+=-d extension=$(EXTENSION_DIR)/pthreads.so
endif
testv8: all
$(PHP_EXECUTABLE) -n -d extension_dir=./modules -d extension=v8js.so test.php

View File

@ -52,7 +52,7 @@ svn co http://src.chromium.org/svn/trunk/deps/third_party/cygwin@66844 third_par
svn co http://googletest.googlecode.com/svn/trunk testing/gtest --revision 643
svn co http://googlemock.googlecode.com/svn/trunk testing/gmock --revision 410
python build\gyp_v8 -Dcomponent=shared_library
python build\gyp_v8 -Dcomponent=shared_library -Dv8_use_snapshot=0
"\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.com" /build Release build/All.sln
```
@ -97,9 +97,9 @@ mkdir vc12\x86\deps\lib
and unpack to below `\php-sdk\phpdev\vc12\x86`
* from `\v8\build\Release\lib` copy `icui18n.lib`, `icuuc.lib` and `v8.lib`
to deps\lib folder
* from `\v8\include copy` all v8*.h files to deps\include folder
* within the PHP source code folder create a sub-directory named `pecl`
* download V8Js and unpack it into a seperate directory below the `pecl` folder
* from `\v8\include` copy all v8*.h files to deps\include folder
* download V8Js and unpack it into a separate directory below `ext` folder
* make sure `config.w32` file inside that folder defines version of the compiled v8
(still in "VS2013 x86 Native Tools Command Prompt")

View File

@ -17,7 +17,7 @@ of this repository.
Minimum requirements
--------------------
- V8 Javascript Engine library (libv8) master <https://github.com/v8/v8/> (trunk)
- V8 Javascript Engine library (libv8) master <https://github.com/v8/v8-git-mirror> (trunk)
V8 is Google's open source Javascript engine.
V8 is written in C++ and is used in Google Chrome, the open source browser from Google.
@ -26,7 +26,7 @@ Minimum requirements
- PHP 7.0.0+
This embedded implementation of the V8 engine uses thread locking so it should work with ZTS enabled.
This embedded implementation of the V8 engine uses thread locking so it works with ZTS enabled.
Compiling latest version
@ -55,6 +55,7 @@ class V8Js
const FLAG_NONE = 1;
const FLAG_FORCE_ARRAY = 2;
const FLAG_PROPAGATE_PHP_EXCEPTIONS = 4;
const DEBUG_AUTO_BREAK_NEVER = 1;
const DEBUG_AUTO_BREAK_ONCE = 2;
@ -304,3 +305,28 @@ PHP Objects implementing ArrayAccess, Countable
The above rule that PHP objects are generally converted to JavaScript objects also applies to PHP objects of `ArrayObject` type or other classes, that implement both the `ArrayAccess` and the `Countable` interface -- even so they behave like PHP arrays.
This behaviour can be changed by enabling the php.ini flag `v8js.use_array_access`. If set, objects of PHP classes that implement the aforementioned interfaces are converted to JavaScript Array-like objects. This is by-index access of this object results in immediate calls to the `offsetGet` or `offsetSet` PHP methods (effectively this is live-binding of JavaScript against the PHP object). Such an Array-esque object also supports calling every attached public method of the PHP object + methods of JavaScript's native Array.prototype methods (as long as they are not overloaded by PHP methods).
Exceptions
==========
If the JavaScript code throws (without catching), causes errors or doesn't
compile, `V8JsScriptException` exceptions are thrown unless the `V8Js` object
is constructed with `report_uncaught_exceptions` set `FALSE`.
PHP exceptions that occur due to calls from JavaScript code by default are
*not* re-thrown into JavaScript context but cause the JavaScript execution to
be stopped immediately and then are reported at the location calling the JS code.
This behaviour can be changed by setting the `FLAG_PROPAGATE_PHP_EXCEPTIONS`
flag. If it is set, PHP exception (objects) are converted to JavaScript
objects obeying the above rules and re-thrown in JavaScript context. If they
are not caught by JavaScript code the execution stops and a
`V8JsScriptException` is thrown, which has the original PHP exception accessible
via `getPrevious` method.
V8Js versions 0.2.4 and before did not stop JS code execution on PHP exceptions,
but silently ignored them (even so succeeding PHP calls from within the same piece
of JS code were not executed by the PHP engine). This behaviour is considered as
a bug and hence was fixed with 0.2.5 release. Nevertheless there is a
compatibility php.ini switch (`v8js.compat_php_exceptions`) which turns previous
behaviour back on.

View File

@ -16,11 +16,11 @@
<email>stesie@php.net</email>
<active>yes</active>
</lead>
<date>2015-07-26</date>
<time>00:04:15</time>
<date>2015-09-26</date>
<time>12:31:47</time>
<version>
<release>0.2.1</release>
<api>0.2.1</api>
<release>0.2.6</release>
<api>0.2.6</api>
</version>
<stability>
<release>beta</release>
@ -28,10 +28,7 @@
</stability>
<license uri="http://www.php.net/license">The MIT License (MIT)</license>
<notes>
- adapt to latest v8 API (v8 versions from 3.24.6 up to latest 4.6 branch supported now)
- fixed FLAG_FORCE_ARRAY behaviour regarding property assignments
- properly stop (and restart) timer thread (for memory &amp; cpu limits)
- fixed crash on failed module bootstrapping
- Fix reference counting issue on PHP-&gt;JS-&gt;PHP exception propagation
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@ -69,8 +66,15 @@
<file baseinstalldir="/" md5sum="72f2ffb206047d5918d4eb5f32284e3c" name="tests/checkstring_compile.phpt" role="test" />
<file baseinstalldir="/" md5sum="0e6c4098d0f370b2fa8f433ab6026c6a" name="tests/closures_basic.phpt" role="test" />
<file baseinstalldir="/" md5sum="1f5c7e8895220923d0203653fbebfc6f" name="tests/closures_dynamic.phpt" role="test" />
<file baseinstalldir="/" md5sum="50f7ba3626131cf015e26b7dc296d20d" name="tests/commonjs_caching_001.phpt" role="test" />
<file baseinstalldir="/" md5sum="9bcac28a73d4d274c0e62802fd7af96b" name="tests/commonjs_caching_002.phpt" role="test" />
<file baseinstalldir="/" md5sum="90c628544fa6f401221237511a9a4fb7" name="tests/commonjs_modules.phpt" role="test" />
<file baseinstalldir="/" md5sum="24e2a74c0d15b94cbcdc926d1e19af0c" name="tests/commonjs_multiassign.phpt" role="test" />
<file baseinstalldir="/" md5sum="1d7a8f251186c47ce92fe7b1fbb0abc0" name="tests/commonjs_normalise_001.phpt" role="test" />
<file baseinstalldir="/" md5sum="3d705ba0a7c22a73be170c9bae2303ba" name="tests/commonjs_normalise_002.phpt" role="test" />
<file baseinstalldir="/" md5sum="8e0e5d784e6f7f896dcc94acbf909bbc" name="tests/commonjs_normalise_003.phpt" role="test" />
<file baseinstalldir="/" md5sum="b573c7fa2e53c8d20eb88dfb747811fc" name="tests/commonjs_normalise_004.phpt" role="test" />
<file baseinstalldir="/" md5sum="e9eb81a3065e2858d79fb772e837982c" name="tests/commonjs_normalise_005.phpt" role="test" />
<file baseinstalldir="/" md5sum="6980e6a4c02cf3de87c0eab762fe2a69" name="tests/compile_string.phpt" role="test" />
<file baseinstalldir="/" md5sum="177659c1f2be8fb1b018341f896b7cd6" name="tests/compile_string_isolate.phpt" role="test" />
<file baseinstalldir="/" md5sum="bf4fed6b841034477cb61e3303fb1362" name="tests/construct.phpt" role="test" />
@ -88,7 +92,7 @@
<file baseinstalldir="/" md5sum="7da1f96584a7ed1edd19c73dd80f01d6" name="tests/exception.phpt" role="test" />
<file baseinstalldir="/" md5sum="1942e8949e4b323d6ef92aef92334103" name="tests/exception_clearing.phpt" role="test" />
<file baseinstalldir="/" md5sum="446308298f2562a0dd7779486fa561aa" name="tests/exception_propagation_1.phpt" role="test" />
<file baseinstalldir="/" md5sum="74026d3872c248782bf98dcc8e05ef41" name="tests/exception_propagation_2.phpt" role="test" />
<file baseinstalldir="/" md5sum="fafb380c87c0241f18fc4b5d318b282f" name="tests/exception_propagation_2.phpt" role="test" />
<file baseinstalldir="/" md5sum="f90813f9ac47107b4630461816ad6221" name="tests/exception_propagation_3.phpt" role="test" />
<file baseinstalldir="/" md5sum="cf4ef4abb30a47214e7f368b378f54a8" name="tests/exception_start_column.phpt" role="test" />
<file baseinstalldir="/" md5sum="8ed403ca3798d987b0f29e0132c7686f" name="tests/execute_flags.phpt" role="test" />
@ -111,7 +115,9 @@
<file baseinstalldir="/" md5sum="7d240e23d061f59599109cc679084da4" name="tests/has_property_after_dispose.phpt" role="test" />
<file baseinstalldir="/" md5sum="1443aef2fda8793abd79c06a29639797" name="tests/inheritance_basic.phpt" role="test" />
<file baseinstalldir="/" md5sum="afdb74aca312497cce114a8d9dba6ee9" name="tests/issue_116-v8function-injection.phpt" role="test" />
<file baseinstalldir="/" md5sum="422d9e9af28d9c7e8042bbf9496fc04c" name="tests/issue_127_001.phpt" role="test" />
<file baseinstalldir="/" md5sum="6d4e573daaf2ca5c177230541c31fc96" name="tests/issue_127_001.phpt" role="test" />
<file baseinstalldir="/" md5sum="3ff639cdb2f80e8b0a256aa12fce9c5d" name="tests/issue_156_001.phpt" role="test" />
<file baseinstalldir="/" md5sum="858c759b267b903dcdd65b5f208dc07f" name="tests/issue_160_basic.phpt" role="test" />
<file baseinstalldir="/" md5sum="9f1e697d63231a03da06de97c14a5076" name="tests/js-construct-basic.phpt" role="test" />
<file baseinstalldir="/" md5sum="0e951523a9abae08b531ecd3193a2581" name="tests/js-construct-direct-call.phpt" role="test" />
<file baseinstalldir="/" md5sum="7733d7eb9693e1c799a3d071a7804b13" name="tests/js-construct-protected-ctor.phpt" role="test" />
@ -129,6 +135,13 @@
<file baseinstalldir="/" md5sum="ed1d6d0aafe39f41545c375507507564" name="tests/object_passback.phpt" role="test" />
<file baseinstalldir="/" md5sum="95e8658755180e9dc7533c0ed4d61bb2" name="tests/object_prototype.phpt" role="test" />
<file baseinstalldir="/" md5sum="732770da7b148dcb702894dcb9462674" name="tests/object_reuse.phpt" role="test" />
<file baseinstalldir="/" md5sum="e49bb15778697eea7d717de4cfc0c385" name="tests/php_exceptions_001.phpt" role="test" />
<file baseinstalldir="/" md5sum="bc07bbc424d078d3d0590540a67648ba" name="tests/php_exceptions_002.phpt" role="test" />
<file baseinstalldir="/" md5sum="3913092b6336924271fd9315a87d0973" name="tests/php_exceptions_003.phpt" role="test" />
<file baseinstalldir="/" md5sum="66c0769781344af35f63d5d1b7a50852" name="tests/php_exceptions_004.phpt" role="test" />
<file baseinstalldir="/" md5sum="610889e09e1579075ef973ef41883e8f" name="tests/php_exceptions_005.phpt" role="test" />
<file baseinstalldir="/" md5sum="59e80f305f84f2effbac279261f8c5a6" name="tests/php_exceptions_006.phpt" role="test" />
<file baseinstalldir="/" md5sum="c513770deccefc87636a30aa4329f779" name="tests/php_exceptions_basic.phpt" role="test" />
<file baseinstalldir="/" md5sum="3cc6c105f2413e4270eba038e6a2dffd" name="tests/property_exists.phpt" role="test" />
<file baseinstalldir="/" md5sum="065d238a0c45902ce226622847e5e341" name="tests/property_visibility-delete.phpt" role="test" />
<file baseinstalldir="/" md5sum="4aa538bcaa3ab56b2fad8b6105ec1717" name="tests/property_visibility-enumerate.phpt" role="test" />
@ -158,39 +171,40 @@
<file baseinstalldir="/" md5sum="35ce3816ae00e697fca26142c46e0c79" name="tests/v8_write_property.phpt" role="test" />
<file baseinstalldir="/" md5sum="ae504a63e5ff800e3aa7d529835d0e8e" name="tests/variable_passing.phpt" role="test" />
<file baseinstalldir="/" md5sum="1bd7738aeeb5cf80d80561554f59f2ed" name="tests/var_dump.phpt" role="test" />
<file baseinstalldir="/" md5sum="19150f213fb00790c51f22989b39ff55" name="config.m4" role="src" />
<file baseinstalldir="/" md5sum="63c4b2873ccc935571ae7fbb1baeab7b" name="config.m4" role="src" />
<file baseinstalldir="/" md5sum="987d834d2edc84ead98dc1fddba2ad73" name="config.w32" role="src" />
<file baseinstalldir="/" md5sum="cea72666538d5b0b80a64ccdbda24919" name="CREDITS" role="doc" />
<file baseinstalldir="/" md5sum="9f5b5f41204bcde55d9df87d5a970b30" name="LICENSE" role="doc" />
<file baseinstalldir="/" md5sum="25260e0bc3111b01f700fad13544d6a9" name="Makefile.frag" role="src" />
<file baseinstalldir="/" md5sum="31e331386def7ce98943694151c0d5cb" name="Makefile.travis" role="src" />
<file baseinstalldir="/" md5sum="0e23fa6446e52a3b1cff8b18a6e0bd79" name="php_v8js.h" role="src" />
<file baseinstalldir="/" md5sum="b81ab8ff4f87d883363b02fe358da87c" name="php_v8js_macros.h" role="src" />
<file baseinstalldir="/" md5sum="8d36541e788d9f2de7d19d4e167a1b3b" name="README.Linux.md" role="doc" />
<file baseinstalldir="/" md5sum="0d986531818b0e31633f2db3a242afb7" name="php_v8js_macros.h" role="src" />
<file baseinstalldir="/" md5sum="ec19e63ca9310bfc4dc4dbd357c779ae" name="README.Linux.md" role="doc" />
<file baseinstalldir="/" md5sum="4a65a3f9995d325a2c2ccb23224ea503" name="README.MacOS.md" role="doc" />
<file baseinstalldir="/" md5sum="00cc5dd1c69120c7156abd08efafacba" name="README.md" role="doc" />
<file baseinstalldir="/" md5sum="f7baf040ec2145f7eeccd5540ebb085f" name="README.Win32.md" role="doc" />
<file baseinstalldir="/" md5sum="177459a9628e3c8c31b305f20c970f8d" name="README.md" role="doc" />
<file baseinstalldir="/" md5sum="9839870e001306943797003e8828d855" name="README.Win32.md" role="doc" />
<file baseinstalldir="/" md5sum="542f52c54898f33ac53b173970cba305" name="test.php" role="php" />
<file baseinstalldir="/" md5sum="65294fadb5ed766094b1f587fc20ad37" name="TODO" role="doc" />
<file baseinstalldir="/" md5sum="d1e8223596fac67062055261b6cf1180" name="v8js.cc" role="src" />
<file baseinstalldir="/" md5sum="cc54d77b4d0044d7b143989f2dc12b94" name="v8js.cc" role="src" />
<file baseinstalldir="/" md5sum="358c628b2627319e40fd7e5092f19872" name="v8js_array_access.cc" role="src" />
<file baseinstalldir="/" md5sum="7baf3fe5b77d1374b39a1d8332e05df4" name="v8js_array_access.h" role="src" />
<file baseinstalldir="/" md5sum="5504a5f186152a48ef3b3819bd53a676" name="v8js_class.cc" role="src" />
<file baseinstalldir="/" md5sum="afd1c86428a25cc71c35a6f9e3ea04bb" name="v8js_class.h" role="src" />
<file baseinstalldir="/" md5sum="795e65a077e963de413eb6947edd1f94" name="v8js_commonjs.cc" role="src" />
<file baseinstalldir="/" md5sum="6b3d174805b6c97bdec88b9479e8ce6c" name="v8js_convert.cc" role="src" />
<file baseinstalldir="/" md5sum="6c213918edf4f46ac630498e92bb99f6" name="v8js_class.cc" role="src" />
<file baseinstalldir="/" md5sum="444a6fda6259076cd2a419cf59ab2c42" name="v8js_class.h" role="src" />
<file baseinstalldir="/" md5sum="88b49988a5ef55edbd7ba085e7857f64" name="v8js_commonjs.cc" role="src" />
<file baseinstalldir="/" md5sum="32a5d1a65f64ec37ec294f496fc11ff1" name="v8js_commonjs.h" role="src" />
<file baseinstalldir="/" md5sum="c061344705c42fb705bffb2959fc1001" name="v8js_convert.cc" role="src" />
<file baseinstalldir="/" md5sum="ede2cf80141b1831c7e7ab50dc57236f" name="v8js_debug.cc" role="src" />
<file baseinstalldir="/" md5sum="cbdb6ed29c9ece278aa2aeab75dbe61f" name="v8js_debug.h" role="src" />
<file baseinstalldir="/" md5sum="1867ebcefbc577aed051f40d9ccc58ad" name="v8js_exceptions.cc" role="src" />
<file baseinstalldir="/" md5sum="587370513a019c34f2ddaac3b1f4cbf8" name="v8js_exceptions.h" role="src" />
<file baseinstalldir="/" md5sum="3b5845c5f4109366257a9e35975703ac" name="v8js_methods.cc" role="src" />
<file baseinstalldir="/" md5sum="55bfab106f9a92e8909aa6fba344037c" name="v8js_object_export.cc" role="src" />
<file baseinstalldir="/" md5sum="40b66c44650a8127618c7fc48bf4b0b2" name="v8js_exceptions.cc" role="src" />
<file baseinstalldir="/" md5sum="9d13bf5f413c2d76664670e847e1a801" name="v8js_exceptions.h" role="src" />
<file baseinstalldir="/" md5sum="9f3ad8c136cdc3ebc2bdf993491f9ad8" name="v8js_methods.cc" role="src" />
<file baseinstalldir="/" md5sum="d688b8eb822736d49f7282d22546d6bc" name="v8js_object_export.cc" role="src" />
<file baseinstalldir="/" md5sum="281fb591fbebc3d23e04196cdb3ec64a" name="v8js_object_export.h" role="src" />
<file baseinstalldir="/" md5sum="767d38eec0b407fba5e30398444e180e" name="v8js_timer.cc" role="src" />
<file baseinstalldir="/" md5sum="d96c0e1eeaf1693813236f7e5da61e09" name="v8js_timer.cc" role="src" />
<file baseinstalldir="/" md5sum="49f609c8cea6033f2ad1e6c9c829a571" name="v8js_timer.h" role="src" />
<file baseinstalldir="/" md5sum="41b036ea855a1c8682a93d50dd834a67" name="v8js_v8.cc" role="src" />
<file baseinstalldir="/" md5sum="72cc4af7af63c62138d4156faf784ec9" name="v8js_v8.h" role="src" />
<file baseinstalldir="/" md5sum="842fb2dea63c473cdfaf501321a6a530" name="v8js_v8object_class.cc" role="src" />
<file baseinstalldir="/" md5sum="b3ba6b76f92683c55b45bce351af887e" name="v8js_v8.cc" role="src" />
<file baseinstalldir="/" md5sum="0c4829d52ff46116c381b1b66ec27541" name="v8js_v8.h" role="src" />
<file baseinstalldir="/" md5sum="82908f4e741755efa2aedfb486945a40" name="v8js_v8object_class.cc" role="src" />
<file baseinstalldir="/" md5sum="8a80d71ff40dfa833d3b58ac94475a9f" name="v8js_v8object_class.h" role="src" />
<file baseinstalldir="/" md5sum="29be67d9bf8bfb1642d1219356109063" name="v8js_variables.cc" role="src" />
</dir>
@ -331,5 +345,87 @@
- fixed crash on failed module bootstrapping
</notes>
</release>
<release>
<version>
<release>0.2.2</release>
<api>0.2.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2015-08-26</date>
<license uri="http://www.php.net/license">The MIT License (MIT)</license>
<notes>
- Fix CommonJS module caching
- Fix use-after-free issue on CommonJS module reuse
- Fix memory leaks in CommonJS module loader
- Fix memory leak regarding lost script resources (compileScript call et al)
- Improve V8Function call performance
</notes>
</release>
<release>
<version>
<release>0.2.3</release>
<api>0.2.3</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2015-08-27</date>
<license uri="http://www.php.net/license">The MIT License (MIT)</license>
<notes>
- Fix FLAG_FORCE_ARRAY affecting V8Function objects
- Fix memory leak with repeated calls of methods on exported PHP objects
</notes>
</release>
<release>
<version>
<release>0.2.4</release>
<api>0.2.4</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2015-09-01</date>
<license uri="http://www.php.net/license">The MIT License (MIT)</license>
<notes>
- Fix memory leak with repeated Array exports from PHP to JS
</notes>
</release>
<release>
<version>
<release>0.2.5</release>
<api>0.2.5</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2015-09-23</date>
<license uri="http://www.php.net/license">The MIT License (MIT)</license>
<notes>
- Stop JS execution on PHP exceptions (instead of continuing silently)
- Allow propagation of PHP exceptions to JS context (disabled by default)
- Add v8js.compat_php_exceptions php.ini switch to switch previous behaviour back on
</notes>
</release>
<release>
<version>
<release>0.2.6</release>
<api>0.2.6</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2015-09-26</date>
<license uri="http://www.php.net/license">The MIT License (MIT)</license>
<notes>
- Fix reference counting issue on PHP-&gt;JS-&gt;PHP exception propagation
</notes>
</release>
</changelog>
</package>

View File

@ -52,7 +52,7 @@ extern "C" {
#endif
/* V8Js Version */
#define PHP_V8JS_VERSION "0.2.1"
#define PHP_V8JS_VERSION "0.2.6"
/* Hidden field name used to link JS wrappers with underlying PHP object */
#define PHPJS_OBJECT_KEY "phpjs::object"
@ -69,13 +69,10 @@ extern "C" {
# define V8JS_CONST (char *)
#endif
/* Global flags */
#define V8JS_GLOBAL_SET_FLAGS(isolate,flags) V8JS_GLOBAL(isolate)->SetHiddenValue(V8JS_SYM("__php_flags__"), V8JS_INT(flags))
#define V8JS_GLOBAL_GET_FLAGS(isolate) V8JS_GLOBAL(isolate)->GetHiddenValue(V8JS_SYM("__php_flags__"))->IntegerValue();
/* Options */
#define V8JS_FLAG_NONE (1<<0)
#define V8JS_FLAG_FORCE_ARRAY (1<<1)
#define V8JS_FLAG_PROPAGATE_PHP_EXCEPTIONS (1<<2)
#define V8JS_DEBUG_AUTO_BREAK_NEVER 0
#define V8JS_DEBUG_AUTO_BREAK_ONCE 1
@ -104,16 +101,13 @@ struct v8js_timer_ctx;
/* Module globals */
ZEND_BEGIN_MODULE_GLOBALS(v8js)
// Thread-local cache whether V8 has been initialized so far
int v8_initialized;
#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036
v8::Platform *v8_platform;
#endif
HashTable *extensions;
/* Ini globals */
char *v8_flags; /* V8 command line flags */
bool use_date; /* Generate JS Date objects instead of PHP DateTime */
bool use_array_access; /* Convert ArrayAccess, Countable objects to array-like objects */
bool compat_php_exceptions; /* Don't stop JS execution on PHP exception */
// Timer thread globals
std::deque<v8js_timer_ctx *> timer_stack;
@ -130,6 +124,39 @@ ZEND_EXTERN_MODULE_GLOBALS(v8js)
#define V8JSG(v) ZEND_MODULE_GLOBALS_ACCESSOR(v8js, v)
/*
* Process-wide globals
*
* The zend_v8js_globals structure declared above is created once per thread
* (in a ZTS environment). If a multi-threaded PHP process uses V8 there is
* some stuff shared among all of these threads
*
* - whether V8 has been initialized at all
* - the V8 backend platform
* - loaded extensions
* - V8 "command line" flags
*
* In a ZTS-enabled environment access to all of these variables must happen
* while holding a mutex lock.
*/
struct _v8js_process_globals {
#ifdef ZTS
int v8_initialized;
std::mutex lock;
#endif
HashTable *extensions;
/* V8 command line flags */
char *v8_flags;
#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036
v8::Platform *v8_platform;
#endif
};
extern struct _v8js_process_globals v8js_process_globals;
/* Register builtin methods into passed object */
void v8js_register_methods(v8::Handle<v8::ObjectTemplate>, v8js_ctx *c);

View File

@ -14,6 +14,9 @@ class Foo {
$this->v8->foo = $this;
$this->v8->executeString('fooobar', 'throw_0');
var_dump($this->v8->getPendingException());
// the exception is not cleared before the next executeString call,
// hence the next *exiting* executeString will throw.
// In this case this is the executeString call in bar() function.
$this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch1');
$this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch2');
}
@ -21,6 +24,8 @@ class Foo {
public function bar()
{
echo "To Bar!\n";
// This executeString call throws a PHP exception, not propagated
// to JS, hence immediately triggering the top-level catch handler.
$this->v8->executeString('throw new Error();', 'throw_1');
}
}
@ -71,7 +76,7 @@ object(V8JsScriptException)#%d (13) {
["file"]=>
string(%d) "%s"
["line"]=>
int(24)
int(29)
["function"]=>
string(11) "__construct"
["class"]=>
@ -100,6 +105,5 @@ object(V8JsScriptException)#%d (13) {
at throw_0:1:1"
}
To Bar!
Error caught!
PHP Exception: throw_0:1: ReferenceError: fooobar is not defined
===EOF===

33
tests/issue_156_001.phpt Normal file
View File

@ -0,0 +1,33 @@
--TEST--
Test V8::executeString() : Backwards compatibility for issue #156
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--INI--
v8js.compat_php_exceptions = 1
--FILE--
<?php
$v8 = new V8Js();
$v8->throwPHPException = function () {
echo "throwing PHP exception now ...\n";
throw new \Exception('foo');
};
$JS = <<< EOT
PHP.throwPHPException();
print("... old behaviour was to not stop JS execution on PHP exceptions\\n");
EOT;
try {
$v8->executeString($JS, 'issue_156_001.js');
} catch(Exception $e) {
var_dump($e->getMessage());
}
?>
===EOF===
--EXPECT--
throwing PHP exception now ...
... old behaviour was to not stop JS execution on PHP exceptions
string(3) "foo"
===EOF===

View File

@ -0,0 +1,23 @@
--TEST--
Test V8::executeString() : Issue #160 V8Function affected by V8Js::FLAG_FORCE_ARRAY
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
$v8 = new V8Js();
$JS = <<<EOT
(function(foo) { print(foo); });
EOT;
$func = $v8->executeString($JS, 'test', V8Js::FLAG_FORCE_ARRAY);
var_dump($func);
$func("Test-Foo Func Call\n");
?>
===EOF===
--EXPECTF--
object(V8Function)#%d (0) {
}
Test-Foo Func Call
===EOF===

View File

@ -0,0 +1,50 @@
--TEST--
Test V8::executeString() : PHP Exception handling (repeated)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function throwException() {
throw new \Exception("Test-Exception");
}
}
$v8 = new V8Js();
$v8->foo = new \Foo();
$JS = <<< EOT
try {
PHP.foo.throwException();
// the exception should abort further execution,
// hence the print must not pop up
print("after throwException\\n");
} catch(e) {
// JS should not catch in default mode
print("JS caught exception");
}
EOT;
for($i = 0; $i < 5; $i ++) {
var_dump($i);
try {
$v8->executeString($JS);
} catch (Exception $e) {
var_dump($e->getMessage());
}
}
?>
===EOF===
--EXPECTF--
int(0)
string(14) "Test-Exception"
int(1)
string(14) "Test-Exception"
int(2)
string(14) "Test-Exception"
int(3)
string(14) "Test-Exception"
int(4)
string(14) "Test-Exception"
===EOF===

View File

@ -0,0 +1,67 @@
--TEST--
Test V8::executeString() : PHP Exception handling (multi-level)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function throwException() {
throw new \Exception("Test-Exception");
}
function recurse($i) {
echo "recurse[$i] ...\n";
global $work;
$work($i);
}
}
$v8 = new V8Js();
$v8->foo = new \Foo();
$work = $v8->executeString(<<<EOT
var work = function(level) {
if(level--) {
PHP.foo.recurse(level);
}
else {
PHP.foo.throwException();
}
};
work;
EOT
);
for($i = 0; $i < 5; $i ++) {
var_dump($i);
try {
$work($i);
} catch (Exception $e) {
var_dump($e->getMessage());
}
}
?>
===EOF===
--EXPECT--
int(0)
string(14) "Test-Exception"
int(1)
recurse[0] ...
string(14) "Test-Exception"
int(2)
recurse[1] ...
recurse[0] ...
string(14) "Test-Exception"
int(3)
recurse[2] ...
recurse[1] ...
recurse[0] ...
string(14) "Test-Exception"
int(4)
recurse[3] ...
recurse[2] ...
recurse[1] ...
recurse[0] ...
string(14) "Test-Exception"
===EOF===

View File

@ -0,0 +1,36 @@
--TEST--
Test V8::executeString() : PHP Exception handling (basic JS propagation)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function throwException() {
throw new \Exception("Test-Exception");
}
}
$v8 = new V8Js();
$v8->foo = new \Foo();
$JS = <<< EOT
try {
PHP.foo.throwException();
// the exception should abort further execution,
// hence the print must not pop up
print("after throwException\\n");
} catch(e) {
print("JS caught exception!\\n");
var_dump(e.getMessage());
}
EOT;
$v8->executeString($JS, 'php_exceptions_003', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS);
?>
===EOF===
--EXPECTF--
JS caught exception!
string(14) "Test-Exception"
===EOF===

View File

@ -0,0 +1,36 @@
--TEST--
Test V8::executeString() : PHP Exception handling (PHP->JS->PHP back propagation)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function throwException() {
throw new \Exception("Test-Exception");
}
}
$v8 = new V8Js();
$v8->foo = new \Foo();
$JS = <<< EOT
PHP.foo.throwException();
// the exception should abort further execution,
// hence the print must not pop up
print("after throwException\\n");
EOT;
try {
$v8->executeString($JS, 'php_exceptions_004', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS);
}
catch(V8JsScriptException $e) {
echo "Got V8JsScriptException\n";
var_dump($e->getPrevious()->getMessage());
}
?>
===EOF===
--EXPECTF--
Got V8JsScriptException
string(14) "Test-Exception"
===EOF===

View File

@ -0,0 +1,43 @@
--TEST--
Test V8::executeString() : PHP Exception handling (JS throw PHP-exception)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function getException() {
return new \Exception("Test-Exception");
}
}
$v8 = new V8Js();
$v8->foo = new \Foo();
$JS = <<< EOT
var ex = PHP.foo.getException();
print("after getException\\n");
throw ex;
print("after throw\\n");
EOT;
try {
$v8->executeString($JS, 'php_exceptions_005');
}
catch(V8JsScriptException $e) {
echo "Got V8JsScriptException\n";
var_dump($e->getMessage());
var_dump($e->getPrevious()->getMessage());
}
?>
===EOF===
--EXPECTF--
after getException
Got V8JsScriptException
string(%d) "php_exceptions_005:3: exception 'Exception' with message 'Test-Exception' in %s
Stack trace:
#0 [internal function]: Foo->getException()
#1 %s: V8Js->executeString('var ex = PHP.fo...', 'php_exceptions_...')
#2 {main}"
string(14) "Test-Exception"
===EOF===

View File

@ -0,0 +1,40 @@
--TEST--
Test V8::executeString() : PHP Exception handling (JS throws normal PHP-object)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function getNonExceptionObject() {
return new \Foo();
}
}
$v8 = new V8Js();
$v8->foo = new \Foo();
$JS = <<< EOT
var ex = PHP.foo.getNonExceptionObject();
print("after getNonExceptionObject\\n");
throw ex;
print("after throw\\n");
EOT;
try {
$v8->executeString($JS, 'php_exceptions_006');
}
catch(V8JsScriptException $e) {
echo "Got V8JsScriptException\n";
var_dump($e->getMessage());
// previous exception should be NULL, as it is *not* a php exception
var_dump($e->getPrevious());
}
?>
===EOF===
--EXPECTF--
after getNonExceptionObject
Got V8JsScriptException
string(34) "php_exceptions_006:3: [object Foo]"
NULL
===EOF===

View File

@ -0,0 +1,42 @@
--TEST--
Test V8::executeString() : PHP Exception handling (basic)
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--FILE--
<?php
class Foo {
function throwException() {
throw new \Exception("Test-Exception");
}
}
$v8 = new V8Js();
$v8->foo = new \Foo();
$JS = <<< EOT
try {
PHP.foo.throwException();
// the exception should abort further execution,
// hence the print must not pop up
print("after throwException\\n");
} catch(e) {
// JS should not catch in default mode
print("JS caught exception");
}
EOT;
try {
$v8->executeString($JS);
} catch (Exception $e) {
var_dump($e->getMessage());
var_dump($e->getFile());
var_dump($e->getLine());
}
?>
===EOF===
--EXPECTF--
string(14) "Test-Exception"
string(%d) "%sphp_exceptions_basic.php"
int(5)
===EOF===

65
tests/pthreads_001.phpt Normal file
View File

@ -0,0 +1,65 @@
--TEST--
Test V8::executeString() : Pthreads test #1
--SKIPIF--
<?php
require_once(dirname(__FILE__) . '/skipif.inc');
if(!class_exists('Thread')) {
die('skip pthreads extension required');
}
?>
--FILE--
<?php
class Workhorse extends Thread
{
protected $val;
public function __construct($val)
{
$this->val = $val;
}
public function run()
{
$v8 = new V8Js();
$v8->val = $this->val;
$v8->sync_var_dump = function($value) {
$this->synchronized(function($thread) use ($value) {
while(!$thread->readyToPrint) {
$thread->wait();
}
var_dump($value);
$thread->notify();
}, $this);
};
$v8->executeString('PHP.sync_var_dump(PHP.val);');
}
}
$foo = new Workhorse('foo');
$bar = new Workhorse('bar');
$foo->start();
$bar->start();
$bar->synchronized(function($thread) {
$thread->readyToPrint = true;
$thread->notify();
$thread->wait();
}, $bar);
$foo->synchronized(function($thread) {
$thread->readyToPrint = true;
$thread->notify();
$thread->wait();
}, $foo);
$foo->join();
$bar->join();
?>
===EOF===
--EXPECT--
string(3) "bar"
string(3) "foo"
===EOF===

125
v8js.cc
View File

@ -28,55 +28,77 @@ extern "C" {
#include "v8js_v8object_class.h"
ZEND_DECLARE_MODULE_GLOBALS(v8js)
struct _v8js_process_globals v8js_process_globals;
/* {{{ INI Settings */
static ZEND_INI_MH(v8js_OnUpdateV8Flags) /* {{{ */
{
bool immutable = false;
#ifdef ZTS
v8js_process_globals.lock.lock();
if(v8js_process_globals.v8_initialized) {
v8js_process_globals.lock.unlock();
immutable = true;
}
v8js_process_globals.lock.unlock();
#else
immutable = V8JSG(v8_initialized);
#endif
if(immutable) {
/* V8 already has been initialized -> cannot be changed anymore */
return FAILURE;
}
if (new_value) {
if (V8JSG(v8_flags)) {
free(V8JSG(v8_flags));
V8JSG(v8_flags) = NULL;
if (v8js_process_globals.v8_flags) {
free(v8js_process_globals.v8_flags);
v8js_process_globals.v8_flags = NULL;
}
if (!new_value->val[0]) {
return FAILURE;
}
V8JSG(v8_flags) = zend_strndup(new_value->val, new_value->len);
v8js_process_globals.v8_flags = zend_strndup(new_value->val, new_value->len);
}
return SUCCESS;
}
static bool v8js_ini_to_bool(const zend_string *new_value) /* {{{ */
{
if (new_value->len == 2 && strcasecmp("on", new_value->val) == 0) {
return true;
} else if (new_value->len == 3 && strcasecmp("yes", new_value->val) == 0) {
return true;
} else if (new_value->len == 4 && strcasecmp("true", new_value->val) == 0) {
return true;
} else {
return (bool) atoi(new_value->val);
}
}
/* }}} */
static ZEND_INI_MH(v8js_OnUpdateUseDate) /* {{{ */
{
bool value;
if (new_value->len == 2 && strcasecmp("on", new_value->val) == 0) {
value = (bool) 1;
} else if (new_value->len == 3 && strcasecmp("yes", new_value->val) == 0) {
value = (bool) 1;
} else if (new_value->len == 4 && strcasecmp("true", new_value->val) == 0) {
value = (bool) 1;
} else {
value = (bool) atoi(new_value->val);
}
V8JSG(use_date) = value;
V8JSG(use_date) = v8js_ini_to_bool(new_value);
return SUCCESS;
}
/* }}} */
static ZEND_INI_MH(v8js_OnUpdateUseArrayAccess) /* {{{ */
{
bool value;
if (new_value->len == 2 && strcasecmp("on", new_value->val) == 0) {
value = (bool) 1;
} else if (new_value->len == 3 && strcasecmp("yes", new_value->val) == 0) {
value = (bool) 1;
} else if (new_value->len == 4 && strcasecmp("true", new_value->val) == 0) {
value = (bool) 1;
} else {
value = (bool) atoi(new_value->val);
}
V8JSG(use_array_access) = value;
V8JSG(use_array_access) = v8js_ini_to_bool(new_value);
return SUCCESS;
}
/* }}} */
static ZEND_INI_MH(v8js_OnUpdateCompatExceptions) /* {{{ */
{
V8JSG(compat_php_exceptions) = v8js_ini_to_bool(new_value);
return SUCCESS;
}
/* }}} */
@ -85,6 +107,7 @@ ZEND_INI_BEGIN() /* {{{ */
ZEND_INI_ENTRY("v8js.flags", NULL, ZEND_INI_ALL, v8js_OnUpdateV8Flags)
ZEND_INI_ENTRY("v8js.use_date", "0", ZEND_INI_ALL, v8js_OnUpdateUseDate)
ZEND_INI_ENTRY("v8js.use_array_access", "0", ZEND_INI_ALL, v8js_OnUpdateUseArrayAccess)
ZEND_INI_ENTRY("v8js.compat_php_exceptions", "0", ZEND_INI_ALL, v8js_OnUpdateCompatExceptions)
ZEND_INI_END()
/* }}} */
@ -119,6 +142,35 @@ PHP_MINIT_FUNCTION(v8js)
static PHP_MSHUTDOWN_FUNCTION(v8js)
{
UNREGISTER_INI_ENTRIES();
bool v8_initialized;
#ifdef ZTS
v8_initialized = v8js_process_globals.v8_initialized;
#else
v8_initialized = V8JSG(v8_initialized);
#endif
if(v8_initialized) {
v8::V8::Dispose();
#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036
v8::V8::ShutdownPlatform();
// @fixme call virtual destructor somehow
//delete v8js_process_globals.v8_platform;
#endif
}
if (v8js_process_globals.v8_flags) {
free(v8js_process_globals.v8_flags);
v8js_process_globals.v8_flags = NULL;
}
if (v8js_process_globals.extensions) {
zend_hash_destroy(v8js_process_globals.extensions);
free(v8js_process_globals.extensions);
v8js_process_globals.extensions = NULL;
}
return SUCCESS;
}
/* }}} */
@ -174,9 +226,7 @@ static PHP_GINIT_FUNCTION(v8js)
run the destructors manually.
*/
#ifdef ZTS
v8js_globals->extensions = NULL;
v8js_globals->v8_initialized = 0;
v8js_globals->v8_flags = NULL;
v8js_globals->timer_thread = NULL;
v8js_globals->timer_stop = false;
@ -192,29 +242,10 @@ static PHP_GINIT_FUNCTION(v8js)
*/
static PHP_GSHUTDOWN_FUNCTION(v8js)
{
if (v8js_globals->extensions) {
zend_hash_destroy(v8js_globals->extensions);
free(v8js_globals->extensions);
v8js_globals->extensions = NULL;
}
if (v8js_globals->v8_flags) {
free(v8js_globals->v8_flags);
v8js_globals->v8_flags = NULL;
}
#ifdef ZTS
v8js_globals->timer_stack.~deque();
v8js_globals->timer_mutex.~mutex();
#endif
if (v8js_globals->v8_initialized) {
v8::V8::Dispose();
#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036
v8::V8::ShutdownPlatform();
delete v8js_globals->v8_platform;
#endif
}
}
/* }}} */

View File

@ -2,12 +2,13 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2013 The PHP Group |
| Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
| Author: Jani Taskinen <jani.taskinen@iki.fi> |
| Author: Patrick Reilly <preilly@php.net> |
| Author: Stefan Siegl <stesie@php.net> |
+----------------------------------------------------------------------+
*/
@ -103,6 +104,22 @@ static void v8js_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
c->object_name.~Persistent();
c->global_template.Reset();
c->global_template.~Persistent();
c->array_tmpl.Reset();
c->array_tmpl.~Persistent();
/* Clear persistent call_impl & method_tmpls templates */
for (std::map<v8js_tmpl_t *, v8js_tmpl_t>::iterator it = c->call_impls.begin();
it != c->call_impls.end(); ++it) {
// No need to free it->first, as it is stored in c->template_cache and freed below
it->second.Reset();
}
c->call_impls.~map();
for (std::map<zend_function *, v8js_tmpl_t>::iterator it = c->method_tmpls.begin();
it != c->method_tmpls.end(); ++it) {
it->second.Reset();
}
c->method_tmpls.~map();
/* Clear persistent handles in template cache */
for (std::map<const zend_string *,v8js_tmpl_t>::iterator it = c->template_cache.begin();
@ -196,6 +213,7 @@ static zend_object* v8js_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */
new(&c->object_name) v8::Persistent<v8::String>();
new(&c->context) v8::Persistent<v8::Context>();
new(&c->global_template) v8::Persistent<v8::FunctionTemplate>();
new(&c->array_tmpl) v8::Persistent<v8::FunctionTemplate>();
new(&c->modules_stack) std::vector<char*>();
new(&c->modules_base) std::vector<char*>();
@ -206,6 +224,8 @@ static zend_object* v8js_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */
new(&c->weak_closures) std::map<v8js_tmpl_t *, v8js_persistent_obj_t>();
new(&c->weak_objects) std::map<zend_object *, v8js_persistent_obj_t>();
new(&c->call_impls) std::map<v8js_tmpl_t *, v8js_tmpl_t>();
new(&c->method_tmpls) std::map<zend_function *, v8js_tmpl_t>();
new(&c->v8js_v8objects) std::list<v8js_v8object *>();
new(&c->script_objects) std::vector<v8js_script *>();
@ -480,7 +500,7 @@ static void v8js_compile_script(zval *this_ptr, zend_string *str, zend_string *i
/* Compile errors? */
if (script.IsEmpty()) {
v8js_throw_script_exception(&try_catch TSRMLS_CC);
v8js_throw_script_exception(c->isolate, &try_catch TSRMLS_CC);
return;
}
res = (v8js_script *)emalloc(sizeof(v8js_script));
@ -774,10 +794,17 @@ static int v8js_register_extension(zend_string *name, zend_string *source, zval
{
v8js_jsext *jsext = NULL;
if (!V8JSG(extensions)) {
V8JSG(extensions) = (HashTable *) malloc(sizeof(HashTable));
zend_hash_init(V8JSG(extensions), 1, NULL, v8js_jsext_dtor, 1);
} else if (zend_hash_exists(V8JSG(extensions), name)) {
#ifdef ZTS
v8js_process_globals.lock.lock();
#endif
if (!v8js_process_globals.extensions) {
v8js_process_globals.extensions = (HashTable *) malloc(sizeof(HashTable));
zend_hash_init(v8js_process_globals.extensions, 1, NULL, v8js_jsext_dtor, 1);
} else if (zend_hash_exists(v8js_process_globals.extensions, name)) {
#ifdef ZTS
v8js_process_globals.lock.unlock();
#endif
return FAILURE;
}
@ -789,6 +816,9 @@ static int v8js_register_extension(zend_string *name, zend_string *source, zval
if (v8js_create_ext_strarr(&jsext->deps, jsext->deps_count, Z_ARRVAL_P(deps_arr)) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid dependency array passed");
v8js_jsext_free_storage(jsext);
#ifdef ZTS
v8js_process_globals.lock.unlock();
#endif
return FAILURE;
}
}
@ -805,11 +835,18 @@ static int v8js_register_extension(zend_string *name, zend_string *source, zval
jsext->extension = new v8::Extension(ZSTR_VAL(jsext->name), ZSTR_VAL(jsext->source), jsext->deps_count, jsext->deps);
if (!zend_hash_add_ptr(V8JSG(extensions), jsext->name, jsext)) {
if (!zend_hash_add_ptr(v8js_process_globals.extensions, jsext->name, jsext)) {
v8js_jsext_free_storage(jsext);
#ifdef ZTS
v8js_process_globals.lock.unlock();
#endif
return FAILURE;
}
#ifdef ZTS
v8js_process_globals.lock.unlock();
#endif
jsext->extension->set_auto_enable(auto_enable ? true : false);
v8::RegisterExtension(jsext->extension);
@ -857,8 +894,12 @@ static PHP_METHOD(V8Js, getExtensions)
array_init(return_value);
if (V8JSG(extensions)) {
ZEND_HASH_FOREACH_KEY_VAL(V8JSG(extensions), index, key, val) {
#ifdef ZTS
v8js_process_globals.lock.lock();
#endif
if (v8js_process_globals.extensions) {
ZEND_HASH_FOREACH_KEY_VAL(v8js_process_globals.extensions, index, key, val) {
if (key) {
jsext = (v8js_jsext *) Z_PTR_P(val);
array_init(&ext);
@ -873,6 +914,10 @@ static PHP_METHOD(V8Js, getExtensions)
}
} ZEND_HASH_FOREACH_END();
}
#ifdef ZTS
v8js_process_globals.lock.unlock();
#endif
}
/* }}} */
@ -1039,6 +1084,7 @@ PHP_MINIT_FUNCTION(v8js_class) /* {{{ */
zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("FLAG_NONE"), V8JS_FLAG_NONE TSRMLS_CC);
zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("FLAG_FORCE_ARRAY"), V8JS_FLAG_FORCE_ARRAY TSRMLS_CC);
zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("FLAG_PROPAGATE_PHP_EXCEPTIONS"), V8JS_FLAG_PROPAGATE_PHP_EXCEPTIONS TSRMLS_CC);
#ifdef ENABLE_DEBUGGER_SUPPORT
zend_declare_class_constant_long(php_ce_v8js, ZEND_STRL("DEBUG_AUTO_BREAK_NEVER"), V8JS_DEBUG_AUTO_BREAK_NEVER TSRMLS_CC);

View File

@ -39,12 +39,15 @@ struct v8js_ctx {
int in_execution;
v8::Isolate *isolate;
long flags;
long time_limit;
bool time_limit_hit;
long memory_limit;
bool memory_limit_hit;
v8::Persistent<v8::FunctionTemplate> global_template;
v8js_tmpl_t global_template;
v8js_tmpl_t array_tmpl;
zval module_loader;
std::vector<char *> modules_stack;
@ -54,6 +57,8 @@ struct v8js_ctx {
std::map<zend_object *, v8js_persistent_obj_t> weak_objects;
std::map<v8js_tmpl_t *, v8js_persistent_obj_t> weak_closures;
std::map<v8js_tmpl_t *, v8js_tmpl_t> call_impls;
std::map<zend_function *, v8js_tmpl_t> method_tmpls;
std::list<v8js_v8object *> v8js_v8objects;

View File

@ -235,7 +235,7 @@ int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags, v
RETVAL_ZVAL(&zval_object, 1, 0);
return SUCCESS;
}
if ((flags & V8JS_FLAG_FORCE_ARRAY) || jsValue->IsArray()) {
if ((flags & V8JS_FLAG_FORCE_ARRAY && !jsValue->IsFunction()) || jsValue->IsArray()) {
array_init(return_value);
return v8js_get_properties_hash(jsValue, Z_ARRVAL_P(return_value), flags, isolate TSRMLS_CC);
} else {

View File

@ -2,12 +2,13 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2013 The PHP Group |
| Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
| Author: Jani Taskinen <jani.taskinen@iki.fi> |
| Author: Patrick Reilly <preilly@php.net> |
| Author: Stefan Siegl <stesie@php.net> |
+----------------------------------------------------------------------+
*/
@ -38,7 +39,7 @@ zend_class_entry *php_ce_v8js_memory_limit_exception;
/* {{{ Class: V8JsScriptException */
void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
{
v8::String::Utf8Value exception(try_catch->Exception());
const char *exception_string = ToCString(exception);
@ -81,6 +82,22 @@ void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TS
const char* stacktrace_string = ToCString(stacktrace);
PHPV8_EXPROP(_string, JsTrace, stacktrace_string);
}
if(try_catch->Exception()->IsObject()) {
v8::Local<v8::Value> php_ref = try_catch->Exception()->ToObject()->GetHiddenValue(V8JS_SYM(PHPJS_OBJECT_KEY));
if(!php_ref.IsEmpty()) {
assert(php_ref->IsExternal());
zval *php_exception = reinterpret_cast<zval *>(v8::External::Cast(*php_ref)->Value());
zend_class_entry *exception_ce = zend_exception_get_default(TSRMLS_C);
if (Z_TYPE_P(php_exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(php_exception), exception_ce TSRMLS_CC)) {
Z_ADDREF_P(php_exception);
zend_exception_set_previous(Z_OBJ_P(return_value), Z_OBJ_P(php_exception));
}
}
}
}
PHPV8_EXPROP(_string, message, message_string);
@ -89,7 +106,7 @@ void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TS
}
/* }}} */
void v8js_throw_script_exception(v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
{
v8::String::Utf8Value exception(try_catch->Exception());
const char *exception_string = ToCString(exception);
@ -98,7 +115,7 @@ void v8js_throw_script_exception(v8::TryCatch *try_catch TSRMLS_DC) /* {{{ */
if (try_catch->Message().IsEmpty()) {
zend_throw_exception(php_ce_v8js_script_exception, (char *) exception_string, 0 TSRMLS_CC);
} else {
v8js_create_script_exception(&zexception, try_catch TSRMLS_CC);
v8js_create_script_exception(&zexception, isolate, try_catch TSRMLS_CC);
zend_throw_exception_object(&zexception TSRMLS_CC);
}
}

View File

@ -2,12 +2,13 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2013 The PHP Group |
| Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
| Author: Jani Taskinen <jani.taskinen@iki.fi> |
| Author: Patrick Reilly <preilly@php.net> |
| Author: Stefan Siegl <stesie@php.net> |
+----------------------------------------------------------------------+
*/
@ -19,8 +20,8 @@ extern zend_class_entry *php_ce_v8js_script_exception;
extern zend_class_entry *php_ce_v8js_time_limit_exception;
extern zend_class_entry *php_ce_v8js_memory_limit_exception;
void v8js_create_script_exception(zval *return_value, v8::TryCatch *try_catch TSRMLS_DC);
void v8js_throw_script_exception(v8::TryCatch *try_catch TSRMLS_DC);
void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC);
void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch TSRMLS_DC);
PHP_MINIT_FUNCTION(v8js_exceptions);

View File

@ -26,20 +26,7 @@ extern "C" {
V8JS_METHOD(exit) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
/* Unfortunately just calling TerminateExecution on the isolate is not
* enough, since v8 just marks the thread as "to be aborted" and doesn't
* immediately do so. Hence we enter an endless loop after signalling
* termination, so we definitely don't execute JS code after the exit()
* statement. */
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::String> source = V8JS_STR("for(;;);");
v8::Local<v8::Script> script = v8::Script::Compile(source);
v8::V8::TerminateExecution(isolate);
script->Run();
v8js_terminate_execution(isolate);
}
/* }}} */

View File

@ -21,6 +21,7 @@ extern "C" {
#include "ext/standard/php_string.h"
#include "zend_interfaces.h"
#include "zend_closures.h"
#include "zend_exceptions.h"
}
#include "php_v8js_macros.h"
@ -33,13 +34,13 @@ static void v8js_weak_object_callback(const v8::WeakCallbackData<v8::Object, zen
/* Callback for PHP methods and functions */
static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v8::Isolate *isolate, const v8::FunctionCallbackInfo<v8::Value>& info TSRMLS_DC) /* {{{ */
{
v8::Handle<v8::Value> return_value;
v8::Handle<v8::Value> return_value = V8JS_NULL;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zval fname, retval, **argv = NULL;
unsigned int argc = info.Length(), min_num_args = 0, max_num_args = 0;
char *error;
int error_len, i, flags = V8JS_FLAG_NONE;
int error_len, i;
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
@ -84,7 +85,6 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v
/* Convert parameters passed from V8 */
if (argc) {
flags = V8JS_GLOBAL_GET_FLAGS(isolate);
fci.params = (zval *) safe_emalloc(argc, sizeof(zval), 0);
for (i = 0; i < argc; i++) {
v8::Local<v8::Value> php_object;
@ -97,7 +97,7 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v
ZVAL_OBJ(&fci.params[i], object);
Z_ADDREF_P(&fci.params[i]);
} else {
if (v8js_to_zval(info[i], &fci.params[i], flags, isolate TSRMLS_CC) == FAILURE) {
if (v8js_to_zval(info[i], &fci.params[i], ctx->flags, isolate TSRMLS_CC) == FAILURE) {
error_len = spprintf(&error, 0, "converting parameter #%d passed to %s() failed", i + 1, method_ptr->common.function_name);
return_value = V8JS_THROW(isolate, Error, error, error_len);
efree(error);
@ -132,7 +132,7 @@ static void v8js_call_php_func(zend_object *object, zend_function *method_ptr, v
isolate->Enter();
}
zend_catch {
v8::V8::TerminateExecution(isolate);
v8js_terminate_execution(isolate);
V8JSG(fatal_error_abort) = 1;
}
zend_end_try();
@ -146,7 +146,19 @@ failure:
efree(fci.params);
}
if(EG(exception) && !V8JSG(compat_php_exceptions)) {
if(ctx->flags & V8JS_FLAG_PROPAGATE_PHP_EXCEPTIONS) {
zval tmp_zv;
ZVAL_OBJ(&tmp_zv, EG(exception));
return_value = isolate->ThrowException(zval_to_v8js(&tmp_zv, isolate TSRMLS_CC));
zend_clear_exception(TSRMLS_C);
} else {
v8js_terminate_execution(isolate);
}
} else {
return_value = zval_to_v8js(&retval, isolate TSRMLS_CC);
}
zval_dtor(&retval);
zval_dtor(&fname);
@ -505,6 +517,7 @@ template<typename T>
v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<T> &info, property_op_t callback_type, v8::Local<v8::Value> set_value) /* {{{ */
{
v8::Isolate *isolate = info.GetIsolate();
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
v8::String::Utf8Value cstr(property);
const char *name = ToCString(cstr);
uint name_len = property->Utf8Length();
@ -524,9 +537,8 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
zval zobject;
ZVAL_OBJ(&zobject, object);
v8::Local<v8::FunctionTemplate> tmpl =
v8::Local<v8::FunctionTemplate>::New
(isolate, *reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0)));
v8js_tmpl_t *tmpl_ptr = reinterpret_cast<v8js_tmpl_t *>(self->GetAlignedPointerFromInternalField(0));
v8::Local<v8::FunctionTemplate> tmpl = v8::Local<v8::FunctionTemplate>::New(isolate, *tmpl_ptr);
ce = scope = object->ce;
/* First, check the (case-insensitive) method table */
@ -560,14 +572,35 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
// Fake __call implementation
// (only use this if method_ptr==NULL, which means
// there is no actual PHP __call() implementation)
v8::Local<v8::Function> cb =
v8::FunctionTemplate::New(isolate,
v8::Local<v8::FunctionTemplate> ft;
try {
ft = v8::Local<v8::FunctionTemplate>::New
(isolate, ctx->call_impls.at(tmpl_ptr));
}
catch (const std::out_of_range &) {
ft = v8::FunctionTemplate::New(isolate,
v8js_fake_call_impl, V8JS_NULL,
v8::Signature::New(isolate, tmpl))->GetFunction();
v8::Signature::New(isolate, tmpl));
v8js_tmpl_t *persistent_ft = &ctx->call_impls[tmpl_ptr];
persistent_ft->Reset(isolate, ft);
}
v8::Local<v8::Function> cb = ft->GetFunction();
cb->SetName(property);
ret_value = cb;
} else {
ret_value = PHP_V8JS_CALLBACK(isolate, method_ptr, tmpl);
v8::Local<v8::FunctionTemplate> ft;
try {
ft = v8::Local<v8::FunctionTemplate>::New
(isolate, ctx->method_tmpls.at(method_ptr));
}
catch (const std::out_of_range &) {
ft = v8::FunctionTemplate::New(isolate, v8js_php_callback,
v8::External::New((isolate), method_ptr),
v8::Signature::New((isolate), tmpl));
v8js_tmpl_t *persistent_ft = &ctx->method_tmpls[method_ptr];
persistent_ft->Reset(isolate, ft);
}
ret_value = ft->GetFunction();
}
}
} else if (callback_type == V8JS_PROP_QUERY) {
@ -623,9 +656,7 @@ v8::Local<v8::Value> v8js_named_property_callback(v8::Local<v8::String> property
}
} else if (callback_type == V8JS_PROP_SETTER) {
int flags = V8JS_GLOBAL_GET_FLAGS(isolate);
if (v8js_to_zval(set_value, &php_value, flags, isolate TSRMLS_CC) != SUCCESS) {
if (v8js_to_zval(set_value, &php_value, ctx->flags, isolate TSRMLS_CC) != SUCCESS) {
ret_value = v8::Handle<v8::Value>();
}
else {
@ -833,13 +864,23 @@ static v8::Handle<v8::Object> v8js_wrap_array_to_object(v8::Isolate *isolate, zv
zend_string *key;
ulong index;
// @todo re-use template likewise
v8::Local<v8::FunctionTemplate> new_tpl = v8::FunctionTemplate::New(isolate, 0);
v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0);
v8::Local<v8::FunctionTemplate> new_tpl;
if(ctx->array_tmpl.IsEmpty()) {
new_tpl = v8::FunctionTemplate::New(isolate, 0);
/* Call it Array, but it is not a native array, especially it doesn't have
* have the typical Array.prototype functions. */
new_tpl->SetClassName(V8JS_SYM("Array"));
/* Store for later re-use */
ctx->array_tmpl.Reset(isolate, new_tpl);
}
else {
new_tpl = v8::Local<v8::FunctionTemplate>::New(isolate, ctx->array_tmpl);
}
v8::Handle<v8::Object> newobj = new_tpl->InstanceTemplate()->NewInstance();
HashTable *myht = HASH_OF(value);

View File

@ -54,7 +54,7 @@ static void v8js_timer_interrupt_handler(v8::Isolate *isolate, void *data) { /*
if (timer_ctx->memory_limit > 0 && hs.used_heap_size() > timer_ctx->memory_limit) {
timer_ctx->killed = true;
v8js_terminate_execution(c TSRMLS_CC);
v8::V8::TerminateExecution(c->isolate);
c->memory_limit_hit = true;
}
}
@ -79,7 +79,7 @@ void v8js_timer_thread(zend_v8js_globals *globals) /* {{{ */
}
else if(timer_ctx->time_limit > 0 && now > timer_ctx->time_point) {
timer_ctx->killed = true;
v8js_terminate_execution(c TSRMLS_CC);
v8::V8::TerminateExecution(c->isolate);
c->time_limit_hit = true;
}
else if (timer_ctx->memory_limit > 0) {

View File

@ -2,12 +2,13 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2013 The PHP Group |
| Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
| Author: Jani Taskinen <jani.taskinen@iki.fi> |
| Author: Patrick Reilly <preilly@php.net> |
| Author: Stefan Siegl <stesie@php.net> |
+----------------------------------------------------------------------+
*/
@ -36,26 +37,42 @@ extern "C" {
void v8js_v8_init(TSRMLS_D) /* {{{ */
{
/* Run only once */
/* Run only once; thread-local test first */
if (V8JSG(v8_initialized)) {
return;
}
/* Set thread-local flag, that V8 was initialized. */
V8JSG(v8_initialized) = 1;
#ifdef ZTS
v8js_process_globals.lock.lock();
if(v8js_process_globals.v8_initialized) {
/* V8 already has been initialized by another thread */
v8js_process_globals.lock.unlock();
return;
}
#endif
#if !defined(_WIN32) && PHP_V8_API_VERSION >= 3029036
V8JSG(v8_platform) = v8::platform::CreateDefaultPlatform();
v8::V8::InitializePlatform(V8JSG(v8_platform));
v8js_process_globals.v8_platform = v8::platform::CreateDefaultPlatform();
v8::V8::InitializePlatform(v8js_process_globals.v8_platform);
#endif
/* Set V8 command line flags (must be done before V8::Initialize()!) */
if (V8JSG(v8_flags)) {
v8::V8::SetFlagsFromString(V8JSG(v8_flags), strlen(V8JSG(v8_flags)));
if (v8js_process_globals.v8_flags) {
v8::V8::SetFlagsFromString(v8js_process_globals.v8_flags,
strlen(v8js_process_globals.v8_flags));
}
/* Initialize V8 */
v8::V8::Initialize();
/* Run only once */
V8JSG(v8_initialized) = 1;
#ifdef ZTS
v8js_process_globals.v8_initialized = 1;
v8js_process_globals.lock.unlock();
#endif
}
/* }}} */
@ -77,7 +94,7 @@ void v8js_v8_call(v8js_ctx *c, zval **return_value,
v8::TryCatch try_catch;
/* Set flags for runtime use */
V8JS_GLOBAL_SET_FLAGS(isolate, flags);
c->flags = flags;
/* Check if timezone has been changed and notify V8 */
tz = getenv("TZ");
@ -176,13 +193,13 @@ void v8js_v8_call(v8js_ctx *c, zval **return_value,
/* Report immediately if report_uncaught is true */
if (c->report_uncaught) {
v8js_throw_script_exception(&try_catch TSRMLS_CC);
v8js_throw_script_exception(c->isolate, &try_catch TSRMLS_CC);
return;
}
/* Exception thrown from JS, preserve it for future execution */
if (result.IsEmpty()) {
v8js_create_script_exception(&c->pending_exception, &try_catch TSRMLS_CC);
v8js_create_script_exception(&c->pending_exception, c->isolate, &try_catch TSRMLS_CC);
return;
}
}
@ -199,10 +216,28 @@ void v8js_v8_call(v8js_ctx *c, zval **return_value,
}
/* }}} */
void v8js_terminate_execution(v8js_ctx *c TSRMLS_DC) /* {{{ */
void v8js_terminate_execution(v8::Isolate *isolate) /* {{{ */
{
// Forcefully terminate the current thread of V8 execution in the isolate
v8::V8::TerminateExecution(c->isolate);
if(v8::V8::IsExecutionTerminating(isolate)) {
/* Execution already terminating, needn't trigger it again and
* especially must not execute the spinning loop (which would cause
* crashes in V8 itself, at least with 4.2 and 4.3 version lines). */
return;
}
/* Unfortunately just calling TerminateExecution on the isolate is not
* enough, since v8 just marks the thread as "to be aborted" and doesn't
* immediately do so. Hence we enter an endless loop after signalling
* termination, so we definitely don't execute JS code after the exit()
* statement. */
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::String> source = V8JS_STR("for(;;);");
v8::Local<v8::Script> script = v8::Script::Compile(source);
v8::V8::TerminateExecution(isolate);
script->Run();
}
/* }}} */

View File

@ -49,15 +49,15 @@ void v8js_v8_init(TSRMLS_D);
void v8js_v8_call(v8js_ctx *c, zval **return_value,
long flags, long time_limit, long memory_limit,
std::function< v8::Local<v8::Value>(v8::Isolate *) >& v8_call TSRMLS_DC);
void v8js_terminate_execution(v8js_ctx *c TSRMLS_DC);
void v8js_terminate_execution(v8::Isolate *isolate);
/* Fetch V8 object properties */
int v8js_get_properties_hash(v8::Handle<v8::Value> jsValue, HashTable *retval, int flags, v8::Isolate *isolate TSRMLS_DC);
#define V8JS_CTX_PROLOGUE(ctx) \
#define V8JS_CTX_PROLOGUE_EX(ctx, ret) \
if (!V8JSG(v8_initialized)) { \
zend_error(E_ERROR, "V8 not initialized"); \
return; \
return ret; \
} \
\
v8::Isolate *isolate = (ctx)->isolate; \
@ -67,6 +67,9 @@ int v8js_get_properties_hash(v8::Handle<v8::Value> jsValue, HashTable *retval, i
v8::Local<v8::Context> v8_context = v8::Local<v8::Context>::New(isolate, (ctx)->context); \
v8::Context::Scope context_scope(v8_context);
#define V8JS_CTX_PROLOGUE(ctx) \
V8JS_CTX_PROLOGUE_EX(ctx,)
#define V8JS_BEGIN_CTX(ctx, object) \
v8js_ctx *(ctx); \
(ctx) = Z_V8JS_CTX_OBJ_P(object); \

View File

@ -60,13 +60,7 @@ static int v8js_v8object_has_property(zval *object, zval *member, int has_set_ex
return retval;
}
v8::Isolate *isolate = obj->ctx->isolate;
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope local_scope(isolate);
v8::Local<v8::Context> temp_context = v8::Context::New(isolate);
v8::Context::Scope temp_scope(temp_context);
V8JS_CTX_PROLOGUE_EX(obj->ctx, retval);
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj);
if (Z_TYPE_P(member) == IS_STRING && v8obj->IsObject() && !v8obj->IsFunction())
@ -125,13 +119,7 @@ static zval *v8js_v8object_read_property(zval *object, zval *member, int type, v
return retval;
}
v8::Isolate *isolate = obj->ctx->isolate;
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope local_scope(isolate);
v8::Local<v8::Context> temp_context = v8::Context::New(isolate);
v8::Context::Scope temp_scope(temp_context);
V8JS_CTX_PROLOGUE_EX(obj->ctx, retval);
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj);
if (Z_TYPE_P(member) == IS_STRING && v8obj->IsObject() && !v8obj->IsFunction())
@ -165,13 +153,7 @@ static void v8js_v8object_write_property(zval *object, zval *member, zval *value
return;
}
v8::Isolate *isolate = obj->ctx->isolate;
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope local_scope(isolate);
v8::Local<v8::Context> temp_context = v8::Context::New(isolate);
v8::Context::Scope temp_scope(temp_context);
V8JS_CTX_PROLOGUE(obj->ctx);
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj);
if (v8obj->IsObject() && !v8obj->IsFunction()) {
@ -190,13 +172,7 @@ static void v8js_v8object_unset_property(zval *object, zval *member, void **cach
return;
}
v8::Isolate *isolate = obj->ctx->isolate;
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope local_scope(isolate);
v8::Local<v8::Context> temp_context = v8::Context::New(isolate);
v8::Context::Scope temp_scope(temp_context);
V8JS_CTX_PROLOGUE(obj->ctx);
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj);
if (v8obj->IsObject() && !v8obj->IsFunction()) {
@ -235,12 +211,7 @@ static HashTable *v8js_v8object_get_properties(zval *object TSRMLS_DC) /* {{{ */
return NULL;
}
v8::Isolate *isolate = obj->ctx->isolate;
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope local_scope(isolate);
v8::Local<v8::Context> temp_context = v8::Context::New(isolate);
v8::Context::Scope temp_scope(temp_context);
V8JS_CTX_PROLOGUE_EX(obj->ctx, NULL);
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj);
if (v8js_get_properties_hash(v8obj, obj->properties, obj->flags, isolate TSRMLS_CC) == SUCCESS) {
@ -269,12 +240,7 @@ static zend_function *v8js_v8object_get_method(zend_object **object_ptr, zend_st
return NULL;
}
v8::Isolate *isolate = obj->ctx->isolate;
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope local_scope(isolate);
v8::Local<v8::Context> temp_context = v8::Context::New(isolate);
v8::Context::Scope temp_scope(temp_context);
V8JS_CTX_PROLOGUE_EX(obj->ctx, NULL);
v8::Local<v8::String> jsKey = V8JS_ZSTR(method);
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj);
@ -360,12 +326,7 @@ static int v8js_v8object_get_closure(zval *object, zend_class_entry **ce_ptr, ze
return FAILURE;
}
v8::Isolate *isolate = obj->ctx->isolate;
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope local_scope(isolate);
v8::Local<v8::Context> temp_context = v8::Context::New(isolate);
v8::Context::Scope temp_scope(temp_context);
V8JS_CTX_PROLOGUE_EX(obj->ctx, FAILURE);
v8::Local<v8::Value> v8obj = v8::Local<v8::Value>::New(isolate, obj->v8obj);
if (!v8obj->IsFunction()) {