From 0531b38367eb23b787276b9b6ef1f6992b4b3bc2 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 3 Sep 2015 15:54:18 -0700 Subject: [PATCH 1/4] Nan 2.0 --- package.json | 2 +- platform/node/src/node_file_source.cpp | 49 ++---- platform/node/src/node_file_source.hpp | 12 +- platform/node/src/node_log.cpp | 35 ++-- platform/node/src/node_log.hpp | 5 +- platform/node/src/node_map.cpp | 178 ++++++++++---------- platform/node/src/node_map.hpp | 22 +-- platform/node/src/node_mapbox_gl_native.cpp | 71 +++++--- platform/node/src/node_request.cpp | 91 +++++----- platform/node/src/node_request.hpp | 14 +- 10 files changed, 238 insertions(+), 241 deletions(-) diff --git a/package.json b/package.json index 0fd6887ba0a..b8305af3ed0 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ } ], "dependencies": { - "nan": "^1.9.0", + "nan": "^2.0.8", "node-pre-gyp": "^0.6.9" }, "bundledDependencies": [ diff --git a/platform/node/src/node_file_source.cpp b/platform/node/src/node_file_source.cpp index 204e85a1262..29a4748c532 100644 --- a/platform/node/src/node_file_source.cpp +++ b/platform/node/src/node_file_source.cpp @@ -11,7 +11,7 @@ struct NodeFileSource::Action { mbgl::Resource const resource; }; -NodeFileSource::NodeFileSource(v8::Handle options_) : +NodeFileSource::NodeFileSource(v8::Local options_) : queue(new Queue(uv_default_loop(), [this](Action &action) { if (action.type == Action::Add) { processAdd(action.resource); @@ -20,7 +20,7 @@ NodeFileSource::NodeFileSource(v8::Handle options_) : } })) { - NanAssignPersistent(options, options_->ToObject()); + options.Reset(options_); // Make sure that the queue doesn't block the loop from exiting. queue->unref(); @@ -30,7 +30,7 @@ NodeFileSource::~NodeFileSource() { queue->stop(); queue = nullptr; - NanDisposePersistent(options); + options.Reset(); } mbgl::Request* NodeFileSource::request(const mbgl::Resource& resource, uv_loop_t* loop, Callback callback) { @@ -68,44 +68,30 @@ void NodeFileSource::cancel(mbgl::Request* req) { } void NodeFileSource::processAdd(const mbgl::Resource& resource) { - NanScope(); + Nan::HandleScope scope; // Make sure the loop stays alive as long as request is pending. if (pending.empty()) { queue->ref(); } - auto requestHandle = NanNew(NodeRequest::Create(this, resource)); - - v8::Persistent requestPersistent; - NanAssignPersistent(requestPersistent, requestHandle); - pending.emplace(resource, std::move(requestPersistent)); - -#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) - auto requestFunction = v8::Local::New(v8::Isolate::GetCurrent(), options)->Get(NanNew("request")).As(); -#else - auto requestFunction = options->Get(NanNew("request")).As(); -#endif + auto requestHandle = Nan::New(NodeRequest::Create(this, resource)); + pending.emplace(resource, requestHandle); v8::Local argv[] = { requestHandle }; - NanMakeCallback(NanGetCurrentContext()->Global(), requestFunction, 1, argv); + Nan::MakeCallback(Nan::New(options), "request", 1, argv); } void NodeFileSource::processCancel(const mbgl::Resource& resource) { - NanScope(); + Nan::HandleScope scope; auto it = pending.find(resource); if (it == pending.end()) { // The response callback was already fired. There is no point in calling the cancelation // callback because the request is already completed. } else { -#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) - auto requestHandle = v8::Local::New(v8::Isolate::GetCurrent(), it->second); + v8::Local requestHandle = Nan::New(it->second); it->second.Reset(); -#else - auto requestHandle = NanNew(it->second); - NanDisposePersistent(it->second); -#endif pending.erase(it); // Make sure the the loop can exit when there are no pending requests. @@ -113,20 +99,13 @@ void NodeFileSource::processCancel(const mbgl::Resource& resource) { queue->unref(); } -#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) - auto optionsObject = v8::Local::New(v8::Isolate::GetCurrent(), options); - if (optionsObject->Has(NanNew("cancel"))) { - auto cancelFunction = optionsObject->Get(NanNew("cancel")).As(); -#else - if (options->Has(NanNew("cancel"))) { - auto cancelFunction = options->Get(NanNew("cancel")).As(); -#endif + if (Nan::Has(Nan::New(options), Nan::New("cancel").ToLocalChecked()).FromJust()) { v8::Local argv[] = { requestHandle }; - NanMakeCallback(NanGetCurrentContext()->Global(), cancelFunction, 1, argv); + Nan::MakeCallback(Nan::New(options), "cancel", 1, argv); } // Set the request handle in the request wrapper handle to null - node::ObjectWrap::Unwrap(requestHandle)->cancel(); + Nan::ObjectWrap::Unwrap(requestHandle)->cancel(); } } @@ -134,11 +113,7 @@ void NodeFileSource::notify(const mbgl::Resource& resource, const std::shared_pt // First, remove the request, since it might be destructed at any point now. auto it = pending.find(resource); if (it != pending.end()) { -#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) it->second.Reset(); -#else - NanDisposePersistent(it->second); -#endif pending.erase(it); // Make sure the the loop can exit when there are no pending requests. diff --git a/platform/node/src/node_file_source.hpp b/platform/node/src/node_file_source.hpp index f412bdee164..038765cb20f 100644 --- a/platform/node/src/node_file_source.hpp +++ b/platform/node/src/node_file_source.hpp @@ -5,8 +5,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wshadow" -#include -#include #include #pragma GCC diagnostic pop @@ -20,7 +18,7 @@ namespace util { template class AsyncQueue; } class NodeFileSource : public mbgl::FileSource { public: - NodeFileSource(v8::Handle); + NodeFileSource(v8::Local); ~NodeFileSource(); mbgl::Request* request(const mbgl::Resource&, uv_loop_t*, Callback); @@ -36,14 +34,10 @@ class NodeFileSource : public mbgl::FileSource { void processAdd(const mbgl::Resource&); void processCancel(const mbgl::Resource&); - v8::Persistent options; + Nan::Persistent options; private: -#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) - std::unordered_map>, mbgl::Resource::Hash> pending; -#else - std::unordered_map, mbgl::Resource::Hash> pending; -#endif + std::unordered_map, mbgl::Resource::Hash> pending; // The observers list will hold pointers to all the requests waiting // for a particular resource. The access must be guarded by a mutex diff --git a/platform/node/src/node_log.cpp b/platform/node/src/node_log.cpp index 63753480700..8230bb36ce3 100644 --- a/platform/node/src/node_log.cpp +++ b/platform/node/src/node_log.cpp @@ -16,27 +16,35 @@ struct NodeLogObserver::LogMessage { text(text_) {} }; -NodeLogObserver::NodeLogObserver(v8::Handle target) +NodeLogObserver::NodeLogObserver(v8::Local target) : queue(new Queue(uv_default_loop(), [this](LogMessage &message) { - NanScope(); + Nan::HandleScope scope; + + auto msg = Nan::New(); + + Nan::Set(msg, Nan::New("class").ToLocalChecked(), + Nan::New(mbgl::EventClass(message.event).c_str()).ToLocalChecked()); + + Nan::Set(msg, Nan::New("severity").ToLocalChecked(), + Nan::New(mbgl::EventSeverityClass(message.severity).c_str()).ToLocalChecked()); - auto msg = NanNew(); - msg->Set(NanNew("class"), NanNew(mbgl::EventClass(message.event).c_str())); - msg->Set(NanNew("severity"), NanNew(mbgl::EventSeverityClass(message.severity).c_str())); if (message.code != -1) { - msg->Set(NanNew("code"), NanNew(message.code)); + Nan::Set(msg, Nan::New("code").ToLocalChecked(), + Nan::New(message.code)); } + if (!message.text.empty()) { - msg->Set(NanNew("text"), NanNew(message.text)); + Nan::Set(msg, Nan::New("text").ToLocalChecked(), + Nan::New(message.text).ToLocalChecked()); } - v8::Local argv[] = { NanNew("message"), msg }; - auto handle = NanNew(module); - auto emit = handle->Get(NanNew("emit"))->ToObject(); - emit->CallAsFunction(handle, 2, argv); + v8::Local argv[] = { Nan::New("message").ToLocalChecked(), msg }; + auto handle = Nan::New(module); + auto emit = Nan::Get(handle, Nan::New("emit").ToLocalChecked()).ToLocalChecked()->ToObject(); + Nan::CallAsFunction(emit, handle, 2, argv); })) { - NanScope(); - NanAssignPersistent(module, target); + Nan::HandleScope scope; + module.Reset(target); // Don't keep the event loop alive. queue->unref(); @@ -44,6 +52,7 @@ NodeLogObserver::NodeLogObserver(v8::Handle target) NodeLogObserver::~NodeLogObserver() { queue->stop(); + module.Reset(); } bool NodeLogObserver::onRecord(mbgl::EventSeverity severity, mbgl::Event event, int64_t code, const std::string &text) { diff --git a/platform/node/src/node_log.hpp b/platform/node/src/node_log.hpp index 5c0048d2619..d29e4e28e0b 100644 --- a/platform/node/src/node_log.hpp +++ b/platform/node/src/node_log.hpp @@ -5,7 +5,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wshadow" -#include #include #pragma GCC diagnostic pop @@ -15,14 +14,14 @@ namespace util { template class AsyncQueue; } class NodeLogObserver : public mbgl::Log::Observer { public: - NodeLogObserver(v8::Handle target); + NodeLogObserver(v8::Local target); ~NodeLogObserver(); // Log::Observer implementation virtual bool onRecord(mbgl::EventSeverity severity, mbgl::Event event, int64_t code, const std::string &msg) override; private: - v8::Persistent module; + Nan::Persistent module; struct LogMessage; using Queue = util::AsyncQueue; diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index b624e32e664..0133babc048 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -21,7 +21,7 @@ struct NodeMap::RenderOptions { //////////////////////////////////////////////////////////////////////////////////////////////// // Static Node Methods -v8::Persistent NodeMap::constructorTemplate; +Nan::Persistent NodeMap::constructor; static std::shared_ptr sharedDisplay() { static auto display = std::make_shared(); @@ -32,127 +32,137 @@ const static char* releasedMessage() { return "Map resources have already been released"; } -void NodeMap::Init(v8::Handle target) { - NanScope(); +NAN_MODULE_INIT(NodeMap::Init) { + v8::Local tpl = Nan::New(New); - v8::Local t = NanNew(New); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + tpl->SetClassName(Nan::New("Map").ToLocalChecked()); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("Map")); + Nan::SetPrototypeMethod(tpl, "load", Load); + Nan::SetPrototypeMethod(tpl, "render", Render); + Nan::SetPrototypeMethod(tpl, "release", Release); - NODE_SET_PROTOTYPE_METHOD(t, "load", Load); - NODE_SET_PROTOTYPE_METHOD(t, "render", Render); - NODE_SET_PROTOTYPE_METHOD(t, "release", Release); - - NanAssignPersistent(constructorTemplate, t); - - target->Set(NanNew("Map"), t->GetFunction()); + constructor.Reset(tpl->GetFunction()); + Nan::Set(target, Nan::New("Map").ToLocalChecked(), tpl->GetFunction()); // Initialize display connection on module load. sharedDisplay(); } NAN_METHOD(NodeMap::New) { - NanScope(); - - if (!args.IsConstructCall()) { - return NanThrowTypeError("Use the new operator to create new Map objects"); + if (!info.IsConstructCall()) { + return Nan::ThrowTypeError("Use the new operator to create new Map objects"); } - if (args.Length() < 1 || !args[0]->IsObject()) { - return NanThrowTypeError("Requires an options object as first argument"); + if (info.Length() < 1 || !info[0]->IsObject()) { + return Nan::ThrowTypeError("Requires an options object as first argument"); } - auto options = args[0]->ToObject(); + auto options = info[0]->ToObject(); // Check that 'request', 'cancel' and 'ratio' are defined. - if (!options->Has(NanNew("request")) || !options->Get(NanNew("request"))->IsFunction()) { - return NanThrowError("Options object must have a 'request' method"); + if (!Nan::Has(options, Nan::New("request").ToLocalChecked()).FromJust() + || !Nan::Get(options, Nan::New("request").ToLocalChecked()).ToLocalChecked()->IsFunction()) { + return Nan::ThrowError("Options object must have a 'request' method"); } - if (options->Has(NanNew("cancel")) && !options->Get(NanNew("cancel"))->IsFunction()) { - return NanThrowError("Options object 'cancel' property must be a function"); + + if ( Nan::Has(options, Nan::New("cancel").ToLocalChecked()).FromJust() + && !Nan::Get(options, Nan::New("cancel").ToLocalChecked()).ToLocalChecked()->IsFunction()) { + return Nan::ThrowError("Options object 'cancel' property must be a function"); } - if (!options->Has(NanNew("ratio")) || !options->Get(NanNew("ratio"))->IsNumber()) { - return NanThrowError("Options object must have a numerical 'ratio' property"); + if (!Nan::Has(options, Nan::New("ratio").ToLocalChecked()).FromJust() + || !Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->IsNumber()) { + return Nan::ThrowError("Options object must have a numerical 'ratio' property"); } try { auto nodeMap = new NodeMap(options); - nodeMap->Wrap(args.This()); + nodeMap->Wrap(info.This()); } catch(std::exception &ex) { - return NanThrowError(ex.what()); + return Nan::ThrowError(ex.what()); } - NanReturnValue(args.This()); + info.GetReturnValue().Set(info.This()); } -const std::string StringifyStyle(v8::Handle styleHandle) { - NanScope(); +const std::string StringifyStyle(v8::Local styleHandle) { + Nan::HandleScope scope; - auto JSON = NanGetCurrentContext()->Global()->Get(NanNew("JSON"))->ToObject(); - auto stringify = v8::Handle::Cast(JSON->Get(NanNew("stringify"))); + v8::Local JSON = Nan::Get( + Nan::GetCurrentContext()->Global(), + Nan::New("JSON").ToLocalChecked()).ToLocalChecked()->ToObject(); - return *NanUtf8String(stringify->Call(JSON, 1, &styleHandle)); + return *Nan::Utf8String(Nan::MakeCallback(JSON, "stringify", 1, &styleHandle)); } NAN_METHOD(NodeMap::Load) { - NanScope(); + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); - auto nodeMap = node::ObjectWrap::Unwrap(args.Holder()); - - if (!nodeMap->isValid()) return NanThrowError(releasedMessage()); + if (!nodeMap->isValid()) return Nan::ThrowError(releasedMessage()); // Reset the flag as this could be the second time // we are calling this (being the previous successful). nodeMap->loaded = false; - if (args.Length() < 1) { - return NanThrowError("Requires a map style as first argument"); + if (info.Length() < 1) { + return Nan::ThrowError("Requires a map style as first argument"); } std::string style; - if (args[0]->IsObject()) { - style = StringifyStyle(args[0]); - } else if (args[0]->IsString()) { - style = *NanUtf8String(args[0]); + if (info[0]->IsObject()) { + style = StringifyStyle(info[0]); + } else if (info[0]->IsString()) { + style = *Nan::Utf8String(info[0]); } else { - return NanThrowTypeError("First argument must be a string or object"); + return Nan::ThrowTypeError("First argument must be a string or object"); } try { nodeMap->map->setStyleJSON(style, "."); } catch (const std::exception &ex) { - return NanThrowError(ex.what()); + return Nan::ThrowError(ex.what()); } nodeMap->loaded = true; - NanReturnUndefined(); + info.GetReturnValue().SetUndefined(); } std::unique_ptr NodeMap::ParseOptions(v8::Local obj) { - NanScope(); + Nan::HandleScope scope; auto options = std::make_unique(); - if (obj->Has(NanNew("zoom"))) { options->zoom = obj->Get(NanNew("zoom"))->NumberValue(); } - if (obj->Has(NanNew("bearing"))) { options->bearing = obj->Get(NanNew("bearing"))->NumberValue(); } - if (obj->Has(NanNew("center"))) { - auto center = obj->Get(NanNew("center")).As(); - if (center->Length() > 0) { options->latitude = center->Get(0)->NumberValue(); } - if (center->Length() > 1) { options->longitude = center->Get(1)->NumberValue(); } + if (Nan::Has(obj, Nan::New("zoom").ToLocalChecked()).FromJust()) { + options->zoom = Nan::Get(obj, Nan::New("zoom").ToLocalChecked()).ToLocalChecked()->NumberValue(); + } + + if (Nan::Has(obj, Nan::New("bearing").ToLocalChecked()).FromJust()) { + options->bearing = Nan::Get(obj, Nan::New("bearing").ToLocalChecked()).ToLocalChecked()->NumberValue(); } - if (obj->Has(NanNew("width"))) { options->width = obj->Get(NanNew("width"))->IntegerValue(); } - if (obj->Has(NanNew("height"))) { options->height = obj->Get(NanNew("height"))->IntegerValue(); } - if (obj->Has(NanNew("classes"))) { - auto classes = obj->Get(NanNew("classes"))->ToObject().As(); + if (Nan::Has(obj, Nan::New("center").ToLocalChecked()).FromJust()) { + auto center = Nan::Get(obj, Nan::New("center").ToLocalChecked()).ToLocalChecked().As(); + if (center->Length() > 0) { options->latitude = Nan::Get(center, 0).ToLocalChecked()->NumberValue(); } + if (center->Length() > 1) { options->longitude = Nan::Get(center, 1).ToLocalChecked()->NumberValue(); } + } + + if (Nan::Has(obj, Nan::New("width").ToLocalChecked()).FromJust()) { + options->width = Nan::Get(obj, Nan::New("width").ToLocalChecked()).ToLocalChecked()->IntegerValue(); + } + + if (Nan::Has(obj, Nan::New("height").ToLocalChecked()).FromJust()) { + options->height = Nan::Get(obj, Nan::New("height").ToLocalChecked()).ToLocalChecked()->IntegerValue(); + } + + if (Nan::Has(obj, Nan::New("classes").ToLocalChecked()).FromJust()) { + auto classes = Nan::Get(obj, Nan::New("classes").ToLocalChecked()).ToLocalChecked()->ToObject().As(); const int length = classes->Length(); options->classes.reserve(length); for (int i = 0; i < length; i++) { - options->classes.push_back(std::string { *NanUtf8String(classes->Get(i)->ToString()) }); + options->classes.push_back(std::string { *Nan::Utf8String(Nan::Get(classes, i).ToLocalChecked()->ToString()) }); } } @@ -160,37 +170,35 @@ std::unique_ptr NodeMap::ParseOptions(v8::Local(args.Holder()); + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!nodeMap->isValid()) return NanThrowError(releasedMessage()); + if (!nodeMap->isValid()) return Nan::ThrowError(releasedMessage()); - if (args.Length() <= 0 || !args[0]->IsObject()) { - return NanThrowTypeError("First argument must be an options object"); + if (info.Length() <= 0 || !info[0]->IsObject()) { + return Nan::ThrowTypeError("First argument must be an options object"); } - if (args.Length() <= 1 || !args[1]->IsFunction()) { - return NanThrowTypeError("Second argument must be a callback function"); + if (info.Length() <= 1 || !info[1]->IsFunction()) { + return Nan::ThrowTypeError("Second argument must be a callback function"); } if (!nodeMap->isLoaded()) { - return NanThrowTypeError("Style is not loaded"); + return Nan::ThrowTypeError("Style is not loaded"); } - auto options = ParseOptions(args[0]->ToObject()); + auto options = ParseOptions(info[0]->ToObject()); assert(!nodeMap->callback); assert(!nodeMap->image); - nodeMap->callback = std::unique_ptr(new NanCallback(args[1].As())); + nodeMap->callback = std::make_unique(info[1].As()); try { nodeMap->startRender(std::move(options)); } catch (mbgl::util::Exception &ex) { - return NanThrowError(ex.what()); + return Nan::ThrowError(ex.what()); } - NanReturnUndefined(); + info.GetReturnValue().SetUndefined(); } void NodeMap::startRender(std::unique_ptr options) { @@ -221,7 +229,7 @@ void NodeMap::startRender(std::unique_ptr options) { } void NodeMap::renderFinished() { - NanScope(); + Nan::HandleScope scope; // We're done with this render call, so we're unrefing so that the loop could close. uv_unref(reinterpret_cast(async)); @@ -249,7 +257,7 @@ void NodeMap::renderFinished() { } v8::Local argv[] = { - NanError(errorMessage.c_str()) + Nan::Error(errorMessage.c_str()) }; // This must be empty to be prepared for the next render call. @@ -258,7 +266,7 @@ void NodeMap::renderFinished() { cb->Call(1, argv); } else if (img) { - v8::Local pixels = NanNewBufferHandle( + v8::Local pixels = Nan::NewBuffer( reinterpret_cast(img->pixels.get()), size_t(img->width) * size_t(img->height) * sizeof(mbgl::StillImage::Pixel), @@ -267,36 +275,34 @@ void NodeMap::renderFinished() { delete reinterpret_cast(hint); }, const_cast(img.get()) - ); + ).ToLocalChecked(); img.release(); v8::Local argv[] = { - NanNull(), + Nan::Null(), pixels, }; cb->Call(2, argv); } else { v8::Local argv[] = { - NanError("Didn't get an image") + Nan::Error("Didn't get an image") }; cb->Call(1, argv); } } NAN_METHOD(NodeMap::Release) { - NanScope(); - - auto nodeMap = node::ObjectWrap::Unwrap(args.Holder()); + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!nodeMap->isValid()) return NanThrowError(releasedMessage()); + if (!nodeMap->isValid()) return Nan::ThrowError(releasedMessage()); try { nodeMap->release(); } catch (const std::exception &ex) { - return NanThrowError(ex.what()); + return Nan::ThrowError(ex.what()); } - NanReturnUndefined(); + info.GetReturnValue().SetUndefined(); } void NodeMap::release() { @@ -315,8 +321,8 @@ void NodeMap::release() { //////////////////////////////////////////////////////////////////////////////////////////////// // Instance -NodeMap::NodeMap(v8::Handle options) : - view(sharedDisplay(), options->Get(NanNew("ratio"))->NumberValue()), +NodeMap::NodeMap(v8::Local options) : + view(sharedDisplay(), Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->NumberValue()), fs(options), map(std::make_unique(view, fs, mbgl::MapMode::Still)), async(new uv_async_t) { diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp index 2c87900d4d8..90edf44f735 100644 --- a/platform/node/src/node_map.hpp +++ b/platform/node/src/node_map.hpp @@ -8,7 +8,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wshadow" -#include #include #pragma GCC diagnostic pop @@ -16,14 +15,13 @@ namespace node_mbgl { -class NodeMap : public node::ObjectWrap { +class NodeMap : public Nan::ObjectWrap { +public: struct RenderOptions; class RenderWorker; - //////////////////////////////////////////////////////////////////////////////////////////////// - // Static Node Methods -public: - static void Init(v8::Handle target); + static NAN_MODULE_INIT(Init); + static NAN_METHOD(New); static NAN_METHOD(Load); static NAN_METHOD(Render); @@ -37,24 +35,20 @@ class NodeMap : public node::ObjectWrap { inline bool isLoaded() { return loaded; } inline bool isValid() { return valid; } - static std::unique_ptr ParseOptions(v8::Local obj); + static std::unique_ptr ParseOptions(v8::Local); + static Nan::Persistent constructor; - static v8::Persistent constructorTemplate; - - //////////////////////////////////////////////////////////////////////////////////////////////// - // Instance private: - NodeMap(v8::Handle); + NodeMap(v8::Local); ~NodeMap(); -private: mbgl::HeadlessView view; NodeFileSource fs; std::unique_ptr map; std::exception_ptr error; std::unique_ptr image; - std::unique_ptr callback; + std::unique_ptr callback; // Async for delivering the notifications of render completion. uv_async_t *async; diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp index 14a0c9ad268..b631b32c54f 100644 --- a/platform/node/src/node_mapbox_gl_native.cpp +++ b/platform/node/src/node_mapbox_gl_native.cpp @@ -9,30 +9,57 @@ #include "node_log.hpp" #include "node_request.hpp" -void RegisterModule(v8::Handle exports) { - NanScope(); - - node_mbgl::NodeMap::Init(exports); - node_mbgl::NodeRequest::Init(exports); +NAN_MODULE_INIT(RegisterModule) { + node_mbgl::NodeMap::Init(target); + node_mbgl::NodeRequest::Init(target); // Exports Resource constants. - auto ConstantProperty = static_cast(v8::ReadOnly | v8::DontDelete); - auto resource = NanNew(); - resource->ForceSet(NanNew("Unknown"), NanNew(mbgl::Resource::Unknown), ConstantProperty); - resource->ForceSet(NanNew("Style"), NanNew(mbgl::Resource::Style), ConstantProperty); - resource->ForceSet(NanNew("Source"), NanNew(mbgl::Resource::Source), ConstantProperty); - resource->ForceSet(NanNew("Tile"), NanNew(mbgl::Resource::Tile), ConstantProperty); - resource->ForceSet(NanNew("Glyphs"), NanNew(mbgl::Resource::Glyphs), ConstantProperty); - resource->ForceSet(NanNew("SpriteImage"), NanNew(mbgl::Resource::SpriteImage), ConstantProperty); - resource->ForceSet(NanNew("SpriteJSON"), NanNew(mbgl::Resource::SpriteJSON), ConstantProperty); - exports->ForceSet(NanNew("Resource"), resource, ConstantProperty); - - // Make the exported object inerhit from process.EventEmitter - auto process = NanGetCurrentContext()->Global()->Get(NanNew("process"))->ToObject(); - auto EventEmitter = process->Get(NanNew("EventEmitter"))->ToObject(); - exports->SetPrototype(EventEmitter->Get(NanNew("prototype"))); - - mbgl::Log::setObserver(std::make_unique(exports)); + v8::Local resource = Nan::New(); + + Nan::Set(resource, + Nan::New("Unknown").ToLocalChecked(), + Nan::New(mbgl::Resource::Unknown)); + + Nan::Set(resource, + Nan::New("Style").ToLocalChecked(), + Nan::New(mbgl::Resource::Style)); + + Nan::Set(resource, + Nan::New("Source").ToLocalChecked(), + Nan::New(mbgl::Resource::Source)); + + Nan::Set(resource, + Nan::New("Tile").ToLocalChecked(), + Nan::New(mbgl::Resource::Tile)); + + Nan::Set(resource, + Nan::New("Glyphs").ToLocalChecked(), + Nan::New(mbgl::Resource::Glyphs)); + + Nan::Set(resource, + Nan::New("SpriteImage").ToLocalChecked(), + Nan::New(mbgl::Resource::SpriteImage)); + + Nan::Set(resource, + Nan::New("SpriteJSON").ToLocalChecked(), + Nan::New(mbgl::Resource::SpriteJSON)); + + Nan::Set(target, + Nan::New("Resource").ToLocalChecked(), + resource); + + // Make the exported object inherit from process.EventEmitter + v8::Local process = Nan::Get( + Nan::GetCurrentContext()->Global(), + Nan::New("process").ToLocalChecked()).ToLocalChecked()->ToObject(); + + v8::Local EventEmitter = Nan::Get(process, + Nan::New("EventEmitter").ToLocalChecked()).ToLocalChecked()->ToObject(); + + Nan::SetPrototype(target, + Nan::Get(EventEmitter, Nan::New("prototype").ToLocalChecked()).ToLocalChecked()); + + mbgl::Log::setObserver(std::make_unique(Nan::New(target))); } NODE_MODULE(mapbox_gl_native, RegisterModule) diff --git a/platform/node/src/node_request.cpp b/platform/node/src/node_request.cpp index ea9fc4d7327..09d7bf79847 100644 --- a/platform/node/src/node_request.cpp +++ b/platform/node/src/node_request.cpp @@ -11,112 +11,111 @@ namespace node_mbgl { //////////////////////////////////////////////////////////////////////////////////////////////// // Static Node Methods -v8::Persistent NodeRequest::constructorTemplate; +Nan::Persistent NodeRequest::constructor; -void NodeRequest::Init(v8::Handle target) { - NanScope(); +NAN_MODULE_INIT(NodeRequest::Init) { + v8::Local tpl = Nan::New(New); - v8::Local t = NanNew(New); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + tpl->SetClassName(Nan::New("Request").ToLocalChecked()); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("Request")); + Nan::SetPrototypeMethod(tpl, "respond", Respond); - NODE_SET_PROTOTYPE_METHOD(t, "respond", Respond); - - NanAssignPersistent(constructorTemplate, t); - - target->Set(NanNew("Request"), t->GetFunction()); + constructor.Reset(tpl->GetFunction()); + Nan::Set(target, Nan::New("Request").ToLocalChecked(), tpl->GetFunction()); } NAN_METHOD(NodeRequest::New) { - NanScope(); - // Extract the pointer from the first argument - if (args.Length() < 2 || !args[0]->IsExternal() || !args[1]->IsExternal()) { - return NanThrowTypeError("Cannot create Request objects explicitly"); + if (info.Length() < 2 || !info[0]->IsExternal() || !info[1]->IsExternal()) { + return Nan::ThrowTypeError("Cannot create Request objects explicitly"); } - auto source = reinterpret_cast(args[0].As()->Value()); - auto resource = reinterpret_cast(args[1].As()->Value()); + auto source = reinterpret_cast(info[0].As()->Value()); + auto resource = reinterpret_cast(info[1].As()->Value()); auto req = new NodeRequest(source, *resource); - req->Wrap(args.This()); + req->Wrap(info.This()); - NanReturnValue(args.This()); + info.GetReturnValue().Set(info.This()); } v8::Handle NodeRequest::Create(NodeFileSource* source, const mbgl::Resource& resource) { - NanEscapableScope(); + Nan::EscapableHandleScope scope; - v8::Local argv[] = { NanNew(const_cast(source)), - NanNew(const_cast(&resource)) }; - auto instance = NanNew(constructorTemplate)->GetFunction()->NewInstance(2, argv); + v8::Local argv[] = { + Nan::New(const_cast(source)), + Nan::New(const_cast(&resource)) + }; + auto instance = Nan::New(constructor)->NewInstance(2, argv); - instance->ForceSet(NanNew("url"), NanNew(resource.url), v8::ReadOnly); - instance->ForceSet(NanNew("kind"), NanNew(int(resource.kind)), v8::ReadOnly); + 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 NanEscapeScope(instance); + return scope.Escape(instance); } NAN_METHOD(NodeRequest::Respond) { - auto nodeRequest = ObjectWrap::Unwrap(args.Holder()); + auto nodeRequest = Nan::ObjectWrap::Unwrap(info.Holder()); // Request has already been responded to, or was canceled, fail silently. - if (!nodeRequest->resource) NanReturnUndefined(); + if (!nodeRequest->resource) { + return info.GetReturnValue().SetUndefined(); + } auto source = nodeRequest->source; auto resource = std::move(nodeRequest->resource); - if (args.Length() < 1) { - return NanThrowTypeError("First argument must be an error object"); - } else if (args[0]->BooleanValue()) { + if (info.Length() < 1) { + return Nan::ThrowTypeError("First argument must be an error object"); + } else if (info[0]->BooleanValue()) { auto response = std::make_shared(); response->status = mbgl::Response::Error; // Store the error string. - const NanUtf8String message { args[0]->ToString() }; + const Nan::Utf8String message { info[0]->ToString() }; response->message = std::string { *message, size_t(message.length()) }; source->notify(*resource, response); - } else if (args.Length() < 2 || !args[1]->IsObject()) { - return NanThrowTypeError("Second argument must be a response object"); + } else if (info.Length() < 2 || !info[1]->IsObject()) { + return Nan::ThrowTypeError("Second argument must be a response object"); } else { auto response = std::make_shared(); - auto res = args[1]->ToObject(); + auto res = info[1]->ToObject(); response->status = mbgl::Response::Successful; - if (res->Has(NanNew("modified"))) { - const double modified = res->Get(NanNew("modified"))->ToNumber()->Value(); + if (Nan::Has(res, Nan::New("modified").ToLocalChecked()).FromJust()) { + const double modified = Nan::Get(res, Nan::New("modified").ToLocalChecked()).ToLocalChecked()->ToNumber()->Value(); if (!std::isnan(modified)) { response->modified = modified / 1000; // JS timestamps are milliseconds } } - if (res->Has(NanNew("expires"))) { - const double expires = res->Get(NanNew("expires"))->ToNumber()->Value(); + if (Nan::Has(res, Nan::New("expires").ToLocalChecked()).FromJust()) { + const double expires = Nan::Get(res, Nan::New("expires").ToLocalChecked()).ToLocalChecked()->ToNumber()->Value(); if (!std::isnan(expires)) { response->expires = expires / 1000; // JS timestamps are milliseconds } } - if (res->Has(NanNew("etag"))) { - auto etagHandle = res->Get(NanNew("etag")); + if (Nan::Has(res, Nan::New("etag").ToLocalChecked()).FromJust()) { + auto etagHandle = Nan::Get(res, Nan::New("etag").ToLocalChecked()).ToLocalChecked(); if (etagHandle->BooleanValue()) { - const NanUtf8String etag { etagHandle->ToString() }; + const Nan::Utf8String etag { etagHandle->ToString() }; response->etag = std::string { *etag, size_t(etag.length()) }; } } - if (res->Has(NanNew("data"))) { - auto dataHandle = res->Get(NanNew("data")); + if (Nan::Has(res, Nan::New("data").ToLocalChecked()).FromJust()) { + auto dataHandle = Nan::Get(res, Nan::New("data").ToLocalChecked()).ToLocalChecked(); if (node::Buffer::HasInstance(dataHandle)) { response->data = std::string { node::Buffer::Data(dataHandle), node::Buffer::Length(dataHandle) }; } else { - return NanThrowTypeError("Response data must be a Buffer"); + return Nan::ThrowTypeError("Response data must be a Buffer"); } } @@ -124,7 +123,7 @@ NAN_METHOD(NodeRequest::Respond) { source->notify(*resource, response); } - NanReturnUndefined(); + info.GetReturnValue().SetUndefined(); } //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/platform/node/src/node_request.hpp b/platform/node/src/node_request.hpp index a690904ef25..35bb8e5205d 100644 --- a/platform/node/src/node_request.hpp +++ b/platform/node/src/node_request.hpp @@ -3,7 +3,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wshadow" -#include #include #pragma GCC diagnostic pop @@ -15,21 +14,16 @@ namespace node_mbgl { class NodeFileSource; -class NodeRequest : public node::ObjectWrap { - //////////////////////////////////////////////////////////////////////////////////////////////// - // Static Node Methods +class NodeRequest : public Nan::ObjectWrap { public: - static void Init(v8::Handle target); + static NAN_MODULE_INIT(Init); + static NAN_METHOD(New); static NAN_METHOD(Respond); static v8::Handle Create(NodeFileSource*, const mbgl::Resource&); + static Nan::Persistent constructor; - static v8::Persistent constructorTemplate; - - //////////////////////////////////////////////////////////////////////////////////////////////// - // Instance -public: NodeRequest(NodeFileSource* source, const mbgl::Resource& resource); ~NodeRequest(); From 627623edbcc0fa8812bfc345b3e338eff229626b Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 8 Sep 2015 17:14:39 -0400 Subject: [PATCH 2/4] Use nan with https://github.com/nodejs/nan/pull/443 fixed --- package.json | 2 +- platform/node/src/node_map.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b8305af3ed0..4284fccfd5b 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ } ], "dependencies": { - "nan": "^2.0.8", + "nan": "nodejs/nan#a71301e0f62877ca017c4ebec7fbac9f4359038e", "node-pre-gyp": "^0.6.9" }, "bundledDependencies": [ diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 0133babc048..121265f4fc4 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -280,7 +280,7 @@ void NodeMap::renderFinished() { v8::Local argv[] = { Nan::Null(), - pixels, + pixels }; cb->Call(2, argv); } else { From 3d48147f2f8d2ef3ed3a9b8848ba0304d27c3403 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 8 Sep 2015 15:17:49 -0400 Subject: [PATCH 3/4] add io.js v3.x support --- .travis.yml | 4 ++-- platform/node/CHANGELOG.md | 1 + platform/node/src/node_file_source.cpp | 2 +- platform/node/src/node_mapbox_gl_native.cpp | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2e300c568af..d16643364fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,7 +59,7 @@ matrix: apt: packages: [ 'lib32stdc++6' ] - os: linux - env: FLAVOR=node CXX=clang++-3.5 BUILDTYPE=Release NODE_VERSION=iojs-v2 + env: FLAVOR=node CXX=clang++-3.5 BUILDTYPE=Release NODE_VERSION=iojs-v3 addons: apt: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] @@ -79,7 +79,7 @@ matrix: - os: osx osx_image: xcode6.4 compiler: clang - env: FLAVOR=node NODE_VERSION=iojs-v2 + env: FLAVOR=node NODE_VERSION=iojs-v3 - os: osx osx_image: xcode6.4 compiler: clang diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md index 6d6486bd29d..927cc5ece49 100644 --- a/platform/node/CHANGELOG.md +++ b/platform/node/CHANGELOG.md @@ -9,6 +9,7 @@ render options. - Adds support for rendering v8 styles. - No longer load resources before a render request is made. +- Adds io.js v3.x support. # 1.1.3 diff --git a/platform/node/src/node_file_source.cpp b/platform/node/src/node_file_source.cpp index 29a4748c532..622584846cf 100644 --- a/platform/node/src/node_file_source.cpp +++ b/platform/node/src/node_file_source.cpp @@ -75,7 +75,7 @@ void NodeFileSource::processAdd(const mbgl::Resource& resource) { queue->ref(); } - auto requestHandle = Nan::New(NodeRequest::Create(this, resource)); + v8::Local requestHandle = NodeRequest::Create(this, resource)->ToObject(); pending.emplace(resource, requestHandle); v8::Local argv[] = { requestHandle }; diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp index b631b32c54f..c0fb47d1448 100644 --- a/platform/node/src/node_mapbox_gl_native.cpp +++ b/platform/node/src/node_mapbox_gl_native.cpp @@ -59,7 +59,7 @@ NAN_MODULE_INIT(RegisterModule) { Nan::SetPrototype(target, Nan::Get(EventEmitter, Nan::New("prototype").ToLocalChecked()).ToLocalChecked()); - mbgl::Log::setObserver(std::make_unique(Nan::New(target))); + mbgl::Log::setObserver(std::make_unique(target->ToObject())); } NODE_MODULE(mapbox_gl_native, RegisterModule) From 532bbd54845d78749983b9c5410f506d7dc64a66 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 9 Sep 2015 15:06:54 -0700 Subject: [PATCH 4/4] Add anonymous lambda for HandleScope --- platform/node/src/node_map.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 121265f4fc4..5b2a839164c 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -322,7 +322,10 @@ void NodeMap::release() { // Instance NodeMap::NodeMap(v8::Local options) : - view(sharedDisplay(), Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->NumberValue()), + view(sharedDisplay(), [&] { + Nan::HandleScope scope; + return Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->NumberValue(); + }()), fs(options), map(std::make_unique(view, fs, mbgl::MapMode::Still)), async(new uv_async_t) {