From bd7d649d90c3ef66ae73fc8c8fa93c65683b7271 Mon Sep 17 00:00:00 2001 From: Taneli Leppa Date: Tue, 16 Sep 2014 17:09:58 +0300 Subject: [PATCH 1/4] Added new functions V8Js::compileString() and V8Js::executeScript(). Conflicts: php_v8js_macros.h --- README.md | 7 ++ php_v8js_macros.h | 9 ++ tests/compile_string.phpt | 46 +++++++++ tests/compile_string_isolate.phpt | 46 +++++++++ v8js.cc | 159 ++++++++++++++++++++++++++---- 5 files changed, 246 insertions(+), 21 deletions(-) create mode 100644 tests/compile_string.phpt create mode 100644 tests/compile_string_isolate.phpt diff --git a/README.md b/README.md index 6c58c60..be19c85 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,13 @@ PHP API // A time limit (milliseconds) and/or memory limit (bytes) can be provided to restrict execution. These options will throw a V8JsTimeLimitException or V8JsMemoryLimitException. public mixed V8Js::executeString( string $script [, string $identifier [, int $flags = V8Js::FLAG_NONE [, int $time_limit = 0 [, int $memory_limit = 0]]]]) + // Compiles a script in object's context with optional identifier string. + public mixed V8Js::compileString( string $script [, string $identifier ]) + + // Executes a precompiled script in object's context. + // A time limit (milliseconds) and/or memory limit (bytes) can be provided to restrict execution. These options will throw a V8JsTimeLimitException or V8JsMemoryLimitException. + public mixed V8Js::executeScript( resource $script [, int $flags = V8Js::FLAG_NONE [, int $time_limit = 0 [, int $memory_limit = 0]]]) + // Returns uncaught pending exception or null if there is no pending exception. public V8JsScriptException V8Js::getPendingException( ) diff --git a/php_v8js_macros.h b/php_v8js_macros.h index 3628932..5d6a854 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -246,6 +246,7 @@ struct php_v8js_object { }; /* }}} */ +/* Resource declaration */ /* Module globals */ ZEND_BEGIN_MODULE_GLOBALS(v8js) @@ -285,6 +286,14 @@ ZEND_EXTERN_MODULE_GLOBALS(v8js) /* Register builtin methods into passed object */ void php_v8js_register_methods(v8::Handle, php_v8js_ctx *c); +typedef struct _php_v8js_script { + char *name; + v8::Isolate *isolate; + v8::Persistent> *script; +} php_v8js_script; + +static void php_v8js_script_free(php_v8js_script *res); + #endif /* PHP_V8JS_MACROS_H */ /* diff --git a/tests/compile_string.phpt b/tests/compile_string.phpt new file mode 100644 index 0000000..9cf91f4 --- /dev/null +++ b/tests/compile_string.phpt @@ -0,0 +1,46 @@ +--TEST-- +Test V8::compileString() : Compile and run a script +--SKIPIF-- + +--FILE-- +compileString($js, 'a.js'); + var_dump(is_resource($script_a)); + $script_b = $v8->compileString($js2, 'b.js'); + var_dump(is_resource($script_b)); + var_dump($v8->executeScript($script_a)); + var_dump($v8->executeScript($script_b)); + var_dump($v8->executeScript($script_a)); +} catch (V8JsScriptException $e) { + var_dump($e); +} +?> +===EOF=== +--EXPECT-- +bool(true) +bool(true) +object(V8Object)#2 (1) { + ["hello"]=> + string(5) "world" +} +object(V8Object)#2 (1) { + ["foo"]=> + string(3) "bar" +} +object(V8Object)#2 (1) { + ["hello"]=> + string(5) "world" +} +===EOF=== diff --git a/tests/compile_string_isolate.phpt b/tests/compile_string_isolate.phpt new file mode 100644 index 0000000..05b4d92 --- /dev/null +++ b/tests/compile_string_isolate.phpt @@ -0,0 +1,46 @@ +--TEST-- +Test V8::compileString() : Check compiled script isolate processing +--SKIPIF-- + +--FILE-- +compileString($js, 'a.js'); + var_dump($script_a); + $script_b = $v8two->compileString($js2, 'b.js'); + var_dump($script_b); + var_dump($v8->executeScript($script_a)); + var_dump($v8->executeScript($script_b)); + var_dump($v8->executeScript($script_a)); +} catch (V8JsScriptException $e) { + var_dump($e); +} +?> +===EOF=== +--EXPECTF-- +resource(%d) of type (V8Js script) +resource(%d) of type (V8Js script) +object(V8Object)#%d (1) { + ["hello"]=> + string(5) "world" +} + +Warning: Script resource from wrong V8Js object passed in %s on line %d +bool(false) +object(V8Object)#%d (1) { + ["hello"]=> + string(5) "world" +} +===EOF=== diff --git a/v8js.cc b/v8js.cc index 04d05b3..4c19c60 100644 --- a/v8js.cc +++ b/v8js.cc @@ -37,6 +37,9 @@ static void php_v8js_create_script_exception(zval *, v8::TryCatch * TSRMLS_DC); ZEND_DECLARE_MODULE_GLOBALS(v8js) +int le_v8js_script; +#define PHP_V8JS_SCRIPT_RES_NAME "V8Js script" + /* {{{ INI Settings */ static ZEND_INI_MH(v8js_OnUpdateV8Flags) /* {{{ */ @@ -72,7 +75,7 @@ static ZEND_INI_MH(v8js_OnUpdateUseDate) /* {{{ */ } /* }}} */ -ZEND_INI_BEGIN() /* {{{ */ +ZEND_INI_BEGIN() /* {{{ */ ZEND_INI_ENTRY("v8js.flags", NULL, ZEND_INI_ALL, v8js_OnUpdateV8Flags) ZEND_INI_ENTRY("v8js.use_date", "0", ZEND_INI_ALL, v8js_OnUpdateUseDate) ZEND_INI_END() @@ -1126,30 +1129,16 @@ static void php_v8js_timer_thread(TSRMLS_D) } } -/* {{{ proto mixed V8Js::executeString(string script [, string identifier [, int flags]]) - */ -static PHP_METHOD(V8Js, executeString) +static php_v8js_script *php_v8js_compile_script(php_v8js_ctx *c, const char *str, int str_len, const char *identifier, int identifier_len) { - char *str = NULL, *identifier = NULL, *tz = NULL; - int str_len = 0, identifier_len = 0; - long flags = V8JS_FLAG_NONE, time_limit = 0, memory_limit = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|slll", &str, &str_len, &identifier, &identifier_len, &flags, &time_limit, &memory_limit) == FAILURE) { - return; - } - - V8JS_BEGIN_CTX(c, getThis()) - - V8JSG(timer_mutex).lock(); - c->time_limit_hit = false; - c->memory_limit_hit = false; - V8JSG(timer_mutex).unlock(); + v8::Isolate *isolate = c->isolate; + php_v8js_script *res = NULL; /* Catch JS exceptions */ v8::TryCatch try_catch; /* Set script identifier */ - v8::Local sname = identifier_len ? V8JS_SYML(identifier, identifier_len) : V8JS_SYM("V8Js::executeString()"); + v8::Local sname = identifier_len ? V8JS_SYML(identifier, identifier_len) : V8JS_SYM("V8Js::compileString()"); /* Compiles a string context independently. TODO: Add a php function which calls this and returns the result as resource which can be executed later. */ v8::Local source = V8JS_STRL(str, str_len); @@ -1158,9 +1147,36 @@ static PHP_METHOD(V8Js, executeString) /* Compile errors? */ if (script.IsEmpty()) { php_v8js_throw_script_exception(&try_catch TSRMLS_CC); + return NULL; + } + res = (php_v8js_script *)emalloc(sizeof(php_v8js_script)); + res->script = new v8::Persistent>(c->isolate, script); + + v8::String::Utf8Value _sname(sname); + res->name = estrndup(ToCString(_sname), _sname.length()); + res->isolate = c->isolate; + return res; +} + +static void php_v8js_execute_script(php_v8js_ctx *c, php_v8js_script *res, long flags, long time_limit, long memory_limit, zval **return_value) +{ + v8::Isolate *isolate = c->isolate; + char *tz = NULL; + + if (res->isolate != c->isolate) { + zend_error(E_WARNING, "Script resource from wrong V8Js object passed"); + ZVAL_BOOL(*return_value, 0); return; } + V8JSG(timer_mutex).lock(); + c->time_limit_hit = false; + c->memory_limit_hit = false; + V8JSG(timer_mutex).unlock(); + + /* Catch JS exceptions */ + v8::TryCatch try_catch; + /* Set flags for runtime use */ V8JS_GLOBAL_SET_FLAGS(isolate, flags); @@ -1206,6 +1222,7 @@ static PHP_METHOD(V8Js, executeString) /* Execute script */ c->in_execution++; + v8::Local script = v8::Local::New(c->isolate, *res->script); v8::Local result = script->Run(); c->in_execution--; @@ -1273,9 +1290,78 @@ static PHP_METHOD(V8Js, executeString) /* Convert V8 value to PHP value */ if (!result.IsEmpty()) { - v8js_to_zval(result, return_value, flags, c->isolate TSRMLS_CC); + v8js_to_zval(result, *return_value, flags, c->isolate TSRMLS_CC); } } + +/* {{{ proto mixed V8Js::executeString(string script [, string identifier [, int flags]]) + */ +static PHP_METHOD(V8Js, executeString) +{ + char *str = NULL, *identifier = NULL, *tz = NULL; + int str_len = 0, identifier_len = 0; + long flags = V8JS_FLAG_NONE, time_limit = 0, memory_limit = 0; + php_v8js_script *res; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|slll", &str, &str_len, &identifier, &identifier_len, &flags, &time_limit, &memory_limit) == FAILURE) { + return; + } + + V8JS_BEGIN_CTX(c, getThis()) + + res = php_v8js_compile_script(c, str, str_len, identifier, identifier_len); + if (!res) { + RETURN_FALSE; + } + php_v8js_execute_script(c, res, flags, time_limit, memory_limit, &return_value); + php_v8js_script_free(res); + +} +/* }}} */ + + +/* {{{ proto mixed V8Js::compileString(string script [, string identifier]) + */ +static PHP_METHOD(V8Js, compileString) +{ + char *str = NULL, *identifier = NULL; + int str_len = 0, identifier_len = 0; + php_v8js_script *res; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &identifier, &identifier_len) == FAILURE) { + return; + } + + V8JS_BEGIN_CTX(c, getThis()) + + res = php_v8js_compile_script(c, str, str_len, identifier, identifier_len); + if (res) { + ZEND_REGISTER_RESOURCE(return_value, res, le_v8js_script); + } + 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; + php_v8js_script *res; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lll", &zscript, &flags, &time_limit, &memory_limit) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(res, php_v8js_script*, &zscript, -1, PHP_V8JS_SCRIPT_RES_NAME, le_v8js_script); + ZEND_VERIFY_RESOURCE(res); + + V8JS_BEGIN_CTX(c, getThis()) + + php_v8js_execute_script(c, res, flags, time_limit, memory_limit, &return_value); +} /* }}} */ /* {{{ proto mixed V8Js::checkString(string script) @@ -1437,7 +1523,22 @@ static void php_v8js_persistent_zval_dtor(zval **p) /* {{{ */ } /* }}} */ -static int php_v8js_register_extension(char *name, uint name_len, char *source, uint source_len, zval *deps_arr, zend_bool auto_enable TSRMLS_DC) /* {{{ */ +static void php_v8js_script_free(php_v8js_script *res) +{ + if (res->name) { + efree(res->name); + } + res->script->~Persistent(); +} + +static void php_v8js_script_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ +{ + php_v8js_script *res = (php_v8js_script *)rsrc->ptr; + if (res) php_v8js_script_free(res); +} +/* }}} */ + +static int php_v8js_register_extension(char *name, uint name_len, char *source, uint source_len, zval *deps_arr, zend_bool auto_enable TSRMLS_DC) /* {{{ */ { php_v8js_jsext *jsext = NULL; @@ -1566,6 +1667,18 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_executestring, 0, 0, 1) 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() @@ -1617,6 +1730,8 @@ static const zend_function_entry v8_function_methods[] = { /* {{{ */ static const zend_function_entry v8js_methods[] = { /* {{{ */ PHP_ME(V8Js, __construct, arginfo_v8js_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) 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) PHP_ME(V8Js, getPendingException, arginfo_v8js_getpendingexception, ZEND_ACC_PUBLIC) PHP_ME(V8Js, setModuleLoader, arginfo_v8js_setmoduleloader, ZEND_ACC_PUBLIC) @@ -1875,6 +1990,8 @@ static PHP_MINIT_FUNCTION(v8js) php_ce_v8js_memory_limit_exception = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); php_ce_v8js_memory_limit_exception->ce_flags |= ZEND_ACC_FINAL; + le_v8js_script = zend_register_list_destructors_ex(php_v8js_script_dtor, NULL, PHP_V8JS_SCRIPT_RES_NAME, module_number); + REGISTER_INI_ENTRIES(); return SUCCESS; From 7310c93c1e802b9ea40e2ce943a1399f1b48c0a1 Mon Sep 17 00:00:00 2001 From: Taneli Leppa Date: Tue, 27 May 2014 10:41:32 +0300 Subject: [PATCH 2/4] Deprecate V8Js::checkString() in favour of compileString() and add tests. --- tests/checkstring.phpt | 5 ++++- tests/checkstring_compile.phpt | 21 +++++++++++++++++++++ v8js.cc | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/checkstring_compile.phpt diff --git a/tests/checkstring.phpt b/tests/checkstring.phpt index a19788e..b5f2790 100644 --- a/tests/checkstring.phpt +++ b/tests/checkstring.phpt @@ -15,7 +15,10 @@ try { } ?> ===EOF=== ---EXPECT-- +--EXPECTF-- +Deprecated: Function V8Js::checkString() is deprecated in %s on line %d bool(true) + +Deprecated: Function V8Js::checkString() is deprecated in %s on line %d string(60) "V8Js::checkString():1: SyntaxError: Unexpected token ILLEGAL" ===EOF=== diff --git a/tests/checkstring_compile.phpt b/tests/checkstring_compile.phpt new file mode 100644 index 0000000..2c9e188 --- /dev/null +++ b/tests/checkstring_compile.phpt @@ -0,0 +1,21 @@ +--TEST-- +Test V8::executeString() : Script validator test using compileString +--SKIPIF-- + +--FILE-- +compileString('print("Hello World!");')); + +try { + var_dump($v8->compileString('print("Hello World!);')); +} catch (V8JsScriptException $e) { + var_dump($e->getMessage()); +} +?> +===EOF=== +--EXPECTF-- +resource(%d) of type (V8Js script) +string(62) "V8Js::compileString():1: SyntaxError: Unexpected token ILLEGAL" +===EOF=== diff --git a/v8js.cc b/v8js.cc index 4c19c60..2201ece 100644 --- a/v8js.cc +++ b/v8js.cc @@ -1732,7 +1732,7 @@ static const zend_function_entry v8js_methods[] = { /* {{{ */ 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) + 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, setModuleLoader, arginfo_v8js_setmoduleloader, ZEND_ACC_PUBLIC) PHP_ME(V8Js, registerExtension, arginfo_v8js_registerextension, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) From de8b0666a6a84bfa57ae4778d429f6f984b7f293 Mon Sep 17 00:00:00 2001 From: Taneli Leppa Date: Tue, 27 May 2014 11:02:17 +0300 Subject: [PATCH 3/4] Some changes to how V8 contexts are managed. --- v8js.cc | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/v8js.cc b/v8js.cc index 2201ece..9198a6f 100644 --- a/v8js.cc +++ b/v8js.cc @@ -1129,11 +1129,12 @@ static void php_v8js_timer_thread(TSRMLS_D) } } -static php_v8js_script *php_v8js_compile_script(php_v8js_ctx *c, const char *str, int str_len, const char *identifier, int identifier_len) +static void php_v8js_compile_script(zval *this_ptr, const char *str, int str_len, const char *identifier, int identifier_len, php_v8js_script **ret) { - v8::Isolate *isolate = c->isolate; php_v8js_script *res = NULL; + V8JS_BEGIN_CTX(c, this_ptr) + /* Catch JS exceptions */ v8::TryCatch try_catch; @@ -1147,7 +1148,7 @@ static php_v8js_script *php_v8js_compile_script(php_v8js_ctx *c, const char *str /* Compile errors? */ if (script.IsEmpty()) { php_v8js_throw_script_exception(&try_catch TSRMLS_CC); - return NULL; + return; } res = (php_v8js_script *)emalloc(sizeof(php_v8js_script)); res->script = new v8::Persistent>(c->isolate, script); @@ -1155,20 +1156,23 @@ static php_v8js_script *php_v8js_compile_script(php_v8js_ctx *c, const char *str v8::String::Utf8Value _sname(sname); res->name = estrndup(ToCString(_sname), _sname.length()); res->isolate = c->isolate; - return res; + *ret = res; + return; } -static void php_v8js_execute_script(php_v8js_ctx *c, php_v8js_script *res, long flags, long time_limit, long memory_limit, zval **return_value) +static void php_v8js_execute_script(zval *this_ptr, php_v8js_script *res, long flags, long time_limit, long memory_limit, zval **return_value) { - v8::Isolate *isolate = c->isolate; char *tz = NULL; + V8JS_BEGIN_CTX(c, this_ptr) + if (res->isolate != c->isolate) { zend_error(E_WARNING, "Script resource from wrong V8Js object passed"); ZVAL_BOOL(*return_value, 0); return; } + V8JSG(timer_mutex).lock(); c->time_limit_hit = false; c->memory_limit_hit = false; @@ -1301,19 +1305,17 @@ static PHP_METHOD(V8Js, executeString) char *str = NULL, *identifier = NULL, *tz = NULL; int str_len = 0, identifier_len = 0; long flags = V8JS_FLAG_NONE, time_limit = 0, memory_limit = 0; - php_v8js_script *res; + php_v8js_script *res = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|slll", &str, &str_len, &identifier, &identifier_len, &flags, &time_limit, &memory_limit) == FAILURE) { return; } - V8JS_BEGIN_CTX(c, getThis()) - - res = php_v8js_compile_script(c, str, str_len, identifier, identifier_len); + php_v8js_compile_script(getThis(), str, str_len, identifier, identifier_len, &res); if (!res) { RETURN_FALSE; } - php_v8js_execute_script(c, res, flags, time_limit, memory_limit, &return_value); + php_v8js_execute_script(getThis(), res, flags, time_limit, memory_limit, &return_value); php_v8js_script_free(res); } @@ -1326,15 +1328,13 @@ static PHP_METHOD(V8Js, compileString) { char *str = NULL, *identifier = NULL; int str_len = 0, identifier_len = 0; - php_v8js_script *res; + php_v8js_script *res = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &identifier, &identifier_len) == FAILURE) { return; } - V8JS_BEGIN_CTX(c, getThis()) - - res = php_v8js_compile_script(c, str, str_len, identifier, identifier_len); + php_v8js_compile_script(getThis(), str, str_len, identifier, identifier_len, &res); if (res) { ZEND_REGISTER_RESOURCE(return_value, res, le_v8js_script); } @@ -1358,9 +1358,7 @@ static PHP_METHOD(V8Js, executeScript) ZEND_FETCH_RESOURCE(res, php_v8js_script*, &zscript, -1, PHP_V8JS_SCRIPT_RES_NAME, le_v8js_script); ZEND_VERIFY_RESOURCE(res); - V8JS_BEGIN_CTX(c, getThis()) - - php_v8js_execute_script(c, res, flags, time_limit, memory_limit, &return_value); + php_v8js_execute_script(getThis(), res, flags, time_limit, memory_limit, &return_value); } /* }}} */ @@ -1528,6 +1526,7 @@ static void php_v8js_script_free(php_v8js_script *res) if (res->name) { efree(res->name); } + res->script->Reset(); res->script->~Persistent(); } From 200c16c30e4669812db21437555a803c168ba8fe Mon Sep 17 00:00:00 2001 From: Taneli Leppa Date: Tue, 1 Jul 2014 11:25:37 +0300 Subject: [PATCH 4/4] Fixed script destructor and free resource struct when done. --- php_v8js_macros.h | 2 +- v8js.cc | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/php_v8js_macros.h b/php_v8js_macros.h index 5d6a854..26230cf 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -292,7 +292,7 @@ typedef struct _php_v8js_script { v8::Persistent> *script; } php_v8js_script; -static void php_v8js_script_free(php_v8js_script *res); +static void php_v8js_script_free(php_v8js_script *res, bool dispose_persistent); #endif /* PHP_V8JS_MACROS_H */ diff --git a/v8js.cc b/v8js.cc index 9198a6f..17a2c66 100644 --- a/v8js.cc +++ b/v8js.cc @@ -1316,7 +1316,7 @@ static PHP_METHOD(V8Js, executeString) RETURN_FALSE; } php_v8js_execute_script(getThis(), res, flags, time_limit, memory_limit, &return_value); - php_v8js_script_free(res); + php_v8js_script_free(res, true); } /* }}} */ @@ -1521,19 +1521,25 @@ static void php_v8js_persistent_zval_dtor(zval **p) /* {{{ */ } /* }}} */ -static void php_v8js_script_free(php_v8js_script *res) +static void php_v8js_script_free(php_v8js_script *res, bool dispose_persistent) { if (res->name) { efree(res->name); + res->name = NULL; + } + if (dispose_persistent) { + res->script->~Persistent(); // does Reset() + res->script = NULL; } - res->script->Reset(); - res->script->~Persistent(); } static void php_v8js_script_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { php_v8js_script *res = (php_v8js_script *)rsrc->ptr; - if (res) php_v8js_script_free(res); + if (res) { + php_v8js_script_free(res, false); + efree(res); + } } /* }}} */