├── .cargo └── config ├── .github └── workflows │ └── build.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── README.md ├── src ├── lib.rs └── runtime.rs └── tests ├── commonjs_modules.php ├── compile_error.php ├── execute_string.php ├── global_functions.php ├── js_bridge.php ├── memory_limit.php ├── php_bridge.php ├── phpt ├── .phpunit.result.cache ├── 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.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 ├── composer.json ├── composer.lock ├── 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_clearing.phpt ├── exception_propagation_1.phpt ├── exception_propagation_2.phpt ├── exception_propagation_3.phpt ├── exception_start_column.phpt ├── execute_flags.phpt ├── execute_flags_args.phpt ├── execute_flags_property_writing.phpt ├── extensions_basic.phpt ├── extensions_circular_dependency.phpt ├── extensions_error.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 ├── 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_basic.phpt ├── phpunit.xml ├── 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 ├── unicode.phpt ├── use_after_dispose.phpt ├── v8_unset_property.phpt ├── v8_write_property.phpt ├── var_dump.phpt └── variable_passing.phpt ├── react-wp-scripts-bundle.js ├── react-wp-ssr.php ├── snapshot.php ├── time_limit.php └── version.php /.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = ["-C", "link-arg=-Wl,-undefined,dynamic_lookup"] 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /tests/phpt/vendor 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "v8js" 3 | version = "0.5.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | ext-php-rs = "0.11.1" 10 | v8 = "0.82.0" 11 | 12 | [lib] 13 | crate-type = ["cdylib"] 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Define versions used to select image versions 2 | # (ARGs declared before FROM can't be used outside of FROMs) 3 | ARG FROM_PHP=8.0 4 | 5 | # Select distro 6 | ARG FROM_DISTRO=bullseye 7 | 8 | FROM php:${FROM_PHP}-fpm-${FROM_DISTRO} 9 | 10 | RUN apt-get update && apt install curl build-essential gcc libclang-dev make -y 11 | 12 | RUN curl https://sh.rustup.rs -sSf | bash -s -- -y 13 | 14 | RUN echo 'source $HOME/.cargo/env' >> $HOME/.bashrc 15 | ENV PATH="/root/.cargo/bin:${PATH}" 16 | 17 | WORKDIR /code 18 | ENTRYPOINT [ "" ] 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP-V8Js 2 | 3 | PHP-V8Js is a PHP extension for the V8 JavaScript engine. It is a re-implementation of the fantastic (though unmaintained) [V8Js PHP extension](https://github.com/phpv8/v8js). 4 | 5 | The extension allows you to execute JavaScript code in a secure sandbox from PHP. The executed code can be restricted using a time limit and/or memory limit. This provides the possibility to execute untrusted code with confidence. 6 | 7 | ## Requirements 8 | 9 | - PHP 8.0+ 10 | 11 | The extension includes builds of libv8, via the [v8 crate](https://docs.rs/v8/latest/v8/). This makes installing the extension very simple. 12 | 13 | ## Mapping Rules 14 | 15 | |PHP -> JavaScript|JavaScript -> PHP| 16 | |---|---| 17 | |String -> string|string -> String| 18 | |Bool -> bool|bool -> Bool| 19 | |Array (numeric) -> Array|array -> Array| 20 | |Array (string keys) -> Object|Object -> V8Object| 21 | |Int -> Number|Number -> Float| 22 | 23 | 24 | ## Todo: 25 | 26 | ### V8Js Compatibility 27 | 28 | - [x] Memory / time limits 29 | - [x] Snapshop creating and loading 30 | - [x] Default global functions `var_dump`, `sleep`, `exit` 31 | - [x] Default global function `print` 32 | - [x] CommonJS / `require` support 33 | - [x] `setModuleLoader` 34 | - [ ] `setModuleNormaliser` 35 | - [ ] Subclassing V8Js 36 | - [x] Custom exceptions for `V8JsScriptException`, `V8JsMemoryLimitException` and `V8JsTimeLimitException` 37 | - [ ] Support for `V8JsScriptException::getJsLineNumber` etc. 38 | - [ ] Support for `FLAG_PROPAGATE_PHP_EXCEPTIONS`, `V8Js::FLAG_FORCE_ARRAY` 39 | - [ ] PHP INI settings `v8js.flags` 40 | - [x] `V8Js::V8_VERSION` constant 41 | 42 | ### Not planned compatibility 43 | 44 | - Support for `ArrayAccess` objects mapped into JavaScript 45 | - PHP INI settings `v8js.use_array_access`, `v8js.use_date`, `v8js.icudtl_dat_path` 46 | - `V8Js::registerExtension` 47 | 48 | ### New features 49 | 50 | - [ ] Support for native ES modules 51 | 52 | ## Credits 53 | 54 | - [Stefan Siegl](https://github.com/stesie) of course for creating v8js, and the [37 contributors](https://github.com/phpv8/v8js/graphs/contributors). 55 | - [David Cole](https://github.com/davidcole1340) for creating ext-php-rs and helping me use the library. 56 | -------------------------------------------------------------------------------- /tests/commonjs_modules.php: -------------------------------------------------------------------------------- 1 | setModuleLoader( function ( string $module ) : string { 5 | return 'module.exports = 10'; 6 | } ); 7 | 8 | assert( 10 === $v8js->executeString( 'require("lodash")') ); 9 | 10 | $v8js = new V8Js; 11 | $v8js->setModuleLoader( function ( string $module ) : string { 12 | return 'exports.get = 10'; 13 | } ); 14 | 15 | assert( 10 === $v8js->executeString( 'require("lodash").get') ); 16 | -------------------------------------------------------------------------------- /tests/compile_error.php: -------------------------------------------------------------------------------- 1 | executeString( 'my_func();' ); 7 | } catch ( V8JsScriptException $e ) { 8 | assert( $e->getJsFileName() ); 9 | } 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/execute_string.php: -------------------------------------------------------------------------------- 1 | executeString( '5 + 5' ); 5 | assert( $result === 10 ); 6 | -------------------------------------------------------------------------------- /tests/global_functions.php: -------------------------------------------------------------------------------- 1 | executeString( 'print("hello")' ); 8 | $result = ob_get_clean(); 9 | assert( $result === "hello"); 10 | 11 | $v8js = new V8Js; 12 | ob_start(); 13 | $v8js->executeString( 'var_dump("hello")' ); 14 | $result = ob_get_clean(); 15 | assert( $result === 'string(5) "hello"' . "\n"); 16 | 17 | $v8js = new V8Js; 18 | $called_done = false; 19 | $v8js->done = function () use ( &$called_done ) { 20 | $called_done = true; 21 | }; 22 | $v8js->executeString( 'exit(); PHP.done();' ); 23 | assert($called_done === false); 24 | 25 | $v8js = new V8Js; 26 | $start = microtime( true ); 27 | $v8js->executeString( 'sleep(1);' ); 28 | $elapsed = microtime( true ) - $start; 29 | assert( $elapsed > 1 ); 30 | -------------------------------------------------------------------------------- /tests/js_bridge.php: -------------------------------------------------------------------------------- 1 | executeString( '({ foo: "bar" })' ); 5 | assert($result instanceof V8Object ); 6 | assert($result->foo === 'bar' ); 7 | 8 | $result = $v8js->executeString( '[1, 2, 3]' ); 9 | assert($result === [1, 2, 3] ); 10 | 11 | $result = $v8js->executeString( 'print' ); 12 | assert($result === 'Function'); // Todo: better handling for this 13 | 14 | $result = $v8js->executeString( '"hello"' ); 15 | assert($result === 'hello'); 16 | 17 | $result = $v8js->executeString( '10' ); 18 | assert($result === 10); 19 | 20 | $result = $v8js->executeString( '10.1' ); 21 | assert($result === 10.1); 22 | 23 | $result = $v8js->executeString( 'true' ); 24 | assert($result === true); 25 | 26 | -------------------------------------------------------------------------------- /tests/memory_limit.php: -------------------------------------------------------------------------------- 1 | sleep = function ( int $milliseconds ) { 5 | usleep( $milliseconds * 1000 ); 6 | }; 7 | 8 | $killed = null; 9 | $used_memory_limit_exception = false; 10 | try { 11 | $result = $v8js->executeString( 'let my_arr = []; for ( let i = 0; i < 100000 ; i++ ) { my_arr.push( (new Date).toString() ); }; ', null, null, null, 1024 * 10 ); 12 | $killed = false; 13 | } catch ( V8JsMemoryLimitException $e ) { 14 | $killed = true; 15 | $used_memory_limit_exception = true; 16 | } catch ( Exception $e ) { 17 | $killed = true; 18 | } 19 | assert( $killed === true ); 20 | assert( $used_memory_limit_exception === true ); 21 | -------------------------------------------------------------------------------- /tests/php_bridge.php: -------------------------------------------------------------------------------- 1 | executeString( 'PHP' ); 5 | assert( $result instanceof V8Object ); 6 | 7 | $v8js = new V8Js('MyBridge'); 8 | $result = $v8js->executeString( 'MyBridge' ); 9 | assert( $result instanceof V8Object ); 10 | 11 | $v8js = new V8Js; 12 | $v8js->my_var = 'abc'; 13 | $result = $v8js->executeString( 'PHP.my_var' ); 14 | assert( $result === 'abc' ); 15 | 16 | $v8js = new V8Js; 17 | $v8js->my_func = function () { 18 | return 1; 19 | }; 20 | $result = $v8js->executeString( 'PHP.my_func()' ); 21 | assert( $result === 1 ); 22 | 23 | $v8js = new V8Js; 24 | $v8js->sleep = function ( int $milliseconds ) { 25 | usleep( $milliseconds * 1000 ); 26 | return "done"; 27 | }; 28 | $result = $v8js->executeString( 'PHP.sleep(200);' ); 29 | assert( $result === "done" ); 30 | 31 | -------------------------------------------------------------------------------- /tests/phpt/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($offset) { 16 | return 19 - $offset; 17 | } 18 | 19 | public function offsetSet($offset, $value) { 20 | throw new Exception('Not implemented'); 21 | } 22 | 23 | public function offsetUnset($offset) { 24 | throw new Exception('Not implemented'); 25 | } 26 | 27 | public function count() { 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/phpt/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($offset) { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet($offset, $value) { 22 | $this->data[$offset] = $value; 23 | } 24 | 25 | public function offsetUnset($offset) { 26 | throw new Exception('Not implemented'); 27 | } 28 | 29 | public function count() { 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/phpt/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]); 15 | } 16 | 17 | public function offsetGet($offset) { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet($offset, $value) { 22 | echo "set[$offset] = $value\n"; 23 | $this->data[$offset] = $value; 24 | } 25 | 26 | public function offsetUnset($offset) { 27 | throw new Exception('Not implemented'); 28 | } 29 | 30 | public function count() { 31 | return count($this->data); 32 | } 33 | } 34 | 35 | $v8 = new V8Js(); 36 | $v8->myarr = new MyArray(); 37 | 38 | /* Call native JavaScript push method, this should cause a count 39 | * offsetSet call. */ 40 | $v8->executeString('PHP.myarr.push(23);'); 41 | 42 | /* Access array from PHP side, should work if JavaScript called 43 | * the write accessor functions. */ 44 | var_dump(count($v8->myarr)); 45 | var_dump($v8->myarr[3]); 46 | 47 | /* And JS side of course should see it too. */ 48 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 49 | 50 | ?> 51 | ===EOF=== 52 | --EXPECT-- 53 | set[3] = 23 54 | int(4) 55 | int(23) 56 | string(16) "one,two,three,23" 57 | ===EOF=== 58 | -------------------------------------------------------------------------------- /tests/phpt/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]); 15 | } 16 | 17 | public function offsetGet($offset) { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet($offset, $value) { 22 | echo "set[$offset] = $value\n"; 23 | $this->data[$offset] = $value; 24 | } 25 | 26 | public function offsetUnset($offset) { 27 | throw new Exception('Not implemented'); 28 | } 29 | 30 | public function count() { 31 | echo 'count() = ', count($this->data), "\n"; 32 | return count($this->data); 33 | } 34 | 35 | public function phpSidePush($value) { 36 | echo "push << $value\n"; 37 | $this->data[] = $value; 38 | } 39 | 40 | public function push($value) { 41 | echo "php-side-push << $value\n"; 42 | $this->data[] = $value; 43 | } 44 | } 45 | 46 | $v8 = new V8Js(); 47 | $v8->myarr = new MyArray(); 48 | 49 | /* Call PHP method to modify the array. */ 50 | $v8->executeString('PHP.myarr.phpSidePush(23);'); 51 | 52 | var_dump(count($v8->myarr)); 53 | var_dump($v8->myarr[3]); 54 | 55 | /* And JS should see the changes due to live binding. */ 56 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 57 | 58 | 59 | /* Call `push' method, this should trigger the PHP method. */ 60 | $v8->executeString('PHP.myarr.push(42);'); 61 | 62 | var_dump(count($v8->myarr)); 63 | var_dump($v8->myarr[4]); 64 | 65 | /* And JS should see the changes due to live binding. */ 66 | $v8->executeString('var_dump(PHP.myarr.join(","));'); 67 | 68 | ?> 69 | ===EOF=== 70 | --EXPECT-- 71 | push << 23 72 | count() = 4 73 | int(4) 74 | int(23) 75 | count() = 4 76 | string(16) "one,two,three,23" 77 | php-side-push << 42 78 | count() = 5 79 | int(5) 80 | int(42) 81 | count() = 5 82 | string(19) "one,two,three,23,42" 83 | ===EOF=== 84 | -------------------------------------------------------------------------------- /tests/phpt/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]); 24 | } 25 | 26 | public function offsetGet($offset) { 27 | return $this->data[$offset]; 28 | } 29 | 30 | public function offsetSet($offset, $value) { 31 | echo "set[$offset] = $value\n"; 32 | $this->data[$offset] = $value; 33 | } 34 | 35 | public function offsetUnset($offset) { 36 | throw new Exception('Not implemented'); 37 | } 38 | 39 | public function count() { 40 | return count($this->data); 41 | } 42 | } 43 | 44 | $v8 = new V8Js(); 45 | $v8->myarr = new MyArray(); 46 | 47 | $v8->executeString('var_dump(PHP.myarr.privFoo);'); 48 | $v8->executeString('var_dump(PHP.myarr.protFoo);'); 49 | $v8->executeString('var_dump(PHP.myarr.pubFoo);'); 50 | 51 | /* This should call count(), i.e. return 3 */ 52 | $v8->executeString('var_dump(PHP.myarr.length);'); 53 | 54 | /* This should print the value of the $length property */ 55 | $v8->executeString('var_dump(PHP.myarr.$length);'); 56 | 57 | ?> 58 | ===EOF=== 59 | --EXPECT-- 60 | NULL 61 | NULL 62 | int(42) 63 | int(3) 64 | int(42) 65 | ===EOF=== 66 | -------------------------------------------------------------------------------- /tests/phpt/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]); 15 | } 16 | 17 | public function offsetGet($offset) { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet($offset, $value) { 22 | echo "set[$offset] = $value\n"; 23 | $this->data[$offset] = $value; 24 | } 25 | 26 | public function offsetUnset($offset) { 27 | throw new Exception('Not implemented'); 28 | } 29 | 30 | public function count() { 31 | return count($this->data); 32 | } 33 | 34 | public function __invoke() { 35 | echo "__invoke called!\n"; 36 | } 37 | } 38 | 39 | $v8 = new V8Js(); 40 | $v8->myarr = new MyArray(); 41 | 42 | $v8->executeString('PHP.myarr();'); 43 | 44 | $v8->executeString('var_dump(PHP.myarr.length);'); 45 | $v8->executeString('var_dump(PHP.myarr.join(", "));'); 46 | 47 | ?> 48 | ===EOF=== 49 | --EXPECT-- 50 | __invoke called! 51 | int(3) 52 | string(15) "one, two, three" 53 | ===EOF=== 54 | -------------------------------------------------------------------------------- /tests/phpt/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]); 15 | } 16 | 17 | public function offsetGet($offset) { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet($offset, $value) { 22 | echo "set[$offset] = $value\n"; 23 | $this->data[$offset] = $value; 24 | } 25 | 26 | public function offsetUnset($offset) { 27 | throw new Exception('Not implemented'); 28 | } 29 | 30 | public function count() { 31 | return count($this->data); 32 | } 33 | } 34 | 35 | $v8 = new V8Js(); 36 | $v8->myarr = new MyArray(); 37 | 38 | $js = <<executeString($js); 51 | 52 | ?> 53 | ===EOF=== 54 | --EXPECT-- 55 | string(1) "0" 56 | string(1) "1" 57 | string(1) "2" 58 | string(1) "4" 59 | string(1) "0" 60 | string(1) "1" 61 | string(1) "2" 62 | string(1) "4" 63 | ===EOF=== 64 | -------------------------------------------------------------------------------- /tests/phpt/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]); 15 | } 16 | 17 | public function offsetGet($offset) { 18 | if(!$this->offsetExists($offset)) { 19 | return null; 20 | } 21 | return $this->data[$offset]; 22 | } 23 | 24 | public function offsetSet($offset, $value) { 25 | $this->data[$offset] = $value; 26 | } 27 | 28 | public function offsetUnset($offset) { 29 | unset($this->data[$offset]); 30 | } 31 | 32 | public function count() { 33 | return max(array_keys($this->data)) + 1; 34 | } 35 | } 36 | 37 | $v8 = new V8Js(); 38 | $v8->myarr = new MyArray(); 39 | 40 | $js = <<executeString($js); 51 | 52 | ?> 53 | ===EOF=== 54 | --EXPECT-- 55 | string(10) "one,,three" 56 | string(10) "one,,three" 57 | ===EOF=== 58 | -------------------------------------------------------------------------------- /tests/phpt/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]); 15 | } 16 | 17 | public function offsetGet($offset) { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet($offset, $value) { 22 | $this->data[$offset] = $value; 23 | } 24 | 25 | public function offsetUnset($offset) { 26 | unset($this->data[$offset]); 27 | } 28 | 29 | public function count() { 30 | return max(array_keys($this->data)) + 1; 31 | } 32 | } 33 | 34 | $v8 = new V8Js(); 35 | $v8->myarr = new MyArray(); 36 | 37 | $js = <<executeString($js); 48 | 49 | ?> 50 | ===EOF=== 51 | --EXPECT-- 52 | bool(true) 53 | bool(false) 54 | bool(true) 55 | bool(false) 56 | ===EOF=== 57 | -------------------------------------------------------------------------------- /tests/phpt/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]); 15 | } 16 | 17 | public function offsetGet($offset) { 18 | return $this->data[$offset]; 19 | } 20 | 21 | public function offsetSet($offset, $value) { 22 | $this->data[$offset] = $value; 23 | } 24 | 25 | public function offsetUnset($offset) { 26 | throw new Exception('Not implemented'); 27 | } 28 | 29 | public function count() { 30 | return count($this->data); 31 | } 32 | } 33 | 34 | $myarr = new MyArray(); 35 | $myarr[0] = 'three'; 36 | 37 | $js = <<myarr = $myarr; 46 | $v8->executeString($js); 47 | 48 | var_dump($myarr[2]); 49 | 50 | ?> 51 | ===EOF=== 52 | --EXPECT-- 53 | string(5) "three" 54 | string(3) "one" 55 | string(13) "three,two,one" 56 | string(3) "one" 57 | ===EOF=== 58 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/checkstring.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Script validator test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | checkString('print("Hello World!");')); 10 | 11 | try { 12 | var_dump($v8->checkString('print("Hello World!);')); 13 | } catch (V8JsScriptException $e) { 14 | var_dump($e->getMessage()); 15 | } 16 | ?> 17 | ===EOF=== 18 | --EXPECTF-- 19 | Deprecated: Function V8Js::checkString() is deprecated in %s on line %d 20 | bool(true) 21 | 22 | Deprecated: Function V8Js::checkString() is deprecated in %s on line %d 23 | string(%d) "V8Js::checkString():1: SyntaxError: %s" 24 | ===EOF=== 25 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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]: {closure}('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]: {closure}('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/phpt/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]: {closure}('', './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]: {closure}('', './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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "joehoyle/v8js-tests", 3 | "autoload": { 4 | "psr-4": { 5 | "Joehoyle\\V8jsTests\\": "src/" 6 | } 7 | }, 8 | "authors": [ 9 | { 10 | "name": "Joe Hoyle", 11 | "email": "joehoyle@gmail.com" 12 | } 13 | ], 14 | "require": { 15 | "phpunit/phpunit": "^9.5" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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(), array(), true, $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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/exception_clearing.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Exception clearing test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getPendingException()); 11 | 12 | $v8->clearPendingException(); 13 | var_dump($v8->getPendingException()); 14 | 15 | $v8->executeString('fooobar', 'throw_0'); 16 | var_dump($v8->getPendingException()); 17 | 18 | $v8->clearPendingException(); 19 | var_dump($v8->getPendingException()); 20 | 21 | ?> 22 | ===EOF=== 23 | --EXPECTF-- 24 | Deprecated: V8Js::__construct(): Disabling exception reporting is deprecated, $report_uncaught_exceptions != true in %s%eexception_clearing.php on line 3 25 | 26 | Deprecated: Function V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 5 27 | NULL 28 | 29 | Deprecated: Function V8Js::clearPendingException() is deprecated in %s%eexception_clearing.php on line 7 30 | 31 | Deprecated: Function V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 8 32 | NULL 33 | 34 | Deprecated: Function V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 11 35 | object(V8JsScriptException)#%d (13) { 36 | ["message":protected]=> 37 | string(49) "throw_0:1: ReferenceError: fooobar is not defined" 38 | ["string":"Exception":private]=> 39 | string(0) "" 40 | ["code":protected]=> 41 | int(0) 42 | ["file":protected]=> 43 | string(%d) "%s" 44 | ["line":protected]=> 45 | int(10) 46 | ["trace":"Exception":private]=> 47 | array(1) { 48 | [0]=> 49 | array(6) { 50 | ["file"]=> 51 | string(%d) "%s" 52 | ["line"]=> 53 | int(10) 54 | ["function"]=> 55 | string(13) "executeString" 56 | ["class"]=> 57 | string(4) "V8Js" 58 | ["type"]=> 59 | string(2) "->" 60 | ["args"]=> 61 | array(2) { 62 | [0]=> 63 | string(7) "fooobar" 64 | [1]=> 65 | string(7) "throw_0" 66 | } 67 | } 68 | } 69 | ["previous":"Exception":private]=> 70 | NULL 71 | ["JsFileName":protected]=> 72 | string(7) "throw_0" 73 | ["JsLineNumber":protected]=> 74 | int(1) 75 | ["JsStartColumn":protected]=> 76 | int(0) 77 | ["JsEndColumn":protected]=> 78 | int(1) 79 | ["JsSourceLine":protected]=> 80 | string(7) "fooobar" 81 | ["JsTrace":protected]=> 82 | string(57) "ReferenceError: fooobar is not defined 83 | at throw_0:1:1" 84 | } 85 | 86 | Deprecated: Function V8Js::clearPendingException() is deprecated in %s%eexception_clearing.php on line 13 87 | 88 | Deprecated: Function V8Js::getPendingException() is deprecated in %s%eexception_clearing.php on line 14 89 | NULL 90 | ===EOF=== 91 | -------------------------------------------------------------------------------- /tests/phpt/exception_propagation_1.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Exception propagation test 1 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | v8 = new V8Js(); 14 | $this->v8->foo = $this; 15 | $this->v8->executeString('fooobar', 'throw_0'); 16 | var_dump($this->v8->getPendingException()); 17 | $this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch1'); 18 | $this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch2'); 19 | } 20 | 21 | public function bar() 22 | { 23 | echo "To Bar!\n"; 24 | $this->v8->executeString('throw new Error();', 'throw_1'); 25 | } 26 | } 27 | 28 | try { 29 | $foo = new Foo(); 30 | } catch (V8JsScriptException $e) { 31 | echo "PHP Exception: ", $e->getMessage(), "\n"; //var_dump($e); 32 | } 33 | ?> 34 | ===EOF=== 35 | --EXPECTF-- 36 | PHP Exception: throw_0:1: ReferenceError: fooobar is not defined 37 | ===EOF=== 38 | -------------------------------------------------------------------------------- /tests/phpt/exception_propagation_2.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Exception propagation test 2 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | v8 = new V8Js(null, array(), array(), false); 14 | $this->v8->foo = $this; 15 | $this->v8->executeString('fooobar', 'throw_0'); 16 | var_dump($this->v8->getPendingException()); 17 | // the exception is not cleared before the next executeString call, 18 | // hence the next *exiting* executeString will throw. 19 | // In this case this is the executeString call in bar() function. 20 | $this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch1'); 21 | $this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught!\n"); }', 'trycatch2'); 22 | } 23 | 24 | public function bar() 25 | { 26 | echo "To Bar!\n"; 27 | // This executeString call throws a PHP exception, not propagated 28 | // to JS, hence immediately triggering the top-level catch handler. 29 | $this->v8->executeString('throw new Error();', 'throw_1'); 30 | } 31 | } 32 | 33 | try { 34 | $foo = new Foo(); 35 | } catch (V8JsScriptException $e) { 36 | echo "PHP Exception: ", $e->getMessage(), "\n"; //var_dump($e); 37 | } 38 | ?> 39 | ===EOF=== 40 | --EXPECTF-- 41 | Deprecated: V8Js::__construct(): Disabling exception reporting is deprecated, $report_uncaught_exceptions != true in %s%eexception_propagation_2.php on line 8 42 | 43 | Deprecated: Function V8Js::getPendingException() is deprecated in %s%eexception_propagation_2.php on line 11 44 | object(V8JsScriptException)#%d (13) { 45 | ["message":protected]=> 46 | string(49) "throw_0:1: ReferenceError: fooobar is not defined" 47 | ["string":"Exception":private]=> 48 | string(0) "" 49 | ["code":protected]=> 50 | int(0) 51 | ["file":protected]=> 52 | string(%d) "%s" 53 | ["line":protected]=> 54 | int(10) 55 | ["trace":"Exception":private]=> 56 | array(2) { 57 | [0]=> 58 | array(6) { 59 | ["file"]=> 60 | string(%d) "%s" 61 | ["line"]=> 62 | int(10) 63 | ["function"]=> 64 | string(13) "executeString" 65 | ["class"]=> 66 | string(4) "V8Js" 67 | ["type"]=> 68 | string(2) "->" 69 | ["args"]=> 70 | array(2) { 71 | [0]=> 72 | string(7) "fooobar" 73 | [1]=> 74 | string(7) "throw_0" 75 | } 76 | } 77 | [1]=> 78 | array(6) { 79 | ["file"]=> 80 | string(%d) "%s" 81 | ["line"]=> 82 | int(29) 83 | ["function"]=> 84 | string(11) "__construct" 85 | ["class"]=> 86 | string(3) "Foo" 87 | ["type"]=> 88 | string(2) "->" 89 | ["args"]=> 90 | array(0) { 91 | } 92 | } 93 | } 94 | ["previous":"Exception":private]=> 95 | NULL 96 | ["JsFileName":protected]=> 97 | string(7) "throw_0" 98 | ["JsLineNumber":protected]=> 99 | int(1) 100 | ["JsStartColumn":protected]=> 101 | int(0) 102 | ["JsEndColumn":protected]=> 103 | int(1) 104 | ["JsSourceLine":protected]=> 105 | string(7) "fooobar" 106 | ["JsTrace":protected]=> 107 | string(57) "ReferenceError: fooobar is not defined 108 | at throw_0:1:1" 109 | } 110 | To Bar! 111 | PHP Exception: throw_0:1: ReferenceError: fooobar is not defined 112 | ===EOF=== 113 | -------------------------------------------------------------------------------- /tests/phpt/exception_propagation_3.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Exception propagation test 3 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | v8 = new V8Js(null, array(), array(), false); 14 | $this->v8->foo = $this; 15 | $this->v8->executeString('function foobar() { throw new SyntaxError(); }', 'throw_1'); 16 | $this->v8->executeString('try { foobar(); } catch (e) { print(e + " caught in JS!\n"); }', 'trycatch1'); 17 | $this->v8->executeString('try { PHP.foo.bar(); } catch (e) { print(e + " caught via PHP callback!\n"); }', 'trycatch2'); 18 | } 19 | 20 | public function bar() 21 | { 22 | echo "To Bar!\n"; 23 | $this->v8->executeString('throw new Error();', 'throw_2'); 24 | } 25 | } 26 | 27 | try { 28 | $foo = new Foo(); 29 | } catch (V8JsScriptException $e) { 30 | echo "PHP Exception: ", $e->getMessage(), "\n"; 31 | } 32 | ?> 33 | ===EOF=== 34 | --EXPECTF-- 35 | Deprecated: V8Js::__construct(): Disabling exception reporting is deprecated, $report_uncaught_exceptions != true in %s%eexception_propagation_3.php on line 8 36 | SyntaxError caught in JS! 37 | To Bar! 38 | Error caught via PHP callback! 39 | ===EOF=== 40 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/extensions_basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::registerExtension() : Basic extension registering 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 15 | ===EOF=== 16 | --EXPECTF-- 17 | Deprecated: Function V8Js::registerExtension() is deprecated in %s%eextensions_basic.php on line 3 18 | 19 | Deprecated: Function V8Js::registerExtension() is deprecated in %s%eextensions_basic.php on line 4 20 | 21 | Deprecated: Function V8Js::getExtensions() is deprecated in %s%eextensions_basic.php on line 6 22 | array(2) { 23 | ["a"]=> 24 | array(2) { 25 | ["auto_enable"]=> 26 | bool(false) 27 | ["deps"]=> 28 | array(1) { 29 | [0]=> 30 | string(1) "b" 31 | } 32 | } 33 | ["b"]=> 34 | array(1) { 35 | ["auto_enable"]=> 36 | bool(false) 37 | } 38 | } 39 | 40 | Deprecated: V8Js::__construct(): Use of extensions is deprecated, $extensions array passed in %s%eextensions_basic.php on line 8 41 | Hello world! 42 | ===EOF=== 43 | -------------------------------------------------------------------------------- /tests/phpt/extensions_circular_dependency.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::registerExtension() : Circular dependencies 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 15 | --EXPECTF-- 16 | Deprecated: Function V8Js::registerExtension() is deprecated in %s%eextensions_circular_dependency.php on line 3 17 | 18 | Deprecated: Function V8Js::registerExtension() is deprecated in %s%eextensions_circular_dependency.php on line 4 19 | 20 | Deprecated: Function V8Js::getExtensions() is deprecated in %s%eextensions_circular_dependency.php on line 6 21 | array(2) { 22 | ["a"]=> 23 | array(2) { 24 | ["auto_enable"]=> 25 | bool(false) 26 | ["deps"]=> 27 | array(1) { 28 | [0]=> 29 | string(1) "b" 30 | } 31 | } 32 | ["b"]=> 33 | array(2) { 34 | ["auto_enable"]=> 35 | bool(false) 36 | ["deps"]=> 37 | array(1) { 38 | [0]=> 39 | string(1) "a" 40 | } 41 | } 42 | } 43 | 44 | Deprecated: V8Js::__construct(): Use of extensions is deprecated, $extensions array passed in %s%eextensions_circular_dependency.php on line 8 45 | 46 | Warning: Fatal V8 error in v8::Context::New(): Circular extension dependency in %s on line 8 47 | 48 | Fatal error: Uncaught V8JsException: Failed to create V8 context. Check that registered extensions do not have errors. in %s:8 49 | Stack trace: 50 | #0 %s(8): V8Js->__construct('myobj', Array, Array) 51 | #1 {main} 52 | thrown in %s on line 8 53 | -------------------------------------------------------------------------------- /tests/phpt/extensions_error.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::registerExtension() : Register extension with errors 3 | --SKIPIF-- 4 | (.*)/", $minfo, $matches)) { 13 | $version = explode('.', $matches[1]); 14 | if($version[0] < 5 || ($version[0] == 5 && $version[1] < 7)) { 15 | // old v8 version, has shorter error message and hence doesn't 16 | // fit our EXCEPTF below 17 | echo "SKIP too old V8 version"; 18 | } 19 | } 20 | 21 | ?> 22 | --FILE-- 23 | 32 | ===EOF=== 33 | --EXPECTF-- 34 | -- registerExtension -- 35 | 36 | Deprecated: Function V8Js::registerExtension() is deprecated in %s%eextensions_error.php on line 5 37 | -- creating V8Js object -- 38 | Error installing extension 'handlebars'. 39 | 40 | Fatal error: Uncaught V8JsException: Failed to create V8 context. Check that registered extensions do not have errors. in %s%eextensions_error.php:7 41 | Stack trace: 42 | #0 %s%eextensions_error.php(7): V8Js->__construct() 43 | #1 {main} 44 | thrown in %s%eextensions_error.php on line 7 45 | -------------------------------------------------------------------------------- /tests/phpt/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 | Notice: Undefined variable: bar 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/phpt/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]: {closure}() 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/phpt/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]: {closure}() 41 | #1 [internal function]: Closure->__invoke() 42 | #2 %s%efatal_error_recursive.php(12): V8Js->executeString('PHP.baz();') 43 | #3 [internal function]: {closure}() 44 | #4 [internal function]: Closure->__invoke() 45 | #5 %s%efatal_error_recursive.php(17): V8Js->executeString('PHP.bar();') 46 | #6 [internal function]: {closure}() 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/phpt/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]: {closure}() 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/phpt/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/phpt/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 [internal function]: 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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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]: {closure}() 41 | #1 [internal function]: Closure->__invoke() 42 | #2 %s: V8Generator->next() 43 | #3 {main} 44 | thrown in %s 45 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/has_property_after_dispose.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : has_property after dispose 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | x = $x; 12 | } 13 | } 14 | 15 | $v8 = new V8Js(); 16 | $v8->foo = $foo = new Foo(); 17 | 18 | $JS = <<< EOT 19 | PHP.foo.callMe({ bla: 23 }); 20 | 21 | EOT; 22 | 23 | $v8->executeString($JS, 'basic.js'); 24 | unset($v8); 25 | 26 | try { 27 | var_dump(property_exists($foo->x, 'bla')); 28 | } 29 | catch(V8JsException $e) { 30 | var_dump($e->getMessage()); 31 | } 32 | ?> 33 | ===EOF=== 34 | --EXPECTF-- 35 | bool(true) 36 | string(55) "Can't access V8Object after V8Js instance is destroyed!" 37 | ===EOF=== 38 | 39 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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); 40 | 41 | ?> 42 | ===EOF=== 43 | --EXPECTF-- 44 | string(8) "function" 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(9) "undefined" 55 | string(9) "undefined" 56 | string(6) "caught" 57 | ===EOF=== 58 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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; 15 | } 16 | 17 | public function getData() { 18 | return $this->data; 19 | } 20 | 21 | public function getMeta() { 22 | return $this->meta; 23 | } 24 | 25 | public function setData($data=[]) { 26 | $this->data = $data; 27 | } 28 | 29 | public function setMeta($meta) { 30 | return; 31 | } 32 | } 33 | 34 | $v8 = new V8Js("server"); 35 | $code = <<< EOT 36 | var v1 = server.response.getData(); 37 | var v2 = server.response.getMeta(); 38 | 39 | server.response.setData({}); 40 | server.response.setTitle("ouch"); 41 | server.response.setMeta({}); 42 | EOT; 43 | 44 | $response = new TestObject(); 45 | 46 | $v8->response = $response; 47 | 48 | try { 49 | $result = $v8->executeString($code); 50 | var_dump($v8->response); 51 | } catch (V8JsException $e) { 52 | var_dump($e); 53 | } 54 | 55 | ?> 56 | ===EOF=== 57 | --EXPECTREGEX-- 58 | (?:Warning\: Creating default object from empty value in [^\r\n]+\/issue_250_001\.php on line 9\s*)+ 59 | object\(TestObject\)\#\d+ \(3\) \{ 60 | \["data"\:"TestObject"\:private\]\=\> 61 | object\(V8Object\)\#\d+ \(0\) \{ 62 | \} 63 | \["meta"\:"TestObject"\:private\]\=\> 64 | array\(0\) \{ 65 | \} 66 | \["a"\]\=\> 67 | object\(stdClass\)\#\d+ \(1\) \{ 68 | \["b"\]\=\> 69 | object\(stdClass\)\#\d+ \(1\) \{ 70 | \["title"\]\=\> 71 | string\(4\) "ouch" 72 | \} 73 | \} 74 | \} 75 | \=\=\=EOF\=\=\= 76 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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(29) 56 | ["trace":"Exception":private]=> 57 | array(1) { 58 | [0]=> 59 | array(6) { 60 | ["file"]=> 61 | string(%d) "%s" 62 | ["line"]=> 63 | int(29) 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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/object_method_call.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Calling methods of object passed from PHP 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | date.timezone=UTC 7 | --FILE-- 8 | setTimeZone(new DateTimeZone(ini_get('date.timezone'))); 24 | echo $date->format(DateTime::RFC1123), "\n"; 25 | var_dump($b); 26 | } 27 | } 28 | 29 | $a = new V8Js(); 30 | $a->myobj = new Testing(); 31 | 32 | $a->executeString("PHP.myobj.mytest('arg1', 'arg2');", "test1.js"); 33 | $a->executeString("PHP.myobj.mytest(true, false, 1234567890);", "test2.js"); 34 | $a->executeString("PHP.myobj.mytest(3.14, 42, null);", "test3.js"); 35 | 36 | // Invalid parameters 37 | try { 38 | $a->executeString("PHP.myobj.mytest();", "test4.js"); 39 | } catch (V8JsScriptException $e) { 40 | echo $e->getMessage(), "\n"; 41 | } 42 | 43 | try { 44 | $a->executeString("PHP.myobj.mytest('arg1', 'arg2', 'arg3', 'extra_arg');", "test5.js"); 45 | } catch (V8JsScriptException $e) { 46 | echo $e->getMessage(), "\n"; 47 | } 48 | 49 | try { 50 | echo "\nTEST: Javascript Date -> PHP DateTime\n"; 51 | echo "======================================\n"; 52 | $a->executeString("date = new Date('September 8, 1975 09:00:00 GMT'); print(date.toUTCString() + '\\n'); PHP.myobj.mydatetest(date, 'foo');", "test6.js"); 53 | } catch (V8JsScriptException $e) { 54 | echo $e->getMessage(), "\n"; 55 | } 56 | 57 | // Array / Object 58 | try { 59 | $a->executeString("PHP.myobj.mytest(PHP.myobj, new Array(1,2,3), new Array('foo', 'bar', PHP.myobj));", "test7.js"); 60 | } catch (V8JsScriptException $e) { 61 | var_dump($e); 62 | } 63 | 64 | // Type safety 65 | // this is illegal, but shouldn't crash! 66 | try { 67 | $a->executeString("PHP.myobj.mytest.call({})", "test8.js"); 68 | } catch (V8JsScriptException $e) { 69 | echo "exception: ", $e->getMessage(), "\n"; 70 | } 71 | 72 | ?> 73 | ===EOF=== 74 | --EXPECTF-- 75 | array(2) { 76 | [0]=> 77 | string(4) "arg1" 78 | [1]=> 79 | string(4) "arg2" 80 | } 81 | array(3) { 82 | [0]=> 83 | bool(true) 84 | [1]=> 85 | bool(false) 86 | [2]=> 87 | int(1234567890) 88 | } 89 | array(3) { 90 | [0]=> 91 | float(3.14) 92 | [1]=> 93 | int(42) 94 | [2]=> 95 | NULL 96 | } 97 | test4.js:1: TypeError: Testing::mytest() expects at least 2 parameters, 0 given 98 | array(4) { 99 | [0]=> 100 | string(4) "arg1" 101 | [1]=> 102 | string(4) "arg2" 103 | [2]=> 104 | string(4) "arg3" 105 | [3]=> 106 | string(9) "extra_arg" 107 | } 108 | 109 | TEST: Javascript Date -> PHP DateTime 110 | ====================================== 111 | Mon, 08 Sep 1975 09:00:00 GMT 112 | Mon, 08 Sep 1975 09:00:00 +0000 113 | string(3) "foo" 114 | array(3) { 115 | [0]=> 116 | object(Testing)#%d (3) { 117 | ["foo"]=> 118 | string(8) "ORIGINAL" 119 | ["my_private":"Testing":private]=> 120 | string(3) "arf" 121 | ["my_protected":protected]=> 122 | string(4) "argh" 123 | } 124 | [1]=> 125 | array(3) { 126 | [0]=> 127 | int(1) 128 | [1]=> 129 | int(2) 130 | [2]=> 131 | int(3) 132 | } 133 | [2]=> 134 | array(3) { 135 | [0]=> 136 | string(3) "foo" 137 | [1]=> 138 | string(3) "bar" 139 | [2]=> 140 | object(Testing)#%d (3) { 141 | ["foo"]=> 142 | string(8) "ORIGINAL" 143 | ["my_private":"Testing":private]=> 144 | string(3) "arf" 145 | ["my_protected":protected]=> 146 | string(4) "argh" 147 | } 148 | } 149 | } 150 | exception: test8.js:1: TypeError: Illegal invocation 151 | ===EOF=== 152 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | . 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/phpt/property_exists.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : property_exists/isset/empty on wrapped JS objects 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | executeString($JS, 'basic.js'); 28 | 29 | echo "= isset() =\n"; 30 | echo "bogus: "; var_dump(isset( $exports->bogus )); 31 | echo "hello: "; var_dump(isset( $exports->hello )); 32 | echo "isnull: "; var_dump(isset( $exports->isnull )); 33 | echo "isundefined: "; var_dump(isset( $exports->isundefined )); 34 | echo "isfalse: "; var_dump(isset( $exports->isfalse )); 35 | echo "iszero: "; var_dump(isset( $exports->iszero )); 36 | echo "isquotezero: "; var_dump(isset( $exports->isquotezero )); 37 | echo "isemptyarray: "; var_dump(isset( $exports->isemptyarray )); 38 | echo "isemptystring: "; var_dump(isset( $exports->isemptystring )); 39 | echo "istrue: "; var_dump(isset( $exports->istrue )); 40 | echo "\n"; 41 | 42 | echo "= empty() =\n"; 43 | echo "bogus: "; var_dump(empty( $exports->bogus )); 44 | echo "hello: "; var_dump(empty( $exports->hello )); 45 | echo "isnull: "; var_dump(empty( $exports->isnull )); 46 | echo "isundefined: "; var_dump(empty( $exports->isundefined )); 47 | echo "isfalse: "; var_dump(empty( $exports->isfalse )); 48 | echo "iszero: "; var_dump(empty( $exports->iszero )); 49 | echo "isquotezero: "; var_dump(empty( $exports->isquotezero )); 50 | echo "isemptyarray: "; var_dump(empty( $exports->isemptyarray )); 51 | echo "isemptystring: "; var_dump(empty( $exports->isemptystring )); 52 | echo "istrue: "; var_dump(empty( $exports->istrue )); 53 | echo "\n"; 54 | 55 | echo "= property_exists() =\n"; 56 | echo "bogus: "; var_dump(property_exists( $exports, 'bogus' )); 57 | echo "hello: "; var_dump(property_exists( $exports, 'hello' )); 58 | echo "isnull: "; var_dump(property_exists( $exports, 'isnull' )); 59 | echo "isundefined: "; var_dump(property_exists( $exports, 'isundefined' )); 60 | echo "isfalse: "; var_dump(property_exists( $exports, 'isfalse' )); 61 | echo "iszero: "; var_dump(property_exists( $exports, 'iszero' )); 62 | echo "isquotezero: "; var_dump(property_exists( $exports, 'isquotezero' )); 63 | echo "isemptyarray: "; var_dump(property_exists( $exports, 'isemptyarray' )); 64 | echo "isemptystring: "; var_dump(property_exists( $exports, 'isemptystring' )); 65 | echo "istrue: "; var_dump(property_exists( $exports, 'istrue' )); 66 | echo "\n"; 67 | 68 | ?> 69 | ===EOF=== 70 | --EXPECT-- 71 | = isset() = 72 | bogus: bool(false) 73 | hello: bool(true) 74 | isnull: bool(false) 75 | isundefined: bool(false) 76 | isfalse: bool(true) 77 | iszero: bool(true) 78 | isquotezero: bool(true) 79 | isemptyarray: bool(true) 80 | isemptystring: bool(true) 81 | istrue: bool(true) 82 | 83 | = empty() = 84 | bogus: bool(true) 85 | hello: bool(false) 86 | isnull: bool(true) 87 | isundefined: bool(true) 88 | isfalse: bool(true) 89 | iszero: bool(true) 90 | isquotezero: bool(true) 91 | isemptyarray: bool(true) 92 | isemptystring: bool(true) 93 | istrue: bool(false) 94 | 95 | = property_exists() = 96 | bogus: bool(false) 97 | hello: bool(true) 98 | isnull: bool(true) 99 | isundefined: bool(true) 100 | isfalse: bool(true) 101 | iszero: bool(true) 102 | isquotezero: bool(true) 103 | isemptyarray: bool(true) 104 | isemptystring: bool(true) 105 | istrue: bool(true) 106 | 107 | ===EOF=== 108 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/property_visibility-has-property.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility - has property 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | foo = new Foo(); 16 | 17 | $script = <<executeString($script); 37 | 38 | ?> 39 | ===EOF=== 40 | --EXPECT-- 41 | bool(false) 42 | bool(false) 43 | bool(true) 44 | bool(false) 45 | bool(true) 46 | bool(true) 47 | bool(true) 48 | bool(true) 49 | ===EOF=== 50 | -------------------------------------------------------------------------------- /tests/phpt/property_visibility-set.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Property visibility - set 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | privBar); 15 | var_dump($this->protBar); 16 | var_dump($this->pubBar); 17 | var_dump($this->unknownBar); 18 | } 19 | } 20 | 21 | $js = new V8Js(); 22 | $js->foo = new Foo(); 23 | 24 | $script = <<executeString($script); 39 | $js->foo->dump(); 40 | ?> 41 | ===EOF=== 42 | --EXPECT-- 43 | string(6) "jsPriv" 44 | string(6) "jsProt" 45 | string(5) "jsPub" 46 | string(9) "jsUnknown" 47 | string(7) "privBar" 48 | string(7) "protBar" 49 | string(5) "jsPub" 50 | string(9) "jsUnknown" 51 | ===EOF=== 52 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/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/phpt/timezones.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Check timezone handling 3 | --SKIPIF-- 4 | SKIP test currently broken, see #378 5 | 6 | 12 | --FILE-- 13 | executeString('print (new Date("Thu, 20 Mar 2014 09:03:24 +0000")).toString();'); 19 | echo "\n"; 20 | } catch (V8JsScriptException $e) { 21 | var_dump($e->getMessage()); 22 | } 23 | 24 | try { 25 | putenv('TZ=America/New_York'); 26 | $v8->executeString('print (new Date("Thu, 20 Mar 2014 09:03:24 +0000")).toString();'); 27 | echo "\n"; 28 | } catch (V8JsScriptException $e) { 29 | var_dump($e->getMessage()); 30 | } 31 | 32 | try { 33 | putenv('TZ=Europe/Helsinki'); 34 | $v8->executeString('print (new Date("Thu, 20 Mar 2014 09:03:24 +0000")).toString();'); 35 | echo "\n"; 36 | } catch (V8JsScriptException $e) { 37 | var_dump($e->getMessage()); 38 | } 39 | ?> 40 | ===EOF=== 41 | --EXPECT-- 42 | Thu Mar 20 2014 11:03:24 GMT+0200 (EET) 43 | Thu Mar 20 2014 05:03:24 GMT-0400 (EDT) 44 | Thu Mar 20 2014 11:03:24 GMT+0200 (EET) 45 | ===EOF=== 46 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/use_after_dispose.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test V8::executeString() : Use after dispose 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | x = $x; 12 | } 13 | } 14 | 15 | $v8 = new V8Js(); 16 | $v8->foo = $foo = new Foo(); 17 | 18 | $JS = <<< EOT 19 | PHP.foo.callMe({ bla: 23 }); 20 | 21 | EOT; 22 | 23 | $v8->executeString($JS, 'basic.js'); 24 | unset($v8); 25 | 26 | try { 27 | var_dump($foo->x); 28 | } 29 | catch(V8JsException $e) { 30 | var_dump($e->getMessage()); 31 | } 32 | ?> 33 | ===EOF=== 34 | --EXPECTF-- 35 | object(V8Object)#%d (1) { 36 | ["bla"]=> 37 | int(23) 38 | } 39 | object(V8Object)#%d (0) { 40 | } 41 | string(55) "Can't access V8Object after V8Js instance is destroyed!" 42 | ===EOF=== 43 | -------------------------------------------------------------------------------- /tests/phpt/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/phpt/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/phpt/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 | -------------------------------------------------------------------------------- /tests/react-wp-ssr.php: -------------------------------------------------------------------------------- 1 | [ 15 | 'hash' => '', 16 | 'host' => 'localhost', 17 | 'hostname' => 'localhost', 18 | 'pathname' => $path, 19 | 'port' => $port, 20 | 'protocol' => 'http:', 21 | 'search' => $query ? '?' . $query : '', 22 | ], 23 | ]; 24 | } 25 | 26 | // Create stubs. 27 | $window = json_encode( get_window_object() ); 28 | $setup = << it => print( JSON.stringify( it ) ) )( print ) 37 | }; 38 | window.setTimeout = window.clearTimeout = () => {}; 39 | 40 | // Expose more globals we might want. 41 | var global = global || this, 42 | self = self || this; 43 | var isSSR = true; 44 | 45 | // Remove default top-level APIs. 46 | delete exit; 47 | delete var_dump; 48 | delete require; 49 | delete sleep; 50 | END; 51 | 52 | $v8 = new V8Js(); 53 | 54 | /** 55 | * Filter functions available to the server-side rendering. 56 | * 57 | * @param array $functions Map of function name => callback. Exposed on the global `PHP` object. 58 | * @param string $handle Script being rendered. 59 | * @param array $options Options passed to render. 60 | */ 61 | // $functions = apply_filters( 'reactwpssr.functions', [], $handle, $options ); 62 | $functions = []; 63 | foreach ( $functions as $name => $function ) { 64 | $v8->$name = $function; 65 | } 66 | 67 | // Load the app source. 68 | $source = file_get_contents( __DIR__ . '/react-wp-scripts-bundle.js' ); 69 | try { 70 | // Run the setup. 71 | $v8->executeString( $setup, 'ssrBootstrap' ); 72 | 73 | // Then, execute the script. 74 | ob_start(); 75 | $v8->executeString( $source, './react-wp-scripts-bundle.js' ); 76 | $output = ob_get_clean(); 77 | 78 | echo $output; 79 | } catch ( V8JsScriptException $e ) { 80 | // handle_exception($e); 81 | echo $e->getMessage(); 82 | } 83 | 84 | /** 85 | * Render JS exception handler. 86 | * 87 | * @param V8JsScriptException $e Exception to handle. 88 | */ 89 | function handle_exception( V8JsScriptException $e ) { 90 | $file = $e->getJsFileName(); 91 | ?> 92 | 93 |
94 |
Failed to render
95 |
getJsTrace();
 99 | 			if ( $trace ) {
100 | 				$trace_lines = $error = explode( "\n", $e->getJsTrace() );
101 | 				echo esc_html( $trace_lines[0] ) . "\n\n";
102 | 			} else {
103 | 				echo $e->getMessage() . "\n\n";
104 | 			}
105 | 
106 | 			// Replace tabs with tab character.
107 | 			$prefix = '> ' . (int) $e->getJsLineNumber() . ' | ';
108 | 			echo $prefix . str_replace(
109 | 				"\t",
110 | 				'',
111 | 				esc_html( $e->getJsSourceLine() )
112 | 			) . "\n";
113 | 			echo str_repeat( " ", strlen( $prefix ) + $e->getJsStartColumn() );
114 | 			echo str_repeat( "^", $e->getJsEndColumn() - $e->getJsStartColumn() ) . "\n";
115 | 			?>
116 | 124 |
125 | n < 3 ? 1 : fibonacci(n - 1) + fibonacci(n - 2)'); 3 | $jscript = new V8Js('php', array(), array(), true, $snapshot); 4 | $result = $jscript->executeString('fibonacci(10)'); 5 | assert($result === 55); 6 | 7 | -------------------------------------------------------------------------------- /tests/time_limit.php: -------------------------------------------------------------------------------- 1 | sleep = function ( int $milliseconds ) { 5 | usleep( $milliseconds * 1000 ); 6 | }; 7 | 8 | $killed = null; 9 | $used_time_limit_exception = false; 10 | try { 11 | $result = $v8js->executeString( 'for ( let i = 0; i < 100 ; i++ ) { PHP.sleep(100); }; "done"', null, null, 100 ); 12 | $killed = false; 13 | } catch( V8JsTimeLimitException ) { 14 | $killed = true; 15 | $used_time_limit_exception = true; 16 | } catch ( Exception $e ) { 17 | $killed = true; 18 | } 19 | assert( $killed === true ); 20 | assert( $used_time_limit_exception === true ); 21 | -------------------------------------------------------------------------------- /tests/version.php: -------------------------------------------------------------------------------- 1 |