diff --git a/.github/workflows/scan-build.yml b/.github/workflows/scan-build.yml index 5617f3a688..4237a28c4f 100644 --- a/.github/workflows/scan-build.yml +++ b/.github/workflows/scan-build.yml @@ -54,7 +54,7 @@ jobs: shell: bash working-directory: freeswitch run: | - DEBIAN_FRONTEND=noninteractive apt-get install -y libpcre2-dev libsphinxbase-dev libpocketsphinx-dev + DEBIAN_FRONTEND=noninteractive apt-get install -y libpcre2-dev libsphinxbase-dev libpocketsphinx-dev libnode-dev ./ci.sh -t scan-build -a configure -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip" ./ci.sh -t scan-build -a build -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip" ./ci.sh -t scan-build -a install -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip" diff --git a/configure.ac b/configure.ac index 5dd7e4b980..f1ef880d53 100644 --- a/configure.ac +++ b/configure.ac @@ -1507,21 +1507,60 @@ PKG_CHECK_MODULES([MEMCACHED], [libmemcached >= 0.31],[ AM_CONDITIONAL([HAVE_MEMCACHED],[false]) ]) -PKG_CHECK_MODULES([V8FS_STATIC], [v8-6.1_static >= 6.1.298],[ - AM_CONDITIONAL([HAVE_V8FS],[true])],[ - PKG_CHECK_MODULES([V8FS_STATIC], [v8fs_static >= 6.1.298],[ - AM_CONDITIONAL([HAVE_V8FS],[true])],[ - PKG_CHECK_MODULES([V8FS_STATIC], [v8 >= 6.1.298],[ - AM_CONDITIONAL([HAVE_V8FS],[true])],[ - if module_enabled mod_v8; then - AC_MSG_ERROR([You need to either install libv8-6.1-dev (>= 6.1.298), libv8fs-dev (>= 6.1.298) or disable mod_v8 in modules.conf]) - else - AC_MSG_RESULT([no]) - AM_CONDITIONAL([HAVE_V8FS],[false]) - fi - ]) - ]) -]) +# mod_v8 needs the V8 JavaScript engine, provided by libnode-dev. It ships no +# pkg-config file, so probe the well known header and library locations. +AC_ARG_WITH([v8], + [AS_HELP_STRING([--with-v8=DIR], + [look for the libnode/V8 headers (the directory containing v8.h) in DIR])], + [v8_incdir="$withval"], [v8_incdir=""]) + +have_v8="no" + +AC_MSG_CHECKING([for libnode bundled V8 headers]) +V8_INCDIR="" +for d in "$v8_incdir" /usr/include/nodejs/deps/v8/include /usr/include/node /usr/local/include/node /usr/include/v8 ; do + if test -n "$d" && test -f "$d/v8.h" && test -f "$d/libplatform/libplatform.h" ; then + V8_INCDIR="$d"; break + fi +done +if test -n "$V8_INCDIR"; then + AC_MSG_RESULT([$V8_INCDIR]) + AC_LANG_PUSH([C++]) + v8_save_LIBS="$LIBS" + # Prefer the standalone split V8 libraries shipped by libnode-dev; fall + # back to the all-in-one libnode if they are not present. + AC_MSG_CHECKING([for standalone V8 libraries (-lv8 -lv8_libplatform)]) + LIBS="-lv8 -lv8_libplatform -lv8_libbase $v8_save_LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes]); V8_LIBS="-lv8 -lv8_libplatform -lv8_libbase"], + [AC_MSG_RESULT([no]) + AC_MSG_CHECKING([for all-in-one libnode (-lnode)]) + LIBS="-lnode $v8_save_LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes]); V8_LIBS="-lnode"], + [AC_MSG_RESULT([no])])]) + LIBS="$v8_save_LIBS" + AC_LANG_POP([C++]) + if test -n "$V8_LIBS"; then + V8_CFLAGS="-I$V8_INCDIR" + have_v8="yes" + fi +else + AC_MSG_RESULT([no]) +fi + +AC_SUBST([V8_CFLAGS]) +AC_SUBST([V8_LIBS]) + +if test "x$have_v8" = "xyes"; then + AM_CONDITIONAL([HAVE_V8],[true]) +else + if module_enabled mod_v8; then + AC_MSG_ERROR([mod_v8 is enabled but libnode was not found. Install libnode-dev (Debian/Ubuntu: apt-get install libnode-dev) or disable mod_v8 in modules.conf]) + else + AM_CONDITIONAL([HAVE_V8],[false]) + fi +fi PKG_CHECK_MODULES([KS], [libks2 >= 2.0.11],[ AM_CONDITIONAL([HAVE_KS],[true])],[ diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 80996ed4dc..b4f6eb3a57 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -51,10 +51,8 @@ avoid_mods=( xml_int/mod_xml_ldap ) avoid_mods_armhf=( - languages/mod_v8 ) avoid_mods_arm64=( - languages/mod_v8 ) avoid_mods_sid=( directories/mod_ldap diff --git a/debian/control-modules b/debian/control-modules index 07a7bdc455..c33b873a88 100755 --- a/debian/control-modules +++ b/debian/control-modules @@ -540,7 +540,7 @@ Build-Depends-Trixie: python3-dev, python3-setuptools Module: languages/mod_v8 Description: mod_v8 Adds mod_v8. -Build-Depends: git, libv8-6.1-dev +Build-Depends: libnode-dev ## mod/loggers diff --git a/src/mod/languages/mod_v8/Makefile.am b/src/mod/languages/mod_v8/Makefile.am index 1363d8b2c2..bb14928ae9 100644 --- a/src/mod/languages/mod_v8/Makefile.am +++ b/src/mod/languages/mod_v8/Makefile.am @@ -4,12 +4,12 @@ AUTOMAKE_OPTIONS += foreign MODNAME=mod_v8 -AM_CFLAGS += -I. -I./include -I$(switch_srcdir)/src/mod/languages/mod_v8/include $(V8FS_STATIC_CFLAGS) -AM_CPPFLAGS += -I. -I./include -I$(switch_srcdir)/src/mod/languages/mod_v8/include $(V8FS_STATIC_CFLAGS) -std=c++11 +AM_CFLAGS += -I. -I./include -I$(switch_srcdir)/src/mod/languages/mod_v8/include $(V8_CFLAGS) +AM_CPPFLAGS += -I. -I./include -I$(switch_srcdir)/src/mod/languages/mod_v8/include $(V8_CFLAGS) -std=c++17 AM_LDFLAGS += -avoid-version -module -no-undefined -shared AM_LIBADD = $(switch_builddir)/libfreeswitch.la -AM_LDFLAGS += $(V8FS_STATIC_LIBS) +AM_LDFLAGS += $(V8_LIBS) BUILT_SOURCES = $(V8LIB) diff --git a/src/mod/languages/mod_v8/include/fsdtmf.hpp b/src/mod/languages/mod_v8/include/fsdtmf.hpp index c931390cea..0482a8ef0b 100644 --- a/src/mod/languages/mod_v8/include/fsdtmf.hpp +++ b/src/mod/languages/mod_v8/include/fsdtmf.hpp @@ -56,7 +56,7 @@ public: /* Methods available from JavaScript */ static void *Construct(const v8::FunctionCallbackInfo& info); - static v8::Handle New(switch_dtmf_t *dtmf, const char *name, JSMain *js); + static v8::Local New(switch_dtmf_t *dtmf, const char *name, JSMain *js); JS_DTMF_GET_PROPERTY_DEF(GetProperty); }; diff --git a/src/mod/languages/mod_v8/include/fsevent.hpp b/src/mod/languages/mod_v8/include/fsevent.hpp index 53336aede2..b289268b2e 100644 --- a/src/mod/languages/mod_v8/include/fsevent.hpp +++ b/src/mod/languages/mod_v8/include/fsevent.hpp @@ -67,7 +67,7 @@ public: /* Methods available from JavaScript */ static void *Construct(const v8::FunctionCallbackInfo& info); - static v8::Handle New(switch_event_t *event, const char *name, JSMain *js); + static v8::Local New(switch_event_t *event, const char *name, JSMain *js); JS_EVENT_FUNCTION_DEF(AddHeader); JS_EVENT_FUNCTION_DEF(GetHeader); JS_EVENT_FUNCTION_DEF(IsArrayHeader); diff --git a/src/mod/languages/mod_v8/include/fsxml.hpp b/src/mod/languages/mod_v8/include/fsxml.hpp index e831c659ec..b8e81b8352 100644 --- a/src/mod/languages/mod_v8/include/fsxml.hpp +++ b/src/mod/languages/mod_v8/include/fsxml.hpp @@ -53,7 +53,7 @@ private: void Init(); void InitRootObject(); - v8::Handle GetJSObjFromXMLObj(const switch_xml_t xml, const v8::FunctionCallbackInfo& info); + v8::Local GetJSObjFromXMLObj(const switch_xml_t xml, const v8::FunctionCallbackInfo& info); void StoreObjectInHash(switch_xml_t xml, FSXML *obj); FSXML *FindObjectInHash(switch_xml_t xml); void DeleteObjectInHash(switch_xml_t xml); diff --git a/src/mod/languages/mod_v8/include/javascript.hpp b/src/mod/languages/mod_v8/include/javascript.hpp index 800e5894af..35d30ea570 100644 --- a/src/mod/languages/mod_v8/include/javascript.hpp +++ b/src/mod/languages/mod_v8/include/javascript.hpp @@ -33,10 +33,160 @@ #include #include + +/* + * --- V8 API compatibility layer --- + * + * mod_v8 was originally written against the custom static V8 6.1 package. On + * modern systems FreeSWITCH builds it against the V8 engine bundled with + * upstream libnode-dev (V8 10.x). The two APIs differ in a handful of + * mechanical but pervasive ways (MaybeLocal return values, mandatory Isolate* + * / Context arguments, a few removed methods). The helpers below hide those + * differences so the bulk of the module is shared between both engines. + * + * Windows keeps building against the old static V8 6.1, so the legacy (#else) + * branches must remain valid. The active API is selected purely from + * V8_MAJOR_VERSION, so no build-system define is required. + */ +#if defined(V8_MAJOR_VERSION) && V8_MAJOR_VERSION >= 7 +#define V8FS_NEW_API 1 +#else +#define V8FS_NEW_API 0 +#endif + #if defined(V8_MAJOR_VERSION) && V8_MAJOR_VERSION >=5 #include +#if !V8FS_NEW_API +/* v8-util.h is unused by mod_v8 and is no longer shipped by libnode-dev. */ #include #endif +#endif + +/* + * The isolate / context currently entered by the running script. mod_v8 only + * touches V8 objects while a script is executing (inside an Isolate::Scope and + * Context::Scope), where GetCurrent()/GetCurrentContext() are valid. + */ +static inline v8::Isolate *js_current_isolate(void) +{ + return v8::Isolate::GetCurrent(); +} + +static inline v8::Local js_current_context(void) +{ + return v8::Isolate::GetCurrent()->GetCurrentContext(); +} + +/* + * v8::String::NewFromUtf8() returns a Local on V8 6.1 but a MaybeLocal on + * V8 7+. This wrapper always yields a Local and tolerates a NULL str. + */ +static inline v8::Local js_new_string(v8::Isolate *isolate, const char *str, int length = -1) +{ +#if V8FS_NEW_API + return v8::String::NewFromUtf8(isolate, str ? str : "", v8::NewStringType::kNormal, length).ToLocalChecked(); +#else + return v8::String::NewFromUtf8(isolate, str ? str : "", v8::String::kNormalString, length); +#endif +} + +/* + * v8::String::Utf8Value requires an explicit Isolate* on V8 7+. The single + * argument constructor keeps the (very common) call sites unchanged by using + * the currently entered isolate. + */ +class JsUtf8Value : public v8::String::Utf8Value +{ +public: + explicit JsUtf8Value(v8::Local obj) +#if V8FS_NEW_API + : v8::String::Utf8Value(v8::Isolate::GetCurrent(), obj) {} +#else + : v8::String::Utf8Value(obj) {} +#endif + JsUtf8Value(v8::Isolate *isolate, v8::Local obj) +#if V8FS_NEW_API + : v8::String::Utf8Value(isolate, obj) {} +#else + : v8::String::Utf8Value(obj) {} +#endif +}; + +/* v8::Value::BooleanValue lost its no-argument form on V8 7+. */ +static inline bool js_to_bool(v8::Local val) +{ +#if V8FS_NEW_API + return val->BooleanValue(v8::Isolate::GetCurrent()); +#else + return val->BooleanValue(); +#endif +} + +/* + * v8::Object::Set() / Get() lost their no-context forms on V8 7+. These run + * while the script's context is entered, so the current context is used. + */ +static inline void js_obj_set(v8::Local obj, v8::Local key, v8::Local val) +{ + obj->Set(js_current_context(), key, val).FromMaybe(false); +} + +static inline v8::Local js_obj_get(v8::Local obj, v8::Local key) +{ + return obj->Get(js_current_context(), key).FromMaybe(v8::Local()); +} + +/* + * v8::ReturnValue::Set() no longer accepts a Persistent handle on V8 7+; + * convert it to a Local first. Local::New(isolate, persistent) is valid on the + * old API too, so this helper works for both engines. + */ +template +static inline v8::Local js_local(const v8::Persistent &persistent) +{ + return v8::Local::New(v8::Isolate::GetCurrent(), persistent); +} + +/* v8::Script::Run() now requires a context and returns a MaybeLocal. */ +static inline v8::Local js_run_script(v8::Local script) +{ + if (script.IsEmpty()) { + return v8::Local(); + } +#if V8FS_NEW_API + v8::Local result; + if (!script->Run(js_current_context()).ToLocal(&result)) { + return v8::Local(); + } + return result; +#else + return script->Run(); +#endif +} + +/* v8::Function::Call now requires a context and returns a MaybeLocal. */ +static inline v8::Local js_call(v8::Local fn, v8::Local recv, int argc, v8::Local *argv) +{ +#if V8FS_NEW_API + v8::Local result; + if (!fn->Call(js_current_context(), recv, argc, argv).ToLocal(&result)) { + return v8::Local(); + } + return result; +#else + return fn->Call(recv, argc, argv); +#endif +} + +/* v8::StackTrace::GetFrame() requires an Isolate* on V8 7+. */ +static inline v8::Local js_stack_frame(v8::Local trace, v8::Isolate *isolate, uint32_t index) +{ +#if V8FS_NEW_API + return trace->GetFrame(isolate, index); +#else + return trace->GetFrame(index); +#endif +} #include #include @@ -64,7 +214,7 @@ } else {\ int line;\ char *file = JSMain::GetStackInfo(info.GetIsolate(), &line);\ - v8::String::Utf8Value str(info.Holder());\ + JsUtf8Value str(info.Holder());\ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "mod_v8", line, NULL, SWITCH_LOG_DEBUG, "No valid internal data available for %s when calling %s\n", *str ? *str : "[unknown]", #class_name "::" #method_name "()");\ free(file);\ info.GetReturnValue().Set(false);\ @@ -83,10 +233,10 @@ } else {\ int line;\ char *file = JSMain::GetStackInfo(info.GetIsolate(), &line);\ - v8::String::Utf8Value str(info.Holder());\ + JsUtf8Value str(info.Holder());\ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "mod_v8", line, NULL, SWITCH_LOG_DEBUG, "No valid internal data available for %s when calling %s\n", *str ? *str : "[unknown]", #class_name "::" #method_name "()");\ free(file);\ - info.GetReturnValue().Set(false);\ + /* A property setter's ReturnValue is void; V8 7+ rejects Set() on it. */\ }\ }\ void method_name##Impl(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info) @@ -102,7 +252,7 @@ } else {\ int line;\ char *file = JSMain::GetStackInfo(info.GetIsolate(), &line);\ - v8::String::Utf8Value str(info.Holder());\ + JsUtf8Value str(info.Holder());\ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "mod_v8", line, NULL, SWITCH_LOG_DEBUG, "No valid internal data available for %s when calling %s\n", *str ? *str : "[unknown]", #class_name "::" #method_name "()");\ free(file);\ info.GetReturnValue().Set(false);\ @@ -226,14 +376,14 @@ private: static void CreateInstance(const v8::FunctionCallbackInfo& args); /* Store a C++ instance to a JS object's private data */ - static void AddInstance(v8::Isolate *isolate, const v8::Handle& handle, const v8::Handle& object, bool autoDestroy); + static void AddInstance(v8::Isolate *isolate, const v8::Local& handle, const v8::Local& object, bool autoDestroy); public: JSBase(JSMain *owner); JSBase(const v8::FunctionCallbackInfo& info); virtual ~JSBase(void); /* Returns the JS object related to the C++ instance */ - v8::Handle GetJavaScriptObject(); + v8::Local GetJavaScriptObject(); /* Register a C++ class inside V8 (must be called within a entered isolate, and context) */ static void Register(v8::Isolate *isolate, const js_class_definition_t *desc); @@ -263,7 +413,7 @@ public: } /* Get a JavaScript function from a JavaScript argument (can be either a string or the actual function) */ - static v8::Handle GetFunctionFromArg(v8::Isolate *isolate, const v8::Local& arg); + static v8::Local GetFunctionFromArg(v8::Isolate *isolate, const v8::Local& arg); /* Default JS setter callback, to be used for read only values */ static void DefaultSetProperty(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); diff --git a/src/mod/languages/mod_v8/mod_v8.cpp b/src/mod/languages/mod_v8/mod_v8.cpp index 96ac67f2f6..b3b14906e4 100644 --- a/src/mod/languages/mod_v8/mod_v8.cpp +++ b/src/mod/languages/mod_v8/mod_v8.cpp @@ -95,6 +95,7 @@ #include "fseventhandler.hpp" #include +#include using namespace std; using namespace v8; @@ -421,9 +422,9 @@ static int env_init(JSMain *js) static void v8_error(Isolate* isolate, TryCatch* try_catch) { HandleScope handle_scope(isolate); - String::Utf8Value exception(try_catch->Exception()); + JsUtf8Value exception(try_catch->Exception()); const char *exception_string = js_safe_str(*exception); - Handle message = try_catch->Message(); + Local message = try_catch->Message(); const char *msg; string filename = __FILE__; int line = __LINE__; @@ -437,16 +438,16 @@ static void v8_error(Isolate* isolate, TryCatch* try_catch) } if (!message.IsEmpty()) { - String::Utf8Value fname(message->GetScriptResourceName()); + JsUtf8Value fname(message->GetScriptResourceName()); if (*fname) { filename = *fname; } - line = message->GetLineNumber(); + line = message->GetLineNumber(js_current_context()).FromMaybe(0); msg = exception_string; - String::Utf8Value sourceline(message->GetSourceLine()); + JsUtf8Value sourceline(message->GetSourceLine(js_current_context()).ToLocalChecked()); if (*sourceline) { text = *sourceline; } @@ -495,7 +496,7 @@ void perf_log(const char *fmt, ...) switch_mutex_lock(globals.mutex); if (globals.performance_monitor) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, fmt, ap); + switch_log_vprintf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, fmt, ap); } switch_mutex_unlock(globals.mutex); @@ -523,6 +524,7 @@ void LoadScript(MaybeLocal *v8_script, Isolate *isolate, const char ScriptCompiler::CachedData *cached_data = 0; v8_compiled_script_cache_t *stored_compiled_script_cache = NULL; ScriptCompiler::CompileOptions options; + bool produce_cache = false; /* Do not cache if the caching is disabled @@ -557,30 +559,68 @@ void LoadScript(MaybeLocal *v8_script, Isolate *isolate, const char } - if (!cached_data) options = ScriptCompiler::kProduceCodeCache; + if (!cached_data) { +#if V8FS_NEW_API + /* V8 7+ removed kProduceCodeCache; the code cache is created + * explicitly from the compiled script further down. */ + options = ScriptCompiler::kNoCompileOptions; +#else + options = ScriptCompiler::kProduceCodeCache; +#endif + produce_cache = true; + } } - ScriptCompiler::Source source(String::NewFromUtf8(isolate, script_data), cached_data); + ScriptCompiler::Source source(js_new_string(isolate, script_data), cached_data); *v8_script = ScriptCompiler::Compile(isolate->GetCurrentContext(), &source, options); if (!v8_script->IsEmpty()) { - if (options == ScriptCompiler::kProduceCodeCache && !source.GetCachedData()->rejected) { - int length = source.GetCachedData()->length; - uint8_t* raw_cached_data = new uint8_t[length]; - v8_compiled_script_cache_t *compiled_script_cache = new v8_compiled_script_cache_t; - memcpy(raw_cached_data, source.GetCachedData()->data, static_cast(length)); - compiled_script_cache->data.reset(raw_cached_data, array_deleter()); - compiled_script_cache->length = length; - compiled_script_cache->compile_time = switch_time_now(); + if (produce_cache) { +#if V8FS_NEW_API + /* Produce the code cache explicitly from the freshly compiled script. */ + Local compiled_script; + ScriptCompiler::CachedData *produced = NULL; - switch_mutex_lock(globals.compiled_script_hash_mutex); - switch_core_hash_insert_destructor(globals.compiled_script_hash, script_file, compiled_script_cache, destructor); - switch_mutex_unlock(globals.compiled_script_hash_mutex); - - perf_log("Javascript ['%s'] cache was produced.\n", script_file); + if (v8_script->ToLocal(&compiled_script)) { + produced = ScriptCompiler::CreateCodeCache(compiled_script->GetUnboundScript()); + } + if (produced) { + int length = produced->length; + uint8_t* raw_cached_data = new uint8_t[length]; + v8_compiled_script_cache_t *compiled_script_cache = new v8_compiled_script_cache_t; + memcpy(raw_cached_data, produced->data, static_cast(length)); + compiled_script_cache->data.reset(raw_cached_data, array_deleter()); + compiled_script_cache->length = length; + compiled_script_cache->compile_time = switch_time_now(); + + switch_mutex_lock(globals.compiled_script_hash_mutex); + switch_core_hash_insert_destructor(globals.compiled_script_hash, script_file, compiled_script_cache, destructor); + switch_mutex_unlock(globals.compiled_script_hash_mutex); + + perf_log("Javascript ['%s'] cache was produced.\n", script_file); + + delete produced; + } +#else + if (!source.GetCachedData()->rejected) { + int length = source.GetCachedData()->length; + uint8_t* raw_cached_data = new uint8_t[length]; + v8_compiled_script_cache_t *compiled_script_cache = new v8_compiled_script_cache_t; + memcpy(raw_cached_data, source.GetCachedData()->data, static_cast(length)); + compiled_script_cache->data.reset(raw_cached_data, array_deleter()); + compiled_script_cache->length = length; + compiled_script_cache->compile_time = switch_time_now(); + + switch_mutex_lock(globals.compiled_script_hash_mutex); + switch_core_hash_insert_destructor(globals.compiled_script_hash, script_file, compiled_script_cache, destructor); + switch_mutex_unlock(globals.compiled_script_hash_mutex); + + perf_log("Javascript ['%s'] cache was produced.\n", script_file); + } +#endif } else if (options == ScriptCompiler::kConsumeCodeCache) { if (source.GetCachedData()->rejected) { @@ -665,7 +705,7 @@ static int v8_parse_and_execute(switch_core_session_t *session, const char *inpu switch_mutex_unlock(globals.task_manager_mutex); // New global template - Handle global = ObjectTemplate::New(isolate); + Local global = ObjectTemplate::New(isolate); if (global.IsEmpty()) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create JS global object template\n"); @@ -673,7 +713,7 @@ static int v8_parse_and_execute(switch_core_session_t *session, const char *inpu /* Add all global functions */ for (size_t i = 0; i < js->GetExtenderFunctions().size(); i++) { js_function_t *proc = js->GetExtenderFunctions()[i]; - global->Set(String::NewFromUtf8(isolate, proc->name), FunctionTemplate::New(isolate, proc->func)); + global->Set(js_new_string(isolate, proc->name), FunctionTemplate::New(isolate, proc->func)); } // Create a new context. @@ -721,7 +761,7 @@ static int v8_parse_and_execute(switch_core_session_t *session, const char *inpu obj->RegisterInstance(isolate, "session", true); } else { /* Add a session object as a boolean instead, just to make it safe to check if it exists as expected */ - context->Global()->Set(String::NewFromUtf8(isolate, "session"), Boolean::New(isolate, false)); + js_obj_set(context->Global(), js_new_string(isolate, "session"), Boolean::New(isolate, false)); } if (v8_event) { @@ -742,14 +782,14 @@ static int v8_parse_and_execute(switch_core_session_t *session, const char *inpu { /* Add xml handler global variables */ - Handle XML_REQUEST = Array::New(isolate, 4); + Local XML_REQUEST = Array::New(isolate, 4); - XML_REQUEST->Set(String::NewFromUtf8(isolate, "key_name"), String::NewFromUtf8(isolate, js_safe_str(xml_handler->key_name))); - XML_REQUEST->Set(String::NewFromUtf8(isolate, "key_value"), String::NewFromUtf8(isolate, js_safe_str(xml_handler->key_value))); - XML_REQUEST->Set(String::NewFromUtf8(isolate, "section"), String::NewFromUtf8(isolate, js_safe_str(xml_handler->section))); - XML_REQUEST->Set(String::NewFromUtf8(isolate, "tag_name"), String::NewFromUtf8(isolate, js_safe_str(xml_handler->tag_name))); + js_obj_set(XML_REQUEST, js_new_string(isolate, "key_name"), js_new_string(isolate, js_safe_str(xml_handler->key_name))); + js_obj_set(XML_REQUEST, js_new_string(isolate, "key_value"), js_new_string(isolate, js_safe_str(xml_handler->key_value))); + js_obj_set(XML_REQUEST, js_new_string(isolate, "section"), js_new_string(isolate, js_safe_str(xml_handler->section))); + js_obj_set(XML_REQUEST, js_new_string(isolate, "tag_name"), js_new_string(isolate, js_safe_str(xml_handler->tag_name))); - context->Global()->Set(String::NewFromUtf8(isolate, "XML_REQUEST"), XML_REQUEST); + js_obj_set(context->Global(), js_new_string(isolate, "XML_REQUEST"), XML_REQUEST); if (xml_handler->params) { FSEvent::New(xml_handler->params, "params", js); @@ -767,10 +807,10 @@ static int v8_parse_and_execute(switch_core_session_t *session, const char *inpu // Add arguments before running script. Local arguments = Array::New(isolate, argc); for (int y = 0; y < argc; y++) { - arguments->Set(Integer::New(isolate, y), String::NewFromUtf8(isolate, argv[y])); + js_obj_set(arguments, Integer::New(isolate, y), js_new_string(isolate, argv[y])); } - context->Global()->Set(String::NewFromUtf8(isolate, "argv"), arguments); - context->Global()->Set(String::NewFromUtf8(isolate, "argc"), Integer::New(isolate, argc)); + js_obj_set(context->Global(), js_new_string(isolate, "argv"), arguments); + js_obj_set(context->Global(), js_new_string(isolate, "argc"), Integer::New(isolate, argc)); } const char *script_data = NULL; @@ -806,7 +846,7 @@ static int v8_parse_and_execute(switch_core_session_t *session, const char *inpu /* Store our base directory in variable 'scriptPath' */ char *scriptPath = v8_get_script_path(script_file); if (scriptPath) { - context->Global()->Set(String::NewFromUtf8(isolate, "scriptPath"), String::NewFromUtf8(isolate, scriptPath)); + js_obj_set(context->Global(), js_new_string(isolate, "scriptPath"), js_new_string(isolate, scriptPath)); switch_safe_free(scriptPath); } @@ -819,8 +859,8 @@ static int v8_parse_and_execute(switch_core_session_t *session, const char *inpu LoadScript(&v8_script, isolate, script_data, script_file); #else // Create a string containing the JavaScript source code. - Handle source = String::NewFromUtf8(isolate, script_data); - Handle