diff --git a/.travis.yml b/.travis.yml index 4dabbd25e8a..8c0e08ce1ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ jdk: - oraclejdk7 install: - ANDROID_SDK_PACKAGE=android-sdk_r24.0.1-macosx.zip - - ANDROID_NDK_PACKAGE=android-ndk-r10e-darwin-x86_64.zip + - ANDROID_NDK_PACKAGE=android-ndk-r11c-darwin-x86_64.zip - export TITANIUM_ANDROID_API="23" - export SDKS="$TRAVIS_BUILD_DIR/sdks" - echo $SDKS @@ -23,8 +23,8 @@ install: - echo yes | android -s update sdk --no-ui --all --filter sys-img-armeabi-v7a-android-22 - # Install required Android NDK - - if [ ! -d "$SDKS/android-ndk-r10e" ]; then wget http://dl.google.com/android/repository/$ANDROID_NDK_PACKAGE; unzip -q -o $ANDROID_NDK_PACKAGE; fi - - export ANDROID_NDK=${PWD}/android-ndk-r10e + - if [ ! -d "$SDKS/android-ndk-r11c" ]; then wget http://dl.google.com/android/repository/$ANDROID_NDK_PACKAGE; unzip -q -o $ANDROID_NDK_PACKAGE; fi + - export ANDROID_NDK=${PWD}/android-ndk-r11c - - export ANDROID_PLATFORM=$ANDROID_SDK/platforms/android-$TITANIUM_ANDROID_API - export GOOGLE_APIS=$ANDROID_SDK/add-ons/addon-google_apis-google-$TITANIUM_ANDROID_API diff --git a/android/build/libv8.properties b/android/build/libv8.properties index a30206bea70..bbba1dff6e9 100644 --- a/android/build/libv8.properties +++ b/android/build/libv8.properties @@ -1,2 +1,2 @@ -libv8.version=3.9.24.29 +libv8.version=5.0.71.33 libv8.mode=release diff --git a/android/cli/commands/_build.js b/android/cli/commands/_build.js index 0f6a5242cbf..1f92d57b6f4 100644 --- a/android/cli/commands/_build.js +++ b/android/cli/commands/_build.js @@ -69,7 +69,7 @@ function AndroidBuilder() { this.targets = ['emulator', 'device', 'dist-playstore']; - this.validABIs = ['armeabi', 'armeabi-v7a', 'x86']; + this.validABIs = ['armeabi-v7a', 'x86']; this.xmlMergeRegExp = /^(strings|attrs|styles|bools|colors|dimens|ids|integers|arrays)\.xml$/; diff --git a/android/cli/commands/_buildModule.js b/android/cli/commands/_buildModule.js index 31a7a7cd328..745a4ed62da 100644 --- a/android/cli/commands/_buildModule.js +++ b/android/cli/commands/_buildModule.js @@ -1076,7 +1076,7 @@ AndroidModuleBuilder.prototype.ndkBuild = function (next) { } this.dirWalker(this.buildGenLibsDir, function (file) { - if (path.extname(file) == '.so' && file.indexOf('libstlport_shared.so') == -1) { + if (path.extname(file) == '.so' && file.indexOf('libstlport_shared.so') == -1 && file.indexOf('libc++_shared.so') == -1) { var relativeName = path.relative(this.buildGenLibsDir, file), targetDir = path.join(this.libsDir, path.dirname(relativeName)); diff --git a/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBinding.fm b/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBinding.fm index 05685a4c99a..8b779a208cb 100644 --- a/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBinding.fm +++ b/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBinding.fm @@ -169,13 +169,13 @@ <#macro openModuleNamespace> <#list moduleId?split(".") as ns> - namespace ${ns?lower_case} { +namespace ${ns?lower_case} { <#macro closeModuleNamespace> <#list moduleId?split(".")?reverse as ns> - } // ${ns?lower_case} +} // ${ns?lower_case} @@ -183,7 +183,7 @@ <@openModuleNamespace/> <#list proxyAttrs.fullAPIName?split(".") as ns> <#if ns_has_next && ns?lower_case != moduleId?lower_case> - namespace ${ns?lower_case} { + namespace ${ns?lower_case} { @@ -191,7 +191,7 @@ <#macro closeNamespace> <#list proxyAttrs.fullAPIName?split(".")?reverse as ns> <#if ns_index != 0 && ns?lower_case != moduleId?lower_case> - } // namespace ${ns?lower_case} + } // namespace ${ns?lower_case} <@closeModuleNamespace/> @@ -426,7 +426,7 @@ <#if type?ends_with("Proxy")> <#return typeInfo["org.appcelerator.kroll.KrollProxy"]> - + <#if type?ends_with("Exception")> <#return typeInfo["org.appcelerator.kroll.KrollException"]> @@ -485,7 +485,8 @@ fails, a JS exception is returned. const char *error = "Invalid value, expected type ${info.jsType}."; LOGE(TAG, error); <#if !(logOnly!false)> - return titanium::JSException::Error(error); + titanium::JSException::Error(isolate, error); + return; } @@ -510,23 +511,24 @@ fails, a JS exception is returned. <#local valueExpr = expr> <#elseif info.jsType == "Number"> <#local type = "Local"> - <#local valueExpr = expr + "->ToNumber()"> - <#local stringExpr = expr + "->ToString()"> + <#local valueExpr = expr + "->ToNumber(isolate)"> + <#local stringExpr = expr + "->ToString(isolate)"> <#elseif info?keys?seq_contains("jsHandleCast")> <#local type = "Local<" + info.jsType + ">"> - <#local valueExpr = "Local<" + info.jsType + ">::Cast(" + expr + ")"> + <#local valueExpr = expr + ".As<" + info.jsType + ">()"> <#else> <#local type = "Local<" + info.jsType + ">"> - <#local valueExpr = expr + "->To" + info.jsType + "()"> + <#local valueExpr = expr + "->To" + info.jsType + "(isolate)"> - + <#t> <#if info.jsType == "Number"> - if ((titanium::V8Util::isNaN(${expr}) && !${expr}->IsUndefined()) || ${stringExpr}->Length() == 0) { + if ((titanium::V8Util::isNaN(isolate, ${expr}) && !${expr}->IsUndefined()) || ${stringExpr}->Length() == 0) { const char *error = "Invalid value, expected type ${info.jsType}."; LOGE(TAG, error); <#if !(logOnly!false)> - return titanium::JSException::Error(error); + titanium::JSException::Error(isolate, error); + return; } @@ -534,7 +536,12 @@ fails, a JS exception is returned. if (!${expr}->IsNull()) { ${type} ${current_arg} = ${valueExpr}; jArguments[${index}].${info.jvalue} = - titanium::TypeConverter::${info.jsToJavaConverter}(env, ${current_arg}<#if checkNew>, &isNew_${index}); + titanium::TypeConverter::${info.jsToJavaConverter}( + <#if info.jsToJavaConverter?matches("^js(Number|Date|String|Boolean)To.+")> + <#else> + isolate, + + env, ${current_arg}<#if checkNew>, &isNew_${index}); } else { jArguments[${index}].${info.jvalue} = NULL; } @@ -553,7 +560,7 @@ fails, a JS exception is returned. jobjectArray varArgs = env->NewObjectArray(length, titanium::JNIUtil::objectClass, NULL); for (uint32_t i = 0; i < length; ++i) { bool isNew; - jobject arg = titanium::TypeConverter::jsValueToJavaObject(env, args[i+${start}], &isNew); + jobject arg = titanium::TypeConverter::jsValueToJavaObject(isolate, env, args[i+${start}], &isNew); env->SetObjectArrayElement(varArgs, i, arg); if (isNew) { env->DeleteLocalRef(arg); @@ -570,7 +577,8 @@ fails, a JS exception is returned. if (args.Length() < ${requiredCount}) { char errorStringBuffer[100]; sprintf(errorStringBuffer, "${method.apiName}: Invalid number of arguments. Expected ${requiredCount} but got %d", args.Length()); - return ThrowException(Exception::Error(String::New(errorStringBuffer))); + titanium::JSException::Error(isolate, errorStringBuffer); + return; } @@ -586,9 +594,9 @@ fails, a JS exception is returned. <#if method.hasInvocation> - Handle scopeVars = args[0]->ToObject(); - jstring sourceUrl = titanium::TypeConverter::jsValueToJavaString(env, - scopeVars->Get(Proxy::sourceUrlSymbol)); + Local scopeVars = args[0]->ToObject(isolate); + jstring sourceUrl = titanium::TypeConverter::jsValueToJavaString(isolate, env, + scopeVars->Get(Proxy::sourceUrlSymbol.Get(isolate))); jArguments[0].l = env->NewObject(titanium::JNIUtil::krollInvocationClass, titanium::JNIUtil::krollInvocationInitMethod, sourceUrl); env->DeleteLocalRef(sourceUrl); @@ -666,21 +674,22 @@ beprovided to handle the result. <@Proxy.cleanupMethodArguments args=methodArgs hasInvocation=hasInvocation/> if (env->ExceptionCheck()) { - <#if hasResult>Handle jsException = titanium::JSException::fromJavaException(); + <#if hasResult>Local jsException = titanium::JSException::fromJavaException(isolate); env->ExceptionClear(); <#if hasResult> - return jsException; + return; } <#if hasResult && info.javaValidation!false> if (jResult == NULL) { - return Null(); + args.GetReturnValue().Set(Null(isolate)); + return; } <#if hasResult> - Handle<${jsType}> v8Result = titanium::TypeConverter::${info.javaToJsConverter}(env, jResult); + Local<${jsType}> v8Result = titanium::TypeConverter::${info.javaToJsConverter}(isolate, env, jResult); <#if info.javaDeleteLocalRef!false> env->DeleteLocalRef(jResult); @@ -693,7 +702,8 @@ beprovided to handle the result. <#macro initJNIEnv> JNIEnv *env = titanium::JNIScope::getEnv(); if (!env) { - return titanium::JSException::GetJNIEnvironmentError(); + titanium::JSException::GetJNIEnvironmentError(isolate); + return; } @@ -706,7 +716,8 @@ beprovided to handle the result. const char *error = "Couldn't find proxy method '${name}' with signature '${signature}'"; LOGE(TAG, error); <#if !(logOnly!false)> - return titanium::JSException::Error(error); + titanium::JSException::Error(isolate, error); + return; } } diff --git a/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.cpp.fm b/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.cpp.fm index cee59ada11e..a6dbb27ef4d 100644 --- a/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.cpp.fm +++ b/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.cpp.fm @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011-2013 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -42,25 +42,22 @@ using namespace v8; <#assign className = Proxy.className(proxyClassName)> -Persistent ${className}::proxyTemplate = Persistent(); +Persistent ${className}::proxyTemplate; jclass ${className}::javaClass = NULL; ${className}::${className}(jobject javaObject) : titanium::Proxy(javaObject) { } -void ${className}::bindProxy(Handle exports) +void ${className}::bindProxy(Local exports, Local context) { - if (proxyTemplate.IsEmpty()) { - getProxyTemplate(); - } - - // use symbol over string for efficiency - Handle nameSymbol = String::NewSymbol("${proxyAttrs.name}"); + Isolate* isolate = context->GetIsolate(); - Local proxyConstructor = proxyTemplate->GetFunction(); + Local pt = getProxyTemplate(isolate); + Local proxyConstructor = pt->GetFunction(context).ToLocalChecked(); + Local nameSymbol = NEW_SYMBOL(isolate, "${proxyAttrs.name}"); // use symbol over string for efficiency <#if isModule> - Local moduleInstance = proxyConstructor->NewInstance(); + Local moduleInstance = proxyConstructor->NewInstance(context).ToLocalChecked(); exports->Set(nameSymbol, moduleInstance); <#else> exports->Set(nameSymbol, proxyConstructor); @@ -71,8 +68,7 @@ void ${className}::dispose() { LOGD(TAG, "dispose()"); if (!proxyTemplate.IsEmpty()) { - proxyTemplate.Dispose(); - proxyTemplate = Persistent(); + proxyTemplate.Reset(); } <#if superProxyClassName??> @@ -80,46 +76,46 @@ void ${className}::dispose() } -Handle ${className}::getProxyTemplate() +Local ${className}::getProxyTemplate(Isolate* isolate) { if (!proxyTemplate.IsEmpty()) { - return proxyTemplate; + return proxyTemplate.Get(isolate); } LOGD(TAG, "GetProxyTemplate"); <#-- Query the class for the Java proxy --> javaClass = titanium::JNIUtil::findClass("${packageName?replace('.','/')}/${className}"); - HandleScope scope; + EscapableHandleScope scope(isolate); // use symbol over string for efficiency - Handle nameSymbol = String::NewSymbol("${proxyAttrs.name}"); + Local nameSymbol = NEW_SYMBOL(isolate, "${proxyAttrs.name}"); - Handle t = titanium::Proxy::inheritProxyTemplate( + Local t = titanium::Proxy::inheritProxyTemplate(isolate, <#if superProxyClassName??> - <@Proxy.superNamespace/>${superProxyClassName}::getProxyTemplate() + <@Proxy.superNamespace/>${superProxyClassName}::getProxyTemplate(isolate) <#else> - titanium::Proxy::baseProxyTemplate + titanium::Proxy::baseProxyTemplate.Get(isolate) , javaClass, nameSymbol); - proxyTemplate = Persistent::New(t); - proxyTemplate->Set(titanium::Proxy::inheritSymbol, - FunctionTemplate::New(titanium::Proxy::inherit<${className}>)->GetFunction()); + proxyTemplate.Reset(isolate, t); + t->Set(titanium::Proxy::inheritSymbol.Get(isolate), + FunctionTemplate::New(isolate, titanium::Proxy::inherit<${className}>)->GetFunction()); <#if (useTiContext!false)> <#-- this proxy has a TiContext constructor, use the deprecated TiContext for compatibility --> - titanium::ProxyFactory::registerProxyPair(javaClass, *proxyTemplate, true); + titanium::ProxyFactory::registerProxyPair(javaClass, *t, true); <#else> - titanium::ProxyFactory::registerProxyPair(javaClass, *proxyTemplate); + titanium::ProxyFactory::registerProxyPair(javaClass, *t); // Method bindings -------------------------------------------------------- <@Proxy.listMethods ; isFirst, name, method, signature> - DEFINE_PROTOTYPE_METHOD(proxyTemplate, "${method.apiName}", ${className}::${method.apiName}); + titanium::SetProtoMethod(isolate, t, "${method.apiName}", ${className}::${method.apiName}); - Local prototypeTemplate = proxyTemplate->PrototypeTemplate(); - Local instanceTemplate = proxyTemplate->InstanceTemplate(); + Local prototypeTemplate = t->PrototypeTemplate(); + Local instanceTemplate = t->InstanceTemplate(); // Delegate indexed property get and set to the Java proxy. instanceTemplate->SetIndexedPropertyHandler(titanium::Proxy::getIndexedProperty, @@ -137,42 +133,42 @@ Handle ${className}::getProxyTemplate() <#if (constant.value)??> <#if constant.type = "java.lang.String"> - DEFINE_STRING_CONSTANT(prototypeTemplate, "${name}", "${constant.value}"); + DEFINE_STRING_CONSTANT(isolate, prototypeTemplate, "${name}", "${constant.value}"); <#elseif constant.type = "int" || constant.type = "long" || constant.type = "short"> - DEFINE_INT_CONSTANT(prototypeTemplate, "${name}", ${constant.value?c}); + DEFINE_INT_CONSTANT(isolate, prototypeTemplate, "${name}", ${constant.value?c}); <#else> - DEFINE_NUMBER_CONSTANT(prototypeTemplate, "${name}", ${constant.value?c}); + DEFINE_NUMBER_CONSTANT(isolate, prototypeTemplate, "${name}", ${constant.value?c}); <#else> <#if constant.type = "java.lang.String"> - jfieldID field${constant.name} = env->GetStaticFieldID (javaClass, "${constant.name}", "Ljava/lang/String;"); + jfieldID field${constant.name} = env->GetStaticFieldID(javaClass, "${constant.name}", "Ljava/lang/String;"); jobject fieldValue${constant.name} = env->GetStaticObjectField(javaClass, field${constant.name}); - DEFINE_STRING_CONSTANT(prototypeTemplate, "${name}", fieldValue${constant.name}); + DEFINE_STRING_CONSTANT(isolate, prototypeTemplate, "${name}", fieldValue${constant.name}); <#elseif constant.type = "short"> - jfieldID field${constant.name} = env->GetStaticFieldID (javaClass, "${constant.name}", "S"); + jfieldID field${constant.name} = env->GetStaticFieldID(javaClass, "${constant.name}", "S"); jshort fieldValue${constant.name} = env->GetStaticShortField(javaClass, field${constant.name}); - DEFINE_INT_CONSTANT(prototypeTemplate, "${name}", fieldValue${constant.name}); + DEFINE_INT_CONSTANT(isolate, prototypeTemplate, "${name}", fieldValue${constant.name}); <#elseif constant.type = "int"> - jfieldID field${constant.name} = env->GetStaticFieldID (javaClass, "${constant.name}", "I"); + jfieldID field${constant.name} = env->GetStaticFieldID(javaClass, "${constant.name}", "I"); jint fieldValue${constant.name} = env->GetStaticIntField(javaClass, field${constant.name}); - DEFINE_NUMBER_CONSTANT(prototypeTemplate, "${name}", fieldValue${constant.name}); + DEFINE_NUMBER_CONSTANT(isolate, prototypeTemplate, "${name}", fieldValue${constant.name}); <#elseif constant.type = "long"> - jfieldID field${constant.name} = env->GetStaticFieldID (javaClass, "${constant.name}", "J"); + jfieldID field${constant.name} = env->GetStaticFieldID(javaClass, "${constant.name}", "J"); jlong fieldValue${constant.name} = env->GetStaticLongField(javaClass, field${constant.name}); - DEFINE_NUMBER_CONSTANT(prototypeTemplate, "${name}", fieldValue${constant.name}); + DEFINE_NUMBER_CONSTANT(isolate, prototypeTemplate, "${name}", fieldValue${constant.name}); <#elseif constant.type = "float"> - jfieldID field${constant.name} = env->GetStaticFieldID (javaClass, "${constant.name}", "F"); + jfieldID field${constant.name} = env->GetStaticFieldID(javaClass, "${constant.name}", "F"); jfloat fieldValue${constant.name} = env->GetStaticFloatField(javaClass, field${constant.name}); - DEFINE_NUMBER_CONSTANT(prototypeTemplate, "${name}", fieldValue${constant.name}); + DEFINE_NUMBER_CONSTANT(isolate, prototypeTemplate, "${name}", fieldValue${constant.name}); <#elseif constant.type = "double"> - jfieldID field${constant.name} = env->GetStaticFieldID (javaClass, "${constant.name}", "D"); + jfieldID field${constant.name} = env->GetStaticFieldID(javaClass, "${constant.name}", "D"); jdouble fieldValue${constant.name} = env->GetStaticDoubleField(javaClass, field${constant.name}); - DEFINE_NUMBER_CONSTANT(prototypeTemplate, "${name}", fieldValue${constant.name}); + DEFINE_NUMBER_CONSTANT(isolate, prototypeTemplate, "${name}", fieldValue${constant.name}); @@ -181,52 +177,60 @@ Handle ${className}::getProxyTemplate() // Dynamic properties ----------------------------------------------------- <@Proxy.listDynamicProperties ; isFirst, name, property, getSignature, setSignature> - instanceTemplate->SetAccessor(String::NewSymbol("${name}"), + instanceTemplate->SetAccessor(NEW_SYMBOL(isolate, "${name}"), <#if property.get> - ${className}::getter_${name} + ${className}::getter_${name}, <#else> - titanium::Proxy::getProperty + titanium::Proxy::getProperty, <#if property.set> - , ${className}::setter_${name} + ${className}::setter_${name}, <#else> - , titanium::Proxy::onPropertyChanged - , Handle(), DEFAULT + titanium::Proxy::onPropertyChanged, + + Local(), DEFAULT, <#if property.set> - , static_cast(v8::DontDelete) + static_cast(v8::DontDelete) <#else> - , static_cast(v8::ReadOnly | v8::DontDelete) - ); + static_cast(v8::ReadOnly | v8::DontDelete) + + ); // Accessors -------------------------------------------------------------- <@Proxy.listPropertyAccessors ; isFirst, name, getter, setter> instanceTemplate->SetAccessor( - String::NewSymbol("${name}"), + NEW_SYMBOL(isolate, "${name}"), titanium::Proxy::getProperty, - titanium::Proxy::onPropertyChanged, - Handle(), DEFAULT); - DEFINE_PROTOTYPE_METHOD_DATA(proxyTemplate, "${getter}", titanium::Proxy::getProperty, String::NewSymbol("${name}")); - DEFINE_PROTOTYPE_METHOD_DATA(proxyTemplate, "${setter}", titanium::Proxy::onPropertyChanged, String::NewSymbol("${name}")); + titanium::Proxy::onPropertyChanged); + DEFINE_PROTOTYPE_METHOD_DATA(isolate, t, "${getter}", titanium::Proxy::getProperty, NEW_SYMBOL(isolate, "${name}")); + DEFINE_PROTOTYPE_METHOD_DATA(isolate, t, "${setter}", titanium::Proxy::onPropertyChanged, NEW_SYMBOL(isolate, "${name}")); <#if interceptor??> instanceTemplate->SetNamedPropertyHandler(${className}::interceptor); - return proxyTemplate; + return scope.Escape(t); } // Methods -------------------------------------------------------------------- <@Proxy.listMethods ; isFirst, name, method, signature> -Handle ${className}::${method.apiName}(const Arguments& args) +void ${className}::${method.apiName}(const FunctionCallbackInfo& args) { LOGD(TAG, "${method.apiName}()"); - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); <@Proxy.initJNIEnv/> <@Proxy.initMethodID className=className name=name signature=signature logOnly=false/> - titanium::Proxy* proxy = titanium::Proxy::unwrap(args.Holder()); + Local holder = args.Holder(); + // If holder isn't the JavaObject wrapper we expect, look up the prototype chain + if (!JavaObject::isJavaObject(holder)) { + holder = holder->FindInstanceInPrototypeChain(getProxyTemplate(isolate)); + } + + titanium::Proxy* proxy = titanium::Proxy::unwrap(holder); <#if method.args?size > 0> <@Proxy.verifyAndConvertArguments method.args method /> @@ -239,9 +243,9 @@ Handle ${className}::${method.apiName}(const Arguments& args) "methodID", "javaProxy", "jArguments", (method.returnType != "void") ; hasResult, resultVar> <#if hasResult> - return ${resultVar}; + args.GetReturnValue().Set(${resultVar}); <#else> - return v8::Undefined(); + args.GetReturnValue().Set(v8::Undefined(isolate)); @@ -252,18 +256,19 @@ Handle ${className}::${method.apiName}(const Arguments& args) <@Proxy.listDynamicProperties ; isFirst, name, property, getSignature, setSignature> <#if property.get> -Handle ${className}::getter_${name}(Local property, const AccessorInfo& info) +void ${className}::getter_${name}(Local property, const PropertyCallbackInfo& args) { - LOGD(TAG, "get ${name}"); - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); <@Proxy.initJNIEnv/> <@Proxy.initMethodID className=className name=property.getMethodName signature=getSignature logOnly=false/> - titanium::Proxy* proxy = titanium::Proxy::unwrap(info.Holder()); + titanium::Proxy* proxy = titanium::Proxy::unwrap(args.Holder()); if (!proxy) { - return Undefined(); + args.GetReturnValue().Set(Undefined(isolate)); + return; } jvalue* jArguments = 0; @@ -272,17 +277,17 @@ Handle ${className}::getter_${name}(Local property, const Accesso <@Proxy.callJNIMethod property.getMethodArgs, property.getHasInvocation, property.getReturnType, "methodID", "javaProxy", "jArguments", (property.getReturnType != "void") ; hasResult, resultVar> - return ${resultVar}; + args.GetReturnValue().Set(${resultVar}); } <#if property.set> -void ${className}::setter_${name}(Local property, Local value, const AccessorInfo& info) +void ${className}::setter_${name}(Local property, Local value, const PropertyCallbackInfo& args) { - LOGD(TAG, "set ${name}"); - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); JNIEnv *env = titanium::JNIScope::getEnv(); if (!env) { @@ -292,7 +297,7 @@ void ${className}::setter_${name}(Local property, Local value, co <@Proxy.initMethodID className=className name=property.setMethodName signature=setSignature logOnly=true /> - titanium::Proxy* proxy = titanium::Proxy::unwrap(info.Holder()); + titanium::Proxy* proxy = titanium::Proxy::unwrap(args.Holder()); if (!proxy) { return; } @@ -312,7 +317,7 @@ void ${className}::setter_${name}(Local property, Local value, co Otherwise you can never read back the value that was last set. --> <#if property.get == false> - Proxy::setProperty(property, value, info); + Proxy::setProperty(property, value, args); } @@ -320,17 +325,19 @@ void ${className}::setter_${name}(Local property, Local value, co <#if interceptor??> -Handle ${className}::interceptor(Local property, const AccessorInfo& info) +void ${className}::interceptor(Local property, const v8::PropertyCallbackInfo& args) { - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); <@Proxy.initJNIEnv/> <@Proxy.initMethodID className=className name=interceptor.name signature="(Ljava/lang/String;)Ljava/lang/Object;" logOnly=false/> - titanium::Proxy* proxy = titanium::Proxy::unwrap(info.Holder()); + titanium::Proxy* proxy = titanium::Proxy::unwrap(args.Holder()); if (!proxy) { - return Undefined(); + args.GetReturnValue().Set(Undefined(isolate)); + return; } jobject javaProxy = proxy->getJavaObject(); @@ -343,28 +350,30 @@ Handle ${className}::interceptor(Local property, const AccessorIn env->DeleteLocalRef(javaProperty); if (env->ExceptionCheck()) { - Handle jsException = titanium::JSException::fromJavaException(); + Local jsException = titanium::JSException::fromJavaException(isolate); env->ExceptionClear(); - return jsException; + args.GetReturnValue().Set(jsException); + return; } if (jResult == NULL) { - return Null(); + args.GetReturnValue().Set(Null(isolate)); + return; } - Handle v8Result = titanium::TypeConverter::javaObjectToJsValue(env, jResult); + Local v8Result = titanium::TypeConverter::javaObjectToJsValue(isolate, env, jResult); env->DeleteLocalRef(jResult); if (v8Result->IsNumber()) { int32_t intResult = v8Result->Int32Value(); if (intResult == titanium::JNIUtil::krollRuntimeDontIntercept) { - return Handle(); + args.GetReturnValue().Set(Local()); + return; } } - return v8Result; - + args.GetReturnValue().Set(v8Result); } diff --git a/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.h.fm b/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.h.fm index ee11474fa0f..705bbd50151 100644 --- a/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.h.fm +++ b/android/kroll-apt/src/java/org/appcelerator/kroll/annotations/generator/ProxyBindingV8.h.fm @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011-2013 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -15,37 +15,37 @@ <@Proxy.openNamespace/> <#assign className = Proxy.className(proxyClassName)> - class ${className} : public titanium::Proxy { public: explicit ${className}(jobject javaObject); - static void bindProxy(v8::Handle exports); - static v8::Handle getProxyTemplate(); + static void bindProxy(v8::Local, v8::Local); + static v8::Local getProxyTemplate(v8::Isolate*); static void dispose(); - static v8::Persistent proxyTemplate; static jclass javaClass; private: + static v8::Persistent proxyTemplate; + // Methods ----------------------------------------------------------- <@Proxy.listMethods ; isFirst, name, method> - static v8::Handle ${method.apiName}(const v8::Arguments&); + static void ${method.apiName}(const v8::FunctionCallbackInfo&); // Dynamic property accessors ---------------------------------------- <@Proxy.listDynamicProperties ; isFirst, name, property, getSignature, setSignature> <#if property.get> - static v8::Handle getter_${name}(v8::Local property, const v8::AccessorInfo& info); + static void getter_${name}(v8::Local name, const v8::PropertyCallbackInfo& info); <#if property.set> - static void setter_${name}(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static void setter_${name}(v8::Local name, v8::Local value, const v8::PropertyCallbackInfo& info); <#if interceptor??> - static v8::Handle interceptor(v8::Local property, const v8::AccessorInfo& info); + static void interceptor(v8::Local property, const v8::PropertyCallbackInfo& info); }; diff --git a/android/notes.md b/android/notes.md new file mode 100644 index 00000000000..74af1de7729 --- /dev/null +++ b/android/notes.md @@ -0,0 +1,18 @@ +Done: +====== +- Fix To* calls wrongly converted to As() calls + - As can replace Cast, or when we check IsSomething() first, since it casts + - ToSomething() coerces the type +- Replace Cast usage with as()? +- http://stackoverflow.com/questions/15017113/cast-vs-toxxx-for-value-handles-in-v8 + +TODOs!!! +===== +- Clean up all the debug logging I put in place +- Write up notes on generating debug build of library, using ndk-stack to get line numbers in native crash stack traces + - ./adb logcat | /Users/cwilliams/Developer/SDKs/android-ndk-r10c/ndk-stack -sym /Users/cwilliams/repos/titanium_mobile/android/runtime/v8/obj/local/x86 +- Use ToSomething(Context) in place of ToSomething(Isolate) +- Convert to using all of the MaybeLocal APIs +- Look for other deprecated API usage and update +- Write up some docs on how everything works? +- Clean up JavaObject/Proxy/NativeObject hierarchy, duplicated work. Basically JavaObject just needs a special callback that doesn't immediately clean up. We have all these wrap/unwrap methods diff --git a/android/runtime/v8/Application.mk b/android/runtime/v8/Application.mk index fceafb77ea0..231ace73f30 100644 --- a/android/runtime/v8/Application.mk +++ b/android/runtime/v8/Application.mk @@ -1,6 +1,6 @@ # # Appcelerator Titanium Mobile -# Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. +# Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. # Licensed under the terms of the Apache Public License # Please see the LICENSE included with this distribution for details. # @@ -8,11 +8,12 @@ APP_BUILD_SCRIPT = src/native/Android.mk TARGET_PLATFORM = android-10 -APP_STL := stlport_shared +APP_CPPFLAGS += -std=c++11 +APP_STL := c++_shared ifeq ($(BUILD_X86), 1) - APP_ABI := armeabi armeabi-v7a x86 + APP_ABI := armeabi-v7a x86 else - APP_ABI := armeabi armeabi-v7a + APP_ABI := armeabi-v7a endif diff --git a/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/ReferenceTable.java b/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/ReferenceTable.java index c8de4031693..b8f10632d35 100644 --- a/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/ReferenceTable.java +++ b/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/ReferenceTable.java @@ -49,11 +49,8 @@ public static void makeWeakReference(int key) */ public static Object clearWeakReference(int key) { - Object ref = references.get(key); - if (ref instanceof WeakReference) { - ref = ((WeakReference)ref).get(); - references.put(key, ref); - } + Object ref = getReference(key); + references.put(key, ref); return ref; } diff --git a/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/V8Runtime.java b/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/V8Runtime.java index 35837220369..0d9ee77ed7b 100644 --- a/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/V8Runtime.java +++ b/android/runtime/v8/src/java/org/appcelerator/kroll/runtime/v8/V8Runtime.java @@ -56,7 +56,7 @@ public void initRuntime() } if (!libLoaded) { - System.loadLibrary("stlport_shared"); + System.loadLibrary("c++_shared"); System.loadLibrary("kroll-v8"); // TIMOB-16810 Add a delay to allow symbols to load before calling nativeInit (For HTC One Devices) @@ -245,4 +245,3 @@ public void setGCFlag() private native void nativeDispose(); private native void nativeAddExternalCommonJsModule(String moduleName, KrollSourceCodeProvider sourceProvider); } - diff --git a/android/runtime/v8/src/native/Android.mk b/android/runtime/v8/src/native/Android.mk index 3cd347b8297..1f68f7c4b45 100644 --- a/android/runtime/v8/src/native/Android.mk +++ b/android/runtime/v8/src/native/Android.mk @@ -4,7 +4,7 @@ # Licensed under the terms of the Apache Public License # Please see the LICENSE included with this distribution for details. # -# +# # Top level kroll-v8 runtime Makefile LOCAL_PATH := $(call my-dir) @@ -25,7 +25,7 @@ LOCAL_SRC_FILES := $(SRC_FILES) LOCAL_JS_FILES := $(JS_FILES) -LOCAL_STATIC_LIBRARIES := libv8 +LOCAL_STATIC_LIBRARIES := libv8_base libv8_libbase libv8_libplatform libv8_nosnapshot libicui18n libicuuc libicudata include $(BUILD_SHARED_LIBRARY) diff --git a/android/runtime/v8/src/native/EventEmitter.cpp b/android/runtime/v8/src/native/EventEmitter.cpp index 72cdd4d1e48..eb21dc75fe0 100644 --- a/android/runtime/v8/src/native/EventEmitter.cpp +++ b/android/runtime/v8/src/native/EventEmitter.cpp @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2015 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. * @@ -27,67 +27,65 @@ Persistent EventEmitter::constructorTemplate; static Persistent eventsSymbol; Persistent EventEmitter::emitSymbol; -Handle EventEmitter::eventEmitterConstructor(const Arguments& args) +void EventEmitter::eventEmitterConstructor(const FunctionCallbackInfo& args) { - HandleScope scope; - + HandleScope scope(args.GetIsolate()); EventEmitter *emitter = new EventEmitter(); emitter->Wrap(args.This()); - - return args.This(); } -void EventEmitter::initTemplate() +void EventEmitter::initTemplate(Local context) { - HandleScope scope; - constructorTemplate = Persistent::New(FunctionTemplate::New(eventEmitterConstructor)); - constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1); - constructorTemplate->SetClassName(String::NewSymbol("EventEmitter")); - - eventsSymbol = SYMBOL_LITERAL("_events"); - emitSymbol = SYMBOL_LITERAL("emit"); + Isolate* isolate = context->GetIsolate(); + HandleScope scope(isolate); + Local constructor = FunctionTemplate::New(isolate, eventEmitterConstructor); + constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->SetClassName(NEW_SYMBOL(isolate, "EventEmitter")); + constructorTemplate.Reset(isolate, constructor); + + eventsSymbol.Reset(isolate, NEW_SYMBOL(isolate, "_events")); + emitSymbol.Reset(isolate, NEW_SYMBOL(isolate, "emit")); } void EventEmitter::dispose() { - constructorTemplate.Dispose(); - constructorTemplate = Persistent(); - - eventsSymbol.Dispose(); - eventsSymbol = Persistent(); - - emitSymbol.Dispose(); - emitSymbol = Persistent(); + constructorTemplate.Reset(); + eventsSymbol.Reset(); + emitSymbol.Reset(); } -bool EventEmitter::emit(Handle event, int argc, Handle *argv) +bool EventEmitter::emit(Local event, int argc, Local *argv) { - HandleScope scope; - Handle events_v = handle_->Get(eventsSymbol); + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + + Local self = handle(); + + Local events_v = self->Get(eventsSymbol.Get(isolate)); if (!events_v->IsObject()) return false; - Handle events = events_v->ToObject(); + Local events = events_v.As(); - Handle listeners_v = events->Get(event); + Local listeners_v = events->Get(event); TryCatch try_catch; if (listeners_v->IsFunction()) { // Optimized one-listener case - Handle listener = Handle::Cast(listeners_v); - listener->Call(handle_, argc, argv); + Local listener = listeners_v.As(); + listener->Call(isolate->GetCurrentContext(), self, argc, argv); if (try_catch.HasCaught()) { - V8Util::fatalException(try_catch); + V8Util::fatalException(isolate, try_catch); return false; } } else if (listeners_v->IsArray()) { - Handle listeners = Handle::Cast(listeners_v->ToObject()->Clone()); + Local listeners = listeners_v.As()->Clone().As(); for (uint32_t i = 0; i < listeners->Length(); ++i) { - Handle listener_v = listeners->Get(i); + Local listener_v = listeners->Get(i); if (!listener_v->IsFunction()) continue; - Handle listener = Handle::Cast(listener_v); - listener->Call(handle_, argc, argv); + Local listener = listener_v.As(); + listener->Call(isolate->GetCurrentContext(), self, argc, argv); if (try_catch.HasCaught()) { - V8Util::fatalException(try_catch); + V8Util::fatalException(isolate, try_catch); return false; } } @@ -99,4 +97,3 @@ bool EventEmitter::emit(Handle event, int argc, Handle *argv) } } // namespace titanium - diff --git a/android/runtime/v8/src/native/EventEmitter.h b/android/runtime/v8/src/native/EventEmitter.h index aded70fd5e1..7394f6dc9e7 100644 --- a/android/runtime/v8/src/native/EventEmitter.h +++ b/android/runtime/v8/src/native/EventEmitter.h @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2015 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. * @@ -16,6 +16,14 @@ namespace titanium { +using v8::Persistent; +using v8::Local; +using v8::Context; +using v8::Value; +using v8::String; +using v8::FunctionTemplate; +using v8::FunctionCallbackInfo; + // The base class for any object that emits events. // Provides an interface for listening to and firing events. // See events.js in the common runtime which implements most @@ -23,15 +31,15 @@ namespace titanium { class EventEmitter : public NativeObject { public: - static v8::Persistent emitSymbol; + static Persistent emitSymbol; - static v8::Handle eventEmitterConstructor(const v8::Arguments& args); - static void initTemplate(); + static void eventEmitterConstructor(const FunctionCallbackInfo& args); + static void initTemplate(Local context); static void dispose(); - static v8::Persistent constructorTemplate; + static Persistent constructorTemplate; - bool emit(v8::Handle event, int argc, v8::Handle *argv); + bool emit(Local event, int argc, Local *argv); protected: EventEmitter() diff --git a/android/runtime/v8/src/native/JSException.cpp b/android/runtime/v8/src/native/JSException.cpp index e48cd618846..b95e01fb03f 100644 --- a/android/runtime/v8/src/native/JSException.cpp +++ b/android/runtime/v8/src/native/JSException.cpp @@ -16,11 +16,11 @@ using namespace v8; namespace titanium { -Handle JSException::fromJavaException(jthrowable javaException) +Local JSException::fromJavaException(v8::Isolate* isolate, jthrowable javaException) { JNIEnv *env = JNIScope::getEnv(); if (!env) { - return GetJNIEnvironmentError(); + return GetJNIEnvironmentError(isolate); } env->ExceptionDescribe(); @@ -36,17 +36,17 @@ Handle JSException::fromJavaException(jthrowable javaException) jstring message = (jstring) env->CallObjectMethod(javaException, JNIUtil::throwableGetMessageMethod); if (!message) { - return THROW("Java Exception occurred"); + return THROW(isolate, "Java Exception occurred"); } - Handle jsMessage = TypeConverter::javaStringToJsString(env, message); + Local jsMessage = TypeConverter::javaStringToJsString(isolate, env, message); env->DeleteLocalRef(message); if (deleteRef) { env->DeleteLocalRef(javaException); } - return ThrowException(Exception::Error(jsMessage->ToString())); + return isolate->ThrowException(jsMessage->ToString(isolate)); } } diff --git a/android/runtime/v8/src/native/JSException.h b/android/runtime/v8/src/native/JSException.h index d04e91dff95..8cf01ece8e6 100644 --- a/android/runtime/v8/src/native/JSException.h +++ b/android/runtime/v8/src/native/JSException.h @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -11,32 +11,32 @@ #include #include -#define THROW(msg) \ - v8::ThrowException(v8::Exception::Error(v8::String::New(msg))) +#define THROW(isolate, msg) \ + isolate->ThrowException(v8::String::NewFromUtf8(isolate, msg)) namespace titanium { class JSException { public: - static v8::Handle Error(const char* msg) + static v8::Local Error(v8::Isolate* isolate, const char* msg) { - return THROW(msg); + return THROW(isolate, msg); } // Calling a constructor as a function not allowed. - static v8::Handle CalledConstructor() + static v8::Local CalledConstructor(v8::Isolate* isolate) { - return THROW("Calling this constructor is not allowed."); + return THROW(isolate, "Calling this constructor is not allowed."); } // An attempt to get the current JNI environment failed. - static v8::Handle GetJNIEnvironmentError() + static v8::Local GetJNIEnvironmentError(v8::Isolate* isolate) { - return THROW(JNIENV_GET_ERROR_MSG); + return THROW(isolate, JNIENV_GET_ERROR_MSG); } - static v8::Handle fromJavaException(jthrowable javaException = NULL); + static v8::Local fromJavaException(v8::Isolate* isolate, jthrowable javaException = NULL); }; } diff --git a/android/runtime/v8/src/native/JavaObject.cpp b/android/runtime/v8/src/native/JavaObject.cpp index e10d80bc5bf..f30659c6b7a 100644 --- a/android/runtime/v8/src/native/JavaObject.cpp +++ b/android/runtime/v8/src/native/JavaObject.cpp @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -40,9 +40,9 @@ static struct { // Callback for V8 letting us know the JavaScript object is no longer reachable. // Once we receive this callback we can safely release our strong reference // on the wrapped Java object so it can become eligible for collection. -static void DetachCallback(v8::Persistent value, void *data) +static void DetachCallback(const v8::WeakCallbackData& data) { - JavaObject *javaObject = static_cast(data); + JavaObject* javaObject = data.GetParameter(); javaObject->detach(); } @@ -75,9 +75,9 @@ void JavaObject::newGlobalRef() } javaObject_ = globalRef; } else { - ASSERT(refTableKey_ == 0); - refTableKey_ = ReferenceTable::createReference(javaObject_); - javaObject_ = NULL; + ASSERT(refTableKey_ == 0); // make sure we haven't already stored something + refTableKey_ = ReferenceTable::createReference(javaObject_); // make strong ref on Java side + javaObject_ = NULL; // toss out the java object copy here, it's in ReferenceTable's HashMap } } @@ -99,14 +99,23 @@ jobject JavaObject::getJavaObject() return javaObject_; } else { - if (isWeakRef_) { - UPDATE_STATS(0, -1); + if (isWeakRef_) { // Did JS side try to collect our object already? + // OH SNAP, DON'T KILL OUR OBJECT YET JVM! + // make reference strong again on Java side if we can... jobject javaObject = ReferenceTable::clearWeakReference(refTableKey_); + UPDATE_STATS(0, -1); if (javaObject == NULL) { + // SHIT! Java collected it. ummmm, not much we can do here. + // Maybe we can... Nope. It's gone. Live with it. LOGE(TAG, "Java object reference has been invalidated."); } - isWeakRef_ = false; - handle_.MakeWeak(this, DetachCallback); + + isWeakRef_ = false; // not weak on Java side anymore + + // tell V8 to let us know when it thinks the JS object can be collected again + persistent().SetWeak(this, DetachCallback); + persistent().MarkIndependent(); + return javaObject; } return ReferenceTable::getReference(refTableKey_); @@ -128,10 +137,12 @@ void JavaObject::weakGlobalRef() env->DeleteGlobalRef(javaObject_); javaObject_ = weakRef; } else { + // Make our strong reference weak on Java side + // Dead man walking ReferenceTable::makeWeakReference(refTableKey_); } - isWeakRef_ = true; + isWeakRef_ = true; // remember that our ref on Java side is weak } // Deletes the reference to the wrapped Java object. @@ -151,8 +162,8 @@ void JavaObject::deleteGlobalRef() } javaObject_ = NULL; } else { - ReferenceTable::destroyReference(refTableKey_); - refTableKey_ = 0; + ReferenceTable::destroyReference(refTableKey_); // Kill the Java side + refTableKey_ = 0; // throw away the key } } @@ -163,14 +174,20 @@ JavaObject::~JavaObject() if (javaObject_ || refTableKey_ > 0) { deleteGlobalRef(); } + + if (persistent().IsEmpty()) + return; + assert(persistent().IsNearDeath()); + persistent().ClearWeak(); + persistent().Reset(); } -void JavaObject::wrap(Handle jsObject) +void JavaObject::wrap(Isolate* isolate, Local jsObject) { - ASSERT(handle_.IsEmpty()); + ASSERT(persistent().IsEmpty()); ASSERT(jsObject->InternalFieldCount() > 0); - handle_ = v8::Persistent::New(jsObject); - handle_->SetPointerInInternalField(0, this); + jsObject->SetAlignedPointerInInternalField(0, this); + persistent().Reset(isolate, jsObject); } // Attaches the Java object to this native wrapper. @@ -182,25 +199,30 @@ void JavaObject::attach(jobject javaObject) ASSERT((javaObject && javaObject_ == NULL) || javaObject == NULL); UPDATE_STATS(0, -1); - handle_.MakeWeak(this, DetachCallback); - handle_.MarkIndependent(); - if (javaObject) { javaObject_ = javaObject; } + // make strong ref to Java object in JVM newGlobalRef(); + + // So let's mark this JS object as independent and weak so V8 can tell us + // when the JS object is ready to be GCed, which is first step in it's death + persistent().SetWeak(this, DetachCallback); + persistent().MarkIndependent(); } void JavaObject::detach() { - handle_.MakeWeak(this, DetachCallback); + // WAIT A SECOND V8!!! DON'T KILL MY OBJECT YET! THE JVM MAY STILL WANT IT! + persistent().ClearWeak(); if (isDetached()) { return; } + // V8 says we don't need the object on the JS side + // Let's make the object weak in the JVM now... UPDATE_STATS(0, 1); - weakGlobalRef(); } @@ -210,4 +232,3 @@ bool JavaObject::isDetached() } } - diff --git a/android/runtime/v8/src/native/JavaObject.h b/android/runtime/v8/src/native/JavaObject.h index 4e055680348..afe01e5b330 100644 --- a/android/runtime/v8/src/native/JavaObject.h +++ b/android/runtime/v8/src/native/JavaObject.h @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -13,6 +13,11 @@ #include "EventEmitter.h" #include "NativeObject.h" +// FIXME This and NativeObject duplicate a lot of functionality! +// We should be using NativeObject to Wrap/Unwrap +// but we need some of the Java specifics this provides with managing the +// reference table - moving java objects to weak or strong - and reviving +// them when getJavaObject is called, or destroying when destructor is called! namespace titanium { // Provides an interface between a JavaScript object @@ -30,18 +35,15 @@ class JavaObject : public EventEmitter // Delete this object once the Java object has been finalized. virtual ~JavaObject(); - // Test if the JavaScript object wraps a Java object. - static bool isJavaObject(v8::Handle jsObject) + // Test if the JavaScript object wraps a Java object. + static bool isJavaObject(v8::Local jsObject) { - if (jsObject->InternalFieldCount() > 0) { - return true; - } - return false; + return jsObject->InternalFieldCount() > 0; } // Wrap the given JavaScript object which provides // bindings to this Java object. - void wrap(v8::Handle jsObject); + void wrap(v8::Isolate* isolate, v8::Local jsObject); // Attach to the given Java object. A reference // to this object will be held until it is detached. diff --git a/android/runtime/v8/src/native/KrollBindings.cpp b/android/runtime/v8/src/native/KrollBindings.cpp index a0663a5fefa..e601393ad9d 100644 --- a/android/runtime/v8/src/native/KrollBindings.cpp +++ b/android/runtime/v8/src/native/KrollBindings.cpp @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011-2012 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -43,38 +43,41 @@ std::map KrollBindings::commonJsSourceRetrievalMethods; std::vector KrollBindings::externalLookups; std::map KrollBindings::externalLookupBindings; -void KrollBindings::initFunctions(Handle exports) +void KrollBindings::initFunctions(Local exports, Local context) { - DEFINE_METHOD(exports, "binding", KrollBindings::getBinding); - DEFINE_METHOD(exports, "externalBinding", KrollBindings::getExternalBinding); - DEFINE_METHOD(exports, "isExternalCommonJsModule", KrollBindings::isExternalCommonJsModule); - DEFINE_METHOD(exports, "getExternalCommonJsModule", KrollBindings::getExternalCommonJsModule); + Isolate* isolate = context->GetIsolate(); + SetMethod(isolate, exports, "binding", KrollBindings::getBinding); + SetMethod(isolate, exports, "externalBinding", KrollBindings::getExternalBinding); + SetMethod(isolate, exports, "isExternalCommonJsModule", KrollBindings::isExternalCommonJsModule); + SetMethod(isolate, exports, "getExternalCommonJsModule", KrollBindings::getExternalCommonJsModule); } -void KrollBindings::initNatives(Handle exports) +void KrollBindings::initNatives(Local exports, Local context) { - HandleScope scope; + Isolate* isolate = context->GetIsolate(); + HandleScope scope(isolate); for (int i = 0; natives[i].name; ++i) { if (natives[i].source == kroll_native) continue; - Local name = String::New(natives[i].name); - Handle source = IMMUTABLE_STRING_LITERAL_FROM_ARRAY(natives[i].source, natives[i].source_length); + Local name = String::NewFromUtf8(isolate, natives[i].name); + Local source = IMMUTABLE_STRING_LITERAL_FROM_ARRAY(isolate, natives[i].source, natives[i].source_length); exports->Set(name, source); } } -void KrollBindings::initTitanium(Handle exports) +void KrollBindings::initTitanium(Local exports, Local context) { - HandleScope scope; + Isolate* isolate = context->GetIsolate(); + HandleScope scope(isolate); JNIEnv *env = JNIScope::getEnv(); if (!env) { LOGE(TAG, "Couldn't initialize JNIEnv"); return; } - Proxy::bindProxy(exports); - KrollProxy::bindProxy(exports); - KrollModule::bindProxy(exports); - TitaniumModule::bindProxy(exports); + Proxy::bindProxy(exports, context); + KrollProxy::bindProxy(exports, context); + KrollModule::bindProxy(exports, context); + TitaniumModule::bindProxy(exports, context); } void KrollBindings::disposeTitanium() @@ -87,50 +90,50 @@ void KrollBindings::disposeTitanium() static Persistent bindingCache; -Handle KrollBindings::getBinding(const Arguments& args) +void KrollBindings::getBinding(const FunctionCallbackInfo& args) { - HandleScope scope; + Isolate* isolate = args.GetIsolate(); - if (args.Length() == 0 || !args[0]->IsString()) { - return JSException::Error("Invalid arguments to binding, expected String"); + if (args.Length() == 0 || !(args[0]->IsString())) { + JSException::Error(isolate, "Invalid arguments to binding, expected String"); + return; } - Handle binding = getBinding(args[0]->ToString()); + Local binding = getBinding(isolate, args[0].As()); if (binding.IsEmpty()) { - return Undefined(); + return; } - return scope.Close(binding); + args.GetReturnValue().Set(binding); } -Handle KrollBindings::getExternalBinding(const Arguments& args) +void KrollBindings::getExternalBinding(const FunctionCallbackInfo& args) { - HandleScope scope; - - if (args.Length() == 0 || !args[0]->IsString()) { - return JSException::Error("Invalid arguments to externalBinding, expected String"); + Isolate* isolate = args.GetIsolate(); + if (args.Length() == 0 || !(args[0]->IsString())) { + JSException::Error(args.GetIsolate(), "Invalid arguments to externalBinding, expected String"); + return; } - Handle binding = args[0]->ToString(); - - if (bindingCache->Has(binding)) { - return bindingCache->Get(binding)->ToObject(); + Local binding = args[0].As(); + Local cache = bindingCache.Get(isolate); + if (cache->Has(binding)) { + args.GetReturnValue().Set(cache->Get(binding)->ToObject(isolate)); + return; } - String::AsciiValue bindingValue(binding); + titanium::Utf8Value bindingValue(binding); std::string key(*bindingValue); struct bindings::BindEntry *externalBinding = externalBindings[key]; if (externalBinding) { - Local exports = Object::New(); - externalBinding->bind(exports); - bindingCache->Set(binding, exports); - - return scope.Close(exports); + Local exports = Object::New(isolate); + Local context = isolate->GetCurrentContext(); + externalBinding->bind(exports, context); + cache->Set(binding, exports); + args.GetReturnValue().Set(exports); } - - return Undefined(); } void KrollBindings::addExternalBinding(const char *name, struct bindings::BindEntry *binding) @@ -143,34 +146,37 @@ void KrollBindings::addExternalLookup(LookupFunction lookup) externalLookups.push_back(lookup); } -Handle KrollBindings::getBinding(Handle binding) +Local KrollBindings::getBinding(v8::Isolate* isolate, Local binding) { + Local cache; if (bindingCache.IsEmpty()) { - bindingCache = Persistent::New(Object::New()); + cache = Object::New(isolate); + bindingCache.Reset(isolate, cache); + } else { + cache = bindingCache.Get(isolate); } - String::Utf8Value bindingValue(binding); - - if (bindingCache->Has(binding)) { - return bindingCache->Get(binding)->ToObject(); + if (cache->Has(binding)) { + return cache->Get(binding)->ToObject(isolate); } + titanium::Utf8Value bindingValue(binding); int length = bindingValue.length(); - + // TODO Combine all this duplicated code here... struct bindings::BindEntry *native = bindings::native::lookupBindingInit(*bindingValue, length); if (native) { - Local exports = Object::New(); - native->bind(exports); - bindingCache->Set(binding, exports); + Local exports = Object::New(isolate); + native->bind(exports, isolate->GetCurrentContext()); + cache->Set(binding, exports); return exports; } struct bindings::BindEntry* generated = bindings::generated::lookupGeneratedInit(*bindingValue, length); if (generated) { - Local exports = Object::New(); - generated->bind(exports); - bindingCache->Set(binding, exports); + Local exports = Object::New(isolate); + generated->bind(exports, isolate->GetCurrentContext()); + cache->Set(binding, exports); return exports; } @@ -180,25 +186,23 @@ Handle KrollBindings::getBinding(Handle binding) struct bindings::BindEntry* external = (*lookupFunction)(*bindingValue, length); if (external) { - Local exports = Object::New(); - external->bind(exports); - bindingCache->Set(binding, exports); + Local exports = Object::New(isolate); + external->bind(exports, isolate->GetCurrentContext()); + cache->Set(binding, exports); externalLookupBindings[*bindingValue] = external; return exports; } } - return Handle(); + return Local(); } // Dispose of all static function templates // in the generated and native bindings. This // clears out the module lookup cache -void KrollBindings::dispose() +void KrollBindings::dispose(v8::Isolate* isolate) { - HandleScope scope; - JNIEnv *env = JNIScope::getEnv(); std::map::iterator iterMods; for (iterMods = externalCommonJsModules.begin(); iterMods != externalCommonJsModules.end(); ++iterMods) { @@ -222,11 +226,12 @@ void KrollBindings::dispose() return; } - Local propertyNames = bindingCache->GetPropertyNames(); + Local cache = bindingCache.Get(isolate); + Local propertyNames = cache->GetPropertyNames(); uint32_t length = propertyNames->Length(); for (uint32_t i = 0; i < length; i++) { - String::Utf8Value binding(propertyNames->Get(i)); + titanium::Utf8Value binding(propertyNames->Get(i)); int bindingLength = binding.length(); struct titanium::bindings::BindEntry *generated = bindings::generated::lookupGeneratedInit(*binding, bindingLength); @@ -250,8 +255,7 @@ void KrollBindings::dispose() externalLookupBindings.clear(); - bindingCache.Dispose(); - bindingCache = Persistent(); + bindingCache.Reset(); } /* @@ -269,37 +273,40 @@ void KrollBindings::addExternalCommonJsModule(const char *name, jobject sourcePr * Checks if an external CommonJS module with given name has been registered * here. */ -v8::Handle KrollBindings::isExternalCommonJsModule(const Arguments& args) +void KrollBindings::isExternalCommonJsModule(const FunctionCallbackInfo& args) { - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); - if (args.Length() == 0 || !args[0]->IsString()) { - return JSException::Error("Invalid arguments to isExternalCommonJsModule, expected String"); + if (args.Length() == 0 || !(args[0]->IsString())) { + JSException::Error(isolate, "Invalid arguments to isExternalCommonJsModule, expected String"); + return; } - v8::Handle name = args[0]->ToString(); - v8::String::Utf8Value nameVal(name); + v8::Local name = args[0].As(); + titanium::Utf8Value nameVal(name); std::string nameKey(*nameVal); bool exists = (externalCommonJsModules.count(nameKey) > 0); - v8::Handle existsV8 = v8::Boolean::New(exists); - return scope.Close(existsV8); + args.GetReturnValue().Set(exists); } /* * Makes the KrollSourceCodeProvider's getSourceCode method call to grab * the source code of a CommonJS module stored in a native (java) external module. */ -v8::Handle KrollBindings::getExternalCommonJsModule(const Arguments& args) +void KrollBindings::getExternalCommonJsModule(const FunctionCallbackInfo& args) { - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + EscapableHandleScope scope(args.GetIsolate()); - if (args.Length() == 0 || !args[0]->IsString()) { - return JSException::Error("Invalid arguments to getExternalCommonJsBinding, expected String"); + if (args.Length() == 0 || !(args[0]->IsString())) { + JSException::Error(isolate, "Invalid arguments to getExternalCommonJsBinding, expected String"); + return; } - v8::Handle name = args[0]->ToString(); - v8::String::Utf8Value nameVal(name); + v8::Local name = args[0].As(); + titanium::Utf8Value nameVal(name); std::string nameKey(*nameVal); std::string moduleRoot = nameKey; std::string subPath = nameKey; @@ -337,13 +344,13 @@ v8::Handle KrollBindings::getExternalCommonJsModule(const Arguments& } } - v8::Handle sourceCode = TypeConverter::javaStringToJsString(env, sourceJavaString); - return scope.Close(sourceCode); + v8::Local sourceCode = TypeConverter::javaStringToJsString(isolate, env, sourceJavaString); + args.GetReturnValue().Set(scope.Escape(sourceCode)); } -Handle KrollBindings::getMainSource() +Local KrollBindings::getMainSource(v8::Isolate* isolate) { - return IMMUTABLE_STRING_LITERAL_FROM_ARRAY(kroll_native, sizeof(kroll_native)-1); + return IMMUTABLE_STRING_LITERAL_FROM_ARRAY(isolate, kroll_native, sizeof(kroll_native)-1); } } diff --git a/android/runtime/v8/src/native/KrollBindings.h b/android/runtime/v8/src/native/KrollBindings.h index 3e68dcc6a93..080bc3477ff 100644 --- a/android/runtime/v8/src/native/KrollBindings.h +++ b/android/runtime/v8/src/native/KrollBindings.h @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -17,7 +17,7 @@ namespace titanium { namespace bindings { - typedef void (*BindCallback)(v8::Handle exports); + typedef void (*BindCallback)(v8::Local exports, v8::Local context); typedef void (*DisposeCallback)(); struct BindEntry { @@ -41,26 +41,26 @@ class KrollBindings static std::map externalLookupBindings; public: - static void initFunctions(v8::Handle exports); + static void initFunctions(v8::Local exports, v8::Local context); - static void initNatives(v8::Handle exports); - static void initTitanium(v8::Handle exports); + static void initNatives(v8::Local exports, v8::Local context); + static void initTitanium(v8::Local exports, v8::Local context); static void disposeTitanium(); - static v8::Handle getMainSource(); + static v8::Local getMainSource(v8::Isolate* isolate); - static v8::Handle getBinding(const v8::Arguments& args); - static v8::Handle getBinding(v8::Handle binding); + static void getBinding(const v8::FunctionCallbackInfo& args); + static v8::Local getBinding(v8::Isolate* isolate, v8::Local binding); - static v8::Handle getExternalBinding(const v8::Arguments& args); + static void getExternalBinding(const v8::FunctionCallbackInfo& args); static void addExternalBinding(const char *name, bindings::BindEntry *binding); static void addExternalLookup(LookupFunction lookup); static void addExternalCommonJsModule(const char *name, jobject sourceProvider, jmethodID sourceRetrievalMethod); - static v8::Handle isExternalCommonJsModule(const v8::Arguments& args); - static v8::Handle getExternalCommonJsModule(const v8::Arguments& args); + static void isExternalCommonJsModule(const v8::FunctionCallbackInfo& args); + static void getExternalCommonJsModule(const v8::FunctionCallbackInfo& args); - static void dispose(); + static void dispose(v8::Isolate* isolate); }; } // namespace titanium diff --git a/android/runtime/v8/src/native/NativeObject.h b/android/runtime/v8/src/native/NativeObject.h index a5389f9b003..3b6b9b7c211 100644 --- a/android/runtime/v8/src/native/NativeObject.h +++ b/android/runtime/v8/src/native/NativeObject.h @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2015 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. * @@ -22,98 +22,111 @@ class ProxyFactory; // this native object will be automatically deleted. This is // used to store "user data" in the JavaScript object for use // inside method and property callbacks. + +// https://github.com/nodejs/node/blob/master/src/node_object_wrap.h class NativeObject { -public: - NativeObject() - { - refs_ = 0; - } - - virtual ~NativeObject() - { - if (!handle_.IsEmpty()) { - assert(handle_.IsNearDeath()); - handle_.ClearWeak(); - handle_->SetInternalField(0, v8::Undefined()); - handle_.Dispose(); - handle_.Clear(); - } - } - - inline v8::Local getHandle() - { - return v8::Local::New(handle_); - } - - template - static inline T* Unwrap(v8::Handle handle) - { - assert(!handle.IsEmpty()); - assert(handle->InternalFieldCount() > 0); - - return static_cast(handle->GetPointerFromInternalField(0)); - } - - v8::Persistent handle_; // ro - -protected: - inline void Wrap(v8::Handle handle) - { - assert(handle_.IsEmpty()); - assert(handle->InternalFieldCount() > 0); - handle_ = v8::Persistent::New(handle); - handle_->SetPointerInInternalField(0, this); - MakeWeak(); - } - - inline void MakeWeak(void) - { - handle_.MakeWeak(this, WeakCallback); - handle_.MarkIndependent(); - } - - /* Ref() marks the object as being attached to an event loop. - * Refed objects will not be garbage collected, even if - * all references are lost. - */ - virtual void Ref() - { - assert(!handle_.IsEmpty()); - refs_++; - handle_.ClearWeak(); - } - - /* Unref() marks an object as detached from the event loop. This is its - * default state. When an object with a "weak" reference changes from - * attached to detached state it will be freed. Be careful not to access - * the object after making this call as it might be gone! - * (A "weak reference" means an object that only has a - * persistant handle.) - * - * DO NOT CALL THIS FROM DESTRUCTOR - */ - virtual void Unref() - { - assert(!handle_.IsEmpty()); - assert(!handle_.IsWeak()); - assert(refs_ > 0); - if (--refs_ == 0) { - MakeWeak(); - } - } - - int refs_; // ro - -private: - static void WeakCallback(v8::Persistent value, void *data) - { - NativeObject *obj = static_cast(data); - assert(value == obj->handle_); - assert(!obj->refs_); - assert(value.IsNearDeath()); - delete obj; - } + public: + NativeObject() { + refs_ = 0; + } + + + virtual ~NativeObject() { + if (persistent().IsEmpty()) + return; + assert(persistent().IsNearDeath()); + persistent().ClearWeak(); + persistent().Reset(); + } + + + template + static inline T* Unwrap(v8::Local handle) { + assert(!handle.IsEmpty()); + assert(handle->InternalFieldCount() > 0); + // Cast to NativeObject before casting to T. A direct cast from void + // to T won't work right when T has more than one base class. + void* ptr = handle->GetAlignedPointerFromInternalField(0); + NativeObject* wrap = static_cast(ptr); + return static_cast(wrap); + } + + + inline v8::Local handle() { + return handle(v8::Isolate::GetCurrent()); + } + + + inline v8::Local handle(v8::Isolate* isolate) { + return persistent().Get(isolate); + } + + + inline v8::Persistent& persistent() { + return handle_; + } + + + protected: + inline void Wrap(v8::Local handle) { + assert(persistent().IsEmpty()); + assert(handle->InternalFieldCount() > 0); + handle->SetAlignedPointerInInternalField(0, this); + persistent().Reset(v8::Isolate::GetCurrent(), handle); + MakeWeak(); + } + + + inline void MakeWeak(void) { + persistent().SetWeak(this, WeakCallback); + persistent().MarkIndependent(); + } + + /* Ref() marks the object as being attached to an event loop. + * Refed objects will not be garbage collected, even if + * all references are lost. + */ + virtual void Ref() { + assert(!persistent().IsEmpty()); + persistent().ClearWeak(); + refs_++; + } + + /* Unref() marks an object as detached from the event loop. This is its + * default state. When an object with a "weak" reference changes from + * attached to detached state it will be freed. Be careful not to access + * the object after making this call as it might be gone! + * (A "weak reference" means an object that only has a + * persistent handle.) + * + * DO NOT CALL THIS FROM DESTRUCTOR + */ + virtual void Unref() { + assert(!persistent().IsEmpty()); + assert(!persistent().IsWeak()); + assert(refs_ > 0); + if (--refs_ == 0) + MakeWeak(); + } + + int refs_; // ro + + private: + static void WeakCallback( + const v8::WeakCallbackData& data) { + v8::Isolate* isolate = data.GetIsolate(); + v8::HandleScope scope(isolate); + NativeObject* wrap = data.GetParameter(); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + assert( + data.GetValue() == v8::Local::New(isolate, wrap->handle_)); + wrap->handle_.Reset(); + delete wrap; + } + + v8::Persistent handle_; friend class ProxyFactory; }; diff --git a/android/runtime/v8/src/native/Proxy.cpp b/android/runtime/v8/src/native/Proxy.cpp index a830560d5ea..6b48206a336 100644 --- a/android/runtime/v8/src/native/Proxy.cpp +++ b/android/runtime/v8/src/native/Proxy.cpp @@ -1,6 +1,6 @@ /* * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -40,90 +40,97 @@ Proxy::Proxy(jobject javaProxy) : { } -void Proxy::bindProxy(Handle exports) +void Proxy::bindProxy(Local exports, Local context) { - javaClassSymbol = SYMBOL_LITERAL("__javaClass__"); - constructorSymbol = SYMBOL_LITERAL("constructor"); - inheritSymbol = SYMBOL_LITERAL("inherit"); - propertiesSymbol = SYMBOL_LITERAL("_properties"); - lengthSymbol = SYMBOL_LITERAL("length"); - sourceUrlSymbol = SYMBOL_LITERAL("sourceUrl"); - - Local proxyTemplate = FunctionTemplate::New(); - Local proxySymbol = String::NewSymbol("Proxy"); + Isolate* isolate = context->GetIsolate(); + Local javaClass = NEW_SYMBOL(isolate, "__javaClass__"); + javaClassSymbol.Reset(isolate, javaClass); + constructorSymbol.Reset(isolate, NEW_SYMBOL(isolate, "constructor")); + inheritSymbol.Reset(isolate, NEW_SYMBOL(isolate, "inherit")); + propertiesSymbol.Reset(isolate, NEW_SYMBOL(isolate, "_properties")); + lengthSymbol.Reset(isolate, NEW_SYMBOL(isolate, "length")); + sourceUrlSymbol.Reset(isolate, NEW_SYMBOL(isolate, "sourceUrl")); + + Local proxyTemplate = FunctionTemplate::New(isolate); + Local proxySymbol = NEW_SYMBOL(isolate, "Proxy"); proxyTemplate->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount); proxyTemplate->SetClassName(proxySymbol); - proxyTemplate->Inherit(EventEmitter::constructorTemplate); + proxyTemplate->Inherit(EventEmitter::constructorTemplate.Get(isolate)); - proxyTemplate->Set(javaClassSymbol, External::Wrap(JNIUtil::krollProxyClass), - PropertyAttribute(DontDelete | DontEnum)); + proxyTemplate->Set(javaClass, External::New(isolate, JNIUtil::krollProxyClass), + static_cast(DontDelete | DontEnum)); - DEFINE_PROTOTYPE_METHOD(proxyTemplate, "_hasListenersForEventType", hasListenersForEventType); - DEFINE_PROTOTYPE_METHOD(proxyTemplate, "onPropertiesChanged", proxyOnPropertiesChanged); - DEFINE_PROTOTYPE_METHOD(proxyTemplate, "_onEventFired", onEventFired); + SetProtoMethod(isolate, proxyTemplate, "_hasListenersForEventType", hasListenersForEventType); + SetProtoMethod(isolate, proxyTemplate, "onPropertiesChanged", proxyOnPropertiesChanged); + SetProtoMethod(isolate, proxyTemplate, "_onEventFired", onEventFired); + baseProxyTemplate.Reset(isolate, proxyTemplate); - baseProxyTemplate = Persistent::New(proxyTemplate); - - exports->Set(proxySymbol, proxyTemplate->GetFunction()); + exports->Set(proxySymbol, proxyTemplate->GetFunction(context).ToLocalChecked()); } -static Handle getPropertyForProxy(Local property, Local proxy) +static Local getPropertyForProxy(Isolate* isolate, Local property, Local proxy) { // Call getProperty on the Proxy to get the property. // We define this method in JavaScript on the Proxy prototype. - Local getProperty = proxy->Get(String::New("getProperty")); + Local getProperty = proxy->Get(STRING_NEW(isolate, "getProperty")); if (!getProperty.IsEmpty() && getProperty->IsFunction()) { Local argv[1] = { property }; - return Handle::Cast(getProperty)->Call(proxy, 1, argv); + MaybeLocal value = getProperty.As()->Call(isolate->GetCurrentContext(), proxy, 1, argv); + if (value.IsEmpty()) { + return Undefined(isolate); + } + return value.ToLocalChecked(); } LOGE(TAG, "Unable to lookup Proxy.prototype.getProperty"); - return Undefined(); + return Undefined(isolate); } -Handle Proxy::getProperty(Local property, const AccessorInfo& info) +void Proxy::getProperty(Local property, const PropertyCallbackInfo& args) { - return getPropertyForProxy(property, info.This()); + Isolate* isolate = args.GetIsolate(); + args.GetReturnValue().Set(getPropertyForProxy(isolate, property->ToString(isolate), args.Holder())); } -Handle Proxy::getProperty(const Arguments& args) +void Proxy::getProperty(const FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); // The name of the property can be passed either as // an argument or a data parameter. Local name; if (args.Length() >= 1) { - name = args[0]->ToString(); - + name = args[0]->ToString(isolate); } else if (args.Data()->IsString()) { - name = args.Data()->ToString(); - + name = args.Data().As(); } else { - return JSException::Error("Requires property name."); + JSException::Error(isolate, "Requires property name."); + return; } - return getPropertyForProxy(name, args.Holder()); + args.GetReturnValue().Set(getPropertyForProxy(isolate, name, args.Holder())); } -static void setPropertyOnProxy(Local property, Local value, Local proxy) +static void setPropertyOnProxy(Isolate* isolate, Local property, Local value, Local proxy) { // Call Proxy.prototype.setProperty. - Local setProperty = proxy->Get(String::New("setProperty")); + Local setProperty = proxy->Get(STRING_NEW(isolate, "setProperty")); if (!setProperty.IsEmpty() && setProperty->IsFunction()) { Local argv[2] = { property, value }; - Handle::Cast(setProperty)->Call(proxy, 2, argv); + setProperty.As()->Call(isolate->GetCurrentContext(), proxy, 2, argv); return; } LOGE(TAG, "Unable to lookup Proxy.prototype.setProperty"); } -void Proxy::setProperty(Local property, Local value, const AccessorInfo& info) +void Proxy::setProperty(Local property, Local value, const PropertyCallbackInfo& info) { - setPropertyOnProxy(property, value, info.This()); + Isolate* isolate = info.GetIsolate(); + setPropertyOnProxy(isolate, property->ToString(isolate), value, info.This()); } -static void onPropertyChangedForProxy(Local property, Local value, Local proxyObject) +static void onPropertyChangedForProxy(Isolate* isolate, Local property, Local value, Local proxyObject) { Proxy* proxy = NativeObject::Unwrap(proxyObject); @@ -135,7 +142,7 @@ static void onPropertyChangedForProxy(Local property, Local value jstring javaProperty = TypeConverter::jsStringToJavaString(env, property); bool javaValueIsNew; - jobject javaValue = TypeConverter::jsValueToJavaObject(env, value, &javaValueIsNew); + jobject javaValue = TypeConverter::jsValueToJavaObject(isolate, env, value, &javaValueIsNew); jobject javaProxy = proxy->getJavaObject(); env->CallVoidMethod(javaProxy, @@ -153,32 +160,35 @@ static void onPropertyChangedForProxy(Local property, Local value } // Store new property value on JS internal map. - setPropertyOnProxy(property, value, proxyObject); + setPropertyOnProxy(isolate, property, value, proxyObject); } -void Proxy::onPropertyChanged(Local property, Local value, const AccessorInfo& info) +void Proxy::onPropertyChanged(Local property, Local value, const v8::PropertyCallbackInfo& info) { - onPropertyChangedForProxy(property, value, info.Holder()); + Isolate* isolate = info.GetIsolate(); + onPropertyChangedForProxy(isolate, property->ToString(isolate), value, info.Holder()); } -Handle Proxy::onPropertyChanged(const Arguments& args) +void Proxy::onPropertyChanged(const v8::FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); if (args.Length() < 1) { - return JSException::Error("Requires property name as first parameters."); + JSException::Error(isolate, "Requires property name as first parameters."); + return; } - Local name = args.Data()->ToString(); + Local name = args.Data()->ToString(isolate); Local value = args[0]; - onPropertyChangedForProxy(name, value, args.Holder()); - - return Undefined(); + onPropertyChangedForProxy(isolate, name, value, args.Holder()); } -Handle Proxy::getIndexedProperty(uint32_t index, const AccessorInfo& info) +void Proxy::getIndexedProperty(uint32_t index, const PropertyCallbackInfo& info) { + Isolate* isolate = info.GetIsolate(); JNIEnv* env = JNIScope::getEnv(); if (!env) { - return JSException::GetJNIEnvironmentError(); + JSException::GetJNIEnvironmentError(isolate); + return; } Proxy* proxy = NativeObject::Unwrap(info.Holder()); @@ -191,24 +201,26 @@ Handle Proxy::getIndexedProperty(uint32_t index, const AccessorInfo& info env->DeleteLocalRef(javaProxy); } - Handle result = TypeConverter::javaObjectToJsValue(env, value); + Local result = TypeConverter::javaObjectToJsValue(isolate, env, value); env->DeleteLocalRef(value); - return result; + info.GetReturnValue().Set(result); } -Handle Proxy::setIndexedProperty(uint32_t index, Local value, const AccessorInfo& info) +void Proxy::setIndexedProperty(uint32_t index, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = info.GetIsolate(); JNIEnv* env = JNIScope::getEnv(); if (!env) { LOG_JNIENV_GET_ERROR(TAG); - return Undefined(); + // Returns undefined by default + return; } Proxy* proxy = NativeObject::Unwrap(info.Holder()); bool javaValueIsNew; - jobject javaValue = TypeConverter::jsValueToJavaObject(env, value, &javaValueIsNew); + jobject javaValue = TypeConverter::jsValueToJavaObject(isolate, env, value, &javaValueIsNew); jobject javaProxy = proxy->getJavaObject(); env->CallVoidMethod(javaProxy, JNIUtil::krollProxySetIndexedPropertyMethod, @@ -222,20 +234,22 @@ Handle Proxy::setIndexedProperty(uint32_t index, Local value, cons env->DeleteLocalRef(javaValue); } - return value; + info.GetReturnValue().Set(value); } -Handle Proxy::hasListenersForEventType(const Arguments& args) +void Proxy::hasListenersForEventType(const v8::FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); JNIEnv* env = JNIScope::getEnv(); if (!env) { - return JSException::GetJNIEnvironmentError(); + JSException::GetJNIEnvironmentError(isolate); + return; } Proxy* proxy = NativeObject::Unwrap(args.Holder()); - Local eventType = args[0]->ToString(); - Local hasListeners = args[1]->ToBoolean(); + Local eventType = args[0]->ToString(isolate); + Local hasListeners = args[1]->ToBoolean(isolate); jobject javaProxy = proxy->getJavaObject(); jobject krollObject = env->GetObjectField(javaProxy, JNIUtil::krollProxyKrollObjectField); @@ -252,27 +266,27 @@ Handle Proxy::hasListenersForEventType(const Arguments& args) env->DeleteLocalRef(krollObject); env->DeleteLocalRef(javaEventType); - - return Undefined(); } -Handle Proxy::onEventFired(const Arguments& args) +void Proxy::onEventFired(const v8::FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); JNIEnv* env = JNIScope::getEnv(); if (!env) { - return JSException::GetJNIEnvironmentError(); + JSException::GetJNIEnvironmentError(isolate); + return; } Proxy* proxy = NativeObject::Unwrap(args.Holder()); - Local eventType = args[0]->ToString(); + Local eventType = args[0]->ToString(isolate); Local eventData = args[1]; jobject javaProxy = proxy->getJavaObject(); jobject krollObject = env->GetObjectField(javaProxy, JNIUtil::krollProxyKrollObjectField); jstring javaEventType = TypeConverter::jsStringToJavaString(env, eventType); - jobject javaEventData = TypeConverter::jsValueToJavaObject(env, eventData); + jobject javaEventData = TypeConverter::jsValueToJavaObject(isolate, env, eventData); if (!JavaObject::useGlobalRefs) { @@ -287,53 +301,55 @@ Handle Proxy::onEventFired(const Arguments& args) env->DeleteLocalRef(krollObject); env->DeleteLocalRef(javaEventType); env->DeleteLocalRef(javaEventData); - - return Undefined(); } -Handle Proxy::inheritProxyTemplate( - Handle superTemplate, jclass javaClass, - Handle className, Handle callback) +Local Proxy::inheritProxyTemplate(Isolate* isolate, + Local superTemplate, jclass javaClass, + Local className, Local callback) { - HandleScope scope; + EscapableHandleScope scope(isolate); - Local wrappedClass = External::Wrap(javaClass); - Local inheritedTemplate = FunctionTemplate::New(proxyConstructor, callback); + Local wrappedClass = External::New(isolate, javaClass); + Local inheritedTemplate = FunctionTemplate::New(isolate, proxyConstructor, callback); - inheritedTemplate->Set(javaClassSymbol, wrappedClass, PropertyAttribute(DontDelete | DontEnum)); + inheritedTemplate->Set(javaClassSymbol.Get(isolate), wrappedClass, static_cast(DontDelete | DontEnum)); inheritedTemplate->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount); + // every instance gets a special "_properties" object for us to use inetrnally for get/setProperty + inheritedTemplate->InstanceTemplate()->Set(propertiesSymbol.Get(isolate), Object::New(isolate), static_cast(DontEnum)); inheritedTemplate->SetClassName(className); inheritedTemplate->Inherit(superTemplate); - return scope.Close(inheritedTemplate); + return scope.Escape(inheritedTemplate); } -Handle Proxy::proxyConstructor(const Arguments& args) +void Proxy::proxyConstructor(const v8::FunctionCallbackInfo& args) { - HandleScope scope; - JNIEnv *env = JNIScope::getEnv(); - Local jsProxy = args.Holder(); + LOGD(TAG, "proxy constructor callback!"); + Isolate* isolate = args.GetIsolate(); + EscapableHandleScope scope(isolate); - Handle properties = Object::New(); - jsProxy->Set(propertiesSymbol, properties, PropertyAttribute(DontEnum)); - - Handle prototype = jsProxy->GetPrototype()->ToObject(); - - Handle constructor = Handle::Cast(prototype->Get(constructorSymbol)); - jclass javaClass = (jclass) External::Unwrap(constructor->Get(javaClassSymbol)); - - JNIUtil::logClassName("Create proxy: %s", javaClass); + JNIEnv *env = JNIScope::getEnv(); + Local jsProxy = args.This(); + // First things first, we need to wrap the object in case future calls need to unwrap proxy! Proxy* proxy = new Proxy(NULL); - proxy->wrap(jsProxy); + proxy->wrap(isolate, jsProxy); - // If ProxyFactory::createV8Proxy invoked us, unwrap - // the pre-created Java proxy it sent. - jobject javaProxy = ProxyFactory::unwrapJavaProxy(args); + // Now we hook up a java Object from the JVM... + jobject javaProxy = ProxyFactory::unwrapJavaProxy(args); // do we already have one that got passed in? bool deleteRef = false; if (!javaProxy) { + // No passed in java object, so let's create an instance + // Look up java class from prototype... + Local prototype = jsProxy->GetPrototype()->ToObject(isolate); + Local constructor = prototype->Get(constructorSymbol.Get(isolate)).As(); + Local wrap = constructor->Get(javaClassSymbol.Get(isolate)).As(); + jclass javaClass = static_cast(wrap->Value()); + + // Now we create an instance of the class and hook it up + JNIUtil::logClassName("Creating java proxy for class %s", javaClass); javaProxy = ProxyFactory::createJavaProxy(javaClass, jsProxy, args); deleteRef = true; } @@ -342,37 +358,32 @@ Handle Proxy::proxyConstructor(const Arguments& args) int length = args.Length(); if (length > 0 && args[0]->IsObject()) { - /* - Handle argsStr = V8Util::jsonStringify(args[0]); - String::Utf8Value str(argsStr); - LOGV(TAG, " with args: %s", *str); - */ - bool extend = true; - Handle createProperties = args[0]->ToObject(); + Local createProperties = args[0].As(); Local constructorName = createProperties->GetConstructorName(); - if (strcmp(*String::Utf8Value(constructorName), "Arguments") == 0) { + if (strcmp(*titanium::Utf8Value(constructorName), "Arguments") == 0) { extend = false; - int32_t argsLength = createProperties->Get(String::New("length"))->Int32Value(); + int32_t argsLength = createProperties->Get(STRING_NEW(isolate, "length"))->Int32Value(); if (argsLength > 1) { - Handle properties = createProperties->Get(1); + Local properties = createProperties->Get(1); if (properties->IsObject()) { extend = true; - createProperties = properties->ToObject(); + createProperties = properties.As(); } } } if (extend) { - Handle names = createProperties->GetOwnPropertyNames(); + Local names = createProperties->GetOwnPropertyNames(); int length = names->Length(); + Local properties = jsProxy->Get(propertiesSymbol.Get(isolate))->ToObject(isolate); for (int i = 0; i < length; ++i) { - Handle name = names->Get(i); - Handle value = createProperties->Get(name); + Local name = names->Get(i); + Local value = createProperties->Get(name); bool isProperty = true; if (name->IsString()) { - Handle nameString = name->ToString(); + Local nameString = name.As(); if (!jsProxy->HasRealNamedCallbackProperty(nameString) && !jsProxy->HasRealNamedProperty(nameString)) { jsProxy->Set(name, value); @@ -388,12 +399,12 @@ Handle Proxy::proxyConstructor(const Arguments& args) if (!args.Data().IsEmpty() && args.Data()->IsFunction()) { - Handle proxyFn = Handle::Cast(args.Data()); - Handle *fnArgs = new Handle[length]; + Local proxyFn = args.Data().As(); + Local *fnArgs = new Local[length]; for (int i = 0; i < length; ++i) { fnArgs[i] = args[i]; } - proxyFn->Call(jsProxy, length, fnArgs); + proxyFn->Call(isolate->GetCurrentContext(), jsProxy, length, fnArgs); } if (deleteRef) { @@ -403,35 +414,39 @@ Handle Proxy::proxyConstructor(const Arguments& args) } } - return jsProxy; + args.GetReturnValue().Set(scope.Escape(jsProxy)); } -Handle Proxy::proxyOnPropertiesChanged(const Arguments& args) +void Proxy::proxyOnPropertiesChanged(const v8::FunctionCallbackInfo& args) { - HandleScope scope; - Handle jsProxy = args.Holder(); + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + Local jsProxy = args.Holder(); - if (args.Length() < 1 || !args[0]->IsArray()) { - return JSException::Error("Proxy.propertiesChanged requires a list of lists of property name, the old value, and the new value"); + if (args.Length() < 1 || !(args[0]->IsArray())) { + JSException::Error(isolate, "Proxy.propertiesChanged requires a list of lists of property name, the old value, and the new value"); + return; } JNIEnv *env = JNIScope::getEnv(); if (!env) { - return JSException::GetJNIEnvironmentError(); + JSException::GetJNIEnvironmentError(isolate); + return; } Proxy *proxy = unwrap(jsProxy); if (!proxy) { - return JSException::Error("Failed to unwrap Proxy instance"); + JSException::Error(isolate, "Failed to unwrap Proxy instance"); + return; } - Local changes = Local::Cast(args[0]); + Local changes = args[0].As(); uint32_t length = changes->Length(); jobjectArray jChanges = env->NewObjectArray(length, JNIUtil::objectClass, NULL); for (uint32_t i = 0; i < length; ++i) { - Local change = Local::Cast(changes->Get(i)); - Local name = change->Get(INDEX_NAME)->ToString(); + Local change = changes->Get(i).As(); + Local name = change->Get(INDEX_NAME)->ToString(isolate); Local oldValue = change->Get(INDEX_OLD_VALUE); Local value = change->Get(INDEX_VALUE); @@ -442,13 +457,13 @@ Handle Proxy::proxyOnPropertiesChanged(const Arguments& args) env->DeleteLocalRef(jName); bool isNew; - jobject jOldValue = TypeConverter::jsValueToJavaObject(env, oldValue, &isNew); + jobject jOldValue = TypeConverter::jsValueToJavaObject(isolate, env, oldValue, &isNew); env->SetObjectArrayElement(jChange, INDEX_OLD_VALUE, jOldValue); if (isNew) { env->DeleteLocalRef(jOldValue); } - jobject jValue = TypeConverter::jsValueToJavaObject(env, value, &isNew); + jobject jValue = TypeConverter::jsValueToJavaObject(isolate, env, value, &isNew); env->SetObjectArrayElement(jChange, INDEX_VALUE, jValue); if (isNew) { env->DeleteLocalRef(jValue); @@ -466,31 +481,18 @@ Handle Proxy::proxyOnPropertiesChanged(const Arguments& args) env->DeleteLocalRef(javaProxy); } - return Undefined(); + return; } void Proxy::dispose() { - baseProxyTemplate.Dispose(); - baseProxyTemplate = Persistent(); - - javaClassSymbol.Dispose(); - javaClassSymbol = Persistent(); - - constructorSymbol.Dispose(); - constructorSymbol = Persistent(); - - inheritSymbol.Dispose(); - inheritSymbol = Persistent(); - - propertiesSymbol.Dispose(); - propertiesSymbol = Persistent(); - - lengthSymbol.Dispose(); - lengthSymbol = Persistent(); - - sourceUrlSymbol.Dispose(); - sourceUrlSymbol = Persistent(); + baseProxyTemplate.Reset(); + javaClassSymbol.Reset(); + constructorSymbol.Reset(); + inheritSymbol.Reset(); + propertiesSymbol.Reset(); + lengthSymbol.Reset(); + sourceUrlSymbol.Reset(); } } // namespace titanium diff --git a/android/runtime/v8/src/native/Proxy.h b/android/runtime/v8/src/native/Proxy.h index ca78f4d5fe8..cfeec033f38 100644 --- a/android/runtime/v8/src/native/Proxy.h +++ b/android/runtime/v8/src/native/Proxy.h @@ -1,6 +1,6 @@ /* * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -33,43 +33,42 @@ class Proxy : public JavaObject Proxy(jobject javaProxy); // Initialize the base proxy template - static void bindProxy(v8::Handle exports); + static void bindProxy(v8::Local exports, Local context); // Query the property value from the internal property map. // Proxies that have only setters in Java store the value // on the JavaScript side in this map. This getter is then // used when the user script requests the value. - static v8::Handle getProperty(v8::Local property, - const v8::AccessorInfo& info); - static v8::Handle getProperty(const v8::Arguments& args); + static void getProperty(v8::Local name, const v8::PropertyCallbackInfo& args); + static void getProperty(const v8::FunctionCallbackInfo& args); // Stores the new value for the property into the internal map. - static void setProperty(v8::Local property, - v8::Local value, - const v8::AccessorInfo& info); + static void setProperty(v8::Local name, + v8::Local value, + const v8::PropertyCallbackInfo& info); // Setter that reports to the Java proxy when a property has changed. // Used by proxies that use accessor based properties. - static void onPropertyChanged(v8::Local property, - v8::Local value, - const v8::AccessorInfo& info); - static v8::Handle onPropertyChanged(const v8::Arguments& args); + static void onPropertyChanged(v8::Local name, + v8::Local value, + const v8::PropertyCallbackInfo& info); + static void onPropertyChanged(const v8::FunctionCallbackInfo& args); // Fetches an indexed property value from the Java proxy. - static v8::Handle getIndexedProperty(uint32_t index, - const v8::AccessorInfo& info); + static void getIndexedProperty(uint32_t index, + const v8::PropertyCallbackInfo& info); // Sets an indexed property on the Java proxy. - static v8::Handle setIndexedProperty(uint32_t index, + static void setIndexedProperty(uint32_t index, v8::Local value, - const v8::AccessorInfo& info); + const v8::PropertyCallbackInfo& info); // Called by EventEmitter to notify when listeners // are watching for a type of event. Notifies the Java proxy when this changes. - static v8::Handle hasListenersForEventType(const v8::Arguments& args); + static void hasListenersForEventType(const v8::FunctionCallbackInfo& args); // Called by EventEmitter when we fire events from JS to Java - static v8::Handle onEventFired(const v8::Arguments& args); + static void onEventFired(const v8::FunctionCallbackInfo& args); // This provides Javascript a way to extend one of our native / wrapped // templates without needing to know about the internal java class. @@ -79,32 +78,35 @@ class Proxy : public JavaObject // // constructor code goes here.. (optional) // }); template - static v8::Handle inherit(const v8::Arguments& args) + static void inherit(const v8::FunctionCallbackInfo& args) { - v8::HandleScope scope; - v8::Handle fn = v8::Handle::Cast(args[0]); + v8::Isolate* isolate = args.GetIsolate(); + v8::HandleScope scope(isolate); + v8::Local fn = args[0].As(); - v8::Handle newType = inheritProxyTemplate( - ProxyClass::proxyTemplate, + v8::Local newType = inheritProxyTemplate( + isolate, + ProxyClass::getProxyTemplate(isolate), ProxyClass::javaClass, - fn->GetName()->ToString(), fn); - return newType->GetFunction(); + fn->GetName()->ToString(isolate), fn); + args.GetReturnValue().Set(newType->GetFunction()); } // Inherit a built-in proxy template for use in Javascript (used by generated code) - static v8::Handle inheritProxyTemplate( - v8::Handle superTemplate, + static v8::Local inheritProxyTemplate( + v8::Isolate* isolate, + v8::Local superTemplate, jclass javaClass, - v8::Handle className, - v8::Handle callback = v8::Handle()); + v8::Local className, + v8::Local callback = v8::Local()); - static inline Proxy* unwrap(v8::Handle value) + static inline Proxy* unwrap(v8::Local value) { if (!JavaObject::isJavaObject(value)) { return NULL; } - void *ptr = value->GetPointerFromInternalField(0); + void *ptr = value->GetAlignedPointerFromInternalField(0); if (!ptr) { return NULL; } @@ -115,8 +117,8 @@ class Proxy : public JavaObject static void dispose(); private: - static v8::Handle proxyConstructor(const v8::Arguments& args); - static v8::Handle proxyOnPropertiesChanged(const v8::Arguments& args); + static void proxyConstructor(const v8::FunctionCallbackInfo& args); + static void proxyOnPropertiesChanged(const v8::FunctionCallbackInfo& args); }; } diff --git a/android/runtime/v8/src/native/ProxyFactory.cpp b/android/runtime/v8/src/native/ProxyFactory.cpp index fcaed283f88..3e2997a4edf 100644 --- a/android/runtime/v8/src/native/ProxyFactory.cpp +++ b/android/runtime/v8/src/native/ProxyFactory.cpp @@ -1,6 +1,6 @@ /* * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -41,16 +41,16 @@ static ProxyFactoryMap factories; #define LOG_JNIENV_ERROR(msgMore) \ LOGE(TAG, "Unable to find class %s", msgMore) -Handle ProxyFactory::createV8Proxy(jclass javaClass, jobject javaProxy) +Local ProxyFactory::createV8Proxy(v8::Isolate* isolate, jclass javaClass, jobject javaProxy) { LOGV(TAG, "create v8 proxy"); JNIEnv* env = JNIScope::getEnv(); if (!env) { LOG_JNIENV_ERROR("while creating Java proxy."); - return Handle(); + return Local(); } - ENTER_V8(V8Runtime::globalContext); + v8::EscapableHandleScope scope(isolate); Local creator; LOGV(TAG, "get proxy info"); @@ -61,40 +61,41 @@ Handle ProxyFactory::createV8Proxy(jclass javaClass, jobject javaProxy) // No info has been registered for this class yet, fall back // to the binding lookup table jstring javaClassName = JNIUtil::getClassName(javaClass); - Handle className = TypeConverter::javaStringToJsString(env, javaClassName); + Local className = TypeConverter::javaStringToJsString(isolate, env, javaClassName); env->DeleteLocalRef(javaClassName); - Handle exports = KrollBindings::getBinding(className->ToString()); + Local exports = KrollBindings::getBinding(isolate, className->ToString(isolate)); if (exports.IsEmpty()) { - String::Utf8Value classStr(className); + titanium::Utf8Value classStr(className); LOGE(TAG, "Failed to find class for %s", *classStr); LOG_JNIENV_ERROR("while creating V8 Proxy."); - return Handle(); + return scope.Escape(Local()); } // TODO: The first value in exports should be the type that's exported // But there's probably a better way to do this - Handle names = exports->GetPropertyNames(); + Local names = exports->GetPropertyNames(); if (names->Length() >= 1) { - creator = Local::Cast(exports->Get(names->Get(0))); + creator = exports->Get(names->Get(0)).As(); } } else { - creator = info->v8ProxyTemplate->GetFunction(); + creator = info->v8ProxyTemplate->GetFunction(isolate->GetCurrentContext()).ToLocalChecked(); } - Local external = External::New(javaProxy); - TryCatch tryCatch; - Local v8Proxy = creator->NewInstance(1, &external); + Local external = External::New(isolate, javaProxy); + TryCatch tryCatch(isolate); + Local argv[1] = { external }; + Local v8Proxy = creator->NewInstance(1, argv); if (tryCatch.HasCaught()) { LOGE(TAG, "Exception thrown while creating V8 proxy."); - V8Util::reportException(tryCatch); - return Handle(); + V8Util::reportException(isolate, tryCatch); + return scope.Escape(Local()); } // set the pointer back on the java proxy Proxy* proxy = NativeObject::Unwrap(v8Proxy); - jlong ptr = (jlong) *(proxy->handle_); + jlong ptr = (jlong) &(proxy->persistent()); jobject javaV8Object = env->NewObject(JNIUtil::v8ObjectClass, JNIUtil::v8ObjectInitMethod, ptr); @@ -103,11 +104,12 @@ Handle ProxyFactory::createV8Proxy(jclass javaClass, jobject javaProxy) JNIUtil::krollProxyKrollObjectField, javaV8Object); env->DeleteLocalRef(javaV8Object); - return scope.Close(v8Proxy); + return scope.Escape(v8Proxy); } -jobject ProxyFactory::createJavaProxy(jclass javaClass, Local v8Proxy, const Arguments& args) +jobject ProxyFactory::createJavaProxy(jclass javaClass, Local v8Proxy, const v8::FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); ProxyInfo* info; GET_PROXY_INFO(javaClass, info); @@ -126,12 +128,13 @@ jobject ProxyFactory::createJavaProxy(jclass javaClass, Local v8Proxy, c // Create a persistent handle to the V8 proxy // and cast it to a pointer. The Java proxy needs // a reference to the V8 proxy for later use. - Proxy* proxy = NativeObject::Unwrap(v8Proxy); - jlong pv8Proxy = (jlong) *(proxy->handle_); + Proxy* proxy = NativeObject::Unwrap(v8Proxy); // v8Proxy holds Proxy object in internal field + jlong pv8Proxy = (jlong) &(proxy->persistent()); // proxy has a persistent holding the v8Proxy. + // So we're getting address of the persistent which holds v8Proxy here... // We also pass the creation URL of the proxy so we can track relative URLs - Handle sourceUrl = args.Callee()->GetScriptOrigin().ResourceName(); - String::Utf8Value sourceUrlValue(sourceUrl); + Local sourceUrl = args.Callee()->GetScriptOrigin().ResourceName(); + titanium::Utf8Value sourceUrlValue(sourceUrl); const char *url = "app://app.js"; jstring javaSourceUrl = NULL; @@ -145,7 +148,7 @@ jobject ProxyFactory::createJavaProxy(jclass javaClass, Local v8Proxy, c // if an Arguments object was passed as the sole argument. bool calledFromCreate = false; if (args.Length() == 1 && args[0]->IsObject()) { - if (V8Util::constructorNameMatches(args[0]->ToObject(), "Arguments")) { + if (V8Util::constructorNameMatches(isolate, args[0].As(), "Arguments")) { calledFromCreate = true; } } @@ -155,22 +158,22 @@ jobject ProxyFactory::createJavaProxy(jclass javaClass, Local v8Proxy, c // depends how this constructor was called. jobjectArray javaArgs; if (calledFromCreate) { - Local arguments = args[0]->ToObject(); - int length = arguments->Get(Proxy::lengthSymbol)->Int32Value(); + Local arguments = args[0]->ToObject(isolate); + int length = arguments->Get(Proxy::lengthSymbol.Get(isolate))->Int32Value(); int start = 0; // Get the scope variables if provided and extract the source URL. // We need to send that to the Java side when creating the proxy. if (length > 0) { - Local scopeVars = arguments->Get(0)->ToObject(); - if (V8Util::constructorNameMatches(scopeVars, "ScopeVars")) { - Local sourceUrl = scopeVars->Get(Proxy::sourceUrlSymbol); - javaSourceUrl = TypeConverter::jsValueToJavaString(env, sourceUrl); + Local scopeVars = arguments->Get(0)->ToObject(isolate); + if (V8Util::constructorNameMatches(isolate, scopeVars, "ScopeVars")) { + Local sourceUrl = scopeVars->Get(Proxy::sourceUrlSymbol.Get(isolate)); + javaSourceUrl = TypeConverter::jsValueToJavaString(isolate, env, sourceUrl); start = 1; } } - javaArgs = TypeConverter::jsObjectIndexPropsToJavaArray(env, arguments, start, length); + javaArgs = TypeConverter::jsObjectIndexPropsToJavaArray(isolate, env, arguments, start, length); } else { javaArgs = TypeConverter::jsArgumentsToJavaArray(env, args); } @@ -194,12 +197,13 @@ jobject ProxyFactory::createJavaProxy(jclass javaClass, Local v8Proxy, c return javaProxy; } -jobject ProxyFactory::unwrapJavaProxy(const Arguments& args) +jobject ProxyFactory::unwrapJavaProxy(const v8::FunctionCallbackInfo& args) { if (args.Length() != 1) return NULL; + Local firstArgument = args[0]; - return firstArgument->IsExternal() ? (jobject)External::Unwrap(firstArgument) : NULL; + return firstArgument->IsExternal() ? (jobject) (firstArgument.As()->Value()) : NULL; } void ProxyFactory::registerProxyPair(jclass javaProxyClass, FunctionTemplate* v8ProxyTemplate, bool createDeprecated) @@ -228,4 +232,3 @@ void ProxyFactory::dispose() } } - diff --git a/android/runtime/v8/src/native/ProxyFactory.h b/android/runtime/v8/src/native/ProxyFactory.h index a9e5f7d67c4..65931b21ef2 100644 --- a/android/runtime/v8/src/native/ProxyFactory.h +++ b/android/runtime/v8/src/native/ProxyFactory.h @@ -1,6 +1,6 @@ /* * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -27,21 +27,21 @@ class ProxyFactory public: // Creates a proxy on the V8 side given an existing Java proxy. - static v8::Handle createV8Proxy(jclass javaClass, jobject javaProxy); + static v8::Local createV8Proxy(v8::Isolate* isolate, jclass javaClass, jobject javaProxy); // Creates a proxy on the Java side given an existing V8 proxy. - static jobject createJavaProxy(jclass javaClass, v8::Local v8Proxy, const v8::Arguments& args); + static jobject createJavaProxy(jclass javaClass, v8::Local v8Proxy, const v8::FunctionCallbackInfo& args); // Used by createV8Proxy() which invokes the ProxyBinding::Constructor // callback to create a new V8 object. We need a way to pass the Java proxy // jobject. This is done by passing it as an External value argument. - static jobject unwrapJavaProxy(const v8::Arguments& args); + static jobject unwrapJavaProxy(const v8::FunctionCallbackInfo& args); // Setup a new proxy pair for some Kroll type. static void registerProxyPair(jclass javaProxyClass, v8::FunctionTemplate* factory, bool createDeprecated = false); // The generic constructor for all proxies - static v8::Handle proxyConstructor(const v8::Arguments& args); + static void proxyConstructor(const v8::FunctionCallbackInfo& args); static void dispose(); }; diff --git a/android/runtime/v8/src/native/TypeConverter.cpp b/android/runtime/v8/src/native/TypeConverter.cpp index 456e9f0e37d..8e8bce35f47 100644 --- a/android/runtime/v8/src/native/TypeConverter.cpp +++ b/android/runtime/v8/src/native/TypeConverter.cpp @@ -1,9 +1,10 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011-2012 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ +#include #include #include #include @@ -14,73 +15,80 @@ #include "JavaObject.h" #include "ProxyFactory.h" #include "V8Runtime.h" +#include "V8Util.h" #define TAG "TypeConverter" using namespace titanium; +// The incrementing index used to store new persistent functions in our global map. Start at the minimum value possible and increment by one as we go +// Ideally we should "wrap around" when we reach max, but are we really expecting to go through more than 18,446,744,073,709,551,615 functions? +int64_t TypeConverter::functionIndex = std::numeric_limits::min(); +// The global map to hold persistent functions. We use the index as our "pointer" to store and retrieve the function +std::map>> TypeConverter::functions; + /****************************** public methods ******************************/ -jshort TypeConverter::jsNumberToJavaShort(v8::Handle jsNumber) +jshort TypeConverter::jsNumberToJavaShort(v8::Local jsNumber) { return ((jshort) jsNumber->Value()); } -v8::Handle TypeConverter::javaShortToJsNumber(jshort javaShort) +v8::Local TypeConverter::javaShortToJsNumber(v8::Isolate* isolate, jshort javaShort) { - return v8::Number::New((double) javaShort); + return v8::Number::New(isolate, (double) javaShort); } -jint TypeConverter::jsNumberToJavaInt(v8::Handle jsNumber) +jint TypeConverter::jsNumberToJavaInt(v8::Local jsNumber) { return ((jint) jsNumber->Value()); } -v8::Handle TypeConverter::javaIntToJsNumber(jint javaInt) +v8::Local TypeConverter::javaIntToJsNumber(v8::Isolate* isolate, jint javaInt) { - return v8::Number::New((double) javaInt); + return v8::Number::New(isolate, (double) javaInt); } -jlong TypeConverter::jsNumberToJavaLong(v8::Handle jsNumber) +jlong TypeConverter::jsNumberToJavaLong(v8::Local jsNumber) { return ((jlong) jsNumber->Value()); } -v8::Handle TypeConverter::javaLongToJsNumber(jlong javaLong) +v8::Local TypeConverter::javaLongToJsNumber(v8::Isolate* isolate, jlong javaLong) { - return v8::Number::New((double) javaLong); + return v8::Number::New(isolate, (double) javaLong); } -jfloat TypeConverter::jsNumberToJavaFloat(v8::Handle jsNumber) +jfloat TypeConverter::jsNumberToJavaFloat(v8::Local jsNumber) { return ((jfloat) jsNumber->Value()); } -v8::Handle TypeConverter::javaFloatToJsNumber(jfloat javaFloat) +v8::Local TypeConverter::javaFloatToJsNumber(v8::Isolate* isolate, jfloat javaFloat) { - return v8::Number::New((double) javaFloat); + return v8::Number::New(isolate, (double) javaFloat); } -jdouble TypeConverter::jsNumberToJavaDouble(v8::Handle jsNumber) +jdouble TypeConverter::jsNumberToJavaDouble(v8::Local jsNumber) { return ((jdouble) jsNumber->Value()); } -v8::Handle TypeConverter::javaDoubleToJsNumber(jdouble javaDouble) +v8::Local TypeConverter::javaDoubleToJsNumber(v8::Isolate* isolate, jdouble javaDouble) { - return v8::Number::New(javaDouble); + return v8::Number::New(isolate, javaDouble); } -jboolean TypeConverter::jsBooleanToJavaBoolean(v8::Handle jsBoolean) +jboolean TypeConverter::jsBooleanToJavaBoolean(v8::Local jsBoolean) { return (jsBoolean->Value()) == JNI_TRUE; } -v8::Handle TypeConverter::javaBooleanToJsBoolean(jboolean javaBoolean) +v8::Local TypeConverter::javaBooleanToJsBoolean(v8::Isolate* isolate, jboolean javaBoolean) { - return v8::Boolean::New((bool) javaBoolean); + return v8::Boolean::New(isolate, (bool) javaBoolean); } -jstring TypeConverter::jsStringToJavaString(v8::Handle jsString) +jstring TypeConverter::jsStringToJavaString(v8::Local jsString) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { @@ -89,56 +97,54 @@ jstring TypeConverter::jsStringToJavaString(v8::Handle jsString) return TypeConverter::jsStringToJavaString(env, jsString); } -jstring TypeConverter::jsStringToJavaString(JNIEnv *env, v8::Handle jsString) +jstring TypeConverter::jsStringToJavaString(JNIEnv *env, v8::Local jsString) { - v8::String::Value javaString(jsString); - return env->NewString(*javaString, javaString.length()); + titanium::TwoByteValue string(jsString); + return env->NewString(reinterpret_cast(*string), string.length()); } -jstring TypeConverter::jsValueToJavaString(v8::Handle jsValue) +jstring TypeConverter::jsValueToJavaString(v8::Isolate* isolate, v8::Local jsValue) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsValueToJavaString(env, jsValue); + return TypeConverter::jsValueToJavaString(isolate, env, jsValue); } -jstring TypeConverter::jsValueToJavaString(JNIEnv *env, v8::Handle jsValue) +jstring TypeConverter::jsValueToJavaString(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue) { if (jsValue->IsNull()) { return NULL; } - v8::Local jsString = jsValue->ToString(); - v8::String::Value javaString(jsString); - return env->NewString(*javaString, javaString.length()); + return TypeConverter::jsStringToJavaString(env, jsValue->ToString(isolate)); } -v8::Handle TypeConverter::javaStringToJsString(jstring javaString) +v8::Local TypeConverter::javaStringToJsString(v8::Isolate* isolate, jstring javaString) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::String::Empty(isolate); } - return TypeConverter::javaStringToJsString(env, javaString); + return TypeConverter::javaStringToJsString(isolate, env, javaString); } -v8::Handle TypeConverter::javaStringToJsString(JNIEnv *env, jstring javaString) +v8::Local TypeConverter::javaStringToJsString(v8::Isolate* isolate, JNIEnv *env, jstring javaString) { if (!javaString) { - return v8::Null(); + return v8::Null(isolate); } int nativeStringLength = env->GetStringLength(javaString); const jchar *nativeString = env->GetStringChars(javaString, NULL); - v8::Handle jsString = v8::String::New(nativeString, nativeStringLength); + v8::Local jsString = v8::String::NewFromTwoByte(isolate, nativeString, v8::String::kNormalString, nativeStringLength); env->ReleaseStringChars(javaString, nativeString); return jsString; } -jobject TypeConverter::jsDateToJavaDate(v8::Handle jsDate) +jobject TypeConverter::jsDateToJavaDate(v8::Local jsDate) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { @@ -147,70 +153,81 @@ jobject TypeConverter::jsDateToJavaDate(v8::Handle jsDate) return TypeConverter::jsDateToJavaDate(env, jsDate); } -jobject TypeConverter::jsDateToJavaDate(JNIEnv *env, v8::Handle jsDate) +jobject TypeConverter::jsDateToJavaDate(JNIEnv *env, v8::Local jsDate) { - return env->NewObject(JNIUtil::dateClass, JNIUtil::dateInitMethod, (jlong) jsDate->NumberValue()); + return env->NewObject(JNIUtil::dateClass, JNIUtil::dateInitMethod, (jlong) jsDate->ValueOf()); } -jlong TypeConverter::jsDateToJavaLong(v8::Handle jsDate) +jlong TypeConverter::jsDateToJavaLong(v8::Local jsDate) { - return (jlong) jsDate->NumberValue(); + return (jlong) jsDate->ValueOf(); } -v8::Handle TypeConverter::javaDateToJsDate(jobject javaDate) +v8::Local TypeConverter::javaDateToJsDate(v8::Isolate* isolate, jobject javaDate) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Local(); } - return TypeConverter::javaDateToJsDate(env, javaDate); + return TypeConverter::javaDateToJsDate(isolate, env, javaDate); } -v8::Handle TypeConverter::javaDateToJsDate(JNIEnv *env, jobject javaDate) +Local TypeConverter::javaDateToJsDate(Isolate* isolate, JNIEnv *env, jobject javaDate) { jlong epochTime = env->CallLongMethod(javaDate, JNIUtil::dateGetTimeMethod); - return v8::Handle::Cast(v8::Date::New((double) epochTime)); + return TypeConverter::javaLongToJsDate(isolate, epochTime); } -v8::Handle TypeConverter::javaLongToJsDate(jlong javaLong) +Local TypeConverter::javaLongToJsDate(Isolate* isolate, jlong javaLong) { - return v8::Handle::Cast(v8::Date::New((double) javaLong)); + return Date::New(isolate, (double) javaLong).As(); // perversely, the date constructor returns Local so we need to cast it } -jobject TypeConverter::jsObjectToJavaFunction(v8::Handle jsObject) +jobject TypeConverter::jsObjectToJavaFunction(v8::Isolate* isolate, v8::Local jsObject) { JNIEnv *env = JNIScope::getEnv(); if (!env) { return NULL; } - return TypeConverter::jsObjectToJavaFunction(env, jsObject); + return TypeConverter::jsObjectToJavaFunction(isolate, env, jsObject); } -jobject TypeConverter::jsObjectToJavaFunction(JNIEnv *env, v8::Handle jsObject) +jobject TypeConverter::jsObjectToJavaFunction(v8::Isolate* isolate, JNIEnv *env, v8::Local jsObject) { - Persistent jsFunction = Persistent::New(Handle::Cast(jsObject)); + Local func = jsObject.As(); + Persistent> jsFunction(isolate, func); jsFunction.MarkIndependent(); - jlong ptr = (jlong) *jsFunction; + // Place the persistent into some global table with incrementing index, use the index as the "ptr" here + // Then when we re-construct, use the ptr value as index into the table to grab the persistent! + jlong ptr = (jlong) functionIndex; // jlong is signed 64-bit, so int64_t should match up + TypeConverter::functions[functionIndex] = jsFunction; + functionIndex++; + // Java code assumes 0 is null pointer. So we need to skip it. TODO fix this so we don't need to perform this special check? + if (functionIndex == 0) { + functionIndex++; + } + return env->NewObject(JNIUtil::v8FunctionClass, JNIUtil::v8FunctionInitMethod, ptr); } -v8::Handle TypeConverter::javaObjectToJsFunction(jobject javaObject) +v8::Local TypeConverter::javaObjectToJsFunction(Isolate* isolate, jobject javaObject) { JNIEnv *env = JNIScope::getEnv(); if (!env) { - return v8::Handle(); + return v8::Local(); } - return TypeConverter::javaObjectToJsFunction(env, javaObject); + return TypeConverter::javaObjectToJsFunction(isolate, env, javaObject); } -v8::Handle TypeConverter::javaObjectToJsFunction(JNIEnv *env, jobject javaObject) +v8::Local TypeConverter::javaObjectToJsFunction(Isolate* isolate, JNIEnv *env, jobject javaObject) { jlong v8ObjectPointer = env->GetLongField(javaObject, JNIUtil::v8ObjectPtrField); - return v8::Handle(reinterpret_cast(v8ObjectPointer)); + Persistent> persistentV8Object = TypeConverter::functions.at(v8ObjectPointer); + return persistentV8Object.Get(isolate); } -jobjectArray TypeConverter::jsArgumentsToJavaArray(const Arguments& args) +jobjectArray TypeConverter::jsArgumentsToJavaArray(const FunctionCallbackInfo& args) { JNIEnv *env = JNIScope::getEnv(); if (!env) { @@ -219,9 +236,10 @@ jobjectArray TypeConverter::jsArgumentsToJavaArray(const Arguments& args) return TypeConverter::jsArgumentsToJavaArray(env, args); } -jobjectArray TypeConverter::jsArgumentsToJavaArray(JNIEnv *env, const Arguments& args) +jobjectArray TypeConverter::jsArgumentsToJavaArray(JNIEnv *env, const FunctionCallbackInfo& args) { - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); int argCount = args.Length(); jobjectArray javaArgs = env->NewObjectArray(argCount, JNIUtil::objectClass, NULL); @@ -229,7 +247,7 @@ jobjectArray TypeConverter::jsArgumentsToJavaArray(JNIEnv *env, const Arguments& { Local v8Arg = args[i]; bool isNew; - jobject javaArg = jsValueToJavaObject(v8Arg, &isNew); + jobject javaArg = jsValueToJavaObject(isolate, v8Arg, &isNew); env->SetObjectArrayElement(javaArgs, i, javaArg); if (isNew) { @@ -241,23 +259,23 @@ jobjectArray TypeConverter::jsArgumentsToJavaArray(JNIEnv *env, const Arguments& } // call "delete" on the return value otherwise the memory will never be released -v8::Handle * TypeConverter::javaObjectArrayToJsArguments(jobjectArray javaObjectArray, int *length) +Local* TypeConverter::javaObjectArrayToJsArguments(Isolate* isolate, jobjectArray javaObjectArray, int* length) { JNIEnv *env = JNIScope::getEnv(); if (!env) { return NULL; } - return TypeConverter::javaObjectArrayToJsArguments(env, javaObjectArray, length); + return TypeConverter::javaObjectArrayToJsArguments(isolate, env, javaObjectArray, length); } -v8::Handle * TypeConverter::javaObjectArrayToJsArguments(JNIEnv *env, jobjectArray javaObjectArray, int *length) +Local* TypeConverter::javaObjectArrayToJsArguments(Isolate* isolate, JNIEnv *env, jobjectArray javaObjectArray, int* length) { jsize javaArrayLength = env->GetArrayLength(javaObjectArray); - v8::Handle *jsArguments = new v8::Handle[javaArrayLength]; + Local *jsArguments = new Local[javaArrayLength]; for (int i = 0; i < javaArrayLength; i++) { jobject arrayElement = env->GetObjectArrayElement(javaObjectArray, i); - jsArguments[i] = TypeConverter::javaObjectToJsValue(env, arrayElement); + jsArguments[i] = TypeConverter::javaObjectToJsValue(isolate, env, arrayElement); env->DeleteLocalRef(arrayElement); } @@ -265,16 +283,16 @@ v8::Handle * TypeConverter::javaObjectArrayToJsArguments(JNIEnv *env, return jsArguments; } -jarray TypeConverter::jsArrayToJavaArray(v8::Handle jsArray) +jarray TypeConverter::jsArrayToJavaArray(v8::Isolate* isolate, v8::Local jsArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsArrayToJavaArray(env, jsArray); + return TypeConverter::jsArrayToJavaArray(isolate, env, jsArray); } -jarray TypeConverter::jsArrayToJavaArray(JNIEnv *env, v8::Handle jsArray) +jarray TypeConverter::jsArrayToJavaArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray) { int arrayLength = jsArray->Length(); jobjectArray javaArray = env->NewObjectArray(arrayLength, JNIUtil::objectClass, NULL); @@ -287,7 +305,7 @@ jarray TypeConverter::jsArrayToJavaArray(JNIEnv *env, v8::Handle jsAr v8::Local element = jsArray->Get(i); bool isNew; - jobject javaObject = jsValueToJavaObject(element, &isNew); + jobject javaObject = jsValueToJavaObject(isolate, element, &isNew); env->SetObjectArrayElement(javaArray, i, javaObject); if (isNew) { @@ -298,16 +316,16 @@ jarray TypeConverter::jsArrayToJavaArray(JNIEnv *env, v8::Handle jsAr return javaArray; } -jobjectArray TypeConverter::jsArrayToJavaStringArray(v8::Handle jsArray) +jobjectArray TypeConverter::jsArrayToJavaStringArray(v8::Isolate* isolate, v8::Local jsArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsArrayToJavaStringArray(env, jsArray); + return TypeConverter::jsArrayToJavaStringArray(isolate, env, jsArray); } -jobjectArray TypeConverter::jsArrayToJavaStringArray(JNIEnv *env, v8::Handle jsArray) +jobjectArray TypeConverter::jsArrayToJavaStringArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray) { int arrayLength = jsArray->Length(); jobjectArray javaArray = env->NewObjectArray(arrayLength, JNIUtil::stringClass, NULL); @@ -318,7 +336,7 @@ jobjectArray TypeConverter::jsArrayToJavaStringArray(JNIEnv *env, v8::Handle element = jsArray->Get(i); - jstring javaObject = jsStringToJavaString(env, element->ToString()); + jstring javaObject = jsStringToJavaString(env, element->ToString(isolate)); env->SetObjectArrayElement(javaArray, i, javaObject); env->DeleteLocalRef(javaObject); @@ -327,38 +345,38 @@ jobjectArray TypeConverter::jsArrayToJavaStringArray(JNIEnv *env, v8::Handle TypeConverter::javaArrayToJsArray(jbooleanArray javaBooleanArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, jbooleanArray javaBooleanArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Array::New(isolate); } - return TypeConverter::javaArrayToJsArray(env, javaBooleanArray); + return TypeConverter::javaArrayToJsArray(isolate, env, javaBooleanArray); } -v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jbooleanArray javaBooleanArray) +Local TypeConverter::javaArrayToJsArray(Isolate* isolate, JNIEnv *env, jbooleanArray javaBooleanArray) { int arrayLength = env->GetArrayLength(javaBooleanArray); - v8::Handle jsArray = v8::Array::New(arrayLength); + v8::Local jsArray = v8::Array::New(isolate, arrayLength); jboolean *arrayElements = env->GetBooleanArrayElements(javaBooleanArray, 0); for (int i = 0; i < arrayLength; i++) { - jsArray->Set((uint32_t) i, v8::Boolean::New(arrayElements[i])); + jsArray->Set((uint32_t) i, v8::Boolean::New(isolate, arrayElements[i])); } return jsArray; } -jshortArray TypeConverter::jsArrayToJavaShortArray(v8::Handle jsArray) +jshortArray TypeConverter::jsArrayToJavaShortArray(Isolate* isolate, Local jsArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsArrayToJavaShortArray(env, jsArray); + return TypeConverter::jsArrayToJavaShortArray(isolate, env, jsArray); } -jshortArray TypeConverter::jsArrayToJavaShortArray(JNIEnv *env, v8::Handle jsArray) +jshortArray TypeConverter::jsArrayToJavaShortArray(Isolate* isolate, JNIEnv *env, Local jsArray) { int arrayLength = jsArray->Length(); jshortArray javaShortArray = env->NewShortArray(arrayLength); @@ -369,34 +387,34 @@ jshortArray TypeConverter::jsArrayToJavaShortArray(JNIEnv *env, v8::Handle element = jsArray->Get(i); - shortBuffer[i] = TypeConverter::jsNumberToJavaShort(element->ToNumber()); + Local element = jsArray->Get(i); + shortBuffer[i] = TypeConverter::jsNumberToJavaShort(element->ToNumber(isolate)); } env->SetShortArrayRegion(javaShortArray, 0, arrayLength, shortBuffer); return javaShortArray; } -v8::Handle TypeConverter::javaArrayToJsArray(jshortArray javaShortArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, jshortArray javaShortArray) { - return javaShortArrayToJsNumberArray(javaShortArray); + return javaShortArrayToJsNumberArray(isolate, javaShortArray); } -v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jshortArray javaShortArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jshortArray javaShortArray) { - return javaShortArrayToJsNumberArray(env, javaShortArray); + return javaShortArrayToJsNumberArray(isolate, env, javaShortArray); } -jintArray TypeConverter::jsArrayToJavaIntArray(v8::Handle jsArray) +jintArray TypeConverter::jsArrayToJavaIntArray(v8::Isolate* isolate, v8::Local jsArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsArrayToJavaIntArray(env, jsArray); + return TypeConverter::jsArrayToJavaIntArray(isolate, env, jsArray); } -jintArray TypeConverter::jsArrayToJavaIntArray(JNIEnv *env, v8::Handle jsArray) +jintArray TypeConverter::jsArrayToJavaIntArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray) { int arrayLength = jsArray->Length(); jintArray javaIntArray = env->NewIntArray(arrayLength); @@ -408,45 +426,45 @@ jintArray TypeConverter::jsArrayToJavaIntArray(JNIEnv *env, v8::Handle element = jsArray->Get(i); - intBuffer[i] = TypeConverter::jsNumberToJavaInt(element->ToNumber()); + intBuffer[i] = TypeConverter::jsNumberToJavaInt(element->ToNumber(isolate)); } env->SetIntArrayRegion(javaIntArray, 0, arrayLength, intBuffer); return javaIntArray; } -v8::Handle TypeConverter::javaArrayToJsArray(jintArray javaIntArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, jintArray javaIntArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Local(); } - return TypeConverter::javaArrayToJsArray(env, javaIntArray); + return TypeConverter::javaArrayToJsArray(isolate, env, javaIntArray); } -v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jintArray javaIntArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jintArray javaIntArray) { int arrayLength = env->GetArrayLength(javaIntArray); - v8::Handle jsArray = v8::Array::New(arrayLength); + v8::Local jsArray = v8::Array::New(isolate, arrayLength); jint *arrayElements = env->GetIntArrayElements(javaIntArray, 0); for (int i = 0; i < arrayLength; i++) { - jsArray->Set((uint32_t) i, v8::Integer::New(arrayElements[i])); + jsArray->Set((uint32_t) i, v8::Integer::New(isolate, arrayElements[i])); } return jsArray; } -jlongArray TypeConverter::jsArrayToJavaLongArray(v8::Handle jsArray) +jlongArray TypeConverter::jsArrayToJavaLongArray(v8::Isolate* isolate, v8::Local jsArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsArrayToJavaLongArray(env, jsArray); + return TypeConverter::jsArrayToJavaLongArray(isolate, env, jsArray); } -jlongArray TypeConverter::jsArrayToJavaLongArray(JNIEnv *env, v8::Handle jsArray) +jlongArray TypeConverter::jsArrayToJavaLongArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray) { int arrayLength = jsArray->Length(); jlongArray javaLongArray = env->NewLongArray(arrayLength); @@ -458,23 +476,23 @@ jlongArray TypeConverter::jsArrayToJavaLongArray(JNIEnv *env, v8::Handle element = jsArray->Get(i); - longBuffer[i] = TypeConverter::jsNumberToJavaLong(element->ToNumber()); + longBuffer[i] = TypeConverter::jsNumberToJavaLong(element->ToNumber(isolate)); } env->SetLongArrayRegion(javaLongArray, 0, arrayLength, longBuffer); return javaLongArray; } -jfloatArray TypeConverter::jsArrayToJavaFloatArray(v8::Handle jsArray) +jfloatArray TypeConverter::jsArrayToJavaFloatArray(v8::Isolate* isolate, v8::Local jsArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsArrayToJavaFloatArray(env, jsArray); + return TypeConverter::jsArrayToJavaFloatArray(isolate, env, jsArray); } -jfloatArray TypeConverter::jsArrayToJavaFloatArray(JNIEnv *env, v8::Handle jsArray) +jfloatArray TypeConverter::jsArrayToJavaFloatArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray) { int arrayLength = jsArray->Length(); jfloatArray javaFloatArray = env->NewFloatArray(arrayLength); @@ -486,43 +504,43 @@ jfloatArray TypeConverter::jsArrayToJavaFloatArray(JNIEnv *env, v8::Handle element = jsArray->Get(i); - floatBuffer[i] = TypeConverter::jsNumberToJavaFloat(element->ToNumber()); + floatBuffer[i] = TypeConverter::jsNumberToJavaFloat(element->ToNumber(isolate)); } env->SetFloatArrayRegion(javaFloatArray, 0, arrayLength, floatBuffer); return javaFloatArray; } -v8::Handle TypeConverter::javaArrayToJsArray(jlongArray javaLongArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, jlongArray javaLongArray) { - return javaLongArrayToJsNumberArray(javaLongArray); + return javaLongArrayToJsNumberArray(isolate, javaLongArray); } -v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jlongArray javaLongArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jlongArray javaLongArray) { - return javaLongArrayToJsNumberArray(env, javaLongArray); + return javaLongArrayToJsNumberArray(isolate, env, javaLongArray); } -v8::Handle TypeConverter::javaArrayToJsArray(jfloatArray javaFloatArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, jfloatArray javaFloatArray) { - return javaFloatArrayToJsNumberArray(javaFloatArray); + return javaFloatArrayToJsNumberArray(isolate, javaFloatArray); } -v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jfloatArray javaFloatArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jfloatArray javaFloatArray) { - return javaFloatArrayToJsNumberArray(env, javaFloatArray); + return javaFloatArrayToJsNumberArray(isolate, env, javaFloatArray); } -jdoubleArray TypeConverter::jsArrayToJavaDoubleArray(v8::Handle jsArray) +jdoubleArray TypeConverter::jsArrayToJavaDoubleArray(v8::Isolate* isolate, v8::Local jsArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsArrayToJavaDoubleArray(env,jsArray); + return TypeConverter::jsArrayToJavaDoubleArray(isolate, env, jsArray); } -jdoubleArray TypeConverter::jsArrayToJavaDoubleArray(JNIEnv *env, v8::Handle jsArray) +jdoubleArray TypeConverter::jsArrayToJavaDoubleArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray) { int arrayLength = jsArray->Length(); jdoubleArray javaDoubleArray = env->NewDoubleArray(arrayLength); @@ -534,40 +552,40 @@ jdoubleArray TypeConverter::jsArrayToJavaDoubleArray(JNIEnv *env, v8::Handle element = jsArray->Get(i); - doubleBuffer[i] = TypeConverter::jsNumberToJavaDouble(element->ToNumber()); + doubleBuffer[i] = TypeConverter::jsNumberToJavaDouble(element->ToNumber(isolate)); } env->SetDoubleArrayRegion(javaDoubleArray, 0, arrayLength, doubleBuffer); return javaDoubleArray; } -v8::Handle TypeConverter::javaArrayToJsArray(jdoubleArray javaDoubleArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, jdoubleArray javaDoubleArray) { - return javaDoubleArrayToJsNumberArray(javaDoubleArray); + return javaDoubleArrayToJsNumberArray(isolate, javaDoubleArray); } -v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jdoubleArray javaDoubleArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jdoubleArray javaDoubleArray) { - return javaDoubleArrayToJsNumberArray(env, javaDoubleArray); + return javaDoubleArrayToJsNumberArray(isolate, env, javaDoubleArray); } -v8::Handle TypeConverter::javaArrayToJsArray(jobjectArray javaObjectArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, jobjectArray javaObjectArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Array::New(isolate); } - return TypeConverter::javaArrayToJsArray(env, javaObjectArray); + return TypeConverter::javaArrayToJsArray(isolate, env, javaObjectArray); } -v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jobjectArray javaObjectArray) +v8::Local TypeConverter::javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jobjectArray javaObjectArray) { int arrayLength = env->GetArrayLength(javaObjectArray); - v8::Handle jsArray = v8::Array::New(arrayLength); + v8::Local jsArray = v8::Array::New(isolate, arrayLength); for (int i = 0; i < arrayLength; i++) { jobject javaArrayElement = env->GetObjectArrayElement(javaObjectArray, i); - v8::Handle jsArrayElement = TypeConverter::javaObjectToJsValue(env, javaArrayElement); + v8::Local jsArrayElement = TypeConverter::javaObjectToJsValue(isolate, env, javaArrayElement); jsArray->Set((uint32_t) i, jsArrayElement); env->DeleteLocalRef(javaArrayElement); } @@ -577,59 +595,60 @@ v8::Handle TypeConverter::javaArrayToJsArray(JNIEnv *env, jobjectArra // converts js value to java object and recursively converts sub objects if this // object is a container type -jobject TypeConverter::jsValueToJavaObject(v8::Local jsValue, bool *isNew) +jobject TypeConverter::jsValueToJavaObject(v8::Isolate* isolate, v8::Local jsValue, bool *isNew) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsValueToJavaObject(env,jsValue,isNew); + return TypeConverter::jsValueToJavaObject(isolate, env, jsValue, isNew); } -jobject TypeConverter::jsValueToJavaObject(JNIEnv *env, v8::Local jsValue, bool *isNew) +jobject TypeConverter::jsValueToJavaObject(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue, bool *isNew) { if (jsValue->IsNumber()) { *isNew = true; + Local number = jsValue.As(); if (jsValue->IsInt32()) { - jint javaInt = TypeConverter::jsNumberToJavaInt(jsValue->ToNumber()); + jint javaInt = TypeConverter::jsNumberToJavaInt(number); return env->NewObject(JNIUtil::integerClass, JNIUtil::integerInitMethod, javaInt); } - jdouble javaDouble = TypeConverter::jsNumberToJavaDouble(jsValue->ToNumber()); + jdouble javaDouble = TypeConverter::jsNumberToJavaDouble(number); return env->NewObject(JNIUtil::doubleClass, JNIUtil::doubleInitMethod, javaDouble); } else if (jsValue->IsBoolean()) { - jboolean javaBoolean = TypeConverter::jsBooleanToJavaBoolean(jsValue->ToBoolean()); + jboolean javaBoolean = TypeConverter::jsBooleanToJavaBoolean(jsValue.As()); *isNew = true; return env->NewObject(JNIUtil::booleanClass, JNIUtil::booleanInitMethod, javaBoolean); } else if (jsValue->IsString()) { *isNew = true; - return TypeConverter::jsStringToJavaString(env, jsValue->ToString()); + return TypeConverter::jsStringToJavaString(env, jsValue.As()); } else if (jsValue->IsDate()) { - Local date = Local::Cast(jsValue); - return TypeConverter::jsDateToJavaDate(env, date); + return TypeConverter::jsDateToJavaDate(env, jsValue.As()); } else if (jsValue->IsArray()) { *isNew = true; - return TypeConverter::jsArrayToJavaArray(env, v8::Handle::Cast(jsValue)); + return TypeConverter::jsArrayToJavaArray(isolate, env, jsValue.As()); } else if (jsValue->IsFunction()) { *isNew = true; - return TypeConverter::jsObjectToJavaFunction(env, jsValue->ToObject()); + return TypeConverter::jsObjectToJavaFunction(isolate, env, jsValue.As()); } else if (jsValue->IsObject()) { - v8::Handle jsObject = jsValue->ToObject(); + v8::Local jsObject = jsValue.As(); + if (JavaObject::isJavaObject(jsObject)) { *isNew = JavaObject::useGlobalRefs ? false : true; JavaObject *javaObject = JavaObject::Unwrap(jsObject); return javaObject->getJavaObject(); } else { // Unwrap hyperloop JS wrappers to get native java proxy - Handle nativeString = String::New("$native"); + v8::Local nativeString = STRING_NEW(isolate, "$native"); if (jsObject->HasOwnProperty(nativeString)) { v8::Local nativeObject = jsObject->GetRealNamedProperty(nativeString); - jsObject = nativeObject->ToObject(); + jsObject = nativeObject->ToObject(isolate); if (JavaObject::isJavaObject(jsObject)) { *isNew = JavaObject::useGlobalRefs ? false : true; JavaObject *javaObject = JavaObject::Unwrap(jsObject); @@ -637,7 +656,7 @@ jobject TypeConverter::jsValueToJavaObject(JNIEnv *env, v8::Local jsV } } - v8::Handle objectKeys = jsObject->GetOwnPropertyNames(); + v8::Local objectKeys = jsObject->GetOwnPropertyNames(); int numKeys = objectKeys->Length(); *isNew = true; jobject javaHashMap = env->NewObject(JNIUtil::hashMapClass, JNIUtil::hashMapInitMethod, numKeys); @@ -645,9 +664,9 @@ jobject TypeConverter::jsValueToJavaObject(JNIEnv *env, v8::Local jsV for (int i = 0; i < numKeys; i++) { v8::Local jsObjectPropertyKey = objectKeys->Get((uint32_t) i); bool keyIsNew, valueIsNew; - jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyKey, &keyIsNew); + jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(isolate, env, jsObjectPropertyKey, &keyIsNew); v8::Local jsObjectPropertyValue = jsObject->Get(jsObjectPropertyKey); - jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyValue, &valueIsNew); + jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(isolate, env, jsObjectPropertyValue, &valueIsNew); jobject result = env->CallObjectMethod(javaHashMap, JNIUtil::hashMapPutMethod, @@ -675,21 +694,21 @@ jobject TypeConverter::jsValueToJavaObject(JNIEnv *env, v8::Local jsV // converts js object to kroll dict and recursively converts sub objects if this // object is a container type -jobject TypeConverter::jsObjectToJavaKrollDict(v8::Local jsValue, bool *isNew) +jobject TypeConverter::jsObjectToJavaKrollDict(v8::Isolate* isolate, v8::Local jsValue, bool *isNew) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsObjectToJavaKrollDict(env,jsValue,isNew); + return TypeConverter::jsObjectToJavaKrollDict(isolate, env,jsValue,isNew); } -jobject TypeConverter::jsObjectToJavaKrollDict(JNIEnv *env, v8::Local jsValue, bool *isNew) +jobject TypeConverter::jsObjectToJavaKrollDict(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue, bool *isNew) { if (jsValue->IsObject()) { - v8::Handle jsObject = jsValue->ToObject(); - v8::Handle objectKeys = jsObject->GetOwnPropertyNames(); + v8::Local jsObject = jsValue.As(); + v8::Local objectKeys = jsObject->GetOwnPropertyNames(); int numKeys = objectKeys->Length(); *isNew = true; jobject javaKrollDict = env->NewObject(JNIUtil::krollDictClass, JNIUtil::krollDictInitMethod, numKeys); @@ -697,9 +716,9 @@ jobject TypeConverter::jsObjectToJavaKrollDict(JNIEnv *env, v8::Local for (int i = 0; i < numKeys; i++) { v8::Local jsObjectPropertyKey = objectKeys->Get((uint32_t) i); bool keyIsNew, valueIsNew; - jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyKey, &keyIsNew); + jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(isolate, env, jsObjectPropertyKey, &keyIsNew); v8::Local jsObjectPropertyValue = jsObject->Get(jsObjectPropertyKey); - jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyValue, &valueIsNew); + jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(isolate, env, jsObjectPropertyValue, &valueIsNew); jobject result = env->CallObjectMethod(javaKrollDict, JNIUtil::krollDictPutMethod, @@ -726,24 +745,24 @@ jobject TypeConverter::jsObjectToJavaKrollDict(JNIEnv *env, v8::Local // converts js value to java error -jobject TypeConverter::jsValueToJavaError(v8::Local jsValue, bool* isNew) +jobject TypeConverter::jsValueToJavaError(v8::Isolate* isolate, v8::Local jsValue, bool* isNew) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { return NULL; } - return TypeConverter::jsValueToJavaError(env,jsValue,isNew); + return TypeConverter::jsValueToJavaError(isolate, env, jsValue, isNew); } -jobject TypeConverter::jsValueToJavaError(JNIEnv *env, v8::Local jsValue, bool* isNew) +jobject TypeConverter::jsValueToJavaError(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue, bool* isNew) { if (jsValue->IsObject()) { - v8::Handle jsObject = jsValue->ToObject(); + v8::Local jsObject = jsValue.As(); // If it's a java object, we just return null for now. if (!JavaObject::isJavaObject(jsObject)) { - Handle stackString = String::New("stack"), messageString = String::New("message"); + Local stackString = STRING_NEW(isolate, "stack"), messageString = STRING_NEW(isolate, "message"); if (jsObject->HasOwnProperty(stackString) || jsObject->HasOwnProperty(messageString)) { bool keyIsNew, valueIsNew; *isNew = true; @@ -751,14 +770,14 @@ jobject TypeConverter::jsValueToJavaError(JNIEnv *env, v8::Local jsVa v8::Local jsObjectStackProperty = jsObject->GetRealNamedProperty(stackString); return env->NewObject(JNIUtil::krollExceptionClass, JNIUtil::krollExceptionInitMethod, - TypeConverter::jsValueToJavaString(env, jsObjectMessageProperty), TypeConverter::jsValueToJavaString(env, jsObjectStackProperty)); + TypeConverter::jsValueToJavaString(isolate, env, jsObjectMessageProperty), TypeConverter::jsValueToJavaString(isolate, env, jsObjectStackProperty)); } } } else { *isNew = true; return env->NewObject(JNIUtil::krollExceptionClass, JNIUtil::krollExceptionInitMethod, - TypeConverter::jsValueToJavaString(env, jsValue), NULL); + TypeConverter::jsValueToJavaString(isolate, env, jsValue), NULL); } if (!jsValue->IsNull() && !jsValue->IsUndefined()) { @@ -769,9 +788,9 @@ jobject TypeConverter::jsValueToJavaError(JNIEnv *env, v8::Local jsVa // converts java hashmap to js value and recursively converts sub objects if this // object is a container type. If javaObject is NULL, an empty object is created. -v8::Handle TypeConverter::javaHashMapToJsValue(JNIEnv *env, jobject javaObject) +v8::Local TypeConverter::javaHashMapToJsValue(v8::Isolate* isolate, JNIEnv *env, jobject javaObject) { - v8::Handle jsObject = v8::Object::New(); + v8::Local jsObject = v8::Object::New(isolate); if (!javaObject || !env) { return jsObject; } @@ -785,21 +804,17 @@ v8::Handle TypeConverter::javaHashMapToJsValue(JNIEnv *env, jobject for (int i = 0; i < hashMapKeysLength; i++) { jobject javaPairKey = env->GetObjectArrayElement(hashMapKeys, i); - v8::Handle jsPairKey; + v8::Local jsPairKey; if (isStringHashMap) { - jstring javaString = (jstring)javaPairKey; - int nativeStringLength = env->GetStringLength(javaString); - const jchar *nativeString = env->GetStringChars(javaString, NULL); - jsPairKey = v8::String::New(nativeString, nativeStringLength); - env->ReleaseStringChars(javaString, nativeString); + jsPairKey = TypeConverter::javaStringToJsString(isolate, env, (jstring)javaPairKey); } else { - jsPairKey = TypeConverter::javaObjectToJsValue(env, javaPairKey); + jsPairKey = TypeConverter::javaObjectToJsValue(isolate, env, javaPairKey); } jobject javaPairValue = env->CallObjectMethod(javaObject, JNIUtil::hashMapGetMethod, javaPairKey); env->DeleteLocalRef(javaPairKey); - jsObject->Set(jsPairKey, TypeConverter::javaObjectToJsValue(env, javaPairValue)); + jsObject->Set(jsPairKey, TypeConverter::javaObjectToJsValue(isolate, env, javaPairValue)); env->DeleteLocalRef(javaPairValue); } @@ -810,41 +825,41 @@ v8::Handle TypeConverter::javaHashMapToJsValue(JNIEnv *env, jobject // converts java object to js value and recursively converts sub objects if this // object is a container type -v8::Handle TypeConverter::javaObjectToJsValue(jobject javaObject) +Local TypeConverter::javaObjectToJsValue(Isolate* isolate, jobject javaObject) { if (!javaObject) { - return v8::Null(); + return v8::Null(isolate); } JNIEnv *env = JNIScope::getEnv(); if (!env) { - return v8::Handle(); + return v8::Undefined(isolate); } - return TypeConverter::javaObjectToJsValue(env,javaObject); + return TypeConverter::javaObjectToJsValue(isolate, env, javaObject); } -v8::Handle TypeConverter::javaObjectToJsValue(JNIEnv *env, jobject javaObject) +v8::Local TypeConverter::javaObjectToJsValue(v8::Isolate* isolate, JNIEnv *env, jobject javaObject) { if (!javaObject) { - return v8::Null(); + return v8::Null(isolate); } if (env->IsInstanceOf(javaObject, JNIUtil::booleanClass)) { jboolean javaBoolean = env->CallBooleanMethod(javaObject, JNIUtil::booleanBooleanValueMethod); - return javaBoolean ? v8::True() : v8::False(); + return javaBoolean ? v8::True(isolate) : v8::False(isolate); } else if (env->IsInstanceOf(javaObject, JNIUtil::numberClass)) { jdouble javaDouble = env->CallDoubleMethod(javaObject, JNIUtil::numberDoubleValueMethod); - return v8::Number::New((double) javaDouble); + return v8::Number::New(isolate, (double) javaDouble); } else if (env->IsInstanceOf(javaObject, JNIUtil::stringClass)) { - return TypeConverter::javaStringToJsString(env, (jstring) javaObject); + return TypeConverter::javaStringToJsString(isolate, env, (jstring) javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::dateClass)) { - return TypeConverter::javaDateToJsDate(env, javaObject); + return TypeConverter::javaDateToJsDate(isolate, env, javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::hashMapClass)) { - return TypeConverter::javaHashMapToJsValue(env, javaObject); + return TypeConverter::javaHashMapToJsValue(isolate, env, javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::krollProxyClass)) { jobject krollObject = env->GetObjectField(javaObject, JNIUtil::krollProxyKrollObjectField); if (krollObject) { @@ -852,7 +867,8 @@ v8::Handle TypeConverter::javaObjectToJsValue(JNIEnv *env, jobject ja env->DeleteLocalRef(krollObject); if (v8ObjectPointer != 0) { - Persistent v8Object = Persistent((Object *) v8ObjectPointer); + Persistent* persistentV8Object = (Persistent*) v8ObjectPointer; + auto v8Object = (*persistentV8Object).Get(isolate); JavaObject *jo = NativeObject::Unwrap(v8Object); jo->getJavaObject(); return v8Object; @@ -860,56 +876,56 @@ v8::Handle TypeConverter::javaObjectToJsValue(JNIEnv *env, jobject ja } jclass javaObjectClass = env->GetObjectClass(javaObject); - v8::Handle proxyHandle = ProxyFactory::createV8Proxy(javaObjectClass, javaObject); + v8::Local proxyHandle = ProxyFactory::createV8Proxy(isolate, javaObjectClass, javaObject); env->DeleteLocalRef(javaObjectClass); return proxyHandle; } else if (env->IsInstanceOf(javaObject, JNIUtil::v8FunctionClass)) { - return javaObjectToJsFunction(javaObject); + return javaObjectToJsFunction(isolate, javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::objectArrayClass)) { - return javaArrayToJsArray((jobjectArray) javaObject); + return javaArrayToJsArray(isolate, (jobjectArray) javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::shortArrayClass)) { - return javaArrayToJsArray((jshortArray) javaObject); + return javaArrayToJsArray(isolate, (jshortArray) javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::intArrayClass)) { - return javaArrayToJsArray((jintArray) javaObject); + return javaArrayToJsArray(isolate, (jintArray) javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::longArrayClass)) { - return javaArrayToJsArray((jlongArray) javaObject); + return javaArrayToJsArray(isolate, (jlongArray) javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::floatArrayClass)) { - return javaArrayToJsArray((jfloatArray) javaObject); + return javaArrayToJsArray(isolate, (jfloatArray) javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::doubleArrayClass)) { - return javaArrayToJsArray((jdoubleArray) javaObject); + return javaArrayToJsArray(isolate, (jdoubleArray) javaObject); } else if (env->IsInstanceOf(javaObject, JNIUtil::booleanArrayClass)) { - return javaArrayToJsArray((jbooleanArray) javaObject); + return javaArrayToJsArray(isolate, (jbooleanArray) javaObject); } else if (env->IsSameObject(JNIUtil::undefinedObject, javaObject)) { - return v8::Undefined(); + return v8::Undefined(isolate); } JNIUtil::logClassName("!!! Unable to convert unknown Java object class '%s' to Js value !!!", env->GetObjectClass(javaObject), true); - return v8::Handle(); + return v8::Undefined(isolate); } -jobjectArray TypeConverter::jsObjectIndexPropsToJavaArray(v8::Handle jsObject, int start, int length) +jobjectArray TypeConverter::jsObjectIndexPropsToJavaArray(Isolate* isolate, Local jsObject, int start, int length) { JNIEnv *env = JNIScope::getEnv(); if (!env) { return NULL; } - return TypeConverter::jsObjectIndexPropsToJavaArray(env, jsObject, start, length); + return TypeConverter::jsObjectIndexPropsToJavaArray(isolate, env, jsObject, start, length); } -jobjectArray TypeConverter::jsObjectIndexPropsToJavaArray(JNIEnv *env, v8::Handle jsObject, int start, int length) +jobjectArray TypeConverter::jsObjectIndexPropsToJavaArray(Isolate* isolate, JNIEnv *env, Local jsObject, int start, int length) { - HandleScope scope; + HandleScope scope(isolate); int arrayLength = length == 0 ? 0 : length - start; jobjectArray javaArray = env->NewObjectArray(arrayLength, JNIUtil::objectClass, NULL); @@ -919,7 +935,7 @@ jobjectArray TypeConverter::jsObjectIndexPropsToJavaArray(JNIEnv *env, v8::Handl v8::Local prop = jsObject->Get(index); bool isNew; - jobject javaObject = jsValueToJavaObject(prop, &isNew); + jobject javaObject = jsValueToJavaObject(isolate, prop, &isNew); env->SetObjectArrayElement(javaArray, index - start, javaObject); if (isNew) { @@ -934,89 +950,89 @@ jobjectArray TypeConverter::jsObjectIndexPropsToJavaArray(JNIEnv *env, v8::Handl // used mainly by the array conversion methods when converting java numeric types // arrays to to the generic js number type -v8::Handle TypeConverter::javaDoubleArrayToJsNumberArray(jdoubleArray javaDoubleArray) +v8::Local TypeConverter::javaDoubleArrayToJsNumberArray(v8::Isolate* isolate, jdoubleArray javaDoubleArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Array::New(isolate); } - return TypeConverter::javaDoubleArrayToJsNumberArray(env, javaDoubleArray); + return TypeConverter::javaDoubleArrayToJsNumberArray(isolate, env, javaDoubleArray); } -v8::Handle TypeConverter::javaDoubleArrayToJsNumberArray(JNIEnv *env, jdoubleArray javaDoubleArray) +v8::Local TypeConverter::javaDoubleArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jdoubleArray javaDoubleArray) { int arrayLength = env->GetArrayLength(javaDoubleArray); - v8::Handle jsArray = v8::Array::New(arrayLength); + v8::Local jsArray = v8::Array::New(isolate, arrayLength); jdouble *arrayElements = env->GetDoubleArrayElements(javaDoubleArray, 0); for (int i = 0; i < arrayLength; i++) { - jsArray->Set((uint32_t) i, v8::Number::New(arrayElements[i])); + jsArray->Set((uint32_t) i, v8::Number::New(isolate, arrayElements[i])); } env->ReleaseDoubleArrayElements(javaDoubleArray, arrayElements, JNI_ABORT); //Since we were only reading, there is no need to copy back. Thus, Abort. return jsArray; } -v8::Handle TypeConverter::javaLongArrayToJsNumberArray(jlongArray javaLongArray) +v8::Local TypeConverter::javaLongArrayToJsNumberArray(v8::Isolate* isolate, jlongArray javaLongArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Array::New(isolate); } - return TypeConverter::javaLongArrayToJsNumberArray(env, javaLongArray); + return TypeConverter::javaLongArrayToJsNumberArray(isolate, env, javaLongArray); } -v8::Handle TypeConverter::javaLongArrayToJsNumberArray(JNIEnv *env, jlongArray javaLongArray) +v8::Local TypeConverter::javaLongArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jlongArray javaLongArray) { int arrayLength = env->GetArrayLength(javaLongArray); - v8::Handle jsArray = v8::Array::New(arrayLength); + v8::Local jsArray = v8::Array::New(isolate, arrayLength); jlong *arrayElements = env->GetLongArrayElements(javaLongArray, 0); for (int i = 0; i < arrayLength; i++) { - jsArray->Set((uint32_t) i, v8::Number::New(arrayElements[i])); + jsArray->Set((uint32_t) i, v8::Number::New(isolate, arrayElements[i])); } return jsArray; } -v8::Handle TypeConverter::javaFloatArrayToJsNumberArray(jfloatArray javaFloatArray) +v8::Local TypeConverter::javaFloatArrayToJsNumberArray(v8::Isolate* isolate, jfloatArray javaFloatArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Array::New(isolate); } - return TypeConverter::javaFloatArrayToJsNumberArray(env, javaFloatArray); + return TypeConverter::javaFloatArrayToJsNumberArray(isolate, env, javaFloatArray); } -v8::Handle TypeConverter::javaFloatArrayToJsNumberArray(JNIEnv *env, jfloatArray javaFloatArray) +v8::Local TypeConverter::javaFloatArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jfloatArray javaFloatArray) { int arrayLength = env->GetArrayLength(javaFloatArray); - v8::Handle jsArray = v8::Array::New(arrayLength); + v8::Local jsArray = v8::Array::New(isolate, arrayLength); jfloat *arrayElements = env->GetFloatArrayElements(javaFloatArray, 0); for (int i = 0; i < arrayLength; i++) { - jsArray->Set((uint32_t) i, v8::Number::New(arrayElements[i])); + jsArray->Set((uint32_t) i, v8::Number::New(isolate, arrayElements[i])); } env->ReleaseFloatArrayElements(javaFloatArray, arrayElements, JNI_ABORT); return jsArray; } -v8::Handle TypeConverter::javaShortArrayToJsNumberArray(jshortArray javaShortArray) +v8::Local TypeConverter::javaShortArrayToJsNumberArray(v8::Isolate* isolate, jshortArray javaShortArray) { JNIEnv *env = JNIScope::getEnv(); if (env == NULL) { - return v8::Handle(); + return v8::Array::New(isolate); } - return TypeConverter::javaShortArrayToJsNumberArray(env, javaShortArray); + return TypeConverter::javaShortArrayToJsNumberArray(isolate, env, javaShortArray); } -v8::Handle TypeConverter::javaShortArrayToJsNumberArray(JNIEnv *env, jshortArray javaShortArray) +v8::Local TypeConverter::javaShortArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jshortArray javaShortArray) { int arrayLength = env->GetArrayLength(javaShortArray); - v8::Handle jsArray = v8::Array::New(arrayLength); + v8::Local jsArray = v8::Array::New(isolate, arrayLength); jshort *arrayElements = env->GetShortArrayElements(javaShortArray, 0); for (int i = 0; i < arrayLength; i++) { - jsArray->Set((uint32_t) i, v8::Number::New(arrayElements[i])); + jsArray->Set((uint32_t) i, v8::Number::New(isolate, arrayElements[i])); } env->ReleaseShortArrayElements(javaShortArray, arrayElements, JNI_ABORT); return jsArray; diff --git a/android/runtime/v8/src/native/TypeConverter.h b/android/runtime/v8/src/native/TypeConverter.h index aa32e417572..f7fa07725ce 100644 --- a/android/runtime/v8/src/native/TypeConverter.h +++ b/android/runtime/v8/src/native/TypeConverter.h @@ -1,6 +1,6 @@ /* * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -8,6 +8,7 @@ #ifndef TYPE_CONVERTER_H #define TYPE_CONVERTER_H +#include #include #include @@ -15,187 +16,191 @@ namespace titanium { class TypeConverter { public: + // Our global map of "pointers" to persistent functions + static std::map>> functions; + //The incrementing key to store the persistent functions + static int64_t functionIndex; + // short convert methods - static jshort jsNumberToJavaShort(v8::Handle jsNumber); - static v8::Handle javaShortToJsNumber(jshort javaShort); - - static inline jshort jsNumberToJavaShort(JNIEnv *env, v8::Handle jsNumber) { + static jshort jsNumberToJavaShort(v8::Local jsNumber); + static v8::Local javaShortToJsNumber(v8::Isolate* isolate, jshort javaShort); + + static inline jshort jsNumberToJavaShort(JNIEnv *env, v8::Local jsNumber) { return jsNumberToJavaShort(jsNumber); } - static inline v8::Handle javaShortToJsNumber(JNIEnv *env, jshort javaShort) { - return javaShortToJsNumber(javaShort); + static inline v8::Local javaShortToJsNumber(v8::Isolate* isolate, JNIEnv *env, jshort javaShort) { + return javaShortToJsNumber(isolate, javaShort); } // int convert methods - static jint jsNumberToJavaInt(v8::Handle jsNumber); - static v8::Handle javaIntToJsNumber(jint javaInt); + static jint jsNumberToJavaInt(v8::Local jsNumber); + static v8::Local javaIntToJsNumber(v8::Isolate* isolate, jint javaInt); - static inline jint jsNumberToJavaInt(JNIEnv *env, v8::Handle jsNumber) { + static inline jint jsNumberToJavaInt(JNIEnv *env, v8::Local jsNumber) { return jsNumberToJavaInt(jsNumber); } - static inline v8::Handle javaIntToJsNumber(JNIEnv *env, jint javaInt) { - return javaIntToJsNumber(javaInt); + static inline v8::Local javaIntToJsNumber(v8::Isolate* isolate, JNIEnv *env, jint javaInt) { + return javaIntToJsNumber(isolate, javaInt); } // long convert methods - static jlong jsNumberToJavaLong(v8::Handle jsNumber); - static v8::Handle javaLongToJsNumber(jlong javaLong); + static jlong jsNumberToJavaLong(v8::Local jsNumber); + static v8::Local javaLongToJsNumber(v8::Isolate* isolate, jlong javaLong); - static inline jlong jsNumberToJavaLong(JNIEnv *env, v8::Handle jsNumber) { + static inline jlong jsNumberToJavaLong(JNIEnv *env, v8::Local jsNumber) { return jsNumberToJavaLong(jsNumber); } - static inline v8::Handle javaLongToJsNumber(JNIEnv *env, jlong javaLong) { - return javaLongToJsNumber(javaLong); + static inline v8::Local javaLongToJsNumber(v8::Isolate* isolate, JNIEnv *env, jlong javaLong) { + return javaLongToJsNumber(isolate, javaLong); } // float convert methods - static jfloat jsNumberToJavaFloat(v8::Handle jsNumber); - static v8::Handle javaFloatToJsNumber(jfloat javaFloat); + static jfloat jsNumberToJavaFloat(v8::Local jsNumber); + static v8::Local javaFloatToJsNumber(v8::Isolate* isolate, jfloat javaFloat); - static inline jfloat jsNumberToJavaFloat(JNIEnv *env, v8::Handle jsNumber) { + static inline jfloat jsNumberToJavaFloat(JNIEnv *env, v8::Local jsNumber) { return jsNumberToJavaFloat(jsNumber); } - static inline v8::Handle javaFloatToJsNumber(JNIEnv *env, jfloat javaFloat) { - return javaFloatToJsNumber(javaFloat); + static inline v8::Local javaFloatToJsNumber(v8::Isolate* isolate, JNIEnv *env, jfloat javaFloat) { + return javaFloatToJsNumber(isolate, javaFloat); } // double convert methods - static jdouble jsNumberToJavaDouble(v8::Handle jsNumber); - static v8::Handle javaDoubleToJsNumber(jdouble javaDouble); + static jdouble jsNumberToJavaDouble(v8::Local jsNumber); + static v8::Local javaDoubleToJsNumber(v8::Isolate* isolate, jdouble javaDouble); - static inline jdouble jsNumberToJavaDouble(JNIEnv *env, v8::Handle jsNumber) { + static inline jdouble jsNumberToJavaDouble(JNIEnv *env, v8::Local jsNumber) { return jsNumberToJavaDouble(jsNumber); } - static inline v8::Handle javaDoubleToJsNumber(JNIEnv *env, jdouble javaDouble) { - return javaDoubleToJsNumber(javaDouble); + static inline v8::Local javaDoubleToJsNumber(v8::Isolate* isolate, JNIEnv *env, jdouble javaDouble) { + return javaDoubleToJsNumber(isolate, javaDouble); } // boolean convert methods - static jboolean jsBooleanToJavaBoolean(v8::Handle jsBoolean); - static v8::Handle javaBooleanToJsBoolean(jboolean javaBoolean); + static jboolean jsBooleanToJavaBoolean(v8::Local jsBoolean); + static v8::Local javaBooleanToJsBoolean(v8::Isolate* isolate, jboolean javaBoolean); - static inline jboolean jsBooleanToJavaBoolean(JNIEnv *env, v8::Handle jsBoolean) { + static inline jboolean jsBooleanToJavaBoolean(JNIEnv *env, v8::Local jsBoolean) { return jsBooleanToJavaBoolean(jsBoolean); } - static inline v8::Handle javaBooleanToJsBoolean(JNIEnv *env, jboolean javaBoolean) { - return javaBooleanToJsBoolean(javaBoolean); + static inline v8::Local javaBooleanToJsBoolean(v8::Isolate* isolate, JNIEnv *env, jboolean javaBoolean) { + return javaBooleanToJsBoolean(isolate, javaBoolean); } // string convert methods - static jstring jsStringToJavaString(v8::Handle jsString); - static jstring jsValueToJavaString(v8::Handle jsValue); - static v8::Handle javaStringToJsString(jstring javaString); + static jstring jsStringToJavaString(v8::Local jsString); + static jstring jsValueToJavaString(v8::Isolate* isolate, v8::Local jsValue); + static v8::Local javaStringToJsString(v8::Isolate* isolate, jstring javaString); - static jstring jsStringToJavaString(JNIEnv *env, v8::Handle jsString); - static jstring jsValueToJavaString(JNIEnv *env, v8::Handle jsValue); - static v8::Handle javaStringToJsString(JNIEnv *env, jstring javaString); + static jstring jsStringToJavaString(JNIEnv *env, v8::Local jsString); + static jstring jsValueToJavaString(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue); + static v8::Local javaStringToJsString(v8::Isolate* isolate, JNIEnv *env, jstring javaString); // date convert methods - static jobject jsDateToJavaDate(v8::Handle jsDate); - static jlong jsDateToJavaLong(v8::Handle jsDate); - static v8::Handle javaDateToJsDate(jobject); - static v8::Handle javaLongToJsDate(jlong); - - static jobject jsDateToJavaDate(JNIEnv *env, v8::Handle jsDate); - static v8::Handle javaDateToJsDate(JNIEnv *env, jobject); - static inline jlong jsDateToJavaLong(JNIEnv *env, v8::Handle jsDate) { + static jobject jsDateToJavaDate(v8::Local jsDate); + static jlong jsDateToJavaLong(v8::Local jsDate); + static v8::Local javaDateToJsDate(v8::Isolate* isolate, jobject); + static v8::Local javaLongToJsDate(v8::Isolate* isolate, jlong); + + static jobject jsDateToJavaDate(JNIEnv *env, v8::Local jsDate); + static v8::Local javaDateToJsDate(v8::Isolate* isolate, JNIEnv *env, jobject); + static inline jlong jsDateToJavaLong(JNIEnv *env, v8::Local jsDate) { return jsDateToJavaLong(jsDate); } - static inline v8::Handle javaLongToJsDate(JNIEnv *env, jlong javaLong) { - return javaLongToJsDate(javaLong); + static inline v8::Local javaLongToJsDate(v8::Isolate* isolate, JNIEnv *env, jlong javaLong) { + return javaLongToJsDate(isolate, javaLong); } // function convert methods - static jobject jsObjectToJavaFunction(v8::Handle jsObject); - static v8::Handle javaObjectToJsFunction(jobject javaObject); + static jobject jsObjectToJavaFunction(v8::Isolate* isolate, v8::Local jsObject); + static v8::Local javaObjectToJsFunction(v8::Isolate* isolate, jobject javaObject); - static jobject jsObjectToJavaFunction(JNIEnv *env, v8::Handle jsObject); - static v8::Handle javaObjectToJsFunction(JNIEnv *env, jobject javaObject); + static jobject jsObjectToJavaFunction(v8::Isolate* isolate, JNIEnv *env, v8::Local jsObject); + static v8::Local javaObjectToJsFunction(v8::Isolate* isolate, JNIEnv *env, jobject javaObject); // arguments conversion - static jobjectArray jsArgumentsToJavaArray(const v8::Arguments& args); + static jobjectArray jsArgumentsToJavaArray(const v8::FunctionCallbackInfo& args); // BIG FUCKING WARNING!! make sure you call "delete" on the return value otherwise the // you have introduced a memory leak and the world will end. plzkthksbye - static v8::Handle * javaObjectArrayToJsArguments(jobjectArray javaObjectArray, int *length); + static v8::Local * javaObjectArrayToJsArguments(v8::Isolate* isolate, jobjectArray javaObjectArray, int *length); - static jobjectArray jsArgumentsToJavaArray(JNIEnv *env, const v8::Arguments& args); - static v8::Handle * javaObjectArrayToJsArguments(JNIEnv *env, jobjectArray javaObjectArray, int *length); + static jobjectArray jsArgumentsToJavaArray(JNIEnv *env, const v8::FunctionCallbackInfo& args); + static v8::Local * javaObjectArrayToJsArguments(v8::Isolate* isolate, JNIEnv *env, jobjectArray javaObjectArray, int *length); // array convert methods - static jarray jsArrayToJavaArray(v8::Handle jsArray); - static jobjectArray jsArrayToJavaStringArray(v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(jbooleanArray javaBooleanArray); - static jshortArray jsArrayToJavaShortArray(v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(jshortArray javaShortArray); - static jintArray jsArrayToJavaIntArray(v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(jintArray javaIntArray); - static jlongArray jsArrayToJavaLongArray(v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(jlongArray javaLongArray); - static jfloatArray jsArrayToJavaFloatArray(v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(jfloatArray javaFloatArray); - static jdoubleArray jsArrayToJavaDoubleArray(v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(jdoubleArray javaDoubleArray); - static v8::Handle javaArrayToJsArray(jobjectArray javaObjectArray); - - static jarray jsArrayToJavaArray(JNIEnv *env, v8::Handle jsArray); - static jobjectArray jsArrayToJavaStringArray(JNIEnv *env, v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(JNIEnv *env, jbooleanArray javaBooleanArray); - static jshortArray jsArrayToJavaShortArray(JNIEnv *env, v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(JNIEnv *env, jshortArray javaShortArray); - static jintArray jsArrayToJavaIntArray(JNIEnv *env, v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(JNIEnv *env, jintArray javaIntArray); - static jlongArray jsArrayToJavaLongArray(JNIEnv *env, v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(JNIEnv *env, jlongArray javaLongArray); - static jfloatArray jsArrayToJavaFloatArray(JNIEnv *env, v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(JNIEnv *env, jfloatArray javaFloatArray); - static jdoubleArray jsArrayToJavaDoubleArray(JNIEnv *env, v8::Handle jsArray); - static v8::Handle javaArrayToJsArray(JNIEnv *env, jdoubleArray javaDoubleArray); - static v8::Handle javaArrayToJsArray(JNIEnv *env, jobjectArray javaObjectArray); + static jarray jsArrayToJavaArray(v8::Isolate* isolate, v8::Local jsArray); + static jobjectArray jsArrayToJavaStringArray(v8::Isolate* isolate, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, jbooleanArray javaBooleanArray); + static jshortArray jsArrayToJavaShortArray(v8::Isolate* isolate, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, jshortArray javaShortArray); + static jintArray jsArrayToJavaIntArray(v8::Isolate* isolate, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, jintArray javaIntArray); + static jlongArray jsArrayToJavaLongArray(v8::Isolate* isolate, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, jlongArray javaLongArray); + static jfloatArray jsArrayToJavaFloatArray(v8::Isolate* isolate, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, jfloatArray javaFloatArray); + static jdoubleArray jsArrayToJavaDoubleArray(v8::Isolate* isolate, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, jdoubleArray javaDoubleArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, jobjectArray javaObjectArray); + + static jarray jsArrayToJavaArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray); + static jobjectArray jsArrayToJavaStringArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jbooleanArray javaBooleanArray); + static jshortArray jsArrayToJavaShortArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jshortArray javaShortArray); + static jintArray jsArrayToJavaIntArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jintArray javaIntArray); + static jlongArray jsArrayToJavaLongArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jlongArray javaLongArray); + static jfloatArray jsArrayToJavaFloatArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jfloatArray javaFloatArray); + static jdoubleArray jsArrayToJavaDoubleArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jdoubleArray javaDoubleArray); + static v8::Local javaArrayToJsArray(v8::Isolate* isolate, JNIEnv *env, jobjectArray javaObjectArray); // object convert methods - static inline jobject jsValueToJavaObject(v8::Local jsValue) { + static inline jobject jsValueToJavaObject(v8::Isolate* isolate, v8::Local jsValue) { bool isNew; - return jsValueToJavaObject(jsValue, &isNew); + return jsValueToJavaObject(isolate, jsValue, &isNew); } - static inline jobject jsValueToJavaObject(JNIEnv *env, v8::Local jsValue) { + static inline jobject jsValueToJavaObject(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue) { bool isNew; - return jsValueToJavaObject(env, jsValue, &isNew); + return jsValueToJavaObject(isolate, env, jsValue, &isNew); } - - static jobject jsValueToJavaError(v8::Local jsValue, bool *isNew); - static jobject jsValueToJavaObject(v8::Local jsValue, bool *isNew); - static v8::Handle javaObjectToJsValue(jobject javaObject); - static jobject jsObjectToJavaKrollDict(v8::Local jsValue, bool *isNew); - static jobject jsValueToJavaError(JNIEnv *env, v8::Local jsValue, bool *isNew); - static jobject jsValueToJavaObject(JNIEnv *env, v8::Local jsValue, bool *isNew); - static v8::Handle javaHashMapToJsValue(JNIEnv *env, jobject javaObject); - static v8::Handle javaObjectToJsValue(JNIEnv *env, jobject javaObject); - static jobject jsObjectToJavaKrollDict(JNIEnv *env, v8::Local jsValue, bool *isNew); + static jobject jsValueToJavaError(v8::Isolate* isolate, v8::Local jsValue, bool *isNew); + static jobject jsValueToJavaObject(v8::Isolate* isolate, v8::Local jsValue, bool *isNew); + static v8::Local javaObjectToJsValue(v8::Isolate* isolate, jobject javaObject); + static jobject jsObjectToJavaKrollDict(v8::Isolate* isolate, v8::Local jsValue, bool *isNew); + + static jobject jsValueToJavaError(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue, bool *isNew); + static jobject jsValueToJavaObject(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue, bool *isNew); + static v8::Local javaHashMapToJsValue(v8::Isolate* isolate, JNIEnv *env, jobject javaObject); + static v8::Local javaObjectToJsValue(v8::Isolate* isolate, JNIEnv *env, jobject javaObject); + static jobject jsObjectToJavaKrollDict(v8::Isolate* isolate, JNIEnv *env, v8::Local jsValue, bool *isNew); // Convert a JS object's indexed properties to a Java object array. // Starts at index zero and continues until length is reached. - static jobjectArray jsObjectIndexPropsToJavaArray(v8::Handle jsObject, int start, int length); + static jobjectArray jsObjectIndexPropsToJavaArray(v8::Isolate* isolate, v8::Local jsObject, int start, int length); - static jobjectArray jsObjectIndexPropsToJavaArray(JNIEnv *env, v8::Handle jsObject, int start, int length); + static jobjectArray jsObjectIndexPropsToJavaArray(v8::Isolate* isolate, JNIEnv *env, v8::Local jsObject, int start, int length); private: // utility methods - static v8::Handle javaDoubleArrayToJsNumberArray(jdoubleArray javaDoubleArray); - static v8::Handle javaLongArrayToJsNumberArray(jlongArray javaLongArray); - static v8::Handle javaFloatArrayToJsNumberArray(jfloatArray javaFloatArray); - static v8::Handle javaShortArrayToJsNumberArray(jshortArray javaShortArray); + static v8::Local javaDoubleArrayToJsNumberArray(v8::Isolate* isolate, jdoubleArray javaDoubleArray); + static v8::Local javaLongArrayToJsNumberArray(v8::Isolate* isolate, jlongArray javaLongArray); + static v8::Local javaFloatArrayToJsNumberArray(v8::Isolate* isolate, jfloatArray javaFloatArray); + static v8::Local javaShortArrayToJsNumberArray(v8::Isolate* isolate, jshortArray javaShortArray); - static v8::Handle javaDoubleArrayToJsNumberArray(JNIEnv *env, jdoubleArray javaDoubleArray); - static v8::Handle javaLongArrayToJsNumberArray(JNIEnv *env, jlongArray javaLongArray); - static v8::Handle javaFloatArrayToJsNumberArray(JNIEnv *env, jfloatArray javaFloatArray); - static v8::Handle javaShortArrayToJsNumberArray(JNIEnv *env, jshortArray javaShortArray); + static v8::Local javaDoubleArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jdoubleArray javaDoubleArray); + static v8::Local javaLongArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jlongArray javaLongArray); + static v8::Local javaFloatArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jfloatArray javaFloatArray); + static v8::Local javaShortArrayToJsNumberArray(v8::Isolate* isolate, JNIEnv *env, jshortArray javaShortArray); }; } #endif - diff --git a/android/runtime/v8/src/native/V8Function.cpp b/android/runtime/v8/src/native/V8Function.cpp index 1a1ba27d155..97a370e1be9 100644 --- a/android/runtime/v8/src/native/V8Function.cpp +++ b/android/runtime/v8/src/native/V8Function.cpp @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -30,22 +30,27 @@ extern "C" { JNIEXPORT jobject JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Function_nativeInvoke( JNIEnv *env, jobject caller, jlong thisPointer, jlong functionPointer, jobjectArray functionArguments) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); titanium::JNIScope jniScope(env); - Local thisObject = Local((Object *) thisPointer); + // construct this from pointer + Persistent* persistentJSObject = (Persistent*) thisPointer; + Local thisObject = persistentJSObject->Get(V8Runtime::v8_isolate); - // construct function from pointer - Function *jsFunction = (Function *) functionPointer; + // construct function from "pointer" - we used to use pointers to Persistent to re-construct Functions + // But that was a _BAD_ idea because V8 moves handles around as GC runs, resulting in the stored memory address being invalid + // So now we basically use a global map with an incrementing key to store the functions, where the "pointer" is the indx the function is stored under in the map. + Persistent> persistentJSFunction = TypeConverter::functions.at(functionPointer); + Local jsFunction = persistentJSFunction.Get(V8Runtime::v8_isolate); // create function arguments int length; - v8::Handle *jsFunctionArguments = - TypeConverter::javaObjectArrayToJsArguments(env, functionArguments, &length); + v8::Local* jsFunctionArguments = + TypeConverter::javaObjectArrayToJsArguments(V8Runtime::v8_isolate, env, functionArguments, &length); // call into the JS function with the provided argument - TryCatch tryCatch; - v8::Local object = jsFunction->Call(thisObject, length, jsFunctionArguments); + TryCatch tryCatch(V8Runtime::v8_isolate); + v8::MaybeLocal object = jsFunction->Call(V8Runtime::v8_isolate->GetCurrentContext(), thisObject, length, jsFunctionArguments); // make sure to delete the arguments since the arguments array is built on the heap if (jsFunctionArguments) { @@ -53,29 +58,32 @@ JNIEXPORT jobject JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Function_nati } if (tryCatch.HasCaught()) { - V8Util::openJSErrorDialog(tryCatch); - V8Util::reportException(tryCatch); + V8Util::openJSErrorDialog(V8Runtime::v8_isolate, tryCatch); + V8Util::reportException(V8Runtime::v8_isolate, tryCatch); + return NULL; + } else if (object.IsEmpty()) { return NULL; } - + bool isNew; - return TypeConverter::jsValueToJavaObject(env, object, &isNew); + return TypeConverter::jsValueToJavaObject(V8Runtime::v8_isolate, env, object.ToLocalChecked(), &isNew); } JNIEXPORT void JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Function_nativeRelease (JNIEnv *env, jclass clazz, jlong ptr) { - ASSERT(ptr != 0); - Persistent function = Persistent((Function*) ptr); - // Release the JS function so it can be collected. - function.Dispose(); - function.Clear(); + // We guard against "bad" pointers by searching by index before releasing + auto it = TypeConverter::functions.find(ptr); + if (it != TypeConverter::functions.end()) { + auto jsFunction = it->second; + jsFunction.Reset(); + TypeConverter::functions.erase(it); + } } #ifdef __cplusplus } #endif - diff --git a/android/runtime/v8/src/native/V8Object.cpp b/android/runtime/v8/src/native/V8Object.cpp index d866c7ee23e..7ceca176b31 100644 --- a/android/runtime/v8/src/native/V8Object.cpp +++ b/android/runtime/v8/src/native/V8Object.cpp @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2009-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -32,30 +32,31 @@ JNIEXPORT void JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Object_nativeInitObject (JNIEnv *env, jclass clazz, jclass proxyClass, jobject proxyObject) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); JNIScope jniScope(env); - ProxyFactory::createV8Proxy(proxyClass, proxyObject); + ProxyFactory::createV8Proxy(V8Runtime::v8_isolate, proxyClass, proxyObject); } JNIEXPORT void JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Object_nativeSetProperty (JNIEnv *env, jobject object, jlong ptr, jstring name, jobject value) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); titanium::JNIScope jniScope(env); - Handle jsObject; + Local jsObject; if (ptr != 0) { - jsObject = Persistent((Object *) ptr); + Persistent* persistentV8Object = (Persistent*) ptr; + jsObject = persistentV8Object->Get(V8Runtime::v8_isolate); } else { - jsObject = TypeConverter::javaObjectToJsValue(env, object)->ToObject(); + jsObject = TypeConverter::javaObjectToJsValue(V8Runtime::v8_isolate, env, object).As(); } - Handle properties = jsObject->Get(Proxy::propertiesSymbol)->ToObject(); - Handle jsName = TypeConverter::javaStringToJsString(env, name); + Local properties = jsObject->Get(titanium::Proxy::propertiesSymbol.Get(V8Runtime::v8_isolate)).As(); + Local jsName = TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, name); - Handle jsValue = TypeConverter::javaObjectToJsValue(env, value); + Local jsValue = TypeConverter::javaObjectToJsValue(V8Runtime::v8_isolate, env, value); properties->Set(jsName, jsValue); } @@ -64,63 +65,66 @@ JNIEXPORT jboolean JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Object_nativeFireEvent (JNIEnv *env, jobject jEmitter, jlong ptr, jobject jsource, jlong sourcePtr, jstring event, jobject data, jboolean bubble, jboolean reportSuccess, jint code, jstring errorMessage) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); JNIScope jniScope(env); - Handle jsEvent = TypeConverter::javaStringToJsString(env, event); + Local jsEvent = TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, event); #ifdef TI_DEBUG - String::Utf8Value eventName(jsEvent); + titanium::Utf8Value eventName(jsEvent); LOGV(TAG, "firing event \"%s\"", *eventName); #endif - Handle emitter; + Local emitter; if (ptr != 0) { - emitter = Persistent((Object *) ptr); + Persistent* persistentV8Object = (Persistent*) ptr; + emitter = persistentV8Object->Get(V8Runtime::v8_isolate); } else { - emitter = TypeConverter::javaObjectToJsValue(env, jEmitter)->ToObject(); + emitter = TypeConverter::javaObjectToJsValue(V8Runtime::v8_isolate, env, jEmitter).As(); } - Handle fireEventValue = emitter->Get(EventEmitter::emitSymbol); + Local fireEventValue = emitter->Get(EventEmitter::emitSymbol.Get(V8Runtime::v8_isolate)); if (!fireEventValue->IsFunction()) { return JNI_FALSE; } - Handle source; + Local source; if ((jsource == NULL) || (jsource == jEmitter)) { source = emitter; } else if (sourcePtr != 0) { - source = Persistent((Object *) sourcePtr); + Persistent* persistentV8Object = (Persistent*) sourcePtr; + source = persistentV8Object->Get(V8Runtime::v8_isolate); } else { - source = TypeConverter::javaObjectToJsValue(env, jsource)->ToObject(); + source = TypeConverter::javaObjectToJsValue(V8Runtime::v8_isolate, env, jsource).As(); } - Handle fireEvent = Handle::Cast(fireEventValue->ToObject()); + Local fireEvent = fireEventValue.As(); - Handle jsData = TypeConverter::javaHashMapToJsValue(env, data); + Local jsData = TypeConverter::javaHashMapToJsValue(V8Runtime::v8_isolate, env, data); - jsData->Set(String::NewSymbol("bubbles"), TypeConverter::javaBooleanToJsBoolean(bubble)); + jsData->Set(NEW_SYMBOL(V8Runtime::v8_isolate, "bubbles"), TypeConverter::javaBooleanToJsBoolean(V8Runtime::v8_isolate, bubble)); - jsData->Set(String::NewSymbol("source"), source); + jsData->Set(NEW_SYMBOL(V8Runtime::v8_isolate, "source"), source); if (reportSuccess || code != 0) { - jsData->Set(String::NewSymbol("success"), TypeConverter::javaBooleanToJsBoolean(code == 0)); - jsData->Set(String::NewSymbol("code"), TypeConverter::javaIntToJsNumber(code)); + jsData->Set(NEW_SYMBOL(V8Runtime::v8_isolate, "success"), TypeConverter::javaBooleanToJsBoolean(V8Runtime::v8_isolate, code == 0)); + jsData->Set(NEW_SYMBOL(V8Runtime::v8_isolate, "code"), TypeConverter::javaIntToJsNumber(V8Runtime::v8_isolate, code)); } - + if (errorMessage != NULL) { - jsData->Set(String::NewSymbol("error"), TypeConverter::javaStringToJsString(env, errorMessage)); + jsData->Set(NEW_SYMBOL(V8Runtime::v8_isolate, "error"), TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, errorMessage)); } - Handle result; - TryCatch tryCatch; - Handle args[] = { jsEvent, jsData }; - result = fireEvent->Call(emitter, 2, args); + TryCatch tryCatch(V8Runtime::v8_isolate); + Local args[] = { jsEvent, jsData }; + MaybeLocal result = fireEvent->Call(V8Runtime::v8_isolate->GetCurrentContext(), emitter, 2, args); if (tryCatch.HasCaught()) { - V8Util::openJSErrorDialog(tryCatch); - V8Util::reportException(tryCatch); - } else if (result->IsTrue()) { + V8Util::openJSErrorDialog(V8Runtime::v8_isolate, tryCatch); + V8Util::reportException(V8Runtime::v8_isolate, tryCatch); + } else if (result.IsEmpty()) { + return JNI_FALSE; + } else if (result.ToLocalChecked()->IsTrue()) { return JNI_TRUE; } return JNI_FALSE; @@ -130,49 +134,54 @@ JNIEXPORT jobject JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Object_nativeCallProperty (JNIEnv* env, jclass clazz, jlong ptr, jstring propertyName, jobjectArray args) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); JNIScope jniScope(env); - Handle jsPropertyName = TypeConverter::javaStringToJsString(env, propertyName); - Persistent object = Persistent((Object*) ptr); + Local jsPropertyName = TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, propertyName); + + Persistent* persistentV8Object = (Persistent*) ptr; + Local object = persistentV8Object->Get(V8Runtime::v8_isolate); Local property = object->Get(jsPropertyName); if (!property->IsFunction()) { return JNIUtil::undefinedObject; } int argc = 0; - Handle* argv = NULL; + Local* argv = NULL; if (args) { - argv = TypeConverter::javaObjectArrayToJsArguments(args, &argc); + argv = TypeConverter::javaObjectArrayToJsArguments(V8Runtime::v8_isolate, args, &argc); } - TryCatch tryCatch; - Local function = Local::Cast(property); - Local returnValue = function->Call(object, argc, argv); + TryCatch tryCatch(V8Runtime::v8_isolate); + Local function = property.As(); + MaybeLocal returnValue = function->Call(V8Runtime::v8_isolate->GetCurrentContext(), object, argc, argv); if (argv) { delete[] argv; } if (tryCatch.HasCaught()) { - V8Util::openJSErrorDialog(tryCatch); - V8Util::reportException(tryCatch); + V8Util::openJSErrorDialog(V8Runtime::v8_isolate, tryCatch); + V8Util::reportException(V8Runtime::v8_isolate, tryCatch); + return JNIUtil::undefinedObject; + } else if (returnValue.IsEmpty()) { return JNIUtil::undefinedObject; } bool isNew; - return TypeConverter::jsValueToJavaObject(env, returnValue, &isNew); + return TypeConverter::jsValueToJavaObject(V8Runtime::v8_isolate, env, returnValue.ToLocalChecked(), &isNew); } JNIEXPORT jboolean JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Object_nativeRelease (JNIEnv *env, jclass clazz, jlong refPointer) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); JNIScope jniScope(env); if (refPointer) { - Persistent handle((Object *)refPointer); + Persistent* persistentV8Object = (Persistent*) refPointer; + Local handle = persistentV8Object->Get(V8Runtime::v8_isolate); JavaObject *javaObject = NativeObject::Unwrap(handle); if (javaObject && javaObject->isDetached()) { delete javaObject; @@ -187,34 +196,35 @@ JNIEXPORT void JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Object_nativeSetWindow (JNIEnv *env, jobject javaKrollWindow, jlong ptr, jobject javaWindow) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); titanium::JNIScope jniScope(env); - Handle jsKrollWindow; + Local jsKrollWindow; if (ptr != 0) { - jsKrollWindow = Persistent((Object *) ptr); + Persistent* persistentV8Object = (Persistent*) ptr; + jsKrollWindow = persistentV8Object->Get(V8Runtime::v8_isolate); } else { - jsKrollWindow = TypeConverter::javaObjectToJsValue(env, javaKrollWindow)->ToObject(); + jsKrollWindow = TypeConverter::javaObjectToJsValue(V8Runtime::v8_isolate, env, javaKrollWindow).As(); } - Handle setWindowValue = jsKrollWindow->Get(String::New("setWindow")); + Local setWindowValue = jsKrollWindow->Get(STRING_NEW(V8Runtime::v8_isolate, "setWindow")); if (!setWindowValue->IsFunction()) { return; } - Handle setWindow = Handle::Cast(setWindowValue->ToObject()); + Local setWindow = setWindowValue.As(); - Handle jsWindow = TypeConverter::javaObjectToJsValue(env, javaWindow); + Local jsWindow = TypeConverter::javaObjectToJsValue(V8Runtime::v8_isolate, env, javaWindow); - TryCatch tryCatch; + TryCatch tryCatch(V8Runtime::v8_isolate); if (!jsWindow->IsNull()) { - Handle args[] = { jsWindow }; - setWindow->Call(jsKrollWindow, 1, args); + Local args[] = { jsWindow }; + setWindow->Call(V8Runtime::v8_isolate->GetCurrentContext(), jsKrollWindow, 1, args); } if (tryCatch.HasCaught()) { - V8Util::openJSErrorDialog(tryCatch); - V8Util::reportException(tryCatch); + V8Util::openJSErrorDialog(V8Runtime::v8_isolate, tryCatch); + V8Util::reportException(V8Runtime::v8_isolate, tryCatch); } } diff --git a/android/runtime/v8/src/native/V8Runtime.cpp b/android/runtime/v8/src/native/V8Runtime.cpp index 53104c886bb..b325e01ae2a 100644 --- a/android/runtime/v8/src/native/V8Runtime.cpp +++ b/android/runtime/v8/src/native/V8Runtime.cpp @@ -1,6 +1,6 @@ /** * Appcelerator Titanium Mobile - * Copyright (c) 2011-2012 by Appcelerator, Inc. All Rights Reserved. + * Copyright (c) 2011-2016 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "AndroidUtil.h" @@ -35,92 +36,138 @@ namespace titanium { Persistent V8Runtime::globalContext; Persistent V8Runtime::krollGlobalObject; Persistent V8Runtime::moduleContexts; +Persistent V8Runtime::moduleObject; +Persistent V8Runtime::runModuleFunction; jobject V8Runtime::javaInstance; +Platform* V8Runtime::platform = nullptr; +Isolate* V8Runtime::v8_isolate = nullptr; bool V8Runtime::debuggerEnabled = false; bool V8Runtime::DBG = false; +bool V8Runtime::initialized = false; + +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); } +}; /* static */ void V8Runtime::collectWeakRef(Persistent ref, void *parameter) { jobject v8Object = (jobject) parameter; - ref.Dispose(); + ref.Reset(); JNIScope::getEnv()->DeleteGlobalRef(v8Object); } +Local V8Runtime::Global() +{ + return krollGlobalObject.Get(v8_isolate); +} + +Local V8Runtime::GlobalContext() +{ + return globalContext.Get(v8_isolate); +} + +Local V8Runtime::ModuleObject() +{ + return moduleObject.Get(v8_isolate); +} + +Local V8Runtime::RunModuleFunction() +{ + return runModuleFunction.Get(v8_isolate); +} + +Local V8Runtime::ModuleContexts() +{ + return moduleContexts.Get(v8_isolate); +} + // Minimalistic logging function for internal JS -static Handle krollLog(const Arguments& args) +static void krollLog(const FunctionCallbackInfo& args) { - HandleScope scope; + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); uint32_t len = args.Length(); if (len < 2) { - return JSException::Error("log: missing required tag and message arguments"); + JSException::Error(isolate, "log: missing required tag and message arguments"); + return; } - Handle tag = args[0]->ToString(); - Handle message = args[1]->ToString(); + Local tag = args[0].As(); + Local message = args[1].As(); + Local space = STRING_NEW(isolate, " "); for (uint32_t i = 2; i < len; ++i) { - message = String::Concat(String::Concat(message, String::New(" ")), args[i]->ToString()); + message = String::Concat(String::Concat(message, space), args[i].As()); } - String::Utf8Value tagValue(tag); - String::Utf8Value messageValue(message); + titanium::Utf8Value tagValue(tag); + titanium::Utf8Value messageValue(message); __android_log_print(ANDROID_LOG_DEBUG, *tagValue, *messageValue); - - return Undefined(); } /* static */ -void V8Runtime::bootstrap(Local global) +void V8Runtime::bootstrap(Local context) { - EventEmitter::initTemplate(); + Isolate* isolate = context->GetIsolate(); + EventEmitter::initTemplate(context); - krollGlobalObject = Persistent::New(Object::New()); - moduleContexts = Persistent::New(Array::New()); + Local global = Object::New(isolate); + krollGlobalObject.Reset(isolate, global); + Local mc = Array::New(isolate); + moduleContexts.Reset(isolate, mc); - KrollBindings::initFunctions(krollGlobalObject); + KrollBindings::initFunctions(global, context); - DEFINE_METHOD(krollGlobalObject, "log", krollLog); - DEFINE_TEMPLATE(krollGlobalObject, "EventEmitter", EventEmitter::constructorTemplate); + SetMethod(isolate, global, "log", krollLog); + // Move this into the EventEmitter::initTemplate call? + Local eect = Local::New(isolate, EventEmitter::constructorTemplate); + global->Set(NEW_SYMBOL(isolate, "EventEmitter"), eect->GetFunction()); - krollGlobalObject->Set(String::NewSymbol("runtime"), String::New("v8")); - krollGlobalObject->Set(String::NewSymbol("DBG"), v8::Boolean::New(V8Runtime::DBG)); - krollGlobalObject->Set(String::NewSymbol("moduleContexts"), moduleContexts); + global->Set(NEW_SYMBOL(isolate, "runtime"), STRING_NEW(isolate, "v8")); + global->Set(NEW_SYMBOL(isolate, "DBG"), v8::Boolean::New(isolate, V8Runtime::DBG)); + global->Set(NEW_SYMBOL(isolate, "moduleContexts"), mc); LOG_TIMER(TAG, "Executing kroll.js"); - TryCatch tryCatch; - Handle result = V8Util::executeString(KrollBindings::getMainSource(), String::New("ti:/kroll.js")); + TryCatch tryCatch(isolate); + Local result = V8Util::executeString(isolate, KrollBindings::getMainSource(isolate), STRING_NEW(isolate, "ti:/kroll.js")); if (tryCatch.HasCaught()) { - V8Util::reportException(tryCatch, true); + V8Util::reportException(isolate, tryCatch, true); } if (!result->IsFunction()) { LOGF(TAG, "kroll.js result is not a function"); - V8Util::reportException(tryCatch, true); + V8Util::reportException(isolate, tryCatch, true); } - Handle mainFunction = Handle::Cast(result); - Local args[] = { Local::New(krollGlobalObject) }; - mainFunction->Call(global, 1, args); + Local mainFunction = result.As(); + Local args[] = { global }; + mainFunction->Call(context, context->Global(), 1, args); if (tryCatch.HasCaught()) { - V8Util::reportException(tryCatch, true); + V8Util::reportException(isolate, tryCatch, true); LOGE(TAG, "Caught exception while bootstrapping Kroll"); } } -static void logV8Exception(Handle msg, Handle data) +static void logV8Exception(Local msg, Local data) { - HandleScope scope; + HandleScope scope(V8Runtime::v8_isolate); // Log reason and location of the error. - LOGD(TAG, *String::Utf8Value(msg->Get())); + LOGD(TAG, *titanium::Utf8Value(msg->Get())); LOGD(TAG, "%s @ %d >>> %s", - *String::Utf8Value(msg->GetScriptResourceName()), + *titanium::Utf8Value(msg->GetScriptResourceName()), msg->GetLineNumber(), - *String::Utf8Value(msg->GetSourceLine())); + *titanium::Utf8Value(msg->GetSourceLine())); } static jmethodID dispatchDebugMessage = NULL; @@ -150,19 +197,25 @@ using namespace titanium; */ JNIEXPORT void JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Runtime_nativeInit(JNIEnv *env, jobject self, jboolean useGlobalRefs, jint debuggerPort, jboolean DBG, jboolean profilerEnabled) { + if (!V8Runtime::initialized) { + // Initialize V8. + V8::InitializeICU(); + // TODO Enable this when we use snapshots? + //V8::InitializeExternalStartupData(argv[0]); + V8Runtime::platform = platform::CreateDefaultPlatform(); + V8::InitializePlatform(V8Runtime::platform); + V8::Initialize(); + V8Runtime::initialized = true; + } + if (profilerEnabled) { char* argv[] = { const_cast(""), const_cast("--expose-gc") }; int argc = sizeof(argv)/sizeof(*argv); V8::SetFlagsFromCommandLine(&argc, argv, false); } - HandleScope scope; titanium::JNIScope jniScope(env); - // Log all uncaught V8 exceptions. - V8::AddMessageListener(logV8Exception); - V8::SetCaptureStackTraceForUncaughtExceptions(true); - JavaObject::useGlobalRefs = useGlobalRefs; V8Runtime::debuggerEnabled = debuggerPort >= 0; V8Runtime::DBG = DBG; @@ -170,26 +223,43 @@ JNIEXPORT void JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Runtime_nativeIn V8Runtime::javaInstance = env->NewGlobalRef(self); JNIUtil::initCache(); - Persistent context = Context::New(); + Isolate* isolate; + if (V8Runtime::v8_isolate == nullptr) { + // Create a new Isolate and make it the current one. + ArrayBufferAllocator allocator; + Isolate::CreateParams create_params; + create_params.array_buffer_allocator = &allocator; + isolate = Isolate::New(create_params); + + V8Runtime::v8_isolate = isolate; + Isolate::Scope isolate_scope(isolate); + + // Log all uncaught V8 exceptions. + V8::AddMessageListener(&logV8Exception); + V8::SetCaptureStackTraceForUncaughtExceptions(true); + } else { + isolate = V8Runtime::v8_isolate; + } + + HandleScope scope(isolate); + Local context = Context::New(isolate); context->Enter(); - V8Runtime::globalContext = context; - V8Runtime::bootstrap(context->Global()); + V8Runtime::globalContext.Reset(isolate, context); + V8Runtime::bootstrap(context); if (V8Runtime::debuggerEnabled) { jclass v8RuntimeClass = env->FindClass("org/appcelerator/kroll/runtime/v8/V8Runtime"); dispatchDebugMessage = env->GetMethodID(v8RuntimeClass, "dispatchDebugMessages", "()V"); - Debug::SetDebugMessageDispatchHandler(dispatchHandler); - Debug::EnableAgent("titanium", debuggerPort, true); + // FIXME Fix up debugger! + //Debug::SetMessageHandler(dispatchHandler); + //Debug::EnableAgent("titanium", debuggerPort, true); } - LOG_HEAP_STATS(TAG); + LOG_HEAP_STATS(isolate, TAG); } -static Persistent moduleObject; -static Persistent runModuleFunction; - /* * Class: org_appcelerator_kroll_runtime_v8_V8Runtime * Method: nativeRunModule @@ -198,57 +268,56 @@ static Persistent runModuleFunction; JNIEXPORT void JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Runtime_nativeRunModule (JNIEnv *env, jobject self, jstring source, jstring filename, jobject activityProxy) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); titanium::JNIScope jniScope(env); - if (moduleObject.IsEmpty()) { - moduleObject = Persistent::New( - V8Runtime::krollGlobalObject->Get(String::New("Module"))->ToObject()); + if (V8Runtime::moduleObject.IsEmpty()) { + Local module = V8Runtime::Global()->Get(STRING_NEW(V8Runtime::v8_isolate, "Module")).As(); + V8Runtime::moduleObject.Reset(V8Runtime::v8_isolate, module); - runModuleFunction = Persistent::New( - Handle::Cast(moduleObject->Get(String::New("runModule")))); + V8Runtime::runModuleFunction.Reset(V8Runtime::v8_isolate, + module->Get(STRING_NEW(V8Runtime::v8_isolate, "runModule")).As()); } - Handle jsSource = TypeConverter::javaStringToJsString(env, source); - Handle jsFilename = TypeConverter::javaStringToJsString(env, filename); - Handle jsActivity = TypeConverter::javaObjectToJsValue(env, activityProxy); - - Handle args[] = { jsSource, jsFilename, jsActivity }; - TryCatch tryCatch; + Local jsSource = TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, source); + Local jsFilename = TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, filename); + Local jsActivity = TypeConverter::javaObjectToJsValue(V8Runtime::v8_isolate, env, activityProxy); - runModuleFunction->Call(moduleObject, 3, args); + Local args[] = { jsSource, jsFilename, jsActivity }; + TryCatch tryCatch(V8Runtime::v8_isolate); + V8Runtime::RunModuleFunction()->Call(V8Runtime::v8_isolate->GetCurrentContext(), V8Runtime::ModuleObject(), 3, args); if (tryCatch.HasCaught()) { - V8Util::openJSErrorDialog(tryCatch); - V8Util::reportException(tryCatch, true); + V8Util::openJSErrorDialog(V8Runtime::v8_isolate, tryCatch); + V8Util::reportException(V8Runtime::v8_isolate, tryCatch, true); } } JNIEXPORT jobject JNICALL Java_org_appcelerator_kroll_runtime_v8_V8Runtime_nativeEvalString (JNIEnv *env, jobject self, jstring source, jstring filename) { - ENTER_V8(V8Runtime::globalContext); + HandleScope scope(V8Runtime::v8_isolate); titanium::JNIScope jniScope(env); - Handle jsSource = TypeConverter::javaStringToJsString(env, source); + Local jsSource = TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, source); if (jsSource.IsEmpty() || !jsSource->IsString()) { LOGE(TAG, "Error converting Javascript string, aborting evalString"); return NULL; } - Handle jsFilename = TypeConverter::javaStringToJsString(env, filename); + Local jsFilename = TypeConverter::javaStringToJsString(V8Runtime::v8_isolate, env, filename); - TryCatch tryCatch; - Handle