diff options
Diffstat (limited to 'platform/node/src')
-rw-r--r-- | platform/node/src/node_expression.cpp | 126 | ||||
-rw-r--r-- | platform/node/src/node_expression.hpp | 36 | ||||
-rw-r--r-- | platform/node/src/node_mapbox_gl_native.cpp | 2 |
3 files changed, 164 insertions, 0 deletions
diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp new file mode 100644 index 0000000000..51a9fca5ef --- /dev/null +++ b/platform/node/src/node_expression.cpp @@ -0,0 +1,126 @@ +#include "node_expression.hpp" +#include "node_conversion.hpp" + +#include <mbgl/style/conversion/geojson.hpp> +#include <mbgl/style/conversion/expression.hpp> +#include <mbgl/util/geojson.hpp> +#include <nan.h> + +using namespace mbgl::style; +using namespace mbgl::style::expression; + +namespace node_mbgl { + +Nan::Persistent<v8::Function> NodeExpression::constructor; + +void NodeExpression::Init(v8::Local<v8::Object> target) { + v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New); + tpl->SetClassName(Nan::New("Expression").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); // what is this doing? + + Nan::SetPrototypeMethod(tpl, "evaluate", Evaluate); + Nan::SetPrototypeMethod(tpl, "getType", GetType); + Nan::SetPrototypeMethod(tpl, "isFeatureConstant", IsFeatureConstant); + Nan::SetPrototypeMethod(tpl, "isZoomConstant", IsZoomConstant); + + constructor.Reset(tpl->GetFunction()); // what is this doing? + Nan::Set(target, Nan::New("Expression").ToLocalChecked(), tpl->GetFunction()); +} + +void NodeExpression::New(const Nan::FunctionCallbackInfo<v8::Value>& info) { + if (!info.IsConstructCall()) { + return Nan::ThrowTypeError("Use the new operator to create new Expression objects"); + } + + if (info.Length() < 1 || info[0]->IsUndefined()) { + return Nan::ThrowTypeError("Requires a JSON style expression argument."); + } + + auto expr = info[0]; + + try { + conversion::Error error; + auto expression = conversion::convert<std::unique_ptr<Expression>>(expr, error); + if (!expression) { + return Nan::ThrowTypeError(error.message.c_str()); + } + auto nodeExpr = new NodeExpression(std::move(*expression)); + nodeExpr->Wrap(info.This()); + } catch(std::exception &ex) { + return Nan::ThrowError(ex.what()); + } + + info.GetReturnValue().Set(info.This()); +} + +void NodeExpression::Evaluate(const Nan::FunctionCallbackInfo<v8::Value>& info) { + NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder()); + + if (info.Length() < 2) { + return Nan::ThrowTypeError("Requires arguments zoom and feature arguments."); + } + + float zoom = info[0]->NumberValue(); + + // Pending https://github.com/mapbox/mapbox-gl-native/issues/5623, + // stringify the geojson feature in order to use convert<GeoJSON, string>() + Nan::JSON NanJSON; + Nan::MaybeLocal<v8::String> geojsonString = NanJSON.Stringify(Nan::To<v8::Object>(info[1]).ToLocalChecked()); + if (geojsonString.IsEmpty()) { + return Nan::ThrowTypeError("couldn't stringify JSON"); + } + conversion::Error conversionError; + mbgl::optional<mbgl::GeoJSON> geoJSON = conversion::convert<mbgl::GeoJSON, std::string>(*Nan::Utf8String(geojsonString.ToLocalChecked()), conversionError); + if (!geoJSON) { + Nan::ThrowTypeError(conversionError.message.c_str()); + return; + } + + try { + mapbox::geojson::feature feature = geoJSON->get<mapbox::geojson::feature>(); + Error error; + auto result = nodeExpr->expression->evaluate(zoom, feature, error); + if (result) { + result->match( + [&] (const std::array<float, 2>&) {}, + [&] (const std::array<float, 4>&) {}, + [&] (const std::string s) { + info.GetReturnValue().Set(Nan::New(s.c_str()).ToLocalChecked()); + }, + [&] (const mbgl::Color& c) { + info.GetReturnValue().Set(Nan::New(c.stringify().c_str()).ToLocalChecked()); + }, + [&] (const auto& v) { + info.GetReturnValue().Set(Nan::New(v)); + } + ); + } else { + v8::Local<v8::Object> res = Nan::New<v8::Object>(); + Nan::Set(res, + Nan::New("error").ToLocalChecked(), + Nan::New(error.message.c_str()).ToLocalChecked()); + info.GetReturnValue().Set(res); + } + } catch(std::exception &ex) { + return Nan::ThrowTypeError(ex.what()); + } +} + +void NodeExpression::GetType(const Nan::FunctionCallbackInfo<v8::Value>& info) { + NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder()); + const auto& type = nodeExpr->expression->getType(); + const auto& name = type.match([&] (const auto& t) { return t.getName(); }); + info.GetReturnValue().Set(Nan::New(name.c_str()).ToLocalChecked()); +} + +void NodeExpression::IsFeatureConstant(const Nan::FunctionCallbackInfo<v8::Value>& info) { + NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder()); + info.GetReturnValue().Set(Nan::New(nodeExpr->expression->isFeatureConstant())); +} + +void NodeExpression::IsZoomConstant(const Nan::FunctionCallbackInfo<v8::Value>& info) { + NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder()); + info.GetReturnValue().Set(Nan::New(nodeExpr->expression->isZoomConstant())); +} + +} // namespace node_mbgl diff --git a/platform/node/src/node_expression.hpp b/platform/node/src/node_expression.hpp new file mode 100644 index 0000000000..8913bead1b --- /dev/null +++ b/platform/node/src/node_expression.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include <exception> +#include <memory> +#include <mbgl/style/function/expression.hpp> + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wshadow" +#include <nan.h> +#pragma GCC diagnostic pop + +using namespace mbgl::style::expression; + +namespace node_mbgl { + +class NodeExpression : public Nan::ObjectWrap { +public: + static void Init(v8::Local<v8::Object>); + +private: + NodeExpression(std::unique_ptr<Expression> expression_) : + expression(std::move(expression_)) + {}; + + static void New(const Nan::FunctionCallbackInfo<v8::Value>&); + static void Evaluate(const Nan::FunctionCallbackInfo<v8::Value>&); + static void GetType(const Nan::FunctionCallbackInfo<v8::Value>&); + static void IsFeatureConstant(const Nan::FunctionCallbackInfo<v8::Value>&); + static void IsZoomConstant(const Nan::FunctionCallbackInfo<v8::Value>&); + static Nan::Persistent<v8::Function> constructor; + + std::unique_ptr<Expression> expression; +}; + +} // namespace node_mbgl diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp index cdcc982220..96e96e4298 100644 --- a/platform/node/src/node_mapbox_gl_native.cpp +++ b/platform/node/src/node_mapbox_gl_native.cpp @@ -10,6 +10,7 @@ #include "node_map.hpp" #include "node_logging.hpp" #include "node_request.hpp" +#include "node_expression.hpp" void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module) { // This has the effect of: @@ -20,6 +21,7 @@ void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module) node_mbgl::NodeMap::Init(target); node_mbgl::NodeRequest::Init(); + node_mbgl::NodeExpression::Init(target); // Exports Resource constants. v8::Local<v8::Object> resource = Nan::New<v8::Object>(); |