Skip to content

Commit 2548b54

Browse files
authored
fix: Do not update in-place object prototypes (#67) (#70)
* fix: Do not update in-place object prototypes (#67) * fix: Load proper prototype when registering additional protocols
1 parent f19d5a7 commit 2548b54

File tree

10 files changed

+97
-65
lines changed

10 files changed

+97
-65
lines changed

NativeScript/runtime/ArgConverter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ class ArgConverter {
3131
public:
3232
static void Init(v8::Local<v8::Context> context, v8::GenericNamedPropertyGetterCallback structPropertyGetter, v8::GenericNamedPropertySetterCallback structPropertySetter);
3333
static v8::Local<v8::Value> Invoke(v8::Local<v8::Context> context, Class klass, v8::Local<v8::Object> receiver, V8Args& args, const MethodMeta* meta, bool isMethodCallback);
34-
static v8::Local<v8::Value> ConvertArgument(v8::Local<v8::Context> context, BaseDataWrapper* wrapper, bool skipGCRegistration = false);
35-
static v8::Local<v8::Value> CreateJsWrapper(v8::Local<v8::Context> context, BaseDataWrapper* wrapper, v8::Local<v8::Object> receiver, bool skipGCRegistration = false);
34+
static v8::Local<v8::Value> ConvertArgument(v8::Local<v8::Context> context, BaseDataWrapper* wrapper, bool skipGCRegistration = false, const std::vector<std::string>& additionalProtocols = std::vector<std::string>());
35+
static v8::Local<v8::Value> CreateJsWrapper(v8::Local<v8::Context> context, BaseDataWrapper* wrapper, v8::Local<v8::Object> receiver, bool skipGCRegistration = false, const std::vector<std::string>& additionalProtocols = std::vector<std::string>());
3636
static std::shared_ptr<v8::Persistent<v8::Value>> CreateEmptyObject(v8::Local<v8::Context> context, bool skipGCRegistration = false);
3737
static std::shared_ptr<v8::Persistent<v8::Value>> CreateEmptyStruct(v8::Local<v8::Context> context);
3838
static const Meta* FindMeta(Class klass, const TypeEncoding* typeEncoding = nullptr);

NativeScript/runtime/ArgConverter.mm

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@
7878
return Interop::CallFunction(methodCall);
7979
}
8080

81-
Local<Value> ArgConverter::ConvertArgument(Local<Context> context, BaseDataWrapper* wrapper, bool skipGCRegistration) {
81+
Local<Value> ArgConverter::ConvertArgument(Local<Context> context, BaseDataWrapper* wrapper, bool skipGCRegistration, const std::vector<std::string>& additionalProtocols) {
8282
Isolate* isolate = context->GetIsolate();
8383
if (wrapper == nullptr) {
8484
return Null(isolate);
8585
}
8686

87-
Local<Value> result = CreateJsWrapper(context, wrapper, Local<Object>(), skipGCRegistration);
87+
Local<Value> result = CreateJsWrapper(context, wrapper, Local<Object>(), skipGCRegistration, additionalProtocols);
8888
return result;
8989
}
9090

@@ -526,7 +526,7 @@
526526
return args;
527527
}
528528

529-
Local<Value> ArgConverter::CreateJsWrapper(Local<Context> context, BaseDataWrapper* wrapper, Local<Object> receiver, bool skipGCRegistration) {
529+
Local<Value> ArgConverter::CreateJsWrapper(Local<Context> context, BaseDataWrapper* wrapper, Local<Object> receiver, bool skipGCRegistration, const std::vector<std::string>& additionalProtocols) {
530530
Isolate* isolate = context->GetIsolate();
531531

532532
if (wrapper == nullptr) {
@@ -567,7 +567,8 @@
567567
if (meta != nullptr) {
568568
auto cache = Caches::Get(isolate);
569569
KnownUnknownClassPair pair(objc_getClass(meta->name()));
570-
cache->ObjectCtorInitializer(context, static_cast<const BaseClassMeta*>(meta), pair);
570+
std::vector<std::string> emptyProtocols;
571+
cache->ObjectCtorInitializer(context, static_cast<const BaseClassMeta*>(meta), pair, emptyProtocols);
571572
auto it = cache->Prototypes.find(meta);
572573
if (it != cache->Prototypes.end()) {
573574
Local<Value> prototype = it->second->Get(isolate);
@@ -625,14 +626,18 @@
625626
} else {
626627
Class knownClass = objc_getClass(meta->name());
627628
KnownUnknownClassPair pair(knownClass, klass);
628-
cache->ObjectCtorInitializer(context, static_cast<const BaseClassMeta*>(meta), pair);
629-
auto it = cache->Prototypes.find(meta);
630-
if (it != cache->Prototypes.end()) {
631-
Local<Value> prototype = it->second->Get(isolate);
632-
bool success;
633-
if (!receiver->SetPrototype(context, prototype).To(&success) || !success) {
634-
tns::Assert(false, isolate);
635-
}
629+
Local<FunctionTemplate> ctorFuncTemplate = cache->ObjectCtorInitializer(context, static_cast<const BaseClassMeta*>(meta), pair, additionalProtocols);
630+
Local<v8::Function> ctorFunc;
631+
bool success = ctorFuncTemplate->GetFunction(context).ToLocal(&ctorFunc);
632+
tns::Assert(success, isolate);
633+
634+
Local<Value> prototypeValue;
635+
success = ctorFunc->Get(context, tns::ToV8String(isolate, "prototype")).ToLocal(&prototypeValue);
636+
tns::Assert(success, isolate);
637+
Local<Object> prototype = prototypeValue.As<Object>();
638+
639+
if (!receiver->SetPrototype(context, prototype).To(&success) || !success) {
640+
tns::Assert(false, isolate);
636641
}
637642
}
638643
}

NativeScript/runtime/Caches.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define Caches_h
33

44
#include <string>
5+
#include <vector>
56
#include "ConcurrentMap.h"
67
#include "robin_hood.h"
78
#include "Common.h"
@@ -70,7 +71,7 @@ class Caches {
7071
robin_hood::unordered_map<std::pair<void*, std::string>, std::shared_ptr<v8::Persistent<v8::Value>>, pair_hash> StructInstances;
7172
robin_hood::unordered_map<const void*, std::shared_ptr<v8::Persistent<v8::Object>>> PointerInstances;
7273

73-
std::function<v8::Local<v8::FunctionTemplate>(v8::Local<v8::Context>, const BaseClassMeta*, KnownUnknownClassPair)> ObjectCtorInitializer;
74+
std::function<v8::Local<v8::FunctionTemplate>(v8::Local<v8::Context>, const BaseClassMeta*, KnownUnknownClassPair, const std::vector<std::string>&)> ObjectCtorInitializer;
7475
std::function<v8::Local<v8::Function>(v8::Local<v8::Context>, StructInfo)> StructCtorInitializer;
7576
robin_hood::unordered_map<std::string, double> Timers;
7677
robin_hood::unordered_map<const InterfaceMeta*, std::vector<const MethodMeta*>> Initializers;

NativeScript/runtime/Interop.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ class Interop {
139139
static v8::Local<v8::Value> CallFunctionInternal(MethodCall& methodCall);
140140
static bool IsNumbericType(BinaryTypeEncodingType type);
141141
static v8::Local<v8::Object> GetInteropType(v8::Local<v8::Context> context, BinaryTypeEncodingType type);
142-
static void AttachProtocols(v8::Local<v8::Context> context, v8::Local<v8::Object> instance, PtrTo<Array<PtrTo<char>>> protocols, KnownUnknownClassPair pair);
142+
static std::vector<std::string> GetAdditionalProtocols(const TypeEncoding* typeEncoding);
143143

144144
template <typename T>
145145
static inline void SetValue(void* dest, T value) {

NativeScript/runtime/Interop.mm

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,8 @@
792792

793793
auto cache = Caches::Get(isolate);
794794
KnownUnknownClassPair pair;
795-
cache->ObjectCtorInitializer(context, protocolMeta, pair);
795+
std::vector<std::string> emptyProtocols;
796+
cache->ObjectCtorInitializer(context, protocolMeta, pair, emptyProtocols);
796797

797798
auto it = cache->ProtocolCtorFuncs.find(protocolMeta->name());
798799
if (it != cache->ProtocolCtorFuncs.end()) {
@@ -817,7 +818,8 @@
817818
const BaseClassMeta* baseMeta = static_cast<const BaseClassMeta*>(meta);
818819
Class knownClass = meta->type() == MetaType::Interface ? objc_getClass(meta->name()) : nil;
819820
KnownUnknownClassPair pair(knownClass);
820-
cache->ObjectCtorInitializer(context, baseMeta, pair);
821+
std::vector<std::string> emptyProtocols;
822+
cache->ObjectCtorInitializer(context, baseMeta, pair, emptyProtocols);
821823
}
822824

823825
auto it = cache->CtorFuncs.find(name);
@@ -1024,23 +1026,8 @@
10241026
const TypeEncoding* te = [result isProxy] ? typeEncoding : nullptr;
10251027

10261028
ObjCDataWrapper* wrapper = new ObjCDataWrapper(result, te);
1027-
Local<Value> jsResult = ArgConverter::ConvertArgument(context, wrapper);
1028-
1029-
PtrTo<Array<PtrTo<char>>> additionalProtocols;
1030-
int32_t count = 0;
1031-
if (typeEncoding->type == BinaryTypeEncodingType::IdEncoding && typeEncoding->details.idDetails._protocols.offset > 0) {
1032-
additionalProtocols = typeEncoding->details.idDetails._protocols;
1033-
count = additionalProtocols->count;
1034-
} else if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference && typeEncoding->details.interfaceDeclarationReference._protocols.offset > 0) {
1035-
additionalProtocols = typeEncoding->details.interfaceDeclarationReference._protocols;
1036-
count = additionalProtocols->count;
1037-
}
1038-
1039-
if (count > 0) {
1040-
// Attach the protocols to the prototype of the resulting object
1041-
KnownUnknownClassPair pair(nullptr, [result class]);
1042-
Interop::AttachProtocols(context, jsResult.As<Object>(), additionalProtocols, pair);
1043-
}
1029+
std::vector<std::string> additionalProtocols = Interop::GetAdditionalProtocols(typeEncoding);
1030+
Local<Value> jsResult = ArgConverter::ConvertArgument(context, wrapper, false, additionalProtocols);
10441031

10451032
if (ownsReturnedObject || isInitializer) {
10461033
[result release];
@@ -1167,30 +1154,24 @@
11671154
return Local<Value>();
11681155
}
11691156

1170-
void Interop::AttachProtocols(Local<Context> context, Local<Object> instance, PtrTo<Array<PtrTo<char>>> protocols, KnownUnknownClassPair pair) {
1171-
Isolate* isolate = context->GetIsolate();
1172-
std::shared_ptr<Caches> cache = Caches::Get(isolate);
1157+
std::vector<std::string> Interop::GetAdditionalProtocols(const TypeEncoding* typeEncoding) {
1158+
std::vector<std::string> additionalProtocols;
11731159

1174-
Local<Object> prototype = instance->GetPrototype().As<Object>();
1175-
for (auto it = protocols->begin(); it != protocols->end(); it++) {
1176-
const char* protocolName = (*it).valuePtr();
1177-
const Meta* protocolMeta = ArgConverter::GetMeta(protocolName);
1178-
if (protocolMeta == nullptr) {
1179-
continue;
1160+
if (typeEncoding->type == BinaryTypeEncodingType::IdEncoding && typeEncoding->details.idDetails._protocols.offset > 0) {
1161+
PtrTo<Array<String>> protocols = typeEncoding->details.idDetails._protocols;
1162+
for (auto it = protocols->begin(); it != protocols->end(); it++) {
1163+
const char* protocolName = (*it).valuePtr();
1164+
additionalProtocols.push_back(protocolName);
11801165
}
1181-
1182-
cache->ObjectCtorInitializer(context, static_cast<const BaseClassMeta*>(protocolMeta), pair);
1183-
auto protoIt = cache->Prototypes.find(protocolMeta);
1184-
if (protoIt == cache->Prototypes.end()) {
1185-
continue;
1166+
} else if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference && typeEncoding->details.interfaceDeclarationReference._protocols.offset > 0) {
1167+
PtrTo<Array<String>> protocols = typeEncoding->details.interfaceDeclarationReference._protocols;
1168+
for (auto it = protocols->begin(); it != protocols->end(); it++) {
1169+
const char* protocolName = (*it).valuePtr();
1170+
additionalProtocols.push_back(protocolName);
11861171
}
1187-
1188-
Local<Object> protocolPrototype = protoIt->second->Get(isolate).As<Object>();
1189-
1190-
prototype->SetPrototype(context, protocolPrototype).FromMaybe(false);
1191-
1192-
prototype = protocolPrototype;
11931172
}
1173+
1174+
return additionalProtocols;
11941175
}
11951176

11961177
bool Interop::IsNumbericType(BinaryTypeEncodingType type) {

NativeScript/runtime/MetadataBuilder.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ namespace tns {
1313
class MetadataBuilder {
1414
public:
1515
static void RegisterConstantsOnGlobalObject(v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> globalTemplate, bool isWorkerThread);
16-
static v8::Local<v8::FunctionTemplate> GetOrCreateConstructorFunctionTemplate(v8::Local<v8::Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair);
16+
static v8::Local<v8::FunctionTemplate> GetOrCreateConstructorFunctionTemplate(v8::Local<v8::Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair, const std::vector<std::string>& additionalProtocols = std::vector<std::string>());
1717
static v8::Local<v8::Function> GetOrCreateStructCtorFunction(v8::Local<v8::Context> context, StructInfo structInfo);
1818
static void StructPropertyGetterCallback(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info);
1919
static void StructPropertySetterCallback(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info);
2020
private:
21-
static v8::Local<v8::FunctionTemplate> GetOrCreateConstructorFunctionTemplateInternal(v8::Local<v8::Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& instanceMembers, robin_hood::unordered_map<std::string, uint8_t>& staticMembers);
21+
static v8::Local<v8::FunctionTemplate> GetOrCreateConstructorFunctionTemplateInternal(v8::Local<v8::Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& instanceMembers, robin_hood::unordered_map<std::string, uint8_t>& staticMembers, const std::vector<std::string>& additionalProtocols = std::vector<std::string>());
2222
static void GlobalPropertyGetter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info);
2323
static void ClassConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
2424
static void AllocCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
@@ -38,6 +38,7 @@ class MetadataBuilder {
3838
static void RegisterInstanceMethods(v8::Local<v8::Context> context, v8::Local<v8::FunctionTemplate> ctorFuncTemplate, const BaseClassMeta* meta, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& names);
3939
static void RegisterInstanceProperties(v8::Local<v8::Context> context, v8::Local<v8::FunctionTemplate> ctorFuncTemplate, const BaseClassMeta* meta, std::string className, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& names);
4040
static void RegisterInstanceProtocols(v8::Local<v8::Context> context, v8::Local<v8::FunctionTemplate> ctorFuncTemplate, const BaseClassMeta* meta, std::string className, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& names);
41+
static void RegisterAdditionalProtocols(v8::Local<v8::Context> context, v8::Local<v8::FunctionTemplate> ctorFuncTemplate, KnownUnknownClassPair pair, const std::vector<std::string>& additionalProtocols, robin_hood::unordered_map<std::string, uint8_t>& names);
4142
static void RegisterStaticMethods(v8::Local<v8::Context> context, v8::Local<v8::Function> ctorFunc, const BaseClassMeta* meta, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& names);
4243
static void RegisterStaticProperties(v8::Local<v8::Context> context, v8::Local<v8::Function> ctorFunc, const BaseClassMeta* meta, const std::string className, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& names);
4344
static void RegisterStaticProtocols(v8::Local<v8::Context> context, v8::Local<v8::Function> ctorFunc, const BaseClassMeta* meta, const std::string className, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& names);

NativeScript/runtime/MetadataBuilder.mm

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,20 +265,23 @@
265265
return std::make_pair(ffiType, data);
266266
}
267267

268-
Local<FunctionTemplate> MetadataBuilder::GetOrCreateConstructorFunctionTemplate(Local<Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair) {
268+
Local<FunctionTemplate> MetadataBuilder::GetOrCreateConstructorFunctionTemplate(Local<Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair, const std::vector<std::string>& additionalProtocols) {
269269
robin_hood::unordered_map<std::string, uint8_t> instanceMembers;
270270
robin_hood::unordered_map<std::string, uint8_t> staticMembers;
271-
return MetadataBuilder::GetOrCreateConstructorFunctionTemplateInternal(context, meta, pair, instanceMembers, staticMembers);
271+
return MetadataBuilder::GetOrCreateConstructorFunctionTemplateInternal(context, meta, pair, instanceMembers, staticMembers, additionalProtocols);
272272
}
273273

274-
Local<FunctionTemplate> MetadataBuilder::GetOrCreateConstructorFunctionTemplateInternal(Local<Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& instanceMembers, robin_hood::unordered_map<std::string, uint8_t>& staticMembers) {
274+
Local<FunctionTemplate> MetadataBuilder::GetOrCreateConstructorFunctionTemplateInternal(Local<Context> context, const BaseClassMeta* meta, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& instanceMembers, robin_hood::unordered_map<std::string, uint8_t>& staticMembers, const std::vector<std::string>& additionalProtocols) {
275275
Isolate* isolate = context->GetIsolate();
276276
Local<FunctionTemplate> ctorFuncTemplate;
277277
auto cache = Caches::Get(isolate);
278-
auto it = cache->CtorFuncTemplates.find(meta);
279-
if (it != cache->CtorFuncTemplates.end()) {
280-
ctorFuncTemplate = it->second->Get(isolate);
281-
return ctorFuncTemplate;
278+
279+
if (additionalProtocols.empty()) {
280+
auto it = cache->CtorFuncTemplates.find(meta);
281+
if (it != cache->CtorFuncTemplates.end()) {
282+
ctorFuncTemplate = it->second->Get(isolate);
283+
return ctorFuncTemplate;
284+
}
282285
}
283286

284287
std::string className;
@@ -325,6 +328,7 @@
325328
MetadataBuilder::RegisterInstanceProperties(context, ctorFuncTemplate, meta, meta->name(), pair, instanceMembers);
326329
MetadataBuilder::RegisterInstanceMethods(context, ctorFuncTemplate, meta, pair, instanceMembers);
327330
MetadataBuilder::RegisterInstanceProtocols(context, ctorFuncTemplate, meta, meta->name(), pair, instanceMembers);
331+
MetadataBuilder::RegisterAdditionalProtocols(context, ctorFuncTemplate, pair, additionalProtocols, instanceMembers);
328332

329333
ctorFuncTemplate->PrototypeTemplate()->Set(tns::ToV8String(isolate, "toString"), FunctionTemplate::New(isolate, MetadataBuilder::ToStringFunctionCallback));
330334

@@ -482,6 +486,25 @@
482486
}
483487
}
484488

489+
void MetadataBuilder::RegisterAdditionalProtocols(Local<Context> context, Local<FunctionTemplate> ctorFuncTemplate, KnownUnknownClassPair pair, const std::vector<std::string>& additionalProtocols, robin_hood::unordered_map<std::string, uint8_t>& names) {
490+
for (std::string protocolName : additionalProtocols) {
491+
const Meta* meta = ArgConverter::GetMeta(protocolName.c_str());
492+
if (meta != nullptr) {
493+
const BaseClassMeta* baseMeta = static_cast<const BaseClassMeta*>(meta);
494+
MetadataBuilder::RegisterInstanceMethods(context, ctorFuncTemplate, baseMeta, pair, names);
495+
MetadataBuilder::RegisterInstanceProperties(context, ctorFuncTemplate, baseMeta, baseMeta->name(), pair, names);
496+
497+
std::vector<std::string> metaProtocols;
498+
for (auto it = baseMeta->protocols->begin(); it != baseMeta->protocols->end(); it++) {
499+
std::string name = (*it).valuePtr();
500+
metaProtocols.push_back(name);
501+
}
502+
503+
MetadataBuilder::RegisterAdditionalProtocols(context, ctorFuncTemplate, pair, metaProtocols, names);
504+
}
505+
}
506+
}
507+
485508
void MetadataBuilder::RegisterStaticMethods(Local<Context> context, Local<v8::Function> ctorFunc, const BaseClassMeta* meta, KnownUnknownClassPair pair, robin_hood::unordered_map<std::string, uint8_t>& names) {
486509
Isolate* isolate = context->GetIsolate();
487510
for (auto it = meta->staticMethods->begin(); it != meta->staticMethods->end(); it++) {

TestFixtures/Api/TNSPseudoDataTypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
@protocol Proto1
44

5+
@property (nonatomic) NSString* propertyFromProto1;
56
-(void)methodFromProto1;
67

78
@end
89

910
@protocol Proto2
1011

12+
@property (nonatomic) NSString* propertyFromProto2;
1113
-(void)methodFromProto2:(NSString*)param;
1214

1315
@end

TestFixtures/Api/TNSPseudoDataTypes.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ -(void)method {
1919

2020
@implementation TNSPseudoDataTypeInternal
2121

22+
@synthesize propertyFromProto1;
23+
@synthesize propertyFromProto2;
24+
2225
-(void)methodFromProto1 {
2326
TNSLog(@"methodFromProto1 called");
2427
}
@@ -33,11 +36,15 @@ @implementation TNSPseudoDataType
3336

3437
+(id<Proto1, Proto2>)getId {
3538
TNSPseudoDataTypeInternal* internal = [[TNSPseudoDataTypeInternal alloc] init];
39+
internal.propertyFromProto1 = @"property from proto1";
40+
internal.propertyFromProto2 = @"property from proto2";
3641
return internal;
3742
}
3843

3944
+(TNSType<Proto1, Proto2>*)getType {
4045
TNSPseudoDataTypeInternal* internal = [[TNSPseudoDataTypeInternal alloc] init];
46+
internal.propertyFromProto1 = @"property from proto1";
47+
internal.propertyFromProto2 = @"property from proto2";
4148
return internal;
4249
}
4350

0 commit comments

Comments
 (0)