Feature - Bring back node support (#217)

This PR brings back support for node.js later versions, as well as actually making it work. Maps now render, properly, using node v10, v12, and v16.
This commit is contained in:
Justas Brazauskas
2022-02-08 21:40:19 +02:00
committed by GitHub
parent b7a42e9974
commit cfcbc62fad
25 changed files with 3357 additions and 131 deletions

138
.github/workflows/node-ci.yml vendored Normal file
View File

@@ -0,0 +1,138 @@
name: node-ci
on:
workflow_dispatch:
push:
tags-ignore:
- '**'
paths-ignore:
- "platform/android/**"
- "platform/ios/**"
- "platform/qt/**"
- ".gitignore"
branches:
- master
pull_request:
branches:
- master
paths-ignore:
- "platform/android/**"
- "platform/ios/**"
- ".gitignore"
jobs:
build:
strategy:
matrix:
os:
- macos-11.0
- macos-10.15
- ubuntu-20.04
- ubuntu-18.04
runs-on: ${{ matrix.os }}
env:
BUILDTYPE: ${{github.ref == 'refs/heads/master' && 'Release' || 'Debug'}}
defaults:
run:
working-directory: ./
shell: bash
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
fetch-depth: 0
- name: Install dependencies
if: runner.os == 'macOS'
env:
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
run: |
brew list cmake || brew install cmake
brew list ccache || brew install ccache
brew list ninja || brew install ninja
brew list pkg-config || brew install pkg-config
brew list glfw3 || brew install glfw3
brew list libuv || brew install libuv
- name: Install dependencies
if: runner.os == 'Linux'
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get install -y \
ccache \
cmake \
ninja-build \
pkg-config \
xvfb \
libcurl4-openssl-dev \
libglfw3-dev \
libuv1-dev \
g++-10 \
libc++-9-dev \
libc++abi-9-dev
/usr/sbin/update-ccache-symlinks
- name: npm ci
run: npm ci --ignore-scripts
- name: Prepare ccache
run: ccache --clear --set-config cache_dir=~/.ccache
- name: Cache ccache
uses: actions/cache@v2
env:
cache-name: ccache-v1
with:
path: ~/.ccache
key: ${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}-${{ github.ref }}-${{ github.sha }}-${{ github.head_ref }}
restore-keys: |
${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}-${{ github.ref }}
${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}
- name: Clear ccache statistics
run: |
ccache --zero-stats --set-config cache_dir=~/.ccache
ccache --max-size=2G --set-config cache_dir=~/.ccache
ccache --show-stats --set-config cache_dir=~/.ccache
- name: CMake
if: runner.os == 'macOS'
run: |
cmake . -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE=${{ env.BUILDTYPE }} -DMBGL_WITH_COVERAGE=ON
sed -i -e 's/$(ARCHS_STANDARD)/x86_64/g' build/build.ninja
sed -i -e 's/-arch arm64e/-arch x86_64/g' build/build.ninja
- name: CMake
if: runner.os == 'Linux'
run: |
cmake . -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10
- name: Build
run: |
cmake --build build -j $(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)
- name: Test
if: runner.os == 'Linux'
run: xvfb-run --auto-servernum npm test
- name: Test
if: runner.os == 'macOS'
run: npm test
# On PRs make sure that the npm package can be packaged.
- name: Pack
if: github.ref != 'refs/heads/master'
run: |
npm pack --dry-run
# Uncomment to start publishing the package
# @TODO: Figure out the binary distribution method.
# - name: Publish package
# if: github.ref == 'refs/heads/master'
# run: |
# npm publish

3
.gitignore vendored
View File

@@ -35,3 +35,6 @@
/platform/ios/platform/ios/benchmark/assets/glyphs/Roboto Condensed Italic,Noto Sans Italic
/platform/ios/platform/ios/benchmark/assets/glyphs/Noto Sans Regular
/platform/android/key.json
node_modules
# Node binaries.
/lib

3
.npmignore Normal file
View File

@@ -0,0 +1,3 @@
*
platform/node/src
platform/node/test

2954
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,21 @@
{
"name": "@mapbox/mapbox-gl-native",
"name": "@maplibre/maplibre-gl-native",
"version": "5.0.0",
"description": "Renders map tiles with Mapbox GL",
"description": "Renders map tiles with Maplibre GL",
"keywords": [
"mapbox",
"maplibre",
"gl"
],
"directories": {
"lib": "lib"
},
"files": [
"lib"
],
"main": "platform/node/index.js",
"repository": {
"type": "git",
"url": "git://github.com/mapbox/mapbox-gl-native.git"
"url": "git://github.com/maplibre/maplibre-gl-native.git"
},
"license": "BSD-2-Clause",
"dependencies": {

View File

@@ -27,6 +27,7 @@ public:
virtual gl::ProcAddress getExtensionFunctionPointer(const char*) = 0;
virtual void activateContext() = 0;
virtual void deactivateContext() {}
virtual void getContext() {}
};
private:

View File

@@ -32,7 +32,7 @@ HeadlessFrontend::HeadlessFrontend(Size size_,
asyncInvalidate([this] {
if (renderer && updateParameters) {
auto startTime = mbgl::util::MonotonicTimer::now();
gfx::BackendScope guard{*getBackend()};
gfx::BackendScope guard {*getBackend()};
// onStyleImageMissing might be called during a render. The user implemented method
// could trigger a call to MGLRenderFrontend#update which overwrites `updateParameters`.
@@ -143,6 +143,7 @@ PremultipliedImage HeadlessFrontend::readStillImage() {
HeadlessFrontend::RenderResult HeadlessFrontend::render(Map& map) {
HeadlessFrontend::RenderResult result;
std::exception_ptr error;
gfx::BackendScope guard { *getBackend() };
map.renderStill([&](const std::exception_ptr& e) {
if (e) {

View File

@@ -42,7 +42,7 @@ HeadlessBackend::HeadlessBackend(const Size size_,
: mbgl::gl::RendererBackend(contextMode_), mbgl::gfx::HeadlessBackend(size_), swapBehaviour(swapBehaviour_) {}
HeadlessBackend::~HeadlessBackend() {
gfx::BackendScope guard{*this};
gfx::BackendScope guard{ *this, gfx::BackendScope::ScopeType::Implicit };
resource.reset();
// Explicitly reset the context so that it is destructed and cleaned up before we destruct
// the impl object.
@@ -106,5 +106,3 @@ std::unique_ptr<gfx::HeadlessBackend> Backend::Create<gfx::Backend::Type::OpenGL
} // namespace gfx
} // namespace mbgl

View File

@@ -31,7 +31,9 @@ public:
~ForwardingRendererObserver() override { mailbox->close(); }
void onInvalidate() override { delegate.invoke(&RendererObserver::onInvalidate); }
void onInvalidate() override {
delegate.invoke(&RendererObserver::onInvalidate);
}
void onResourceError(std::exception_ptr err) override { delegate.invoke(&RendererObserver::onResourceError, err); }
@@ -62,7 +64,9 @@ public:
frontend.reset();
}
void onInvalidate() override { rendererObserver->onInvalidate(); }
void onInvalidate() override {
rendererObserver->onInvalidate();
}
void onResourceError(std::exception_ptr err) override {
hasPendingStillImageRequest = false;

View File

@@ -9,17 +9,39 @@ include(${PROJECT_SOURCE_DIR}/node_modules/@mapbox/cmake-node-module/module.cmak
add_node_module(
mbgl-node
INSTALL_PATH ${PROJECT_SOURCE_DIR}/lib/{node_abi}/mbgl.node
NAN_VERSION 2.10.0
NAN_VERSION 2.14.2
EXCLUDE_NODE_ABIS
46
47
48
51
59
67
72
79
83
)
find_package(PkgConfig REQUIRED)
pkg_search_module(LIBUV libuv REQUIRED)
add_library(mbgl-node-loop STATIC)
target_sources(
mbgl-node-loop
PRIVATE
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/util/async_task.cpp
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/util/run_loop.cpp
${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/util/timer.cpp
)
target_include_directories(
mbgl-node-loop
PUBLIC
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/platform/default/include
${PROJECT_SOURCE_DIR}/src
PRIVATE ${LIBUV_INCLUDE_DIRS}
)
target_link_libraries(
mbgl-node-loop
PUBLIC
Mapbox::Base
)
target_sources(
@@ -42,6 +64,7 @@ target_sources(
target_link_libraries(
mbgl-node
INTERFACE mbgl-node-loop
INTERFACE Mapbox::Map
)

View File

@@ -1,6 +1,6 @@
# Developing the Mapbox GL Native Node.js module
# Developing the Maplibre GL Native Node.js module
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.
This document explains how to build the [Node.js](https://nodejs.org/) bindings for [Maplibre 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
@@ -8,12 +8,69 @@ To develop these bindings, you’ll need to build them from source. Building req
the [macOS](../macos/INSTALL.md#requirements) or [Linux](../linux/README.md#prerequisites) install documentation, depending
on the target platform.
First you'll need to install dependencies:
#### MacOS
```bash
brew install \
cmake \
ccache \
ninja \
pkg-config \
glfw3 \
libuv
```
#### Linux (Ubuntu)
```bash
sudo apt-get install -y \
ccache \
cmake \
ninja-build \
pkg-config \
xvfb \
libcurl4-openssl-dev \
libglfw3-dev \
libuv1-dev \
g++-10 \
libc++-9-dev \
libc++abi-9-dev
/usr/sbin/update-ccache-symlinks
```
### Compiling
To compile the Node.js bindings and install module dependencies, from the repository root directory, first run:
#### MacOS
```bash
cmake . -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE=Debug -DMBGL_WITH_COVERAGE=ON
```
make distclean
Then, as a temporary step until build system is changed, run:
```bash
sed -i -e 's/$(ARCHS_STANDARD)/x86_64/g' build/build.ninja
sed -i -e 's/-arch arm64e/-arch x86_64/g' build/build.ninja
```
#### Linux
```bash
cmake . -B build -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10
```
### Building
Finally, build:
```bash
cmake --build build -j $(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)
```
If you are rebuilding after time has passed.
Then do:

View File

@@ -1,9 +1,12 @@
# node-mapbox-gl-native
# @maplibre/maplibre-gl-native
[![NPM](https://nodei.co/npm/@mapbox/mapbox-gl-native.png)](https://npmjs.org/package/@mapbox/mapbox-gl-native)
[![NPM](https://nodei.co/npm/@maplibre/maplibre-gl-native.png)](https://npmjs.org/package/@maplibre/maplibre-gl-native)
[![node-ci](https://github.com/maplibre/maplibre-gl-native/actions/workflows/node-ci.yml/badge.svg)](https://github.com/maplibre/maplibre-gl-native/actions/workflows/node-ci.yml)
## Installing
#### :warn: This package isn't live yet.
Requires a modern C++ runtime that supports C++14.
By default, installs binaries. On these platforms no additional dependencies are needed.
@@ -14,7 +17,7 @@ By default, installs binaries. On these platforms no additional dependencies are
Run:
```
npm install @mapbox/mapbox-gl-native
npm install @maplibre/maplibre-gl-native
```
Other platforms will fall back to a source compile with `make node`; see [DEVELOPING.md](DEVELOPING.md) for details on
@@ -32,7 +35,7 @@ npm run test-suite
```js
var fs = require('fs');
var path = require('path');
var mbgl = require('@mapbox/mapbox-gl-native');
var mbgl = require('@maplibre/maplibre-gl-native');
var sharp = require('sharp');
var options = {
@@ -106,7 +109,7 @@ The `request()` method handles a request for a resource. The `ratio` sets the sc
}
```
The `kind` is an enum and defined in [`mbgl.Resource`](https://github.com/mapbox/mapbox-gl-native/blob/master/include/mbgl/storage/resource.hpp):
The `kind` is an enum and defined in [`mbgl.Resource`](https://github.com/maplibre/maplibre-gl-native/blob/master/include/mbgl/storage/resource.hpp):
```json
{
@@ -150,7 +153,7 @@ This is a very barebones implementation and you'll probably want a better implem
A sample implementation that uses [`request`](https://github.com/request/request) to fetch data from a remote source:
```js
var mbgl = require('mapbox-gl-native');
var mbgl = require('@maplibre/maplibre-gl-native');
var request = require('request');
var map = new mbgl.Map({
@@ -184,10 +187,10 @@ Stylesheets are free to use any protocols, but your implementation of `request`
## Listening for log events
The module imported with `require('mapbox-gl-native')` inherits from [`EventEmitter`](https://nodejs.org/api/events.html), and the `NodeLogObserver` will push log events to this. Log messages can have [`class`](https://github.com/mapbox/mapbox-gl-native/blob/node-v2.1.0/include/mbgl/platform/event.hpp#L43-L60), [`severity`](https://github.com/mapbox/mapbox-gl-native/blob/node-v2.1.0/include/mbgl/platform/event.hpp#L17-L23), `code` ([HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)), and `text` parameters.
The module imported with `require('maplibre-gl-native')` inherits from [`EventEmitter`](https://nodejs.org/api/events.html), and the `NodeLogObserver` will push log events to this. Log messages can have [`class`](https://github.com/maplibre/maplibre-gl-native/blob/node-v2.1.0/include/mbgl/platform/event.hpp#L43-L60), [`severity`](https://github.com/maplibre/maplibre-gl-native/blob/node-v2.1.0/include/mbgl/platform/event.hpp#L17-L23), `code` ([HTTP status codes](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)), and `text` parameters.
```js
var mbgl = require('mapbox-gl-native');
var mbgl = require('@maplibre/maplibre-gl-native');
mbgl.on('message', function(msg) {
t.ok(msg, 'emits error');
t.equal(msg.class, 'Style');

View File

@@ -79,7 +79,7 @@ public:
if (!value->IsBoolean()) {
return {};
}
return value->BooleanValue();
return Nan::To<bool>(value).ToChecked();
}
static optional<float> toNumber(const v8::Local<v8::Value>& value) {
@@ -87,7 +87,7 @@ public:
if (!value->IsNumber()) {
return {};
}
return value->NumberValue();
return static_cast<float>(Nan::To<double>(value).ToChecked());
}
static optional<double> toDouble(const v8::Local<v8::Value>& value) {
@@ -95,7 +95,7 @@ public:
if (!value->IsNumber()) {
return {};
}
return value->NumberValue();
return Nan::To<double>(value).ToChecked();
}
static optional<std::string> toString(const v8::Local<v8::Value>& value) {
@@ -114,11 +114,11 @@ public:
} else if (value->IsString()) {
return { std::string(*Nan::Utf8String(value)) };
} else if (value->IsUint32()) {
return { std::uint64_t(value->Uint32Value()) };
return { Nan::To<std::uint32_t>(value).ToChecked() };
} else if (value->IsInt32()) {
return { std::int64_t(value->Int32Value()) };
return { Nan::To<std::int32_t>(value).ToChecked() };
} else if (value->IsNumber()) {
return { value->NumberValue() };
return { Nan::To<double>(value).ToChecked() };
} else {
return {};
}
@@ -126,8 +126,10 @@ public:
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());
Nan::JSON NanJSON;
v8::Local<v8::Object> obj = Nan::To<v8::Object>(value).ToLocalChecked();
v8::Local<v8::String> stringified = NanJSON.Stringify(obj).ToLocalChecked();
std::string string = *Nan::Utf8String(stringified);
return parseGeoJSON(string, error);
} catch (const std::exception& ex) {
error = { ex.what() };

View File

@@ -17,6 +17,7 @@ namespace node_mbgl {
Nan::Persistent<v8::Function> NodeExpression::constructor;
void NodeExpression::Init(v8::Local<v8::Object> target) {
v8::Local<v8::Context> context = target->CreationContext();
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Expression").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1); // what is this doing?
@@ -30,8 +31,8 @@ void NodeExpression::Init(v8::Local<v8::Object> target) {
Nan::SetMethod(tpl, "parse", Parse);
constructor.Reset(tpl->GetFunction()); // what is this doing?
Nan::Set(target, Nan::New("Expression").ToLocalChecked(), tpl->GetFunction());
constructor.Reset(tpl->GetFunction(context).ToLocalChecked()); // what is this doing?
Nan::Set(target, Nan::New("Expression").ToLocalChecked(), tpl->GetFunction(context).ToLocalChecked());
}
type::Type parseType(v8::Local<v8::Object> type) {
@@ -46,10 +47,11 @@ type::Type parseType(v8::Local<v8::Object> type) {
{"resolvedImage", type::Image}};
v8::Local<v8::Value> v8kind = Nan::Get(type, Nan::New("kind").ToLocalChecked()).ToLocalChecked();
std::string kind(*v8::String::Utf8Value(v8kind));
std::string kind(*v8::String::Utf8Value(v8::Isolate::GetCurrent(), v8kind));
if (kind == "array") {
type::Type itemType = parseType(Nan::Get(type, Nan::New("itemType").ToLocalChecked()).ToLocalChecked()->ToObject());
v8::Local<v8::Context> context = type->CreationContext();
type::Type itemType = parseType(Nan::Get(type, Nan::New("itemType").ToLocalChecked()).ToLocalChecked()->ToObject(context).ToLocalChecked());
mbgl::optional<std::size_t> N;
v8::Local<v8::String> Nkey = Nan::New("N").ToLocalChecked();
@@ -64,6 +66,7 @@ type::Type parseType(v8::Local<v8::Object> type) {
void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
v8::Local<v8::Function> cons = Nan::New(constructor);
v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
if (info.Length() < 1 || info[0]->IsUndefined()) {
return Nan::ThrowTypeError("Requires a JSON style expression argument.");
@@ -71,7 +74,7 @@ void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
mbgl::optional<type::Type> expected;
if (info.Length() > 1 && info[1]->IsObject()) {
expected = parseType(info[1]->ToObject());
expected = parseType(info[1]->ToObject(context).ToLocalChecked());
}
auto success = [&cons, &info](std::unique_ptr<Expression> result) {
@@ -157,8 +160,8 @@ struct ToValue {
v8::Local<v8::Value> operator()(const std::vector<Value>& array) {
Nan::EscapableHandleScope scope;
v8::Local<v8::Array> result = Nan::New<v8::Array>();
for (std::size_t i = 0; i < array.size(); i++) {
result->Set(i, toJS(array[i]));
for (std::uint32_t i = 0; i < array.size(); i++) {
Nan::Set(result, i, toJS(array[i]));
}
return scope.Escape(result);
}
@@ -170,7 +173,7 @@ struct ToValue {
Nan::EscapableHandleScope scope;
return scope.Escape(Nan::Null());
}
v8::Local<v8::Value> operator()(const Formatted& formatted) {
// This mimics the internal structure of the Formatted class in formatted.js
// A better approach might be to use the explicit serialized form
@@ -230,6 +233,7 @@ v8::Local<v8::Value> toJS(const Value& value) {
}
void NodeExpression::Evaluate(const Nan::FunctionCallbackInfo<v8::Value>& info) {
v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
auto* nodeExpr = ObjectWrap::Unwrap<NodeExpression>(info.Holder());
const std::unique_ptr<Expression>& expression = nodeExpr->expression;
@@ -238,12 +242,12 @@ void NodeExpression::Evaluate(const Nan::FunctionCallbackInfo<v8::Value>& info)
}
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();
v8::Local<v8::Value> v8zoom = Nan::Get(info[0]->ToObject(context).ToLocalChecked(), Nan::New("zoom").ToLocalChecked()).ToLocalChecked();
if (v8zoom->IsNumber()) zoom = Nan::To<double>(v8zoom).FromJust();
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();
v8::Local<v8::Value> v8heatmapDensity = Nan::Get(info[0]->ToObject(context).ToLocalChecked(), Nan::New("heatmapDensity").ToLocalChecked()).ToLocalChecked();
if (v8heatmapDensity->IsNumber()) heatmapDensity = Nan::To<double>(v8heatmapDensity).FromJust();
Nan::JSON NanJSON;
conversion::Error conversionError;

View File

@@ -113,7 +113,7 @@ struct ToValue {
Nan::EscapableHandleScope scope;
v8::Local<v8::Array> result = Nan::New<v8::Array>();
for (std::size_t i = 0; i < array.size(); i++) {
result->Set(i, toJS(array[i]));
Nan::Set(result, i, toJS(array[i]));
}
return scope.Escape(result);
}

View File

@@ -118,9 +118,10 @@ ParseError)JS").ToLocalChecked()).ToLocalChecked();
Nan::SetPrototypeMethod(tpl, "dumpDebugLogs", DumpDebugLogs);
Nan::SetPrototypeMethod(tpl, "queryRenderedFeatures", QueryRenderedFeatures);
v8::Local<v8::Context> context = target->CreationContext();
constructor.Reset(tpl->GetFunction());
Nan::Set(target, Nan::New("Map").ToLocalChecked(), tpl->GetFunction());
constructor.Reset(tpl->GetFunction(context).ToLocalChecked());
Nan::Set(target, Nan::New("Map").ToLocalChecked(), tpl->GetFunction(context).ToLocalChecked());
}
/**
@@ -227,6 +228,7 @@ void NodeMap::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
* map.load(fs.readFileSync('./test/fixtures/style.json', 'utf8'));
*/
void NodeMap::Load(const Nan::FunctionCallbackInfo<v8::Value>& info) {
v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
@@ -242,7 +244,7 @@ void NodeMap::Load(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (info[0]->IsObject()) {
Nan::JSON JSON;
style = *Nan::Utf8String(JSON.Stringify(info[0]->ToObject()).ToLocalChecked());
style = *Nan::Utf8String(JSON.Stringify(info[0]->ToObject(context).ToLocalChecked()).ToLocalChecked());
} else if (info[0]->IsString()) {
style = *Nan::Utf8String(info[0]);
} else {
@@ -266,7 +268,7 @@ void NodeMap::Load(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (!Nan::Get(options, Nan::New("defaultStyleCamera").ToLocalChecked()).ToLocalChecked()->IsBoolean()) {
return Nan::ThrowError("Options object 'defaultStyleCamera' property must be a boolean");
}
if (Nan::Get(options, Nan::New("cameraMutated").ToLocalChecked()).ToLocalChecked()->BooleanValue()) {
if (Nan::To<bool>(Nan::Get(options, Nan::New("cameraMutated").ToLocalChecked()).ToLocalChecked()).ToChecked()) {
nodeMap->map->jumpTo(nodeMap->map->getStyle().getDefaultCamera());
}
}
@@ -298,15 +300,15 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local<v8::Object> obj) {
NodeMap::RenderOptions options;
if (Nan::Has(obj, Nan::New("zoom").ToLocalChecked()).FromJust()) {
options.zoom = Nan::Get(obj, Nan::New("zoom").ToLocalChecked()).ToLocalChecked()->NumberValue();
options.zoom = Nan::To<double>(Nan::Get(obj, Nan::New("zoom").ToLocalChecked()).ToLocalChecked()).ToChecked();
}
if (Nan::Has(obj, Nan::New("bearing").ToLocalChecked()).FromJust()) {
options.bearing = Nan::Get(obj, Nan::New("bearing").ToLocalChecked()).ToLocalChecked()->NumberValue();
options.bearing = Nan::To<double>(Nan::Get(obj, Nan::New("bearing").ToLocalChecked()).ToLocalChecked()).ToChecked();
}
if (Nan::Has(obj, Nan::New("pitch").ToLocalChecked()).FromJust()) {
options.pitch = Nan::Get(obj, Nan::New("pitch").ToLocalChecked()).ToLocalChecked()->NumberValue();
options.pitch = Nan::To<double>(Nan::Get(obj, Nan::New("pitch").ToLocalChecked()).ToLocalChecked()).ToChecked();
}
if (Nan::Has(obj, Nan::New("light").ToLocalChecked()).FromJust()) {
@@ -320,15 +322,15 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local<v8::Object> obj) {
}
if (Nan::Has(obj, Nan::New("axonometric").ToLocalChecked()).FromJust()) {
options.axonometric = Nan::Get(obj, Nan::New("axonometric").ToLocalChecked()).ToLocalChecked()->BooleanValue();
options.axonometric = Nan::To<bool>(Nan::Get(obj, Nan::New("axonometric").ToLocalChecked()).ToLocalChecked()).ToChecked();
}
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 (skew->Length() > 0) { options.xSkew = Nan::To<double>(Nan::Get(skew, 0).ToLocalChecked()).ToChecked(); }
if (skew->Length() > 1) { options.ySkew = Nan::To<double>(Nan::Get(skew, 1).ToLocalChecked()).ToChecked(); }
}
}
@@ -336,17 +338,17 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local<v8::Object> obj) {
auto centerObj = Nan::Get(obj, Nan::New("center").ToLocalChecked()).ToLocalChecked();
if (centerObj->IsArray()) {
auto center = centerObj.As<v8::Array>();
if (center->Length() > 0) { options.longitude = Nan::Get(center, 0).ToLocalChecked()->NumberValue(); }
if (center->Length() > 1) { options.latitude = Nan::Get(center, 1).ToLocalChecked()->NumberValue(); }
if (center->Length() > 0) { options.longitude = Nan::To<double>(Nan::Get(center, 0).ToLocalChecked()).ToChecked(); }
if (center->Length() > 1) { options.latitude = Nan::To<double>(Nan::Get(center, 1).ToLocalChecked()).ToChecked(); }
}
}
if (Nan::Has(obj, Nan::New("width").ToLocalChecked()).FromJust()) {
options.size.width = Nan::Get(obj, Nan::New("width").ToLocalChecked()).ToLocalChecked()->IntegerValue();
options.size.width = Nan::To<int64_t>(Nan::Get(obj, Nan::New("width").ToLocalChecked()).ToLocalChecked()).ToChecked();
}
if (Nan::Has(obj, Nan::New("height").ToLocalChecked()).FromJust()) {
options.size.height = Nan::Get(obj, Nan::New("height").ToLocalChecked()).ToLocalChecked()->IntegerValue();
options.size.height = Nan::To<int64_t>(Nan::Get(obj, Nan::New("height").ToLocalChecked()).ToLocalChecked()).ToChecked();
}
if (Nan::Has(obj, Nan::New("classes").ToLocalChecked()).FromJust()) {
@@ -361,27 +363,27 @@ NodeMap::RenderOptions NodeMap::ParseOptions(v8::Local<v8::Object> obj) {
if (Nan::Has(obj, Nan::New("debug").ToLocalChecked()).FromJust()) {
auto debug = Nan::To<v8::Object>(Nan::Get(obj, Nan::New("debug").ToLocalChecked()).ToLocalChecked()).ToLocalChecked();
if (Nan::Has(debug, Nan::New("tileBorders").ToLocalChecked()).FromJust()) {
if (Nan::Get(debug, Nan::New("tileBorders").ToLocalChecked()).ToLocalChecked()->BooleanValue()) {
if (Nan::To<bool>(Nan::Get(debug, Nan::New("tileBorders").ToLocalChecked()).ToLocalChecked()).ToChecked()) {
options.debugOptions = options.debugOptions | mbgl::MapDebugOptions::TileBorders;
}
}
if (Nan::Has(debug, Nan::New("parseStatus").ToLocalChecked()).FromJust()) {
if (Nan::Get(debug, Nan::New("parseStatus").ToLocalChecked()).ToLocalChecked()->BooleanValue()) {
if (Nan::To<bool>(Nan::Get(debug, Nan::New("parseStatus").ToLocalChecked()).ToLocalChecked()).ToChecked()) {
options.debugOptions = options.debugOptions | mbgl::MapDebugOptions::ParseStatus;
}
}
if (Nan::Has(debug, Nan::New("timestamps").ToLocalChecked()).FromJust()) {
if (Nan::Get(debug, Nan::New("timestamps").ToLocalChecked()).ToLocalChecked()->BooleanValue()) {
if (Nan::To<bool>(Nan::Get(debug, Nan::New("timestamps").ToLocalChecked()).ToLocalChecked()).ToChecked()) {
options.debugOptions = options.debugOptions | mbgl::MapDebugOptions::Timestamps;
}
}
if (Nan::Has(debug, Nan::New("collision").ToLocalChecked()).FromJust()) {
if (Nan::Get(debug, Nan::New("collision").ToLocalChecked()).ToLocalChecked()->BooleanValue()) {
if (Nan::To<bool>(Nan::Get(debug, Nan::New("collision").ToLocalChecked()).ToLocalChecked()).ToChecked()) {
options.debugOptions = options.debugOptions | mbgl::MapDebugOptions::Collision;
}
}
if (Nan::Has(debug, Nan::New("overdraw").ToLocalChecked()).FromJust()) {
if (Nan::Get(debug, Nan::New("overdraw").ToLocalChecked()).ToLocalChecked()->BooleanValue()) {
if (Nan::To<bool>(Nan::Get(debug, Nan::New("overdraw").ToLocalChecked()).ToLocalChecked()).ToChecked()) {
options.debugOptions = mbgl::MapDebugOptions::Overdraw;
}
}
@@ -593,7 +595,7 @@ void NodeMap::release() {
uv_close(reinterpret_cast<uv_handle_t *>(async), [] (uv_handle_t *h) {
delete reinterpret_cast<uv_async_t *>(h);
});
map.reset();
frontend.reset();
}
@@ -621,7 +623,7 @@ void NodeMap::Cancel(const Nan::FunctionCallbackInfo<v8::Value>& info) {
void NodeMap::cancel() {
auto style = map->getStyle().getJSON();
// Reset map explicitly as it resets the renderer frontend
map.reset();
@@ -640,7 +642,7 @@ void NodeMap::cancel() {
map = std::make_unique<mbgl::Map>(*frontend, mapObserver,
mbgl::MapOptions().withSize(frontend->getSize())
.withPixelRatio(pixelRatio)
.withMapMode(mode)
.withMapMode(mbgl::MapMode::Static)
.withCrossSourceCollisions(crossSourceCollisions),
mbgl::ResourceOptions().withPlatformContext(reinterpret_cast<void*>(this)));
@@ -743,6 +745,8 @@ void NodeMap::AddImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
using namespace mbgl::style;
using namespace mbgl::style::conversion;
v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
@@ -776,8 +780,8 @@ void NodeMap::AddImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
return Nan::ThrowTypeError("pixelRatio parameter required");
}
uint32_t imageHeight = Nan::Get(optionObject, Nan::New("height").ToLocalChecked()).ToLocalChecked()->Uint32Value();
uint32_t imageWidth = Nan::Get(optionObject, Nan::New("width").ToLocalChecked()).ToLocalChecked()->Uint32Value();
uint32_t imageHeight = Nan::To<uint32_t>(Nan::Get(optionObject, Nan::New("height").ToLocalChecked()).ToLocalChecked()).ToChecked();
uint32_t imageWidth = Nan::To<uint32_t>(Nan::Get(optionObject, Nan::New("width").ToLocalChecked()).ToLocalChecked()).ToChecked();
if (imageWidth > 1024 || imageHeight > 1024) {
return Nan::ThrowTypeError("Max height and width is 1024");
@@ -785,12 +789,12 @@ void NodeMap::AddImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
bool sdf = false;
if (Nan::Get(optionObject, Nan::New("sdf").ToLocalChecked()).ToLocalChecked()->IsBoolean()) {
sdf = Nan::Get(optionObject, Nan::New("sdf").ToLocalChecked()).ToLocalChecked()->BooleanValue();
sdf = Nan::To<bool>(Nan::Get(optionObject, Nan::New("sdf").ToLocalChecked()).ToLocalChecked()).ToChecked();
}
float pixelRatio = Nan::Get(optionObject, Nan::New("pixelRatio").ToLocalChecked()).ToLocalChecked()->NumberValue();
auto imageBuffer = Nan::To<v8::Object>(info[1]).ToLocalChecked()->ToObject();
float pixelRatio = (float)Nan::To<double>(Nan::Get(optionObject, Nan::New("pixelRatio").ToLocalChecked()).ToLocalChecked()).ToChecked();
auto imageBuffer = Nan::To<v8::Object>(info[1]).ToLocalChecked()->ToObject(context).ToLocalChecked();
char * imageDataBuffer = node::Buffer::Data(imageBuffer);
size_t imageLength = node::Buffer::Length(imageBuffer);
@@ -800,7 +804,7 @@ void NodeMap::AddImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(imageLength);
std::copy(imageDataBuffer, imageDataBuffer + imageLength, data.get());
mbgl::UnassociatedImage cImage({ imageWidth, imageHeight}, std::move(data));
mbgl::PremultipliedImage cPremultipliedImage = mbgl::util::premultiply(std::move(cImage));
nodeMap->map->getStyle().addImage(std::make_unique<mbgl::style::Image>(*Nan::Utf8String(info[0]), std::move(cPremultipliedImage), pixelRatio, sdf));
@@ -823,32 +827,32 @@ void NodeMap::RemoveImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
nodeMap->map->getStyle().removeImage(*Nan::Utf8String(info[0]));
}
void NodeMap::SetLayerZoomRange(const Nan::FunctionCallbackInfo<v8::Value>& info) {
using namespace mbgl::style;
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
if (info.Length() != 3) {
return Nan::ThrowTypeError("Three arguments required");
}
if (!info[0]->IsString()) {
return Nan::ThrowTypeError("First argument must be a string");
}
if (!info[1]->IsNumber() || !info[2]->IsNumber()) {
return Nan::ThrowTypeError("Second and third arguments must be numbers");
}
mbgl::style::Layer* layer = nodeMap->map->getStyle().getLayer(*Nan::Utf8String(info[0]));
if (!layer) {
return Nan::ThrowTypeError("layer not found");
}
layer->setMinZoom(info[1]->NumberValue());
layer->setMaxZoom(info[2]->NumberValue());
layer->setMinZoom(Nan::To<double>(info[1]).ToChecked());
layer->setMaxZoom(Nan::To<double>(info[2]).ToChecked());
}
void NodeMap::SetLayerProperty(const Nan::FunctionCallbackInfo<v8::Value>& info) {
@@ -929,8 +933,8 @@ void NodeMap::SetCenter(const Nan::FunctionCallbackInfo<v8::Value>& info) {
auto center = info[0].As<v8::Array>();
double latitude = 0;
double longitude = 0;
if (center->Length() > 0) { longitude = Nan::Get(center, 0).ToLocalChecked()->NumberValue(); }
if (center->Length() > 1) { latitude = Nan::Get(center, 1).ToLocalChecked()->NumberValue(); }
if (center->Length() > 0) { longitude = Nan::To<double>(Nan::Get(center, 0).ToLocalChecked()).ToChecked(); }
if (center->Length() > 1) { latitude = Nan::To<double>(Nan::Get(center, 1).ToLocalChecked()).ToChecked(); }
try {
nodeMap->map->jumpTo(mbgl::CameraOptions().withCenter(mbgl::LatLng { latitude, longitude }));
@@ -950,7 +954,7 @@ void NodeMap::SetZoom(const Nan::FunctionCallbackInfo<v8::Value>& info) {
}
try {
nodeMap->map->jumpTo(mbgl::CameraOptions().withZoom(info[0]->NumberValue()));
nodeMap->map->jumpTo(mbgl::CameraOptions().withZoom(Nan::To<double>(info[0]).ToChecked()));
} catch (const std::exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -967,7 +971,7 @@ void NodeMap::SetBearing(const Nan::FunctionCallbackInfo<v8::Value>& info) {
}
try {
nodeMap->map->jumpTo(mbgl::CameraOptions().withBearing(info[0]->NumberValue()));
nodeMap->map->jumpTo(mbgl::CameraOptions().withBearing(Nan::To<double>(info[0]).ToChecked()));
} catch (const std::exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -984,7 +988,7 @@ void NodeMap::SetPitch(const Nan::FunctionCallbackInfo<v8::Value>& info) {
}
try {
nodeMap->map->jumpTo(mbgl::CameraOptions().withPitch(info[0]->NumberValue()));
nodeMap->map->jumpTo(mbgl::CameraOptions().withPitch(Nan::To<double>(info[0]).ToChecked()));
} catch (const std::exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -1027,7 +1031,7 @@ void NodeMap::SetAxonometric(const Nan::FunctionCallbackInfo<v8::Value>& info) {
try {
nodeMap->map->setProjectionMode(mbgl::ProjectionMode()
.withAxonometric(info[0]->BooleanValue()));
.withAxonometric(Nan::To<bool>(info[0]).ToChecked()));
} catch (const std::exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -1045,7 +1049,7 @@ void NodeMap::SetXSkew(const Nan::FunctionCallbackInfo<v8::Value>& info) {
try {
nodeMap->map->setProjectionMode(mbgl::ProjectionMode()
.withXSkew(info[0]->NumberValue()));
.withXSkew(Nan::To<double>(info[0]).ToChecked()));
} catch (const std::exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -1063,7 +1067,7 @@ void NodeMap::SetYSkew(const Nan::FunctionCallbackInfo<v8::Value>& info) {
try {
nodeMap->map->setProjectionMode(mbgl::ProjectionMode()
.withYSkew(info[0]->NumberValue()));
.withYSkew(Nan::To<double>(info[0]).ToChecked()));
} catch (const std::exception &ex) {
return Nan::ThrowError(ex.what());
}
@@ -1324,9 +1328,9 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
if (!info[1]->IsObject()) {
return Nan::ThrowTypeError("options argument must be an object");
}
auto options = Nan::To<v8::Object>(info[1]).ToLocalChecked();
//Check if layers is set. If provided, it must be an array of strings
if (Nan::Has(options, Nan::New("layers").ToLocalChecked()).FromJust()) {
auto layersOption = Nan::Get(options, Nan::New("layers").ToLocalChecked()).ToLocalChecked();
@@ -1340,7 +1344,7 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
}
queryOptions.layerIDs = layersVec;
}
//Check if filter is provided. If set it must be a valid Filter object
if (Nan::Has(options, Nan::New("filter").ToLocalChecked()).FromJust()) {
auto filterOption = Nan::Get(options, Nan::New("filter").ToLocalChecked()).ToLocalChecked();
@@ -1363,24 +1367,24 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
optional = nodeMap->frontend->getRenderer()->queryRenderedFeatures(mbgl::ScreenBox {
{
Nan::Get(pos0, 0).ToLocalChecked()->NumberValue(),
Nan::Get(pos0, 1).ToLocalChecked()->NumberValue()
Nan::To<double>(Nan::Get(pos0, 0).ToLocalChecked()).ToChecked(),
Nan::To<double>(Nan::Get(pos0, 1).ToLocalChecked()).ToChecked()
}, {
Nan::Get(pos1, 0).ToLocalChecked()->NumberValue(),
Nan::Get(pos1, 1).ToLocalChecked()->NumberValue()
Nan::To<double>(Nan::Get(pos1, 0).ToLocalChecked()).ToChecked(),
Nan::To<double>(Nan::Get(pos1, 1).ToLocalChecked()).ToChecked()
}
}, queryOptions);
} else {
optional = nodeMap->frontend->getRenderer()->queryRenderedFeatures(mbgl::ScreenCoordinate {
Nan::Get(posOrBox, 0).ToLocalChecked()->NumberValue(),
Nan::Get(posOrBox, 1).ToLocalChecked()->NumberValue()
Nan::To<double>(Nan::Get(posOrBox, 0).ToLocalChecked()).ToChecked(),
Nan::To<double>(Nan::Get(posOrBox, 1).ToLocalChecked()).ToChecked()
}, queryOptions);
}
auto array = Nan::New<v8::Array>();
for (std::size_t i = 0; i < optional.size(); i++) {
array->Set(i, toJS(optional[i]));
Nan::Set(array, i, toJS(optional[i]));
}
info.GetReturnValue().Set(array);
} catch (const std::exception &ex) {
@@ -1392,15 +1396,13 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
: pixelRatio([&] {
Nan::HandleScope scope;
return Nan::Has(options, Nan::New("ratio").ToLocalChecked()).FromJust()
? Nan::Get(options, Nan::New("ratio").ToLocalChecked())
.ToLocalChecked()
->NumberValue()
? Nan::To<double>(Nan::Get(options, Nan::New("ratio").ToLocalChecked())
.ToLocalChecked()).ToChecked()
: 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") {
if (std::string(*v8::String::Utf8Value(v8::Isolate::GetCurrent(), Nan::Get(options, Nan::New("mode").ToLocalChecked()).ToLocalChecked())) == "tile") {
return mbgl::MapMode::Tile;
} else {
return mbgl::MapMode::Static;
@@ -1409,9 +1411,8 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
, crossSourceCollisions([&] {
Nan::HandleScope scope;
return Nan::Has(options, Nan::New("crossSourceCollisions").ToLocalChecked()).FromJust()
? Nan::Get(options, Nan::New("crossSourceCollisions").ToLocalChecked())
.ToLocalChecked()
->BooleanValue()
? Nan::To<bool>(Nan::Get(options, Nan::New("crossSourceCollisions").ToLocalChecked())
.ToLocalChecked()).ToChecked()
: true;
}())
, mapObserver(NodeMapObserver())
@@ -1419,7 +1420,7 @@ NodeMap::NodeMap(v8::Local<v8::Object> options)
, map(std::make_unique<mbgl::Map>(*frontend, mapObserver,
mbgl::MapOptions().withSize(frontend->getSize())
.withPixelRatio(pixelRatio)
.withMapMode(mode)
.withMapMode(mbgl::MapMode::Static)
.withCrossSourceCollisions(crossSourceCollisions),
mbgl::ResourceOptions().withPlatformContext(reinterpret_cast<void*>(this))))
, async(new uv_async_t) {
@@ -1468,4 +1469,12 @@ bool NodeFileSource::canRequest(const mbgl::Resource&) const {
return true;
}
void NodeFileSource::setResourceOptions(mbgl::ResourceOptions options) {
this->_resourceOptions = std::move(options);
}
mbgl::ResourceOptions NodeFileSource::getResourceOptions() {
return this->_resourceOptions.clone();
}
} // namespace node_mbgl

View File

@@ -2,6 +2,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/util/async_request.hpp>
#include <mbgl/util/image.hpp>
@@ -100,7 +101,10 @@ struct NodeFileSource : public mbgl::FileSource {
~NodeFileSource() override = default;
std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback) final;
bool canRequest(const mbgl::Resource&) const override;
void setResourceOptions(mbgl::ResourceOptions) override;
mbgl::ResourceOptions getResourceOptions() override;
NodeMap* nodeMap;
mbgl::ResourceOptions _resourceOptions;
};
} // namespace node_mbgl

View File

@@ -7,6 +7,7 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/gfx/backend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include "node_map.hpp"
#include "node_logging.hpp"
@@ -33,7 +34,7 @@ void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module)
Nan::SetMethod(target, "setBackendType", SetBackendType);
node_mbgl::NodeMap::Init(target);
node_mbgl::NodeRequest::Init();
node_mbgl::NodeRequest::Init(target);
node_mbgl::NodeExpression::Init(target);
// Exports Resource constants.

View File

@@ -26,7 +26,8 @@ NodeRequest::~NodeRequest() {
Nan::Persistent<v8::Function> NodeRequest::constructor;
void NodeRequest::Init() {
void NodeRequest::Init(v8::Local<v8::Object> target) {
v8::Local<v8::Context> context = target->CreationContext();
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->InstanceTemplate()->SetInternalFieldCount(1);
@@ -34,7 +35,7 @@ void NodeRequest::Init() {
Nan::SetPrototypeMethod(tpl, "respond", HandleCallback);
constructor.Reset(tpl->GetFunction());
constructor.Reset(tpl->GetFunction(context).ToLocalChecked());
}
void NodeRequest::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
@@ -49,7 +50,12 @@ void NodeRequest::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
Nan::Set(info.This(), Nan::New("url").ToLocalChecked(), info[3]);
Nan::Set(info.This(), Nan::New("kind").ToLocalChecked(), info[4]);
v8::Local<v8::Value> argv[] = { info.This() };
request->asyncResource->runInAsyncScope(Nan::To<v8::Object>(target->handle()->GetInternalField(1)).ToLocalChecked(), "request", 1, argv);
request->asyncResource->runInAsyncScope(
Nan::To<v8::Object>(target->handle()->GetInternalField(1)).ToLocalChecked(),
"request",
1,
argv
);
info.GetReturnValue().Set(info.This());
}

View File

@@ -29,7 +29,7 @@ public:
static Nan::Persistent<v8::Function> constructor;
static void Init();
static void Init(v8::Local<v8::Object>);
static void New(const Nan::FunctionCallbackInfo<v8::Value>&);
static void HandleCallback(const Nan::FunctionCallbackInfo<v8::Value>&);

View File

@@ -4,7 +4,7 @@ var mockfs = require('../mockfs');
var mbgl = require('../../index');
var test = require('tape');
[ 'sprite_png', 'sprite_json', 'source_vector', 'glyph' ].forEach(function (resource) {
[ 'sprite_png', 'sprite_json', 'source_vector' ].forEach(function (resource) {
test(`render reports an error when the request function responds with an error (${resource})`, function(t) {
var map = new mbgl.Map({
request: function(req, callback) {
@@ -144,7 +144,12 @@ test(`render does not report an error from rendering a previous style`, function
var map = new mbgl.Map({
request: function(req, callback) {
var data = mockfs.dataForRequest(req);
if (mockfs.source_vector === data) {
if (
mockfs.source_vector === data &&
// By default tiles load sources/v3 as well, which is vector tile,
// messing things up.
req.url !== 'maptiler://sources/v3'
) {
callback(new Error('message'));
} else {
callback(null, { data: data });

View File

@@ -20,19 +20,22 @@ var tile_vector = readFixture('vector.tile');
function dataForRequest(req) {
if (req.url === null) {
return null;
} else if (req.url.indexOf('sprite') > -1 && req.url.endsWith('json')) {
} else if (req.url.includes('sprite') && req.url.endsWith('.json')) {
return sprite_json;
} else if (req.url.indexOf('sprite') > -1 && req.url.endsWith('png')) {
} else if (req.url.includes('sprite') && req.url.endsWith('.png')) {
return sprite_png;
} else if (req.url.indexOf('fonts') > -1 && req.url.endsWith('pbf')) {
} else if (req.url.includes('fonts/') && req.url.endsWith('.pbf')) {
return glyph;
} else if (req.url.endsWith('mapbox.satellite')) {
} else if (req.url.includes('sources/satellite')) {
return source_raster;
} else if (req.url.indexOf('satellite') > -1 && (req.url.endsWith('png') || req.url.endsWith('webp'))) {
} else if (req.url.includes('tiles/satellite') && (req.url.endsWith('png') || req.url.endsWith('webp') || req.url.endsWith('jpg'))) {
return tile_raster;
} else if (req.url.endsWith('mapbox.mapbox-streets-v7')) {
} else if (
req.url === 'https://api.maptiler.com/tiles/v3/tiles.json?key=uwvyvzaF2P7UWbyOEvjU' ||
req.url === 'maptiler://sources/v3'
) {
return source_vector;
} else if (req.url.indexOf('streets') > -1 && req.url.endsWith('pbf')) {
} else if (req.url.includes('tiles/tiles') && req.url.endsWith('pbf')) {
return tile_vector;
} else {
return null;

View File

@@ -23,7 +23,7 @@ void Mailbox::open(Scheduler& scheduler_) {
if (closed) {
return;
}
if (!queue.empty()) {
auto guard = weakScheduler.lock();
if (weakScheduler) weakScheduler->schedule(makeClosure(shared_from_this()));

View File

@@ -179,7 +179,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
// This guarantees that we have at least one function per tile called.
// When only rendering layers via the stylesheet, it's possible that we don't
// ever visit a tile during rendering.
for (const RenderItem& renderItem : sourceRenderItems) {
for (const RenderItem& renderItem : sourceRenderItems) {
renderItem.render(parameters);
}
}

View File

@@ -27,15 +27,16 @@ void Tile::setTriedCache() {
void Tile::dumpDebugLogs() const {
std::string kindString;
switch (kind) {
case Kind::Geometry: kindString = "Geometry"; break;
case Kind::Raster: kindString = "Raster"; break;
case Kind::RasterDEM: kindString = "RasterDEM"; break;
default: kindString = "Unknown"; break;
case Kind::Geometry: kindString = "Geometry"; break;
case Kind::Raster: kindString = "Raster"; break;
case Kind::RasterDEM: kindString = "RasterDEM"; break;
default: kindString = "Unknown"; break;
}
Log::Info(Event::General, "Tile::Kind: %s", kindString.c_str());
Log::Info(Event::General, "Tile::id: %s", util::toString(id).c_str());
Log::Info(Event::General, "Tile::renderable: %s", isRenderable() ? "yes" : "no");
Log::Info(Event::General, "Tile::complete: %s", isComplete() ? "yes" : "no");
Log::Info(Event::General, "Tile::loaded: %s", isLoaded() ? "yes" : "no");
}
void Tile::queryRenderedFeatures(std::unordered_map<std::string, std::vector<Feature>>&, const GeometryCoordinates&,