From 7df0e459b6da75f6ebddedb003f391df7c1959c9 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 12 Jul 2016 18:37:28 -0400 Subject: [PATCH] [node] NodeRequest inherits from Nan::AsyncWorker drop NodeRequest::Create, move MakeCallback to NodeRequest::Execute rework Respond -> HandleCallback modern NAN style updates --- platform/node/src/node_conversion.hpp | 8 +- platform/node/src/node_log.cpp | 2 +- platform/node/src/node_map.cpp | 78 ++++++----- platform/node/src/node_map.hpp | 39 +++--- platform/node/src/node_mapbox_gl_native.cpp | 10 +- platform/node/src/node_request.cpp | 142 +++++++++----------- platform/node/src/node_request.hpp | 30 +++-- 7 files changed, 153 insertions(+), 156 deletions(-) diff --git a/platform/node/src/node_conversion.hpp b/platform/node/src/node_conversion.hpp index 2418a7a6e..4be1670ea 100644 --- a/platform/node/src/node_conversion.hpp +++ b/platform/node/src/node_conversion.hpp @@ -41,10 +41,10 @@ inline bool isObject(v8::Local value) { inline optional> objectMember(v8::Local value, const char * name) { Nan::EscapableHandleScope scope; - if (!Nan::Has(value->ToObject(), Nan::New(name).ToLocalChecked()).FromJust()) { + if (!Nan::Has(Nan::To(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) { return {}; } - Nan::MaybeLocal result = Nan::Get(value->ToObject(), Nan::New(name).ToLocalChecked()); + Nan::MaybeLocal result = Nan::Get(Nan::To(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()); if (result.IsEmpty()) { return {}; } @@ -54,10 +54,10 @@ inline optional> objectMember(v8::Local value, c template optional eachMember(v8::Local value, Fn&& fn) { Nan::HandleScope scope; - v8::Local names = value->ToObject()->GetOwnPropertyNames(); + v8::Local names = Nan::GetOwnPropertyNames(Nan::To(value).ToLocalChecked()).ToLocalChecked(); for (uint32_t i = 0; i < names->Length(); ++i) { v8::Local k = Nan::Get(names, i).ToLocalChecked(); - v8::Local v = Nan::Get(value->ToObject(), k).ToLocalChecked(); + v8::Local v = Nan::Get(Nan::To(value).ToLocalChecked(), k).ToLocalChecked(); optional result = fn(*Nan::Utf8String(k), v); if (result) { return result; diff --git a/platform/node/src/node_log.cpp b/platform/node/src/node_log.cpp index 21eaa55bc..987237690 100644 --- a/platform/node/src/node_log.cpp +++ b/platform/node/src/node_log.cpp @@ -42,7 +42,7 @@ NodeLogObserver::NodeLogObserver(v8::Local target) v8::Local argv[] = { Nan::New("message").ToLocalChecked(), msg }; auto handle = Nan::New(module); - auto emit = Nan::Get(handle, Nan::New("emit").ToLocalChecked()).ToLocalChecked()->ToObject(); + auto emit = Nan::To(Nan::Get(handle, Nan::New("emit").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); Nan::CallAsFunction(emit, handle, 2, argv); })) { Nan::HandleScope scope; diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 00a3041f2..e89089ecb 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -32,9 +32,6 @@ struct NodeMap::RenderOptions { mbgl::MapDebugOptions debugOptions = mbgl::MapDebugOptions::NoDebug; }; -//////////////////////////////////////////////////////////////////////////////////////////////// -// Static Node Methods - Nan::Persistent NodeMap::constructor; static std::shared_ptr sharedDisplay() { @@ -114,7 +111,7 @@ NAN_MODULE_INIT(NodeMap::Init) { * fs.writeFileSync('image.png', image); * }); */ -NAN_METHOD(NodeMap::New) { +void NodeMap::New(const Nan::FunctionCallbackInfo& info) { if (!info.IsConstructCall()) { return Nan::ThrowTypeError("Use the new operator to create new Map objects"); } @@ -123,7 +120,7 @@ NAN_METHOD(NodeMap::New) { return Nan::ThrowTypeError("Requires an options object as first argument"); } - auto options = info[0]->ToObject(); + auto options = Nan::To(info[0]).ToLocalChecked(); // Check that 'request' is set. If 'cancel' is set it must be a // function and if 'ratio' is set it must be a number. @@ -157,9 +154,12 @@ NAN_METHOD(NodeMap::New) { std::string StringifyStyle(v8::Local styleHandle) { Nan::HandleScope scope; - v8::Local JSON = Nan::Get( - Nan::GetCurrentContext()->Global(), - Nan::New("JSON").ToLocalChecked()).ToLocalChecked()->ToObject(); + v8::Local JSON = Nan::To( + Nan::Get( + Nan::GetCurrentContext()->Global(), + Nan::New("JSON").ToLocalChecked() + ).ToLocalChecked() + ).ToLocalChecked(); return *Nan::Utf8String(Nan::MakeCallback(JSON, "stringify", 1, &styleHandle)); } @@ -179,7 +179,7 @@ std::string StringifyStyle(v8::Local styleHandle) { * // providing a string * map.load(fs.readFileSync('./test/fixtures/style.json', 'utf8')); */ -NAN_METHOD(NodeMap::Load) { +void NodeMap::Load(const Nan::FunctionCallbackInfo& info) { auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -212,7 +212,7 @@ NAN_METHOD(NodeMap::Load) { info.GetReturnValue().SetUndefined(); } -NAN_METHOD(NodeMap::Loaded) { +void NodeMap::Loaded(const Nan::FunctionCallbackInfo& info) { auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -262,16 +262,16 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local obj) { } if (Nan::Has(obj, Nan::New("classes").ToLocalChecked()).FromJust()) { - auto classes = Nan::Get(obj, Nan::New("classes").ToLocalChecked()).ToLocalChecked()->ToObject().As(); + auto classes = Nan::To(Nan::Get(obj, Nan::New("classes").ToLocalChecked()).ToLocalChecked()).ToLocalChecked().As(); const int length = classes->Length(); options.classes.reserve(length); for (int i = 0; i < length; i++) { - options.classes.push_back(std::string { *Nan::Utf8String(Nan::Get(classes, i).ToLocalChecked()->ToString()) }); + options.classes.push_back(std::string { *Nan::Utf8String(Nan::To(Nan::Get(classes, i).ToLocalChecked()).ToLocalChecked()) }); } } if (Nan::Has(obj, Nan::New("debug").ToLocalChecked()).FromJust()) { - auto debug = Nan::Get(obj, Nan::New("debug").ToLocalChecked()).ToLocalChecked()->ToObject().As(); + auto debug = Nan::To(Nan::Get(obj, Nan::New("debug").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); if (Nan::Has(debug, Nan::New("tileBorders").ToLocalChecked()).FromJust()) { if (Nan::Get(debug, Nan::New("tileBorders").ToLocalChecked()).ToLocalChecked()->BooleanValue()) { options.debugOptions = options.debugOptions | mbgl::MapDebugOptions::TileBorders; @@ -318,7 +318,7 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local obj) { * @returns {undefined} calls callback * @throws {Error} if stylesheet is not loaded or if map is already rendering */ -NAN_METHOD(NodeMap::Render) { +void NodeMap::Render(const Nan::FunctionCallbackInfo& info) { auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -338,7 +338,7 @@ NAN_METHOD(NodeMap::Render) { return Nan::ThrowError("Map is currently rendering an image"); } - auto options = ParseOptions(info[0]->ToObject()); + auto options = ParseOptions(Nan::To(info[0]).ToLocalChecked()); assert(!nodeMap->callback); assert(!nodeMap->image.data); @@ -448,7 +448,7 @@ void NodeMap::renderFinished() { * @name release * @returns {undefined} */ -NAN_METHOD(NodeMap::Release) { +void NodeMap::Release(const Nan::FunctionCallbackInfo& info) { auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -471,7 +471,7 @@ void NodeMap::release() { map.reset(); } -NAN_METHOD(NodeMap::AddClass) { +void NodeMap::AddClass(const Nan::FunctionCallbackInfo& info) { auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -488,7 +488,7 @@ NAN_METHOD(NodeMap::AddClass) { info.GetReturnValue().SetUndefined(); } -NAN_METHOD(NodeMap::AddSource) { +void NodeMap::AddSource(const Nan::FunctionCallbackInfo& info) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -512,7 +512,7 @@ NAN_METHOD(NodeMap::AddSource) { nodeMap->map->addSource(std::move(*source)); } -NAN_METHOD(NodeMap::AddLayer) { +void NodeMap::AddLayer(const Nan::FunctionCallbackInfo& info) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -532,7 +532,7 @@ NAN_METHOD(NodeMap::AddLayer) { nodeMap->map->addLayer(std::move(*layer)); } -NAN_METHOD(NodeMap::RemoveLayer) { +void NodeMap::RemoveLayer(const Nan::FunctionCallbackInfo& info) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -550,7 +550,7 @@ NAN_METHOD(NodeMap::RemoveLayer) { nodeMap->map->removeLayer(*Nan::Utf8String(info[0])); } -NAN_METHOD(NodeMap::SetLayoutProperty) { +void NodeMap::SetLayoutProperty(const Nan::FunctionCallbackInfo& info) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -583,7 +583,7 @@ NAN_METHOD(NodeMap::SetLayoutProperty) { info.GetReturnValue().SetUndefined(); } -NAN_METHOD(NodeMap::SetPaintProperty) { +void NodeMap::SetPaintProperty(const Nan::FunctionCallbackInfo& info) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -621,7 +621,7 @@ NAN_METHOD(NodeMap::SetPaintProperty) { info.GetReturnValue().SetUndefined(); } -NAN_METHOD(NodeMap::SetFilter) { +void NodeMap::SetFilter(const Nan::FunctionCallbackInfo& info) { using namespace mbgl::style; using namespace mbgl::style::conversion; @@ -676,7 +676,7 @@ NAN_METHOD(NodeMap::SetFilter) { Nan::ThrowTypeError("layer doesn't support filters"); } -NAN_METHOD(NodeMap::DumpDebugLogs) { +void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo& info) { auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -684,7 +684,7 @@ NAN_METHOD(NodeMap::DumpDebugLogs) { info.GetReturnValue().SetUndefined(); } -NAN_METHOD(NodeMap::QueryRenderedFeatures) { +void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo& info) { auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -732,9 +732,6 @@ NAN_METHOD(NodeMap::QueryRenderedFeatures) { } } -//////////////////////////////////////////////////////////////////////////////////////////////// -// Instance - NodeMap::NodeMap(v8::Local options) : view(sharedDisplay(), [&] { Nan::HandleScope scope; @@ -756,22 +753,23 @@ NodeMap::~NodeMap() { if (map) release(); } -std::unique_ptr NodeMap::request(const mbgl::Resource& resource, Callback callback_) { - Nan::HandleScope handleScope; +std::unique_ptr NodeMap::request(const mbgl::Resource& resource, mbgl::FileSource::Callback callback_) { + Nan::HandleScope scope; - // Enter a new v8::Context to avoid leaking v8::FunctionTemplate - // from Nan::New - v8::Local context = v8::Context::New(v8::Isolate::GetCurrent()); - v8::Context::Scope scope(context); + v8::Local argv[] = { + Nan::New(this), + Nan::New(&callback_) + }; - auto requestHandle = NodeRequest::Create(resource, callback_)->ToObject(); - auto request = Nan::ObjectWrap::Unwrap(requestHandle); - auto callbackHandle = Nan::New(NodeRequest::Respond, requestHandle); + auto instance = Nan::New(NodeRequest::constructor)->NewInstance(2, argv); - v8::Local argv[] = { requestHandle, callbackHandle }; - Nan::MakeCallback(handle()->GetInternalField(1)->ToObject(), "request", 2, argv); + Nan::Set(instance, Nan::New("url").ToLocalChecked(), Nan::New(resource.url).ToLocalChecked()); + Nan::Set(instance, Nan::New("kind").ToLocalChecked(), Nan::New(resource.kind)); + + auto request = Nan::ObjectWrap::Unwrap(instance); + request->Execute(); return std::make_unique(request); } -} // namespace node_mbgl +} diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp index 5090b0aed..3673b5f2b 100644 --- a/platform/node/src/node_map.hpp +++ b/platform/node/src/node_map.hpp @@ -18,22 +18,27 @@ public: struct RenderOptions; class RenderWorker; + NodeMap(v8::Local); + ~NodeMap(); + + static Nan::Persistent constructor; + static NAN_MODULE_INIT(Init); - static NAN_METHOD(New); - static NAN_METHOD(Load); - static NAN_METHOD(Loaded); - static NAN_METHOD(Render); - static NAN_METHOD(Release); - static NAN_METHOD(AddClass); - static NAN_METHOD(AddSource); - static NAN_METHOD(AddLayer); - static NAN_METHOD(RemoveLayer); - static NAN_METHOD(SetLayoutProperty); - static NAN_METHOD(SetPaintProperty); - static NAN_METHOD(SetFilter); - static NAN_METHOD(DumpDebugLogs); - static NAN_METHOD(QueryRenderedFeatures); + static void New(const Nan::FunctionCallbackInfo&); + static void Load(const Nan::FunctionCallbackInfo&); + static void Loaded(const Nan::FunctionCallbackInfo&); + static void Render(const Nan::FunctionCallbackInfo&); + static void Release(const Nan::FunctionCallbackInfo&); + static void AddClass(const Nan::FunctionCallbackInfo&); + static void AddSource(const Nan::FunctionCallbackInfo&); + static void AddLayer(const Nan::FunctionCallbackInfo&); + static void RemoveLayer(const Nan::FunctionCallbackInfo&); + static void SetLayoutProperty(const Nan::FunctionCallbackInfo&); + static void SetPaintProperty(const Nan::FunctionCallbackInfo&); + static void SetFilter(const Nan::FunctionCallbackInfo&); + static void DumpDebugLogs(const Nan::FunctionCallbackInfo&); + static void QueryRenderedFeatures(const Nan::FunctionCallbackInfo&); void startRender(RenderOptions options); void renderFinished(); @@ -41,12 +46,8 @@ public: void release(); static RenderOptions ParseOptions(v8::Local); - static Nan::Persistent constructor; - NodeMap(v8::Local); - ~NodeMap(); - - std::unique_ptr request(const mbgl::Resource&, Callback); + std::unique_ptr request(const mbgl::Resource&, mbgl::FileSource::Callback); mbgl::HeadlessView view; std::unique_ptr map; diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp index 26c49918b..7c5a95955 100644 --- a/platform/node/src/node_mapbox_gl_native.cpp +++ b/platform/node/src/node_mapbox_gl_native.cpp @@ -61,10 +61,14 @@ void RegisterModule(v8::Local target, v8::Local module) Nan::New("require").ToLocalChecked()).ToLocalChecked().As(); v8::Local eventsString = Nan::New("events").ToLocalChecked(); - v8::Local events = Nan::Call(require, module, 1, &eventsString).ToLocalChecked()->ToObject(); + v8::Local events = Nan::To(Nan::Call(require, module, 1, &eventsString).ToLocalChecked()).ToLocalChecked(); - v8::Local EventEmitter = Nan::Get(events, - Nan::New("EventEmitter").ToLocalChecked()).ToLocalChecked()->ToObject(); + v8::Local EventEmitter = Nan::To( + Nan::Get( + events, + Nan::New("EventEmitter").ToLocalChecked() + ).ToLocalChecked() + ).ToLocalChecked(); Nan::SetPrototype(target, Nan::Get(EventEmitter, Nan::New("prototype").ToLocalChecked()).ToLocalChecked()); diff --git a/platform/node/src/node_request.cpp b/platform/node/src/node_request.cpp index fa560ed4e..56015726c 100644 --- a/platform/node/src/node_request.cpp +++ b/platform/node/src/node_request.cpp @@ -1,14 +1,28 @@ #include "node_request.hpp" +#include "node_map.hpp" #include #include #include -#include namespace node_mbgl { -//////////////////////////////////////////////////////////////////////////////////////////////// -// Static Node Methods +NodeRequest::NodeRequest( + NodeMap* target_, + mbgl::FileSource::Callback callback_) + : AsyncWorker(nullptr), + target(target_), + callback(callback_) { +} + +NodeRequest::~NodeRequest() { + // When this object gets garbage collected, make sure that the + // AsyncRequest can no longer attempt to remove the callback function + // this object was holding (it can't be fired anymore). + if (asyncRequest) { + asyncRequest->request = nullptr; + } +} Nan::Persistent NodeRequest::constructor; @@ -19,73 +33,50 @@ NAN_MODULE_INIT(NodeRequest::Init) { tpl->SetClassName(Nan::New("Request").ToLocalChecked()); constructor.Reset(tpl->GetFunction()); + + // TODO: Remove this from the public JavaScript API Nan::Set(target, Nan::New("Request").ToLocalChecked(), tpl->GetFunction()); } -NAN_METHOD(NodeRequest::New) { - auto req = new NodeRequest(*reinterpret_cast(info[0].As()->Value())); - req->Wrap(info.This()); +void NodeRequest::New(const Nan::FunctionCallbackInfo& info) { + auto target = reinterpret_cast(info[0].As()->Value()); + auto callback = reinterpret_cast(info[1].As()->Value()); + + auto request = new NodeRequest(target, *callback); + + request->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } -v8::Handle NodeRequest::Create(const mbgl::Resource& resource, mbgl::FileSource::Callback callback) { - Nan::EscapableHandleScope scope; - - v8::Local argv[] = { - Nan::New(const_cast(&callback)) - }; - auto instance = Nan::New(constructor)->NewInstance(1, argv); - - Nan::Set(instance, Nan::New("url").ToLocalChecked(), Nan::New(resource.url).ToLocalChecked()); - Nan::Set(instance, Nan::New("kind").ToLocalChecked(), Nan::New(int(resource.kind))); - - return scope.Escape(instance); -} - -NAN_METHOD(NodeRequest::Respond) { - using Error = mbgl::Response::Error; - +void NodeRequest::HandleCallback(const Nan::FunctionCallbackInfo& info) { // Move out of the object so callback() can only be fired once. auto request = Nan::ObjectWrap::Unwrap(info.Data().As()); auto callback = std::move(request->callback); if (!callback) { - info.GetReturnValue().SetUndefined(); - return; + return info.GetReturnValue().SetUndefined(); } mbgl::Response response; if (info.Length() < 1) { response.noContent = true; + } else if (info[0]->IsObject()) { + auto err = Nan::To(info[0]).ToLocalChecked(); + auto msg = Nan::New("message").ToLocalChecked(); - } else if (info[0]->BooleanValue()) { - std::unique_ptr message; - - // Store the error string. - if (info[0]->IsObject()) { - auto err = info[0]->ToObject(); - if (Nan::Has(err, Nan::New("message").ToLocalChecked()).FromJust()) { - message = std::make_unique( - Nan::Get(err, Nan::New("message").ToLocalChecked()) - .ToLocalChecked() - ->ToString()); - } + if (Nan::Has(err, msg).FromJust()) { + request->SetErrorMessage(*Nan::Utf8String( + Nan::Get(err, msg).ToLocalChecked())); } - - if (!message) { - message = std::make_unique(info[0]->ToString()); - } - response.error = std::make_unique( - Error::Reason::Other, std::string{ **message, size_t(message->length()) }); - + } else if (info[0]->IsString()) { + request->SetErrorMessage(*Nan::Utf8String(info[0])); } else if (info.Length() < 2 || !info[1]->IsObject()) { return Nan::ThrowTypeError("Second argument must be a response object"); - } else { - auto res = info[1]->ToObject(); + auto res = Nan::To(info[1]).ToLocalChecked(); if (Nan::Has(res, Nan::New("modified").ToLocalChecked()).FromJust()) { - const double modified = Nan::Get(res, Nan::New("modified").ToLocalChecked()).ToLocalChecked()->ToNumber()->Value(); + const double modified = Nan::To(Nan::Get(res, Nan::New("modified").ToLocalChecked()).ToLocalChecked()).FromJust(); if (!std::isnan(modified)) { response.modified = mbgl::Timestamp{ mbgl::Seconds( static_cast(modified / 1000)) }; @@ -93,7 +84,7 @@ NAN_METHOD(NodeRequest::Respond) { } if (Nan::Has(res, Nan::New("expires").ToLocalChecked()).FromJust()) { - const double expires = Nan::Get(res, Nan::New("expires").ToLocalChecked()).ToLocalChecked()->ToNumber()->Value(); + const double expires = Nan::To(Nan::Get(res, Nan::New("expires").ToLocalChecked()).ToLocalChecked()).FromJust(); if (!std::isnan(expires)) { response.expires = mbgl::Timestamp{ mbgl::Seconds( static_cast(expires / 1000)) }; @@ -101,19 +92,16 @@ NAN_METHOD(NodeRequest::Respond) { } if (Nan::Has(res, Nan::New("etag").ToLocalChecked()).FromJust()) { - auto etagHandle = Nan::Get(res, Nan::New("etag").ToLocalChecked()).ToLocalChecked(); - if (etagHandle->BooleanValue()) { - const Nan::Utf8String etag { etagHandle->ToString() }; - response.etag = std::string { *etag, size_t(etag.length()) }; - } + const Nan::Utf8String etag(Nan::Get(res, Nan::New("etag").ToLocalChecked()).ToLocalChecked()); + response.etag = std::string { *etag, size_t(etag.length()) }; } if (Nan::Has(res, Nan::New("data").ToLocalChecked()).FromJust()) { - auto dataHandle = Nan::Get(res, Nan::New("data").ToLocalChecked()).ToLocalChecked(); - if (node::Buffer::HasInstance(dataHandle)) { + auto data = Nan::Get(res, Nan::New("data").ToLocalChecked()).ToLocalChecked(); + if (node::Buffer::HasInstance(data)) { response.data = std::make_shared( - node::Buffer::Data(dataHandle), - node::Buffer::Length(dataHandle) + node::Buffer::Data(data), + node::Buffer::Length(data) ); } else { return Nan::ThrowTypeError("Response data must be a Buffer"); @@ -121,40 +109,44 @@ NAN_METHOD(NodeRequest::Respond) { } } + if (request->ErrorMessage()) { + response.error = std::make_unique( + mbgl::Response::Error::Reason::Other, + request->ErrorMessage() + ); + } + // Send the response object to the NodeFileSource object callback(response); info.GetReturnValue().SetUndefined(); } -//////////////////////////////////////////////////////////////////////////////////////////////// -// Instance +void NodeRequest::Execute() { + // Enter a new v8::Context to avoid leaking v8::FunctionTemplate + // from Nan::New + v8::Local context = v8::Context::New(v8::Isolate::GetCurrent()); + v8::Context::Scope scope(context); + + v8::Local argv[] = { handle(), Nan::New(NodeRequest::HandleCallback, handle()) }; + + Nan::MakeCallback(Nan::To(target->handle()->GetInternalField(1)).ToLocalChecked(), "request", 2, argv); +} NodeRequest::NodeAsyncRequest::NodeAsyncRequest(NodeRequest* request_) : request(request_) { assert(request); - // Make sure the JS object has a pointer to this so that it can remove its pointer in the - // destructor + + // Make sure the JS object has a pointer to this so that it can remove + // its pointer in the destructor request->asyncRequest = this; } NodeRequest::NodeAsyncRequest::~NodeAsyncRequest() { if (request) { - // Remove the callback function because the AsyncRequest was canceled and we are no longer - // interested in the result. + // Remove the callback function because the AsyncRequest was + // canceled and we are no longer interested in the result. request->callback = {}; request->asyncRequest = nullptr; } } -NodeRequest::NodeRequest(mbgl::FileSource::Callback callback_) - : callback(callback_) { } - -NodeRequest::~NodeRequest() { - // When this object gets garbage collected, make sure that the AsyncRequest can no longer - // attempt to remove the callback function this object was holding (it can't be fired anymore). - if (asyncRequest) { - asyncRequest->request = nullptr; - } -} - -} // namespace node_mbgl diff --git a/platform/node/src/node_request.hpp b/platform/node/src/node_request.hpp index 2d307a3f1..f7fce9172 100644 --- a/platform/node/src/node_request.hpp +++ b/platform/node/src/node_request.hpp @@ -11,29 +11,31 @@ namespace node_mbgl { -class NodeFileSource; -class NodeRequest; +class NodeMap; -class NodeRequest : public Nan::ObjectWrap { +class NodeRequest : public Nan::ObjectWrap, + public Nan::AsyncWorker { public: - static NAN_MODULE_INIT(Init); - - static NAN_METHOD(New); - static NAN_METHOD(Respond); - - static v8::Handle Create(const mbgl::Resource&, mbgl::FileSource::Callback); - static Nan::Persistent constructor; - - NodeRequest(mbgl::FileSource::Callback); - ~NodeRequest(); - struct NodeAsyncRequest : public mbgl::AsyncRequest { NodeAsyncRequest(NodeRequest*); ~NodeAsyncRequest() override; NodeRequest* request; }; + NodeRequest(NodeMap*, mbgl::FileSource::Callback); + ~NodeRequest(); + + static Nan::Persistent constructor; + + static NAN_MODULE_INIT(Init); + + static void New(const Nan::FunctionCallbackInfo&); + static void HandleCallback(const Nan::FunctionCallbackInfo&); + + void Execute(); + private: + NodeMap* target; mbgl::FileSource::Callback callback; NodeAsyncRequest* asyncRequest = nullptr; };