[node] capture invalid input data as ParseError objects

This allows us to distinguish them from other types of errors
This commit is contained in:
Konstantin Käfer
2018-07-16 14:20:09 +02:00
committed by John Firebaugh
parent 1e454642c8
commit 30272924a9
5 changed files with 47 additions and 7 deletions

View File

@@ -47,6 +47,7 @@ struct NodeMap::RenderOptions {
};
Nan::Persistent<v8::Function> NodeMap::constructor;
Nan::Persistent<v8::Object> NodeMap::parseError;
static const char* releasedMessage() {
return "Map resources have already been released";
@@ -57,6 +58,20 @@ void NodeMapObserver::onDidFailLoadingMap(std::exception_ptr error) {
}
void NodeMap::Init(v8::Local<v8::Object> target) {
// Define a custom error class for parse errors
auto script = Nan::New<v8::UnboundScript>(Nan::New(R"JS(
class ParseError extends Error {
constructor(...params) {
super(...params);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ParseError);
}
}
}
ParseError)JS").ToLocalChecked()).ToLocalChecked();
parseError.Reset(Nan::To<v8::Object>(Nan::RunScript(script).ToLocalChecked()).ToLocalChecked());
Nan::Set(target, Nan::New("ParseError").ToLocalChecked(), Nan::New(parseError));
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Map").ToLocalChecked());
@@ -216,6 +231,8 @@ void NodeMap::Load(const Nan::FunctionCallbackInfo<v8::Value>& info) {
try {
nodeMap->map->getStyle().loadJSON(style);
} catch (const mbgl::util::StyleParseException& ex) {
return Nan::ThrowError(ParseError(ex.what()));
} catch (const std::exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -408,9 +425,11 @@ void NodeMap::Render(const Nan::FunctionCallbackInfo<v8::Value>& info) {
nodeMap->req = std::make_unique<RenderRequest>(Nan::To<v8::Function>(info[1]).ToLocalChecked());
nodeMap->startRender(std::move(options));
} catch (mbgl::style::conversion::Error& err) {
} catch (const mbgl::style::conversion::Error& err) {
return Nan::ThrowTypeError(err.message.c_str());
} catch (mbgl::util::Exception &ex) {
} catch (const mbgl::util::StyleParseException& ex) {
return Nan::ThrowError(ParseError(ex.what()));
} catch (const mbgl::util::Exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -459,6 +478,11 @@ void NodeMap::startRender(NodeMap::RenderOptions options) {
uv_ref(reinterpret_cast<uv_handle_t *>(async));
}
v8::Local<v8::Value> NodeMap::ParseError(const char* msg) {
v8::Local<v8::Value> argv[] = { Nan::New(msg).ToLocalChecked() };
return Nan::CallAsConstructor(Nan::New(parseError), 1, argv).ToLocalChecked();
}
void NodeMap::renderFinished() {
assert(req);
@@ -480,16 +504,19 @@ void NodeMap::renderFinished() {
v8::Local<v8::Object> target = Nan::New<v8::Object>();
if (error) {
std::string errorMessage;
v8::Local<v8::Value> err;
try {
std::rethrow_exception(error);
assert(false);
} catch (const mbgl::util::StyleParseException& ex) {
err = ParseError(ex.what());
} catch (const std::exception& ex) {
errorMessage = ex.what();
err = Nan::Error(ex.what());
}
v8::Local<v8::Value> argv[] = {
Nan::Error(errorMessage.c_str())
err
};
// This must be empty to be prepared for the next render call.