Skip to content

Commit abc637b

Browse files
author
Nathanael Anderson
authored
Merge pull request #1633 from NativeScript/fix_metadata_hydration
Fix for extra MetaData duplication and invalid rehydration with Kotlin
2 parents d77217f + ada4178 commit abc637b

File tree

5 files changed

+186
-45
lines changed

5 files changed

+186
-45
lines changed

test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Builder.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@ static TreeNode build(List<String> paths) throws Exception {
9898
}
9999
}
100100

101+
System.out.println("Added Properties "+TreeNode.addedProperties);
102+
System.out.println("Ignored Properties "+TreeNode.skippedProperties+" duplicates.");
103+
System.out.println("Added Methods "+TreeNode.addedMethods);
104+
System.out.println("Ignored Methods "+TreeNode.skippedMethods+" duplicates.");
105+
System.out.println("Added Fields "+TreeNode.addedFields);
106+
System.out.println("Ignored Fields "+TreeNode.skippedFields+" duplicates.");
107+
108+
101109

102110
return root;
103111
}
@@ -161,7 +169,7 @@ private static void setNodeMembers(NativeClassDescriptor clazz, TreeNode node, T
161169
node.setWentThroughSettingMembers(true);
162170

163171
Map<String, MethodInfo> existingMethods = new HashMap<>();
164-
for (MethodInfo mi : node.instanceMethods) {
172+
for (MethodInfo mi : node.getInstanceMethods()) {
165173
existingMethods.put(mi.name + mi.sig, mi);
166174
}
167175
NativeMethodDescriptor[] extensionFunctions = ExtensionFunctionsStorage.getInstance().retrieveFunctions(clazz.getClassName()).toArray(new NativeMethodDescriptor[0]);
@@ -228,7 +236,7 @@ private static void setMethodsInfo(TreeNode root, TreeNode node, NativeClassDesc
228236
if (isStatic) {
229237
if (!mi.isExtensionFunction) {
230238
mi.declaringType = getOrCreateNode(root, clazz, null);
231-
node.staticMethods.add(mi);
239+
node.addStaticFunction(mi);
232240
} else {
233241
mi.declaringType = getOrCreateNode(root, ownMethod.getDeclaringClass(), null);
234242
node.addExtensionFunction(mi);
@@ -238,13 +246,10 @@ private static void setMethodsInfo(TreeNode root, TreeNode node, NativeClassDesc
238246
if (existingNodeMethods.containsKey(sig)) {
239247
continue;
240248
}
241-
node.instanceMethods.add(mi);
249+
node.addInstanceMethod(mi);
242250
}
243251
}
244252

245-
if (mi.isResolved) {
246-
node.resolvedMethods.add(mi);
247-
}
248253
}
249254
}
250255

@@ -301,9 +306,9 @@ private static void setFieldInfo(NativeClassDescriptor clazz, TreeNode node, Tre
301306
} else {
302307
fi.declaringType = getOrCreateNode(root, clazz, null);
303308
}
304-
node.staticFields.add(fi);
309+
node.addStaticField(fi);
305310
} else {
306-
node.instanceFields.add(fi);
311+
node.addInstanceField(fi);
307312
}
308313
}
309314
}

test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Generator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414
import java.util.ArrayList;
1515
import java.util.List;
1616

17+
import static java.lang.System.exit;
18+
1719
public class Generator {
1820

1921
private static final String VERBOSE_FLAG_NAME = "verbose";
22+
private static final String SKIP_FLAG_NAME = "skip";
2023
private static final String ANALYTICS_ARGUMENT_BEGINNING = "analyticsFilePath=";
2124
private static final String MDG_OUTPUT_DIR = "mdg-output-dir.txt";
2225
private static final String MDG_JAVA_DEPENDENCIES = "mdg-java-dependencies.txt";
@@ -61,7 +64,7 @@ public static void main(String[] args) {
6164
} catch (Throwable ex) {
6265
System.err.println(String.format("Error executing Metadata Generator: %s", ex.getMessage()));
6366
ex.printStackTrace(System.out);
64-
System.exit(1);
67+
exit(1);
6568
}
6669
}
6770

@@ -72,6 +75,9 @@ private static void enableFlaggedFeatures(String[] args) {
7275
AnalyticsConfiguration.enableAnalytics(filePath);
7376
} else if (VERBOSE_FLAG_NAME.equals(arg)) {
7477
MetadataFilterConsoleLogger.INSTANCE.setEnabled(true);
78+
} else if (SKIP_FLAG_NAME.equals(arg)) {
79+
System.out.println("Skipping metadata generation: skip flag used.");
80+
exit(0);
7581
}
7682
}
7783
}

