Skip to content

Commit 8e9671d

Browse files
authored
Merge pull request #1258 from NativeScript/vmutafov/release-native-counterpart
Add releaseNativeCounterpart JS function for releasing the native par…
2 parents 03dc822 + 65597c3 commit 8e9671d

File tree

10 files changed

+457
-122
lines changed

10 files changed

+457
-122
lines changed

test-app/app/src/main/assets/app/mainpage.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ require("./tests/byte-buffer-test");
5252
require("./tests/dex-interface-implementation");
5353
require("./tests/testInterfaceImplementation");
5454
require("./tests/testRuntimeImplementedAPIs");
55-
require("./tests/testsInstanceOfOperator");
55+
require("./tests/testsInstanceOfOperator");
56+
require("./tests/testReleaseNativeCounterpart");
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
describe("Test native counterpart release", function () {
2+
3+
var myCustomEquality = function(first, second) {
4+
return first == second;
5+
};
6+
7+
beforeEach(function() {
8+
jasmine.addCustomEqualityTester(myCustomEquality);
9+
});
10+
11+
it("Calling a method on a released object should throw exception", function () {
12+
13+
var errorMessage = "";
14+
15+
try{
16+
var object1 = new java.lang.Object();
17+
18+
global.__releaseNativeCounterpart(object1);
19+
20+
object1.toString();
21+
} catch(e){
22+
errorMessage = e.message;
23+
}
24+
25+
expect(errorMessage).toBe("Failed calling toString on a java/lang/Object instance. The JavaScript instance no longer has available Java instance counterpart.");
26+
});
27+
28+
it("Calling release on a non native object should throw exception", function () {
29+
30+
var errorMessage = "";
31+
32+
try{
33+
var object2 = {prop: "test"};
34+
global.__releaseNativeCounterpart(object2);
35+
} catch(e){
36+
errorMessage = e.message;
37+
}
38+
39+
expect(errorMessage).toBe("Trying to release a non native object!");
40+
});
41+
42+
43+
it("Calling release on a non native primitive type should throw exception", function () {
44+
45+
var errorMessage = "";
46+
47+
try{
48+
global.__releaseNativeCounterpart(42);
49+
} catch(e){
50+
errorMessage = e.message;
51+
}
52+
53+
expect(errorMessage).toBe("Argument is not an object!");
54+
});
55+
56+
it("Calling the __releaseNativeCounterpart function with 0 arguments should throw exception", function(){
57+
var errorMessage = "";
58+
59+
try{
60+
global.__releaseNativeCounterpart();
61+
} catch(e){
62+
errorMessage = e.message;
63+
}
64+
65+
expect(errorMessage).toBe("Unexpected arguments count!");
66+
});
67+
68+
it("Calling the __releaseNativeCounterpart function with more than 1 arguments should throw exception", function(){
69+
var errorMessage = "";
70+
71+
try{
72+
global.__releaseNativeCounterpart({},{});
73+
} catch(e){
74+
errorMessage = e.message;
75+
}
76+
77+
expect(errorMessage).toBe("Unexpected arguments count!");
78+
});
79+
80+
81+
});

test-app/runtime/build.gradle

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ android {
6161
arguments.push("-DOPTIMIZED_WITH_INSPECTOR_BUILD=true")
6262
}
6363

