diff --git a/Makefile b/Makefile index a4f68303..a29287b4 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,7 @@ LINT_SOURCES = \ test/cpp/morenews.cpp \ test/cpp/converters.cpp \ test/cpp/isolatedata.cpp \ + test/cpp/global.cpp \ test/cpp/makecallback.cpp \ test/cpp/morenews.cpp \ test/cpp/multifile1.cpp \ diff --git a/test/binding.gyp b/test/binding.gyp index afc2882c..bd548835 100644 --- a/test/binding.gyp +++ b/test/binding.gyp @@ -148,4 +148,8 @@ "target_name" : "typedarrays" , "sources" : [ "cpp/typedarrays.cpp" ] } + , { + "target_name" : "global" + , "sources" : [ "cpp/global.cpp" ] + } ]} diff --git a/test/cpp/global.cpp b/test/cpp/global.cpp new file mode 100644 index 00000000..112f7c8b --- /dev/null +++ b/test/cpp/global.cpp @@ -0,0 +1,75 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2016 NAN contributors + * + * MIT License + ********************************************************************/ + +#include + +using namespace Nan; // NOLINT(build/namespaces) + +template Global passer(v8::Local handle) { + return Global(handle).Pass(); +} + +NAN_METHOD(PassGlobal) { + info.GetReturnValue().Set(passer(New(42))); +} + +NAN_METHOD(EmptyGlobal) { + Global g(New("value").ToLocalChecked()); + bool b1 = !g.IsEmpty(); + g.Empty(); // this will leak, never do it + info.GetReturnValue().Set(b1 && g.IsEmpty()); +} + +NAN_METHOD(MoveConstructGlobal) { + Global g(Global(New("value").ToLocalChecked())); + info.GetReturnValue().Set(!g.IsEmpty()); +} + +NAN_METHOD(CopyConstructGlobal) { + Persistent p(New("value").ToLocalChecked()); + bool b1 = !p.IsEmpty(); + Global g(p); + bool b2 = !p.IsEmpty(); + p.Reset(); + info.GetReturnValue().Set(b1 && b2 && !g.IsEmpty()); +} + +NAN_METHOD(MoveAssignGlobal) { + Global g = passer(New("value").ToLocalChecked()); + info.GetReturnValue().Set(!g.IsEmpty()); +} + +NAN_MODULE_INIT(Init) { + Set(target + , New("passGlobal").ToLocalChecked() + , GetFunction(New(PassGlobal)) + .ToLocalChecked() + ); + Set(target + , New("emptyGlobal").ToLocalChecked() + , GetFunction(New(EmptyGlobal)) + .ToLocalChecked() + ); + Set(target + , New("moveConstructGlobal").ToLocalChecked() + , GetFunction(New(MoveConstructGlobal)) + .ToLocalChecked() + ); + Set(target + , New("copyConstructGlobal").ToLocalChecked() + , GetFunction(New(CopyConstructGlobal)) + .ToLocalChecked() + ); + Set(target + , New("moveAssignGlobal").ToLocalChecked() + , GetFunction(New(MoveAssignGlobal)) + .ToLocalChecked() + ); +} + +NODE_MODULE(global, Init) diff --git a/test/cpp/persistent.cpp b/test/cpp/persistent.cpp index e28b17ce..4d3504a3 100644 --- a/test/cpp/persistent.cpp +++ b/test/cpp/persistent.cpp @@ -12,6 +12,7 @@ using namespace Nan; // NOLINT(build/namespaces) static Persistent persistentTest1; +static Persistent persistentTest2; NAN_METHOD(Save1) { persistentTest1.Reset(info[0].As()); @@ -55,6 +56,39 @@ NAN_METHOD(PassGlobal) { info.GetReturnValue().Set(passer(New(42))); } +NAN_METHOD(EmptyPersistent) { + persistentTest2.Reset(New("value").ToLocalChecked()); + bool b1 = !persistentTest2.IsEmpty(); + persistentTest2.Empty(); // this will leak, never do it + info.GetReturnValue().Set(b1 && persistentTest2.IsEmpty()); +} + +NAN_METHOD(EmptyGlobal) { + Global g(New("value").ToLocalChecked()); + bool b1 = !g.IsEmpty(); + g.Empty(); // this will leak, never do it + info.GetReturnValue().Set(b1 && g.IsEmpty()); +} + +NAN_METHOD(MoveConstructGlobal) { + Global g(Global(New("value").ToLocalChecked())); + info.GetReturnValue().Set(!g.IsEmpty()); +} + +NAN_METHOD(CopyConstructGlobal) { + Persistent p(New("value").ToLocalChecked()); + bool b1 = !p.IsEmpty(); + Global g(p); + bool b2 = !p.IsEmpty(); + p.Reset(); + info.GetReturnValue().Set(b1 && b2 && !g.IsEmpty()); +} + +NAN_METHOD(MoveAssignGlobal) { + Global g = passer(New("value").ToLocalChecked()); + info.GetReturnValue().Set(!g.IsEmpty()); +} + NAN_MODULE_INIT(Init) { Set(target , New("save1").ToLocalChecked() @@ -88,6 +122,31 @@ NAN_MODULE_INIT(Init) { , GetFunction(New(PassGlobal)) .ToLocalChecked() ); + Set(target + , New("emptyPersistent").ToLocalChecked() + , GetFunction(New(EmptyPersistent)) + .ToLocalChecked() + ); + Set(target + , New("emptyGlobal").ToLocalChecked() + , GetFunction(New(EmptyGlobal)) + .ToLocalChecked() + ); + Set(target + , New("moveConstructGlobal").ToLocalChecked() + , GetFunction(New(MoveConstructGlobal)) + .ToLocalChecked() + ); + Set(target + , New("copyConstructGlobal").ToLocalChecked() + , GetFunction(New(CopyConstructGlobal)) + .ToLocalChecked() + ); + Set(target + , New("moveAssignGlobal").ToLocalChecked() + , GetFunction(New(MoveAssignGlobal)) + .ToLocalChecked() + ); } NODE_MODULE(persistent, Init) diff --git a/test/cpp/weak.cpp b/test/cpp/weak.cpp index fcf7960a..cc0ad509 100644 --- a/test/cpp/weak.cpp +++ b/test/cpp/weak.cpp @@ -11,6 +11,7 @@ using namespace Nan; // NOLINT(build/namespaces) static Persistent cb; +static Global gcb; void weakCallback( const WeakCallbackInfo &data) { // NOLINT(runtime/references) @@ -30,16 +31,35 @@ v8::Local wrap(v8::Local func) { return scope.Escape(lstring); } +v8::Local gwrap(v8::Local func) { + EscapableHandleScope scope; + v8::Local lstring = New("result").ToLocalChecked(); + int *parameter = new int(42); + gcb.Reset(func); + gcb.SetWeak(parameter, weakCallback, WeakCallbackType::kParameter); + assert(gcb.IsWeak()); + return scope.Escape(lstring); +} + NAN_METHOD(Hustle) { cb.Reset(info[1].As()); info.GetReturnValue().Set(wrap(info[0].As())); } +NAN_METHOD(HustleGlobal) { + cb.Reset(info[1].As()); + info.GetReturnValue().Set(gwrap(info[0].As())); +} + NAN_MODULE_INIT(Init) { Set(target , New("hustle").ToLocalChecked() , New(Hustle)->GetFunction() ); + Set(target + , New("hustleGlobal").ToLocalChecked() + , New(HustleGlobal)->GetFunction() + ); } NODE_MODULE(weak, Init) diff --git a/test/js/global-test.js b/test/js/global-test.js new file mode 100644 index 00000000..eea19c05 --- /dev/null +++ b/test/js/global-test.js @@ -0,0 +1,28 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2016 NAN contributors + * + * MIT License + ********************************************************************/ + +const test = require('tap').test + , testRoot = require('path').resolve(__dirname, '..') + , bindings = require('bindings')({ module_root: testRoot, bindings: 'global' }); + +test('global', function (t) { + t.plan(10); + + var global_ = bindings; + t.type(global_.passGlobal, 'function'); + t.type(global_.emptyGlobal, 'function'); + t.type(global_.moveConstructGlobal, 'function'); + t.type(global_.copyConstructGlobal, 'function'); + t.type(global_.moveAssignGlobal, 'function'); + + t.equal(global_.passGlobal(), 42, 'pass global'); + t.ok(global_.emptyGlobal()); + t.ok(global_.moveConstructGlobal()); + t.ok(global_.copyConstructGlobal()); + t.ok(global_.moveAssignGlobal()); +}); diff --git a/test/js/persistent-test.js b/test/js/persistent-test.js index b7dd33ff..3707d912 100644 --- a/test/js/persistent-test.js +++ b/test/js/persistent-test.js @@ -20,7 +20,9 @@ test('persistent', function (t) { t.type(persistent.toPersistentAndBackAgain, 'function'); t.type(persistent.persistentToPersistent, 'function'); t.type(persistent.copyablePersistent, 'function'); - t.type(persistent.passGlobal, 'function'); + t.type(persistent.emptyPersistent, 'function'); + + t.ok(persistent.emptyPersistent()); t.deepEqual(persistent.toPersistentAndBackAgain({ x: 42 }), { x: 42 }); @@ -30,8 +32,6 @@ test('persistent', function (t) { t.equal(persistent.get1(), 'a string to save'); t.equal(persistent.copyablePersistent(), 'a string to save'); - t.equal(persistent.passGlobal(), 42, 'pass global'); - setTimeout(function () { t.equal(persistent.get1(), 'a string to save'); persistent.dispose1(); diff --git a/test/js/weak-test.js b/test/js/weak-test.js index 5c91590a..4c842aaa 100644 --- a/test/js/weak-test.js +++ b/test/js/weak-test.js @@ -11,10 +11,11 @@ const test = require('tap').test , bindings = require('bindings')({ module_root: testRoot, bindings: 'weak' }); test('weak', function (t) { - t.plan(3); + t.plan(6); var weak = bindings, count = 0; t.type(weak.hustle, 'function'); + t.type(weak.hustleGlobal, 'function'); weak.hustle(function () {}, function (val) { t.equal(val, 42); @@ -27,5 +28,20 @@ test('weak', function (t) { // do not run weak callback gc(); + t.equal(count, 1); + + count = 0; + + weak.hustleGlobal(function () {}, function (val) { + t.equal(val, 42); + count++; + }); + + // run weak callback, should dispose + gc(); + + // do not run weak callback + gc(); + t.equal(count, 1); });