#pragma once #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wshadow" #include #pragma GCC diagnostic pop #include #include #include namespace mbgl { namespace style { namespace conversion { template <> class ConversionTraits> { public: static bool isUndefined(const v8::Local& value) { Nan::HandleScope scope; return value->IsUndefined() || value->IsNull(); } static bool isArray(const v8::Local& value) { Nan::HandleScope scope; return value->IsArray(); } static std::size_t arrayLength(const v8::Local& value) { Nan::HandleScope scope; // const_cast because v8::Local::As is not marked const until node v8.0 v8::Local array = const_cast&>(value).As(); return array->Length(); } static v8::Local arrayMember(const v8::Local& value, std::size_t i) { Nan::EscapableHandleScope scope; // const_cast because v8::Local::As is not marked const until node v8.0 v8::Local array = const_cast&>(value).As(); return scope.Escape(Nan::Get(array, static_cast(i)).ToLocalChecked()); } static bool isObject(const v8::Local& value) { Nan::HandleScope scope; return value->IsObject() && !value->IsArray(); } static std::optional> objectMember(const v8::Local& value, const char* name) { Nan::EscapableHandleScope scope; if (!Nan::Has(Nan::To(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) { return {}; } Nan::MaybeLocal result = Nan::Get(Nan::To(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()); if (result.IsEmpty()) { return {}; } return {scope.Escape(result.ToLocalChecked())}; } template static std::optional eachMember(const v8::Local& value, Fn&& fn) { Nan::HandleScope scope; v8::Local names = Nan::GetOwnPropertyNames(Nan::To(value).ToLocalChecked()).ToLocalChecked(); for (uint32_t i = 0; i < names->Length(); ++i) { v8::Local k = Nan::Get(names, i).ToLocalChecked(); v8::Local v = Nan::Get(Nan::To(value).ToLocalChecked(), k).ToLocalChecked(); std::optional result = fn(*Nan::Utf8String(k), std::move(v)); // NOLINT(performance-move-const-arg) if (result) { return result; } } return {}; } static std::optional toBool(const v8::Local& value) { Nan::HandleScope scope; if (!value->IsBoolean()) { return {}; } return Nan::To(value).ToChecked(); } static std::optional toNumber(const v8::Local& value) { Nan::HandleScope scope; if (!value->IsNumber()) { return {}; } return static_cast(Nan::To(value).ToChecked()); } static std::optional toDouble(const v8::Local& value) { Nan::HandleScope scope; if (!value->IsNumber()) { return {}; } return Nan::To(value).ToChecked(); } static std::optional toString(const v8::Local& value) { Nan::HandleScope scope; if (!value->IsString()) { return {}; } return std::string(*Nan::Utf8String(value)); } static std::optional toValue(const v8::Local& 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 {Nan::To(value).ToChecked()}; } else if (value->IsInt32()) { return {Nan::To(value).ToChecked()}; } else if (value->IsNumber()) { return {Nan::To(value).ToChecked()}; } else if (value->IsArray()) { v8::Local array = value.As(); std::vector result; result.reserve(array->Length()); for (uint32_t i = 0; i < array->Length(); ++i) { v8::Local item = Nan::Get(array, i).ToLocalChecked(); auto converted = toValue(item); if (converted) { result.push_back(*converted); } } return {result}; } else { return {}; } } static std::optional toGeoJSON(const v8::Local& value, Error& error) { try { Nan::JSON NanJSON; v8::Local obj = Nan::To(value).ToLocalChecked(); v8::Local stringified = NanJSON.Stringify(obj).ToLocalChecked(); std::string string = *Nan::Utf8String(stringified); return parseGeoJSON(string, error); } catch (const std::exception& ex) { error = {ex.what()}; return {}; } } }; template std::optional convert(const v8::Local& value, Error& error, Args&&... args) { return convert(Convertible(value), error, std::forward(args)...); } } // namespace conversion } // namespace style } // namespace mbgl