Skip to content

Commit 187e8fd

Browse files
petekanevPlamen5kov
authored andcommitted
fix(runtime-binding-generator): address the changes in the class name format with shorter class names and support for typescript class extend location
1 parent b39015f commit 187e8fd

File tree

6 files changed

+64
-49
lines changed

6 files changed

+64
-49
lines changed

test-app/runtime/src/main/cpp/CallbackHandlers.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ void CallbackHandlers::Init(Isolate* isolate) {
3232
assert(RUNTIME_CLASS != nullptr);
3333

3434
RESOLVE_CLASS_METHOD_ID = env.GetMethodID(RUNTIME_CLASS, "resolveClass",
35-
"(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Z)Ljava/lang/Class;");
35+
"(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Z)Ljava/lang/Class;");
3636
assert(RESOLVE_CLASS_METHOD_ID != nullptr);
3737

3838
CURRENT_OBJECTID_FIELD_ID = env.GetFieldID(RUNTIME_CLASS, "currentObjectId", "I");
@@ -67,7 +67,8 @@ bool CallbackHandlers::RegisterInstance(Isolate* isolate, const Local<Object>& j
6767
const std::string& fullClassName,
6868
const ArgsWrapper& argWrapper,
6969
const Local<Object>& implementationObject,
70-
bool isInterface) {
70+
bool isInterface,
71+
const std::string& baseClassName) {
7172
bool success;
7273

7374
DEBUG_WRITE("RegisterInstance called for '%s'", fullClassName.c_str());
@@ -77,7 +78,7 @@ bool CallbackHandlers::RegisterInstance(Isolate* isolate, const Local<Object>& j
7778

7879
JEnv env;
7980

80-
jclass generatedJavaClass = ResolveClass(isolate, fullClassName, implementationObject,
81+
jclass generatedJavaClass = ResolveClass(isolate, baseClassName, fullClassName, implementationObject,
8182
isInterface);
8283

8384
int javaObjectID = objectManager->GenerateNewObjectID();
@@ -123,15 +124,16 @@ bool CallbackHandlers::RegisterInstance(Isolate* isolate, const Local<Object>& j
123124
return success;
124125
}
125126

126-
jclass CallbackHandlers::ResolveClass(Isolate* isolate, const string& fullClassname,
127+
jclass CallbackHandlers::ResolveClass(Isolate* isolate, const string& baseClassName, const string& fullClassName,
127128
const Local<Object>& implementationObject, bool isInterface) {
128129
JEnv env;
129-
jclass globalRefToGeneratedClass = env.CheckForClassInCache(fullClassname);
130+
jclass globalRefToGeneratedClass = env.CheckForClassInCache(fullClassName);
130131

131132
if (globalRefToGeneratedClass == nullptr) {
132133

133134
// get needed arguments in order to load binding
134-
JniLocalRef javaFullClassName(env.NewStringUTF(fullClassname.c_str()));
135+
JniLocalRef javaBaseClassName(env.NewStringUTF(baseClassName.c_str()));
136+
JniLocalRef javaFullClassName(env.NewStringUTF(fullClassName.c_str()));
135137

136138
jobjectArray methodOverrides = GetMethodOverrides(env, implementationObject);
137139

@@ -142,12 +144,13 @@ jclass CallbackHandlers::ResolveClass(Isolate* isolate, const string& fullClassn
142144
// create or load generated binding (java class)
143145
jclass generatedClass = (jclass)env.CallObjectMethod(runtime->GetJavaRuntime(),
144146
RESOLVE_CLASS_METHOD_ID,
147+
(jstring) javaBaseClassName,
145148
(jstring) javaFullClassName,
146149
methodOverrides,
147150
implementedInterfaces,
148151
isInterface);
149152

150-
globalRefToGeneratedClass = env.InsertClassIntoCache(fullClassname, generatedClass);
153+
globalRefToGeneratedClass = env.InsertClassIntoCache(fullClassName, generatedClass);
151154

152155
env.DeleteGlobalRef(methodOverrides);
153156
env.DeleteGlobalRef(implementedInterfaces);

test-app/runtime/src/main/cpp/CallbackHandlers.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ class CallbackHandlers {
3232

3333
static v8::Local<v8::Object> CreateJSWrapper(v8::Isolate* isolate, jint javaObjectID, const std::string& typeName);
3434

35-
static bool RegisterInstance(v8::Isolate* isolate, const v8::Local<v8::Object>& jsObject, const std::string& fullClassName, const ArgsWrapper& argWrapper, const v8::Local<v8::Object>& implementationObject, bool isInterface);
35+
static bool RegisterInstance(v8::Isolate* isolate, const v8::Local<v8::Object>& jsObject, const std::string& fullClassName, const ArgsWrapper& argWrapper, const v8::Local<v8::Object>& implementationObject, bool isInterface, const std::string& baseClassName = std::string());
3636

37-
static jclass ResolveClass(v8::Isolate* isolate, const std::string& fullClassname, const v8::Local<v8::Object>& implementationObject, bool isInterface);
37+
static jclass ResolveClass(v8::Isolate* isolate, const std::string& baseClassName, const std::string& fullClassName, const v8::Local<v8::Object>& implementationObject, bool isInterface);
3838

3939
static std::string ResolveClassName(v8::Isolate* isolate, jclass& clazz);
4040

test-app/runtime/src/main/cpp/MetadataNode.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,6 @@ void MetadataNode::ExtendedClassConstructorCallback(const v8::FunctionCallbackIn
825825
v8::HandleScope handleScope(isolate);
826826

827827
auto implementationObject = Local<Object>::New(isolate, *extData->implementationObject);
828-
const auto& extendName = extData->extendedName;
829828

830829
SetInstanceMetadata(isolate, thiz, extData->node);
831830
thiz->SetInternalField(static_cast<int>(ObjectManager::MetadataNodeKeys::CallSuper), True(isolate));
@@ -835,7 +834,7 @@ void MetadataNode::ExtendedClassConstructorCallback(const v8::FunctionCallbackIn
835834

836835
string fullClassName = extData->fullClassName;
837836

838-
bool success = CallbackHandlers::RegisterInstance(isolate, thiz, fullClassName, argWrapper, implementationObject, false);
837+
bool success = CallbackHandlers::RegisterInstance(isolate, thiz, fullClassName, argWrapper, implementationObject, false, extData->node->m_name);
839838
} catch (NativeScriptException& e) {
840839
e.ReThrowToV8();
841840
} catch (std::exception e) {
@@ -934,7 +933,7 @@ void MetadataNode::ClassConstructorCallback(const v8::FunctionCallbackInfo<v8::V
934933
ArgsWrapper argWrapper(info, ArgType::Class);
935934

936935
string fullClassName = CreateFullClassName(className, extendName);
937-
bool success = CallbackHandlers::RegisterInstance(isolate, thiz, fullClassName, argWrapper, Local<Object>(), false);
936+
bool success = CallbackHandlers::RegisterInstance(isolate, thiz, fullClassName, argWrapper, Local<Object>(), false, className);
938937
} catch (NativeScriptException& e) {
939938
e.ReThrowToV8();
940939
} catch (std::exception e) {
@@ -1325,8 +1324,9 @@ void MetadataNode::ExtendMethodCallback(const v8::FunctionCallbackInfo<v8::Value
13251324

13261325
string extendNameAndLocation = extendLocation + ArgConverter::ConvertToString(extendName);
13271326
string fullClassName;
1327+
string baseClassName = node->m_name;
13281328
if (!hasDot) {
1329-
fullClassName = TNS_PREFIX + CreateFullClassName(node->m_name, extendNameAndLocation);
1329+
fullClassName = TNS_PREFIX + CreateFullClassName(baseClassName, extendNameAndLocation);
13301330
} else {
13311331
fullClassName = ArgConverter::ConvertToString(info[0].As<String>());
13321332
}
@@ -1336,7 +1336,7 @@ void MetadataNode::ExtendMethodCallback(const v8::FunctionCallbackInfo<v8::Value
13361336
//resolve class (pre-generated or generated runtime from dex generator)
13371337
uint8_t nodeType = s_metadataReader.GetNodeType(node->m_treeNode);
13381338
bool isInterface = s_metadataReader.IsNodeTypeInterface(nodeType);
1339-
auto clazz = CallbackHandlers::ResolveClass(isolate, fullClassName, implementationObject, isInterface);
1339+
auto clazz = CallbackHandlers::ResolveClass(isolate, baseClassName, fullClassName, implementationObject, isInterface);
13401340
auto fullExtendedName = CallbackHandlers::ResolveClassName(isolate, clazz);
13411341
DEBUG_WRITE("ExtendsCallMethodHandler: extend full name %s", fullClassName.c_str());
13421342

test-app/runtime/src/main/java/com/tns/ClassResolver.java

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,18 @@ public ClassResolver(Runtime runtime) {
99
this.runtime = runtime;
1010
}
1111

12-
public Class<?> resolveClass(String fullClassName, DexFactory dexFactory, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
13-
String cannonicalClassName = fullClassName.replace('/', '.');
14-
String name = null;
15-
String className = cannonicalClassName;
16-
17-
int locationSeparatorIndex = cannonicalClassName.indexOf("_unknown_location");
18-
if (locationSeparatorIndex != -1) {
19-
className = cannonicalClassName.substring(0, locationSeparatorIndex);
20-
name = cannonicalClassName.substring(locationSeparatorIndex + 1);
21-
}
12+
public Class<?> resolveClass(String baseClassName, String fullClassName, DexFactory dexFactory, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
13+
String canonicalClassName = fullClassName.replace('/', '.');
14+
String canonicalBaseClassName = baseClassName.replace('/', '.');
15+
String name = "";
16+
String className = canonicalClassName;
2217

2318
Class<?> clazz = null;
24-
boolean isBindingClass = cannonicalClassName.startsWith("com.tns.gen") && !cannonicalClassName.startsWith("com.tns.tests.");
19+
boolean isBindingClass = canonicalClassName.startsWith("com.tns.gen") && !canonicalClassName.startsWith("com.tns.tests.");
2520

2621
// if binding generate proxy or load pregenerated
2722
if (isBindingClass) {
28-
if (name == null || name == "") {
29-
if (isInterface) {
30-
name = "";
31-
} else {
32-
name = "0";
33-
}
34-
}
35-
36-
clazz = dexFactory.resolveClass(name, className, methodOverrides, implementedInterfaces, isInterface);
23+
clazz = dexFactory.resolveClass(canonicalBaseClassName, name, className, methodOverrides, implementedInterfaces, isInterface);
3724
}
3825

3926
if (clazz == null) {

test-app/runtime/src/main/java/com/tns/DexFactory.java

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
import java.io.InputStreamReader;
1111
import java.io.InvalidClassException;
1212
import java.io.OutputStreamWriter;
13+
import java.util.ArrayList;
1314
import java.util.HashMap;
1415
import java.util.HashSet;
16+
import java.util.List;
1517
import java.util.zip.ZipEntry;
1618
import java.util.zip.ZipOutputStream;
1719

@@ -24,7 +26,7 @@
2426
import dalvik.system.DexFile;
2527

2628
public class DexFactory {
27-
private static final char CLASS_NAME_LOCATION_SEPARATOR = '_';
29+
private static final String COM_TNS_GEN_PREFIX = "com.tns.gen.";
2830

2931
private final Logger logger;
3032
private final File dexDir;
@@ -61,8 +63,9 @@ public DexFactory(Logger logger, ClassLoader classLoader, File dexBaseDir, Strin
6163
static long totalMultiDexTime = 0;
6264
static long totalLoadDexTime = 0;
6365

64-
public Class<?> resolveClass(String name, String className, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
66+
public Class<?> resolveClass(String baseClassName, String name, String className, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
6567
String fullClassName = className.replace("$", "_");
68+
String originalFullClassName = fullClassName;
6669

6770
// try to get pre-generated binding classes
6871
try {
@@ -84,19 +87,31 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
8487
}
8588
//
8689

90+
// new: com.tns.gen.android.widget.DatePicker_MyActivity_59_56_
91+
// old: com.tns.tests.Button1_fMyActivity_l56_c44__MyButton
92+
// ne1: com.tns.tests.Button1_MyActivity_58_44_MyButton_0
8793
Class<?> existingClass = this.injectedDexClasses.get(fullClassName);
8894
if (existingClass != null) {
8995
return existingClass;
9096
}
9197

92-
String classToProxy = this.getClassToProxyName(className);
93-
String dexFilePath = classToProxy;
98+
String classToProxy;
99+
if (!baseClassName.isEmpty()) {
100+
classToProxy = this.getClassToProxyName(baseClassName);
101+
} else {
102+
classToProxy = this.getClassToProxyName(className);
103+
}
94104

95-
if (!isInterface) {
96-
dexFilePath += CLASS_NAME_LOCATION_SEPARATOR + name;
105+
// strip the `com.tns.gen` off the base extended class name
106+
String desiredDexClassName = this.getClassToProxyName(fullClassName);
107+
108+
// when interfaces are extended as classes, we still want to preserve
109+
// just the interface name without the extra file, line, column information
110+
if (!baseClassName.isEmpty() && isInterface) {
111+
fullClassName = COM_TNS_GEN_PREFIX + classToProxy;
97112
}
98113

99-
File dexFile = this.getDexFile(dexFilePath);
114+
File dexFile = this.getDexFile(desiredDexClassName);
100115

101116
// generate dex file
102117
if (dexFile == null) {
@@ -105,7 +120,12 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
105120
logger.write("generating proxy in place");
106121
}
107122

108-
dexFilePath = this.generateDex(name, classToProxy, methodOverrides, implementedInterfaces, isInterface);
123+
String dexFilePath;
124+
if (isInterface) {
125+
dexFilePath = this.generateDex(name, classToProxy, methodOverrides, implementedInterfaces, isInterface);
126+
} else {
127+
dexFilePath = this.generateDex(desiredDexClassName, classToProxy, methodOverrides, implementedInterfaces, isInterface);
128+
}
109129
dexFile = new File(dexFilePath);
110130
long stopGenTime = System.nanoTime();
111131
totalGenTime += stopGenTime - startGenTime;
@@ -145,16 +165,21 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
145165
// However, this is the only viable way to get our dynamic classes
146166
// loaded within the system class loader
147167

148-
df = DexFile.loadDex(jarFilePath, new File(this.odexDir, fullClassName).getAbsolutePath(), 0);
149-
result = df.loadClass(fullClassName, classLoader);
168+
if (isInterface) {
169+
df = DexFile.loadDex(jarFilePath, new File(this.odexDir, fullClassName).getAbsolutePath(), 0);
170+
result = df.loadClass(fullClassName, classLoader);
171+
} else {
172+
df = DexFile.loadDex(jarFilePath, new File(this.odexDir, desiredDexClassName).getAbsolutePath(), 0);
173+
result = df.loadClass(desiredDexClassName, classLoader);
174+
}
150175
} catch (IOException e) {
151176
e.printStackTrace();
152177
// fall back to DexClassLoader
153178
DexClassLoader dexClassLoader = new DexClassLoader(jarFilePath, this.odexDir.getAbsolutePath(), null, classLoader);
154179
result = dexClassLoader.loadClass(fullClassName);
155180
}
156181

157-
this.injectedDexClasses.put(fullClassName, result);
182+
this.injectedDexClasses.put(originalFullClassName, result);
158183

159184
return result;
160185
}
@@ -191,11 +216,11 @@ public static String strJoin(String[] array, String separator) {
191216
private String getClassToProxyName(String className) throws InvalidClassException {
192217
String classToProxy = className;
193218

194-
if (className.startsWith("com.tns.gen.")) {
219+
if (className.startsWith(COM_TNS_GEN_PREFIX)) {
195220
classToProxy = className.substring(12);
196221
}
197222

198-
if (classToProxy.startsWith("com.tns.gen.")) {
223+
if (classToProxy.startsWith(COM_TNS_GEN_PREFIX)) {
199224
throw new InvalidClassException("Can't generate proxy of proxy");
200225
}
201226

test-app/runtime/src/main/java/com/tns/Runtime.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,8 @@ public void run() {
577577
}
578578

579579
@RuntimeCallable
580-
private Class<?> resolveClass(String fullClassName, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
581-
Class<?> javaClass = classResolver.resolveClass(fullClassName, dexFactory, methodOverrides, implementedInterfaces, isInterface);
580+
private Class<?> resolveClass(String baseClassName, String fullClassName, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
581+
Class<?> javaClass = classResolver.resolveClass(baseClassName, fullClassName, dexFactory, methodOverrides, implementedInterfaces, isInterface);
582582

583583
return javaClass;
584584
}

0 commit comments

Comments
 (0)