test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/TreeNode.java

Lines changed: 124 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
import java.util.Optional;
1111

1212
public class TreeNode {
13+
public static int skippedMethods=0;
14+
public static int skippedProperties=0;
15+
public static int skippedFields=0;
16+
public static int addedMethods=0;
17+
public static int addedProperties=0;
18+
public static int addedFields=0;
19+
1320
public static class MethodInfo {
1421
public MethodInfo(NativeMethodDescriptor m) {
1522
this.name = m.getName();
@@ -97,7 +104,6 @@ public TreeNode() {
97104
staticFields = new ArrayList<>();
98105
properties = new ArrayList<>();
99106
extensionFunctions = new ArrayList<>();
100-
resolvedMethods = new ArrayList<>();
101107
}
102108

103109
public static final TreeNode BYTE = getPrimitive("B", (byte) 1);
@@ -222,39 +228,145 @@ public void setName(String value) {
222228
//
223229
public TreeNode arrayElement;
224230
//
225-
public ArrayList<MethodInfo> instanceMethods;
226-
public ArrayList<MethodInfo> staticMethods;
227-
public ArrayList<FieldInfo> instanceFields;
228-
public ArrayList<FieldInfo> staticFields;
229-
ArrayList<PropertyInfo> properties;
230-
ArrayList<MethodInfo> extensionFunctions;
231-
ArrayList<MethodInfo> resolvedMethods;
231+
private ArrayList<MethodInfo> instanceMethods;
232+
private ArrayList<MethodInfo> staticMethods;
233+
private ArrayList<FieldInfo> instanceFields;
234+
private ArrayList<FieldInfo> staticFields;
235+
private ArrayList<PropertyInfo> properties;
236+
private ArrayList<MethodInfo> extensionFunctions;
232237
public TreeNode baseClassNode;
233238
TreeNode parentNode;
234239
//
235240

236241
void addProperty(PropertyInfo propertyInfo) {
242+
for (int i=0;i<properties.size();i++) {
243+
PropertyInfo pi = properties.get(i);
244+
if (pi.propertyName.equals(propertyInfo.propertyName)) {
245+
if (pi.getterMethod != null || propertyInfo.getterMethod != null) {
246+
if (pi.getterMethod != null && propertyInfo.getterMethod != null) {
247+
if (pi.getterMethod.sig != propertyInfo.getterMethod.sig) {
248+
continue;
249+
}
250+
} else {
251+
continue;
252+
}
253+
}
254+
if (pi.setterMethod != null || propertyInfo.setterMethod != null) {
255+
if (pi.setterMethod != null && propertyInfo.setterMethod != null) {
256+
if (pi.setterMethod.sig != propertyInfo.setterMethod.sig) {
257+
continue;
258+
}
259+
} else {
260+
continue;
261+
}
262+
}
263+
skippedProperties++;
264+
return;
265+
}
266+
}
237267
properties.add(propertyInfo);
268+
addedProperties++;
269+
}
270+
271+
void addStaticField(FieldInfo fieldInfo) {
272+
for (int i=0;i<staticFields.size();i++) {
273+
FieldInfo fi = staticFields.get(i);
274+
if (fi.name.equals(fieldInfo.name) && fi.isFinalType == fieldInfo.isFinalType) {
275+
if (fi.declaringType == fieldInfo.declaringType && fi.valueType == fieldInfo.valueType) {
276+
skippedFields++;
277+
return;
278+
}
279+
}
280+
}
281+
staticFields.add(fieldInfo);
282+
addedFields++;
283+
}
284+
285+
286+
void addInstanceField(FieldInfo fieldInfo) {
287+
for (int i=0;i<instanceFields.size();i++) {
288+
FieldInfo fi = instanceFields.get(i);
289+
if (fi.name.equals(fieldInfo.name) && fi.isFinalType == fieldInfo.isFinalType) {
290+
if (fi.declaringType == fieldInfo.declaringType && fi.valueType == fieldInfo.valueType) {
291+
skippedFields++;
292+
return;
293+
}
294+
}
295+
}
296+
instanceFields.add(fieldInfo);
297+
addedFields++;
238298
}
239299

240300
void addExtensionFunction(MethodInfo methodInfo) {
301+
for (int i=0;i<extensionFunctions.size();i++) {
302+
MethodInfo mi = extensionFunctions.get(i);
303+
if (mi.name.equals(methodInfo.name) && mi.sig.equals(methodInfo.sig)) {
304+
if (mi.isResolved == methodInfo.isResolved) {
305+
if (mi.declaringType == methodInfo.declaringType) {
306+
skippedMethods++;
307+
return;
308+
}
309+
}
310+
}
311+
}
241312
extensionFunctions.add(methodInfo);
313+
addedMethods++;
314+
}
315+
316+
void addStaticFunction(MethodInfo methodInfo) {
317+
for (int i=0;i<staticMethods.size();i++) {
318+
MethodInfo mi = staticMethods.get(i);
319+
if (mi.name.equals(methodInfo.name) && mi.sig.equals(methodInfo.sig)) {
320+
if (mi.isResolved == methodInfo.isResolved) {
321+
if (mi.declaringType == methodInfo.declaringType) {
322+
skippedMethods++;
323+
return;
324+
}
325+
}
326+
}
327+
}
328+
this.staticMethods.add(methodInfo);
329+
addedMethods++;
330+
}
331+
332+
void addInstanceMethod(MethodInfo methodInfo) {
333+
for (int i=0;i<instanceMethods.size();i++) {
334+
MethodInfo mi = instanceMethods.get(i);
335+
if (mi.name.equals(methodInfo.name) && mi.sig.equals(methodInfo.sig)) {
336+
if (mi.isResolved == methodInfo.isResolved) {
337+
if (mi.declaringType == methodInfo.declaringType) {
338+
skippedMethods++;
339+
return;
340+
}
341+
}
342+
}
343+
}
344+
instanceMethods.add(methodInfo);
345+
addedMethods++;
242346
}
243347

244348
List<PropertyInfo> getProperties() {
245349
return properties;
246350
}
247351

352+
List<FieldInfo> getInstanceFields() {
353+
return instanceFields;
354+
}
355+
356+
List<FieldInfo> getStaticFields() {
357+
return staticFields;
358+
}
359+
248360
List<MethodInfo> getExtensionFunctions() {
249361
return extensionFunctions;
250362
}
251363

252-
void addResolvedMethod(MethodInfo resolvedMethod) {
253-
resolvedMethods.add(resolvedMethod);
364+
List<MethodInfo> getInstanceMethods() {
365+
return instanceMethods;
254366
}
255367

256-
List<MethodInfo> getResolvedMethods() {
257-
return resolvedMethods;
368+
List<MethodInfo> getStaticMethods() {
369+
return staticMethods;
258370
}
259371

260372
private boolean wentThroughSettingMembers = false;

test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Writer.java

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,16 @@ public void writeClassValue(StreamWriter writer,
124124
writeTreeNodeId(extensionFunction.declaringType, writer);
125125
}
126126

127-
int len = writeLength(n.instanceMethods.size(), writer);
127+
List<MethodInfo> instanceMethods = n.getInstanceMethods();
128+
int len = writeLength(instanceMethods.size(), writer);
128129
for (int i = 0; i < len; i++) {
129-
writeMethodInfo(n.instanceMethods.get(i), stringsMap, writer);
130+
writeMethodInfo(instanceMethods.get(i), stringsMap, writer);
130131
}
131132

132-
len = writeLength(n.instanceFields.size(), writer);
133+
List<FieldInfo> instanceFields = n.getInstanceFields();
134+
len = writeLength(instanceFields.size(), writer);
133135
for (int i = 0; i < len; i++) {
134-
FieldInfo fi = n.instanceFields.get(i);
136+
FieldInfo fi = instanceFields.get(i);
135137
int pos = stringsMap.get(fi.name).intValue(); // get start position
136138
// of the name
137139
writeInt(pos, writer); // write start position of the name of the
@@ -169,16 +171,18 @@ public void writeClassValue(StreamWriter writer,
169171
}
170172
}
171173

172-
len = writeLength(n.staticMethods.size(), writer);
174+
List<MethodInfo> staticMethods = n.getStaticMethods();
175+
len = writeLength(staticMethods.size(), writer);
173176
for (int i = 0; i < len; i++) {
174-
MethodInfo mi = n.staticMethods.get(i);
177+
MethodInfo mi = staticMethods.get(i);
175178
writeMethodInfo(mi, stringsMap, writer);
176179
writeTreeNodeId(mi.declaringType, writer);
177180
}
178181

179-
len = writeLength(n.staticFields.size(), writer);
182+
List<FieldInfo> staticFields = n.getStaticFields();
183+
len = writeLength(staticFields.size(), writer);
180184
for (int i = 0; i < len; i++) {
181-
FieldInfo fi = n.staticFields.get(i);
185+
FieldInfo fi = staticFields.get(i);
182186
int pos = stringsMap.get(fi.name).intValue();
183187
writeInt(pos, writer);
184188
writeTreeNodeId(fi.valueType, writer);
@@ -223,26 +227,30 @@ public void writeTree(TreeNode root) throws Exception {
223227

224228
if (((n.nodeType & TreeNode.Interface) == TreeNode.Interface)
225229
|| ((n.nodeType & TreeNode.Class) == TreeNode.Class)) {
226-
for (int i = 0; i < n.instanceMethods.size(); i++) {
227-
name = n.instanceMethods.get(i).name;
230+
List<MethodInfo> instanceMethods = n.getInstanceMethods();
231+
for (int i = 0; i < instanceMethods.size(); i++) {
232+
name = instanceMethods.get(i).name;
228233
if (!uniqueStrings.containsKey(name)) {
229234
writeUniqueName(name, uniqueStrings, outStringsStream);
230235
}
231236
}
232-
for (int i = 0; i < n.staticMethods.size(); i++) {
233-
name = n.staticMethods.get(i).name;
237+
List<MethodInfo> staticMethods = n.getStaticMethods();
238+
for (int i = 0; i < staticMethods.size(); i++) {
239+
name = staticMethods.get(i).name;
234240
if (!uniqueStrings.containsKey(name)) {
235241
writeUniqueName(name, uniqueStrings, outStringsStream);
236242
}
237243
}
238-
for (int i = 0; i < n.instanceFields.size(); i++) {
239-
name = n.instanceFields.get(i).name;
244+
List<FieldInfo> instanceFields = n.getInstanceFields();
245+
for (int i = 0; i < instanceFields.size(); i++) {
246+
name = instanceFields.get(i).name;
240247
if (!uniqueStrings.containsKey(name)) {
241248
writeUniqueName(name, uniqueStrings, outStringsStream);
242249
}
243250
}
244-
for (int i = 0; i < n.staticFields.size(); i++) {
245-
name = n.staticFields.get(i).name;
251+
List<FieldInfo> staticFields = n.getStaticFields();
252+
for (int i = 0; i < staticFields.size(); i++) {
253+
name = staticFields.get(i).name;
246254
if (!uniqueStrings.containsKey(name)) {
247255
writeUniqueName(name, uniqueStrings, outStringsStream);
248256
}

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -530,15 +530,20 @@ vector<MetadataNode::MethodCallbackData *> MetadataNode::SetInstanceMethodsFromS
530530
auto entry = s_metadataReader.ReadExtensionFunctionEntry(&curPtr);
531531

532532
if (entry.name != lastMethodName) {
533-
callbackData = new MethodCallbackData(this);
534-
auto funcData = External::New(isolate, callbackData);
535-
auto funcTemplate = FunctionTemplate::New(isolate, MethodCallback, funcData);
536-
auto funcName = ArgConverter::ConvertToV8String(isolate, entry.name);
537-
prototypeTemplate->Set(funcName, funcTemplate);
533+
//
534+
callbackData = tryGetExtensionMethodCallbackData(collectedExtensionMethodDatas,
535+
entry.name);
536+
if (callbackData == nullptr) {
537+
callbackData = new MethodCallbackData(this);
538+
auto funcData = External::New(isolate, callbackData);
539+
auto funcTemplate = FunctionTemplate::New(isolate, MethodCallback, funcData);
540+
auto funcName = ArgConverter::ConvertToV8String(isolate, entry.name);
541+
prototypeTemplate->Set(funcName, funcTemplate);
538542

539-
lastMethodName = entry.name;
540-
std::pair<std::string, MethodCallbackData *> p(entry.name, callbackData);
541-
collectedExtensionMethodDatas.insert(p);
543+
lastMethodName = entry.name;
544+
std::pair<std::string, MethodCallbackData *> p(entry.name, callbackData);
545+
collectedExtensionMethodDatas.insert(p);
546+
}
542547
}
543548
callbackData->candidates.push_back(entry);
544549
}
@@ -553,10 +558,15 @@ vector<MetadataNode::MethodCallbackData *> MetadataNode::SetInstanceMethodsFromS
553558

554559
// attach a function to the prototype of a javascript Object
555560
if (entry.name != lastMethodName) {
561+
// See if we have tracked the callback data before (meaning another version of entry.name exists with different parameters)
556562
callbackData = tryGetExtensionMethodCallbackData(collectedExtensionMethodDatas,
557563
entry.name);
558564
if (callbackData == nullptr) {
559565
callbackData = new MethodCallbackData(this);
566+
567+
// If we have no tracking of this callback data, create tracking so that we can find it if need be for future itterations where the entry.name is the same...
568+
std::pair<std::string, MethodCallbackData *> p(entry.name, callbackData);
569+
collectedExtensionMethodDatas.insert(p);
560570
}
561571

562572
instanceMethodData.push_back(callbackData);

0 commit comments

Comments
 (0)