diff --git a/src/assets/app/mainpage.js b/src/assets/app/mainpage.js index 99e23de0f..d5cd0175f 100644 --- a/src/assets/app/mainpage.js +++ b/src/assets/app/mainpage.js @@ -12,10 +12,10 @@ require("./tests/stringConversionTests"); require("./tests/testsForTypescript"); require("./tests/testGC"); require("./tests/testsMemoryManagement"); - require("./tests/testIfAbleToRunExternalFile"); - require("./tests/finalFieldsSetTests"); +require("./tests/extendedClassesTests"); + var MainActivity = com.tns.NativeScriptActivity.extend("MainActivity", { onCreate: function() { diff --git a/src/assets/app/tests/extendedClassesTests.js b/src/assets/app/tests/extendedClassesTests.js new file mode 100644 index 000000000..971e96d7b --- /dev/null +++ b/src/assets/app/tests/extendedClassesTests.js @@ -0,0 +1,79 @@ +var Assert = function(condition, failMessage) { + if (condition == false) { + fail(failMessage); + } +} + +var Instance_with_no_extension_shouldnt_use_previously_defined_implementation_object = function() { + var button = new com.tns.tests.Button1.extend({ + toString: function () { + return "overriden toString method of chronometer instance"; + }, + getIMAGE_ID_PROP: function () { + return "overriden getIMAGE_ID_PROP method on button"; + } + }); + var labelToString = button.toString(); + var labelgetIMAGE_ID_PROP = button.getIMAGE_ID_PROP(); + // + + var button1 = new com.tns.tests.Button1(); + var labelToString1 = button1.toString(); + var labelgetIMAGE_ID_PROP1 = button1.getIMAGE_ID_PROP(); + + + Assert((labelToString !== labelToString1) && (labelgetIMAGE_ID_PROP !== labelgetIMAGE_ID_PROP1), "Instance_with_no_extension_it_shouldnt_use_previously_defined_implementation_object FAILED! Labels need to be different"); +} + +var Instance_with_extension_shouldnt_use_previously_defined_implementation_object = function() { + var button = new com.tns.tests.Button1.extend({ + toString: function () { + return "overriden toString method of button instance"; + }, + getIMAGE_ID_PROP: function () { + return "overriden getIMAGE_ID_PROP method on button"; + } + }); + var labelToString = button.toString(); + var labelgetIMAGE_ID_PROP = button.getIMAGE_ID_PROP(); + // + + var button1 = new com.tns.tests.Button1.extend({ + toString: function () { + return "overriden toString method of button1 instance "; + }, + getIMAGE_ID_PROP: function () { + return "overriden getIMAGE_ID_PROP method on button1"; + } + }); + var labelToString1 = button1.toString(); + var labelgetIMAGE_ID_PROP1 = button1.getIMAGE_ID_PROP(); + + + Assert((labelToString !== labelToString1) && (labelgetIMAGE_ID_PROP !== labelgetIMAGE_ID_PROP1), "Instance_with_no_extension_it_shouldnt_use_previously_defined_implementation_object FAILED! Labels need to be different"); +} + +var Newly_created_instances_should_behave_the_same_and_not_use_previously_defined_implementation_objects = function() { + + var button1 = new com.tns.tests.Button1(); + var labelgetIMAGE_ID_PROP1 = button1.getIMAGE_ID_PROP(); + + // + var button = new com.tns.tests.Button1.extend({ + getIMAGE_ID_PROP: function () { + return "overriden getIMAGE_ID_PROP method on button"; + } + }); + var labelgetIMAGE_ID_PROP = button.getIMAGE_ID_PROP(); + // + + var button2 = new com.tns.tests.Button1(); + var labelgetIMAGE_ID_PROP2 = button2.getIMAGE_ID_PROP(); + + Assert(labelgetIMAGE_ID_PROP1 === labelgetIMAGE_ID_PROP2, "Instance_with_no_extension_it_shouldnt_use_previously_defined_implementation_object FAILED! Labels need to be different"); + +} + +Instance_with_no_extension_shouldnt_use_previously_defined_implementation_object(); +Instance_with_extension_shouldnt_use_previously_defined_implementation_object(); +Newly_created_instances_should_behave_the_same_and_not_use_previously_defined_implementation_objects(); diff --git a/src/assets/app/tests/tests.js b/src/assets/app/tests/tests.js index a38d9a5f8..36bb605e2 100644 --- a/src/assets/app/tests/tests.js +++ b/src/assets/app/tests/tests.js @@ -305,10 +305,6 @@ var When_calling_toString_on_an_java_object_that_has_overriden_toString_in_js_it } var When_extending_a_class_two_times_without_second_implementation_object = function() { - - Log("//TODO: NOT WORKING: FAILS with button1Label=button1, button2Label=button1"); - return; - Log("TEST: When_extending_a_class_two_times_without_second_implementation_object"); var MyButton = com.tns.tests.Button1.extend("MyButton257", { diff --git a/src/jni/MetadataNode.cpp b/src/jni/MetadataNode.cpp index a66c26fdf..e454ce572 100644 --- a/src/jni/MetadataNode.cpp +++ b/src/jni/MetadataNode.cpp @@ -992,8 +992,6 @@ void MetadataNode::ExtendCallMethodHandler(const v8::FunctionCallbackInfoSetHiddenValue(V8StringConstants::GetTSuper(), Boolean::New(isolate, true)); @@ -1005,13 +1003,19 @@ void MetadataNode::ExtendCallMethodHandler(const v8::FunctionCallbackInfoSet(V8StringConstants::GetPrototype(), classProxy); - auto extendedClass = node->CreateExtendedClassProxy(isolate, classProxy, implementationObject, ConvertToV8String(extendNameAndLocation)); + Local extendedClass = node->CreateExtendedClassProxy(isolate, implementationObject, ConvertToV8String(extendNameAndLocation)); + + auto classProxyPersistent = new Persistent(isolate, extendedClass); + DEBUG_WRITE("CreateExtendedClassProxy: ExtendedClassProxy for %s created id:%d", node->m_name.c_str(), extendedClass->GetIdentityHash()); + s_classProxies[fullClassName] = classProxyPersistent; + + V8SetHiddenValue(extendedClass, "t::ext", implementationObject); s_usedExtendNames[fullClassName] = 1; DEBUG_WRITE("ExtendsCallMethodHandler: created ExtendedClassProxy on %s, Id: %d", currExtClass.c_str(), extendedClass->GetIdentityHash()); args.GetReturnValue().Set(extendedClass); } -Handle MetadataNode::CreateExtendedClassProxy(Isolate *isolate, const Handle& classProxy, const Handle& implementationObject, const Handle& name) +Handle MetadataNode::CreateExtendedClassProxy(Isolate *isolate, const Handle& implementationObject, const Handle& name) { EscapableHandleScope handleScope(isolate); diff --git a/src/jni/MetadataNode.h b/src/jni/MetadataNode.h index 18ee74f90..d30c97148 100644 --- a/src/jni/MetadataNode.h +++ b/src/jni/MetadataNode.h @@ -155,7 +155,7 @@ namespace tns v8::Handle CreatePackageProxy(v8::Isolate *isolate); v8::Handle CreateClassProxy(v8::Isolate *isolate, bool isClass); - v8::Handle CreateExtendedClassProxy(v8::Isolate *isolate, const v8::Handle& classProxy, const v8::Handle& implementationObject, const v8::Handle& name); + v8::Handle CreateExtendedClassProxy(v8::Isolate *isolate, const v8::Handle& implementationObject, const v8::Handle& name); v8::Handle CreateStaticClassProxy(v8::Isolate *isolate); v8::Handle CreateFunction(const v8::Handle& thiz, const std::vector& candidates); diff --git a/src/jni/ObjectManager.cpp b/src/jni/ObjectManager.cpp index da6313985..e5a8d3830 100644 --- a/src/jni/ObjectManager.cpp +++ b/src/jni/ObjectManager.cpp @@ -244,8 +244,8 @@ string ObjectManager::GetClassName(jclass clazz) JEnv env; jclass javaLangClass = env.FindClass("java/lang/Class"); - jmethodID getCanonicalNameId = env.GetMethodID(javaLangClass, "getName", "()Ljava/lang/String;"); - JniLocalRef javaCanonicalName(env.CallObjectMethod(clazz, getCanonicalNameId)); + jmethodID getNameId = env.GetMethodID(javaLangClass, "getName", "()Ljava/lang/String;"); + JniLocalRef javaCanonicalName(env.CallObjectMethod(clazz, getNameId)); string className = ArgConverter::jstringToString(javaCanonicalName); diff --git a/src/jni/com_tns_Platform.cpp b/src/jni/com_tns_Platform.cpp index 0ab0b49de..5fc6de16d 100644 --- a/src/jni/com_tns_Platform.cpp +++ b/src/jni/com_tns_Platform.cpp @@ -330,7 +330,7 @@ extern "C" jobject Java_com_tns_Platform_callJSMethodNative(JNIEnv *_env, jobjec return javaObject; } -extern "C" jobjectArray Java_com_tns_Platform_createJSInstanceNative(JNIEnv *_env, jobject obj, jobject javaObject, jint javaObjectID, jstring canonicalName, jboolean createActivity, jobjectArray packagedCreationArgs) +extern "C" jobjectArray Java_com_tns_Platform_createJSInstanceNative(JNIEnv *_env, jobject obj, jobject javaObject, jint javaObjectID, jstring className, jboolean createActivity, jobjectArray packagedCreationArgs) { DEBUG_WRITE("createJSInstanceNative called"); @@ -341,8 +341,8 @@ extern "C" jobjectArray Java_com_tns_Platform_createJSInstanceNative(JNIEnv *_en // TODO: Do we need a TryCatch here? It is currently not used anywhere // TryCatch tc; - string existingClassCanonicalName = ArgConverter::jstringToString(canonicalName); - string jniName = Util::ConvertFromCanonicalToJniName(existingClassCanonicalName); + string existingClassName = ArgConverter::jstringToString(className); + string jniName = Util::ConvertFromCanonicalToJniName(existingClassName); Handle jsInstance; Handle implementationObject; Handle classProxy; @@ -390,15 +390,17 @@ extern "C" jobjectArray Java_com_tns_Platform_createJSInstanceNative(JNIEnv *_en } else { - DEBUG_WRITE("createJSInstanceNative class %s", jniName.c_str()); - classProxy = MetadataNode::GetExistingClassProxy(jniName); + string proxyClassName = objectManager->GetClassName(javaObject); + + DEBUG_WRITE("createJSInstanceNative class %s", proxyClassName.c_str()); + classProxy = MetadataNode::GetExistingClassProxy(proxyClassName); if (classProxy.IsEmpty()) { string nativeScriptBindingPrefix("com/tns/gen/"); - if (Util::StartsWith(jniName, nativeScriptBindingPrefix)) + if (Util::StartsWith(proxyClassName, nativeScriptBindingPrefix)) { - jniName = jniName.substr(nativeScriptBindingPrefix.length()); - classProxy = MetadataNode::GetExistingClassProxy(jniName); + proxyClassName = proxyClassName.substr(nativeScriptBindingPrefix.length()); + classProxy = MetadataNode::GetExistingClassProxy(proxyClassName); } if (classProxy.IsEmpty()) { diff --git a/src/src/com/tns/Platform.java b/src/src/com/tns/Platform.java index caf428304..9dde7b50f 100644 --- a/src/src/com/tns/Platform.java +++ b/src/src/com/tns/Platform.java @@ -387,15 +387,15 @@ private static String[] createJSInstance(Object instance, Object... args) Object[] packagedArgs = packageArgs(args); - String canonicalName = instance.getClass().getCanonicalName(); + String className = instance.getClass().getName(); boolean isGeneratedProxy = instance instanceof NativeScriptHashCodeProvider; boolean createActivity = instance instanceof Activity; if (isGeneratedProxy && !createActivity) { - canonicalName = instance.getClass().getSuperclass().getCanonicalName(); + className = instance.getClass().getSuperclass().getName(); } - String[] methodOverrides = createJSInstanceNative(instance, javaObjectID, canonicalName, createActivity, packagedArgs); + String[] methodOverrides = createJSInstanceNative(instance, javaObjectID, className, createActivity, packagedArgs); if (IsLogEnabled) { @@ -700,11 +700,11 @@ public static Object callJSMethod(Object javaObject, String methodName, boolean Integer javaObjectID = getJavaObjectID(javaObject); if (javaObjectID == null) { - if (IsLogEnabled) Log.e(DEFAULT_LOG_TAG, "Platform.CallJSMethod: calling js method " + methodName + " with javaObjectID " + javaObjectID + " type=" + ((javaObject != null) ? javaObject.getClass().getCanonicalName() : "null")); + if (IsLogEnabled) Log.e(DEFAULT_LOG_TAG, "Platform.CallJSMethod: calling js method " + methodName + " with javaObjectID " + javaObjectID + " type=" + ((javaObject != null) ? javaObject.getClass().getName() : "null")); APP_FAIL("Application failed"); } - if (IsLogEnabled) Log.d(DEFAULT_LOG_TAG, "Platform.CallJSMethod: calling js method " + methodName + " with javaObjectID " + javaObjectID + " type=" + ((javaObject != null) ? javaObject.getClass().getCanonicalName() : "null")); + if (IsLogEnabled) Log.d(DEFAULT_LOG_TAG, "Platform.CallJSMethod: calling js method " + methodName + " with javaObjectID " + javaObjectID + " type=" + ((javaObject != null) ? javaObject.getClass().getName() : "null")); Object result = dispatchCallJSMethodNative(javaObjectID, methodName, isConstructor, delay, args); diff --git a/src/src/com/tns/tests/MyClassBase.java b/src/src/com/tns/tests/MyClassBase.java index b0b21510e..a54e56d35 100644 --- a/src/src/com/tns/tests/MyClassBase.java +++ b/src/src/com/tns/tests/MyClassBase.java @@ -4,6 +4,6 @@ public class MyClassBase { public static String getName() { - return MyClassBase.class.getCanonicalName(); + return MyClassBase.class.getName(); } }