Skip to content

Commit 77ff417

Browse files
authored
Merge pull request #843 from NativeScript/pete/fix-ctor-calls
Improve exceptions when incorrectly instantiating interfaces
2 parents 6bc64ce + a4e0f99 commit 77ff417

File tree

3 files changed

+26
-7
lines changed

3 files changed

+26
-7
lines changed

runtime/src/main/jni/MetadataNode.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -655,15 +655,10 @@ void MetadataNode::SetInnerTypes(Isolate* isolate, Local<Function>& ctorFunction
655655
if (treeNode->children != nullptr) {
656656
const auto& children = *treeNode->children;
657657

658-
// // prototype of outer class
659-
// auto prototypeTemplate2 = ctorFunction->Get(V8StringConstants::GetPrototype(isolate)).As<Object>();
660-
661658
for (auto curChild : children) {
662659
auto childNode = GetOrCreateInternal(curChild);
663660

664-
auto type = s_metadataReader.GetNodeType(curChild);
665-
auto isStatic = s_metadataReader.IsNodeTypeStatic(type);
666-
661+
// The call to GetConstructorFunctionTemplate bootstraps the ctor function for the childNode
667662
auto innerTypeCtorFuncTemplate = childNode->GetConstructorFunctionTemplate(isolate, curChild);
668663
auto innerTypeCtorFunc = Local<Function>::New(isolate, *GetOrCreateInternal(curChild)->GetPersistentConstructorFunction(isolate));
669664
auto innerTypeName = ArgConverter::ConvertToV8String(isolate, curChild->name);
@@ -684,6 +679,8 @@ Local<FunctionTemplate> MetadataNode::GetConstructorFunctionTemplate(Isolate* is
684679
SET_PROFILER_FRAME();
685680
tns::instrumentation::Frame frame;
686681

682+
v8::HandleScope handleScope(isolate);
683+
687684
//try get cached "ctorFuncTemplate"
688685
Local<FunctionTemplate> ctorFuncTemplate;
689686
auto cache = GetMetadataNodeCache(isolate);
@@ -817,12 +814,16 @@ void MetadataNode::ExtendedClassConstructorCallback(const v8::FunctionCallbackIn
817814
try {
818815
SET_PROFILER_FRAME();
819816

820-
assert(info.IsConstructCall());
817+
if (!info.IsConstructCall()) {
818+
throw NativeScriptException(string("Incorrectly calling a Java class as a method. Class must be created by invoking its constructor with the `new` keyword."));
819+
}
821820

822821
auto isolate = info.GetIsolate();
823822
auto thiz = info.This();
824823
auto extData = reinterpret_cast<ExtendedClassCallbackData*>(info.Data().As<External>()->Value());
825824

825+
v8::HandleScope handleScope(isolate);
826+
826827
auto implementationObject = Local<Object>::New(isolate, *extData->implementationObject);
827828

828829
const auto& extendName = extData->extendedName;
@@ -854,10 +855,16 @@ void MetadataNode::InterfaceConstructorCallback(const v8::FunctionCallbackInfo<v
854855
try {
855856
SET_PROFILER_FRAME();
856857

858+
if (!info.IsConstructCall()) {
859+
throw NativeScriptException(string("Interface implementation must be invoked as a constructor with the `new` keyword."));
860+
}
861+
857862
auto isolate = info.GetIsolate();
858863
auto thiz = info.This();
859864
auto node = reinterpret_cast<MetadataNode*>(info.Data().As<External>()->Value());
860865

866+
v8::HandleScope handleScope(isolate);
867+
861868
Local<Object> implementationObject;
862869
Local<String> v8ExtendName;
863870

test-app/app/src/main/assets/app/tests/extendedClassesTests.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,12 @@ describe("Tests extended classes ", function () {
7373

7474
expect(labelgetIMAGE_ID_PROP1).toBe(labelgetIMAGE_ID_PROP2);
7575
});
76+
77+
it("should not crash with no exception when incorrectly calling extended class constructor", function () {
78+
let MyObj = java.lang.Object.extend({
79+
toString: () => { return "It's MyObj" }
80+
});
81+
82+
expect(() => { myObj() }).toThrow();
83+
});
7684
});

test-app/app/src/main/assets/app/tests/testInterfaceImplementation.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,8 @@ describe("Tests Java interfaces are implemented correctly", function () {
2727

2828
expect(callClose).toBe(true);
2929
});
30+
31+
it("should not crash with no exception when calling interface incorrectly", function () {
32+
expect(() => { java.lang.Runnable({ run: () => { android.util.Log.d("Log", ""); } }) }).toThrow();
33+
});
3034
});

0 commit comments

Comments
 (0)