├── .dockerignore ├── .github └── workflows │ └── build-test.yml ├── .gitignore ├── CREDITS ├── LICENSE ├── Makefile.frag ├── README.Linux.md ├── README.MacOS.md ├── README.Win32.md ├── README.md ├── config.m4 ├── config.w32 ├── package.xml ├── php_v8js.h ├── php_v8js_macros.h ├── tests ├── array_access.phpt ├── array_access_001.phpt ├── array_access_002.phpt ├── array_access_003.phpt ├── array_access_004.phpt ├── array_access_005.phpt ├── array_access_006.phpt ├── array_access_007.phpt ├── array_access_008.phpt ├── array_access_basic2.phpt ├── array_pass.phpt ├── array_pass_flags.phpt ├── array_recursive.phpt ├── basic.phpt ├── callbacks.phpt ├── checkstring_compile.phpt ├── closures_basic.phpt ├── closures_dynamic.phpt ├── commonjs_caching_001.phpt ├── commonjs_caching_002.phpt ├── commonjs_cust_normalise_001.phpt ├── commonjs_cust_normalise_002.phpt ├── commonjs_cust_normalise_003.phpt ├── commonjs_cust_normalise_004.phpt ├── commonjs_exception_001.phpt ├── commonjs_exception_002.phpt ├── commonjs_fatal_error.phpt ├── commonjs_modules.phpt ├── commonjs_multiassign.phpt ├── commonjs_native_basic.phpt ├── commonjs_node_compat_001.phpt ├── commonjs_node_compat_002.phpt ├── commonjs_node_compat_003.phpt ├── commonjs_node_compat_basic.phpt ├── commonjs_normalise_001.phpt ├── commonjs_normalise_002.phpt ├── commonjs_normalise_003.phpt ├── commonjs_normalise_004.phpt ├── commonjs_normalise_005.phpt ├── commonjs_source_naming.phpt ├── compile_string.phpt ├── compile_string_isolate.phpt ├── construct.phpt ├── context_preserving.phpt ├── context_separation.phpt ├── context_temp_creation.phpt ├── create_snapshot_basic.phpt ├── ctx_lifetime.phpt ├── datetime_pass.phpt ├── derived_class_properties.phpt ├── derived_class_properties_extra.phpt ├── derived_class_properties_init.phpt ├── derived_class_properties_protected.phpt ├── die.phpt ├── direct_construct.phpt ├── exception.phpt ├── exception_filter_001.phpt ├── exception_filter_002.phpt ├── exception_filter_003.phpt ├── exception_filter_004.phpt ├── exception_filter_005.phpt ├── exception_filter_006.phpt ├── exception_filter_basic.phpt ├── exception_start_column.phpt ├── execute_flags.phpt ├── execute_flags_args.phpt ├── execute_flags_property_writing.phpt ├── fatal_error_ignore_non_fatals.phpt ├── fatal_error_no_uninstall_inner_frame.phpt ├── fatal_error_recursive.phpt ├── fatal_error_rethrow.phpt ├── fatal_error_uninstall_in_first_frame.phpt ├── fatal_error_v8function.phpt ├── function_call.phpt ├── function_passback.phpt ├── function_passback2.phpt ├── function_properties.phpt ├── generators_from_v8_001.phpt ├── generators_from_v8_002.phpt ├── generators_from_v8_003.phpt ├── generators_from_v8_004.phpt ├── generators_from_v8_005.phpt ├── generators_from_v8_006.phpt ├── generators_from_v8_007.phpt ├── generators_from_v8_008.phpt ├── generators_from_v8_009.phpt ├── generators_from_v8_010.phpt ├── generators_from_v8_basic.phpt ├── generators_to_v8_001.phpt ├── generators_to_v8_002.phpt ├── generators_to_v8_003.phpt ├── generators_to_v8_004.phpt ├── generators_to_v8_basic.phpt ├── get_accessor.phpt ├── get_constructor.phpt ├── global_object_basic.phpt ├── has_property_after_dispose.phpt ├── inheritance_basic.phpt ├── issue_116-v8function-injection.phpt ├── issue_127_001.phpt ├── issue_160_basic.phpt ├── issue_183_001.phpt ├── issue_183_002.phpt ├── issue_183_003.phpt ├── issue_183_004.phpt ├── issue_183_005.phpt ├── issue_183_006.phpt ├── issue_183_basic.phpt ├── issue_185_001.phpt ├── issue_185_002.phpt ├── issue_185_basic.phpt ├── issue_246_001.phpt ├── issue_250_001.phpt ├── issue_250_002.phpt ├── issue_306_basic.phpt ├── issue_316_basic.phpt ├── issue_349_basic.phpt ├── issue_410_basic.phpt ├── issue_472_basic.phpt ├── issue_497_001.phpt ├── issue_504_001.phpt ├── js-construct-basic.phpt ├── js-construct-direct-call.phpt ├── js-construct-protected-ctor.phpt ├── js-construct-with-ctor.phpt ├── leak-php-object.phpt ├── long.phpt ├── long_int64.phpt ├── memory_limit.phpt ├── multi-object.phpt ├── multi.phpt ├── null_byte_string.phpt ├── object.phpt ├── object_dom.phpt ├── object_method_call.phpt ├── object_passback.phpt ├── object_passback_002.phpt ├── object_prototype.phpt ├── object_reuse.phpt ├── php_exceptions_001.phpt ├── php_exceptions_002.phpt ├── php_exceptions_003.phpt ├── php_exceptions_004.phpt ├── php_exceptions_005.phpt ├── php_exceptions_006.phpt ├── php_exceptions_007.phpt ├── php_exceptions_basic.phpt ├── property_exists.phpt ├── property_visibility-delete.phpt ├── property_visibility-enumerate.phpt ├── property_visibility-has-property.phpt ├── property_visibility-set.phpt ├── property_visibility.phpt ├── property_visibility__get.phpt ├── property_visibility__set.phpt ├── pthreads_001.phpt ├── regression_121.phpt ├── return_this_001.phpt ├── return_this_basic.phpt ├── return_value.phpt ├── serialize_001.phpt ├── serialize_002.phpt ├── serialize_basic.phpt ├── set_average_object_size_basic.phpt ├── set_memory_limit_001.phpt ├── set_memory_limit_003.phpt ├── set_memory_limit_basic.phpt ├── set_time_limit_001.phpt ├── set_time_limit_002.phpt ├── set_time_limit_003.phpt ├── set_time_limit_004.phpt ├── set_time_limit_basic.phpt ├── skipif.inc ├── time_limit.phpt ├── timezones.phpt ├── tojson_001.phpt ├── unicode.phpt ├── use_after_dispose.phpt ├── v8_unset_property.phpt ├── v8_write_property.phpt ├── var_dump.phpt ├── var_dump_php83.phpt └── variable_passing.phpt ├── v8js_array_access.cc ├── v8js_array_access.h ├── v8js_class.cc ├── v8js_class.h ├── v8js_commonjs.cc ├── v8js_commonjs.h ├── v8js_convert.cc ├── v8js_exceptions.cc ├── v8js_exceptions.h ├── v8js_generator_export.cc ├── v8js_generator_export.h ├── v8js_main.cc ├── v8js_methods.cc ├── v8js_object_export.cc ├── v8js_object_export.h ├── v8js_timer.cc ├── v8js_timer.h ├── v8js_v8.cc ├── v8js_v8.h ├── v8js_v8object_class.cc ├── v8js_v8object_class.h └── v8js_variables.cc /.dockerignore: -------------------------------------------------------------------------------- 1 | *.lo 2 | *.o 3 | .deps 4 | .libs 5 | Dockerfile.tmp 6 | Makefile 7 | Makefile.fragments 8 | Makefile.global 9 | Makefile.objects 10 | acinclude.m4 11 | aclocal.m4 12 | autom4te.cache/* 13 | build/* 14 | config.guess 15 | config.h 16 | config.h.in 17 | *.log 18 | config.nice 19 | config.status 20 | config.sub 21 | configure 22 | configure.in 23 | configure.ac 24 | *~ 25 | install-sh 26 | libtool 27 | ltmain.sh 28 | missing 29 | mkinstalldirs 30 | modules/* 31 | v8js.la 32 | v8js-*.tgz 33 | run-tests.php 34 | .*.sw[poq] 35 | 36 | tests/*.diff 37 | tests/*.exp 38 | tests/*.out 39 | tests/*.php 40 | tests/*.sh 41 | tests/*.mem 42 | 43 | tmp-php.ini 44 | 45 | coverage_report/** 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.lo 2 | *.o 3 | *.dep 4 | .deps 5 | .libs 6 | Dockerfile.tmp 7 | Makefile 8 | Makefile.fragments 9 | Makefile.global 10 | Makefile.objects 11 | acinclude.m4 12 | aclocal.m4 13 | autom4te.cache/* 14 | build/* 15 | config.guess 16 | config.h 17 | config.h.in 18 | *.log 19 | config.nice 20 | config.status 21 | config.sub 22 | configure 23 | configure.in 24 | configure.ac 25 | *~ 26 | install-sh 27 | libtool 28 | ltmain.sh 29 | missing 30 | mkinstalldirs 31 | modules/* 32 | v8js.la 33 | v8js-*.tgz 34 | run-tests.php 35 | .*.sw[poq] 36 | 37 | tests/*.diff 38 | tests/*.exp 39 | tests/*.out 40 | tests/*.php 41 | tests/*.sh 42 | tests/*.mem 43 | 44 | tmp-php.ini 45 | 46 | coverage_report/** 47 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | v8js 2 | Jani Taskinen 3 | Patrick Reilly 4 | Simon Best 5 | C. Scott Ananian 6 | Stefan Siegl 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 The PHP Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile.frag: -------------------------------------------------------------------------------- 1 | # add json extension, if needed (ie, for PHP >= 5.5) 2 | ifneq (,$(realpath $(EXTENSION_DIR)/json.so)) 3 | PHP_TEST_SHARED_EXTENSIONS+=-d extension=$(EXTENSION_DIR)/json.so 4 | endif 5 | 6 | # add pthreads extension, if available 7 | ifneq (,$(realpath $(EXTENSION_DIR)/pthreads.so)) 8 | PHP_TEST_SHARED_EXTENSIONS+=-d extension=$(EXTENSION_DIR)/pthreads.so 9 | endif 10 | 11 | # add dom extension, if available 12 | ifneq (,$(realpath $(EXTENSION_DIR)/dom.so)) 13 | PHP_TEST_SHARED_EXTENSIONS+=-d extension=$(EXTENSION_DIR)/dom.so 14 | endif 15 | -------------------------------------------------------------------------------- /README.MacOS.md: -------------------------------------------------------------------------------- 1 | V8Js on MacOS 2 | ============= 3 | 4 | Installation of V8Js on MacOS is pretty much straight forward. 5 | The ARM-based M1 chips also work just fine. 6 | 7 | You can use [brew](https://brew.sh) to install `v8`. This provides 8 | both the library as well as necessary include files in `/opt/homebrew`. 9 | 10 | 11 | Compile php-v8js itself 12 | ----------------------- 13 | 14 | ``` 15 | cd /tmp 16 | git clone https://github.com/phpv8/v8js.git 17 | cd v8js 18 | phpize 19 | ./configure --with-v8js=/opt/homebrew CPPFLAGS="-DV8_COMPRESS_POINTERS" 20 | make -j4 21 | make test 22 | make install 23 | ``` 24 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | 2 | ARG_WITH("v8js", "for V8 Javascript Engine", "no"); 3 | 4 | function v8js_zeroPad(num, places) { 5 | var zero = places - num.toString().length + 1; 6 | return Array(+(zero > 0 && zero)).join("0") + num; 7 | } 8 | 9 | if (PHP_V8JS != "no") { 10 | if (CHECK_LIB("winmm.lib", "v8js") && 11 | CHECK_HEADER_ADD_INCLUDE("v8.h", "CFLAGS_V8JS")) { 12 | 13 | ADD_FLAG("CFLAGS_V8JS", "/EHcs"); 14 | ADD_FLAG("CFLAGS_V8JS", "/D _ALLOW_KEYWORD_MACROS"); 15 | ADD_FLAG("CFLAGS_V8JS", "/D __STDC_LIMIT_MACROS"); 16 | 17 | // defaults 18 | var v8major = 7; 19 | var v8minor = 0; 20 | var v8build = 276; 21 | var v8patch = 11; 22 | var v8pinc = search_paths("v8-version.h", php_usual_include_suspects, null); 23 | if (typeof(v8pinc) == "string") { 24 | var v8versionh = file_get_contents(v8pinc + '\\v8-version.h'); 25 | if (v8versionh.match(/#define V8_MAJOR_VERSION ([0-9]*)/i)) { 26 | v8major = RegExp.$1; 27 | } 28 | if (v8versionh.match(/#define V8_MINOR_VERSION ([0-9]*)/i)) { 29 | v8minor = RegExp.$1; 30 | } 31 | if (v8versionh.match(/#define V8_BUILD_NUMBER ([0-9]*)/i)) { 32 | v8build = RegExp.$1; 33 | } 34 | if (v8versionh.match(/#define V8_PATCH_LEVEL ([0-9]*)/i)) { 35 | v8patch = RegExp.$1; 36 | } 37 | } else { 38 | WARNING("Could not parse v8-version.h"); 39 | } 40 | 41 | var v8api = v8major + v8js_zeroPad(v8minor, 3) + v8js_zeroPad(v8build, 3); 42 | var v8ver = v8major + "." + v8minor + "." + v8build + "." + v8patch; 43 | 44 | if (v8api >= 5005000) { 45 | CHECK_LIB("v8.dll.lib", "v8js"); 46 | CHECK_LIB("v8_libplatform.dll.lib", "v8js"); 47 | CHECK_LIB("v8_libbase.dll.lib", "v8js"); 48 | ADD_FLAG("CFLAGS_V8JS", "/D BUILDING_V8_PLATFORM_SHARED"); 49 | // #define _STRING_ to disable #include in v8-platform.h and avoid 50 | // C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\string(671): 51 | // error C2143: syntax error: missing ';' before 'namespace' 52 | // (compiling source file ext\v8js\v8js_v8.cc) 53 | ADD_FLAG("CFLAGS_V8JS", "/D _STRING_"); 54 | } else if (v8api >= 5002000) { 55 | CHECK_LIB("v8.dll.lib", "v8js"); 56 | // created by 'cd obj\v8_libplatform && lib /out:v8_libplatform.lib *.obj' 57 | CHECK_LIB("v8_libplatform.lib", "v8js"); 58 | // created by 'cd obj\v8_libbase && lib /out:v8_libbase.lib *.obj' 59 | CHECK_LIB("v8_libbase.lib", "v8js"); 60 | } else { 61 | CHECK_LIB("v8.lib", "v8js"); 62 | CHECK_LIB("v8_libplatform.lib", "v8js"); 63 | CHECK_LIB("v8_libbase.lib", "v8js"); 64 | } 65 | if (v8api >= 5003000) { 66 | // For SymLoadModule64 e.a. 67 | // #include in src\base\win32-headers.h 68 | // Adds dependency on dbghelp.dll 69 | CHECK_LIB("dbghelp.lib", "v8js"); 70 | } 71 | if (v8api >= 5004000) { 72 | // For PathRemoveFileSpecW in v8_libbase.lib(stack_trace_win) 73 | CHECK_LIB("Shlwapi.lib", "v8js"); 74 | } 75 | 76 | AC_DEFINE("PHP_V8_API_VERSION", v8api, "", false); 77 | AC_DEFINE("PHP_V8_VERSION", v8ver, "", true); 78 | 79 | // AC_DEFINE("PHP_V8_EXEC_PATH", "C:\\php\\bin\\v8.dll", "", true); 80 | 81 | EXTENSION("v8js", "v8js_array_access.cc v8js_class.cc v8js_commonjs.cc v8js_convert.cc v8js_exceptions.cc v8js_generator_export.cc v8js_main.cc v8js_methods.cc v8js_object_export.cc v8js_timer.cc v8js_v8.cc v8js_v8object_class.cc v8js_variables.cc", "yes"); 82 | ADD_FLAG("CFLAGS_BD_EXT_V8JS", "/D ZEND_WIN32_KEEP_INLINE=1 /U ZEND_WIN32_FORCE_INLINE"); 83 | 84 | } else { 85 | WARNING("v8js not enabled, headers or libs not found"); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /php_v8js.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2013 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Jani Taskinen | 10 | | Author: Patrick Reilly | 11 | +----------------------------------------------------------------------+ 12 | */ 13 | 14 | #ifndef PHP_V8JS_H 15 | #define PHP_V8JS_H 16 | 17 | extern zend_module_entry v8js_module_entry; 18 | #define phpext_v8js_ptr &v8js_module_entry 19 | 20 | #endif /* PHP_V8JS_H */ 21 | 22 | /* 23 | * Local variables: 24 | * tab-width: 4 25 | * c-basic-offset: 4 26 | * indent-tabs-mode: t 27 | * End: 28 | * vim600: noet sw=4 ts=4 fdm=marker 29 | * vim<600: noet sw=4 ts=4 30 | */ 31 | -------------------------------------------------------------------------------- /tests/array_access.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check ArrayAccess interface wrapping 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | = 0 && $offset <= 20; 13 | } 14 | 15 | public function offsetGet(mixed $offset): mixed { 16 | return 19 - $offset; 17 | } 18 | 19 | public function offsetSet(mixed $offset, mixed $value): void { 20 | throw new Exception('Not implemented'); 21 | } 22 | 23 | public function offsetUnset(mixed $offset): void { 24 | throw new Exception('Not implemented'); 25 | } 26 | 27 | public function count(): int { 28 | return 20; 29 | } 30 | } 31 | 32 | $myarr = new MyArray(); 33 | var_dump(count($myarr)); 34 | var_dump($myarr[5]); 35 | 36 | $js = <<myarr = $myarr; 47 | $v8->executeString($js); 48 | 49 | ?> 50 | ===EOF=== 51 | --EXPECT-- 52 | int(20) 53 | int(14) 54 | string(5) "Array" 55 | int(20) 56 | int(14) 57 | string(68) "19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0" 58 | string(18) "14, 13, 12, 11, 10" 59 | ===EOF=== 60 | -------------------------------------------------------------------------------- /tests/array_access_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check ArrayAccess live binding 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 15 | } 16 | 17 | public function offsetGet(mixed $offset): mixed { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet(mixed $offset, mixed $value): void { 22 | $this->data[$offset] = $value; 23 | } 24 | 25 | public function offsetUnset(mixed $offset): void { 26 | throw new Exception('Not implemented'); 27 | } 28 | 29 | public function count(): int { 30 | return count($this->data); 31 | } 32 | 33 | public function push($value) { 34 | $this->data[] = $value; 35 | } 36 | } 37 | 38 | $v8 = new V8Js(); 39 | $v8->myarr = new MyArray(); 40 | 41 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 42 | 43 | /* array is "live bound", i.e. new elements just pop up on js side. */ 44 | $v8->myarr->push('new'); 45 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 46 | 47 | ?> 48 | ===EOF=== 49 | --EXPECT-- 50 | string(13) "one,two,three" 51 | string(17) "one,two,three,new" 52 | ===EOF=== 53 | -------------------------------------------------------------------------------- /tests/array_access_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Use ArrayAccess with JavaScript native push method 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 19 | } 20 | 21 | public function offsetGet(mixed $offset): mixed { 22 | return $this->data[$offset]; 23 | } 24 | 25 | public function offsetSet(mixed $offset, mixed $value): void { 26 | if ($this->setterCalled) { 27 | return; 28 | } 29 | 30 | echo "set[$offset] = $value\n"; 31 | $this->data[$offset] = $value; 32 | $this->setterCalled = true; 33 | } 34 | 35 | public function offsetUnset(mixed $offset): void { 36 | throw new Exception('Not implemented'); 37 | } 38 | 39 | public function count(): int { 40 | return count($this->data); 41 | } 42 | } 43 | 44 | $v8 = new V8Js(); 45 | $v8->myarr = new MyArray(); 46 | 47 | /* Call native JavaScript push method, this should cause a count 48 | * offsetSet call. */ 49 | $v8->executeString('PHP.myarr.push(23);'); 50 | 51 | /* Access array from PHP side, should work if JavaScript called 52 | * the write accessor functions. */ 53 | var_dump(count($v8->myarr)); 54 | var_dump($v8->myarr[3]); 55 | 56 | /* And JS side of course should see it too. */ 57 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 58 | 59 | ?> 60 | ===EOF=== 61 | --EXPECT-- 62 | set[3] = 23 63 | int(4) 64 | int(23) 65 | string(16) "one,two,three,23" 66 | ===EOF=== 67 | -------------------------------------------------------------------------------- /tests/array_access_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Export PHP methods on ArrayAccess objects 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 14 | } 15 | 16 | public function offsetGet(mixed $offset): mixed { 17 | return $this->data[$offset]; 18 | } 19 | 20 | public function offsetSet(mixed $offset, mixed $value): void { 21 | echo "set[$offset] = $value\n"; 22 | $this->data[$offset] = $value; 23 | } 24 | 25 | public function offsetUnset(mixed $offset): void { 26 | throw new Exception('Not implemented'); 27 | } 28 | 29 | public function count(): int { 30 | echo 'count() = ', count($this->data), "\n"; 31 | return count($this->data); 32 | } 33 | 34 | public function phpSidePush($value) { 35 | echo "push << $value\n"; 36 | $this->data[] = $value; 37 | } 38 | 39 | public function push($value) { 40 | echo "php-side-push << $value\n"; 41 | $this->data[] = $value; 42 | } 43 | } 44 | 45 | $v8 = new V8Js(); 46 | $v8->myarr = new MyArray(); 47 | 48 | /* Call PHP method to modify the array. */ 49 | $v8->executeString('PHP.myarr.phpSidePush(23);'); 50 | 51 | var_dump(count($v8->myarr)); 52 | var_dump($v8->myarr[3]); 53 | 54 | /* And JS should see the changes due to live binding. */ 55 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 56 | 57 | 58 | /* Call `push' method, this should trigger the PHP method. */ 59 | $v8->executeString('PHP.myarr.push(42);'); 60 | 61 | var_dump(count($v8->myarr)); 62 | var_dump($v8->myarr[4]); 63 | 64 | /* And JS should see the changes due to live binding. */ 65 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 66 | 67 | ?> 68 | ===EOF=== 69 | --EXPECT-- 70 | push << 23 71 | count() = 4 72 | int(4) 73 | int(23) 74 | count() = 4 75 | string(16) "one,two,three,23" 76 | php-side-push << 42 77 | count() = 5 78 | int(5) 79 | int(42) 80 | count() = 5 81 | string(19) "one,two,three,23,42" 82 | ===EOF=== 83 | -------------------------------------------------------------------------------- /tests/array_access_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Export PHP properties on ArrayAccess objects 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 23 | } 24 | 25 | public function offsetGet(mixed $offset): mixed { 26 | return $this->data[$offset]; 27 | } 28 | 29 | public function offsetSet(mixed $offset, mixed $value): void { 30 | echo "set[$offset] = $value\n"; 31 | $this->data[$offset] = $value; 32 | } 33 | 34 | public function offsetUnset(mixed $offset): void { 35 | throw new Exception('Not implemented'); 36 | } 37 | 38 | public function count(): int { 39 | return count($this->data); 40 | } 41 | } 42 | 43 | $v8 = new V8Js(); 44 | $v8->myarr = new MyArray(); 45 | 46 | $v8->executeString('var_dump(PHP.myarr.privFoo);'); 47 | $v8->executeString('var_dump(PHP.myarr.protFoo);'); 48 | $v8->executeString('var_dump(PHP.myarr.pubFoo);'); 49 | 50 | /* This should call count(), i.e. return 3 */ 51 | $v8->executeString('var_dump(PHP.myarr.length);'); 52 | 53 | /* This should print the value of the $length property */ 54 | $v8->executeString('var_dump(PHP.myarr.$length);'); 55 | 56 | ?> 57 | ===EOF=== 58 | --EXPECT-- 59 | NULL 60 | NULL 61 | int(42) 62 | int(3) 63 | int(42) 64 | ===EOF=== 65 | -------------------------------------------------------------------------------- /tests/array_access_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Export __invoke method on ArrayAccess objects 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 14 | } 15 | 16 | public function offsetGet(mixed $offset): mixed { 17 | return $this->data[$offset]; 18 | } 19 | 20 | public function offsetSet(mixed $offset, mixed $value): void { 21 | echo "set[$offset] = $value\n"; 22 | $this->data[$offset] = $value; 23 | } 24 | 25 | public function offsetUnset(mixed $offset): void { 26 | throw new Exception('Not implemented'); 27 | } 28 | 29 | public function count(): int { 30 | return count($this->data); 31 | } 32 | 33 | public function __invoke() { 34 | echo "__invoke called!\n"; 35 | } 36 | } 37 | 38 | $v8 = new V8Js(); 39 | $v8->myarr = new MyArray(); 40 | 41 | $v8->executeString('PHP.myarr();'); 42 | 43 | $v8->executeString('var_dump(PHP.myarr.length);'); 44 | $v8->executeString('var_dump(PHP.myarr.join(", "));'); 45 | 46 | ?> 47 | ===EOF=== 48 | --EXPECT-- 49 | __invoke called! 50 | int(3) 51 | string(15) "one, two, three" 52 | ===EOF=== 53 | -------------------------------------------------------------------------------- /tests/array_access_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Enumerate ArrayAccess keys 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 14 | } 15 | 16 | public function offsetGet(mixed $offset): mixed { 17 | return $this->data[$offset]; 18 | } 19 | 20 | public function offsetSet(mixed $offset, mixed $value): void { 21 | echo "set[$offset] = $value\n"; 22 | $this->data[$offset] = $value; 23 | } 24 | 25 | public function offsetUnset(mixed $offset): void { 26 | throw new Exception('Not implemented'); 27 | } 28 | 29 | public function count(): int { 30 | return count($this->data); 31 | } 32 | } 33 | 34 | $v8 = new V8Js(); 35 | $v8->myarr = new MyArray(); 36 | 37 | $js = <<executeString($js); 50 | 51 | ?> 52 | ===EOF=== 53 | --EXPECT-- 54 | string(1) "0" 55 | string(1) "1" 56 | string(1) "2" 57 | string(1) "4" 58 | string(1) "0" 59 | string(1) "1" 60 | string(1) "2" 61 | string(1) "4" 62 | ===EOF=== 63 | -------------------------------------------------------------------------------- /tests/array_access_007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Delete (unset) ArrayAccess keys 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 14 | } 15 | 16 | public function offsetGet(mixed $offset): mixed { 17 | if(!$this->offsetExists($offset)) { 18 | return null; 19 | } 20 | return $this->data[$offset]; 21 | } 22 | 23 | public function offsetSet(mixed $offset, mixed $value): void { 24 | $this->data[$offset] = $value; 25 | } 26 | 27 | public function offsetUnset(mixed $offset): void { 28 | unset($this->data[$offset]); 29 | } 30 | 31 | public function count(): int { 32 | return max(array_keys($this->data)) + 1; 33 | } 34 | } 35 | 36 | $v8 = new V8Js(); 37 | $v8->myarr = new MyArray(); 38 | 39 | $js = <<executeString($js); 50 | 51 | ?> 52 | ===EOF=== 53 | --EXPECT-- 54 | string(10) "one,,three" 55 | string(10) "one,,three" 56 | ===EOF=== 57 | -------------------------------------------------------------------------------- /tests/array_access_008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : in array (isset) behaviour of ArrayAccess 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 14 | } 15 | 16 | public function offsetGet(mixed $offset): mixed { 17 | return $this->data[$offset]; 18 | } 19 | 20 | public function offsetSet(mixed $offset, mixed $value): void { 21 | $this->data[$offset] = $value; 22 | } 23 | 24 | public function offsetUnset(mixed $offset): void { 25 | unset($this->data[$offset]); 26 | } 27 | 28 | public function count(): int { 29 | return max(array_keys($this->data)) + 1; 30 | } 31 | } 32 | 33 | $v8 = new V8Js(); 34 | $v8->myarr = new MyArray(); 35 | 36 | $js = <<executeString($js); 47 | 48 | ?> 49 | ===EOF=== 50 | --EXPECT-- 51 | bool(true) 52 | bool(false) 53 | bool(true) 54 | bool(false) 55 | ===EOF=== 56 | -------------------------------------------------------------------------------- /tests/array_access_basic2.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check array access setter behaviour 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | v8js.use_array_access = 1 7 | --FILE-- 8 | data[$offset]); 14 | } 15 | 16 | public function offsetGet(mixed $offset): mixed { 17 | return $this->data[$offset]; 18 | } 19 | 20 | public function offsetSet(mixed $offset, mixed $value): void { 21 | $this->data[$offset] = $value; 22 | } 23 | 24 | public function offsetUnset(mixed $offset): void { 25 | throw new Exception('Not implemented'); 26 | } 27 | 28 | public function count(): int { 29 | return count($this->data); 30 | } 31 | } 32 | 33 | $myarr = new MyArray(); 34 | $myarr[0] = 'three'; 35 | 36 | $js = <<myarr = $myarr; 45 | $v8->executeString($js); 46 | 47 | var_dump($myarr[2]); 48 | 49 | ?> 50 | ===EOF=== 51 | --EXPECT-- 52 | string(5) "three" 53 | string(3) "one" 54 | string(13) "three,two,one" 55 | string(3) "one" 56 | ===EOF=== 57 | -------------------------------------------------------------------------------- /tests/array_pass.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check passing array from JS to PHP 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | test = function ($arr) { var_dump($arr); }; 10 | try { 11 | $v8->executeString('PHP.test([0, 1, 2]);'); 12 | } catch (V8JsScriptException $e) { 13 | var_dump($e->getMessage()); 14 | } 15 | 16 | try { 17 | $v8->executeString('PHP.test({ "0" : "0", "1" : "1", "2" : "2" });'); 18 | } catch (V8JsScriptException $e) { 19 | var_dump($e->getMessage()); 20 | } 21 | 22 | try { 23 | $v8->executeString('PHP.test({ "0" : "foo", "1" : "bar", "2" : "baz" });'); 24 | } catch (V8JsScriptException $e) { 25 | var_dump($e->getMessage()); 26 | } 27 | 28 | try { 29 | $v8->executeString('PHP.test({ "foo" : "0", "bar" : "1", "baz" : "2" });'); 30 | } catch (V8JsScriptException $e) { 31 | var_dump($e->getMessage()); 32 | } 33 | 34 | try { 35 | // includes gap 36 | $v8->executeString('PHP.test({ "0" : "0", "2" : "2", "3" : "3" });'); 37 | } catch (V8JsScriptException $e) { 38 | var_dump($e->getMessage()); 39 | } 40 | 41 | try { 42 | // mixed key types 43 | $v8->executeString('PHP.test({ "0" : "0", "bar" : "1", "2" : "2" });'); 44 | } catch (V8JsScriptException $e) { 45 | var_dump($e->getMessage()); 46 | } 47 | 48 | ?> 49 | ===EOF=== 50 | --EXPECT-- 51 | array(3) { 52 | [0]=> 53 | int(0) 54 | [1]=> 55 | int(1) 56 | [2]=> 57 | int(2) 58 | } 59 | object(V8Object)#3 (3) { 60 | ["0"]=> 61 | string(1) "0" 62 | ["1"]=> 63 | string(1) "1" 64 | ["2"]=> 65 | string(1) "2" 66 | } 67 | object(V8Object)#3 (3) { 68 | ["0"]=> 69 | string(3) "foo" 70 | ["1"]=> 71 | string(3) "bar" 72 | ["2"]=> 73 | string(3) "baz" 74 | } 75 | object(V8Object)#3 (3) { 76 | ["foo"]=> 77 | string(1) "0" 78 | ["bar"]=> 79 | string(1) "1" 80 | ["baz"]=> 81 | string(1) "2" 82 | } 83 | object(V8Object)#3 (3) { 84 | ["0"]=> 85 | string(1) "0" 86 | ["2"]=> 87 | string(1) "2" 88 | ["3"]=> 89 | string(1) "3" 90 | } 91 | object(V8Object)#3 (3) { 92 | ["0"]=> 93 | string(1) "0" 94 | ["2"]=> 95 | string(1) "2" 96 | ["bar"]=> 97 | string(1) "1" 98 | } 99 | ===EOF=== 100 | -------------------------------------------------------------------------------- /tests/array_pass_flags.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check passing array from JS to PHP (using force array flag) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | test = function ($arr) { var_dump($arr); }; 10 | try { 11 | $v8->executeString('PHP.test([0, 1, 2]);', "test", \V8Js::FLAG_FORCE_ARRAY); 12 | } catch (V8JsScriptException $e) { 13 | var_dump($e->getMessage()); 14 | } 15 | 16 | try { 17 | $v8->executeString('PHP.test({ "0" : "0", "1" : "1", "2" : "2" });', "test", \V8Js::FLAG_FORCE_ARRAY); 18 | } catch (V8JsScriptException $e) { 19 | var_dump($e->getMessage()); 20 | } 21 | 22 | try { 23 | $v8->executeString('PHP.test({ "0" : "foo", "1" : "bar", "2" : "baz" });', "test", \V8Js::FLAG_FORCE_ARRAY); 24 | } catch (V8JsScriptException $e) { 25 | var_dump($e->getMessage()); 26 | } 27 | 28 | try { 29 | $v8->executeString('PHP.test({ "foo" : "0", "bar" : "1", "baz" : "2" });', "test", \V8Js::FLAG_FORCE_ARRAY); 30 | } catch (V8JsScriptException $e) { 31 | var_dump($e->getMessage()); 32 | } 33 | 34 | try { 35 | // includes gap 36 | $v8->executeString('PHP.test({ "0" : "0", "2" : "2", "3" : "3" });', "test", \V8Js::FLAG_FORCE_ARRAY); 37 | } catch (V8JsScriptException $e) { 38 | var_dump($e->getMessage()); 39 | } 40 | 41 | try { 42 | // mixed key types 43 | $v8->executeString('PHP.test({ "0" : "0", "bar" : "1", "2" : "2" });', "test", \V8Js::FLAG_FORCE_ARRAY); 44 | } catch (V8JsScriptException $e) { 45 | var_dump($e->getMessage()); 46 | } 47 | 48 | ?> 49 | ===EOF=== 50 | --EXPECT-- 51 | array(3) { 52 | [0]=> 53 | int(0) 54 | [1]=> 55 | int(1) 56 | [2]=> 57 | int(2) 58 | } 59 | array(3) { 60 | [0]=> 61 | string(1) "0" 62 | [1]=> 63 | string(1) "1" 64 | [2]=> 65 | string(1) "2" 66 | } 67 | array(3) { 68 | [0]=> 69 | string(3) "foo" 70 | [1]=> 71 | string(3) "bar" 72 | [2]=> 73 | string(3) "baz" 74 | } 75 | array(3) { 76 | ["foo"]=> 77 | string(1) "0" 78 | ["bar"]=> 79 | string(1) "1" 80 | ["baz"]=> 81 | string(1) "2" 82 | } 83 | array(3) { 84 | [0]=> 85 | string(1) "0" 86 | [2]=> 87 | string(1) "2" 88 | [3]=> 89 | string(1) "3" 90 | } 91 | array(3) { 92 | [0]=> 93 | string(1) "0" 94 | [2]=> 95 | string(1) "2" 96 | ["bar"]=> 97 | string(1) "1" 98 | } 99 | ===EOF=== 100 | -------------------------------------------------------------------------------- /tests/array_recursive.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : export of recursive array 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = $a; 14 | $v8->executeString('var_dump(PHP.foo);'); 15 | 16 | ?> 17 | ===EOF=== 18 | --EXPECT-- 19 | array(2) { 20 | [0] => 21 | NULL 22 | [1] => 23 | int(23) 24 | } 25 | ===EOF=== 26 | -------------------------------------------------------------------------------- /tests/basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Simple test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'basic.js')); 17 | } catch (V8JsScriptException $e) { 18 | var_dump($e); 19 | } 20 | ?> 21 | ===EOF=== 22 | --EXPECT-- 23 | Hello World! 24 | int(13) 25 | ===EOF=== 26 | -------------------------------------------------------------------------------- /tests/callbacks.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Call JS from PHP 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | test = function ($params) { return (method_exists($params, 'cb1')) ? $params->cb1("hello") : false; }; 12 | $ret = $a->executeString('PHP.test(function (foo) { return foo + " world"; });'); 13 | var_dump(__LINE__, $ret); 14 | 15 | // Test is_a() 16 | $a->test = function ($params) { return (is_a($params, 'V8Object')) ? $params->cb1("hello") : false; }; 17 | $ret = $a->executeString('PHP.test({ "cb1" : function (foo) { return foo + " world"; } });'); 18 | var_dump(__LINE__, $ret); 19 | 20 | // Test is_a() 21 | $a->test = function ($params) { return (is_a($params, 'V8Function')) ? $params("hello") : false; }; 22 | $ret = $a->executeString('PHP.test(function (foo) { return foo + " world"; });'); 23 | var_dump(__LINE__, $ret); 24 | 25 | // Should not work with object 26 | $a->test = function ($params) { return (is_a($params, 'Closure')) ? $params("hello") : false; }; 27 | $ret = $a->executeString('PHP.test({ "cb1" : function (foo) { return foo + " world"; } });'); 28 | var_dump(__LINE__, $ret); 29 | 30 | // Works 31 | $a->test = function ($params) { return $params->cb1("hello"); }; 32 | $ret = $a->executeString('PHP.test({ "cb1" : function (foo) { return foo + " world"; } });'); 33 | var_dump(__LINE__, $ret); 34 | 35 | ?> 36 | ===EOF=== 37 | --EXPECT-- 38 | int(8) 39 | bool(false) 40 | int(13) 41 | string(11) "hello world" 42 | int(18) 43 | string(11) "hello world" 44 | int(23) 45 | bool(false) 46 | int(28) 47 | string(11) "hello world" 48 | ===EOF=== 49 | -------------------------------------------------------------------------------- /tests/checkstring_compile.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Script validator test using compileString 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | compileString('print("Hello World!");')); 10 | 11 | try { 12 | var_dump($v8->compileString('print("Hello World!);')); 13 | } catch (V8JsScriptException $e) { 14 | var_dump($e->getMessage()); 15 | } 16 | ?> 17 | ===EOF=== 18 | --EXPECTF-- 19 | resource(%d) of type (V8Js script) 20 | string(%d) "V8Js::compileString():1: SyntaxError: %s" 21 | ===EOF=== 22 | -------------------------------------------------------------------------------- /tests/closures_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Simple test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | func = function ($arg) { echo "Hello {$arg}, I'm Closure!\n"; }; 10 | 11 | try { 12 | $a->executeString('print(PHP.func + "\n"); PHP.func("foobar");', "closure_test.js"); 13 | } catch (V8JsScriptException $e) { 14 | echo $e->getMessage(), "\n"; 15 | } 16 | ?> 17 | ===EOF=== 18 | --EXPECTF-- 19 | [object %s] 20 | Hello foobar, I'm Closure! 21 | ===EOF=== 22 | -------------------------------------------------------------------------------- /tests/closures_dynamic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Dynamic closure call test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | func = function ($arg) use ($b) { return call_user_func($b, $arg); }; 19 | 20 | try { 21 | $a->executeString('print(PHP.func + "\n"); print(PHP.func("world") + "\n");', "closure_test.js"); 22 | } catch (V8JsScriptException $e) { 23 | echo $e->getMessage(), "\n"; 24 | } 25 | ?> 26 | ===EOF=== 27 | --EXPECTF-- 28 | [object %s] 29 | Hello world 30 | ===EOF=== 31 | -------------------------------------------------------------------------------- /tests/commonjs_caching_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Returned modules are cached 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 16 | print("setModuleLoader called for ".$module."\n"); 17 | return 'exports.bar = 23;'; 18 | }); 19 | 20 | $v8->executeString($JS, 'module.js'); 21 | ?> 22 | ===EOF=== 23 | --EXPECT-- 24 | setModuleLoader called for test 25 | setModuleLoader called for test2 26 | ===EOF=== 27 | -------------------------------------------------------------------------------- /tests/commonjs_caching_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : module cache seperated per isolate 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 15 | print("setModuleLoader called for ".$module."\n"); 16 | return 'exports.bar = 23;'; 17 | }); 18 | 19 | $v8two = new V8Js(); 20 | $v8two->setModuleLoader(function($module) { 21 | print("setModuleLoader called for ".$module."\n"); 22 | return 'exports.bar = 23;'; 23 | }); 24 | 25 | $v8->executeString($JS, 'module.js'); 26 | echo "--- v8two ---\n"; 27 | $v8two->executeString($JS, 'module.js'); 28 | ?> 29 | ===EOF=== 30 | --EXPECT-- 31 | setModuleLoader called for test 32 | --- v8two --- 33 | setModuleLoader called for test 34 | ===EOF=== 35 | -------------------------------------------------------------------------------- /tests/commonjs_cust_normalise_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleNormaliser : Custom normalisation #001 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleNormaliser(function($base, $module) { 15 | var_dump($base, $module); 16 | return [ "", "test" ]; 17 | }); 18 | 19 | $v8->setModuleLoader(function($module) { 20 | print("setModuleLoader called for ".$module."\n"); 21 | return 'exports.bar = 23;'; 22 | }); 23 | 24 | $v8->executeString($JS, 'module.js'); 25 | ?> 26 | ===EOF=== 27 | --EXPECT-- 28 | string(0) "" 29 | string(6) "./test" 30 | setModuleLoader called for test 31 | ===EOF=== 32 | -------------------------------------------------------------------------------- /tests/commonjs_cust_normalise_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleNormaliser : Custom normalisation #002 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleNormaliser(function($base, $module) { 17 | var_dump($base, $module); 18 | return [ "path/to", "test-foo" ]; 19 | }); 20 | 21 | $v8->setModuleLoader(function($module) { 22 | print("setModuleLoader called for ".$module."\n"); 23 | return 'exports.bar = 23;'; 24 | }); 25 | 26 | $v8->executeString($JS, 'module.js'); 27 | ?> 28 | ===EOF=== 29 | --EXPECT-- 30 | string(0) "" 31 | string(6) "./test" 32 | setModuleLoader called for path/to/test-foo 33 | ===EOF=== 34 | -------------------------------------------------------------------------------- /tests/commonjs_cust_normalise_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleNormaliser : Custom normalisation #003 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleNormaliser(function($base, $module) { 20 | var_dump($base, $module); 21 | return [ "path/to", "test-foo" ]; 22 | }); 23 | 24 | $v8->setModuleLoader(function($module) { 25 | print("setModuleLoader called for ".$module."\n"); 26 | if($module != "path/to/test-foo") { 27 | throw new \Exception("module caching fails"); 28 | } 29 | return 'exports.bar = 23;'; 30 | }); 31 | 32 | $v8->executeString($JS, 'module.js'); 33 | ?> 34 | ===EOF=== 35 | --EXPECT-- 36 | string(0) "" 37 | string(6) "./test" 38 | setModuleLoader called for path/to/test-foo 39 | string(0) "" 40 | string(4) "test" 41 | ===EOF=== 42 | -------------------------------------------------------------------------------- /tests/commonjs_cust_normalise_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleNormaliser : Custom normalisation #004 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleNormaliser(function($base, $module) { 17 | var_dump($base, $module); 18 | return [ "path/to", $module ]; 19 | }); 20 | 21 | $v8->setModuleLoader(function($module) { 22 | print("setModuleLoader called for ".$module."\n"); 23 | switch($module) { 24 | case "path/to/foo": 25 | return "require('bar');"; 26 | 27 | case "path/to/bar": 28 | return 'exports.bar = 23;'; 29 | } 30 | }); 31 | 32 | $v8->executeString($JS, 'module.js'); 33 | ?> 34 | ===EOF=== 35 | --EXPECT-- 36 | string(0) "" 37 | string(3) "foo" 38 | setModuleLoader called for path/to/foo 39 | string(7) "path/to" 40 | string(3) "bar" 41 | setModuleLoader called for path/to/bar 42 | ===EOF=== 43 | -------------------------------------------------------------------------------- /tests/commonjs_exception_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Forward exceptions 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 14 | throw new Exception('some exception'); 15 | }); 16 | 17 | $v8->executeString($JS, 'module.js', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 18 | ?> 19 | ===EOF=== 20 | --EXPECTF-- 21 | Fatal error: Uncaught Exception: some exception in %s%ecommonjs_exception_001.php:9 22 | Stack trace: 23 | #0 [internal function]: {closur%s}('test') 24 | #1 %s%ecommonjs_exception_001.php(12): V8Js->executeString('var foo = requi...', 'module.js', 4) 25 | #2 {main} 26 | 27 | Next V8JsScriptException: module.js:1: Exception: some exception in %s%ecommonjs_exception_001.php:9 28 | Stack trace: 29 | #0 [internal function]: {closur%s}('test') 30 | #1 %s%ecommonjs_exception_001.php(12): V8Js->executeString('var foo = requi...', 'module.js', 4) 31 | #2 {main} in %s%ecommonjs_exception_001.php:12 32 | Stack trace: 33 | #0 %s%ecommonjs_exception_001.php(12): V8Js->executeString('var foo = requi...', 'module.js', 4) 34 | #1 {main} 35 | thrown in %s%ecommonjs_exception_001.php on line 12 36 | -------------------------------------------------------------------------------- /tests/commonjs_exception_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleNormaliser : Forward exceptions 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleNormaliser(function($module) { 14 | throw new Exception('some exception'); 15 | }); 16 | $v8->setModuleLoader(function($module) { 17 | echo 'dummy ...'; 18 | }); 19 | 20 | $v8->executeString($JS, 'module.js', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 21 | ?> 22 | ===EOF=== 23 | --EXPECTF-- 24 | Fatal error: Uncaught Exception: some exception in %s%ecommonjs_exception_002.php:9 25 | Stack trace: 26 | #0 [internal function]: {closur%s}('', './test') 27 | #1 %s%ecommonjs_exception_002.php(15): V8Js->executeString('var foo = requi...', 'module.js', 4) 28 | #2 {main} 29 | 30 | Next V8JsScriptException: module.js:1: Exception: some exception in %s%ecommonjs_exception_002.php:9 31 | Stack trace: 32 | #0 [internal function]: {closur%s}('', './test') 33 | #1 %s%ecommonjs_exception_002.php(15): V8Js->executeString('var foo = requi...', 'module.js', 4) 34 | #2 {main} in %s%ecommonjs_exception_002.php:15 35 | Stack trace: 36 | #0 %s%ecommonjs_exception_002.php(15): V8Js->executeString('var foo = requi...', 'module.js', 4) 37 | #1 {main} 38 | thrown in %s%ecommonjs_exception_002.php on line 15 39 | -------------------------------------------------------------------------------- /tests/commonjs_fatal_error.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Handle fatal errors gracefully 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function() { 10 | @trigger_error('some fatal error', E_USER_ERROR); 11 | }); 12 | 13 | $v8->executeString(' require("foo"); '); 14 | ?> 15 | ===EOF=== 16 | --EXPECTF-- 17 | Fatal error: some fatal error in %s%ecommonjs_fatal_error.php on line 5 18 | -------------------------------------------------------------------------------- /tests/commonjs_modules.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : CommonJS modules 3 | --SKIPIF-- 4 | 10 | --FILE-- 11 | setModuleLoader(function($module) { 19 | switch ($module) { 20 | case 'path/to/module1': 21 | return 'print(' . json_encode($module . PHP_EOL) . ');require("./module2");'; 22 | 23 | case 'path/to/module2': 24 | return 'print(' . json_encode($module . PHP_EOL) . ');require("../../module3");'; 25 | 26 | default: 27 | return 'print(' . json_encode($module . PHP_EOL) . ');'; 28 | } 29 | }); 30 | 31 | $v8->executeString($JS, 'module.js'); 32 | ?> 33 | ===EOF=== 34 | --EXPECT-- 35 | path/to/module1 36 | path/to/module2 37 | module3 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/commonjs_multiassign.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Assign result multiple times 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 17 | return 'exports.bar = 23;'; 18 | }); 19 | 20 | $v8->executeString($JS, 'module.js'); 21 | ?> 22 | ===EOF=== 23 | --EXPECT-- 24 | int(23) 25 | int(23) 26 | ===EOF=== 27 | -------------------------------------------------------------------------------- /tests/commonjs_native_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Native Module basic behaviour 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 17 | return new NativeModule(); 18 | }); 19 | $v8->executeString('require("foo").sayHello("World");'); 20 | ?> 21 | ===EOF=== 22 | --EXPECT-- 23 | Hello World! 24 | ===EOF=== -------------------------------------------------------------------------------- /tests/commonjs_node_compat_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : this === module.exports 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function ($moduleName) { 11 | return <<<'EOJS' 12 | var_dump(this === global); 13 | var_dump(this === module.exports); 14 | EOJS 15 | ; 16 | }); 17 | 18 | $v8->executeString(<<<'EOJS' 19 | var result = require('foo'); 20 | EOJS 21 | ); 22 | 23 | ?> 24 | ===EOF=== 25 | --EXPECT-- 26 | bool(false) 27 | bool(true) 28 | ===EOF=== 29 | -------------------------------------------------------------------------------- /tests/commonjs_node_compat_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : modules can return arbitrary values 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function ($moduleName) { 11 | return <<<'EOJS' 12 | module.exports = 23; 13 | EOJS 14 | ; 15 | }); 16 | 17 | $v8->executeString(<<<'EOJS' 18 | var result = require('foo'); 19 | var_dump(typeof result); 20 | var_dump(result); 21 | EOJS 22 | ); 23 | 24 | ?> 25 | ===EOF=== 26 | --EXPECT-- 27 | string(6) "number" 28 | int(23) 29 | ===EOF=== 30 | -------------------------------------------------------------------------------- /tests/commonjs_node_compat_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : delete module.exports yields undefined 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function ($moduleName) { 11 | return <<<'EOJS' 12 | delete module.exports; 13 | EOJS 14 | ; 15 | }); 16 | 17 | $v8->executeString(<<<'EOJS' 18 | var result = require('foo'); 19 | var_dump(typeof result); 20 | EOJS 21 | ); 22 | 23 | ?> 24 | ===EOF=== 25 | --EXPECT-- 26 | string(9) "undefined" 27 | ===EOF=== 28 | -------------------------------------------------------------------------------- /tests/commonjs_node_compat_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : exports/module.exports behaviour 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function ($moduleName) { 11 | return <<<'EOJS' 12 | var_dump(typeof exports); 13 | var_dump(typeof module.exports); 14 | 15 | // for compatibility both should be linked 16 | var_dump(exports === module.exports); 17 | 18 | exports = { number: 23 }; 19 | module.exports = { number: 42 }; 20 | EOJS 21 | ; 22 | }); 23 | 24 | $v8->executeString(<<<'EOJS' 25 | var result = require('foo'); 26 | 27 | // expect module.exports value to be picked up 28 | var_dump(typeof result); 29 | var_dump(result.number); 30 | EOJS 31 | ); 32 | 33 | ?> 34 | ===EOF=== 35 | --EXPECT-- 36 | string(6) "object" 37 | string(6) "object" 38 | bool(true) 39 | string(6) "object" 40 | int(42) 41 | ===EOF=== 42 | -------------------------------------------------------------------------------- /tests/commonjs_normalise_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Path normalisation #001 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 14 | print("setModuleLoader called for ".$module."\n"); 15 | return 'exports.bar = 23;'; 16 | }); 17 | 18 | $v8->executeString($JS, 'module.js'); 19 | ?> 20 | ===EOF=== 21 | --EXPECT-- 22 | setModuleLoader called for test 23 | ===EOF=== 24 | -------------------------------------------------------------------------------- /tests/commonjs_normalise_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Path normalisation #002 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 14 | print("setModuleLoader called for ".$module."\n"); 15 | return 'exports.bar = 23;'; 16 | }); 17 | 18 | $v8->executeString($JS, 'module.js'); 19 | ?> 20 | ===EOF=== 21 | --EXPECT-- 22 | setModuleLoader called for test 23 | ===EOF=== 24 | -------------------------------------------------------------------------------- /tests/commonjs_normalise_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Path normalisation #003 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 16 | print("setModuleLoader called for ".$module."\n"); 17 | return 'exports.bar = 23;'; 18 | }); 19 | 20 | $v8->executeString($JS, 'module.js'); 21 | ?> 22 | ===EOF=== 23 | --EXPECT-- 24 | setModuleLoader called for foo/test 25 | setModuleLoader called for foo/bar/baz/test 26 | setModuleLoader called for foo/bar/baz/blub 27 | ===EOF=== 28 | -------------------------------------------------------------------------------- /tests/commonjs_normalise_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Path normalisation #004 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 14 | print("setModuleLoader called for ".$module."\n"); 15 | 16 | switch($module) { 17 | case 'foo/test': 18 | return 'require("./blar");'; 19 | case 'foo/blar': 20 | return 'exports.bar = 23;'; 21 | } 22 | }); 23 | 24 | $v8->executeString($JS, 'module.js'); 25 | ?> 26 | ===EOF=== 27 | --EXPECT-- 28 | setModuleLoader called for foo/test 29 | setModuleLoader called for foo/blar 30 | ===EOF=== 31 | -------------------------------------------------------------------------------- /tests/commonjs_normalise_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Path normalisation #005 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 14 | print("setModuleLoader called for ".$module."\n"); 15 | 16 | switch($module) { 17 | case 'foo/test': 18 | return 'require("../blar");'; 19 | case 'blar': 20 | return 'exports.bar = 23;'; 21 | } 22 | }); 23 | 24 | $v8->executeString($JS, 'module.js'); 25 | ?> 26 | ===EOF=== 27 | --EXPECT-- 28 | setModuleLoader called for foo/test 29 | setModuleLoader called for blar 30 | ===EOF=== 31 | -------------------------------------------------------------------------------- /tests/commonjs_source_naming.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleLoader : Module source naming 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function($module) { 14 | // return code with syntax errors to provoke script exception 15 | return "foo(blar);"; 16 | }); 17 | 18 | try { 19 | $v8->executeString($JS, 'commonjs_source_naming.js'); 20 | } catch (V8JsScriptException $e) { 21 | var_dump($e->getJsFileName()); 22 | } 23 | ?> 24 | ===EOF=== 25 | --EXPECT-- 26 | string(7) "foo/bar" 27 | ===EOF=== 28 | -------------------------------------------------------------------------------- /tests/compile_string.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::compileString() : Compile and run a script 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | compileString($js, 'a.js'); 20 | var_dump(is_resource($script_a)); 21 | $script_b = $v8->compileString($js2, 'b.js'); 22 | var_dump(is_resource($script_b)); 23 | var_dump($v8->executeScript($script_a)); 24 | var_dump($v8->executeScript($script_b)); 25 | var_dump($v8->executeScript($script_a)); 26 | } catch (V8JsScriptException $e) { 27 | var_dump($e); 28 | } 29 | ?> 30 | ===EOF=== 31 | --EXPECT-- 32 | bool(true) 33 | bool(true) 34 | object(V8Object)#2 (1) { 35 | ["hello"]=> 36 | string(5) "world" 37 | } 38 | object(V8Object)#2 (1) { 39 | ["foo"]=> 40 | string(3) "bar" 41 | } 42 | object(V8Object)#2 (1) { 43 | ["hello"]=> 44 | string(5) "world" 45 | } 46 | ===EOF=== 47 | -------------------------------------------------------------------------------- /tests/compile_string_isolate.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::compileString() : Check compiled script isolate processing 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | compileString($js, 'a.js'); 21 | var_dump($script_a); 22 | $script_b = $v8two->compileString($js2, 'b.js'); 23 | var_dump($script_b); 24 | var_dump($v8->executeScript($script_a)); 25 | var_dump($v8->executeScript($script_b)); 26 | var_dump($v8->executeScript($script_a)); 27 | } catch (V8JsScriptException $e) { 28 | var_dump($e); 29 | } 30 | ?> 31 | ===EOF=== 32 | --EXPECTF-- 33 | resource(%d) of type (V8Js script) 34 | resource(%d) of type (V8Js script) 35 | object(V8Object)#%d (1) { 36 | ["hello"]=> 37 | string(5) "world" 38 | } 39 | 40 | Warning: Script resource from wrong V8Js object passed in %s on line %d 41 | bool(false) 42 | object(V8Object)#%d (1) { 43 | ["hello"]=> 44 | string(5) "world" 45 | } 46 | ===EOF=== 47 | -------------------------------------------------------------------------------- /tests/construct.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Calling construct twice 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | __construct(); 14 | 15 | try { 16 | $v8->executeString($JS, 'basic.js'); 17 | } catch (V8JsScriptException $e) { 18 | var_dump($e); 19 | } 20 | ?> 21 | ===EOF=== 22 | --EXPECT-- 23 | Hello World! 24 | ===EOF=== 25 | -------------------------------------------------------------------------------- /tests/context_preserving.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : test context preserving 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | ctx = '#1'; 26 | 27 | try { 28 | echo '1. '; 29 | $a->executeString($JS_set, 'set.js'); 30 | } catch (V8JsScriptException $e) { 31 | var_dump($e); 32 | } 33 | 34 | // Second context: Change variable 35 | $b = new V8Js(); 36 | $b->ctx = '#2'; 37 | 38 | try { 39 | echo '2. '; 40 | $b->executeString($JS_change, 'change.js'); 41 | } catch (V8JsScriptException $e) { 42 | var_dump($e); 43 | } 44 | 45 | // First context: Read variable 46 | try { 47 | echo '3. '; 48 | $a->executeString($JS_read, 'read.js'); 49 | } catch (V8JsScriptException $e) { 50 | var_dump($e); 51 | } 52 | 53 | // First context: Change variable 54 | try { 55 | echo '4. '; 56 | $a->executeString($JS_change, 'change.js'); 57 | } catch (V8JsScriptException $e) { 58 | var_dump($e); 59 | } 60 | 61 | // First context: Read variable again 62 | try { 63 | echo '5. '; 64 | $a->executeString($JS_read, 'read.js'); 65 | } catch (V8JsScriptException $e) { 66 | var_dump($e); 67 | } 68 | ?> 69 | ===EOF=== 70 | --EXPECT-- 71 | 1. Set variable (#1) 72 | 2. Change variable (#2) 73 | 3. Read variable (#1) 74 | Result: ORIGINAL 75 | 4. Change variable (#1) 76 | 5. Read variable (#1) 77 | Result: CHANGED 78 | ===EOF=== 79 | -------------------------------------------------------------------------------- /tests/context_separation.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : test context separation 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = 'from first.js'; 14 | 15 | try { 16 | $a->executeString($JS, 'first.js'); 17 | } catch (V8JsScriptException $e) { 18 | var_dump($e); 19 | } 20 | 21 | echo "\n"; 22 | 23 | $b = new V8Js(); 24 | $b->foo = 'from second.js'; 25 | 26 | try { 27 | $b->executeString($JS, 'second.js'); 28 | } catch (V8JsScriptException $e) { 29 | var_dump($e); 30 | } 31 | 32 | echo "\n"; 33 | ?> 34 | ===EOF=== 35 | --EXPECTF-- 36 | from first.js 37 | from second.js 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/context_temp_creation.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : correct temp context construction 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | _b = $a; 15 | } 16 | 17 | function test() { 18 | print_r($this->_b); 19 | } 20 | } 21 | 22 | $v8->failer = new Failer(); 23 | $v8->executeString('PHP.failer.call({ foo: 23 });'); 24 | $v8->failer->test(); 25 | ?> 26 | ===EOF=== 27 | --EXPECT-- 28 | V8Object Object 29 | ( 30 | [foo] => 23 31 | ) 32 | ===EOF=== 33 | -------------------------------------------------------------------------------- /tests/create_snapshot_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::createSnapshot() : Basic snapshot creation & re-use 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | 0) { 22 | var_dump("snapshot successfully created"); 23 | } 24 | 25 | $v8 = new V8Js('PHP', array(), $snap); 26 | $v8->executeString('var_dump(doublify(23));'); 27 | ?> 28 | ===EOF=== 29 | --EXPECT-- 30 | string(29) "snapshot successfully created" 31 | int(46) 32 | ===EOF=== 33 | -------------------------------------------------------------------------------- /tests/ctx_lifetime.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Testing lifespan of V8Js context objects 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo; 21 | return $v8js->executeString("({ bar: 23, hello: function() { PHP.foo.__call('hello',[]); } })"); 22 | // $v8js will be dereferenced here, but the result escapes. 23 | } 24 | } 25 | 26 | $t = new Testing(); 27 | 28 | $a = $t->onectx(); 29 | /* $a is no longer valid, since the associated V8Js() object has been 30 | * destroyed. Instead the property access will throw. */ 31 | var_dump($a); 32 | 33 | try { 34 | var_dump($a->bar); 35 | } 36 | catch(Exception $e) { 37 | var_dump($e->getMessage()); 38 | } 39 | 40 | $a->hello(); 41 | 42 | ?> 43 | ===EOF=== 44 | --EXPECTF-- 45 | object(V8Object)#%d (0) { 46 | } 47 | string(55) "Can't access V8Object after V8Js instance is destroyed!" 48 | 49 | Fatal error: Uncaught V8JsException: Can't access V8Object after V8Js instance is destroyed! in %s%etests%ectx_lifetime.php:35 50 | Stack trace: 51 | #0 {main} 52 | thrown in %s%etests%ectx_lifetime.php on line 35 53 | -------------------------------------------------------------------------------- /tests/datetime_pass.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Pass JS date to PHP 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | var = new \DateTime("Wed, 19 Mar 2014 14:37:11 +0000"); 17 | $a->executeString('print(PHP.var.toGMTString()); print("\n");'); 18 | ini_set('v8js.use_date', 0); 19 | 20 | $a = new V8Js(); 21 | $a->var = new \DateTime("Wed, 19 Mar 2014 14:37:11 +0000"); 22 | $a->executeString('print(PHP.var.toString()); print("\n");'); 23 | 24 | ?> 25 | ===EOF=== 26 | --EXPECTF-- 27 | Wed, 19 Mar 2014 14:37:11 GMT 28 | [object %s] 29 | ===EOF=== 30 | -------------------------------------------------------------------------------- /tests/derived_class_properties.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Properties on derived class 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | testing = 23; 14 | } 15 | } 16 | 17 | $v8 = new V8Wrapper(); 18 | $v8->executeString('print("foo\n");'); 19 | ?> 20 | ===EOF=== 21 | --EXPECT-- 22 | foo 23 | ===EOF=== 24 | -------------------------------------------------------------------------------- /tests/derived_class_properties_extra.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Extra properties on derived class 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | testing = 23; 14 | $this->extraTesting = 42; 15 | } 16 | } 17 | 18 | $v8 = new V8Wrapper(); 19 | $v8->executeString('print(PHP.testing + "\n");'); 20 | $v8->executeString('print(PHP.extraTesting + "\n");'); 21 | ?> 22 | ===EOF=== 23 | --EXPECT-- 24 | undefined 25 | 42 26 | ===EOF=== 27 | -------------------------------------------------------------------------------- /tests/derived_class_properties_init.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Initialized properties on derived class 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | testing."\n"); 16 | $v8->executeString('print(PHP.testing + "\n");'); 17 | $v8->executeString('print(PHP.protectedVar + "\n");'); 18 | $v8->executeString('print(PHP.privateVar + "\n");'); 19 | ?> 20 | ===EOF=== 21 | --EXPECT-- 22 | 23 23 | 23 24 | undefined 25 | undefined 26 | ===EOF=== 27 | -------------------------------------------------------------------------------- /tests/derived_class_properties_protected.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Protected and private properties on derived class 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | testing = 23; 15 | $this->privTesting = 42; 16 | } 17 | } 18 | 19 | $v8 = new V8Wrapper(); 20 | $v8->executeString('print(PHP.testing + "\n");'); 21 | $v8->executeString('print(PHP.privTesting + "\n");'); 22 | ?> 23 | ===EOF=== 24 | --EXPECT-- 25 | undefined 26 | undefined 27 | ===EOF=== 28 | -------------------------------------------------------------------------------- /tests/die.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Handle die() gracefully 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = function() { 9 | echo "Hallo\n"; 10 | die("Goodbye cruel world!\n"); 11 | }; 12 | $v8->executeString('PHP.foo();'); 13 | ?> 14 | ===EOF=== 15 | --EXPECT-- 16 | Hallo 17 | Goodbye cruel world! 18 | -------------------------------------------------------------------------------- /tests/direct_construct.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : direct construction is prohibited 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getMessage()); 14 | } 15 | try { 16 | $a = new V8Function; 17 | } catch (V8JsException $e) { 18 | var_dump($e->getMessage()); 19 | } 20 | 21 | # but these are allowed 22 | echo "-- ALLOWED --\n"; 23 | $v8 = new V8Js(); 24 | $o = $v8->executeString("({foo:1})"); 25 | var_dump($o); 26 | $f = $v8->executeString("(function() { return 1; })"); 27 | var_dump($f); 28 | 29 | # but these are not allowed 30 | echo "-- NOT ALLOWED --\n"; 31 | try { 32 | $oo = new $o(); 33 | } catch (V8JsException $e) { 34 | var_dump($e->getMessage()); 35 | } 36 | try { 37 | $ff = new $f; 38 | } catch (V8JsException $e) { 39 | var_dump($e->getMessage()); 40 | } 41 | 42 | // free memory 43 | $o = null; $f = null; $v8 = null; 44 | ?> 45 | ===EOF=== 46 | --EXPECTF-- 47 | -- NOT ALLOWED -- 48 | string(36) "Can't directly construct V8 objects!" 49 | string(36) "Can't directly construct V8 objects!" 50 | -- ALLOWED -- 51 | object(V8Object)#%d (1) { 52 | ["foo"]=> 53 | int(1) 54 | } 55 | object(V8Function)#%d (0) { 56 | } 57 | -- NOT ALLOWED -- 58 | string(36) "Can't directly construct V8 objects!" 59 | string(36) "Can't directly construct V8 objects!" 60 | ===EOF=== 61 | -------------------------------------------------------------------------------- /tests/exception.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : V8JsScriptException 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'exception.js'); 16 | } catch (V8JsScriptException $e) { 17 | var_dump($e); 18 | } 19 | ?> 20 | ===EOF=== 21 | --EXPECTF-- 22 | object(V8JsScriptException)#%d (13) { 23 | ["message":protected]=> 24 | string(75) "exception.js:1: ReferenceError: this_function_does_not_exist is not defined" 25 | ["string":"Exception":private]=> 26 | string(0) "" 27 | ["code":protected]=> 28 | int(0) 29 | ["file":protected]=> 30 | string(%d) "%s" 31 | ["line":protected]=> 32 | int(10) 33 | ["trace":"Exception":private]=> 34 | array(1) { 35 | [0]=> 36 | array(6) { 37 | ["file"]=> 38 | string(%d) "%s" 39 | ["line"]=> 40 | int(10) 41 | ["function"]=> 42 | string(13) "executeString" 43 | ["class"]=> 44 | string(4) "V8Js" 45 | ["type"]=> 46 | string(2) "->" 47 | ["args"]=> 48 | array(2) { 49 | [0]=> 50 | string(31) "this_function_does_not_exist();" 51 | [1]=> 52 | string(12) "exception.js" 53 | } 54 | } 55 | } 56 | ["previous":"Exception":private]=> 57 | NULL 58 | ["JsFileName":protected]=> 59 | string(12) "exception.js" 60 | ["JsLineNumber":protected]=> 61 | int(1) 62 | ["JsStartColumn":protected]=> 63 | int(0) 64 | ["JsEndColumn":protected]=> 65 | int(1) 66 | ["JsSourceLine":protected]=> 67 | string(31) "this_function_does_not_exist();" 68 | ["JsTrace":protected]=> 69 | string(83) "ReferenceError: this_function_does_not_exist is not defined 70 | at exception.js:1:1" 71 | } 72 | ===EOF=== 73 | -------------------------------------------------------------------------------- /tests/exception_filter_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setExceptionFilter() : String conversion 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setExceptionFilter(function (Throwable $ex) { 16 | echo "exception filter called.\n"; 17 | return $ex->getMessage(); 18 | }); 19 | 20 | $v8->executeString(' 21 | try { 22 | PHP.throwException("Oops"); 23 | } 24 | catch (e) { 25 | var_dump(typeof e); // string 26 | var_dump(e); 27 | } 28 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 29 | ?> 30 | ===EOF=== 31 | --EXPECT-- 32 | exception filter called. 33 | string(6) "string" 34 | string(4) "Oops" 35 | ===EOF=== 36 | -------------------------------------------------------------------------------- /tests/exception_filter_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setExceptionFilter() : Filter handling on exception in setModuleLoader 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleLoader(function ($path) { 10 | throw new Error('moep'); 11 | }); 12 | 13 | $v8->setExceptionFilter(function (Throwable $ex) { 14 | echo "exception filter called.\n"; 15 | return $ex->getMessage(); 16 | }); 17 | 18 | $v8->executeString(' 19 | try { 20 | require("file"); 21 | } catch(e) { 22 | var_dump(e); 23 | } 24 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 25 | 26 | ?> 27 | ===EOF=== 28 | --EXPECT-- 29 | exception filter called. 30 | string(4) "moep" 31 | ===EOF=== 32 | 33 | -------------------------------------------------------------------------------- /tests/exception_filter_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setExceptionFilter() : Filter handling on exception in setModuleNormaliser 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleNormaliser(function ($path) { 10 | throw new Error('blarg'); 11 | }); 12 | $v8->setModuleLoader(function ($path) { 13 | throw new Error('moep'); 14 | }); 15 | 16 | $v8->setExceptionFilter(function (Throwable $ex) { 17 | echo "exception filter called.\n"; 18 | return $ex->getMessage(); 19 | }); 20 | 21 | $v8->executeString(' 22 | try { 23 | require("file"); 24 | } catch(e) { 25 | var_dump(e); 26 | } 27 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 28 | 29 | ?> 30 | ===EOF=== 31 | --EXPECT-- 32 | exception filter called. 33 | string(5) "blarg" 34 | ===EOF=== 35 | -------------------------------------------------------------------------------- /tests/exception_filter_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setExceptionFilter() : Filter handling on exception in converter 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setExceptionFilter(function (Throwable $ex) { 16 | throw new Exception('moep'); 17 | }); 18 | 19 | try { 20 | $v8->executeString(' 21 | try { 22 | PHP.throwException("Oops"); 23 | print("done\\n"); 24 | } 25 | catch (e) { 26 | print("caught\\n"); 27 | var_dump(e); 28 | } 29 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 30 | } catch (Exception $ex) { 31 | echo "caught in php: " . $ex->getMessage() . PHP_EOL; 32 | } 33 | ?> 34 | ===EOF=== 35 | --EXPECT-- 36 | caught in php: moep 37 | ===EOF=== 38 | -------------------------------------------------------------------------------- /tests/exception_filter_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setExceptionFilter() : Uninstall filter on NULL 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setExceptionFilter(function (Throwable $ex) { 16 | echo "exception filter called.\n"; 17 | return "moep"; 18 | }); 19 | 20 | $v8->executeString(' 21 | try { 22 | PHP.throwException("Oops"); 23 | } 24 | catch (e) { 25 | var_dump(e); 26 | } 27 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 28 | 29 | $v8->setExceptionFilter(null); 30 | 31 | try { 32 | $v8->executeString(' 33 | try { 34 | PHP.throwException("Oops"); 35 | print("done\\n"); 36 | } 37 | catch (e) { 38 | print("caught\\n"); 39 | var_dump(e.getMessage()); 40 | } 41 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 42 | } catch (Exception $ex) { 43 | echo "caught in php: " . $ex->getMessage() . PHP_EOL; 44 | } 45 | 46 | ?> 47 | ===EOF=== 48 | --EXPECT-- 49 | exception filter called. 50 | string(4) "moep" 51 | caught 52 | string(4) "Oops" 53 | ===EOF=== 54 | -------------------------------------------------------------------------------- /tests/exception_filter_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setExceptionFilter() : re-throw exception in exception filter 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setExceptionFilter(function (Throwable $ex) { 16 | // re-throw exception so it is not forwarded 17 | throw $ex; 18 | }); 19 | 20 | try { 21 | $v8->executeString(' 22 | try { 23 | PHP.throwException("Oops"); 24 | print("done\\n"); 25 | } 26 | catch (e) { 27 | print("caught\\n"); 28 | var_dump(e); 29 | } 30 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 31 | } catch (Exception $ex) { 32 | echo "caught in php: " . $ex->getMessage() . PHP_EOL; 33 | } 34 | ?> 35 | ===EOF=== 36 | --EXPECT-- 37 | caught in php: Oops 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/exception_filter_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setExceptionFilter() : Simple test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getMessage()); 20 | 21 | $this->ex = $ex; 22 | } 23 | 24 | public function getMessage() { 25 | echo "getMessage called\n"; 26 | return $this->ex->getMessage(); 27 | } 28 | } 29 | 30 | $v8 = new myv8(); 31 | $v8->setExceptionFilter(function (Throwable $ex) { 32 | echo "exception filter called.\n"; 33 | return new ExceptionFilter($ex); 34 | }); 35 | 36 | $v8->executeString(' 37 | try { 38 | PHP.throwException("Oops"); 39 | } 40 | catch (e) { 41 | var_dump(e.getMessage()); // calls ExceptionFilter::getMessage 42 | var_dump(typeof e.getTrace); 43 | } 44 | ', null, V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 45 | ?> 46 | ===EOF=== 47 | --EXPECT-- 48 | exception filter called. 49 | ExceptionFilter::__construct called! 50 | string(4) "Oops" 51 | getMessage called 52 | string(4) "Oops" 53 | string(9) "undefined" 54 | ===EOF=== 55 | 56 | -------------------------------------------------------------------------------- /tests/exception_start_column.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Test getJsStartColumn on script exception 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString("print(blar());"); 14 | } 15 | catch(V8JsScriptException $a) { } 16 | 17 | try { 18 | $v8->executeString("(null); print(blar());"); 19 | } 20 | catch(V8JsScriptException $b) { } 21 | 22 | var_dump($b->getJsStartColumn() - $a->getJsStartColumn()); 23 | 24 | ?> 25 | ===EOF=== 26 | --EXPECT-- 27 | int(8) 28 | ===EOF=== 29 | -------------------------------------------------------------------------------- /tests/execute_flags.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Forcing to arrays (return value conversion) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($js, 'assoc_no_flags.js')); 16 | echo "---\n"; 17 | var_dump($v8->executeString($js, 'assoc_force_to_array.js', V8Js::FLAG_FORCE_ARRAY)); 18 | } catch (V8JsScriptException $e) { 19 | var_dump($e); 20 | } 21 | ?> 22 | ===EOF=== 23 | --EXPECTF-- 24 | object(V8Object)#%d (1) { 25 | ["hello"]=> 26 | string(5) "world" 27 | } 28 | --- 29 | array(1) { 30 | ["hello"]=> 31 | string(5) "world" 32 | } 33 | ===EOF=== 34 | -------------------------------------------------------------------------------- /tests/execute_flags_args.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Forcing to arrays (argument passing) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | test = function ($value) { var_dump(func_get_args()); }; 15 | 16 | try { 17 | $v8->executeString($js, 'no_flags.js'); 18 | echo "---\n"; 19 | $v8->executeString($js, 'force_to_array.js', V8Js::FLAG_FORCE_ARRAY); 20 | } catch (V8JsScriptException $e) { 21 | var_dump($e); 22 | } 23 | ?> 24 | ===EOF=== 25 | --EXPECTF-- 26 | array(2) { 27 | [0]=> 28 | object(V8Object)#%d (6) { 29 | ["0"]=> 30 | string(1) "F" 31 | ["1"]=> 32 | string(1) "o" 33 | ["2"]=> 34 | string(1) "o" 35 | ["3"]=> 36 | string(1) "b" 37 | ["4"]=> 38 | string(1) "a" 39 | ["5"]=> 40 | string(1) "r" 41 | } 42 | [1]=> 43 | object(V8Object)#%d (2) { 44 | ["0"]=> 45 | string(3) "foo" 46 | ["1"]=> 47 | string(3) "bar" 48 | } 49 | } 50 | --- 51 | array(2) { 52 | [0]=> 53 | array(6) { 54 | [0]=> 55 | string(1) "F" 56 | [1]=> 57 | string(1) "o" 58 | [2]=> 59 | string(1) "o" 60 | [3]=> 61 | string(1) "b" 62 | [4]=> 63 | string(1) "a" 64 | [5]=> 65 | string(1) "r" 66 | } 67 | [1]=> 68 | array(2) { 69 | [0]=> 70 | string(3) "foo" 71 | [1]=> 72 | string(3) "bar" 73 | } 74 | } 75 | ===EOF=== 76 | -------------------------------------------------------------------------------- /tests/execute_flags_property_writing.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Forcing to arrays (property writing) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | test = new stdClass(); 14 | 15 | try { 16 | $v8->executeString($js, 'no_flags.js'); 17 | var_dump($v8->test); 18 | echo "---\n"; 19 | $v8->executeString($js, 'force_to_array.js', V8Js::FLAG_FORCE_ARRAY); 20 | var_dump($v8->test); 21 | } catch (V8JsScriptException $e) { 22 | var_dump($e); 23 | } 24 | ?> 25 | ===EOF=== 26 | --EXPECTF-- 27 | object(stdClass)#%d (1) { 28 | ["foo"]=> 29 | object(V8Object)#%d (1) { 30 | ["hello"]=> 31 | string(5) "world" 32 | } 33 | } 34 | --- 35 | object(stdClass)#%d (1) { 36 | ["foo"]=> 37 | array(1) { 38 | ["hello"]=> 39 | string(5) "world" 40 | } 41 | } 42 | ===EOF=== 43 | -------------------------------------------------------------------------------- /tests/fatal_error_ignore_non_fatals.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Fatal Error handler to ignore warnings 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = function() { 11 | echo $bar; 12 | trigger_error('Foo Bar!', E_USER_WARNING); 13 | echo "blar foo\n"; 14 | }; 15 | 16 | $script = <<executeString($script); 23 | 24 | ?> 25 | ===EOF=== 26 | --EXPECTF-- 27 | %s: Undefined variable%sbar in %s%efatal_error_ignore_non_fatals.php on line 6 28 | 29 | Warning: Foo Bar! in %s%efatal_error_ignore_non_fatals.php on line 7 30 | blar foo 31 | ===EOF=== -------------------------------------------------------------------------------- /tests/fatal_error_no_uninstall_inner_frame.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Fatal Error handler not to uninstall on inner frames 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | bar = function() { 11 | echo "nothing.\n"; 12 | }; 13 | 14 | $js->foo = function() { 15 | global $js; 16 | // call to JS context, this must not touch the error handling context 17 | $js->executeString("PHP.bar();"); 18 | 19 | $bar = null; 20 | $bar->foo(); 21 | }; 22 | 23 | $js->executeString("PHP.foo();"); 24 | 25 | ?> 26 | ===EOF=== 27 | --EXPECTF-- 28 | nothing. 29 | 30 | Fatal error: Uncaught Error: Call to a member function foo() on null in %s%efatal_error_no_uninstall_inner_frame.php:15 31 | Stack trace: 32 | #0 [internal function]: {closur%s}() 33 | #1 [internal function]: Closure->__invoke() 34 | #2 %s%efatal_error_no_uninstall_inner_frame.php(18): V8Js->executeString('PHP.foo();') 35 | #3 {main} 36 | thrown in %s%efatal_error_no_uninstall_inner_frame.php on line 15 37 | -------------------------------------------------------------------------------- /tests/fatal_error_recursive.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Fatal Error with recursive executeString calls 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | baz = function() { 11 | $bar = null; 12 | $bar->bar(); 13 | }; 14 | 15 | $js->bar = function() { 16 | global $js; 17 | $js->executeString("PHP.baz();"); 18 | }; 19 | 20 | $js->foo = function() { 21 | global $js; 22 | $js->executeString("PHP.bar();"); 23 | }; 24 | 25 | $js->nofail = function() { 26 | echo "foo\n"; 27 | }; 28 | 29 | $js->executeString("PHP.nofail();"); 30 | $js->executeString("PHP.nofail(); PHP.foo();"); 31 | 32 | ?> 33 | ===EOF=== 34 | --EXPECTF-- 35 | foo 36 | foo 37 | 38 | Fatal error: Uncaught Error: Call to a member function bar() on null in %s%efatal_error_recursive.php:7 39 | Stack trace: 40 | #0 [internal function]: {closur%s}() 41 | #1 [internal function]: Closure->__invoke() 42 | #2 %s%efatal_error_recursive.php(12): V8Js->executeString('PHP.baz();') 43 | #3 [internal function]: {closur%s}() 44 | #4 [internal function]: Closure->__invoke() 45 | #5 %s%efatal_error_recursive.php(17): V8Js->executeString('PHP.bar();') 46 | #6 [internal function]: {closur%s}() 47 | #7 [internal function]: Closure->__invoke() 48 | #8 %s%efatal_error_recursive.php(25): V8Js->executeString('PHP.nofail(); P...') 49 | #9 {main} 50 | thrown in %s%efatal_error_recursive.php on line 7 51 | -------------------------------------------------------------------------------- /tests/fatal_error_rethrow.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Fatal Error rethrowing 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = function() { 11 | $bar = null; 12 | $bar->bar(); 13 | }; 14 | 15 | $script = <<executeString($script); 22 | 23 | ?> 24 | ===EOF=== 25 | --EXPECTF-- 26 | Fatal error: Uncaught Error: Call to a member function bar() on %s in %s%efatal_error_rethrow.php:7 27 | Stack trace: 28 | #0 [internal function]: {closur%s}() 29 | #1 [internal function]: Closure->__invoke() 30 | #2 %s%efatal_error_rethrow.php(16): V8Js->executeString(%s) 31 | #3 {main} 32 | thrown in %s%efatal_error_rethrow.php on line 7 33 | -------------------------------------------------------------------------------- /tests/fatal_error_uninstall_in_first_frame.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Fatal Error handler must be uninstalled when leaving outermost frame 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | bar = function() { 11 | echo "nothing.\n"; 12 | }; 13 | 14 | $js->foo = function() { 15 | global $js; 16 | // call to JS context, this must not touch the error handling context 17 | $js->executeString("PHP.bar();"); 18 | }; 19 | 20 | $js->executeString("PHP.foo();"); 21 | 22 | // V8JS handler must be removed, just throw error ... 23 | // if V8JS handler is not removed, it should trigger segfault in V8 :) 24 | $bar = null; 25 | $bar->foo(); 26 | 27 | ?> 28 | ===EOF=== 29 | --EXPECTF-- 30 | nothing. 31 | 32 | Fatal error: Uncaught Error: Call to a member function foo() on null in %s%efatal_error_uninstall_in_first_frame.php:20 33 | Stack trace: 34 | #0 {main} 35 | thrown in %s%efatal_error_uninstall_in_first_frame.php on line 20 36 | -------------------------------------------------------------------------------- /tests/fatal_error_v8function.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Function() : Handle fatal errors gracefully 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | bar(); // trigger fatal error 12 | } 13 | } 14 | 15 | $sandbox = new V8Js(); 16 | $sandbox->foo = new Foo(); 17 | 18 | $cb = $sandbox->executeString('(function() { PHP.foo.callback(); });'); 19 | $cb(); 20 | 21 | ?> 22 | ===EOF=== 23 | --EXPECTF-- 24 | goodbye cruel world! 25 | 26 | Fatal error: Uncaught Error: Call to undefined method Foo::bar() in %s%efatal_error_v8function.php:6 27 | Stack trace: 28 | #0 %s: Foo->callback() 29 | #1 %s%efatal_error_v8function.php(14): V8Function->V8Js::V8::Invoke() 30 | #2 {main} 31 | thrown in %s%efatal_error_v8function.php on line 6 32 | -------------------------------------------------------------------------------- /tests/function_call.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Call passed-back function (directly) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'basic.js'); 20 | echo $exports->hello()."\n"; 21 | 22 | ?> 23 | ===EOF=== 24 | --EXPECT-- 25 | hello 26 | ===EOF=== 27 | -------------------------------------------------------------------------------- /tests/function_passback.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Call passed-back function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'basic.js'); 20 | $vars = get_object_vars($exports); 21 | $v8->func = $vars['hello']; 22 | 23 | echo $v8->executeString('PHP.func();')."\n"; 24 | 25 | ?> 26 | ===EOF=== 27 | --EXPECT-- 28 | hello 29 | ===EOF=== 30 | -------------------------------------------------------------------------------- /tests/function_passback2.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Call passed-back function (property access) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'basic.js'); 20 | $v8->func = $exports->hello; 21 | 22 | echo $v8->executeString('PHP.func();')."\n"; 23 | 24 | ?> 25 | ===EOF=== 26 | --EXPECT-- 27 | hello 28 | ===EOF=== 29 | -------------------------------------------------------------------------------- /tests/function_properties.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Set property on function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'basic.js'); 20 | $exports->hello->foo = "bar"; 21 | $v8->func = $exports->hello; 22 | 23 | $v8->executeString('print(PHP.func.foo + "\n");'); 24 | 25 | ?> 26 | ===EOF=== 27 | --EXPECT-- 28 | bar 29 | ===EOF=== 30 | -------------------------------------------------------------------------------- /tests/generators_from_v8_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (foreach) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 26 | 27 | foreach($gen as $a) { 28 | var_dump($a); 29 | } 30 | 31 | ?> 32 | ===EOF=== 33 | --EXPECTF-- 34 | int(0) 35 | int(1) 36 | int(2) 37 | int(3) 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/generators_from_v8_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (direct) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 26 | 27 | var_dump($gen->current()); 28 | 29 | // JS generators don't have the key concept (-> just "false") 30 | var_dump($gen->key()); 31 | 32 | // fetching multiple times shouldn't leak 33 | var_dump($gen->current()); 34 | var_dump($gen->current()); 35 | 36 | $gen->next(); // 1 37 | var_dump($gen->current()); 38 | 39 | $gen->next(); // 2 40 | var_dump($gen->current()); 41 | 42 | $gen->next(); // 3 43 | var_dump($gen->current()); 44 | var_dump($gen->valid()); 45 | 46 | $gen->next(); // undef 47 | var_dump($gen->current()); 48 | var_dump($gen->valid()); 49 | 50 | ?> 51 | ===EOF=== 52 | --EXPECTF-- 53 | int(0) 54 | bool(false) 55 | int(0) 56 | int(0) 57 | int(1) 58 | int(2) 59 | int(3) 60 | bool(true) 61 | NULL 62 | bool(false) 63 | ===EOF=== 64 | -------------------------------------------------------------------------------- /tests/generators_from_v8_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (rewind) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 26 | 27 | foreach($gen as $a) { 28 | var_dump($a); 29 | } 30 | 31 | foreach($gen as $a) { 32 | var_dump($a); 33 | } 34 | 35 | ?> 36 | ===EOF=== 37 | --EXPECTF-- 38 | int(0) 39 | int(1) 40 | int(2) 41 | int(3) 42 | 43 | Fatal error: Uncaught V8JsException: V8Generator::rewind not supported by ES6 in %s 44 | Stack trace: 45 | #0 %s: V8Generator->rewind() 46 | #1 {main} 47 | thrown in %s on line 20 48 | -------------------------------------------------------------------------------- /tests/generators_from_v8_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (instantiate in PHP + foreach) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 26 | $gen = $TheGen(); 27 | 28 | foreach($gen as $a) { 29 | var_dump($a); 30 | } 31 | 32 | ?> 33 | ===EOF=== 34 | --EXPECTF-- 35 | int(0) 36 | int(1) 37 | int(2) 38 | int(3) 39 | ===EOF=== 40 | -------------------------------------------------------------------------------- /tests/generators_from_v8_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (instantiate in PHP + iterate in JS) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 26 | $gen = $TheGen(); 27 | 28 | $js = <<executeString($js); 36 | $fn($gen); 37 | 38 | ?> 39 | ===EOF=== 40 | --EXPECTF-- 41 | int(0) 42 | int(1) 43 | int(2) 44 | int(3) 45 | ===EOF=== 46 | -------------------------------------------------------------------------------- /tests/generators_from_v8_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (yield from) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 29 | 30 | yield from $jsGen; 31 | } 32 | 33 | $gen = PhpGen(); 34 | 35 | foreach($gen as $a) { 36 | var_dump($a); 37 | } 38 | 39 | ?> 40 | ===EOF=== 41 | --EXPECTF-- 42 | int(23) 43 | int(0) 44 | int(1) 45 | int(2) 46 | int(3) 47 | ===EOF=== 48 | -------------------------------------------------------------------------------- /tests/generators_from_v8_007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (throw JS) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 25 | 26 | foreach($gen as $a) { 27 | var_dump($a); 28 | } 29 | 30 | ?> 31 | ===EOF=== 32 | --EXPECTF-- 33 | int(23) 34 | 35 | Fatal error: Uncaught V8JsScriptException: %s Error: blar in %s 36 | Stack trace: 37 | #0 %s: V8Generator->next() 38 | #1 {main} 39 | thrown in %s 40 | -------------------------------------------------------------------------------- /tests/generators_from_v8_008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (throw PHP) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | getValue = function() { 25 | throw new \Exception('this shall not work'); 26 | }; 27 | $gen = $v8->executeString($js); 28 | 29 | foreach($gen as $a) { 30 | var_dump($a); 31 | } 32 | 33 | ?> 34 | ===EOF=== 35 | --EXPECTF-- 36 | int(23) 37 | 38 | Fatal error: Uncaught Exception: this shall not work in %s 39 | Stack trace: 40 | #0 [internal function]: {closur%s}() 41 | #1 [internal function]: Closure->__invoke() 42 | #2 %s: V8Generator->next() 43 | #3 {main} 44 | thrown in %s 45 | -------------------------------------------------------------------------------- /tests/generators_from_v8_009.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (fatal error) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | getValue = function() { 25 | @trigger_error("you're gonna fail now", E_USER_ERROR); 26 | }; 27 | $gen = $v8->executeString($js); 28 | 29 | foreach($gen as $a) { 30 | var_dump($a); 31 | } 32 | 33 | ?> 34 | ===EOF=== 35 | --EXPECTF-- 36 | int(23) 37 | 38 | Fatal error: you're gonna fail now in %s 39 | -------------------------------------------------------------------------------- /tests/generators_from_v8_010.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP (properties) 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 29 | 30 | var_dump($gen->foo); 31 | $gen->bar(); 32 | 33 | ?> 34 | ===EOF=== 35 | --EXPECT-- 36 | int(23) 37 | string(11) "Hello World" 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/generators_from_v8_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators V8 -> PHP 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($js); 27 | 28 | // just get the Generator itself -- it's just a normal JS function to us, 29 | // i.e. V8Js should create a V8Function object. 30 | $gen = $v8->executeString('(TheGen)'); 31 | var_dump($gen); 32 | 33 | // now instantiate the Generator and pass that back -- should become a 34 | // V8Generator object that implements the Iterator interface 35 | $gen = $v8->executeString('(TheGen())'); 36 | var_dump($gen); 37 | var_dump($gen instanceof Iterator); 38 | 39 | ?> 40 | ===EOF=== 41 | --EXPECTF-- 42 | object(V8Function)#%d (1) { 43 | ["theValue"]=> 44 | int(23) 45 | } 46 | object(V8Generator)#%d (0) { 47 | } 48 | bool(true) 49 | ===EOF=== 50 | -------------------------------------------------------------------------------- /tests/generators_to_v8_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators PHP -> V8 (instantite in JS) 3 | --SKIPIF-- 4 | 13 | --FILE-- 14 | Gen = function() { 24 | for($i = 0; $i < 4; $i ++) { 25 | yield $i; 26 | } 27 | }; 28 | 29 | $v8->executeString($js); 30 | 31 | ?> 32 | ===EOF=== 33 | --EXPECTF-- 34 | int(0) 35 | int(1) 36 | int(2) 37 | int(3) 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/generators_to_v8_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators PHP -> V8 (instantiate in JS, iterate in PHP) 3 | --SKIPIF-- 4 | 13 | --FILE-- 14 | Gen = function() { 18 | for($i = 0; $i < 4; $i ++) { 19 | yield $i; 20 | } 21 | }; 22 | 23 | $gen = $v8->executeString('(PHP.Gen())'); 24 | 25 | foreach($gen as $i) { 26 | var_dump($i); 27 | } 28 | 29 | ?> 30 | ===EOF=== 31 | --EXPECTF-- 32 | int(0) 33 | int(1) 34 | int(2) 35 | int(3) 36 | ===EOF=== 37 | -------------------------------------------------------------------------------- /tests/generators_to_v8_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators PHP -> V8 (instantiate in JS, iterate in PHP) 3 | --SKIPIF-- 4 | 13 | --FILE-- 14 | Gen = function() { 18 | for($i = 0; $i < 6; $i ++) { 19 | yield $i; 20 | } 21 | }; 22 | 23 | $JS = <<executeString($JS); 31 | 32 | foreach($gen as $i) { 33 | var_dump($i); 34 | } 35 | 36 | ?> 37 | ===EOF=== 38 | --EXPECTF-- 39 | object(Object)#%d (2) { 40 | ["value"] => 41 | int(0) 42 | ["done"] => 43 | bool(false) 44 | } 45 | object(Object)#%d (2) { 46 | ["value"] => 47 | int(1) 48 | ["done"] => 49 | bool(false) 50 | } 51 | int(2) 52 | int(3) 53 | int(4) 54 | int(5) 55 | ===EOF=== 56 | -------------------------------------------------------------------------------- /tests/generators_to_v8_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators PHP -> V8 (yield from) 3 | --SKIPIF-- 4 | 13 | --FILE-- 14 | fibs = FibonacciGenerator(); 28 | 29 | $JS = <<executeString($JS); 43 | ?> 44 | ===EOF=== 45 | --EXPECT-- 46 | int(23) 47 | int(42) 48 | int(1) 49 | int(1) 50 | int(2) 51 | int(3) 52 | int(5) 53 | int(8) 54 | int(13) 55 | int(21) 56 | ===EOF=== 57 | -------------------------------------------------------------------------------- /tests/generators_to_v8_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Generators PHP -> V8 3 | --SKIPIF-- 4 | 13 | --FILE-- 14 | gen = TheGenerator(); 36 | $gen = $v8->executeString($js); 37 | 38 | ?> 39 | ===EOF=== 40 | --EXPECTF-- 41 | int(0) 42 | int(1) 43 | int(2) 44 | int(3) 45 | int(0) 46 | int(1) 47 | int(2) 48 | int(3) 49 | ===EOF=== 50 | -------------------------------------------------------------------------------- /tests/get_accessor.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP variables via get accessor 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | display_errors=off 7 | --FILE-- 8 | '_SERVER', '$foobar' => 'myfoobar')); 19 | $a->executeString($JS, "test1.js"); 20 | 21 | $myfoobar = 'myfoobarfromphp'; 22 | 23 | $a->executeString($JS, "test2.js"); 24 | 25 | // Check that variables do not get in object .. 26 | var_dump($a->myfoobar, $a->foobar); 27 | 28 | ?> 29 | ===EOF=== 30 | --EXPECTF-- 31 | undefined 32 | undefined 33 | %d 34 | undefined 35 | undefined 36 | myfoobarfromphp 37 | %d 38 | myfoobarfromphp 39 | NULL 40 | NULL 41 | ===EOF=== 42 | -------------------------------------------------------------------------------- /tests/get_constructor.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Get constructor method 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo(23); 17 | 18 | $js = <<executeString($js); 27 | 28 | ?> 29 | ===EOF=== 30 | --EXPECTF-- 31 | called constructor: array(1) { 32 | [0]=> 33 | int(23) 34 | } 35 | object(Closure)#%d { 36 | function Foo() { [native code] } 37 | } 38 | called constructor: array(1) { 39 | [0]=> 40 | int(42) 41 | } 42 | ===EOF=== 43 | -------------------------------------------------------------------------------- /tests/global_object_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::executeString : Global scope links global object 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 19 | ?> 20 | ===EOF=== 21 | --EXPECT-- 22 | string(6) "object" 23 | bool(true) 24 | bool(true) 25 | ===EOF=== 26 | -------------------------------------------------------------------------------- /tests/has_property_after_dispose.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : has_property after dispose 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | x = $x; 13 | } 14 | } 15 | 16 | $v8 = new V8Js(); 17 | $v8->foo = $foo = new Foo(); 18 | 19 | $JS = <<< EOT 20 | PHP.foo.callMe({ bla: 23 }); 21 | 22 | EOT; 23 | 24 | $v8->executeString($JS, 'basic.js'); 25 | unset($v8); 26 | 27 | try { 28 | var_dump(property_exists($foo->x, 'bla')); 29 | } 30 | catch(V8JsException $e) { 31 | var_dump($e->getMessage()); 32 | } 33 | ?> 34 | ===EOF=== 35 | --EXPECTF-- 36 | bool(true) 37 | string(55) "Can't access V8Object after V8Js instance is destroyed!" 38 | ===EOF=== 39 | 40 | -------------------------------------------------------------------------------- /tests/inheritance_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js : class inheritance 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | ===EOF=== 21 | --EXPECT-- 22 | bool(true) 23 | bool(true) 24 | bool(true) 25 | bool(true) 26 | bool(true) 27 | bool(true) 28 | bool(true) 29 | bool(true) 30 | ===EOF=== 31 | -------------------------------------------------------------------------------- /tests/issue_116-v8function-injection.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #116 V8Function injection into other V8Js 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | name = 'A'; 11 | $b->name = 'B'; 12 | 13 | $a->b = $b; 14 | $a->executeString('PHP.b.test = function() { print("Hallo from within " + PHP.name + ".\\n"); };'); 15 | 16 | // in PHP we see the property 17 | var_dump($b->test); 18 | 19 | // we see (and can call) the function object in instance A 20 | print("in A:\n"); 21 | $a->executeString('PHP.b.test();'); 22 | 23 | // in B the function object is not available 24 | print("in B:\n"); 25 | $b->executeString('print(typeof PHP.b + "\\n");'); 26 | 27 | try { 28 | $b->executeString('PHP.test();'); 29 | } 30 | catch(Exception $e) { 31 | var_dump($e->getMessage()); 32 | } 33 | 34 | unset($a); 35 | unset($b); 36 | ?> 37 | ===EOF=== 38 | --EXPECTF-- 39 | Warning: V8Js::executeString(): V8Function object passed to wrong V8Js instance in %s on line %d 40 | object(V8Function)#%d (0) { 41 | } 42 | in A: 43 | Hallo from within A. 44 | in B: 45 | undefined 46 | string(%d) "V8Js::compileString():1: TypeError: %s is not a function" 47 | ===EOF=== 48 | -------------------------------------------------------------------------------- /tests/issue_127_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Function::__call() : Check v8::TryCatch behaviour 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | executeString('(function() { return oh; });'); 12 | 13 | try { 14 | $cb(); 15 | } catch(\Exception $e) { 16 | echo "caught: ".$e->getMessage()."\n"; 17 | } 18 | ?> 19 | ===EOF=== 20 | --EXPECT-- 21 | caught: V8Js::compileString():1: ReferenceError: oh is not defined 22 | ===EOF=== 23 | -------------------------------------------------------------------------------- /tests/issue_160_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #160 V8Function affected by V8Js::FLAG_FORCE_ARRAY 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'test', V8Js::FLAG_FORCE_ARRAY); 14 | 15 | var_dump($func); 16 | $func("Test-Foo Func Call\n"); 17 | ?> 18 | ===EOF=== 19 | --EXPECTF-- 20 | object(V8Function)#%d (0) { 21 | } 22 | Test-Foo Func Call 23 | ===EOF=== 24 | -------------------------------------------------------------------------------- /tests/issue_183_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access on derived classes (protected) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 22 | 23 | ?> 24 | ===EOF=== 25 | --EXPECTF-- 26 | Fatal error: Uncaught V8JsScriptException: V8Js::compileString():1: TypeError: %s in %s 27 | Stack trace: 28 | #0 %s: V8Js->executeString('PHP.hello();') 29 | #1 {main} 30 | thrown in %s on line 16 31 | -------------------------------------------------------------------------------- /tests/issue_183_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access on derived classes (private) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 22 | 23 | ?> 24 | ===EOF=== 25 | --EXPECTF-- 26 | Fatal error: Uncaught V8JsScriptException: V8Js::compileString():1: TypeError: %s in %s 27 | Stack trace: 28 | #0 %s: V8Js->executeString('PHP.hello();') 29 | #1 {main} 30 | thrown in %s on line 16 31 | -------------------------------------------------------------------------------- /tests/issue_183_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access on derived classes (V8Js methods) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 39 | 40 | ?> 41 | ===EOF=== 42 | --EXPECTF-- 43 | string(8) "function" 44 | string(9) "undefined" 45 | string(9) "undefined" 46 | string(9) "undefined" 47 | string(9) "undefined" 48 | string(9) "undefined" 49 | string(9) "undefined" 50 | string(9) "undefined" 51 | string(9) "undefined" 52 | string(9) "undefined" 53 | string(9) "undefined" 54 | string(6) "caught" 55 | ===EOF=== 56 | -------------------------------------------------------------------------------- /tests/issue_183_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access on derived classes (overridden V8Js methods) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 36 | 37 | ?> 38 | ===EOF=== 39 | --EXPECTF-- 40 | string(13) "executeString" 41 | string(8) "function" 42 | string(9) "undefined" 43 | string(6) "caught" 44 | ===EOF=== 45 | -------------------------------------------------------------------------------- /tests/issue_183_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access on derived classes (__sleep) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 17 | ===EOF=== 18 | --EXPECTF-- 19 | Fatal error: Cannot override final method V8Js::__sleep() in %s 20 | -------------------------------------------------------------------------------- /tests/issue_183_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access on derived classes (__wakeup) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 17 | ===EOF=== 18 | --EXPECTF-- 19 | Fatal error: Cannot override final method V8Js::__wakeup() in %s 20 | -------------------------------------------------------------------------------- /tests/issue_183_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access on derived classes 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 22 | 23 | ?> 24 | ===EOF=== 25 | --EXPECT-- 26 | Hello World 27 | ===EOF=== 28 | -------------------------------------------------------------------------------- /tests/issue_185_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #185 this on direct invocation of method 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 25 | 26 | // now fetch `inst` from V8 and call method from PHP 27 | $fn = $v8->executeString('(inst.tell)'); 28 | $fn(); 29 | ?> 30 | ===EOF=== 31 | --EXPECT-- 32 | NULL 33 | string(8) "function" 34 | NULL 35 | string(8) "function" 36 | ===EOF=== 37 | -------------------------------------------------------------------------------- /tests/issue_185_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #185 this on function invocation 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 19 | 20 | // now fetch `inst` from V8 and call method from PHP 21 | $fn = $v8->executeString('(fn)'); 22 | $fn(); 23 | ?> 24 | ===EOF=== 25 | --EXPECT-- 26 | string(8) "function" 27 | string(8) "function" 28 | ===EOF=== 29 | -------------------------------------------------------------------------------- /tests/issue_185_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #185 Wrong this on V8Object method invocation 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS); 23 | 24 | // now fetch `inst` from V8 and call method from PHP 25 | $inst = $v8->executeString('(inst)'); 26 | $inst->tell(); 27 | ?> 28 | ===EOF=== 29 | --EXPECT-- 30 | int(23) 31 | int(23) 32 | ===EOF=== 33 | -------------------------------------------------------------------------------- /tests/issue_246_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Handle Z_TYPE == IS_REFERENCE (issue #246) 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | 'ipsum']; 11 | array_walk_recursive($array, function (&$item) {}); 12 | $v8->some_array = $array; 13 | $v8->executeString('var_dump(PHP.some_array.lorem);'); 14 | ?> 15 | ===EOF=== 16 | --EXPECT-- 17 | string(5) "ipsum" 18 | ===EOF=== 19 | -------------------------------------------------------------------------------- /tests/issue_250_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #250 (early free of array) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | a->b->title = $title; 16 | } 17 | 18 | public function getData() { 19 | return $this->data; 20 | } 21 | 22 | public function getMeta() { 23 | return $this->meta; 24 | } 25 | 26 | public function setData($data=[]) { 27 | $this->data = $data; 28 | } 29 | 30 | public function setMeta($meta) { 31 | return; 32 | } 33 | } 34 | 35 | $v8 = new V8Js("server"); 36 | $code = <<< EOT 37 | var v1 = server.response.getData(); 38 | var v2 = server.response.getMeta(); 39 | 40 | server.response.setData({}); 41 | server.response.setTitle("ouch"); 42 | server.response.setMeta({}); 43 | EOT; 44 | 45 | $response = new TestObject(); 46 | 47 | $v8->response = $response; 48 | 49 | try { 50 | $result = $v8->executeString($code); 51 | var_dump($v8->response); 52 | } catch (V8JsException $e) { 53 | var_dump($e); 54 | } 55 | 56 | ?> 57 | ===EOF=== 58 | --EXPECTF-- 59 | Fatal error: Uncaught Error: Attempt to modify property "b" on null in %s%eissue_250_001.php:10 60 | Stack trace: 61 | #0 [internal function]: TestObject->setTitle('ouch') 62 | #1 %s%eissue_250_001.php(45): V8Js->executeString(' var v1 = se...') 63 | #2 {main} 64 | thrown in %s%eissue_250_001.php on line 10 65 | -------------------------------------------------------------------------------- /tests/issue_250_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #250 (early free of array) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | data = $data; 14 | } 15 | 16 | public function getData() { 17 | return $this->data; 18 | } 19 | 20 | } 21 | 22 | $v8 = new V8Js("server"); 23 | 24 | $code = <<< EOT 25 | server.response.setData({"new": true}); 26 | EOT; 27 | 28 | $v8->response = new TestObject(); 29 | 30 | try { 31 | $result = $v8->executeString($code, null, \V8Js::FLAG_FORCE_ARRAY | \V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 32 | var_dump($v8->response->getData()); 33 | } catch (V8JsException $e) { 34 | var_dump($e); 35 | } 36 | 37 | ?> 38 | ===EOF=== 39 | --EXPECT-- 40 | array(1) { 41 | ["new"]=> 42 | bool(true) 43 | } 44 | ===EOF=== 45 | -------------------------------------------------------------------------------- /tests/issue_306_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #306 V8 crashing on toLocaleString() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($expr); 12 | 13 | // V8 can be compiled with i18n support and without; 14 | // without i18n support however toLocaleString doesn't really work, 15 | // it just returns the date string... 16 | 17 | if ($result === 'October') { 18 | var_dump(true); 19 | } else { 20 | $expr = 'new Date("10/11/2009").toString();'; 21 | var_dump($v8->executeString($expr) === $result); 22 | } 23 | 24 | ?> 25 | ===EOF=== 26 | --EXPECT-- 27 | bool(true) 28 | ===EOF=== -------------------------------------------------------------------------------- /tests/issue_316_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #316 endless property iteration 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString('({test: "test"})'); 11 | foreach ($values as $value) { 12 | var_dump($value); 13 | } 14 | 15 | ?> 16 | ===EOF=== 17 | --EXPECT-- 18 | string(4) "test" 19 | ===EOF=== 20 | -------------------------------------------------------------------------------- /tests/issue_349_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8Js::setModuleNormaliser : Custom normalisation #005 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setModuleNormaliser(function ($base, $moduleName) { 11 | var_dump($base, $moduleName); 12 | if ($base == '' && $moduleName == './tags') { 13 | return ['./tags', 'index.js']; 14 | } 15 | if ($base == './tags' && $moduleName == './if.js') { 16 | return ['./tags', 'if.js']; 17 | } 18 | return [$base, $moduleName]; 19 | }); 20 | 21 | $v8->setModuleLoader(function ($moduleName) { 22 | print("setModuleLoader called for ".$moduleName."\n"); 23 | switch ($moduleName) { 24 | case './app.js': 25 | return "require('./tags')"; 26 | case './tags/index.js': 27 | return "require('./if.js')"; 28 | } 29 | }); 30 | 31 | $v8->executeString("require('./app.js')"); 32 | 33 | echo "------------------------------------------------\n"; 34 | 35 | $v8 = new V8Js(); 36 | 37 | $v8->setModuleNormaliser(function ($base, $moduleName) { 38 | var_dump($base, $moduleName); 39 | if ($base == '' && $moduleName == './tags') { 40 | return ['./tags', 'index.js']; 41 | } 42 | if ($base == './tags' && $moduleName == './if.js') { 43 | return ['./tags', 'if.js']; 44 | } 45 | return [$base, $moduleName]; 46 | }); 47 | 48 | $v8->setModuleLoader(function ($moduleName) { 49 | print("setModuleLoader called for ".$moduleName."\n"); 50 | switch ($moduleName) { 51 | case './app.js': 52 | return "require('./tags')()"; // different 53 | case './tags/index.js': 54 | return "module.exports = function() {require('./if.js')}"; // different 55 | } 56 | }); 57 | 58 | $v8->executeString("require('./app.js')"); 59 | 60 | ?> 61 | ===EOF=== 62 | --EXPECT-- 63 | string(0) "" 64 | string(8) "./app.js" 65 | setModuleLoader called for ./app.js 66 | string(0) "" 67 | string(6) "./tags" 68 | setModuleLoader called for ./tags/index.js 69 | string(6) "./tags" 70 | string(7) "./if.js" 71 | setModuleLoader called for ./tags/if.js 72 | ------------------------------------------------ 73 | string(0) "" 74 | string(8) "./app.js" 75 | setModuleLoader called for ./app.js 76 | string(0) "" 77 | string(6) "./tags" 78 | setModuleLoader called for ./tags/index.js 79 | string(6) "./tags" 80 | string(7) "./if.js" 81 | setModuleLoader called for ./tags/if.js 82 | ===EOF=== 83 | -------------------------------------------------------------------------------- /tests/issue_410_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Method access from multiple derived classes 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | Foo = new Foo(); 20 | $v8->Bar = new Bar(); 21 | 22 | $code = <<executeString($code); 30 | 31 | ?> 32 | ===EOF=== 33 | --EXPECTF-- 34 | object(Foo)#%d (1) { 35 | ["bla"] => 36 | object(Closure)#%d { 37 | function () { [native code] } 38 | } 39 | } 40 | print bla, called class: Foo 41 | object(Bar)#%d (1) { 42 | ["bla"] => 43 | object(Closure)#%d { 44 | function () { [native code] } 45 | } 46 | } 47 | print bla, called class: Bar 48 | ===EOF=== 49 | 50 | -------------------------------------------------------------------------------- /tests/issue_472_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #472 Destroy V8Js object which V8 isolate entered 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString(' 18 | (() => { 19 | myjs.bosh() 20 | }) 21 | '); 22 | 23 | $ret(); 24 | var_dump($ret); 25 | ?> 26 | ===EOF=== 27 | --EXPECTF-- 28 | object(V8Function)#%d (0) { 29 | } 30 | ===EOF=== 31 | -------------------------------------------------------------------------------- /tests/issue_497_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Issue #497 (segmentation fault calling PHP exit inside object function) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo(); 25 | 26 | $JS = <<< EOT 27 | PHP.foo.somecall(); 28 | PHP.foo.bar(); 29 | EOT; 30 | 31 | $v8->executeString($JS, '', \V8JS::FLAG_PROPAGATE_PHP_EXCEPTIONS); 32 | echo 'Not here!!'; 33 | ?> 34 | --EXPECTF-- 35 | string(12) "Foo somecall" 36 | string(7) "Foo bar" 37 | string(14) "Foo __destruct" 38 | -------------------------------------------------------------------------------- /tests/issue_504_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test empty() : Segmentation fault caused by 'empty' check on a V8Function object 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString(' 9 | a = { 10 | main: function() {} 11 | }; 12 | ', null, V8Js::FLAG_FORCE_ARRAY | V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 13 | 14 | if (!empty($r['main'])) { 15 | echo 'Ok' . PHP_EOL; 16 | } 17 | ?> 18 | --EXPECTF-- 19 | Ok 20 | 21 | -------------------------------------------------------------------------------- /tests/js-construct-basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Test PHP object construction controlled by JavaScript (simple) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | greeter = new Greeter(); 16 | $v8->executeString(' 17 | function JsGreeter() { }; 18 | JsGreeter.prototype.sayHello = function(a) { 19 | print("Hello " + a + "\n"); 20 | }; 21 | 22 | jsGreeter = new JsGreeter(); 23 | jsGreeter.sayHello("Paul"); 24 | 25 | jsGreeterNg = new jsGreeter.constructor(); 26 | jsGreeterNg.sayHello("George"); 27 | 28 | // ----- now the same using v8Js ----- 29 | 30 | PHP.greeter.sayHello("John"); 31 | 32 | var ngGreeter = new PHP.greeter.constructor(); 33 | ngGreeter.sayHello("Ringo"); 34 | '); 35 | ?> 36 | ===EOF=== 37 | --EXPECT-- 38 | Hello Paul 39 | Hello George 40 | Hello John 41 | Hello Ringo 42 | ===EOF=== 43 | -------------------------------------------------------------------------------- /tests/js-construct-direct-call.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Test PHP object construction controlled by JavaScript (non-construction call) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | greeter = new Greeter(); 16 | $v8->executeString(' 17 | function JsGreeter() { }; 18 | JsGreeter.prototype.sayHello = function(a) { 19 | print("Hello " + a + "\n"); 20 | }; 21 | 22 | jsGreeter = new JsGreeter(); 23 | jsGreeter.sayHello("Paul"); 24 | print(jsGreeter.constructor()); 25 | print("\n"); 26 | 27 | // ----- now the same using v8Js ----- 28 | 29 | PHP.greeter.sayHello("John"); 30 | print(PHP.greeter.constructor()); 31 | print("\n"); 32 | '); 33 | ?> 34 | ===EOF=== 35 | --EXPECT-- 36 | Hello Paul 37 | undefined 38 | Hello John 39 | undefined 40 | ===EOF=== 41 | -------------------------------------------------------------------------------- /tests/js-construct-protected-ctor.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Test PHP object construction controlled by JavaScript (protected ctor) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | _name = $name; 15 | } 16 | 17 | static function getInstance($name) { 18 | return new Greeter($name); 19 | } 20 | 21 | function sayHello() { 22 | echo "Hello ".$this->_name."\n"; 23 | } 24 | } 25 | 26 | $v8->greeter = Greeter::getInstance("John"); 27 | 28 | try { 29 | $v8->executeString(' 30 | PHP.greeter.sayHello(); 31 | 32 | var ngGreeter = new PHP.greeter.constructor("Ringo"); 33 | ngGreeter.sayHello(); 34 | ', 'ctor-test'); 35 | } catch(V8JsScriptException $e) { 36 | echo "caught js exception\n"; 37 | var_dump($e); 38 | } 39 | ?> 40 | ===EOF=== 41 | --EXPECTF-- 42 | ctor called (php) 43 | Hello John 44 | caught js exception 45 | object(V8JsScriptException)#%d (13) { 46 | ["message":protected]=> 47 | string(56) "ctor-test:4: Call to protected __construct() not allowed" 48 | ["string":"Exception":private]=> 49 | string(0) "" 50 | ["code":protected]=> 51 | int(0) 52 | ["file":protected]=> 53 | string(%d) "%s" 54 | ["line":protected]=> 55 | int(%d) 56 | ["trace":"Exception":private]=> 57 | array(1) { 58 | [0]=> 59 | array(6) { 60 | ["file"]=> 61 | string(%d) "%s" 62 | ["line"]=> 63 | int(%d) 64 | ["function"]=> 65 | string(13) "executeString" 66 | ["class"]=> 67 | string(4) "V8Js" 68 | ["type"]=> 69 | string(2) "->" 70 | ["args"]=> 71 | array(2) { 72 | [0]=> 73 | string(%d) " 74 | PHP.greeter.sayHello(); 75 | 76 | var ngGreeter = new PHP.greeter.constructor("Ringo"); 77 | ngGreeter.sayHello(); 78 | " 79 | [1]=> 80 | string(9) "ctor-test" 81 | } 82 | } 83 | } 84 | ["previous":"Exception":private]=> 85 | NULL 86 | ["JsFileName":protected]=> 87 | string(9) "ctor-test" 88 | ["JsLineNumber":protected]=> 89 | int(4) 90 | ["JsStartColumn":protected]=> 91 | int(18) 92 | ["JsEndColumn":protected]=> 93 | int(19) 94 | ["JsSourceLine":protected]=> 95 | string(55) " var ngGreeter = new PHP.greeter.constructor("Ringo");" 96 | ["JsTrace":protected]=> 97 | NULL 98 | } 99 | ===EOF=== 100 | 101 | -------------------------------------------------------------------------------- /tests/js-construct-with-ctor.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Test PHP object construction controlled by JavaScript (with ctor) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | _name = $name; 15 | } 16 | 17 | function sayHello() { 18 | echo "Hello ".$this->_name."\n"; 19 | } 20 | } 21 | 22 | $v8->greeter = new Greeter("John"); 23 | 24 | $v8->executeString(' 25 | function JsGreeter(name) { 26 | print("ctor called (js)\n"); 27 | this.name = name; 28 | }; 29 | 30 | JsGreeter.prototype.sayHello = function() { 31 | print("Hello " + this.name + "\n"); 32 | }; 33 | 34 | jsGreeter = new JsGreeter("Paul"); 35 | jsGreeter.sayHello(); 36 | 37 | jsGreeterNg = new jsGreeter.constructor("George"); 38 | jsGreeterNg.sayHello(); 39 | 40 | // ----- now the same using v8Js ----- 41 | 42 | PHP.greeter.sayHello(); 43 | 44 | var ngGreeter = new PHP.greeter.constructor("Ringo"); 45 | ngGreeter.sayHello(); 46 | '); 47 | ?> 48 | ===EOF=== 49 | --EXPECT-- 50 | ctor called (php) 51 | ctor called (js) 52 | Hello Paul 53 | ctor called (js) 54 | Hello George 55 | Hello John 56 | ctor called (php) 57 | Hello Ringo 58 | ===EOF=== 59 | 60 | -------------------------------------------------------------------------------- /tests/leak-php-object.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Test for leaked PHP object if passed back multiple times 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo(); 28 | $v8->executeString($js); 29 | unset($v8); 30 | 31 | ?> 32 | ===EOF=== 33 | --EXPECT-- 34 | destroyed 35 | ===EOF=== 36 | -------------------------------------------------------------------------------- /tests/long.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check long integer handling from PHP to JS 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | long = pow(2, 31); 10 | try { 11 | $v8->executeString('print(PHP.long); print("\n");'); 12 | } catch (V8JsScriptException $e) { 13 | var_dump($e->getMessage()); 14 | } 15 | 16 | $v8->long = pow(2, 31) + 1; 17 | try { 18 | $v8->executeString('print(PHP.long); print("\n");'); 19 | } catch (V8JsScriptException $e) { 20 | var_dump($e->getMessage()); 21 | } 22 | 23 | $v8->long = -pow(2, 31); 24 | try { 25 | $v8->executeString('print(PHP.long); print("\n");'); 26 | } catch (V8JsScriptException $e) { 27 | var_dump($e->getMessage()); 28 | } 29 | 30 | $v8->long = -pow(2, 31) - 1; 31 | try { 32 | $v8->executeString('print(PHP.long); print("\n");'); 33 | } catch (V8JsScriptException $e) { 34 | var_dump($e->getMessage()); 35 | } 36 | 37 | ?> 38 | ===EOF=== 39 | --EXPECT-- 40 | 2147483648 41 | 2147483649 42 | -2147483648 43 | -2147483649 44 | ===EOF=== 45 | -------------------------------------------------------------------------------- /tests/long_int64.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check long 64-bit export from PHP to JS 3 | --SKIPIF-- 4 | 9 | --FILE-- 10 | add = $addInt; 18 | $v8->p1 = 10; 19 | $v8->p2 = pow(2,45); 20 | 21 | var_dump($v8->p2); 22 | 23 | var_dump($v8->executeString(' 24 | var res = PHP.p1 + PHP.p2; 25 | "p1:" + PHP.p1 + 26 | ", p2:" + PHP.p2 + 27 | ", PHP.add(p1,p2)=" + PHP.add(PHP.p1, PHP.p2) + 28 | ", p1+p2=" + res + 29 | " -> " + (new Date(res)).toISOString(); 30 | ')); 31 | ?> 32 | ===EOF=== 33 | --EXPECT-- 34 | int(35184372088832) 35 | string(105) "p1:10, p2:35184372088832, PHP.add(p1,p2)=35184372088842, p1+p2=35184372088842 -> 3084-12-12T12:41:28.842Z" 36 | ===EOF=== 37 | -------------------------------------------------------------------------------- /tests/memory_limit.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Memory limit 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | executeString($JS, 'basic.js', V8Js::FLAG_NONE, 0, 10000000)); 28 | } catch (V8JsMemoryLimitException $e) { 29 | print get_class($e); print PHP_EOL; 30 | print $e->getMessage(); print PHP_EOL; 31 | } 32 | ?> 33 | ===EOF=== 34 | --EXPECT-- 35 | V8JsMemoryLimitException 36 | Script memory limit of 10000000 bytes exceeded 37 | ===EOF=== -------------------------------------------------------------------------------- /tests/multi-object.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Use multiple V8js instances with objects 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | _instNo = $num; 13 | } 14 | 15 | public function sayHello() { 16 | echo 'Hello World! This is instance '.$this->_instNo."\n"; 17 | } 18 | } 19 | 20 | $instances = array(); 21 | for($i = 0; $i < 5; $i ++) { 22 | $v8 = new V8Js(); 23 | $v8->test = new TestClass($i); 24 | $instances[] = $v8; 25 | } 26 | 27 | $JS = <<< EOT 28 | PHP.test.sayHello(); 29 | EOT; 30 | 31 | foreach($instances as $v8) { 32 | $v8->executeString($JS, 'basic.js'); 33 | } 34 | 35 | ?> 36 | ===EOF=== 37 | --EXPECT-- 38 | Hello World! This is instance 0 39 | Hello World! This is instance 1 40 | Hello World! This is instance 2 41 | Hello World! This is instance 3 42 | Hello World! This is instance 4 43 | ===EOF=== 44 | -------------------------------------------------------------------------------- /tests/multi.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Use multiple V8js instances 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString('var instNo = '.$i); 12 | $instances[] = $v8; 13 | } 14 | 15 | $JS = <<< EOT 16 | len = print('Hello' + ' ' + 'World! This is instance ' + instNo + "\\n"); 17 | len; 18 | EOT; 19 | 20 | foreach($instances as $v8) { 21 | $v8->executeString($JS, 'basic.js'); 22 | } 23 | 24 | ?> 25 | ===EOF=== 26 | --EXPECT-- 27 | Hello World! This is instance 0 28 | Hello World! This is instance 1 29 | Hello World! This is instance 2 30 | Hello World! This is instance 3 31 | Hello World! This is instance 4 32 | ===EOF=== 33 | -------------------------------------------------------------------------------- /tests/null_byte_string.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Pass strings with null-bytes 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString("String.fromCharCode(65)"); 11 | var_dump($foo); 12 | 13 | $foo = $v8js->executeString("String.fromCharCode(0)"); 14 | var_dump($foo); 15 | 16 | $v8js->foo = $foo; 17 | $v8js->executeString("var_dump(PHP.foo.length);"); 18 | $v8js->executeString("var_dump(PHP.foo);"); 19 | 20 | 21 | ?> 22 | ===EOF=== 23 | --EXPECT-- 24 | string(1) "A" 25 | string(1) "" 26 | int(1) 27 | string(1) "" 28 | ===EOF=== 29 | -------------------------------------------------------------------------------- /tests/object.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Object passed from PHP 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | ' + val + "\\n"); 14 | } 15 | } 16 | function test() 17 | { 18 | dump(PHP.myobj); 19 | PHP.myobj.foo = 'CHANGED'; 20 | PHP.myobj.mytest(); 21 | } 22 | test(); 23 | print(PHP.myobj.foo + "\\n"); 24 | EOT; 25 | 26 | // Test class 27 | class Testing 28 | { 29 | public $foo = 'ORIGINAL'; 30 | private $my_private = 'arf'; // Should not show in JS side 31 | protected $my_protected = 'argh'; // Should not show in JS side 32 | 33 | function mytest() { echo 'Here be monsters..', "\n"; } 34 | } 35 | 36 | $a = new V8Js(); 37 | $a->myobj = new Testing(); 38 | $a->executeString($JS, "test.js"); 39 | 40 | // Check that variable has not been modified 41 | var_dump($a->myobj->foo); 42 | ?> 43 | ===EOF=== 44 | --EXPECT-- 45 | mytest => function () { [native code] } 46 | $foo => ORIGINAL 47 | Here be monsters.. 48 | CHANGED 49 | string(7) "CHANGED" 50 | ===EOF=== 51 | -------------------------------------------------------------------------------- /tests/object_dom.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : DOM object passed from PHP 3 | --SKIPIF-- 4 | 10 | --FILE-- 11 | loadXML(''); 25 | 26 | $elements = $dom->getElementsByTagName('node'); 27 | echo 'php: ', $elements->length, "\n"; 28 | $node = $elements->item(0); 29 | echo "hasChildNodes: "; var_dump($node->hasChildNodes()); 30 | echo "hasAttribute('class'): "; var_dump($node->hasAttribute('class')); 31 | //var_dump($node); 32 | 33 | $a = new V8Js(); 34 | $a->dom = $dom; 35 | $a->test = array( 'length' => 1 ); 36 | $a->executeString($JS, "test.js"); 37 | 38 | ?> 39 | ===EOF=== 40 | --EXPECT-- 41 | php: 1 42 | hasChildNodes: bool(false) 43 | hasAttribute('class'): bool(true) 44 | js1: 1 45 | js2: 1 46 | hasChildNodes: bool(false) 47 | hasAttribute('class'): bool(true) 48 | ===EOF=== 49 | -------------------------------------------------------------------------------- /tests/object_passback.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Object passing PHP > JS > PHP 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | sayHello(); 23 | } 24 | } 25 | 26 | function callSingle($inst) { 27 | echo get_class($inst)."\n"; 28 | $inst->sayHello(); 29 | } 30 | } 31 | 32 | $v8 = new V8Js(); 33 | $v8->foo = new Foo(); 34 | 35 | $JS = <<< EOF 36 | var obj = PHP.foo.getBar(); 37 | PHP.foo.callMulti([obj]); 38 | PHP.foo.callMulti([obj]); 39 | PHP.foo.callSingle(obj); 40 | PHP.foo.callSingle(obj); 41 | 42 | obj = {}; 43 | obj.sayHello = function() { 44 | print("JavaScript Hello\\n"); 45 | }; 46 | 47 | PHP.foo.callMulti([obj]); 48 | PHP.foo.callMulti([obj]); 49 | PHP.foo.callSingle(obj); 50 | PHP.foo.callSingle(obj); 51 | EOF; 52 | 53 | $v8->executeString($JS); 54 | 55 | ?> 56 | ===EOF=== 57 | --EXPECT-- 58 | Bar 59 | Hello 60 | Bar 61 | Hello 62 | Bar 63 | Hello 64 | Bar 65 | Hello 66 | V8Object 67 | JavaScript Hello 68 | V8Object 69 | JavaScript Hello 70 | V8Object 71 | JavaScript Hello 72 | V8Object 73 | JavaScript Hello 74 | ===EOF=== 75 | -------------------------------------------------------------------------------- /tests/object_passback_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Object passing JS > PHP > JS 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | theApiCall = function() use ($v8) { 11 | return $v8->executeString('({ foo: 23 })'); 12 | }; 13 | 14 | $v8->executeString('var_dump(PHP.theApiCall().constructor.name);'); 15 | 16 | ?> 17 | ===EOF=== 18 | --EXPECT-- 19 | string(6) "Object" 20 | ===EOF=== 21 | -------------------------------------------------------------------------------- /tests/object_prototype.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Prototype with PHP callbacks 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | test = function ($value) { var_dump(func_get_args()); return 'HELLO: ' . md5($value); }; 33 | $a->test_two = new A(); 34 | $a->executeString($js, 'foo'); 35 | ?> 36 | ===EOF=== 37 | --EXPECTF-- 38 | array(2) { 39 | [0]=> 40 | string(6) "Foobar" 41 | [1]=> 42 | object(V8Object)#%d (2) { 43 | ["0"]=> 44 | string(3) "foo" 45 | ["1"]=> 46 | string(3) "bar" 47 | } 48 | } 49 | array(2) { 50 | [0]=> 51 | string(6) "Foobar" 52 | [1]=> 53 | object(V8Object)#%d (2) { 54 | ["0"]=> 55 | string(3) "foo" 56 | ["1"]=> 57 | string(3) "bar" 58 | } 59 | } 60 | array(2) { 61 | [0]=> 62 | string(5) "a,b,c" 63 | [1]=> 64 | object(V8Object)#%d (2) { 65 | ["0"]=> 66 | string(3) "foo" 67 | ["1"]=> 68 | string(3) "bar" 69 | } 70 | } 71 | array(2) { 72 | [0]=> 73 | string(5) "a,b,c" 74 | [1]=> 75 | object(V8Object)#%d (2) { 76 | ["0"]=> 77 | string(3) "foo" 78 | ["1"]=> 79 | string(3) "bar" 80 | } 81 | } 82 | ===EOF=== 83 | -------------------------------------------------------------------------------- /tests/object_reuse.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Test PHP object reusage 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 'Destructor did not mess anything!'); 14 | $v8->foobar = $foo; 15 | 16 | $v8->executeString("print(PHP.foobar['foo'] + '\\n');", "dtor.js"); 17 | 18 | ?> 19 | ===EOF=== 20 | --EXPECT-- 21 | Destructor did not mess anything! 22 | ===EOF=== 23 | -------------------------------------------------------------------------------- /tests/php_exceptions_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (repeated) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new \Foo(); 16 | 17 | $JS = <<< EOT 18 | try { 19 | PHP.foo.throwException(); 20 | // the exception should abort further execution, 21 | // hence the print must not pop up 22 | print("after throwException\\n"); 23 | } catch(e) { 24 | // JS should not catch in default mode 25 | print("JS caught exception"); 26 | } 27 | EOT; 28 | 29 | for($i = 0; $i < 5; $i ++) { 30 | var_dump($i); 31 | try { 32 | $v8->executeString($JS); 33 | } catch (Exception $e) { 34 | var_dump($e->getMessage()); 35 | } 36 | } 37 | ?> 38 | ===EOF=== 39 | --EXPECTF-- 40 | int(0) 41 | string(14) "Test-Exception" 42 | int(1) 43 | string(14) "Test-Exception" 44 | int(2) 45 | string(14) "Test-Exception" 46 | int(3) 47 | string(14) "Test-Exception" 48 | int(4) 49 | string(14) "Test-Exception" 50 | ===EOF=== 51 | -------------------------------------------------------------------------------- /tests/php_exceptions_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (multi-level) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new \Foo(); 22 | 23 | $work = $v8->executeString(<<getMessage()); 42 | } 43 | } 44 | ?> 45 | ===EOF=== 46 | --EXPECT-- 47 | int(0) 48 | string(14) "Test-Exception" 49 | int(1) 50 | recurse[0] ... 51 | string(14) "Test-Exception" 52 | int(2) 53 | recurse[1] ... 54 | recurse[0] ... 55 | string(14) "Test-Exception" 56 | int(3) 57 | recurse[2] ... 58 | recurse[1] ... 59 | recurse[0] ... 60 | string(14) "Test-Exception" 61 | int(4) 62 | recurse[3] ... 63 | recurse[2] ... 64 | recurse[1] ... 65 | recurse[0] ... 66 | string(14) "Test-Exception" 67 | ===EOF=== 68 | -------------------------------------------------------------------------------- /tests/php_exceptions_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (basic JS propagation) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new \Foo(); 16 | 17 | $JS = <<< EOT 18 | try { 19 | PHP.foo.throwException(); 20 | // the exception should abort further execution, 21 | // hence the print must not pop up 22 | print("after throwException\\n"); 23 | } catch(e) { 24 | print("JS caught exception!\\n"); 25 | var_dump(e.getMessage()); 26 | } 27 | EOT; 28 | 29 | $v8->executeString($JS, 'php_exceptions_003', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 30 | 31 | ?> 32 | ===EOF=== 33 | --EXPECTF-- 34 | JS caught exception! 35 | string(14) "Test-Exception" 36 | ===EOF=== 37 | -------------------------------------------------------------------------------- /tests/php_exceptions_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (PHP->JS->PHP back propagation) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new \Foo(); 16 | 17 | $JS = <<< EOT 18 | PHP.foo.throwException(); 19 | // the exception should abort further execution, 20 | // hence the print must not pop up 21 | print("after throwException\\n"); 22 | EOT; 23 | 24 | try { 25 | $v8->executeString($JS, 'php_exceptions_004', V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 26 | } 27 | catch(V8JsScriptException $e) { 28 | echo "Got V8JsScriptException\n"; 29 | var_dump($e->getPrevious()->getMessage()); 30 | } 31 | ?> 32 | ===EOF=== 33 | --EXPECTF-- 34 | Got V8JsScriptException 35 | string(14) "Test-Exception" 36 | ===EOF=== 37 | -------------------------------------------------------------------------------- /tests/php_exceptions_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (JS throw PHP-exception) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new \Foo(); 16 | 17 | $JS = <<< EOT 18 | var ex = PHP.foo.getException(); 19 | print("after getException\\n"); 20 | throw ex; 21 | print("after throw\\n"); 22 | EOT; 23 | 24 | try { 25 | $v8->executeString($JS, 'php_exceptions_005'); 26 | } 27 | catch(V8JsScriptException $e) { 28 | echo "Got V8JsScriptException\n"; 29 | var_dump($e->getMessage()); 30 | var_dump($e->getPrevious()->getMessage()); 31 | } 32 | ?> 33 | ===EOF=== 34 | --EXPECTF-- 35 | after getException 36 | Got V8JsScriptException 37 | string(%d) "php_exceptions_005:3: Exception: Test-Exception in %s 38 | Stack trace: 39 | #0 [internal function]: Foo->getException() 40 | #1 %s: V8Js->executeString('var ex = PHP.fo...', 'php_exceptions_...') 41 | #2 {main}" 42 | string(14) "Test-Exception" 43 | ===EOF=== 44 | -------------------------------------------------------------------------------- /tests/php_exceptions_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (JS throws normal PHP-object) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new \Foo(); 16 | 17 | $JS = <<< EOT 18 | var ex = PHP.foo.getNonExceptionObject(); 19 | print("after getNonExceptionObject\\n"); 20 | throw ex; 21 | print("after throw\\n"); 22 | EOT; 23 | 24 | try { 25 | $v8->executeString($JS, 'php_exceptions_006'); 26 | } 27 | catch(V8JsScriptException $e) { 28 | echo "Got V8JsScriptException\n"; 29 | var_dump($e->getMessage()); 30 | // previous exception should be NULL, as it is *not* a php exception 31 | var_dump($e->getPrevious()); 32 | } 33 | ?> 34 | ===EOF=== 35 | --EXPECTF-- 36 | after getNonExceptionObject 37 | Got V8JsScriptException 38 | string(%d) "php_exceptions_006:3: [object %s]" 39 | NULL 40 | ===EOF=== 41 | -------------------------------------------------------------------------------- /tests/php_exceptions_007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (throwed inside magic method) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | triggerException(); 18 | } 19 | } 20 | 21 | function execute($code, $flags = V8Js::FLAG_NONE) { 22 | $js = new V8Js(); 23 | $js->output = new stdClass(); 24 | $js->SomeClassInstance = new SomeClass(); 25 | try { 26 | $js->executeString(" 27 | try { 28 | $code 29 | } catch(e) { 30 | PHP.output.result = 'Caught exception at javascript level : ' + e.getMessage(); 31 | } 32 | ", '', $flags); 33 | print($js->output->result.PHP_EOL); 34 | } catch (Exception $e) { 35 | print( "Caught exception at php level : ".$e->getMessage().PHP_EOL); 36 | } 37 | } 38 | 39 | execute("PHP.SomeClassInstance.triggerException();"); 40 | execute("PHP.SomeClassInstance.someMethod(PHP.SomeClassInstance.TriggerMagicMethod);"); 41 | execute("PHP.SomeClassInstance.TriggerMagicMethod;"); 42 | execute("PHP.SomeClassInstance.triggerException();", V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 43 | execute("PHP.SomeClassInstance.someMethod(PHP.SomeClassInstance.TriggerMagicMethod);", V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 44 | execute("PHP.SomeClassInstance.TriggerMagicMethod;", V8Js::FLAG_PROPAGATE_PHP_EXCEPTIONS); 45 | ?> 46 | ===EOF=== 47 | --EXPECTF-- 48 | Caught exception at php level : Some exception 49 | Caught exception at php level : Some exception 50 | Caught exception at php level : Some exception 51 | Caught exception at javascript level : Some exception 52 | Caught exception at javascript level : Some exception 53 | Caught exception at javascript level : Some exception 54 | ===EOF=== 55 | -------------------------------------------------------------------------------- /tests/php_exceptions_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : PHP Exception handling (basic) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new \Foo(); 16 | 17 | $JS = <<< EOT 18 | try { 19 | PHP.foo.throwException(); 20 | // the exception should abort further execution, 21 | // hence the print must not pop up 22 | print("after throwException\\n"); 23 | } catch(e) { 24 | // JS should not catch in default mode 25 | print("JS caught exception"); 26 | } 27 | EOT; 28 | 29 | try { 30 | $v8->executeString($JS); 31 | } catch (Exception $e) { 32 | var_dump($e->getMessage()); 33 | var_dump($e->getFile()); 34 | var_dump($e->getLine()); 35 | } 36 | ?> 37 | ===EOF=== 38 | --EXPECTF-- 39 | string(14) "Test-Exception" 40 | string(%d) "%sphp_exceptions_basic.php" 41 | int(5) 42 | ===EOF=== 43 | -------------------------------------------------------------------------------- /tests/property_visibility-delete.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility - delete 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | $a); 16 | } 17 | } 18 | 19 | $js = new V8Js(); 20 | $js->foo = new Foo(); 21 | 22 | $script = <<foo->dump('privBar'); 45 | $js->foo->dump('protBar'); 46 | $js->foo->dump('pubBar'); 47 | 48 | echo "--- JS ---\n"; 49 | $js->executeString($script); 50 | 51 | echo "--- PHP ---\n"; 52 | $js->foo->dump('privBar'); 53 | $js->foo->dump('protBar'); 54 | $js->foo->dump('pubBar'); 55 | 56 | ?> 57 | ===EOF=== 58 | --EXPECT-- 59 | string(7) "privBar" 60 | string(7) "protBar" 61 | string(6) "pubBar" 62 | --- JS --- 63 | NULL 64 | NULL 65 | int(42) 66 | NULL 67 | NULL 68 | NULL 69 | string(6) "pubBar" 70 | NULL 71 | --- PHP --- 72 | string(7) "privBar" 73 | string(7) "protBar" 74 | NULL 75 | ===EOF=== 76 | -------------------------------------------------------------------------------- /tests/property_visibility-enumerate.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility - enumerate 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | $value) { 15 | echo("$key => "); 16 | var_dump($value); 17 | } 18 | } 19 | } 20 | 21 | $js = new V8Js(); 22 | $js->foo = new Foo(); 23 | 24 | $script = <<executeString($script); 42 | 43 | echo "--- PHP ---\n"; 44 | $js->foo->dump(); 45 | ?> 46 | ===EOF=== 47 | --EXPECT-- 48 | string(4) "dump" 49 | string(8) "function" 50 | string(7) "$pubBar" 51 | string(6) "pubBar" 52 | --- PHP --- 53 | privBar => string(7) "privBar" 54 | protBar => string(7) "protBar" 55 | pubBar => string(6) "pubBar" 56 | ===EOF=== 57 | -------------------------------------------------------------------------------- /tests/property_visibility-has-property.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility - has property 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo(); 17 | 18 | $script = <<executeString($script); 38 | 39 | ?> 40 | ===EOF=== 41 | --EXPECT-- 42 | bool(false) 43 | bool(false) 44 | bool(true) 45 | bool(false) 46 | bool(true) 47 | bool(true) 48 | bool(true) 49 | bool(true) 50 | ===EOF=== 51 | -------------------------------------------------------------------------------- /tests/property_visibility-set.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility - set 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | privBar); 16 | var_dump($this->protBar); 17 | var_dump($this->pubBar); 18 | var_dump($this->unknownBar); 19 | } 20 | } 21 | 22 | $js = new V8Js(); 23 | $js->foo = new Foo(); 24 | 25 | $script = <<executeString($script); 40 | $js->foo->dump(); 41 | ?> 42 | ===EOF=== 43 | --EXPECT-- 44 | string(6) "jsPriv" 45 | string(6) "jsProt" 46 | string(5) "jsPub" 47 | string(9) "jsUnknown" 48 | string(7) "privBar" 49 | string(7) "protBar" 50 | string(5) "jsPub" 51 | string(9) "jsUnknown" 52 | ===EOF=== 53 | -------------------------------------------------------------------------------- /tests/property_visibility.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo(); 17 | 18 | $script = <<executeString($script); 27 | ?> 28 | ===EOF=== 29 | --EXPECT-- 30 | NULL 31 | NULL 32 | string(6) "pubBar" 33 | ===EOF=== 34 | -------------------------------------------------------------------------------- /tests/property_visibility__get.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility __get 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo(); 23 | 24 | $script = <<executeString($script); 34 | ?> 35 | ===EOF=== 36 | --EXPECT-- 37 | string(10) "unknownBar" 38 | int(42) 39 | string(7) "privBar" 40 | int(42) 41 | string(7) "protBar" 42 | int(42) 43 | string(6) "pubBar" 44 | ===EOF=== 45 | -------------------------------------------------------------------------------- /tests/property_visibility__set.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility __set 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | privBar); 19 | var_dump($this->protBar); 20 | var_dump($this->pubBar); 21 | var_dump(isset($this->unknownBar)); 22 | var_dump(isset($this->phpBar)); 23 | } 24 | } 25 | 26 | $js = new V8Js(); 27 | 28 | $js->foo = new Foo(); 29 | $js->foo->protBar = 'piet'; 30 | $js->foo->phpBar = 'phpValue'; 31 | 32 | $script = <<executeString($script); 48 | $js->foo->dump(); 49 | ?> 50 | ===EOF=== 51 | --EXPECT-- 52 | protBar <- piet 53 | phpBar <- phpValue 54 | privBar <- jsPriv 55 | protBar <- jsProt 56 | unknownBar <- jsUnknown 57 | NULL 58 | NULL 59 | string(5) "jsPub" 60 | NULL 61 | NULL 62 | string(7) "privBar" 63 | string(7) "protBar" 64 | string(5) "jsPub" 65 | bool(false) 66 | bool(false) 67 | ===EOF=== 68 | -------------------------------------------------------------------------------- /tests/pthreads_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Pthreads test #1 3 | --SKIPIF-- 4 | 10 | --FILE-- 11 | executeString('(11 + 12)') != 23) { 19 | throw new \Exception('fail'); 20 | } 21 | } 22 | } 23 | 24 | $foo = new Workhorse('foo'); 25 | $bar = new Workhorse('bar'); 26 | 27 | $foo->start(); 28 | $bar->start(); 29 | 30 | $foo->join(); 31 | $bar->join(); 32 | ?> 33 | ===EOF=== 34 | --EXPECT-- 35 | ===EOF=== 36 | -------------------------------------------------------------------------------- /tests/regression_121.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Regression #121 Z_ADDREF_P 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | blar = new stdClass(); 10 | 11 | $js = <<executeString($js); 21 | ?> 22 | ===EOF=== 23 | --EXPECT-- 24 | Hello World! 25 | ===EOF=== 26 | -------------------------------------------------------------------------------- /tests/return_this_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : return this (aka fluent setters, JS-side) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($js); 28 | 29 | $ret = $bar->setFoo(23)->setBar(42); 30 | var_dump($bar === $ret); 31 | 32 | $v8->executeString('var_dump(theBar);'); 33 | 34 | ?> 35 | ===EOF=== 36 | --EXPECTF-- 37 | bool(true) 38 | object(Bar)#%d (2) { 39 | ["foo"] => 40 | int(23) 41 | ["bar"] => 42 | int(42) 43 | } 44 | ===EOF=== 45 | -------------------------------------------------------------------------------- /tests/return_this_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : return $this (aka fluent setters) 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = $value; 15 | return $this; 16 | } 17 | 18 | public function setBar($value) 19 | { 20 | $this->bar = $value; 21 | return $this; 22 | } 23 | } 24 | 25 | $v8 = new V8Js(); 26 | $v8->theFoo = new Foo(); 27 | 28 | $v8->executeString(<<theFoo); 38 | 39 | ?> 40 | ===EOF=== 41 | --EXPECTF-- 42 | bool(true) 43 | bool(true) 44 | object(Foo)#%d (2) { 45 | ["foo":"Foo":private]=> 46 | int(23) 47 | ["bar":"Foo":private]=> 48 | int(42) 49 | } 50 | ===EOF=== 51 | -------------------------------------------------------------------------------- /tests/return_value.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Return values 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | date.timezone=UTC 7 | --FILE-- 8 | myobj = new Testing(); 29 | var_dump($a->executeString($JS, "test.js")); 30 | var_dump($a->executeString("test(PHP.myobj);", "test1.js")); 31 | var_dump($a->executeString("test(new Array(1,2,3));", "test2.js")); 32 | var_dump($a->executeString("test(new Array('foo', 'bar'));", "test3.js")); 33 | var_dump($a->executeString("test(new Array('foo', 'bar'));", "test3.js")); 34 | $date = $a->executeString("test(new Date('September 8, 1975 09:00:00 GMT'));", "test4.js"); 35 | $date->setTimeZone(new DateTimeZone('GMT')); 36 | echo $date->format(DateTime::RFC1123), "\n"; 37 | var_dump($a->executeString("test(1234567890);", "test5.js")); 38 | var_dump($a->executeString("test(123.456789);", "test6.js")); 39 | var_dump($a->executeString("test('some string');", "test7.js")); 40 | var_dump($a->executeString("test(true);", "test8.js")); 41 | var_dump($a->executeString("test(false);", "test9.js")); 42 | ?> 43 | ===EOF=== 44 | --EXPECTF-- 45 | NULL 46 | object(Testing)#%d (3) { 47 | ["foo"]=> 48 | string(8) "ORIGINAL" 49 | ["my_private":"Testing":private]=> 50 | string(3) "arf" 51 | ["my_protected":protected]=> 52 | string(4) "argh" 53 | } 54 | array(3) { 55 | [0]=> 56 | int(1) 57 | [1]=> 58 | int(2) 59 | [2]=> 60 | int(3) 61 | } 62 | array(2) { 63 | [0]=> 64 | string(3) "foo" 65 | [1]=> 66 | string(3) "bar" 67 | } 68 | array(2) { 69 | [0]=> 70 | string(3) "foo" 71 | [1]=> 72 | string(3) "bar" 73 | } 74 | Mon, 08 Sep 1975 09:00:00 +0000 75 | int(1234567890) 76 | float(123.456789) 77 | string(11) "some string" 78 | bool(true) 79 | bool(false) 80 | ===EOF=== 81 | -------------------------------------------------------------------------------- /tests/serialize_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test serialize(V8Object) : __sleep and __wakeup throw 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString('({ foo: 23 })'); 10 | 11 | var_dump($obj); 12 | 13 | try { 14 | $stored = serialize($obj); 15 | } 16 | catch(\V8JsException $e) { 17 | var_dump(get_class($e)); 18 | var_dump($e->getMessage()); 19 | } 20 | 21 | $stored = 'O:8:"V8Object":0:{}'; 22 | 23 | try { 24 | $obj2 = unserialize($stored); 25 | } 26 | catch(\V8JsException $e) { 27 | var_dump(get_class($e)); 28 | var_dump($e->getMessage()); 29 | } 30 | 31 | var_dump(isset($obj2)); 32 | 33 | $stored = 'O:8:"V8Object":1:{s:3:"foo";i:23;}'; 34 | 35 | try { 36 | $obj = unserialize($stored); 37 | } 38 | catch(\V8JsException $e) { 39 | var_dump(get_class($e)); 40 | var_dump($e->getMessage()); 41 | } 42 | 43 | var_dump(isset($obj3)); 44 | 45 | ?> 46 | ===EOF=== 47 | --EXPECT-- 48 | object(V8Object)#2 (1) { 49 | ["foo"]=> 50 | int(23) 51 | } 52 | string(13) "V8JsException" 53 | string(54) "You cannot serialize or unserialize V8Object instances" 54 | string(13) "V8JsException" 55 | string(54) "You cannot serialize or unserialize V8Object instances" 56 | bool(false) 57 | string(13) "V8JsException" 58 | string(54) "You cannot serialize or unserialize V8Object instances" 59 | bool(false) 60 | ===EOF=== 61 | -------------------------------------------------------------------------------- /tests/serialize_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test serialize(V8Function) : __sleep and __wakeup throw 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString('(function() { })'); 10 | 11 | var_dump($obj); 12 | 13 | try { 14 | $stored = serialize($obj); 15 | } 16 | catch(\V8JsException $e) { 17 | var_dump(get_class($e)); 18 | var_dump($e->getMessage()); 19 | } 20 | 21 | $stored = 'O:10:"V8Function":0:{}'; 22 | 23 | try { 24 | $obj2 = unserialize($stored); 25 | } 26 | catch(\V8JsException $e) { 27 | var_dump(get_class($e)); 28 | var_dump($e->getMessage()); 29 | } 30 | 31 | var_dump(isset($obj2)); 32 | 33 | $stored = 'O:10:"V8Function":1:{s:3:"foo";i:23;}'; 34 | 35 | try { 36 | $obj = unserialize($stored); 37 | } 38 | catch(\V8JsException $e) { 39 | var_dump(get_class($e)); 40 | var_dump($e->getMessage()); 41 | } 42 | 43 | var_dump(isset($obj3)); 44 | 45 | ?> 46 | ===EOF=== 47 | --EXPECT-- 48 | object(V8Function)#2 (0) { 49 | } 50 | string(13) "V8JsException" 51 | string(56) "You cannot serialize or unserialize V8Function instances" 52 | string(13) "V8JsException" 53 | string(56) "You cannot serialize or unserialize V8Function instances" 54 | bool(false) 55 | string(13) "V8JsException" 56 | string(56) "You cannot serialize or unserialize V8Function instances" 57 | bool(false) 58 | ===EOF=== 59 | -------------------------------------------------------------------------------- /tests/serialize_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test serialize(V8Js) : __sleep and __wakeup throw 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getMessage()); 16 | } 17 | 18 | $stored = 'O:4:"V8Js":0:{}'; 19 | 20 | try { 21 | $b = unserialize($stored); 22 | } 23 | catch(\V8JsException $e) { 24 | var_dump(get_class($e)); 25 | var_dump($e->getMessage()); 26 | } 27 | 28 | $stored = 'O:4:"V8Js":1:{s:3:"foo";i:23;}'; 29 | 30 | try { 31 | $b = unserialize($stored); 32 | } 33 | catch(\V8JsException $e) { 34 | var_dump(get_class($e)); 35 | var_dump($e->getMessage()); 36 | } 37 | 38 | ?> 39 | ===EOF=== 40 | --EXPECT-- 41 | string(13) "V8JsException" 42 | string(50) "You cannot serialize or unserialize V8Js instances" 43 | string(13) "V8JsException" 44 | string(50) "You cannot serialize or unserialize V8Js instances" 45 | string(13) "V8JsException" 46 | string(50) "You cannot serialize or unserialize V8Js instances" 47 | ===EOF=== 48 | -------------------------------------------------------------------------------- /tests/set_average_object_size_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setAverageObjectSize() : Average object size can be set on V8Js object 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setAverageObjectSize(32768); 9 | 10 | // there's no API to query the currently announced external memory allocation, 11 | // hence not much we can do here... 12 | 13 | ?> 14 | ===EOF=== 15 | --EXPECT-- 16 | ===EOF=== 17 | -------------------------------------------------------------------------------- /tests/set_memory_limit_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setMemoryLimit() : Memory limit applied to V8Function calls 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | setMemoryLimit(10000000); 30 | 31 | $func = $v8->executeString($JS); 32 | var_dump($func); 33 | 34 | try { 35 | $func(); 36 | } catch (V8JsMemoryLimitException $e) { 37 | print get_class($e); print PHP_EOL; 38 | print $e->getMessage(); print PHP_EOL; 39 | } 40 | ?> 41 | ===EOF=== 42 | --EXPECTF-- 43 | object(V8Function)#%d (0) { 44 | } 45 | V8JsMemoryLimitException 46 | Script memory limit of 10000000 bytes exceeded 47 | ===EOF=== 48 | -------------------------------------------------------------------------------- /tests/set_memory_limit_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setMemoryLimit() : Memory limit can be imposed later 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | imposeMemoryLimit = function() use ($v8) { 32 | $v8->setMemoryLimit(10000000); 33 | }; 34 | 35 | $func = $v8->executeString($JS); 36 | var_dump($func); 37 | 38 | try { 39 | $func(); 40 | } catch (V8JsMemoryLimitException $e) { 41 | print get_class($e); print PHP_EOL; 42 | print $e->getMessage(); print PHP_EOL; 43 | } 44 | ?> 45 | ===EOF=== 46 | --EXPECTF-- 47 | object(V8Function)#%d (0) { 48 | } 49 | V8JsMemoryLimitException 50 | Script memory limit of 10000000 bytes exceeded 51 | ===EOF=== 52 | -------------------------------------------------------------------------------- /tests/set_memory_limit_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setMemoryLimit() : Memory limit can be set on V8Js object 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | setMemoryLimit(10000000); 26 | 27 | try { 28 | var_dump($v8->executeString($JS, 'basic.js')); 29 | } catch (V8JsMemoryLimitException $e) { 30 | print get_class($e); print PHP_EOL; 31 | print $e->getMessage(); print PHP_EOL; 32 | } 33 | ?> 34 | ===EOF=== 35 | --EXPECT-- 36 | V8JsMemoryLimitException 37 | Script memory limit of 10000000 bytes exceeded 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/set_time_limit_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setTimeLimit() : Time limit applied to V8Function calls 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | setTimeLimit(100); 26 | 27 | $func = $v8->executeString($JS); 28 | var_dump($func); 29 | 30 | try { 31 | $func(); 32 | } catch (V8JsTimeLimitException $e) { 33 | print get_class($e); print PHP_EOL; 34 | print $e->getMessage(); print PHP_EOL; 35 | } 36 | ?> 37 | ===EOF=== 38 | --EXPECTF-- 39 | object(V8Function)#%d (0) { 40 | } 41 | V8JsTimeLimitException 42 | Script time limit of 100 milliseconds exceeded 43 | ===EOF=== 44 | -------------------------------------------------------------------------------- /tests/set_time_limit_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setTimeLimit() : Time limit can be changed 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | setTimeLimit(200); 32 | 33 | $v8->incrTimeLimit = function() use ($v8) { 34 | $v8->setTimeLimit(500); 35 | }; 36 | 37 | $func = $v8->executeString($JS); 38 | var_dump($func); 39 | 40 | try { 41 | $func(); 42 | } catch (V8JsTimeLimitException $e) { 43 | print get_class($e); print PHP_EOL; 44 | print $e->getMessage(); print PHP_EOL; 45 | } 46 | ?> 47 | ===EOF=== 48 | --EXPECTF-- 49 | object(V8Function)#%d (0) { 50 | } 51 | V8JsTimeLimitException 52 | Script time limit of 500 milliseconds exceeded 53 | ===EOF=== 54 | -------------------------------------------------------------------------------- /tests/set_time_limit_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setTimeLimit() : Time limit can be imposed later on 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | imposeTimeLimit = function() use ($v8) { 27 | $v8->setTimeLimit(100); 28 | }; 29 | 30 | $func = $v8->executeString($JS); 31 | var_dump($func); 32 | 33 | try { 34 | $func(); 35 | } catch (V8JsTimeLimitException $e) { 36 | print get_class($e); print PHP_EOL; 37 | print $e->getMessage(); print PHP_EOL; 38 | } 39 | ?> 40 | ===EOF=== 41 | --EXPECTF-- 42 | object(V8Function)#%d (0) { 43 | } 44 | V8JsTimeLimitException 45 | Script time limit of 100 milliseconds exceeded 46 | ===EOF=== 47 | -------------------------------------------------------------------------------- /tests/set_time_limit_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setTimeLimit() : Time limit can be prolonged 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | 10ms in the loop, i.e. at least 750ms; hence 17 | * it should be killed if prolonging doesn't work. */ 18 | for (var j = 0; j < 30; ++j) { 19 | PHP.prolongTimeLimit(); 20 | var start = (new Date()).getTime(); 21 | var encoded = encodeURI(text); 22 | 23 | while ((new Date()).getTime() - start < 10) { 24 | /* pass about 10ms in the loop, then prolong */ 25 | var encoded = encodeURI(text); 26 | } 27 | } 28 | EOT; 29 | 30 | $v8 = new V8Js(); 31 | $v8->setTimeLimit(300); 32 | 33 | $v8->prolongTimeLimit = function() use ($v8) { 34 | $v8->setTimeLimit(300); 35 | }; 36 | 37 | $v8->executeString($JS); 38 | ?> 39 | ===EOF=== 40 | --EXPECTF-- 41 | ===EOF=== 42 | -------------------------------------------------------------------------------- /tests/set_time_limit_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::setTimeLimit() : Time limit can be set on V8Js object 3 | --SKIPIF-- 4 | 11 | --FILE-- 12 | setTimeLimit(100); 23 | 24 | try { 25 | var_dump($v8->executeString($JS, 'basic.js')); 26 | } catch (V8JsTimeLimitException $e) { 27 | print get_class($e); print PHP_EOL; 28 | print $e->getMessage(); print PHP_EOL; 29 | } 30 | ?> 31 | ===EOF=== 32 | --EXPECT-- 33 | V8JsTimeLimitException 34 | Script time limit of 100 milliseconds exceeded 35 | ===EOF=== 36 | -------------------------------------------------------------------------------- /tests/skipif.inc: -------------------------------------------------------------------------------- 1 | 11 | --FILE-- 12 | executeString($JS, 'basic.js', V8Js::FLAG_NONE, 1000)); 25 | } catch (V8JsTimeLimitException $e) { 26 | print get_class($e); print PHP_EOL; 27 | print $e->getMessage(); print PHP_EOL; 28 | } 29 | ?> 30 | ===EOF=== 31 | --EXPECT-- 32 | V8JsTimeLimitException 33 | Script time limit of 1000 milliseconds exceeded 34 | ===EOF=== 35 | -------------------------------------------------------------------------------- /tests/timezones.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check timezone handling 3 | --SKIPIF-- 4 | 10 | --FILE-- 11 | executeString('print (new Date("Thu, 20 Mar 2014 09:03:24 +0000")).toString();'); 18 | echo "\n"; 19 | } catch (V8JsScriptException $e) { 20 | var_dump($e->getMessage()); 21 | } 22 | 23 | try { 24 | putenv('TZ=America/New_York'); 25 | $v8->executeString('print (new Date("Thu, 20 Mar 2014 09:03:24 +0000")).toString();'); 26 | echo "\n"; 27 | } catch (V8JsScriptException $e) { 28 | var_dump($e->getMessage()); 29 | } 30 | 31 | try { 32 | putenv('TZ=Europe/Helsinki'); 33 | $v8->executeString('print (new Date("Thu, 20 Mar 2014 09:03:24 +0000")).toString();'); 34 | echo "\n"; 35 | } catch (V8JsScriptException $e) { 36 | var_dump($e->getMessage()); 37 | } 38 | ?> 39 | ===EOF=== 40 | --EXPECT-- 41 | Thu Mar 20 2014 11:03:24 GMT+0200 (Eastern European Standard Time) 42 | Thu Mar 20 2014 05:03:24 GMT-0400 (Eastern Daylight Time) 43 | Thu Mar 20 2014 11:03:24 GMT+0200 (Eastern European Standard Time) 44 | ===EOF=== -------------------------------------------------------------------------------- /tests/tojson_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : redirects toJSON() to jsonSerialize 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo; 15 | $v8->executeString('var_dump(JSON.stringify(PHP.foo));'); 16 | ?> 17 | ===EOF=== 18 | --EXPECTF-- 19 | string(13) "["foo","bar"]" 20 | ===EOF=== -------------------------------------------------------------------------------- /tests/unicode.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check if imported code works with umlauts 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | unicode = $unicode; 19 | 20 | # insert unicode via executeString 21 | $jscript->executeString("var execStr = {unicode: '" . $unicode . "'}"); 22 | 23 | # insert via module loader 24 | $jscript->setModuleLoader(function ($path) use ($unicode) { 25 | return "module.exports = {unicode: '" . $unicode . "'}"; 26 | }); 27 | 28 | 29 | # return to php 30 | $jscript->executeString("values = {}"); 31 | $jscript->executeString("values['snapshot'] = snapshot.unicode"); 32 | $jscript->executeString("values['php'] = php.unicode"); 33 | $jscript->executeString("values['execStr'] = execStr.unicode"); 34 | $jscript->executeString("values['module'] = require('module').unicode"); 35 | 36 | $values = $jscript->executeString("values"); 37 | 38 | echo "snapshot: $values->snapshot\n"; 39 | echo "php : $values->php\n"; 40 | echo "execStr : $values->execStr\n"; 41 | echo "module : $values->module\n"; 42 | 43 | ?> 44 | ===EOF=== 45 | --EXPECT-- 46 | snapshot: äöüßÜÄÖÜ߀áàâÁÀµ²³▁▂▃▄▅▆▇█    ㌀ ㌁ ㌂ ㌃ 47 | php : äöüßÜÄÖÜ߀áàâÁÀµ²³▁▂▃▄▅▆▇█    ㌀ ㌁ ㌂ ㌃ 48 | execStr : äöüßÜÄÖÜ߀áàâÁÀµ²³▁▂▃▄▅▆▇█    ㌀ ㌁ ㌂ ㌃ 49 | module : äöüßÜÄÖÜ߀áàâÁÀµ²³▁▂▃▄▅▆▇█    ㌀ ㌁ ㌂ ㌃ 50 | ===EOF=== 51 | -------------------------------------------------------------------------------- /tests/use_after_dispose.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Use after dispose 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | x = $x; 13 | } 14 | } 15 | 16 | $v8 = new V8Js(); 17 | $v8->foo = $foo = new Foo(); 18 | 19 | $JS = <<< EOT 20 | PHP.foo.callMe({ bla: 23 }); 21 | 22 | EOT; 23 | 24 | $v8->executeString($JS, 'basic.js'); 25 | unset($v8); 26 | 27 | try { 28 | var_dump($foo->x); 29 | } 30 | catch(V8JsException $e) { 31 | var_dump($e->getMessage()); 32 | } 33 | ?> 34 | ===EOF=== 35 | --EXPECTF-- 36 | object(V8Object)#%d (1) { 37 | ["bla"]=> 38 | int(23) 39 | } 40 | object(V8Object)#%d (0) { 41 | } 42 | string(55) "Can't access V8Object after V8Js instance is destroyed!" 43 | ===EOF=== 44 | -------------------------------------------------------------------------------- /tests/v8_unset_property.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : unset property on V8Object 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString('var a = { bla: 23 }; a'); 10 | var_dump($a); 11 | 12 | // properties on $a should be unset'able 13 | unset($a->bla); 14 | var_dump($a); 15 | 16 | $v8->executeString('print(a.bla + "\\n");'); 17 | 18 | unset($v8); 19 | 20 | try { 21 | // unset not valid, if $v8 object is disposed 22 | unset($a->bla); 23 | } 24 | catch(V8JsException $e) { 25 | var_dump($e->getMessage()); 26 | } 27 | ?> 28 | ===EOF=== 29 | --EXPECTF-- 30 | object(V8Object)#%d (1) { 31 | ["bla"]=> 32 | int(23) 33 | } 34 | object(V8Object)#%d (0) { 35 | } 36 | undefined 37 | string(55) "Can't access V8Object after V8Js instance is destroyed!" 38 | ===EOF=== 39 | -------------------------------------------------------------------------------- /tests/v8_write_property.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : write property on V8Object 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString('var a = { bla: 23 }; a'); 10 | var_dump($a); 11 | 12 | // properties on $a should be writable 13 | $a->bla = 42; 14 | var_dump($a); 15 | 16 | $v8->executeString('print(a.bla + "\\n");'); 17 | 18 | unset($v8); 19 | 20 | try { 21 | // writing not valid, if $v8 object is disposed 22 | $a->bla = 5; 23 | } 24 | catch(V8JsException $e) { 25 | var_dump($e->getMessage()); 26 | } 27 | ?> 28 | ===EOF=== 29 | --EXPECTF-- 30 | object(V8Object)#%d (1) { 31 | ["bla"]=> 32 | int(23) 33 | } 34 | object(V8Object)#%d (1) { 35 | ["bla"]=> 36 | int(42) 37 | } 38 | 42 39 | string(55) "Can't access V8Object after V8Js instance is destroyed!" 40 | ===EOF=== 41 | 42 | 43 | -------------------------------------------------------------------------------- /tests/variable_passing.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : simple variables passed from PHP 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | ' + val + "\\n"); 14 | } 15 | } 16 | function test() 17 | { 18 | var a = 'From PHP: ' + PHP.somevar; 19 | PHP.somevar = 'changed in JS!'; // Should not change.. 20 | 21 | dump(PHP.myarray); 22 | 23 | return a; 24 | } 25 | print(test() + "\\n"); 26 | print(PHP.myinteger + "\\n"); 27 | print(PHP.myfloat + "\\n"); 28 | EOT; 29 | 30 | $a = new V8Js(); 31 | $a->somevar = "From PHP with love!"; 32 | $a->myinteger = 123; 33 | $a->myfloat = 3.14; 34 | $a->_SERVER = $_SERVER; 35 | $a->GLOBALS = $GLOBALS; 36 | $a->myarray = array( 37 | 'a' => 'value for key A', 38 | 'b' => 'value for key B', 39 | 'c' => 'value for key C', 40 | 'd' => 'value for key D', 41 | ); 42 | 43 | $a->executeString($JS, "test.js"); 44 | 45 | // Check that variable has not been modified 46 | var_dump($a->somevar); 47 | ?> 48 | ===EOF=== 49 | --EXPECT-- 50 | a => value for key A 51 | b => value for key B 52 | c => value for key C 53 | d => value for key D 54 | From PHP: From PHP with love! 55 | 123 56 | 3.14 57 | string(19) "From PHP with love!" 58 | ===EOF=== 59 | -------------------------------------------------------------------------------- /v8js_array_access.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2013 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Stefan Siegl | 10 | +----------------------------------------------------------------------+ 11 | */ 12 | 13 | #ifndef V8JS_ARRAY_ACCESS_H 14 | #define V8JS_ARRAY_ACCESS_H 15 | 16 | /* Indexed Property Handlers */ 17 | V8JS_INTERCEPTED v8js_array_access_getter(uint32_t index, 18 | const v8::PropertyCallbackInfo& info); 19 | V8JS_INTERCEPTED v8js_array_access_setter(uint32_t index, v8::Local value, 20 | const V8JS_SETTER_PROPERTY_CALLBACK_INFO &info); 21 | void v8js_array_access_enumerator(const v8::PropertyCallbackInfo& info); 22 | V8JS_INTERCEPTED v8js_array_access_deleter(uint32_t index, 23 | const v8::PropertyCallbackInfo& info); 24 | V8JS_INTERCEPTED v8js_array_access_query(uint32_t index, 25 | const v8::PropertyCallbackInfo& info); 26 | 27 | /* Named Property Handlers */ 28 | V8JS_INTERCEPTED v8js_array_access_named_getter(v8::Local property, 29 | const v8::PropertyCallbackInfo &info); 30 | 31 | #endif /* V8JS_ARRAY_ACCESS_H */ 32 | 33 | /* 34 | * Local variables: 35 | * tab-width: 4 36 | * c-basic-offset: 4 37 | * indent-tabs-mode: t 38 | * End: 39 | * vim600: noet sw=4 ts=4 fdm=marker 40 | * vim<600: noet sw=4 ts=4 41 | */ 42 | -------------------------------------------------------------------------------- /v8js_commonjs.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2015 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Stefan Siegl | 10 | +----------------------------------------------------------------------+ 11 | */ 12 | 13 | #ifndef V8JS_COMMONJS_H 14 | #define V8JS_COMMONJS_H 15 | 16 | void v8js_commonjs_normalise_identifier(const char *base, const char *identifier, char *normalised_path, char *module_name); 17 | 18 | #endif /* V8JS_COMMONJS_H */ 19 | 20 | /* 21 | * Local variables: 22 | * tab-width: 4 23 | * c-basic-offset: 4 24 | * indent-tabs-mode: t 25 | * End: 26 | * vim600: noet sw=4 ts=4 fdm=marker 27 | * vim<600: noet sw=4 ts=4 28 | */ 29 | -------------------------------------------------------------------------------- /v8js_exceptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2015 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Jani Taskinen | 10 | | Author: Patrick Reilly | 11 | | Author: Stefan Siegl | 12 | +----------------------------------------------------------------------+ 13 | */ 14 | 15 | #ifndef V8JS_EXCEPTIONS_H 16 | #define V8JS_EXCEPTIONS_H 17 | 18 | extern zend_class_entry *php_ce_v8js_exception; 19 | extern zend_class_entry *php_ce_v8js_script_exception; 20 | extern zend_class_entry *php_ce_v8js_time_limit_exception; 21 | extern zend_class_entry *php_ce_v8js_memory_limit_exception; 22 | 23 | void v8js_create_script_exception(zval *return_value, v8::Isolate *isolate, v8::TryCatch *try_catch); 24 | void v8js_throw_script_exception(v8::Isolate *isolate, v8::TryCatch *try_catch); 25 | 26 | PHP_MINIT_FUNCTION(v8js_exceptions); 27 | 28 | #endif /* V8JS_EXCEPTIONS_H */ 29 | 30 | /* 31 | * Local variables: 32 | * tab-width: 4 33 | * c-basic-offset: 4 34 | * indent-tabs-mode: t 35 | * End: 36 | * vim600: noet sw=4 ts=4 fdm=marker 37 | * vim<600: noet sw=4 ts=4 38 | */ 39 | -------------------------------------------------------------------------------- /v8js_generator_export.cc: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2016 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Stefan Siegl | 10 | +----------------------------------------------------------------------+ 11 | */ 12 | 13 | #ifdef HAVE_CONFIG_H 14 | #include "config.h" 15 | #endif 16 | 17 | #include 18 | #include "php_v8js_macros.h" 19 | 20 | v8::Local v8js_wrap_generator(v8::Isolate *isolate, v8::Local wrapped_object) /* {{{ */ 21 | { 22 | v8::Local result; 23 | 24 | assert(!wrapped_object.IsEmpty()); 25 | assert(wrapped_object->IsObject()); 26 | 27 | v8js_ctx *ctx = (v8js_ctx *) isolate->GetData(0); 28 | v8::Local v8_context = v8::Local::New(isolate, ctx->context); 29 | 30 | v8::TryCatch try_catch(isolate); 31 | v8::Local source = V8JS_SYM("(\ 32 | function(wrapped_object) { \ 33 | return (function*() { \ 34 | for(;;) { \ 35 | if(!wrapped_object.valid()) { \ 36 | return; \ 37 | } \ 38 | yield wrapped_object.current(); \ 39 | wrapped_object.next(); \ 40 | } \ 41 | })(); \ 42 | })"); 43 | v8::MaybeLocal script = v8::Script::Compile(v8_context, source); 44 | 45 | if(script.IsEmpty()) { 46 | zend_error(E_ERROR, "Failed to compile Generator object wrapper"); 47 | return result; 48 | } 49 | 50 | v8::MaybeLocal wrapper_fn_val = script.ToLocalChecked()->Run(v8_context); 51 | 52 | if(wrapper_fn_val.IsEmpty() || !wrapper_fn_val.ToLocalChecked()->IsFunction()) { 53 | zend_error(E_ERROR, "Failed to create Generator object wrapper function"); 54 | return result; 55 | } 56 | 57 | v8::Local wrapper_fn = v8::Local::Cast(wrapper_fn_val.ToLocalChecked()); 58 | v8::Local *jsArgv = static_cast *>(alloca(sizeof(v8::Local))); 59 | 60 | new(&jsArgv[0]) v8::Local; 61 | jsArgv[0] = v8::Local::New(isolate, wrapped_object); 62 | 63 | wrapper_fn->Call(v8_context, V8JS_GLOBAL(isolate), 1, jsArgv).ToLocal(&result); 64 | return result; 65 | } 66 | /* }}} */ 67 | 68 | /* 69 | * Local variables: 70 | * tab-width: 4 71 | * c-basic-offset: 4 72 | * End: 73 | * vim600: noet sw=4 ts=4 fdm=marker 74 | * vim<600: noet sw=4 ts=4 75 | */ 76 | -------------------------------------------------------------------------------- /v8js_generator_export.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2016 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Stefan Siegl | 10 | +----------------------------------------------------------------------+ 11 | */ 12 | 13 | #ifndef V8JS_GENERATOR_EXPORT_H 14 | #define V8JS_GENERATOR_EXPORT_H 15 | 16 | v8::Local v8js_wrap_generator(v8::Isolate *isolate, v8::Local wrapped_object); 17 | 18 | #endif /* V8JS_GENERATOR_EXPORT_H */ 19 | 20 | /* 21 | * Local variables: 22 | * mode: c++ 23 | * tab-width: 4 24 | * c-basic-offset: 4 25 | * End: 26 | * vim600: noet sw=4 ts=4 fdm=marker 27 | * vim<600: noet sw=4 ts=4 28 | */ 29 | -------------------------------------------------------------------------------- /v8js_object_export.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2013 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Jani Taskinen | 10 | | Author: Patrick Reilly | 11 | +----------------------------------------------------------------------+ 12 | */ 13 | 14 | #ifndef V8JS_OBJECT_EXPORT_H 15 | #define V8JS_OBJECT_EXPORT_H 16 | 17 | v8::Local v8js_hash_to_jsobj(zval *value, v8::Isolate *isolate); 18 | v8::Local v8js_propagate_exception(v8js_ctx *ctx); 19 | 20 | 21 | typedef enum { 22 | V8JS_PROP_GETTER, 23 | V8JS_PROP_SETTER, 24 | V8JS_PROP_QUERY, 25 | V8JS_PROP_DELETER 26 | } property_op_t; 27 | 28 | v8::Local v8js_named_property_callback(v8::Isolate *isolate, v8::Local self, 29 | v8::Local property, property_op_t callback_type, 30 | v8::Local set_value = v8::Local()); 31 | 32 | void v8js_php_callback(const v8::FunctionCallbackInfo& info); 33 | 34 | #endif /* V8JS_OBJECT_EXPORT_H */ 35 | 36 | /* 37 | * Local variables: 38 | * tab-width: 4 39 | * c-basic-offset: 4 40 | * indent-tabs-mode: t 41 | * End: 42 | * vim600: noet sw=4 ts=4 fdm=marker 43 | * vim<600: noet sw=4 ts=4 44 | */ 45 | -------------------------------------------------------------------------------- /v8js_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2013 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Jani Taskinen | 10 | | Author: Patrick Reilly | 11 | +----------------------------------------------------------------------+ 12 | */ 13 | 14 | #ifndef V8JS_TIMER_H 15 | #define V8JS_TIMER_H 16 | 17 | // Timer context 18 | struct v8js_timer_ctx 19 | { 20 | long time_limit; 21 | size_t memory_limit; 22 | std::chrono::time_point time_point; 23 | v8js_ctx *ctx; 24 | bool killed; 25 | }; 26 | 27 | void v8js_timer_thread(zend_v8js_globals *globals); 28 | void v8js_timer_push(long time_limit, size_t memory_limit, v8js_ctx *c); 29 | 30 | #endif /* V8JS_TIMER_H */ 31 | 32 | /* 33 | * Local variables: 34 | * tab-width: 4 35 | * c-basic-offset: 4 36 | * indent-tabs-mode: t 37 | * End: 38 | * vim600: noet sw=4 ts=4 fdm=marker 39 | * vim<600: noet sw=4 ts=4 40 | */ 41 | -------------------------------------------------------------------------------- /v8js_v8object_class.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2013 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Jani Taskinen | 10 | | Author: Patrick Reilly | 11 | +----------------------------------------------------------------------+ 12 | */ 13 | 14 | #ifndef V8JS_V8OBJECT_CLASS_H 15 | #define V8JS_V8OBJECT_CLASS_H 16 | 17 | /* {{{ Object container */ 18 | struct v8js_v8object { 19 | v8::Global v8obj; 20 | int flags; 21 | struct v8js_ctx *ctx; 22 | HashTable *properties; 23 | zend_object std; 24 | }; 25 | /* }}} */ 26 | 27 | extern zend_class_entry *php_ce_v8object; 28 | extern zend_class_entry *php_ce_v8function; 29 | 30 | /* Create PHP V8 object */ 31 | void v8js_v8object_create(zval *, v8::Local, int, v8::Isolate *); 32 | 33 | static inline v8js_v8object *v8js_v8object_fetch_object(zend_object *obj) { 34 | return (v8js_v8object *)((char *)obj - XtOffsetOf(struct v8js_v8object, std)); 35 | } 36 | 37 | #define Z_V8JS_V8OBJECT_OBJ_P(zv) v8js_v8object_fetch_object(Z_OBJ_P(zv)); 38 | #define Z_V8JS_V8OBJECT_OBJ(zv) v8js_v8object_fetch_object(zv); 39 | 40 | /* {{{ Generator container */ 41 | struct v8js_v8generator { 42 | zval value; 43 | bool primed; 44 | bool done; 45 | struct v8js_v8object v8obj; 46 | }; 47 | /* }}} */ 48 | 49 | extern zend_class_entry *php_ce_v8generator; 50 | 51 | 52 | static inline v8js_v8generator *v8js_v8generator_fetch_object(zend_object *obj) { 53 | return (v8js_v8generator *)((char *)obj - XtOffsetOf(struct v8js_v8generator, v8obj.std)); 54 | } 55 | 56 | #define Z_V8JS_V8GENERATOR_OBJ_P(zv) v8js_v8generator_fetch_object(Z_OBJ_P(zv)); 57 | 58 | 59 | 60 | PHP_MINIT_FUNCTION(v8js_v8object_class); 61 | 62 | #endif /* V8JS_V8OBJECT_CLASS_H */ 63 | 64 | /* 65 | * Local variables: 66 | * tab-width: 4 67 | * c-basic-offset: 4 68 | * indent-tabs-mode: t 69 | * End: 70 | * vim600: noet sw=4 ts=4 fdm=marker 71 | * vim<600: noet sw=4 ts=4 72 | */ 73 | -------------------------------------------------------------------------------- /v8js_variables.cc: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 7 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2017 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | http://www.opensource.org/licenses/mit-license.php MIT License | 8 | +----------------------------------------------------------------------+ 9 | | Author: Jani Taskinen | 10 | | Author: Patrick Reilly | 11 | | Author: Stefan Siegl | 12 | +----------------------------------------------------------------------+ 13 | */ 14 | 15 | #ifdef HAVE_CONFIG_H 16 | #include "config.h" 17 | #endif 18 | 19 | #include 20 | 21 | #include "php_v8js_macros.h" 22 | #include "v8js_exceptions.h" 23 | 24 | extern "C" { 25 | #include "zend_exceptions.h" 26 | } 27 | 28 | static void v8js_fetch_php_variable(v8::Local name, const v8::PropertyCallbackInfo& info) /* {{{ */ 29 | { 30 | v8::Local data = v8::Local::Cast(info.Data()); 31 | v8js_accessor_ctx *ctx = static_cast(data->Value()); 32 | v8::Isolate *isolate = ctx->isolate; 33 | zval *variable; 34 | 35 | zend_is_auto_global(ctx->variable_name); 36 | 37 | if ((variable = zend_hash_find(&EG(symbol_table), ctx->variable_name))) { 38 | info.GetReturnValue().Set(zval_to_v8js(variable, isolate)); 39 | return; 40 | } 41 | } 42 | /* }}} */ 43 | 44 | void v8js_accessor_ctx_dtor(v8js_accessor_ctx *ctx) /* {{{ */ 45 | { 46 | zend_string_release(ctx->variable_name); 47 | efree(ctx); 48 | } 49 | /* }}} */ 50 | 51 | void v8js_register_accessors(std::vector *accessor_list, v8::Local php_obj_t, zval *array, v8::Isolate *isolate) /* {{{ */ 52 | { 53 | zend_string *property_name; 54 | zval *item; 55 | v8::Local php_obj = php_obj_t->InstanceTemplate(); 56 | 57 | ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(array), property_name, item) { 58 | switch (Z_TYPE_P(item)) 59 | { 60 | /* 61 | case IS_OBJECT: 62 | case IS_ARRAY: 63 | */ 64 | case IS_STRING: 65 | break; 66 | 67 | default: 68 | continue; /* Ignore invalid values */ 69 | } 70 | 71 | if (ZSTR_LEN(property_name) > std::numeric_limits::max()) { 72 | zend_throw_exception(php_ce_v8js_exception, 73 | "Property name length exceeds maximum supported length", 0); 74 | continue; 75 | } 76 | 77 | // Create context to store accessor data 78 | v8js_accessor_ctx *ctx = (v8js_accessor_ctx *)emalloc(sizeof(v8js_accessor_ctx)); 79 | ctx->variable_name = zend_string_copy(Z_STR_P(item)); 80 | ctx->isolate = isolate; 81 | 82 | /* Set the variable fetch callback for given symbol on named property */ 83 | php_obj->SetNativeDataProperty(V8JS_STRL(ZSTR_VAL(property_name), static_cast(ZSTR_LEN(property_name))), v8js_fetch_php_variable, NULL, v8::External::New(isolate, ctx), v8::PropertyAttribute::ReadOnly); 84 | 85 | /* record the context so we can free it later */ 86 | accessor_list->push_back(ctx); 87 | } ZEND_HASH_FOREACH_END(); 88 | } 89 | /* }}} */ 90 | 91 | /* 92 | * Local variables: 93 | * tab-width: 4 94 | * c-basic-offset: 4 95 | * indent-tabs-mode: t 96 | * End: 97 | * vim600: noet sw=4 ts=4 fdm=marker 98 | * vim<600: noet sw=4 ts=4 99 | */ 100 | --------------------------------------------------------------------------------