[core] Emit MapChangeDidFailLoadingMap when the style cannot be loaded or parsed
Currently this signal is never emitted, which can cause the Still mode to starve in case of an invalid style or failed request.
This commit is contained in:
@@ -38,6 +38,7 @@ public:
|
||||
Impl(View&, FileSource&, MapMode, GLContextMode, ConstrainMode, ViewportMode);
|
||||
|
||||
void onNeedsRepaint() override;
|
||||
void onStyleError() override;
|
||||
void onResourceError(std::exception_ptr) override;
|
||||
|
||||
void update();
|
||||
@@ -316,6 +317,8 @@ void Map::setStyleURL(const std::string& url) {
|
||||
} else {
|
||||
Log::Error(Event::Setup, "loading style failed: %s", res.error->message.c_str());
|
||||
}
|
||||
impl->onStyleError();
|
||||
impl->onResourceError(std::make_exception_ptr(std::runtime_error(res.error->message)));
|
||||
} else if (res.notModified || res.noContent) {
|
||||
return;
|
||||
} else {
|
||||
@@ -343,8 +346,8 @@ void Map::setStyleJSON(const std::string& json) {
|
||||
}
|
||||
|
||||
void Map::Impl::loadStyleJSON(const std::string& json) {
|
||||
style->setJSON(json);
|
||||
style->setObserver(this);
|
||||
style->setJSON(json);
|
||||
styleJSON = json;
|
||||
|
||||
// force style cascade, causing all pending transitions to complete.
|
||||
@@ -908,6 +911,10 @@ void Map::Impl::onNeedsRepaint() {
|
||||
asyncUpdate.send();
|
||||
}
|
||||
|
||||
void Map::Impl::onStyleError() {
|
||||
view.notifyMapChange(MapChangeDidFailLoadingMap);
|
||||
}
|
||||
|
||||
void Map::Impl::onResourceError(std::exception_ptr error) {
|
||||
if (mode == MapMode::Still && callback) {
|
||||
callback(error, {});
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
* and `onNeedsRepaint` will be called.
|
||||
*/
|
||||
void onNeedsRepaint() override {}
|
||||
virtual void onStyleError() {}
|
||||
virtual void onResourceError(std::exception_ptr) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -14,24 +14,27 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
Parser::~Parser() = default;
|
||||
|
||||
void Parser::parse(const std::string& json) {
|
||||
StyleParseResult Parser::parse(const std::string& json) {
|
||||
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
|
||||
document.Parse<0>(json.c_str());
|
||||
|
||||
if (document.HasParseError()) {
|
||||
Log::Error(Event::ParseStyle, "Error parsing style JSON at %i: %s", document.GetErrorOffset(), rapidjson::GetParseError_En(document.GetParseError()));
|
||||
return;
|
||||
std::stringstream message;
|
||||
message << document.GetErrorOffset() << " - "
|
||||
<< rapidjson::GetParseError_En(document.GetParseError());
|
||||
|
||||
return std::make_exception_ptr(std::runtime_error(message.str()));
|
||||
}
|
||||
|
||||
if (!document.IsObject()) {
|
||||
Log::Error(Event::ParseStyle, "Style JSON must be an object");
|
||||
return;
|
||||
return std::make_exception_ptr(std::runtime_error("style must be an object"));
|
||||
}
|
||||
|
||||
if (document.HasMember("version")) {
|
||||
@@ -100,6 +103,8 @@ void Parser::parse(const std::string& json) {
|
||||
glyphURL = { glyphs.GetString(), glyphs.GetStringLength() };
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Parser::parseSources(const JSValue& value) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <forward_list>
|
||||
@@ -16,11 +17,13 @@
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
using StyleParseResult = std::exception_ptr;
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
~Parser();
|
||||
|
||||
void parse(const std::string&);
|
||||
StyleParseResult parse(const std::string&);
|
||||
|
||||
std::string spriteURL;
|
||||
std::string glyphURL;
|
||||
|
||||
@@ -90,7 +90,15 @@ void Style::setJSON(const std::string& json) {
|
||||
classes.clear();
|
||||
|
||||
Parser parser;
|
||||
parser.parse(json);
|
||||
auto error = parser.parse(json);
|
||||
|
||||
if (error) {
|
||||
Log::Error(Event::ParseStyle, "Failed to parse style: %s", util::toString(error).c_str());
|
||||
observer->onStyleError();
|
||||
observer->onResourceError(error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& source : parser.sources) {
|
||||
addSource(std::move(source));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"default": {
|
||||
"log": [
|
||||
[1, "ERROR", "ParseStyle", "Style JSON must be an object"]
|
||||
[1, "ERROR", "ParseStyle", "Failed to parse style: style must be an object"]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ TEST(Map, SetStyleInvalidJSON) {
|
||||
auto observer = Log::removeObserver();
|
||||
auto flo = dynamic_cast<FixtureLogObserver*>(observer.get());
|
||||
EXPECT_EQ(1u, flo->count({ EventSeverity::Error, Event::ParseStyle, -1,
|
||||
"Error parsing style JSON at 0: Invalid value." }));
|
||||
"Failed to parse style: 0 - Invalid value." }));
|
||||
auto unchecked = flo->unchecked();
|
||||
EXPECT_TRUE(unchecked.empty()) << unchecked;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <mbgl/style/parser.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
#include <mbgl/util/enum.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/tileset.hpp>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
@@ -32,7 +33,11 @@ TEST_P(StyleParserTest, ParseStyle) {
|
||||
Log::setObserver(std::unique_ptr<Log::Observer>(observer));
|
||||
|
||||
style::Parser parser;
|
||||
parser.parse(util::read_file(base + ".style.json"));
|
||||
auto error = parser.parse(util::read_file(base + ".style.json"));
|
||||
|
||||
if (error) {
|
||||
Log::Error(Event::ParseStyle, "Failed to parse style: %s", util::toString(error).c_str());
|
||||
}
|
||||
|
||||
for (auto it = infoDoc.MemberBegin(), end = infoDoc.MemberEnd(); it != end; it++) {
|
||||
const std::string name { it->name.GetString(), it->name.GetStringLength() };
|
||||
|
||||
Reference in New Issue
Block a user