diff options
author | Mike Morris <mikemorris@users.noreply.github.com> | 2016-07-12 18:37:28 -0400 |
---|---|---|
committer | Mike Morris <mikemorris@users.noreply.github.com> | 2016-07-14 13:47:02 -0400 |
commit | 7df0e459b6da75f6ebddedb003f391df7c1959c9 (patch) | |
tree | 9c2cee179effa8d31abf58a338129854509c29d2 /platform | |
parent | 480be63396abe016ce8f1c8c5acd8621412a0fa3 (diff) | |
download | qtlocation-mapboxgl-7df0e459b6da75f6ebddedb003f391df7c1959c9.tar.gz |
[node] NodeRequest inherits from Nan::AsyncWorker
drop NodeRequest::Create, move MakeCallback to NodeRequest::Execute
rework Respond -> HandleCallback
modern NAN style updates
Diffstat (limited to 'platform')
-rw-r--r-- | platform/node/src/node_conversion.hpp | 8 | ||||
-rw-r--r-- | platform/node/src/node_log.cpp | 2 | ||||
-rw-r--r-- | platform/node/src/node_map.cpp | 78 | ||||
-rw-r--r-- | platform/node/src/node_map.hpp | 39 | ||||
-rw-r--r-- | platform/node/src/node_mapbox_gl_native.cpp | 12 | ||||
-rw-r--r-- | platform/node/src/node_request.cpp | 140 | ||||
-rw-r--r-- | 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 2418a7a6e4..4be1670ea0 100644 --- a/platform/node/src/node_conversion.hpp +++ b/platform/node/src/node_conversion.hpp @@ -41,10 +41,10 @@ inline bool isObject(v8::Local<v8::Value> value) { inline optional<v8::Local<v8::Value>> objectMember(v8::Local<v8::Value> value, const char * name) { Nan::EscapableHandleScope scope; - if (!Nan::Has(value->ToObject(), Nan::New(name).ToLocalChecked()).FromJust()) { + if (!Nan::Has(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) { return {}; } - Nan::MaybeLocal<v8::Value> result = Nan::Get(value->ToObject(), Nan::New(name).ToLocalChecked()); + Nan::MaybeLocal<v8::Value> result = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()); if (result.IsEmpty()) { return {}; } @@ -54,10 +54,10 @@ inline optional<v8::Local<v8::Value>> objectMember(v8::Local<v8::Value> value, c template <class Fn> optional<Error> eachMember(v8::Local<v8::Value> value, Fn&& fn) { Nan::HandleScope scope; - v8::Local<v8::Array> names = value->ToObject()->GetOwnPropertyNames(); + v8::Local<v8::Array> names = Nan::GetOwnPropertyNames(Nan::To<v8::Object>(value).ToLocalChecked()).ToLocalChecked(); for (uint32_t i = 0; i < names->Length(); ++i) { v8::Local<v8::Value> k = Nan::Get(names, i).ToLocalChecked(); - v8::Local<v8::Value> v = Nan::Get(value->ToObject(), k).ToLocalChecked(); + v8::Local<v8::Value> v = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), k).ToLocalChecked(); optional<Error> 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 21eaa55bca..9872376904 100644 --- a/platform/node/src/node_log.cpp +++ b/platform/node/src/node_log.cpp @@ -42,7 +42,7 @@ NodeLogObserver::NodeLogObserver(v8::Local<v8::Object> target) v8::Local<v8::Value> argv[] = { Nan::New("message").ToLocalChecked(), msg }; auto handle = Nan::New<v8::Object>(module); - auto emit = Nan::Get(handle, Nan::New("emit").ToLocalChecked()).ToLocalChecked()->ToObject(); + auto emit = Nan::To<v8::Object>(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 00a3041f26..e89089ecbb 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<v8::Function> NodeMap::constructor; static std::shared_ptr<mbgl::HeadlessDisplay> 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<v8::Value>& 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<v8::Object>(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<v8::Value> styleHandle) { Nan::HandleScope scope; - v8::Local<v8::Object> JSON = Nan::Get( - Nan::GetCurrentContext()->Global(), - Nan::New("JSON").ToLocalChecked()).ToLocalChecked()->ToObject(); + v8::Local<v8::Object> JSON = Nan::To<v8::Object>( + 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<v8::Value> styleHandle) { * // providing a string * map.load(fs.readFileSync('./test/fixtures/style.json', 'utf8')); */ -NAN_METHOD(NodeMap::Load) { +void NodeMap::Load(const Nan::FunctionCallbackInfo<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(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<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -262,16 +262,16 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local<v8::Object> obj) { } if (Nan::Has(obj, Nan::New("classes").ToLocalChecked()).FromJust()) { - auto classes = Nan::Get(obj, Nan::New("classes").ToLocalChecked()).ToLocalChecked()->ToObject().As<v8::Array>(); + auto classes = Nan::To<v8::Object>(Nan::Get(obj, Nan::New("classes").ToLocalChecked()).ToLocalChecked()).ToLocalChecked().As<v8::Array>(); 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<v8::String>(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<v8::Object>(); + auto debug = Nan::To<v8::Object>(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<v8::Object> 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<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(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<v8::Object>(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<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(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<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(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<v8::Value>& 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(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<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -732,9 +732,6 @@ NAN_METHOD(NodeMap::QueryRenderedFeatures) { } } -//////////////////////////////////////////////////////////////////////////////////////////////// -// Instance - NodeMap::NodeMap(v8::Local<v8::Object> options) : view(sharedDisplay(), [&] { Nan::HandleScope scope; @@ -756,22 +753,23 @@ NodeMap::~NodeMap() { if (map) release(); } -std::unique_ptr<mbgl::AsyncRequest> NodeMap::request(const mbgl::Resource& resource, Callback callback_) { - Nan::HandleScope handleScope; +std::unique_ptr<mbgl::AsyncRequest> 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::Function> - v8::Local<v8::Context> context = v8::Context::New(v8::Isolate::GetCurrent()); - v8::Context::Scope scope(context); + v8::Local<v8::Value> argv[] = { + Nan::New<v8::External>(this), + Nan::New<v8::External>(&callback_) + }; - auto requestHandle = NodeRequest::Create(resource, callback_)->ToObject(); - auto request = Nan::ObjectWrap::Unwrap<NodeRequest>(requestHandle); - auto callbackHandle = Nan::New<v8::Function>(NodeRequest::Respond, requestHandle); + auto instance = Nan::New(NodeRequest::constructor)->NewInstance(2, argv); - v8::Local<v8::Value> 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<v8::Integer>(resource.kind)); + + auto request = Nan::ObjectWrap::Unwrap<NodeRequest>(instance); + request->Execute(); return std::make_unique<NodeRequest::NodeAsyncRequest>(request); } -} // namespace node_mbgl +} diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp index 5090b0aedc..3673b5f2ba 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<v8::Object>); + ~NodeMap(); + + static Nan::Persistent<v8::Function> 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<v8::Value>&); + static void Load(const Nan::FunctionCallbackInfo<v8::Value>&); + static void Loaded(const Nan::FunctionCallbackInfo<v8::Value>&); + static void Render(const Nan::FunctionCallbackInfo<v8::Value>&); + static void Release(const Nan::FunctionCallbackInfo<v8::Value>&); + static void AddClass(const Nan::FunctionCallbackInfo<v8::Value>&); + static void AddSource(const Nan::FunctionCallbackInfo<v8::Value>&); + static void AddLayer(const Nan::FunctionCallbackInfo<v8::Value>&); + static void RemoveLayer(const Nan::FunctionCallbackInfo<v8::Value>&); + static void SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>&); + static void SetPaintProperty(const Nan::FunctionCallbackInfo<v8::Value>&); + static void SetFilter(const Nan::FunctionCallbackInfo<v8::Value>&); + static void DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>&); + static void QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&); void startRender(RenderOptions options); void renderFinished(); @@ -41,12 +46,8 @@ public: void release(); static RenderOptions ParseOptions(v8::Local<v8::Object>); - static Nan::Persistent<v8::Function> constructor; - - NodeMap(v8::Local<v8::Object>); - ~NodeMap(); - std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, Callback); + std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback); mbgl::HeadlessView view; std::unique_ptr<mbgl::Map> map; diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp index 26c49918be..7c5a959553 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<v8::Object> target, v8::Local<v8::Object> module) Nan::New("require").ToLocalChecked()).ToLocalChecked().As<v8::Function>(); v8::Local<v8::Value> eventsString = Nan::New("events").ToLocalChecked(); - v8::Local<v8::Object> events = Nan::Call(require, module, 1, &eventsString).ToLocalChecked()->ToObject(); - - v8::Local<v8::Object> EventEmitter = Nan::Get(events, - Nan::New("EventEmitter").ToLocalChecked()).ToLocalChecked()->ToObject(); + v8::Local<v8::Object> events = Nan::To<v8::Object>(Nan::Call(require, module, 1, &eventsString).ToLocalChecked()).ToLocalChecked(); + + v8::Local<v8::Object> EventEmitter = Nan::To<v8::Object>( + 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 fa560ed4e7..56015726cb 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 <mbgl/storage/response.hpp> #include <mbgl/util/chrono.hpp> #include <cmath> -#include <iostream> 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<v8::Function> NodeRequest::constructor; @@ -19,73 +33,50 @@ NAN_MODULE_INIT(NodeRequest::Init) { tpl->SetClassName(Nan::New("Request").ToLocalChecked()); constructor.Reset(tpl->GetFunction()); - Nan::Set(target, Nan::New("Request").ToLocalChecked(), tpl->GetFunction()); -} -NAN_METHOD(NodeRequest::New) { - auto req = new NodeRequest(*reinterpret_cast<mbgl::FileSource::Callback*>(info[0].As<v8::External>()->Value())); - req->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); + // TODO: Remove this from the public JavaScript API + Nan::Set(target, Nan::New("Request").ToLocalChecked(), tpl->GetFunction()); } -v8::Handle<v8::Object> NodeRequest::Create(const mbgl::Resource& resource, mbgl::FileSource::Callback callback) { - Nan::EscapableHandleScope scope; +void NodeRequest::New(const Nan::FunctionCallbackInfo<v8::Value>& info) { + auto target = reinterpret_cast<NodeMap*>(info[0].As<v8::External>()->Value()); + auto callback = reinterpret_cast<mbgl::FileSource::Callback*>(info[1].As<v8::External>()->Value()); - v8::Local<v8::Value> argv[] = { - Nan::New<v8::External>(const_cast<mbgl::FileSource::Callback*>(&callback)) - }; - auto instance = Nan::New(constructor)->NewInstance(1, argv); + auto request = new NodeRequest(target, *callback); - Nan::Set(instance, Nan::New("url").ToLocalChecked(), Nan::New(resource.url).ToLocalChecked()); - Nan::Set(instance, Nan::New("kind").ToLocalChecked(), Nan::New<v8::Integer>(int(resource.kind))); - - return scope.Escape(instance); + request->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); } -NAN_METHOD(NodeRequest::Respond) { - using Error = mbgl::Response::Error; - +void NodeRequest::HandleCallback(const Nan::FunctionCallbackInfo<v8::Value>& info) { // Move out of the object so callback() can only be fired once. auto request = Nan::ObjectWrap::Unwrap<NodeRequest>(info.Data().As<v8::Object>()); 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<v8::Object>(info[0]).ToLocalChecked(); + auto msg = Nan::New("message").ToLocalChecked(); - } else if (info[0]->BooleanValue()) { - std::unique_ptr<Nan::Utf8String> 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::Utf8String>( - Nan::Get(err, Nan::New("message").ToLocalChecked()) - .ToLocalChecked() - ->ToString()); - } - } - - if (!message) { - message = std::make_unique<Nan::Utf8String>(info[0]->ToString()); + if (Nan::Has(err, msg).FromJust()) { + request->SetErrorMessage(*Nan::Utf8String( + Nan::Get(err, msg).ToLocalChecked())); } - response.error = std::make_unique<Error>( - 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<v8::Object>(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<double>(Nan::Get(res, Nan::New("modified").ToLocalChecked()).ToLocalChecked()).FromJust(); if (!std::isnan(modified)) { response.modified = mbgl::Timestamp{ mbgl::Seconds( static_cast<mbgl::Seconds::rep>(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<double>(Nan::Get(res, Nan::New("expires").ToLocalChecked()).ToLocalChecked()).FromJust(); if (!std::isnan(expires)) { response.expires = mbgl::Timestamp{ mbgl::Seconds( static_cast<mbgl::Seconds::rep>(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<std::string>( - 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>( + 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::Function> + v8::Local<v8::Context> context = v8::Context::New(v8::Isolate::GetCurrent()); + v8::Context::Scope scope(context); + + v8::Local<v8::Value> argv[] = { handle(), Nan::New<v8::Function>(NodeRequest::HandleCallback, handle()) }; + + Nan::MakeCallback(Nan::To<v8::Object>(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 2d307a3f19..f7fce91726 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<v8::Object> Create(const mbgl::Resource&, mbgl::FileSource::Callback); - static Nan::Persistent<v8::Function> 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<v8::Function> constructor; + + static NAN_MODULE_INIT(Init); + + static void New(const Nan::FunctionCallbackInfo<v8::Value>&); + static void HandleCallback(const Nan::FunctionCallbackInfo<v8::Value>&); + + void Execute(); + private: + NodeMap* target; mbgl::FileSource::Callback callback; NodeAsyncRequest* asyncRequest = nullptr; }; |