64-
if(useCCache) {
64+
if (useCCache) {
6565
arguments.push("-DUSE_CCACHE=true")
6666
}
6767

@@ -104,6 +104,8 @@ allprojects {
104104

105105
dependencies {
106106
implementation fileTree(include: ['*.jar'], dir: 'libs')
107+
testImplementation 'junit:junit:4.12'
108+
testImplementation 'org.mockito:mockito-core:1.10.19'
107109
}
108110

109111
tasks.whenTaskAdded { task ->
@@ -112,6 +114,11 @@ tasks.whenTaskAdded { task ->
112114
setRuntimeCommit.dependsOn(setPackageVersion)
113115
task.dependsOn(setRuntimeCommit)
114116
}
117+
118+
if(taskName.contains("bundleReleaseAar")){
119+
task.dependsOn("testDebugUnitTest")
120+
}
121+
115122
if (taskName.contains("Strip")) {
116123
task.finalizedBy(revertVersionFile)
117124
}

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

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,9 @@ CallbackHandlers::GetImplementedInterfaces(JEnv &env, const Local<Object> &imple
573573
auto interfacesArr = prop->ToObject(isolate);
574574

575575
auto context = isolate->GetCurrentContext();
576-
int length = interfacesArr->Get(v8::String::NewFromUtf8(isolate, "length"))->ToObject(isolate)->Uint32Value(context).ToChecked();
576+
int length = interfacesArr->Get(
577+
v8::String::NewFromUtf8(isolate, "length"))->ToObject(isolate)->Uint32Value(
578+
context).ToChecked();
577579

578580
if (length > 0) {
579581
for (int i = 0; i < length; i++) {
@@ -670,6 +672,38 @@ void CallbackHandlers::TimeCallback(const v8::FunctionCallbackInfo<v8::Value> &a
670672
args.GetReturnValue().Set(duration);
671673
}
672674

675+
void CallbackHandlers::ReleaseNativeCounterpartCallback(
676+
const v8::FunctionCallbackInfo<v8::Value> &info) {
677+
try {
678+
SET_PROFILER_FRAME();
679+
680+
validateProvidedArgumentsLength(info, 1);
681+
682+
auto isolate = info.GetIsolate();
683+
Handle<Object> obj = info[0].As<Object>();
684+
685+
auto runtime = Runtime::GetRuntime(isolate);
686+
auto objectManager = runtime->GetObjectManager();
687+
objectManager->ReleaseNativeCounterpart(obj);
688+
} catch (NativeScriptException &e) {
689+
e.ReThrowToV8();
690+
} catch (std::exception e) {
691+
stringstream ss;
692+
ss << "Error: c++ exception: " << e.what() << endl;
693+
NativeScriptException nsEx(ss.str());
694+
nsEx.ReThrowToV8();
695+
} catch (...) {
696+
NativeScriptException nsEx(std::string("Error: c++ exception!"));
697+
nsEx.ReThrowToV8();
698+
}
699+
}
700+
701+
void CallbackHandlers::validateProvidedArgumentsLength(const v8::FunctionCallbackInfo<v8::Value> &args, int expectedSize) {
702+
if(args.Length() != expectedSize){
703+
throw NativeScriptException("Unexpected arguments count!");
704+
}
705+
}
706+
673707
void CallbackHandlers::DumpReferenceTablesMethodCallback(
674708
const v8::FunctionCallbackInfo<v8::Value> &args) {
675709
DumpReferenceTablesMethod();
@@ -887,8 +921,11 @@ void CallbackHandlers::NewThreadCallback(const v8::FunctionCallbackInfo<v8::Valu
887921
auto thiz = args.This();
888922
auto isolate = thiz->GetIsolate();
889923

890-
auto currentExecutingScriptName = StackTrace::CurrentStackTrace(isolate, 1, StackTrace::kScriptName)->GetFrame(isolate, 0)->GetScriptName();
891-
auto currentExecutingScriptNameStr = ArgConverter::ConvertToString(currentExecutingScriptName);
924+
auto currentExecutingScriptName = StackTrace::CurrentStackTrace(isolate, 1,
925+
StackTrace::kScriptName)->GetFrame(
926+
isolate, 0)->GetScriptName();
927+
auto currentExecutingScriptNameStr = ArgConverter::ConvertToString(
928+
currentExecutingScriptName);
892929
auto lastForwardSlash = currentExecutingScriptNameStr.find_last_of("/");
893930
auto currentDir = currentExecutingScriptNameStr.substr(0, lastForwardSlash + 1);
894931
string fileSchema("file://");
@@ -1444,6 +1481,8 @@ jmethodID CallbackHandlers::ENABLE_VERBOSE_LOGGING_METHOD_ID = nullptr;
14441481
jmethodID CallbackHandlers::DISABLE_VERBOSE_LOGGING_METHOD_ID = nullptr;
14451482
jmethodID CallbackHandlers::INIT_WORKER_METHOD_ID = nullptr;
14461483

1484+
1485+
14471486
NumericCasts CallbackHandlers::castFunctions;
14481487
ArrayElementAccessor CallbackHandlers::arrayElementAccessor;
14491488
FieldAccessor CallbackHandlers::fieldAccessor;

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ namespace tns {
111111
static void
112112
DisableVerboseLoggingMethodCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
113113

114+
static void ReleaseNativeCounterpartCallback(const v8::FunctionCallbackInfo<v8::Value> &info);
115+
114116
static v8::Local<v8::Object> FindClass(v8::Isolate *isolate, const std::string &className);
115117

116118
static void NewThreadCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
@@ -194,6 +196,8 @@ namespace tns {
194196
*/
195197
static jobjectArray GetJavaStringArray(JEnv &env, int length);
196198

199+
static void validateProvidedArgumentsLength(const v8::FunctionCallbackInfo<v8::Value> &args, int expectedSize);
200+
197201
static short MAX_JAVA_STRING_ARRAY_LENGTH;
198202

199203
static jclass RUNTIME_CLASS;
@@ -235,6 +239,8 @@ namespace tns {
235239
jfieldID _fieldID;
236240
jobject _runtime;
237241
};
242+
243+
238244
};
239245
}
240246

0 commit comments

Comments
 (0)