diff options
Diffstat (limited to 'platform/node')
-rw-r--r-- | platform/node/CHANGELOG.md | 11 | ||||
-rw-r--r-- | platform/node/DEVELOPING.md | 2 | ||||
-rw-r--r-- | platform/node/src/node_conversion.hpp | 183 | ||||
-rw-r--r-- | platform/node/src/node_expression.cpp | 230 | ||||
-rw-r--r-- | platform/node/src/node_expression.hpp | 40 | ||||
-rw-r--r-- | platform/node/src/node_geojson.hpp | 17 | ||||
-rw-r--r-- | platform/node/src/node_map.cpp | 110 | ||||
-rw-r--r-- | platform/node/src/node_map.hpp | 4 | ||||
-rw-r--r-- | platform/node/src/node_mapbox_gl_native.cpp | 2 | ||||
-rw-r--r-- | platform/node/test/expression.test.js | 71 | ||||
-rw-r--r-- | platform/node/test/ignores.json | 133 | ||||
-rw-r--r-- | platform/node/test/js/map.test.js | 3 | ||||
-rw-r--r-- | platform/node/test/suite_implementation.js | 22 |
13 files changed, 688 insertions, 140 deletions
diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md index 1d166a9a79..feb2b4185d 100644 --- a/platform/node/CHANGELOG.md +++ b/platform/node/CHANGELOG.md @@ -1,3 +1,14 @@ +# master +- The `Map` constructor now accepts a `mode` option which can be either `"static"` (default) or `"tile"`. It must be set to `"tile"` when rendering individual tiles in order for the symbols to match across tiles. + +# 3.5.8 - October 19, 2017 +- Fixes an issue that causes memory leaks when not deleting the frontend object + in NodeMap::release() +- Fixes a crash in Earcut: [#10245](https://github.com/mapbox/mapbox-gl-native/pull/10245) + +# 3.5.7 - October 9, 2017 +- Fixed an issue causing synchronous resource requests to stall [#10153](https://github.com/mapbox/mapbox-gl-native/pull/10153) + # 3.5.6 - September 29, 2017 - Protects against requests which throw [#9554](https://github.com/mapbox/mapbox-gl-native/pull/9554) - Fixed an issue around reusing a map object [#9554](https://github.com/mapbox/mapbox-gl-native/pull/9554) diff --git a/platform/node/DEVELOPING.md b/platform/node/DEVELOPING.md index 4e8da881a8..b313d75c13 100644 --- a/platform/node/DEVELOPING.md +++ b/platform/node/DEVELOPING.md @@ -1,6 +1,6 @@ # Developing the Mapbox GL Native Node.js module -This document explains how to build the [Node.js](https://nodejs.org/) bindings for [../../README.md](Mapbox GL Native) for contributing to the development of the bindings themselves. If you just want to use the module, you can simply install it via `npm`; see [README.md](README.md) for installation and usage instructions. +This document explains how to build the [Node.js](https://nodejs.org/) bindings for [Mapbox GL Native](../../README.md) for contributing to the development of the bindings themselves. If you just want to use the module, you can simply install it via `npm`; see [README.md](README.md) for installation and usage instructions. ## Building diff --git a/platform/node/src/node_conversion.hpp b/platform/node/src/node_conversion.hpp index d266745548..7c5bbf4386 100644 --- a/platform/node/src/node_conversion.hpp +++ b/platform/node/src/node_conversion.hpp @@ -9,111 +9,136 @@ #include <mbgl/util/optional.hpp> #include <mbgl/util/feature.hpp> #include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/geojson.hpp> namespace mbgl { namespace style { namespace conversion { -inline bool isUndefined(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - return value->IsUndefined() || value->IsNull(); -} +template <> +class ConversionTraits<v8::Local<v8::Value>> { +public: + static bool isUndefined(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + return value->IsUndefined() || value->IsNull(); + } -inline bool isArray(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - return value->IsArray(); -} + static bool isArray(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + return value->IsArray(); + } -inline std::size_t arrayLength(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - return value.As<v8::Array>()->Length(); -} + static std::size_t arrayLength(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + // const_cast because v8::Local<T>::As is not marked const until node v8.0 + v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>(); + return array->Length(); + } -inline v8::Local<v8::Value> arrayMember(v8::Local<v8::Value> value, std::size_t i) { - Nan::EscapableHandleScope scope; - return scope.Escape(Nan::Get(value.As<v8::Array>(), i).ToLocalChecked()); -} + static v8::Local<v8::Value> arrayMember(const v8::Local<v8::Value>& value, std::size_t i) { + Nan::EscapableHandleScope scope; + // const_cast because v8::Local<T>::As is not marked const until node v8.0 + v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>(); + return scope.Escape(Nan::Get(array, i).ToLocalChecked()); + } -inline bool isObject(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - return value->IsObject() && !value->IsArray(); -} + static bool isObject(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + return value->IsObject() && !value->IsArray(); + } -inline optional<v8::Local<v8::Value>> objectMember(v8::Local<v8::Value> value, const char * name) { - Nan::EscapableHandleScope scope; - if (!Nan::Has(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) { - return {}; + static optional<v8::Local<v8::Value>> objectMember(const v8::Local<v8::Value>& value, const char * name) { + Nan::EscapableHandleScope scope; + if (!Nan::Has(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) { + return {}; + } + Nan::MaybeLocal<v8::Value> result = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()); + if (result.IsEmpty()) { + return {}; + } + return {scope.Escape(result.ToLocalChecked())}; } - Nan::MaybeLocal<v8::Value> result = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()); - if (result.IsEmpty()) { + + template <class Fn> + static optional<Error> eachMember(const v8::Local<v8::Value>& value, Fn&& fn) { + Nan::HandleScope scope; + 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(Nan::To<v8::Object>(value).ToLocalChecked(), k).ToLocalChecked(); + optional<Error> result = fn(*Nan::Utf8String(k), std::move(v)); + if (result) { + return result; + } + } return {}; } - return scope.Escape(result.ToLocalChecked()); -} -template <class Fn> -optional<Error> eachMember(v8::Local<v8::Value> value, Fn&& fn) { - Nan::HandleScope scope; - 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(Nan::To<v8::Object>(value).ToLocalChecked(), k).ToLocalChecked(); - optional<Error> result = fn(*Nan::Utf8String(k), v); - if (result) { - return result; + static optional<bool> toBool(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + if (!value->IsBoolean()) { + return {}; } + return value->BooleanValue(); } - return {}; -} -inline optional<bool> toBool(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - if (!value->IsBoolean()) { - return {}; + static optional<float> toNumber(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + if (!value->IsNumber()) { + return {}; + } + return value->NumberValue(); } - return value->BooleanValue(); -} -inline optional<float> toNumber(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - if (!value->IsNumber()) { - return {}; + static optional<double> toDouble(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + if (!value->IsNumber()) { + return {}; + } + return value->NumberValue(); } - return value->NumberValue(); -} -inline optional<double> toDouble(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - if (!value->IsNumber()) { - return {}; + static optional<std::string> toString(const v8::Local<v8::Value>& value) { + Nan::HandleScope scope; + if (!value->IsString()) { + return {}; + } + return std::string(*Nan::Utf8String(value)); } - return value->NumberValue(); -} -inline optional<std::string> toString(v8::Local<v8::Value> value) { - Nan::HandleScope scope; - if (!value->IsString()) { - return {}; + static optional<Value> toValue(const v8::Local<v8::Value>& value) { + if (value->IsFalse()) { + return { false }; + } else if (value->IsTrue()) { + return { true }; + } else if (value->IsString()) { + return { std::string(*Nan::Utf8String(value)) }; + } else if (value->IsUint32()) { + return { std::uint64_t(value->Uint32Value()) }; + } else if (value->IsInt32()) { + return { std::int64_t(value->Int32Value()) }; + } else if (value->IsNumber()) { + return { value->NumberValue() }; + } else { + return {}; + } } - return std::string(*Nan::Utf8String(value)); -} -inline optional<Value> toValue(v8::Local<v8::Value> value) { - if (value->IsFalse()) { - return { false }; - } else if (value->IsTrue()) { - return { true }; - } else if (value->IsString()) { - return { std::string(*Nan::Utf8String(value)) }; - } else if (value->IsUint32()) { - return { std::uint64_t(value->Uint32Value()) }; - } else if (value->IsInt32()) { - return { std::int64_t(value->Int32Value()) }; - } else if (value->IsNumber()) { - return { value->NumberValue() }; - } else { - return {}; + static optional<GeoJSON> toGeoJSON(const v8::Local<v8::Value>& value, Error& error) { + try { + Nan::JSON JSON; + std::string string = *Nan::Utf8String(JSON.Stringify(value->ToObject()).ToLocalChecked()); + return parseGeoJSON(string, error); + } catch (const std::exception& ex) { + error = { ex.what() }; + return {}; + } } +}; + +template <class T, class...Args> +optional<T> convert(const v8::Local<v8::Value>& value, Error& error, Args&&...args) { + return convert<T>(Convertible(value), error, std::forward<Args>(args)...); } } // namespace conversion diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp new file mode 100644 index 0000000000..8958d5c6c7 --- /dev/null +++ b/platform/node/src/node_expression.cpp @@ -0,0 +1,230 @@ +#include "node_conversion.hpp" +#include "node_expression.hpp" + +#include <mbgl/style/expression/parsing_context.hpp> +#include <mbgl/style/expression/is_constant.hpp> +#include <mbgl/style/conversion/geojson.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); + + Nan::SetMethod(tpl, "parse", Parse); + + constructor.Reset(tpl->GetFunction()); // what is this doing? + Nan::Set(target, Nan::New("Expression").ToLocalChecked(), tpl->GetFunction()); +} + +type::Type parseType(v8::Local<v8::Object> type) { + static std::unordered_map<std::string, type::Type> types = { + {"string", type::String}, + {"number", type::Number}, + {"noolean", type::Boolean}, + {"object", type::Object}, + {"color", type::Color}, + {"value", type::Value} + }; + + v8::Local<v8::Value> v8kind = Nan::Get(type, Nan::New("kind").ToLocalChecked()).ToLocalChecked(); + std::string kind(*v8::String::Utf8Value(v8kind)); + + if (kind == "array") { + type::Type itemType = parseType(Nan::Get(type, Nan::New("itemType").ToLocalChecked()).ToLocalChecked()->ToObject()); + mbgl::optional<std::size_t> N; + + v8::Local<v8::String> Nkey = Nan::New("N").ToLocalChecked(); + if (Nan::Has(type, Nkey).FromMaybe(false)) { + N = Nan::Get(type, Nkey).ToLocalChecked()->ToInt32()->Value(); + } + return type::Array(itemType, N); + } + + return types[kind]; +} + +void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) { + v8::Local<v8::Function> cons = Nan::New(constructor); + + if (info.Length() < 1 || info[0]->IsUndefined()) { + return Nan::ThrowTypeError("Requires a JSON style expression argument."); + } + + mbgl::optional<type::Type> expected; + if (info.Length() > 1 && info[1]->IsObject()) { + expected = parseType(info[1]->ToObject()); + } + + auto expr = info[0]; + + try { + ParsingContext ctx(expected); + ParseResult parsed = ctx.parse(mbgl::style::conversion::Convertible(expr)); + if (parsed) { + assert(ctx.getErrors().size() == 0); + auto nodeExpr = new NodeExpression(std::move(*parsed)); + const int argc = 0; + v8::Local<v8::Value> argv[0] = {}; + auto wrapped = Nan::NewInstance(cons, argc, argv).ToLocalChecked(); + nodeExpr->Wrap(wrapped); + info.GetReturnValue().Set(wrapped); + return; + } + + v8::Local<v8::Array> result = Nan::New<v8::Array>(); + for (std::size_t i = 0; i < ctx.getErrors().size(); i++) { + const auto& error = ctx.getErrors()[i]; + v8::Local<v8::Object> err = Nan::New<v8::Object>(); + Nan::Set(err, + Nan::New("key").ToLocalChecked(), + Nan::New(error.key.c_str()).ToLocalChecked()); + Nan::Set(err, + Nan::New("error").ToLocalChecked(), + Nan::New(error.message.c_str()).ToLocalChecked()); + Nan::Set(result, Nan::New((uint32_t)i), err); + } + info.GetReturnValue().Set(result); + } catch(std::exception &ex) { + return Nan::ThrowError(ex.what()); + } +} + +void NodeExpression::New(const Nan::FunctionCallbackInfo<v8::Value>& info) { + if (!info.IsConstructCall()) { + return Nan::ThrowTypeError("Use the new operator to create new Expression objects"); + } + + info.GetReturnValue().Set(info.This()); +} + +struct ToValue { + v8::Local<v8::Value> operator()(mbgl::NullValue) { + Nan::EscapableHandleScope scope; + return scope.Escape(Nan::Null()); + } + + v8::Local<v8::Value> operator()(bool t) { + Nan::EscapableHandleScope scope; + return scope.Escape(Nan::New(t)); + } + + v8::Local<v8::Value> operator()(double t) { + Nan::EscapableHandleScope scope; + return scope.Escape(Nan::New(t)); + } + + v8::Local<v8::Value> operator()(const std::string& t) { + Nan::EscapableHandleScope scope; + return scope.Escape(Nan::New(t).ToLocalChecked()); + } + + v8::Local<v8::Value> operator()(const std::vector<Value>& array) { + Nan::EscapableHandleScope scope; + v8::Local<v8::Array> result = Nan::New<v8::Array>(); + for (unsigned int i = 0; i < array.size(); i++) { + result->Set(i, toJS(array[i])); + } + return scope.Escape(result); + } + + v8::Local<v8::Value> operator()(const mbgl::Color& color) { + return operator()(std::vector<Value> { + static_cast<double>(color.r), + static_cast<double>(color.g), + static_cast<double>(color.b), + static_cast<double>(color.a) + }); + } + + v8::Local<v8::Value> operator()(const std::unordered_map<std::string, Value>& map) { + Nan::EscapableHandleScope scope; + v8::Local<v8::Object> result = Nan::New<v8::Object>(); + for (const auto& entry : map) { + Nan::Set(result, Nan::New(entry.first).ToLocalChecked(), toJS(entry.second)); + } + + return scope.Escape(result); + } +}; + +v8::Local<v8::Value> toJS(const Value& value) { + return Value::visit(value, ToValue()); +} + +void NodeExpression::Evaluate(const Nan::FunctionCallbackInfo<v8::Value>& info) { + NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder()); + const std::unique_ptr<Expression>& expression = nodeExpr->expression; + + if (info.Length() < 2 || !info[0]->IsObject()) { + return Nan::ThrowTypeError("Requires globals and feature arguments."); + } + + mbgl::optional<float> zoom; + v8::Local<v8::Value> v8zoom = Nan::Get(info[0]->ToObject(), Nan::New("zoom").ToLocalChecked()).ToLocalChecked(); + if (v8zoom->IsNumber()) zoom = v8zoom->NumberValue(); + + mbgl::optional<double> heatmapDensity; + v8::Local<v8::Value> v8heatmapDensity = Nan::Get(info[0]->ToObject(), Nan::New("heatmapDensity").ToLocalChecked()).ToLocalChecked(); + if (v8heatmapDensity->IsNumber()) heatmapDensity = v8heatmapDensity->NumberValue(); + + Nan::JSON NanJSON; + conversion::Error conversionError; + mbgl::optional<mbgl::GeoJSON> geoJSON = conversion::convert<mbgl::GeoJSON>(info[1], conversionError); + if (!geoJSON) { + Nan::ThrowTypeError(conversionError.message.c_str()); + return; + } + + try { + mapbox::geojson::feature feature = geoJSON->get<mapbox::geojson::feature>(); + auto result = expression->evaluate(zoom, feature, heatmapDensity); + if (result) { + info.GetReturnValue().Set(toJS(*result)); + } else { + v8::Local<v8::Object> res = Nan::New<v8::Object>(); + Nan::Set(res, + Nan::New("error").ToLocalChecked(), + Nan::New(result.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 std::unique_ptr<Expression>& expression = nodeExpr->expression; + + const type::Type type = expression->getType(); + const std::string 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()); + const std::unique_ptr<Expression>& expression = nodeExpr->expression; + info.GetReturnValue().Set(Nan::New(isFeatureConstant(*expression))); +} + +void NodeExpression::IsZoomConstant(const Nan::FunctionCallbackInfo<v8::Value>& info) { + NodeExpression* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder()); + const std::unique_ptr<Expression>& expression = nodeExpr->expression; + info.GetReturnValue().Set(Nan::New(isZoomConstant(*expression))); +} + +} // 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..7af5b7ab51 --- /dev/null +++ b/platform/node/src/node_expression.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/expression/expression.hpp> +#include <exception> +#include <memory> + +#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 { + +v8::Local<v8::Value> toJS(const Value&); + +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 Parse(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_geojson.hpp b/platform/node/src/node_geojson.hpp deleted file mode 100644 index 8a3927e2cf..0000000000 --- a/platform/node/src/node_geojson.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#include <mbgl/style/conversion/geojson.hpp> - -#include <string> -namespace mbgl { -namespace style { -namespace conversion { - -template <> -optional<GeoJSON> Converter<GeoJSON>::operator()(const v8::Local<v8::Value>& value, Error& error) const { - Nan::JSON JSON; - std::string string = *Nan::Utf8String(JSON.Stringify(value->ToObject()).ToLocalChecked()); - return convert<GeoJSON>(string, error); -} - -} // namespace conversion -} // namespace style -} // namespace mbgl diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 9a7ebce445..b8c5e9cc88 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -2,7 +2,6 @@ #include "node_request.hpp" #include "node_feature.hpp" #include "node_conversion.hpp" -#include "node_geojson.hpp" #include <mbgl/util/exception.hpp> #include <mbgl/renderer/renderer.hpp> @@ -10,6 +9,15 @@ #include <mbgl/style/conversion/source.hpp> #include <mbgl/style/conversion/layer.hpp> #include <mbgl/style/conversion/filter.hpp> + +#include <mbgl/style/layers/background_layer.hpp> +#include <mbgl/style/layers/circle_layer.hpp> +#include <mbgl/style/layers/fill_layer.hpp> +#include <mbgl/style/layers/fill_extrusion_layer.hpp> +#include <mbgl/style/layers/line_layer.hpp> +#include <mbgl/style/layers/raster_layer.hpp> +#include <mbgl/style/layers/symbol_layer.hpp> + #include <mbgl/style/style.hpp> #include <mbgl/style/image.hpp> #include <mbgl/map/map_observer.hpp> @@ -26,6 +34,9 @@ struct NodeMap::RenderOptions { double latitude = 0; double longitude = 0; mbgl::Size size = { 512, 512 }; + bool axonometric = false; + double xSkew = 0; + double ySkew = 1; std::vector<std::string> classes; mbgl::MapDebugOptions debugOptions = mbgl::MapDebugOptions::NoDebug; }; @@ -65,6 +76,9 @@ void NodeMap::Init(v8::Local<v8::Object> target) { Nan::SetPrototypeMethod(tpl, "setZoom", SetZoom); Nan::SetPrototypeMethod(tpl, "setBearing", SetBearing); Nan::SetPrototypeMethod(tpl, "setPitch", SetPitch); + Nan::SetPrototypeMethod(tpl, "setAxonometric", SetAxonometric); + Nan::SetPrototypeMethod(tpl, "setXSkew", SetXSkew); + Nan::SetPrototypeMethod(tpl, "setYSkew", SetYSkew); Nan::SetPrototypeMethod(tpl, "dumpDebugLogs", DumpDebugLogs); Nan::SetPrototypeMethod(tpl, "queryRenderedFeatures", QueryRenderedFeatures); @@ -251,6 +265,19 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local<v8::Object> obj) { options.pitch = Nan::Get(obj, Nan::New("pitch").ToLocalChecked()).ToLocalChecked()->NumberValue(); } + if (Nan::Has(obj, Nan::New("axonometric").ToLocalChecked()).FromJust()) { + options.axonometric = Nan::Get(obj, Nan::New("axonometric").ToLocalChecked()).ToLocalChecked()->BooleanValue(); + } + + if (Nan::Has(obj, Nan::New("skew").ToLocalChecked()).FromJust()) { + auto skewObj = Nan::Get(obj, Nan::New("skew").ToLocalChecked()).ToLocalChecked(); + if (skewObj->IsArray()) { + auto skew = skewObj.As<v8::Array>(); + if (skew->Length() > 0) { options.xSkew = Nan::Get(skew, 0).ToLocalChecked()->NumberValue(); } + if (skew->Length() > 1) { options.ySkew = Nan::Get(skew, 1).ToLocalChecked()->NumberValue(); } + } + } + if (Nan::Has(obj, Nan::New("center").ToLocalChecked()).FromJust()) { auto centerObj = Nan::Get(obj, Nan::New("center").ToLocalChecked()).ToLocalChecked(); if (centerObj->IsArray()) { @@ -370,6 +397,18 @@ void NodeMap::startRender(NodeMap::RenderOptions options) { camera.angle = -options.bearing * mbgl::util::DEG2RAD; camera.pitch = options.pitch * mbgl::util::DEG2RAD; + if (map->getAxonometric() != options.axonometric) { + map->setAxonometric(options.axonometric); + } + + if (map->getXSkew() != options.xSkew) { + map->setXSkew(options.xSkew); + } + + if (map->getYSkew() != options.ySkew) { + map->setYSkew(options.ySkew); + } + map->renderStill(camera, options.debugOptions, [this](const std::exception_ptr eptr) { if (eptr) { error = std::move(eptr); @@ -477,6 +516,7 @@ void NodeMap::release() { }); map.reset(); + frontend.reset(); } /** @@ -508,7 +548,7 @@ void NodeMap::cancel() { frontend = std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size{ 256, 256 }, pixelRatio, *this, threadpool); map = std::make_unique<mbgl::Map>(*frontend, mapObserver, frontend->getSize(), pixelRatio, - *this, threadpool, mbgl::MapMode::Still); + *this, threadpool, mode); // FIXME: Reload the style after recreating the map. We need to find // a better way of canceling an ongoing rendering on the core level @@ -709,7 +749,7 @@ void NodeMap::SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>& info return Nan::ThrowTypeError("Second argument must be a string"); } - mbgl::optional<Error> error = setLayoutProperty(*layer, *Nan::Utf8String(info[1]), info[2]); + mbgl::optional<Error> error = setLayoutProperty(*layer, *Nan::Utf8String(info[1]), Convertible(info[2])); if (error) { return Nan::ThrowTypeError(error->message.c_str()); } @@ -741,7 +781,7 @@ void NodeMap::SetPaintProperty(const Nan::FunctionCallbackInfo<v8::Value>& info) return Nan::ThrowTypeError("Second argument must be a string"); } - mbgl::optional<Error> error = setPaintProperty(*layer, *Nan::Utf8String(info[1]), info[2]); + mbgl::optional<Error> error = setPaintProperty(*layer, *Nan::Utf8String(info[1]), Convertible(info[2])); if (error) { return Nan::ThrowTypeError(error->message.c_str()); } @@ -879,6 +919,57 @@ void NodeMap::SetPitch(const Nan::FunctionCallbackInfo<v8::Value>& info) { info.GetReturnValue().SetUndefined(); } +void NodeMap::SetAxonometric(const Nan::FunctionCallbackInfo<v8::Value>& info) { + auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder()); + if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); + + if (info.Length() <= 0 || !info[0]->IsBoolean()) { + return Nan::ThrowTypeError("First argument must be a boolean"); + } + + try { + nodeMap->map->setAxonometric(info[0]->BooleanValue()); + } catch (const std::exception &ex) { + return Nan::ThrowError(ex.what()); + } + + info.GetReturnValue().SetUndefined(); +} + +void NodeMap::SetXSkew(const Nan::FunctionCallbackInfo<v8::Value>& info) { + auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder()); + if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); + + if (info.Length() <= 0 || !info[0]->IsNumber()) { + return Nan::ThrowTypeError("First argument must be a number"); + } + + try { + nodeMap->map->setXSkew(info[0]->NumberValue()); + } catch (const std::exception &ex) { + return Nan::ThrowError(ex.what()); + } + + info.GetReturnValue().SetUndefined(); +} + +void NodeMap::SetYSkew(const Nan::FunctionCallbackInfo<v8::Value>& info) { + auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder()); + if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); + + if (info.Length() <= 0 || !info[0]->IsNumber()) { + return Nan::ThrowTypeError("First argument must be a number"); + } + + try { + nodeMap->map->setYSkew(info[0]->NumberValue()); + } catch (const std::exception &ex) { + return Nan::ThrowError(ex.what()); + } + + info.GetReturnValue().SetUndefined(); +} + void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>& info) { auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -983,6 +1074,15 @@ NodeMap::NodeMap(v8::Local<v8::Object> options) ->NumberValue() : 1.0; }()) + , mode([&] { + Nan::HandleScope scope; + if (Nan::Has(options, Nan::New("mode").ToLocalChecked()).FromJust() && + std::string(*v8::String::Utf8Value(Nan::Get(options, Nan::New("mode").ToLocalChecked()).ToLocalChecked()->ToString())) == "tile") { + return mbgl::MapMode::Tile; + } else { + return mbgl::MapMode::Static; + } + }()) , mapObserver(NodeMapObserver()) , frontend(std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size { 256, 256 }, pixelRatio, *this, threadpool)) , map(std::make_unique<mbgl::Map>(*frontend, @@ -991,7 +1091,7 @@ NodeMap::NodeMap(v8::Local<v8::Object> options) pixelRatio, *this, threadpool, - mbgl::MapMode::Still)), + mode)), async(new uv_async_t) { async->data = this; diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp index c8e33bb347..b84f4d576f 100644 --- a/platform/node/src/node_map.hpp +++ b/platform/node/src/node_map.hpp @@ -57,6 +57,9 @@ public: static void SetZoom(const Nan::FunctionCallbackInfo<v8::Value>&); static void SetBearing(const Nan::FunctionCallbackInfo<v8::Value>&); static void SetPitch(const Nan::FunctionCallbackInfo<v8::Value>&); + static void SetAxonometric(const Nan::FunctionCallbackInfo<v8::Value>&); + static void SetXSkew(const Nan::FunctionCallbackInfo<v8::Value>&); + static void SetYSkew(const Nan::FunctionCallbackInfo<v8::Value>&); static void DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>&); static void QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&); @@ -71,6 +74,7 @@ public: std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback); const float pixelRatio; + mbgl::MapMode mode; NodeThreadPool threadpool; NodeMapObserver mapObserver; std::unique_ptr<mbgl::HeadlessFrontend> frontend; 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>(); diff --git a/platform/node/test/expression.test.js b/platform/node/test/expression.test.js new file mode 100644 index 0000000000..aac039ce18 --- /dev/null +++ b/platform/node/test/expression.test.js @@ -0,0 +1,71 @@ +'use strict'; + +var suite = require('../../../mapbox-gl-js/test/integration').expression; +var mbgl = require('../index'); +var ignores = require('./ignores.json'); + +var tests; + +if (process.argv[1] === __filename && process.argv.length > 2) { + tests = process.argv.slice(2); +} + +function getExpectedType(spec) { + if (spec.type === 'array') { + const itemType = getExpectedType({ type: spec.value }); + const array = { + kind: 'array', + itemType: itemType || { kind: 'value' }, + }; + if (typeof spec.length === 'number') { + array.N = spec.length; + } + return array; + } + + if (spec.type === 'enum') { + return { kind: 'string' }; + } + + return typeof spec.type === 'string' ? {kind: spec.type} : null; +} + +suite.run('native', {ignores: ignores, tests: tests}, (fixture) => { + const compiled = {}; + const result = { + compiled + }; + + const spec = fixture.propertySpec || {}; + const expression = mbgl.Expression.parse(fixture.expression, getExpectedType(spec)); + + if (expression instanceof mbgl.Expression) { + compiled.result = 'success'; + compiled.isFeatureConstant = expression.isFeatureConstant(); + compiled.isZoomConstant = expression.isZoomConstant(); + compiled.type = expression.getType(); + + const evaluate = fixture.inputs || []; + const evaluateResults = []; + for (const input of evaluate) { + const feature = Object.assign({ + type: 'Feature', + properties: {}, + geometry: { type: 'Point', coordinates: [0, 0] } + }, input[1]) + + const output = expression.evaluate(input[0], feature); + evaluateResults.push(output); + } + + if (fixture.inputs) { + result.outputs = evaluateResults; + } + } else { + compiled.result = 'error'; + compiled.errors = expression; + } + + return result; +}); + diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index 1084a5c923..6428bcf49f 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -2,58 +2,127 @@ "query-tests/geometry/multilinestring": "needs investigation", "query-tests/geometry/multipolygon": "needs investigation", "query-tests/geometry/polygon": "needs investigation", - "query-tests/regressions/mapbox-gl-js#3534": "https://github.com/mapbox/mapbox-gl-native/issues/8193", - "query-tests/regressions/mapbox-gl-js#4417": "https://github.com/mapbox/mapbox-gl-native/issues/8007", - "query-tests/symbol-features-in/pitched-screen": "https://github.com/mapbox/mapbox-gl-native/issues/6817", - "query-tests/symbol-features-in/tilted-inside": "https://github.com/mapbox/mapbox-gl-native/issues/5056", - "query-tests/symbol-features-in/tilted-outside": "https://github.com/mapbox/mapbox-gl-native/issues/9435", + "query-tests/symbol/panned-after-insert": "https://github.com/mapbox/mapbox-gl-native/issues/10408", + "query-tests/symbol/rotated-after-insert": "https://github.com/mapbox/mapbox-gl-native/issues/10408", "query-tests/world-wrapping/box": "skip - needs issue", "query-tests/world-wrapping/point": "skip - needs issue", - "render-tests/debug/collision-overscaled": "https://github.com/mapbox/mapbox-gl-native/issues/3841", - "render-tests/debug/collision-pitched-wrapped": "https://github.com/mapbox/mapbox-gl-native/issues/3841", - "render-tests/debug/collision-pitched": "https://github.com/mapbox/mapbox-gl-native/issues/3841", + "render-tests/background-color/transition": "https://github.com/mapbox/mapbox-gl-native/issues/10619", "render-tests/debug/collision": "https://github.com/mapbox/mapbox-gl-native/issues/3841", - "render-tests/debug/tile-overscaled": "https://github.com/mapbox/mapbox-gl-native/issues/3841", + "render-tests/debug/collision-lines": "https://github.com/mapbox/mapbox-gl-native/issues/10412", + "render-tests/debug/collision-lines-pitched": "https://github.com/mapbox/mapbox-gl-native/issues/10412", + "render-tests/debug/collision-pitched-wrapped": "https://github.com/mapbox/mapbox-gl-native/issues/10412", "render-tests/debug/tile": "https://github.com/mapbox/mapbox-gl-native/issues/3841", + "render-tests/debug/tile-overscaled": "https://github.com/mapbox/mapbox-gl-native/issues/3841", "render-tests/extent/1024-circle": "needs investigation", - "render-tests/extent/1024-symbol": "needs investigation", "render-tests/fill-extrusion-pattern/@2x": "https://github.com/mapbox/mapbox-gl-js/issues/3327", - "render-tests/fill-extrusion-pattern/function-2": "https://github.com/mapbox/mapbox-gl-js/issues/3327", "render-tests/fill-extrusion-pattern/function": "https://github.com/mapbox/mapbox-gl-js/issues/3327", + "render-tests/fill-extrusion-pattern/function-2": "https://github.com/mapbox/mapbox-gl-js/issues/3327", "render-tests/fill-extrusion-pattern/literal": "https://github.com/mapbox/mapbox-gl-js/issues/3327", "render-tests/fill-extrusion-pattern/missing": "https://github.com/mapbox/mapbox-gl-js/issues/3327", "render-tests/fill-extrusion-pattern/opacity": "https://github.com/mapbox/mapbox-gl-js/issues/3327", "render-tests/geojson/inline-linestring-fill": "current behavior is arbitrary", "render-tests/geojson/inline-polygon-symbol": "behavior needs reconciliation with gl-js", - "render-tests/icon-size/composite-function-high-base-plain": "https://github.com/mapbox/mapbox-gl-native/issues/8654", - "render-tests/icon-size/composite-function-high-base-sdf": "https://github.com/mapbox/mapbox-gl-native/issues/8654", - "render-tests/icon-text-fit/both-padding": "https://github.com/mapbox/mapbox-gl-native/issues/5602", - "render-tests/icon-text-fit/both": "https://github.com/mapbox/mapbox-gl-native/issues/5602", - "render-tests/icon-text-fit/height": "https://github.com/mapbox/mapbox-gl-native/issues/5602", - "render-tests/icon-text-fit/width-padding": "https://github.com/mapbox/mapbox-gl-native/issues/5602", - "render-tests/icon-text-fit/width": "https://github.com/mapbox/mapbox-gl-native/issues/5602", - "render-tests/line-width/property-function": "https://github.com/mapbox/mapbox-gl-js/issues/3682#issuecomment-264348200", - "render-tests/line-join/property-function": "https://github.com/mapbox/mapbox-gl-js/pull/5020", - "render-tests/line-join/property-function-dasharray": "https://github.com/mapbox/mapbox-gl-js/pull/5020", - "render-tests/line-opacity/step-curve": "https://github.com/mapbox/mapbox-gl-native/pull/9439", + "render-tests/heatmap-color/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-color/expression": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-color/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-intensity/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-intensity/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-intensity/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-opacity/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-opacity/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-opacity/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-radius/antimeridian": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-radius/data-expression": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-radius/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-radius/function": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-radius/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-radius/pitch30": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-weight/default": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-weight/identity-property-function": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/heatmap-weight/literal": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/mixed-zoom/z10-z11": "https://github.com/mapbox/mapbox-gl-native/issues/10397", + "render-tests/raster-masking/overlapping-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/10195", "render-tests/regressions/mapbox-gl-js#2305": "https://github.com/mapbox/mapbox-gl-native/issues/6927", + "render-tests/regressions/mapbox-gl-js#2467": "https://github.com/mapbox/mapbox-gl-native/issues/10619", + "render-tests/regressions/mapbox-gl-js#2762": "https://github.com/mapbox/mapbox-gl-native/issues/10619", + "render-tests/regressions/mapbox-gl-js#2769": "https://github.com/mapbox/mapbox-gl-native/issues/10619", "render-tests/regressions/mapbox-gl-js#3682": "https://github.com/mapbox/mapbox-gl-js/issues/3682", + "render-tests/regressions/mapbox-gl-js#5370": "skip - https://github.com/mapbox/mapbox-gl-native/pull/9439", + "render-tests/regressions/mapbox-gl-js#5599": "https://github.com/mapbox/mapbox-gl-native/issues/10399", + "render-tests/regressions/mapbox-gl-js#5740": "https://github.com/mapbox/mapbox-gl-native/issues/10619", "render-tests/regressions/mapbox-gl-native#7357": "https://github.com/mapbox/mapbox-gl-native/issues/7357", "render-tests/runtime-styling/image-add-sdf": "https://github.com/mapbox/mapbox-gl-native/issues/9847", "render-tests/runtime-styling/paint-property-fill-flat-to-extrude": "https://github.com/mapbox/mapbox-gl-native/issues/6745", "render-tests/runtime-styling/set-style-paint-property-fill-flat-to-extrude": "https://github.com/mapbox/mapbox-gl-native/issues/6745", - "render-tests/symbol-placement/line": "needs issue", - "render-tests/text-font/camera-function": "https://github.com/mapbox/mapbox-gl-native/pull/9439", - "render-tests/text-keep-upright/line-placement-true-offset": "https://github.com/mapbox/mapbox-gl-native/issues/9271", + "render-tests/symbol-placement/line-overscaled": "https://github.com/mapbox/mapbox-gl-js/issues/5654", + "render-tests/symbol-visibility/visible": "https://github.com/mapbox/mapbox-gl-native/issues/10409", "render-tests/text-pitch-alignment/auto-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732", - "render-tests/text-pitch-alignment/auto-text-rotation-alignment-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/9732", "render-tests/text-pitch-alignment/map-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732", - "render-tests/text-pitch-alignment/map-text-rotation-alignment-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/9732", - "render-tests/text-pitch-alignment/viewport-overzoomed": "https://github.com/mapbox/mapbox-gl-js/issues/5095", - "render-tests/text-pitch-alignment/viewport-overzoomed-single-glyph": "https://github.com/mapbox/mapbox-gl-js/issues/5095", "render-tests/text-pitch-alignment/viewport-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732", - "render-tests/text-pitch-alignment/viewport-text-rotation-alignment-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/9732", "render-tests/text-pitch-scaling/line-half": "https://github.com/mapbox/mapbox-gl-native/issues/9732", - "render-tests/text-size/composite-expression": "https://github.com/mapbox/mapbox-gl-native/pull/9439", - "render-tests/video/default": "skip - https://github.com/mapbox/mapbox-gl-native/issues/601" + "render-tests/video/default": "skip - https://github.com/mapbox/mapbox-gl-native/issues/601", + "render-tests/background-color/colorSpace-hcl": "needs issue", + "render-tests/hillshade-accent-color/default": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-accent-color/literal": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-accent-color/zoom-function": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-highlight-color/default": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-highlight-color/literal": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-highlight-color/zoom-function": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-shadow-color/default": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-shadow-color/literal": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/hillshade-shadow-color/zoom-function": "skip - https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/background-opaque--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/background-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/circle-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/fill-extrusion-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/fill-opaque--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/fill-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--background-opaque": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--background-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--circle-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--fill-extrusion-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--fill-opaque": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--fill-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--line-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--raster-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/heatmap-translucent--symbol-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/line-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/raster-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/symbol-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/issues/10146", + "render-tests/combinations/background-opaque--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/background-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/circle-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/fill-extrusion-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/fill-opaque--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/fill-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--background-opaque": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--background-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--circle-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--fill-extrusion-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--fill-opaque": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--fill-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--heatmap-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--line-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--raster-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/hillshade-translucent--symbol-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/line-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/raster-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/symbol-translucent--hillshade-translucent": "https://github.com/mapbox/mapbox-gl-native/pull/10642", + "render-tests/combinations/background-opaque--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/background-translucent--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/circle-translucent--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/fill-extrusion-translucent--background-translucent": "needs investigation", + "render-tests/combinations/fill-extrusion-translucent--circle-translucent": "needs investigation", + "render-tests/combinations/fill-extrusion-translucent--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/fill-extrusion-translucent--fill-translucent": "needs investigation", + "render-tests/combinations/fill-extrusion-translucent--line-translucent": "needs investigation", + "render-tests/combinations/fill-extrusion-translucent--symbol-translucent": "needs investigation", + "render-tests/combinations/fill-opaque--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/fill-translucent--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/line-translucent--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/raster-translucent--fill-extrusion-translucent": "needs investigation", + "render-tests/combinations/symbol-translucent--fill-extrusion-translucent": "needs investigation" } diff --git a/platform/node/test/js/map.test.js b/platform/node/test/js/map.test.js index 39665e41ef..e3c8031908 100644 --- a/platform/node/test/js/map.test.js +++ b/platform/node/test/js/map.test.js @@ -121,6 +121,9 @@ test('Map', function(t) { 'setZoom', 'setBearing', 'setPitch', + 'setAxonometric', + 'setXSkew', + 'setYSkew', 'dumpDebugLogs', 'queryRenderedFeatures' ]); diff --git a/platform/node/test/suite_implementation.js b/platform/node/test/suite_implementation.js index 323f429bed..b0be2fa0eb 100644 --- a/platform/node/test/suite_implementation.js +++ b/platform/node/test/suite_implementation.js @@ -14,21 +14,25 @@ mbgl.on('message', function(msg) { var maps = new Map(); module.exports = function (style, options, callback) { + var tileMode = options.mapMode === 'tile'; if (options.recycleMap) { - if (maps.has(options.pixelRatio)) { - var map = maps.get(options.pixelRatio); + var key = options.pixelRatio + '/' + tileMode; + if (maps.has(key)) { + var map = maps.get(key); map.request = mapRequest; } else { - maps.set(options.pixelRatio, new mbgl.Map({ + maps.set(key, new mbgl.Map({ ratio: options.pixelRatio, - request: mapRequest + request: mapRequest, + mode: options.mapMode })); - var map = maps.get(options.pixelRatio); + var map = maps.get(key); } } else { var map = new mbgl.Map({ ratio: options.pixelRatio, - request: mapRequest + request: mapRequest, + mode: options.mapMode }); } @@ -90,6 +94,12 @@ module.exports = function (style, options, callback) { applyOperations(operations.slice(1), callback); }); + } else if (operation[0] === 'sleep') { + // Prefer "wait", which renders until the map is loaded + // Use "sleep" when you need to test something that sidesteps the "loaded" logic + setTimeout(() => { + applyOperations(operations.slice(1), callback); + }, operation[1]); } else if (operation[0] === 'addImage' || operation[0] === 'updateImage') { var img = PNG.sync.read(fs.readFileSync(path.join(__dirname, '../../../mapbox-gl-js/test/integration', operation[2]))); const testOpts = (operation.length > 3) ? operation[3] : {}; |