Skip to content

Commit 144ca97

Browse files
petekanevMihail Slavchev
authored andcommitted
runtime generator generates universal interfaces
1 parent c5b6a9f commit 144ca97

File tree

9 files changed

+67
-46
lines changed

9 files changed

+67
-46
lines changed

binding-generator/src/main/java/com/tns/bindings/Dump.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,9 +350,15 @@ public void generateProxy(ApplicationWriter aw, String proxyName, Class<?> class
350350
{
351351
String classSignature = getAsmDescriptor(classTo);
352352
//String methodSignature = org.objectweb.asm.Type.getMethodDescriptor(Object.class.getMethods()[0]);
353+
353354
String tnsClassSignature = LCOM_TNS +
354-
classSignature.substring(1, classSignature.length() - 1).replace("$", "_")
355-
+ CLASS_NAME_LOCATION_SEPARATOR + proxyName + ";";
355+
classSignature.substring(1, classSignature.length() - 1).replace("$", "_");
356+
357+
if(!classTo.isInterface()) {
358+
tnsClassSignature += CLASS_NAME_LOCATION_SEPARATOR + proxyName;
359+
}
360+
361+
tnsClassSignature += ";";
356362

357363
ClassVisitor cv = generateClass(aw, classTo, classSignature, tnsClassSignature);
358364
Method[] methods = getSupportedMethods(classTo, methodOverrides);
@@ -723,7 +729,7 @@ private void generateHashCodeSuper(ClassVisitor cv)
723729

724730
private void generateMethod(ClassVisitor cv, Class<?> classTo, Method method, int methodNumber, String classSignature, String tnsClassSignature, int fieldBit)
725731
{
726-
if (ProxyGenerator.IsLogEnabled) Log.d("TNS.Rungime.Proxy.Generator", "generatingMethod " + method.getName());
732+
if (ProxyGenerator.IsLogEnabled) Log.d("Generator", "generatingMethod " + method.getName());
727733

728734
//TODO: handle checked exceptions
729735
String methodDexSignature = getDexMethodDescriptor(method);

binding-generator/src/main/java/com/tns/bindings/ProxyGenerator.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void setProxyThumb(String proxyThumb)
2929
}
3030

3131

32-
public String generateProxy(String proxyName, Class<?> classToProxy, String[] methodOverrides) throws IOException
32+
public String generateProxy(String proxyName, Class<?> classToProxy, String[] methodOverrides, boolean isInterface) throws IOException
3333
{
3434
HashSet<String> methodOverridesSet = null;
3535

@@ -42,18 +42,26 @@ public String generateProxy(String proxyName, Class<?> classToProxy, String[] me
4242
methodOverridesSet.add(methodOverride);
4343
}
4444
}
45-
return generateProxy(proxyName, classToProxy, methodOverridesSet);
45+
return generateProxy(proxyName, classToProxy, methodOverridesSet, isInterface);
4646
}
4747

48-
public String generateProxy(String proxyName, Class<?> classToProxy, HashSet<String> methodOverrides) throws IOException
48+
public String generateProxy(String proxyName, Class<?> classToProxy, HashSet<String> methodOverrides, boolean isInterface) throws IOException
4949
{
5050
ApplicationWriter aw = new ApplicationWriter();
5151
aw.visit();
52+
5253
dump.generateProxy(aw, proxyName, classToProxy, methodOverrides);
54+
5355
aw.visitEnd();
5456
byte[] generatedBytes = aw.toByteArray();
5557

56-
String proxyFileName = classToProxy.getName().replace('$', '_') + Dump.CLASS_NAME_LOCATION_SEPARATOR + proxyName;
58+
String proxyFileName = classToProxy.getName().replace('$', '_');
59+
60+
if(!isInterface)
61+
{
62+
proxyFileName += Dump.CLASS_NAME_LOCATION_SEPARATOR + proxyName;
63+
}
64+
5765
if (proxyThumb != null)
5866
{
5967
proxyFileName += "-" + proxyThumb;

runtime/src/main/java/com/tns/ClassResolver.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
class ClassResolver
66
{
77
private final Runtime runtime;
8-
8+
99
public ClassResolver(Runtime runtime)
1010
{
1111
this.runtime = runtime;
1212
}
13-
14-
public Class<?> resolveClass(String fullClassName, DexFactory dexFactory, String[] methodOverrides) throws ClassNotFoundException, IOException
13+
14+
public Class<?> resolveClass(String fullClassName, DexFactory dexFactory, String[] methodOverrides, boolean isInterface) throws ClassNotFoundException, IOException
1515
{
1616
String cannonicalClassName = fullClassName.replace('/', '.');
1717
String name = null;
@@ -32,10 +32,16 @@ public Class<?> resolveClass(String fullClassName, DexFactory dexFactory, String
3232
{
3333
if (name == null || name == "")
3434
{
35-
name = "0";
35+
if(isInterface)
36+
{
37+
name = "";
38+
} else
39+
{
40+
name = "0";
41+
}
3642
}
3743

38-
clazz = dexFactory.resolveClass(name, className, methodOverrides);
44+
clazz = dexFactory.resolveClass(name, className, methodOverrides, isInterface);
3945
}
4046

4147
if (clazz == null)

runtime/src/main/java/com/tns/DexFactory.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,27 @@ public DexFactory(Logger logger, ClassLoader classLoader, File dexBaseDir, Strin
6262
static long totalMultiDexTime = 0;
6363
static long totalLoadDexTime = 0;
6464

65-
public Class<?> resolveClass(String name, String className, String[] methodOverrides) throws ClassNotFoundException, IOException
65+
public Class<?> resolveClass(String name, String className, String[] methodOverrides, boolean isInterface) throws ClassNotFoundException, IOException
6666
{
67-
String fullClassName = className.replace("$", "_") + CLASS_NAME_LOCATION_SEPARATOR + name;
67+
String fullClassName = className.replace("$", "_");
68+
69+
if(!isInterface) {
70+
fullClassName += CLASS_NAME_LOCATION_SEPARATOR + name;
71+
}
6872

6973
// try to get pre-generated binding classes
7074
try
7175
{
76+
if(logger.isEnabled()) {
77+
logger.write("getting pre-generated proxy class with name: " + fullClassName.replace("-", "_"));
78+
}
79+
7280
Class<?> pregeneratedClass = classLoader.loadClass(fullClassName.replace("-", "_"));
7381

82+
if(logger.isEnabled()) {
83+
logger.write("Pre-generated class found: " + fullClassName.replace("-", "_"));
84+
}
85+
7486
return pregeneratedClass;
7587
}
7688
catch (Exception e)
@@ -85,7 +97,12 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
8597
}
8698

8799
String classToProxy = this.getClassToProxyName(className);
88-
String dexFilePath = classToProxy + CLASS_NAME_LOCATION_SEPARATOR + name;
100+
String dexFilePath = classToProxy;
101+
102+
if(!isInterface) {
103+
dexFilePath += CLASS_NAME_LOCATION_SEPARATOR + name;
104+
}
105+
89106
File dexFile = this.getDexFile(dexFilePath);
90107

91108
// generate dex file
@@ -97,7 +114,7 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
97114
logger.write("generating proxy in place");
98115
}
99116

100-
dexFilePath = this.generateDex(name, classToProxy, methodOverrides);
117+
dexFilePath = this.generateDex(name, classToProxy, methodOverrides, isInterface);
101118
dexFile = new File(dexFilePath);
102119
long stopGenTime = System.nanoTime();
103120
totalGenTime += stopGenTime - startGenTime;
@@ -139,6 +156,7 @@ public Class<?> resolveClass(String name, String className, String[] methodOverr
139156
// be directly used.
140157
// However, this is the only viable way to get our dynamic classes
141158
// loaded within the system class loader
159+
142160
df = DexFile.loadDex(jarFilePath, new File(this.odexDir, fullClassName).getAbsolutePath(), 0);
143161
result = df.loadClass(fullClassName, classLoader);
144162
}
@@ -234,7 +252,7 @@ private File getDexFile(String className) throws InvalidClassException
234252
return null;
235253
}
236254

237-
private String generateDex(String proxyName, String className, String[] methodOverrides) throws ClassNotFoundException, IOException
255+
private String generateDex(String proxyName, String className, String[] methodOverrides, boolean isInterface) throws ClassNotFoundException, IOException
238256
{
239257
Class<?> classToProxy = Class.forName(className);
240258

@@ -249,7 +267,7 @@ private String generateDex(String proxyName, String className, String[] methodOv
249267
}
250268
}
251269

252-
return proxyGenerator.generateProxy(proxyName, classToProxy, methodOverridesSet);
270+
return proxyGenerator.generateProxy(proxyName, classToProxy, methodOverridesSet, isInterface);
253271
}
254272

255273
private void updateDexThumbAndPurgeCache()

runtime/src/main/java/com/tns/Runtime.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,9 @@ public void run()
305305
}
306306

307307
@RuntimeCallable
308-
private Class<?> resolveClass(String fullClassName, String[] methodOverrides) throws ClassNotFoundException, IOException
308+
private Class<?> resolveClass(String fullClassName, String[] methodOverrides, boolean isInterface) throws ClassNotFoundException, IOException
309309
{
310-
Class<?> javaClass = classResolver.resolveClass(fullClassName, dexFactory, methodOverrides);
310+
Class<?> javaClass = classResolver.resolveClass(fullClassName, dexFactory, methodOverrides, isInterface);
311311

312312
return javaClass;
313313
}

runtime/src/main/jni/CallbackHandlers.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void CallbackHandlers::Init(Isolate *isolate, ObjectManager *objectManager)
3636
RUNTIME_CLASS = env.FindClass("com/tns/Runtime");
3737
assert(RUNTIME_CLASS != nullptr);
3838

39-
RESOLVE_CLASS_METHOD_ID = env.GetMethodID(RUNTIME_CLASS, "resolveClass", "(Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Class;");
39+
RESOLVE_CLASS_METHOD_ID = env.GetMethodID(RUNTIME_CLASS, "resolveClass", "(Ljava/lang/String;[Ljava/lang/String;Z)Ljava/lang/Class;");
4040
assert(RESOLVE_CLASS_METHOD_ID != nullptr);
4141

4242
CURRENT_OBJECTID_FIELD_ID = env.GetFieldID(RUNTIME_CLASS, "currentObjectId", "I");
@@ -73,7 +73,7 @@ bool CallbackHandlers::RegisterInstance(Isolate *isolate, const Local<Object>& j
7373

7474
JEnv env;
7575

76-
jclass generatedJavaClass = ResolveClass(isolate, fullClassName, implementationObject);
76+
jclass generatedJavaClass = ResolveClass(isolate, fullClassName, implementationObject, isInterface);
7777

7878
int javaObjectID = objectManager->GenerateNewObjectID();
7979

@@ -123,7 +123,7 @@ bool CallbackHandlers::RegisterInstance(Isolate *isolate, const Local<Object>& j
123123
return success;
124124
}
125125

126-
jclass CallbackHandlers::ResolveClass(Isolate *isolate, const string& fullClassname, const Local<Object>& implementationObject)
126+
jclass CallbackHandlers::ResolveClass(Isolate *isolate, const string& fullClassname, const Local<Object>& implementationObject, bool isInterface)
127127
{
128128
auto itFound = s_classCache.find(fullClassname);
129129

@@ -145,7 +145,7 @@ jclass CallbackHandlers::ResolveClass(Isolate *isolate, const string& fullClassn
145145
auto runtime = Runtime::GetRuntime(isolate);
146146

147147
// create or load generated binding (java class)
148-
JniLocalRef generatedClass(env.CallObjectMethod(runtime->GetJavaRuntime(), RESOLVE_CLASS_METHOD_ID, (jstring) javaFullClassName, methodOverrides));
148+
JniLocalRef generatedClass(env.CallObjectMethod(runtime->GetJavaRuntime(), RESOLVE_CLASS_METHOD_ID, (jstring) javaFullClassName, methodOverrides, isInterface));
149149
globalRefToGeneratedClass = static_cast<jclass>(env.NewGlobalRef(generatedClass));
150150

151151
s_classCache.insert(make_pair(fullClassname, globalRefToGeneratedClass));
@@ -154,9 +154,10 @@ jclass CallbackHandlers::ResolveClass(Isolate *isolate, const string& fullClassn
154154
return globalRefToGeneratedClass;
155155
}
156156

157+
// Called by ExtendCallMethodCallback when extending a class
157158
string CallbackHandlers::ResolveClassName(Isolate *isolate, const string& fullClassname, const Local<Object>& implementationObject)
158159
{
159-
auto clazz = ResolveClass(isolate, fullClassname, implementationObject);
160+
auto clazz = ResolveClass(isolate, fullClassname, implementationObject, false);
160161
auto runtime = Runtime::GetRuntime(isolate);
161162
auto objectManager = runtime->GetObjectManager();
162163
auto className = objectManager->GetClassName(clazz);

runtime/src/main/jni/CallbackHandlers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace tns
3030

3131
static std::string ResolveConstructor(v8::Isolate *isolate, const ArgsWrapper& argWrapper, const std::string& fullClassName, jclass javaClass, bool isInterface);
3232

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

3535
static std::string ResolveClassName(v8::Isolate *isolate, const std::string& fullClassname, const v8::Local<v8::Object>& implementationObject);
3636

runtime/src/main/jni/MetadataNode.cpp

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -983,21 +983,9 @@ void MetadataNode::InterfaceConstructorCallback(const v8::FunctionCallbackInfo<v
983983

984984
Local<Object> implementationObject;
985985
Local<String> v8ExtendName;
986-
string extendLocation;
987-
bool extendLocationFound = GetExtendLocation(extendLocation);
986+
988987
if (info.Length() == 1)
989988
{
990-
if (!extendLocationFound)
991-
{
992-
stringstream ss;
993-
ss << "(InternalError): Invalid extend() call. No name specified for extend. Location: " << extendLocation.c_str();
994-
throw NativeScriptException(ss.str());
995-
}
996-
997-
if (!info[0]->IsObject())
998-
{
999-
throw NativeScriptException(string("First argument must be implementation object"));
1000-
}
1001989
implementationObject = info[0]->ToObject();
1002990
}
1003991
else if (info.Length() == 2)
@@ -1021,22 +1009,18 @@ void MetadataNode::InterfaceConstructorCallback(const v8::FunctionCallbackInfo<v
10211009
}
10221010

10231011
auto className = node->m_implType;
1024-
auto extendName = ConvertToString(v8ExtendName);
1025-
auto extendNameAndLocation = extendLocation + extendName;
10261012
SetInstanceMetadata(isolate, implementationObject, node);
10271013

10281014
//@@@ Refactor
10291015
thiz->SetInternalField(static_cast<int>(ObjectManager::MetadataNodeKeys::CallSuper), True(isolate));
10301016

1031-
string fullClassName = CreateFullClassName(className, extendNameAndLocation);
1032-
10331017
implementationObject->SetPrototype(thiz->GetPrototype());
10341018
thiz->SetPrototype(implementationObject);
10351019
thiz->SetHiddenValue(ConvertToV8String("t::implObj"), implementationObject);
10361020

10371021
ArgsWrapper argWrapper(info, ArgType::Interface, Local<Object>());
10381022

1039-
auto success = CallbackHandlers::RegisterInstance(isolate, thiz, fullClassName, argWrapper, implementationObject, true);
1023+
auto success = CallbackHandlers::RegisterInstance(isolate, thiz, className, argWrapper, implementationObject, true);
10401024
}
10411025
catch (NativeScriptException& e)
10421026
{

test-app/app/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ waitForUnitTestResultFile.dependsOn(createDistFolder)
136136
copyResultToDist.dependsOn(waitForUnitTestResultFile)
137137
deleteRootLevelResult.dependsOn(copyResultToDist)
138138

139-
140-
141139
task runtests {
142140
dependsOn deleteRootLevelResult
143141
}

0 commit comments

Comments
 (0)