2014-12-12 22:59:28 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| PHP Version 5 |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2015-08-23 13:09:21 +00:00
| Copyright ( c ) 1997 - 2015 The PHP Group |
2014-12-12 22:59:28 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| http : //www.opensource.org/licenses/mit-license.php MIT License |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Author : Jani Taskinen < jani . taskinen @ iki . fi > |
| Author : Patrick Reilly < preilly @ php . net > |
2015-08-23 13:09:21 +00:00
| Author : Stefan Siegl < stesie @ php . net > |
2014-12-12 22:59:28 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2016-01-06 09:01:35 +00:00
# include <functional>
# include <algorithm>
# include "php_v8js_macros.h"
# include "v8js_v8.h"
# include "v8js_exceptions.h"
# include "v8js_v8object_class.h"
# include "v8js_timer.h"
2014-12-12 22:59:28 +00:00
extern " C " {
# include "php.h"
# include "ext/date/php_date.h"
# include "ext/standard/php_string.h"
# include "zend_interfaces.h"
# include "zend_closures.h"
# include "ext/spl/spl_exceptions.h"
# include "zend_exceptions.h"
}
# define PHP_V8JS_SCRIPT_RES_NAME "V8Js script"
/* {{{ Class Entries */
static zend_class_entry * php_ce_v8js ;
/* }}} */
/* {{{ Object Handlers */
static zend_object_handlers v8js_object_handlers ;
/* }}} */
2014-12-13 00:30:23 +00:00
typedef struct _v8js_script {
char * name ;
2015-08-02 21:35:47 +00:00
v8js_ctx * ctx ;
2014-12-13 00:30:23 +00:00
v8 : : Persistent < v8 : : Script , v8 : : CopyablePersistentTraits < v8 : : Script > > * script ;
} v8js_script ;
2015-08-02 20:36:23 +00:00
static void v8js_script_free ( v8js_script * res ) ;
2014-12-13 00:30:23 +00:00
2014-12-12 22:59:28 +00:00
int le_v8js_script ;
/* {{{ Extension container */
2014-12-13 00:30:23 +00:00
struct v8js_jsext {
2014-12-12 22:59:28 +00:00
zend_bool auto_enable ;
HashTable * deps_ht ;
const char * * deps ;
int deps_count ;
2015-08-24 20:05:27 +00:00
zend_string * name ;
zend_string * source ;
2015-08-02 17:42:42 +00:00
v8 : : Extension * extension ;
2014-12-12 22:59:28 +00:00
} ;
/* }}} */
2015-07-25 15:28:08 +00:00
# if PHP_V8_API_VERSION >= 4004010
2015-07-25 13:34:19 +00:00
class ArrayBufferAllocator : public v8 : : ArrayBuffer : : Allocator {
public :
virtual void * Allocate ( size_t length ) {
void * data = AllocateUninitialized ( length ) ;
return data = = NULL ? data : memset ( data , 0 , length ) ;
}
virtual void * AllocateUninitialized ( size_t length ) { return malloc ( length ) ; }
virtual void Free ( void * data , size_t ) { free ( data ) ; }
} ;
# endif
2014-12-12 22:59:28 +00:00
2015-08-24 20:19:15 +00:00
static void v8js_free_storage ( zend_object * object TSRMLS_DC ) /* { { { */
2014-12-12 22:59:28 +00:00
{
2015-08-24 22:24:04 +00:00
v8js_ctx * c = v8js_ctx_fetch_object ( object ) ;
2014-12-12 22:59:28 +00:00
zend_object_std_dtor ( & c - > std TSRMLS_CC ) ;
2015-08-24 20:05:27 +00:00
zval_dtor ( & c - > pending_exception ) ;
2015-12-31 19:25:24 +00:00
zval_dtor ( & c - > module_normaliser ) ;
2015-08-24 20:05:27 +00:00
zval_dtor ( & c - > module_loader ) ;
2014-12-12 22:59:28 +00:00
/* Delete PHP global object from JavaScript */
if ( ! c - > context . IsEmpty ( ) ) {
v8 : : Locker locker ( c - > isolate ) ;
v8 : : Isolate : : Scope isolate_scope ( c - > isolate ) ;
v8 : : HandleScope handle_scope ( c - > isolate ) ;
v8 : : Local < v8 : : Context > v8_context = v8 : : Local < v8 : : Context > : : New ( c - > isolate , c - > context ) ;
v8 : : Context : : Scope context_scope ( v8_context ) ;
v8 : : Local < v8 : : String > object_name_js = v8 : : Local < v8 : : String > : : New ( c - > isolate , c - > object_name ) ;
V8JS_GLOBAL ( c - > isolate ) - > Delete ( object_name_js ) ;
}
c - > object_name . Reset ( ) ;
c - > object_name . ~ Persistent ( ) ;
c - > global_template . Reset ( ) ;
c - > global_template . ~ Persistent ( ) ;
2015-09-01 13:53:21 +00:00
c - > array_tmpl . Reset ( ) ;
c - > array_tmpl . ~ Persistent ( ) ;
2014-12-12 22:59:28 +00:00
2015-08-27 12:46:27 +00:00
/* Clear persistent call_impl & method_tmpls templates */
for ( std : : map < v8js_tmpl_t * , v8js_tmpl_t > : : iterator it = c - > call_impls . begin ( ) ;
it ! = c - > call_impls . end ( ) ; + + it ) {
// No need to free it->first, as it is stored in c->template_cache and freed below
it - > second . Reset ( ) ;
}
c - > call_impls . ~ map ( ) ;
for ( std : : map < zend_function * , v8js_tmpl_t > : : iterator it = c - > method_tmpls . begin ( ) ;
it ! = c - > method_tmpls . end ( ) ; + + it ) {
it - > second . Reset ( ) ;
}
c - > method_tmpls . ~ map ( ) ;
2014-12-12 22:59:28 +00:00
/* Clear persistent handles in template cache */
2015-08-29 09:57:53 +00:00
for ( std : : map < const zend_string * , v8js_tmpl_t > : : iterator it = c - > template_cache . begin ( ) ;
2014-12-12 22:59:28 +00:00
it ! = c - > template_cache . end ( ) ; + + it ) {
it - > second . Reset ( ) ;
}
c - > template_cache . ~ map ( ) ;
/* Clear contexts */
2014-12-13 00:15:29 +00:00
for ( std : : vector < v8js_accessor_ctx * > : : iterator it = c - > accessor_list . begin ( ) ;
2014-12-12 22:59:28 +00:00
it ! = c - > accessor_list . end ( ) ; + + it ) {
2014-12-13 00:15:29 +00:00
v8js_accessor_ctx_dtor ( * it TSRMLS_CC ) ;
2014-12-12 22:59:28 +00:00
}
c - > accessor_list . ~ vector ( ) ;
/* Clear global object, dispose context */
if ( ! c - > context . IsEmpty ( ) ) {
c - > context . Reset ( ) ;
}
c - > context . ~ Persistent ( ) ;
/* Dispose yet undisposed weak refs */
2015-08-24 20:05:27 +00:00
for ( std : : map < zend_object * , v8js_persistent_obj_t > : : iterator it = c - > weak_objects . begin ( ) ;
2014-12-12 22:59:28 +00:00
it ! = c - > weak_objects . end ( ) ; + + it ) {
2015-08-24 20:05:27 +00:00
zend_object * object = it - > first ;
zval value ;
ZVAL_OBJ ( & value , object ) ;
zval_dtor ( & value ) ;
2014-12-12 22:59:28 +00:00
c - > isolate - > AdjustAmountOfExternalAllocatedMemory ( - 1024 ) ;
it - > second . Reset ( ) ;
}
c - > weak_objects . ~ map ( ) ;
for ( std : : map < v8js_tmpl_t * , v8js_persistent_obj_t > : : iterator it = c - > weak_closures . begin ( ) ;
it ! = c - > weak_closures . end ( ) ; + + it ) {
v8js_tmpl_t * persist_tpl_ = it - > first ;
persist_tpl_ - > Reset ( ) ;
delete persist_tpl_ ;
it - > second . Reset ( ) ;
}
c - > weak_closures . ~ map ( ) ;
2014-12-12 23:13:03 +00:00
for ( std : : list < v8js_v8object * > : : iterator it = c - > v8js_v8objects . begin ( ) ;
it ! = c - > v8js_v8objects . end ( ) ; it + + ) {
2014-12-12 22:59:28 +00:00
( * it ) - > v8obj . Reset ( ) ;
( * it ) - > ctx = NULL ;
}
2014-12-12 23:13:03 +00:00
c - > v8js_v8objects . ~ list ( ) ;
2014-12-12 22:59:28 +00:00
2015-08-02 21:35:47 +00:00
for ( std : : vector < v8js_script * > : : iterator it = c - > script_objects . begin ( ) ;
it ! = c - > script_objects . end ( ) ; it + + ) {
( * it ) - > ctx = NULL ;
( * it ) - > script - > Reset ( ) ;
}
c - > script_objects . ~ vector ( ) ;
2014-12-12 22:59:28 +00:00
/* Clear persistent handles in module cache */
for ( std : : map < char * , v8js_persistent_obj_t > : : iterator it = c - > modules_loaded . begin ( ) ;
it ! = c - > modules_loaded . end ( ) ; + + it ) {
2015-08-01 15:49:11 +00:00
efree ( it - > first ) ;
2014-12-12 22:59:28 +00:00
it - > second . Reset ( ) ;
}
c - > modules_loaded . ~ map ( ) ;
if ( c - > isolate ) {
/* c->isolate is initialized by V8Js::__construct, but __wakeup calls
* are not fully constructed and hence this would cause a NPE . */
c - > isolate - > Dispose ( ) ;
}
if ( c - > tz ! = NULL ) {
free ( c - > tz ) ;
}
c - > modules_stack . ~ vector ( ) ;
c - > modules_base . ~ vector ( ) ;
}
/* }}} */
2015-08-24 20:05:27 +00:00
static zend_object * v8js_new ( zend_class_entry * ce TSRMLS_DC ) /* { { { */
2014-12-12 22:59:28 +00:00
{
2014-12-13 00:15:29 +00:00
v8js_ctx * c ;
2014-12-12 22:59:28 +00:00
2015-08-24 20:19:15 +00:00
c = ( v8js_ctx * ) ecalloc ( 1 , sizeof ( * c ) + zend_object_properties_size ( ce ) ) ;
2014-12-12 22:59:28 +00:00
zend_object_std_init ( & c - > std , ce TSRMLS_CC ) ;
2015-09-03 21:12:19 +00:00
object_properties_init ( & c - > std , ce ) ;
2015-08-29 16:52:30 +00:00
c - > std . handlers = & v8js_object_handlers ;
2014-12-12 22:59:28 +00:00
TSRMLS_SET_CTX ( c - > zts_ctx ) ;
new ( & c - > object_name ) v8 : : Persistent < v8 : : String > ( ) ;
new ( & c - > context ) v8 : : Persistent < v8 : : Context > ( ) ;
new ( & c - > global_template ) v8 : : Persistent < v8 : : FunctionTemplate > ( ) ;
2015-09-01 13:53:21 +00:00
new ( & c - > array_tmpl ) v8 : : Persistent < v8 : : FunctionTemplate > ( ) ;
2014-12-12 22:59:28 +00:00
new ( & c - > modules_stack ) std : : vector < char * > ( ) ;
new ( & c - > modules_base ) std : : vector < char * > ( ) ;
2015-08-01 15:49:11 +00:00
new ( & c - > modules_loaded ) std : : map < char * , v8js_persistent_obj_t , cmp_str > ;
2014-12-12 22:59:28 +00:00
2015-08-29 09:57:53 +00:00
new ( & c - > template_cache ) std : : map < const zend_string * , v8js_tmpl_t > ( ) ;
2014-12-13 00:15:29 +00:00
new ( & c - > accessor_list ) std : : vector < v8js_accessor_ctx * > ( ) ;
2014-12-12 22:59:28 +00:00
new ( & c - > weak_closures ) std : : map < v8js_tmpl_t * , v8js_persistent_obj_t > ( ) ;
2015-08-24 20:05:27 +00:00
new ( & c - > weak_objects ) std : : map < zend_object * , v8js_persistent_obj_t > ( ) ;
2015-08-27 12:46:27 +00:00
new ( & c - > call_impls ) std : : map < v8js_tmpl_t * , v8js_tmpl_t > ( ) ;
new ( & c - > method_tmpls ) std : : map < zend_function * , v8js_tmpl_t > ( ) ;
2014-12-12 22:59:28 +00:00
2014-12-12 23:13:03 +00:00
new ( & c - > v8js_v8objects ) std : : list < v8js_v8object * > ( ) ;
2015-08-02 21:35:47 +00:00
new ( & c - > script_objects ) std : : vector < v8js_script * > ( ) ;
2014-12-12 22:59:28 +00:00
2015-08-24 20:19:15 +00:00
// @fixme following is const, run on startup
v8js_object_handlers . offset = XtOffsetOf ( struct v8js_ctx , std ) ;
v8js_object_handlers . free_obj = v8js_free_storage ;
2014-12-12 22:59:28 +00:00
2015-08-24 20:19:15 +00:00
return & c - > std ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
2014-12-13 00:30:23 +00:00
static void v8js_free_ext_strarr ( const char * * arr , int count ) /* { { { */
2014-12-12 22:59:28 +00:00
{
int i ;
if ( arr ) {
for ( i = 0 ; i < count ; i + + ) {
if ( arr [ i ] ) {
free ( ( void * ) arr [ i ] ) ;
}
}
free ( arr ) ;
}
}
/* }}} */
2015-08-29 19:45:59 +00:00
static void v8js_jsext_free_storage ( v8js_jsext * jsext ) /* { { { */
2014-12-12 22:59:28 +00:00
{
if ( jsext - > deps_ht ) {
zend_hash_destroy ( jsext - > deps_ht ) ;
free ( jsext - > deps_ht ) ;
}
if ( jsext - > deps ) {
2014-12-13 00:30:23 +00:00
v8js_free_ext_strarr ( jsext - > deps , jsext - > deps_count ) ;
2014-12-12 22:59:28 +00:00
}
2015-08-02 17:42:42 +00:00
delete jsext - > extension ;
2015-08-24 20:05:27 +00:00
zend_string_release ( jsext - > name ) ;
zend_string_release ( jsext - > source ) ;
2015-08-29 19:45:59 +00:00
free ( jsext ) ;
}
/* }}} */
static void v8js_jsext_dtor ( zval * zv ) /* { { { */
{
v8js_jsext_free_storage ( reinterpret_cast < v8js_jsext * > ( Z_PTR_P ( zv ) ) ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
2014-12-13 00:30:23 +00:00
static int v8js_create_ext_strarr ( const char * * * retval , int count , HashTable * ht ) /* { { { */
2014-12-12 22:59:28 +00:00
{
const char * * exts = NULL ;
HashPosition pos ;
2015-08-24 22:24:04 +00:00
zval * tmp ;
2014-12-12 22:59:28 +00:00
int i = 0 ;
exts = ( const char * * ) calloc ( 1 , count * sizeof ( char * ) ) ;
zend_hash_internal_pointer_reset_ex ( ht , & pos ) ;
2015-08-24 22:24:04 +00:00
while ( ( tmp = zend_hash_get_current_data_ex ( ht , & pos ) ) ) {
if ( Z_TYPE_P ( tmp ) = = IS_STRING ) {
exts [ i + + ] = zend_strndup ( Z_STRVAL_P ( tmp ) , Z_STRLEN_P ( tmp ) ) ;
2014-12-12 22:59:28 +00:00
} else {
2014-12-13 00:30:23 +00:00
v8js_free_ext_strarr ( exts , i ) ;
2014-12-12 22:59:28 +00:00
return FAILURE ;
}
zend_hash_move_forward_ex ( ht , & pos ) ;
}
* retval = exts ;
return SUCCESS ;
}
/* }}} */
2014-12-13 00:30:23 +00:00
static void v8js_fatal_error_handler ( const char * location , const char * message ) /* { { { */
2014-12-12 22:59:28 +00:00
{
if ( location ) {
2015-12-30 16:53:46 +00:00
zend_error ( E_WARNING , " Fatal V8 error in %s: %s " , location , message ) ;
2014-12-12 22:59:28 +00:00
} else {
2015-12-30 16:53:46 +00:00
zend_error ( E_WARNING , " Fatal V8 error: %s " , message ) ;
2014-12-12 22:59:28 +00:00
}
}
/* }}} */
/* {{{ proto void V8Js::__construct([string object_name [, array variables [, array extensions [, bool report_uncaught_exceptions]]])
__construct for V8Js */
static PHP_METHOD ( V8Js , __construct )
{
2015-10-02 20:29:54 +00:00
zend_string * object_name = NULL ;
2014-12-12 22:59:28 +00:00
zend_bool report_uncaught = 1 ;
zval * vars_arr = NULL , * exts_arr = NULL ;
const char * * exts = NULL ;
int exts_count = 0 ;
2015-08-24 22:24:04 +00:00
v8js_ctx * c = Z_V8JS_CTX_OBJ_P ( getThis ( ) )
2014-12-12 22:59:28 +00:00
if ( ! c - > context . IsEmpty ( ) ) {
/* called __construct() twice, bail out */
return ;
}
2015-10-02 20:29:54 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |Saab " , & object_name , & vars_arr , & exts_arr , & report_uncaught ) = = FAILURE ) {
2014-12-12 22:59:28 +00:00
return ;
}
/* Initialize V8 */
v8js_v8_init ( TSRMLS_C ) ;
/* Throw PHP exception if uncaught exceptions exist */
c - > report_uncaught = report_uncaught ;
2015-08-24 20:05:27 +00:00
ZVAL_NULL ( & c - > pending_exception ) ;
2014-12-12 22:59:28 +00:00
c - > in_execution = 0 ;
2015-07-25 13:34:19 +00:00
# if PHP_V8_API_VERSION >= 4004044
static ArrayBufferAllocator array_buffer_allocator ;
static v8 : : Isolate : : CreateParams create_params ;
create_params . array_buffer_allocator = & array_buffer_allocator ;
c - > isolate = v8 : : Isolate : : New ( create_params ) ;
# else
2014-12-12 22:59:28 +00:00
c - > isolate = v8 : : Isolate : : New ( ) ;
2015-07-25 13:34:19 +00:00
# endif
2014-12-12 22:59:28 +00:00
c - > isolate - > SetData ( 0 , c ) ;
c - > time_limit = 0 ;
c - > time_limit_hit = false ;
c - > memory_limit = 0 ;
c - > memory_limit_hit = false ;
2015-12-31 19:25:24 +00:00
ZVAL_NULL ( & c - > module_normaliser ) ;
2015-08-24 20:05:27 +00:00
ZVAL_NULL ( & c - > module_loader ) ;
2014-12-12 22:59:28 +00:00
/* Include extensions used by this context */
/* Note: Extensions registered with auto_enable do not need to be added separately like this. */
if ( exts_arr )
{
exts_count = zend_hash_num_elements ( Z_ARRVAL_P ( exts_arr ) ) ;
2014-12-13 00:30:23 +00:00
if ( v8js_create_ext_strarr ( & exts , exts_count , Z_ARRVAL_P ( exts_arr ) ) = = FAILURE ) {
2015-10-02 22:01:12 +00:00
zend_throw_exception ( php_ce_v8js_exception ,
" Invalid extensions array passed " , 0 ) ;
2014-12-12 22:59:28 +00:00
return ;
}
}
/* Declare configuration for extensions */
v8 : : ExtensionConfiguration extension_conf ( exts_count , exts ) ;
// Isolate execution
v8 : : Isolate * isolate = c - > isolate ;
v8 : : Locker locker ( isolate ) ;
v8 : : Isolate : : Scope isolate_scope ( isolate ) ;
/* Handle scope */
v8 : : HandleScope handle_scope ( isolate ) ;
/* Redirect fatal errors to PHP error handler */
// This needs to be done within the context isolate
2014-12-13 00:30:23 +00:00
v8 : : V8 : : SetFatalErrorHandler ( v8js_fatal_error_handler ) ;
2014-12-12 22:59:28 +00:00
/* Create global template for global object */
// Now we are using multiple isolates this needs to be created for every context
v8 : : Local < v8 : : FunctionTemplate > tpl = v8 : : FunctionTemplate : : New ( c - > isolate , 0 ) ;
tpl - > SetClassName ( V8JS_SYM ( " V8Js " ) ) ;
c - > global_template . Reset ( isolate , tpl ) ;
/* Register builtin methods */
2014-12-13 00:30:23 +00:00
v8js_register_methods ( tpl - > InstanceTemplate ( ) , c ) ;
2014-12-12 22:59:28 +00:00
/* Create context */
v8 : : Local < v8 : : Context > context = v8 : : Context : : New ( isolate , & extension_conf , tpl - > InstanceTemplate ( ) ) ;
if ( exts ) {
2014-12-13 00:30:23 +00:00
v8js_free_ext_strarr ( exts , exts_count ) ;
2014-12-12 22:59:28 +00:00
}
/* If extensions have errors, context will be empty. (NOTE: This is V8 stuff, they expect the passed sources to compile :) */
2015-05-01 09:43:24 +00:00
if ( context . IsEmpty ( ) ) {
2015-10-02 22:01:12 +00:00
zend_throw_exception ( php_ce_v8js_exception ,
" Failed to create V8 context. "
" Check that registered extensions do not have errors. " , 0 ) ;
2014-12-12 22:59:28 +00:00
return ;
}
2015-05-01 09:43:24 +00:00
context - > SetAlignedPointerInEmbedderData ( 1 , c ) ;
c - > context . Reset ( isolate , context ) ;
2014-12-12 22:59:28 +00:00
/* Enter context */
v8 : : Context : : Scope context_scope ( context ) ;
/* Create the PHP container object's function template */
v8 : : Local < v8 : : FunctionTemplate > php_obj_t = v8 : : FunctionTemplate : : New ( isolate , 0 ) ;
/* Set class name for PHP object */
2015-08-24 22:24:04 +00:00
zend_class_entry * ce = Z_OBJCE_P ( getThis ( ) ) ;
php_obj_t - > SetClassName ( V8JS_SYML ( ZSTR_VAL ( ce - > name ) , ZSTR_LEN ( ce - > name ) ) ) ;
2014-12-12 22:59:28 +00:00
/* Register Get accessor for passed variables */
if ( vars_arr & & zend_hash_num_elements ( Z_ARRVAL_P ( vars_arr ) ) > 0 ) {
2014-12-13 00:30:23 +00:00
v8js_register_accessors ( & c - > accessor_list , php_obj_t , vars_arr , isolate TSRMLS_CC ) ;
2014-12-12 22:59:28 +00:00
}
/* Set name for the PHP JS object */
2015-10-02 20:29:54 +00:00
v8 : : Local < v8 : : String > object_name_js = ( object_name & & ZSTR_LEN ( object_name ) )
? V8JS_ZSYM ( object_name )
: V8JS_SYM ( " PHP " ) ;
2014-12-12 22:59:28 +00:00
c - > object_name . Reset ( isolate , object_name_js ) ;
/* Add the PHP object into global object */
v8 : : Local < v8 : : Object > php_obj = php_obj_t - > InstanceTemplate ( ) - > NewInstance ( ) ;
V8JS_GLOBAL ( isolate ) - > ForceSet ( object_name_js , php_obj , v8 : : ReadOnly ) ;
/* Export public property values */
HashTable * properties = zend_std_get_properties ( getThis ( ) TSRMLS_CC ) ;
2015-08-24 22:24:04 +00:00
zval * value ;
zend_string * member ;
2014-12-12 22:59:28 +00:00
2015-09-03 21:12:19 +00:00
ZEND_HASH_FOREACH_STR_KEY ( properties , member ) {
2015-08-24 22:24:04 +00:00
zend_property_info * property_info = zend_get_property_info ( c - > std . ce , member , 1 TSRMLS_CC ) ;
2015-08-30 00:08:38 +00:00
if ( property_info & &
property_info ! = ZEND_WRONG_PROPERTY_INFO & &
property_info - > flags & ZEND_ACC_PUBLIC ) {
2014-12-12 22:59:28 +00:00
/* Write value to PHP JS object */
2015-09-03 21:12:19 +00:00
value = OBJ_PROP ( Z_OBJ_P ( getThis ( ) ) , property_info - > offset ) ;
php_obj - > ForceSet ( V8JS_ZSYM ( member ) , zval_to_v8js ( value , isolate TSRMLS_CC ) , v8 : : ReadOnly ) ;
2014-12-12 22:59:28 +00:00
}
2015-09-03 21:12:19 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
/* {{{ proto V8JS::__sleep()
*/
PHP_METHOD ( V8Js , __sleep )
{
zend_throw_exception ( php_ce_v8js_exception ,
" You cannot serialize or unserialize V8Js instances " , 0 TSRMLS_CC ) ;
RETURN_FALSE ;
}
/* }}} */
/* {{{ proto V8JS::__wakeup()
*/
PHP_METHOD ( V8Js , __wakeup )
{
zend_throw_exception ( php_ce_v8js_exception ,
" You cannot serialize or unserialize V8Js instances " , 0 TSRMLS_CC ) ;
RETURN_FALSE ;
}
/* }}} */
2015-08-29 18:19:04 +00:00
static void v8js_compile_script ( zval * this_ptr , zend_string * str , zend_string * identifier , v8js_script * * ret TSRMLS_DC )
2014-12-12 22:59:28 +00:00
{
2014-12-13 00:15:29 +00:00
v8js_script * res = NULL ;
2014-12-12 22:59:28 +00:00
V8JS_BEGIN_CTX ( c , this_ptr )
/* Catch JS exceptions */
v8 : : TryCatch try_catch ;
/* Set script identifier */
2015-08-29 18:19:04 +00:00
v8 : : Local < v8 : : String > sname = identifier ? V8JS_ZSTR ( identifier ) : V8JS_SYM ( " V8Js::compileString() " ) ;
2014-12-12 22:59:28 +00:00
/* Compiles a string context independently. TODO: Add a php function which calls this and returns the result as resource which can be executed later. */
2015-08-29 18:19:04 +00:00
v8 : : Local < v8 : : String > source = V8JS_ZSTR ( str ) ;
2014-12-12 22:59:28 +00:00
v8 : : Local < v8 : : Script > script = v8 : : Script : : Compile ( source , sname ) ;
/* Compile errors? */
if ( script . IsEmpty ( ) ) {
2015-08-23 13:09:21 +00:00
v8js_throw_script_exception ( c - > isolate , & try_catch TSRMLS_CC ) ;
2014-12-12 22:59:28 +00:00
return ;
}
2014-12-13 00:15:29 +00:00
res = ( v8js_script * ) emalloc ( sizeof ( v8js_script ) ) ;
2014-12-12 22:59:28 +00:00
res - > script = new v8 : : Persistent < v8 : : Script , v8 : : CopyablePersistentTraits < v8 : : Script > > ( c - > isolate , script ) ;
v8 : : String : : Utf8Value _sname ( sname ) ;
res - > name = estrndup ( ToCString ( _sname ) , _sname . length ( ) ) ;
2015-08-02 21:35:47 +00:00
res - > ctx = c ;
2014-12-12 22:59:28 +00:00
* ret = res ;
return ;
}
2014-12-13 00:30:23 +00:00
static void v8js_execute_script ( zval * this_ptr , v8js_script * res , long flags , long time_limit , long memory_limit , zval * * return_value TSRMLS_DC )
2014-12-12 22:59:28 +00:00
{
2015-08-24 22:24:04 +00:00
v8js_ctx * c = Z_V8JS_CTX_OBJ_P ( this_ptr ) ;
2014-12-12 22:59:28 +00:00
2015-08-02 21:35:47 +00:00
if ( res - > ctx ! = c ) {
2014-12-12 22:59:28 +00:00
zend_error ( E_WARNING , " Script resource from wrong V8Js object passed " ) ;
ZVAL_BOOL ( * return_value , 0 ) ;
return ;
}
if ( ! c - > in_execution & & time_limit = = 0 ) {
time_limit = c - > time_limit ;
}
if ( ! c - > in_execution & & memory_limit = = 0 ) {
memory_limit = c - > memory_limit ;
}
2016-01-01 18:10:04 +00:00
/* std::function relies on its dtor to be executed, otherwise it leaks
* some memory on bailout . */
{
std : : function < v8 : : Local < v8 : : Value > ( v8 : : Isolate * ) > v8_call = [ res ] ( v8 : : Isolate * isolate ) {
v8 : : Local < v8 : : Script > script = v8 : : Local < v8 : : Script > : : New ( isolate , * res - > script ) ;
return script - > Run ( ) ;
} ;
v8js_v8_call ( c , return_value , flags , time_limit , memory_limit , v8_call TSRMLS_CC ) ;
}
2014-12-12 22:59:28 +00:00
2016-01-01 18:10:04 +00:00
if ( V8JSG ( fatal_error_abort ) ) {
/* Check for fatal error marker possibly set by v8js_error_handler; just
* rethrow the error since we ' re now out of V8 . */
zend_bailout ( ) ;
}
2014-12-12 22:59:28 +00:00
}
/* {{{ proto mixed V8Js::executeString(string script [, string identifier [, int flags]])
*/
static PHP_METHOD ( V8Js , executeString )
{
2015-08-29 18:19:04 +00:00
zend_string * str = NULL , * identifier = NULL ;
2014-12-12 22:59:28 +00:00
int str_len = 0 , identifier_len = 0 ;
long flags = V8JS_FLAG_NONE , time_limit = 0 , memory_limit = 0 ;
2014-12-13 00:15:29 +00:00
v8js_script * res = NULL ;
2014-12-12 22:59:28 +00:00
2015-08-29 18:19:04 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " S|Slll " , & str , & identifier , & flags , & time_limit , & memory_limit ) = = FAILURE ) {
2014-12-12 22:59:28 +00:00
return ;
}
2015-08-29 18:19:04 +00:00
v8js_compile_script ( getThis ( ) , str , identifier , & res TSRMLS_CC ) ;
2014-12-12 22:59:28 +00:00
if ( ! res ) {
RETURN_FALSE ;
}
2015-12-31 23:01:49 +00:00
zend_try {
v8js_execute_script ( getThis ( ) , res , flags , time_limit , memory_limit , & return_value TSRMLS_CC ) ;
v8js_script_free ( res ) ;
}
zend_catch {
v8js_script_free ( res ) ;
zend_bailout ( ) ;
}
zend_end_try ( )
2014-12-12 22:59:28 +00:00
efree ( res ) ;
}
/* }}} */
/* {{{ proto mixed V8Js::compileString(string script [, string identifier])
*/
static PHP_METHOD ( V8Js , compileString )
{
2015-08-29 18:19:04 +00:00
zend_string * str = NULL , * identifier = NULL ;
2014-12-12 22:59:28 +00:00
int str_len = 0 , identifier_len = 0 ;
2014-12-13 00:15:29 +00:00
v8js_script * res = NULL ;
2014-12-12 22:59:28 +00:00
2015-08-29 18:19:04 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " S|S " , & str , & identifier ) = = FAILURE ) {
2014-12-12 22:59:28 +00:00
return ;
}
2015-08-29 18:19:04 +00:00
v8js_compile_script ( getThis ( ) , str , identifier , & res TSRMLS_CC ) ;
2014-12-12 22:59:28 +00:00
if ( res ) {
2015-08-29 19:56:29 +00:00
RETVAL_RES ( zend_register_resource ( res , le_v8js_script ) ) ;
2015-08-02 21:35:47 +00:00
v8js_ctx * ctx ;
2015-08-24 22:24:04 +00:00
ctx = Z_V8JS_CTX_OBJ_P ( getThis ( ) ) ;
2015-08-02 21:35:47 +00:00
ctx - > script_objects . push_back ( res ) ;
2014-12-12 22:59:28 +00:00
}
return ;
}
/* }}} */
/* {{{ proto mixed V8Js::executeScript(resource script [, int flags]])
*/
static PHP_METHOD ( V8Js , executeScript )
{
long flags = V8JS_FLAG_NONE , time_limit = 0 , memory_limit = 0 ;
zval * zscript ;
2014-12-13 00:15:29 +00:00
v8js_script * res ;
2014-12-12 22:59:28 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " r|lll " , & zscript , & flags , & time_limit , & memory_limit ) = = FAILURE ) {
return ;
}
2015-08-24 22:24:04 +00:00
if ( ( res = ( v8js_script * ) zend_fetch_resource ( Z_RES_P ( zscript ) , PHP_V8JS_SCRIPT_RES_NAME , le_v8js_script ) ) = = NULL ) {
RETURN_FALSE ;
}
2014-12-12 22:59:28 +00:00
2014-12-13 00:30:23 +00:00
v8js_execute_script ( getThis ( ) , res , flags , time_limit , memory_limit , & return_value TSRMLS_CC ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
/* {{{ proto mixed V8Js::checkString(string script)
*/
static PHP_METHOD ( V8Js , checkString )
{
2015-08-29 18:19:04 +00:00
zend_string * str = NULL ;
2014-12-12 22:59:28 +00:00
int str_len = 0 ;
2015-08-29 18:19:04 +00:00
zend_string * identifier = zend_string_init ( " V8Js::checkString() " , 19 , 0 ) ;
2014-12-12 22:59:28 +00:00
2014-12-13 00:15:29 +00:00
v8js_script * res = NULL ;
2014-12-12 22:59:28 +00:00
2015-08-29 18:19:04 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " S " , & str ) = = FAILURE ) {
2014-12-12 22:59:28 +00:00
return ;
}
2015-08-29 18:19:04 +00:00
v8js_compile_script ( getThis ( ) , str , identifier , & res TSRMLS_CC ) ;
zend_string_release ( identifier ) ;
2014-12-12 22:59:28 +00:00
if ( ! res ) {
RETURN_FALSE ;
}
2015-08-02 20:36:23 +00:00
v8js_script_free ( res ) ;
2014-12-12 22:59:28 +00:00
efree ( res ) ;
RETURN_TRUE ;
}
/* }}} */
/* {{{ proto mixed V8Js::getPendingException()
*/
static PHP_METHOD ( V8Js , getPendingException )
{
2014-12-13 00:15:29 +00:00
v8js_ctx * c ;
2014-12-12 22:59:28 +00:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-08-24 22:24:04 +00:00
c = Z_V8JS_CTX_OBJ_P ( getThis ( ) ) ;
2014-12-12 22:59:28 +00:00
2015-08-24 22:24:04 +00:00
if ( Z_TYPE ( c - > pending_exception ) = = IS_OBJECT ) {
RETURN_ZVAL ( & c - > pending_exception , 1 , 0 ) ;
2014-12-12 22:59:28 +00:00
}
}
/* }}} */
/* {{{ proto void V8Js::clearPendingException()
*/
static PHP_METHOD ( V8Js , clearPendingException )
{
2014-12-13 00:15:29 +00:00
v8js_ctx * c ;
2014-12-12 22:59:28 +00:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
2015-08-24 22:24:04 +00:00
c = Z_V8JS_CTX_OBJ_P ( getThis ( ) ) ;
2014-12-12 22:59:28 +00:00
2015-08-24 22:24:04 +00:00
if ( Z_TYPE ( c - > pending_exception ) = = IS_OBJECT ) {
zval_dtor ( & c - > pending_exception ) ;
ZVAL_NULL ( & c - > pending_exception ) ;
2014-12-12 22:59:28 +00:00
}
}
/* }}} */
2015-12-06 12:55:13 +00:00
/* {{{ proto void V8Js::setModuleNormaliser(string base, string module_id)
*/
static PHP_METHOD ( V8Js , setModuleNormaliser )
{
v8js_ctx * c ;
zval * callable ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " z " , & callable ) = = FAILURE ) {
return ;
}
2015-12-31 19:25:24 +00:00
c = Z_V8JS_CTX_OBJ_P ( getThis ( ) ) ;
ZVAL_COPY ( & c - > module_normaliser , callable ) ;
2015-12-06 12:55:13 +00:00
}
/* }}} */
2014-12-12 22:59:28 +00:00
/* {{{ proto void V8Js::setModuleLoader(string module)
*/
static PHP_METHOD ( V8Js , setModuleLoader )
{
2014-12-13 00:15:29 +00:00
v8js_ctx * c ;
2015-08-29 19:00:13 +00:00
zval * callable ;
2014-12-12 22:59:28 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " z " , & callable ) = = FAILURE ) {
return ;
}
2015-08-24 22:24:04 +00:00
c = Z_V8JS_CTX_OBJ_P ( getThis ( ) ) ;
2015-08-29 19:00:13 +00:00
ZVAL_COPY ( & c - > module_loader , callable ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
/* {{{ proto void V8Js::setTimeLimit(int time_limit)
*/
static PHP_METHOD ( V8Js , setTimeLimit )
{
2014-12-13 00:15:29 +00:00
v8js_ctx * c ;
2014-12-12 22:59:28 +00:00
long time_limit = 0 ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l " , & time_limit ) = = FAILURE ) {
return ;
}
2015-08-24 22:24:04 +00:00
c = Z_V8JS_CTX_OBJ_P ( getThis ( ) ) ;
2014-12-12 22:59:28 +00:00
c - > time_limit = time_limit ;
V8JSG ( timer_mutex ) . lock ( ) ;
2014-12-13 00:15:29 +00:00
for ( std : : deque < v8js_timer_ctx * > : : iterator it = V8JSG ( timer_stack ) . begin ( ) ;
2014-12-12 22:59:28 +00:00
it ! = V8JSG ( timer_stack ) . end ( ) ; it + + ) {
2014-12-13 00:15:29 +00:00
if ( ( * it ) - > ctx = = c & & ! ( * it ) - > killed ) {
2014-12-12 22:59:28 +00:00
( * it ) - > time_limit = time_limit ;
// Calculate the time point when the time limit is exceeded
std : : chrono : : milliseconds duration ( time_limit ) ;
std : : chrono : : time_point < std : : chrono : : high_resolution_clock > from = std : : chrono : : high_resolution_clock : : now ( ) ;
( * it ) - > time_point = from + duration ;
}
}
V8JSG ( timer_mutex ) . unlock ( ) ;
if ( c - > in_execution & & time_limit & & ! V8JSG ( timer_thread ) ) {
/* If timer thread is not started already and we now impose a time limit
* finally install the timer . */
2015-09-28 20:03:24 +00:00
V8JSG ( timer_thread ) = new std : : thread ( v8js_timer_thread , ZEND_MODULE_GLOBALS_BULK ( v8js ) ) ;
2014-12-12 22:59:28 +00:00
}
}
/* }}} */
/* {{{ proto void V8Js::setMemoryLimit(int memory_limit)
*/
static PHP_METHOD ( V8Js , setMemoryLimit )
{
2014-12-13 00:15:29 +00:00
v8js_ctx * c ;
2014-12-12 22:59:28 +00:00
long memory_limit = 0 ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l " , & memory_limit ) = = FAILURE ) {
return ;
}
2015-08-24 22:24:04 +00:00
c = Z_V8JS_CTX_OBJ_P ( getThis ( ) ) ;
2014-12-12 22:59:28 +00:00
c - > memory_limit = memory_limit ;
V8JSG ( timer_mutex ) . lock ( ) ;
2014-12-13 00:15:29 +00:00
for ( std : : deque < v8js_timer_ctx * > : : iterator it = V8JSG ( timer_stack ) . begin ( ) ;
2014-12-12 22:59:28 +00:00
it ! = V8JSG ( timer_stack ) . end ( ) ; it + + ) {
2014-12-13 00:15:29 +00:00
if ( ( * it ) - > ctx = = c & & ! ( * it ) - > killed ) {
2014-12-12 22:59:28 +00:00
( * it ) - > memory_limit = memory_limit ;
}
}
V8JSG ( timer_mutex ) . unlock ( ) ;
if ( c - > in_execution & & memory_limit & & ! V8JSG ( timer_thread ) ) {
/* If timer thread is not started already and we now impose a memory limit
* finally install the timer . */
2015-09-28 20:03:24 +00:00
V8JSG ( timer_thread ) = new std : : thread ( v8js_timer_thread , ZEND_MODULE_GLOBALS_BULK ( v8js ) ) ;
2014-12-12 22:59:28 +00:00
}
}
/* }}} */
2015-08-25 21:38:09 +00:00
static void v8js_persistent_zval_ctor ( zval * p ) /* { { { */
2014-12-12 22:59:28 +00:00
{
2015-08-25 21:38:09 +00:00
assert ( Z_TYPE_P ( p ) = = IS_STRING ) ;
Z_STR_P ( p ) = zend_string_dup ( Z_STR_P ( p ) , 1 ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
2015-08-25 21:38:09 +00:00
static void v8js_persistent_zval_dtor ( zval * p ) /* { { { */
2014-12-12 22:59:28 +00:00
{
2015-08-25 21:38:09 +00:00
assert ( Z_TYPE_P ( p ) = = IS_STRING ) ;
free ( Z_STR_P ( p ) ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
2015-08-02 20:36:23 +00:00
static void v8js_script_free ( v8js_script * res )
2014-12-12 22:59:28 +00:00
{
2015-08-02 20:36:23 +00:00
efree ( res - > name ) ;
delete res - > script ; // does Reset()
2014-12-12 22:59:28 +00:00
}
2015-08-25 21:38:09 +00:00
static void v8js_script_dtor ( zend_resource * rsrc ) /* { { { */
2014-12-12 22:59:28 +00:00
{
2014-12-13 00:15:29 +00:00
v8js_script * res = ( v8js_script * ) rsrc - > ptr ;
2014-12-12 22:59:28 +00:00
if ( res ) {
2015-08-02 21:35:47 +00:00
if ( res - > ctx ) {
std : : vector < v8js_script * > : : iterator it = std : : find ( res - > ctx - > script_objects . begin ( ) , res - > ctx - > script_objects . end ( ) , res ) ;
res - > ctx - > script_objects . erase ( it ) ;
}
2015-08-02 20:36:23 +00:00
v8js_script_free ( res ) ;
2014-12-12 22:59:28 +00:00
efree ( res ) ;
}
}
/* }}} */
2015-08-24 20:05:27 +00:00
static int v8js_register_extension ( zend_string * name , zend_string * source , zval * deps_arr , zend_bool auto_enable TSRMLS_DC ) /* { { { */
2014-12-12 22:59:28 +00:00
{
2014-12-13 00:30:23 +00:00
v8js_jsext * jsext = NULL ;
2014-12-12 22:59:28 +00:00
2015-09-26 19:39:26 +00:00
# ifdef ZTS
v8js_process_globals . lock . lock ( ) ;
# endif
if ( ! v8js_process_globals . extensions ) {
v8js_process_globals . extensions = ( HashTable * ) malloc ( sizeof ( HashTable ) ) ;
2015-10-11 00:09:59 +00:00
zend_hash_init ( v8js_process_globals . extensions , 1 , NULL , v8js_jsext_dtor , 1 ) ;
} else if ( zend_hash_exists ( v8js_process_globals . extensions , name ) ) {
2015-09-26 19:39:26 +00:00
# ifdef ZTS
v8js_process_globals . lock . unlock ( ) ;
# endif
2014-12-12 22:59:28 +00:00
return FAILURE ;
}
2014-12-13 00:30:23 +00:00
jsext = ( v8js_jsext * ) calloc ( 1 , sizeof ( v8js_jsext ) ) ;
2014-12-12 22:59:28 +00:00
if ( deps_arr ) {
jsext - > deps_count = zend_hash_num_elements ( Z_ARRVAL_P ( deps_arr ) ) ;
2014-12-13 00:30:23 +00:00
if ( v8js_create_ext_strarr ( & jsext - > deps , jsext - > deps_count , Z_ARRVAL_P ( deps_arr ) ) = = FAILURE ) {
2014-12-12 22:59:28 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid dependency array passed " ) ;
2015-08-29 19:45:59 +00:00
v8js_jsext_free_storage ( jsext ) ;
2015-09-26 19:39:26 +00:00
# ifdef ZTS
v8js_process_globals . lock . unlock ( ) ;
# endif
2014-12-12 22:59:28 +00:00
return FAILURE ;
}
}
jsext - > auto_enable = auto_enable ;
2015-08-29 19:45:59 +00:00
jsext - > name = zend_string_dup ( name , 1 ) ;
jsext - > source = zend_string_dup ( source , 1 ) ;
2014-12-12 22:59:28 +00:00
if ( jsext - > deps ) {
jsext - > deps_ht = ( HashTable * ) malloc ( sizeof ( HashTable ) ) ;
2015-08-25 21:38:09 +00:00
zend_hash_init ( jsext - > deps_ht , jsext - > deps_count , NULL , v8js_persistent_zval_dtor , 1 ) ;
zend_hash_copy ( jsext - > deps_ht , Z_ARRVAL_P ( deps_arr ) , v8js_persistent_zval_ctor ) ;
2014-12-12 22:59:28 +00:00
}
2015-08-25 21:38:09 +00:00
jsext - > extension = new v8 : : Extension ( ZSTR_VAL ( jsext - > name ) , ZSTR_VAL ( jsext - > source ) , jsext - > deps_count , jsext - > deps ) ;
2015-08-02 17:42:42 +00:00
2015-10-11 00:09:59 +00:00
if ( ! zend_hash_add_ptr ( v8js_process_globals . extensions , jsext - > name , jsext ) ) {
2015-08-29 19:45:59 +00:00
v8js_jsext_free_storage ( jsext ) ;
2015-09-26 19:39:26 +00:00
# ifdef ZTS
v8js_process_globals . lock . unlock ( ) ;
# endif
2014-12-12 22:59:28 +00:00
return FAILURE ;
}
2015-09-26 19:39:26 +00:00
# ifdef ZTS
v8js_process_globals . lock . unlock ( ) ;
# endif
2015-08-02 17:42:42 +00:00
jsext - > extension - > set_auto_enable ( auto_enable ? true : false ) ;
v8 : : RegisterExtension ( jsext - > extension ) ;
2014-12-12 22:59:28 +00:00
return SUCCESS ;
}
/* }}} */
/* {{{ proto bool V8Js::registerExtension(string ext_name, string script [, array deps [, bool auto_enable]])
*/
static PHP_METHOD ( V8Js , registerExtension )
{
2015-08-25 21:38:09 +00:00
zend_string * ext_name , * script ;
2014-12-12 22:59:28 +00:00
zval * deps_arr = NULL ;
zend_bool auto_enable = 0 ;
2015-08-25 21:38:09 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " SS|ab " , & ext_name , & script , & deps_arr , & auto_enable ) = = FAILURE ) {
2014-12-12 22:59:28 +00:00
return ;
}
2015-08-29 19:45:59 +00:00
if ( ! ZSTR_LEN ( ext_name ) ) {
2014-12-12 22:59:28 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Extension name cannot be empty " ) ;
2015-08-29 19:45:59 +00:00
} else if ( ! ZSTR_LEN ( script ) ) {
2014-12-12 22:59:28 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Script cannot be empty " ) ;
2015-08-25 21:38:09 +00:00
} else if ( v8js_register_extension ( ext_name , script , deps_arr , auto_enable TSRMLS_CC ) = = SUCCESS ) {
2014-12-12 22:59:28 +00:00
RETURN_TRUE ;
}
RETURN_FALSE ;
}
/* }}} */
/* ## Static methods ## */
/* {{{ proto array V8Js::getExtensions()
*/
static PHP_METHOD ( V8Js , getExtensions )
{
2014-12-13 00:30:23 +00:00
v8js_jsext * jsext ;
2014-12-12 22:59:28 +00:00
ulong index ;
2015-08-25 21:38:09 +00:00
zend_string * key ;
zval * val , ext ;
2014-12-12 22:59:28 +00:00
if ( zend_parse_parameters_none ( ) = = FAILURE ) {
return ;
}
array_init ( return_value ) ;
2015-08-25 21:38:09 +00:00
2015-09-26 19:39:26 +00:00
# ifdef ZTS
v8js_process_globals . lock . lock ( ) ;
# endif
if ( v8js_process_globals . extensions ) {
2015-10-11 00:09:59 +00:00
ZEND_HASH_FOREACH_KEY_VAL ( v8js_process_globals . extensions , index , key , val ) {
2015-08-25 21:38:09 +00:00
if ( key ) {
jsext = ( v8js_jsext * ) Z_PTR_P ( val ) ;
array_init ( & ext ) ;
2015-08-30 13:33:51 +00:00
add_assoc_bool_ex ( & ext , ZEND_STRL ( " auto_enable " ) , jsext - > auto_enable ) ;
2014-12-12 22:59:28 +00:00
if ( jsext - > deps_ht ) {
2015-08-25 21:38:09 +00:00
zval deps_arr ;
array_init ( & deps_arr ) ;
zend_hash_copy ( Z_ARRVAL_P ( & deps_arr ) , jsext - > deps_ht , ( copy_ctor_func_t ) zval_add_ref ) ;
2015-08-30 13:33:51 +00:00
add_assoc_zval_ex ( & ext , ZEND_STRL ( " deps " ) , & deps_arr ) ;
2014-12-12 22:59:28 +00:00
}
2015-08-25 21:38:09 +00:00
add_assoc_zval_ex ( return_value , ZSTR_VAL ( key ) , ZSTR_LEN ( key ) , & ext ) ;
2014-12-12 22:59:28 +00:00
}
2015-08-25 21:38:09 +00:00
} ZEND_HASH_FOREACH_END ( ) ;
2014-12-12 22:59:28 +00:00
}
2015-09-26 19:39:26 +00:00
# ifdef ZTS
v8js_process_globals . lock . unlock ( ) ;
# endif
2014-12-12 22:59:28 +00:00
}
/* }}} */
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_construct , 0 , 0 , 0 )
ZEND_ARG_INFO ( 0 , object_name )
ZEND_ARG_INFO ( 0 , variables )
ZEND_ARG_INFO ( 0 , extensions )
ZEND_ARG_INFO ( 0 , report_uncaught_exceptions )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO ( arginfo_v8js_sleep , 0 )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO ( arginfo_v8js_wakeup , 0 )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_executestring , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , script )
ZEND_ARG_INFO ( 0 , identifier )
ZEND_ARG_INFO ( 0 , flags )
ZEND_ARG_INFO ( 0 , time_limit )
ZEND_ARG_INFO ( 0 , memory_limit )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_compilestring , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , script )
ZEND_ARG_INFO ( 0 , identifier )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_executescript , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , script )
ZEND_ARG_INFO ( 0 , flags )
ZEND_ARG_INFO ( 0 , time_limit )
ZEND_ARG_INFO ( 0 , memory_limit )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_checkstring , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , script )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO ( arginfo_v8js_getpendingexception , 0 )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO ( arginfo_v8js_clearpendingexception , 0 )
ZEND_END_ARG_INFO ( )
2015-12-06 12:55:13 +00:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_setmodulenormaliser , 0 , 0 , 2 )
ZEND_ARG_INFO ( 0 , base )
ZEND_ARG_INFO ( 0 , module_id )
ZEND_END_ARG_INFO ( )
2014-12-12 22:59:28 +00:00
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_setmoduleloader , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , callable )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_registerextension , 0 , 0 , 2 )
ZEND_ARG_INFO ( 0 , extension_name )
ZEND_ARG_INFO ( 0 , script )
ZEND_ARG_INFO ( 0 , dependencies )
ZEND_ARG_INFO ( 0 , auto_enable )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO ( arginfo_v8js_getextensions , 0 )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_settimelimit , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , time_limit )
ZEND_END_ARG_INFO ( )
ZEND_BEGIN_ARG_INFO_EX ( arginfo_v8js_setmemorylimit , 0 , 0 , 1 )
ZEND_ARG_INFO ( 0 , memory_limit )
ZEND_END_ARG_INFO ( )
static const zend_function_entry v8js_methods [ ] = { /* {{{ */
PHP_ME ( V8Js , __construct , arginfo_v8js_construct , ZEND_ACC_PUBLIC | ZEND_ACC_CTOR )
PHP_ME ( V8Js , __sleep , arginfo_v8js_sleep , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
PHP_ME ( V8Js , __wakeup , arginfo_v8js_sleep , ZEND_ACC_PUBLIC | ZEND_ACC_FINAL )
PHP_ME ( V8Js , executeString , arginfo_v8js_executestring , ZEND_ACC_PUBLIC )
PHP_ME ( V8Js , compileString , arginfo_v8js_compilestring , ZEND_ACC_PUBLIC )
PHP_ME ( V8Js , executeScript , arginfo_v8js_executescript , ZEND_ACC_PUBLIC )
PHP_ME ( V8Js , checkString , arginfo_v8js_checkstring , ZEND_ACC_PUBLIC | ZEND_ACC_DEPRECATED )
PHP_ME ( V8Js , getPendingException , arginfo_v8js_getpendingexception , ZEND_ACC_PUBLIC )
PHP_ME ( V8Js , clearPendingException , arginfo_v8js_clearpendingexception , ZEND_ACC_PUBLIC )
2015-12-06 12:55:13 +00:00
PHP_ME ( V8Js , setModuleNormaliser , arginfo_v8js_setmodulenormaliser , ZEND_ACC_PUBLIC )
2014-12-12 22:59:28 +00:00
PHP_ME ( V8Js , setModuleLoader , arginfo_v8js_setmoduleloader , ZEND_ACC_PUBLIC )
PHP_ME ( V8Js , registerExtension , arginfo_v8js_registerextension , ZEND_ACC_PUBLIC | ZEND_ACC_STATIC )
PHP_ME ( V8Js , getExtensions , arginfo_v8js_getextensions , ZEND_ACC_PUBLIC | ZEND_ACC_STATIC )
PHP_ME ( V8Js , setTimeLimit , arginfo_v8js_settimelimit , ZEND_ACC_PUBLIC )
PHP_ME ( V8Js , setMemoryLimit , arginfo_v8js_setmemorylimit , ZEND_ACC_PUBLIC )
{ NULL , NULL , NULL }
} ;
/* }}} */
/* V8Js object handlers */
2015-08-25 21:38:09 +00:00
static void v8js_write_property ( zval * object , zval * member , zval * value , void * * cache_slot TSRMLS_DC ) /* { { { */
2014-12-12 22:59:28 +00:00
{
V8JS_BEGIN_CTX ( c , object )
/* Check whether member is public, if so, export to V8. */
2015-08-25 21:38:09 +00:00
zend_property_info * property_info = zend_get_property_info ( c - > std . ce , Z_STR_P ( member ) , 1 TSRMLS_CC ) ;
2015-08-30 00:08:38 +00:00
if ( ! property_info | |
( property_info ! = ZEND_WRONG_PROPERTY_INFO & &
property_info - > flags & ZEND_ACC_PUBLIC ) ) {
2014-12-12 22:59:28 +00:00
/* Global PHP JS object */
v8 : : Local < v8 : : String > object_name_js = v8 : : Local < v8 : : String > : : New ( isolate , c - > object_name ) ;
v8 : : Local < v8 : : Object > jsobj = V8JS_GLOBAL ( isolate ) - > Get ( object_name_js ) - > ToObject ( ) ;
/* Write value to PHP JS object */
jsobj - > ForceSet ( V8JS_SYML ( Z_STRVAL_P ( member ) , Z_STRLEN_P ( member ) ) , zval_to_v8js ( value , isolate TSRMLS_CC ) , v8 : : ReadOnly ) ;
}
/* Write value to PHP object */
2015-10-05 19:41:48 +00:00
std_object_handlers . write_property ( object , member , value , NULL ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
2015-08-25 21:38:09 +00:00
static void v8js_unset_property ( zval * object , zval * member , void * * cache_slot TSRMLS_DC ) /* { { { */
2014-12-12 22:59:28 +00:00
{
V8JS_BEGIN_CTX ( c , object )
/* Global PHP JS object */
v8 : : Local < v8 : : String > object_name_js = v8 : : Local < v8 : : String > : : New ( isolate , c - > object_name ) ;
v8 : : Local < v8 : : Object > jsobj = V8JS_GLOBAL ( isolate ) - > Get ( object_name_js ) - > ToObject ( ) ;
2015-12-31 19:25:24 +00:00
2014-12-12 22:59:28 +00:00
/* Delete value from PHP JS object */
2015-03-10 14:09:41 +00:00
jsobj - > Delete ( V8JS_SYML ( Z_STRVAL_P ( member ) , Z_STRLEN_P ( member ) ) ) ;
2014-12-12 22:59:28 +00:00
/* Unset from PHP object */
2015-10-05 19:41:48 +00:00
std_object_handlers . unset_property ( object , member , NULL ) ;
2014-12-12 22:59:28 +00:00
}
/* }}} */
PHP_MINIT_FUNCTION ( v8js_class ) /* {{{ */
{
zend_class_entry ce ;
/* V8Js Class */
INIT_CLASS_ENTRY ( ce , " V8Js " , v8js_methods ) ;
php_ce_v8js = zend_register_internal_class ( & ce TSRMLS_CC ) ;
2014-12-13 00:30:23 +00:00
php_ce_v8js - > create_object = v8js_new ;
2014-12-12 22:59:28 +00:00
/* V8Js handlers */
memcpy ( & v8js_object_handlers , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
v8js_object_handlers . clone_obj = NULL ;
2014-12-13 00:30:23 +00:00
v8js_object_handlers . write_property = v8js_write_property ;
v8js_object_handlers . unset_property = v8js_unset_property ;
2014-12-12 22:59:28 +00:00
/* V8Js Class Constants */
zend_declare_class_constant_string ( php_ce_v8js , ZEND_STRL ( " V8_VERSION " ) , PHP_V8_VERSION TSRMLS_CC ) ;
zend_declare_class_constant_long ( php_ce_v8js , ZEND_STRL ( " FLAG_NONE " ) , V8JS_FLAG_NONE TSRMLS_CC ) ;
zend_declare_class_constant_long ( php_ce_v8js , ZEND_STRL ( " FLAG_FORCE_ARRAY " ) , V8JS_FLAG_FORCE_ARRAY TSRMLS_CC ) ;
2015-08-22 13:16:02 +00:00
zend_declare_class_constant_long ( php_ce_v8js , ZEND_STRL ( " FLAG_PROPAGATE_PHP_EXCEPTIONS " ) , V8JS_FLAG_PROPAGATE_PHP_EXCEPTIONS TSRMLS_CC ) ;
2014-12-12 22:59:28 +00:00
2014-12-13 00:15:29 +00:00
le_v8js_script = zend_register_list_destructors_ex ( v8js_script_dtor , NULL , PHP_V8JS_SCRIPT_RES_NAME , module_number ) ;
2015-03-12 11:13:33 +00:00
2015-07-25 15:28:08 +00:00
# if PHP_V8_API_VERSION >= 4004010 && PHP_V8_API_VERSION < 4004044
static ArrayBufferAllocator array_buffer_allocator ;
v8 : : V8 : : SetArrayBufferAllocator ( & array_buffer_allocator ) ;
# endif
2015-03-12 11:13:33 +00:00
return SUCCESS ;
2014-12-12 22:59:28 +00:00
} /* }}} */
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
* vim600 : noet sw = 4 ts = 4 fdm = marker
* vim < 600 : noet sw = 4 ts = 4
*/