[Pkg-javascript-commits] [node-mapnik] 03/07: Add patch with changes from upstream git repository.

Bas Couwenberg sebastic at debian.org
Thu Nov 30 15:02:42 UTC 2017


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository node-mapnik.

commit c653a162238403e9a004efec5d832726a92dffd5
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Thu Nov 30 13:37:50 2017 +0100

    Add patch with changes from upstream git repository.
---
 debian/changelog                               |    1 +
 debian/patches/mapnik-config.patch             |   21 -
 debian/patches/no-mason.patch                  |    2 +-
 debian/patches/nodejs.patch                    |    2 +-
 debian/patches/postinstall.patch               |   70 -
 debian/patches/series                          |    3 +-
 debian/patches/upstream-git.patch              | 2209 ++++++++++++++++++++++++
 debian/patches/use-packaged-dependencies.patch |    2 +-
 8 files changed, 2214 insertions(+), 96 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 9eab81b..ccb1f81 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,6 +3,7 @@ node-mapnik (3.6.2+dfsg-2) UNRELEASED; urgency=medium
   * Team upload.
   * Bump Standards-Version to 4.1.1, no changes.
   * Rebuild with Mapnik 3.0.17.
+  * Add patch with changes from upstream git repository.
 
  -- Bas Couwenberg <sebastic at debian.org>  Thu, 16 Nov 2017 20:52:36 +0100
 
diff --git a/debian/patches/mapnik-config.patch b/debian/patches/mapnik-config.patch
deleted file mode 100644
index 9e31030..0000000
--- a/debian/patches/mapnik-config.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Description: Use system mapnik-config.
-Author: Bas Couwenberg <sebastic at debian.org>
-Forwarded: not-needed
-
---- a/gen_settings.py
-+++ b/gen_settings.py
-@@ -28,12 +28,12 @@ if __name__ == '__main__':
-     if ip:
-         settings_dict['input_plugins'] = ip
-     else:
--        settings_dict['input_plugins'] = '\'%s\'' % os.popen("./mason_packages/.link/bin/mapnik-config --input-plugins").readline().strip()
-+        settings_dict['input_plugins'] = '\'%s\'' % os.popen("/usr/bin/mapnik-config --input-plugins").readline().strip()
-     
-     mf = os.environ.get('MAPNIK_FONTS')
-     if mf:
-         settings_dict['fonts'] = mf
-     else:
--        settings_dict['fonts'] = '\'%s\'' % os.popen("./mason_packages/.link/bin/mapnik-config --fonts").readline().strip()
-+        settings_dict['fonts'] = '\'%s\'' % os.popen("/usr/bin/mapnik-config --fonts").readline().strip()
- 
-     write_mapnik_settings(**settings_dict)
diff --git a/debian/patches/no-mason.patch b/debian/patches/no-mason.patch
index 1b02895..79be4e0 100644
--- a/debian/patches/no-mason.patch
+++ b/debian/patches/no-mason.patch
@@ -4,7 +4,7 @@ Forwarded: not-needed
 
 --- a/binding.gyp
 +++ b/binding.gyp
-@@ -54,9 +54,9 @@
+@@ -30,9 +30,9 @@
          4267
        ],
        'include_dirs': [
diff --git a/debian/patches/nodejs.patch b/debian/patches/nodejs.patch
index 90ed6b3..058186f 100644
--- a/debian/patches/nodejs.patch
+++ b/debian/patches/nodejs.patch
@@ -35,7 +35,7 @@ Author: Bas Couwenberg <sebastic at debian.org>
  
 --- a/binding.gyp
 +++ b/binding.gyp
-@@ -58,13 +58,13 @@
+@@ -34,13 +34,13 @@
          './mason_packages/.link/include/freetype2',
          './mason_packages/.link/include/cairo',
          './src',
diff --git a/debian/patches/postinstall.patch b/debian/patches/postinstall.patch
deleted file mode 100644
index 02a3d11..0000000
--- a/debian/patches/postinstall.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-Description: Use paths for packaged dependencies.
-Author: Bas Couwenberg <sebastic at debian.org>
-Forwarded: not-needed
-
---- a/scripts/postinstall.sh
-+++ b/scripts/postinstall.sh
-@@ -3,59 +3,14 @@ set -eu
- set -o pipefail
- 
- MODULE_PATH=./lib/binding
--MAPNIK_SDK=./mason_packages/.link
--
--mkdir -p ${MODULE_PATH}/bin/
--
--# the below switch is used since on osx the default cp
--# resolves symlinks automatically with `cp -r`
--# whereas on linux we need to pass `cp -rL`. But the latter
--# command is not supported on OS X. We could upgrade coreutils
--# but ideally we don't depend on more dependencies
--if [[ $(uname -s) == 'Darwin' ]]; then
--    cp ${MAPNIK_SDK}/bin/mapnik-index ${MODULE_PATH}/bin/
--    # copy shapeindex
--    cp ${MAPNIK_SDK}/bin/shapeindex ${MODULE_PATH}/bin/
--    # copy lib
--    mkdir -p ${MODULE_PATH}/lib/
--    cp ${MAPNIK_SDK}/lib/libmapnik.* ${MODULE_PATH}/lib/
--    # copy plugins
--    cp -r ${MAPNIK_SDK}/lib/mapnik ${MODULE_PATH}/lib/
--    # copy share data
--    mkdir -p ${MODULE_PATH}/share/gdal
--    cp -L ${MAPNIK_SDK}/share/gdal/*.* ${MODULE_PATH}/share/gdal/
--    cp -r ${MAPNIK_SDK}/share/proj ${MODULE_PATH}/share/
--    mkdir -p ${MODULE_PATH}/share/icu
--    cp -L ${MAPNIK_SDK}/share/icu/*/*dat ${MODULE_PATH}/share/icu/
--else
--    cp -L ${MAPNIK_SDK}/bin/mapnik-index ${MODULE_PATH}/bin/
--    # copy shapeindex
--    cp -L ${MAPNIK_SDK}/bin/shapeindex ${MODULE_PATH}/bin/
--    # copy lib
--    mkdir -p ${MODULE_PATH}/lib/
--    cp -L ${MAPNIK_SDK}/lib/libmapnik.* ${MODULE_PATH}/lib/
--    # copy plugins
--    cp -rL ${MAPNIK_SDK}/lib/mapnik ${MODULE_PATH}/lib/
--    # copy share data
--    mkdir -p ${MODULE_PATH}/share/gdal
--    cp -rL ${MAPNIK_SDK}/share/gdal/*.* ${MODULE_PATH}/share/gdal/
--    cp -rL ${MAPNIK_SDK}/share/proj ${MODULE_PATH}/share/
--    mkdir -p ${MODULE_PATH}/share/icu
--    cp -rL ${MAPNIK_SDK}/share/icu/*/*dat ${MODULE_PATH}/share/icu/
--fi
- 
- # generate new settings
- echo "
- var path = require('path');
- module.exports.paths = {
--    'fonts': path.join(__dirname, 'lib/mapnik/fonts'),
--    'input_plugins': path.join(__dirname, 'lib/mapnik/input'),
--    'mapnik_index': path.join(__dirname, 'bin/mapnik-index'),
--    'shape_index': path.join(__dirname, 'bin/shapeindex')
--};
--module.exports.env = {
--    'ICU_DATA': path.join(__dirname, 'share/icu'),
--    'GDAL_DATA': path.join(__dirname, 'share/gdal'),
--    'PROJ_LIB': path.join(__dirname, 'share/proj')
-+    'fonts': '/usr/share/fonts',
-+    'input_plugins': '/usr/lib/mapnik/3.0/input',
-+    'mapnik_index': '/usr/bin/mapnik-index',
-+    'shape_index': '/usr/bin/shapeindex'
- };
- " > ${MODULE_PATH}/mapnik_settings.js
diff --git a/debian/patches/series b/debian/patches/series
index 6de602c..25044c2 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,6 +1,5 @@
+upstream-git.patch
 test_disable_raster_layer.patch
 nodejs.patch
 use-packaged-dependencies.patch
-mapnik-config.patch
 no-mason.patch
-postinstall.patch
diff --git a/debian/patches/upstream-git.patch b/debian/patches/upstream-git.patch
new file mode 100644
index 0000000..15ecaf2
--- /dev/null
+++ b/debian/patches/upstream-git.patch
@@ -0,0 +1,2209 @@
+Description: Various changes from upstream git repository.
+Author: Various
+Origin: https://github.com/mapnik/node-mapnik/tree/v3.0.x
+
+--- a/.npmignore
++++ b/.npmignore
+@@ -11,7 +11,6 @@ test
+ benchmark
+ configure
+ Makefile
+-scripts
+ .travis.yml
+ appveyor.yml
+ examples
+--- a/.travis.yml
++++ b/.travis.yml
+@@ -73,6 +73,10 @@ matrix:
+     - os: linux
+       env: BUILDTYPE=release
+       node_js: 8
++    # linux publishable node v9
++    - os: linux
++      env: BUILDTYPE=release
++      node_js: 8
+     # osx publishable node v0.10
+     - os: osx
+       osx_image: xcode8.3
+@@ -83,11 +87,21 @@ matrix:
+       osx_image: xcode8.3
+       env: BUILDTYPE=release
+       node_js: 4
++    # osx publishable node v4/debug
++    - os: osx
++      osx_image: xcode8.3
++      env: BUILDTYPE=debug
++      node_js: 4
+     # osx publishable node v6
+     - os: osx
+       osx_image: xcode8.3
+       env: BUILDTYPE=release
+       node_js: 6
++    # osx publishable node v6/debug
++    - os: osx
++      osx_image: xcode8.3
++      env: BUILDTYPE=debug
++      node_js: 6
+     # osx publishable node v7
+     - os: osx
+       osx_image: xcode8.2
+@@ -98,11 +112,39 @@ matrix:
+       osx_image: xcode8.2
+       env: BUILDTYPE=release
+       node_js: 8
+-    # Sanitizer build node v4/Debug
++    # osx publishable node v9
++    - os: osx
++      osx_image: xcode8.2
++      env: BUILDTYPE=release
++      node_js: 9
++    # Sanitizer build linux node v4/Debug
+     - os: linux
+       env: BUILDTYPE=debug TOOLSET=-asan
+       node_js: 4
+       # Overrides `install` to set up custom asan flags
++      install:
++        - ./scripts/setup.sh --config local.env
++        # put mason and clang++ on PATH
++        - source local.env
++        # Note: to build without stopping on errors remove the -fno-sanitize-recover=all flag
++        # You might want to do this if there are multiple errors and you want to see them all before fixing
++        - export CXXFLAGS="${MASON_SANITIZE_CXXFLAGS} -fno-sanitize-recover=all"
++        - export LDFLAGS="${MASON_SANITIZE_LDFLAGS}"
++        - make ${BUILDTYPE}
++      # Overrides `script` to disable asan LD_PRELOAD before publishing
++      before_script:
++        - export LD_PRELOAD=${MASON_LLVM_RT_PRELOAD}
++        # TODO: re-enable detect_leaks=0 once we can build and test against an asan sanitized libc++
++        - export ASAN_OPTIONS=fast_unwind_on_malloc=0:detect_leaks=0:${ASAN_OPTIONS}
++        - npm test
++        - unset LD_PRELOAD
++        # after successful tests, publish binaries if specified in commit message
++        - ./scripts/publish.sh --toolset=${TOOLSET:-} --debug=$([ "${BUILDTYPE}" == 'debug' ] && echo "true" || echo "false")
++    # Sanitizer build osx node v4/Debug
++    - os: osx
++      env: BUILDTYPE=debug TOOLSET=-asan
++      node_js: 4
++      # Overrides `install` to set up custom asan flags
+       install:
+         - ./scripts/setup.sh --config local.env
+         # put mason and clang++ on PATH
+--- a/CHANGELOG.md
++++ b/CHANGELOG.md
+@@ -20,6 +20,7 @@ Due to changes in the mapnik core versio
+ - Fixed tests around zlib compression and decompression when comparing to node's implementation
+ - Fixes rare situation of seg faults during mapnik-vector-tile image processing.
+ - Corrects the resolution of images in mapnik-vector-tile when using parameters from postgis plugin.
++- Updated to use `font_engine` `instance()` method explicitely, reflecting on changes brought by [3688](https://github.com/mapnik/mapnik/pull/3688)
+ 
+ ## 3.6.0
+ 
+@@ -31,6 +32,7 @@ The second largest change is the update
+ 
+ The third most important set of changes were to node-mapnik directly: for performance many functions now can premultiply as part of another async operation (to avoid needing an additional threadpool access for async premultiply - this matters under load when the threadpool may be full since access can block). And many functions that allocate images now protect from extreme allocation that could hang a machine and result in OOM. Additionally the address sanitizer caught several cases of  [...]
+ 
++- No longer installing node-pre-gyp in `preinstall` target, now bundling again as a bundledDep (https://github.com/mapbox/node-pre-gyp/issues/260).
+ - Added support for node v7
+ - Updated to 1.3.0 of Mapnik Vector Tile (https://github.com/mapbox/mapnik-vector-tile/blob/master/CHANGELOG.md#130)
+ - Removed Angus Clipper and replaced with Wagyu v0.4.2 (https://github.com/mapbox/wagyu)
+--- a/Makefile
++++ b/Makefile
+@@ -2,25 +2,40 @@ MODULE_NAME := $(shell node -e "console.
+ 
+ default: release
+ 
++ifneq (,$(findstring clang,$(CXX)))
++    PROFILING_FLAG += -gline-tables-only
++else
++    PROFILING_FLAG += -g
++endif
++
+ deps/geometry/include/mapbox/geometry.hpp:
+ 	git submodule update --init
+ 
+-mason_packages/.link/bin/mapnik-config: deps/geometry/include/mapbox/geometry.hpp
++node_modules:
++	npm install --ignore-scripts --clang
++
++mason_packages/.link/bin/mapnik-config:
+ 	./install_mason.sh
+ 
+-node_modules: mason_packages/.link/bin/mapnik-config
+-	# install deps but for now ignore our own install script
+-	# so that we can run it directly in either debug or release
+-	npm install --ignore-scripts --clang
++pre_build_check:
++	@node -e "console.log('\033[94mNOTICE: to build from source you need mapnik >=',require('./package.json').mapnik_version,'\033[0m');"
++	@echo "Looking for mapnik-config on your PATH..."
++	mapnik-config -v
+ 
+-release: node_modules
+-	PATH="./mason_packages/.link/bin/:${PATH}" && V=1 ./node_modules/.bin/node-pre-gyp configure build --loglevel=error --clang
++release_base: pre_build_check deps/geometry/include/mapbox/geometry.hpp node_modules
++	V=1 CXXFLAGS="-fno-omit-frame-pointer $(PROFILING_FLAG)" ./node_modules/.bin/node-pre-gyp configure build --loglevel=error --clang
+ 	@echo "run 'make clean' for full rebuild"
+ 
+-debug: node_modules
+-	PATH="./mason_packages/.link/bin/:${PATH}" && V=1 ./node_modules/.bin/node-pre-gyp configure build --loglevel=error --debug --clang
++debug_base: pre_build_check deps/geometry/include/mapbox/geometry.hpp node_modules
++	V=1 ./node_modules/.bin/node-pre-gyp configure build --loglevel=error --debug --clang
+ 	@echo "run 'make clean' for full rebuild"
+ 
++release: mason_packages/.link/bin/mapnik-config
++	CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" PATH="./mason_packages/.link/bin/:${PATH}" $(MAKE) release_base
++
++debug: mason_packages/.link/bin/mapnik-config
++	CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" PATH="./mason_packages/.link/bin/:${PATH}" $(MAKE) debug_base
++
+ coverage:
+ 	./scripts/coverage.sh
+ 
+@@ -50,6 +65,8 @@ docs:
+ test:
+ 	npm test
+ 
++check: test
++
+ testpack:
+ 	rm -f ./*tgz
+ 	npm pack
+--- a/README.md
++++ b/README.md
+@@ -71,9 +71,9 @@ For more sample code see [the tests](./t
+ 
+ OS|Node.js|C++ minimum requirements|OS versions
+ ---|---|---|---
+-Mac|v0.10.x, v4, v5, v6|C++11|Mac OS X > 10.10
+-Linux|v0.10.x, v4, v5, v6|C++11|Ubuntu Linux > 16.04 or other Linux distributions with g++ >= 5 toolchain (>= GLIBCXX_3.4.21 from libstdc++)
+-Windows|v0.10.x, v4, v5|C++11|See the [Windows requirements](https://github.com/mapnik/node-mapnik#windows-specific) section
++Mac|v0.10.x, v4, v6, v8|C++11|Mac OS X > 10.10
++Linux|v0.10.x, v4, v6, v8|C++11|Ubuntu Linux > 16.04 or other Linux distributions with g++ >= 5 toolchain (>= GLIBCXX_3.4.21 from libstdc++)
++Windows|v0.10.x, v4, v6, v8|C++11|See the [Windows requirements](https://github.com/mapnik/node-mapnik#windows-specific) section
+ 
+ An installation error like below indicates your system does not have a modern enough libstdc++/gcc-base toolchain:
+ 
+@@ -115,7 +115,7 @@ Note: This will install the latest node-
+ 
+ By default, binaries are provided for:
+ 
+- - 64 bit OS X 10.9, 64 bit Linux (>= Ubuntu Trusty), and 64/32 bit Windows
++ - 64 bit OS X >= 10.10, 64 bit Linux (>= Ubuntu Trusty), and 64/32 bit Windows
+  - several node versions:
+    - [versions forLinux/Mac](<https://github.com/mapnik/node-mapnik/blob/master/.travis.yml#L19-L47>)
+    - [versions for Windows](<https://github.com/mapnik/node-mapnik/blob/master/appveyor.yml#L9-L32>)
+@@ -142,17 +142,39 @@ The **1.x** series require the Visual C+
+ 
+ ## Source Build
+ 
+-To build from source you need:
++There are two ways to build from source. These work on both OS X and Linux:
+ 
+- - Mapnik >= v3.0.10
++ - A) Against a binary package from Mapnik from [mason](https://github.com/mapbox/mason)
++ - B) Against an existing version of Mapnik on your system
+ 
+-Install Mapnik using the instructions at: https://github.com/mapnik/mapnik/wiki/Mapnik-Installation
++Using `A)` is recommended. You do not need to have Mapnik installed already, so this is the easiest and most predictable approach. When you use the route a binary package of Mapnik is download dynamically from [mason](https://github.com/mapbox/mason).
+ 
+-Confirm that the `mapnik-config` program is available and on your `${PATH}`.
++You can invoke this method simply by running:
++
++  make release
++
++Or, for debug builds:
++
++  make debug
++
++If you want to do a full rebuild do:
++
++  make distclean
++
++And then re-run the build:
++
++  make release
++
++Using `B)` is also possible, if you would like to build node-mapnik against an external, already installed Mapnik version.
++
++In this case you need to have a Mapnik version installed that is at least as recent as the `mapnik_version` property in the [`package.json`](./package.json) for the branch of node-mapnik you want to build.
++
++And you need to have the `mapnik-config` program is available and on your `${PATH}`.
+ 
+ Then run (within the cloned `node-mapnik` directory:
+ 
+-    npm install --build-from-source
++    make release_base
++
+ 
+ ### Windows specific
+ 
+@@ -173,4 +195,4 @@ To run the tests do:
+ 
+ ## License
+ 
+-  BSD, see LICENSE.txt
++BSD, see LICENSE.txt
+--- a/binding.gyp
++++ b/binding.gyp
+@@ -2,31 +2,7 @@
+   'includes': [ 'common.gypi' ],
+   'targets': [
+     {
+-      'target_name': 'make_vector_tile',
+-      'hard_dependency': 1,
+-      'type': 'none',
+-      'actions': [
+-        {
+-          'action_name': 'generate_setting',
+-          'inputs': [
+-            'gen_settings.py'
+-          ],
+-          'outputs': [
+-            '<(SHARED_INTERMEDIATE_DIR)/mapnik_settings.js'
+-          ],
+-          'action': ['python', 'gen_settings.py', '<(SHARED_INTERMEDIATE_DIR)/mapnik_settings.js']
+-        }
+-      ],
+-      'copies': [
+-        {
+-          'files': [ '<(SHARED_INTERMEDIATE_DIR)/mapnik_settings.js' ],
+-          'destination': '<(module_path)'
+-        }
+-      ]
+-    },
+-    {
+       'target_name': '<(module_name)',
+-      'dependencies': [ 'make_vector_tile' ],
+       'product_dir': '<(module_path)',
+       'sources': [
+         "src/mapnik_logger.cpp",
+@@ -97,7 +73,6 @@
+             'cflags_cc!': ['-fno-rtti', '-fno-exceptions'],
+             'cflags_cc' : [
+               '<!@(mapnik-config --cflags)',
+-              '-D_GLIBCXX_USE_CXX11_ABI=0'
+             ],
+             'libraries':[
+               '<!@(mapnik-config --libs)',
+--- a/gen_settings.py
++++ /dev/null
+@@ -1,39 +0,0 @@
+-import os
+-import sys
+-
+-settings = os.path.abspath(sys.argv[1])
+-
+-# this goes into a mapnik_settings.js file beside the C++ _mapnik.node
+-settings_template = """
+-module.exports.paths = {
+-    'fonts': %s,
+-    'input_plugins': %s
+-};
+-"""
+-
+-def write_mapnik_settings(fonts='undefined',input_plugins='undefined'):
+-    global settings_template
+-    if '__dirname' in fonts or '__dirname' in input_plugins:
+-        settings_template = "var path = require('path');\n" + settings_template
+-    open(settings,'w').write(settings_template % (fonts,input_plugins))
+-
+-
+-if __name__ == '__main__':
+-    settings_dict = {}
+-    
+-    # settings for fonts and input plugins
+-    # environment settings are for windows tilemill packaging:
+-    # https://github.com/mapbox/tilemill/blob/master/platforms/windows/package.bat#L37
+-    ip = os.environ.get('MAPNIK_INPUT_PLUGINS')
+-    if ip:
+-        settings_dict['input_plugins'] = ip
+-    else:
+-        settings_dict['input_plugins'] = '\'%s\'' % os.popen("./mason_packages/.link/bin/mapnik-config --input-plugins").readline().strip()
+-    
+-    mf = os.environ.get('MAPNIK_FONTS')
+-    if mf:
+-        settings_dict['fonts'] = mf
+-    else:
+-        settings_dict['fonts'] = '\'%s\'' % os.popen("./mason_packages/.link/bin/mapnik-config --fonts").readline().strip()
+-
+-    write_mapnik_settings(**settings_dict)
+--- a/install_mason.sh
++++ b/install_mason.sh
+@@ -12,7 +12,7 @@ ICU_VERSION="57.1"
+ 
+ if [ ! -f ./mason/mason.sh ]; then
+     mkdir -p ./mason
+-    curl -sSfL https://github.com/mapbox/mason/archive/c1948184d9430226e36f1bc1f8f081268b6bc2ba.tar.gz | tar --gunzip --extract --strip-components=1 --exclude="*md" --exclude="test*" --directory=./mason
++    curl -sSfL https://github.com/mapbox/mason/archive/23fe28bc578667fc81f4d6e3479ab4ffb4702b77.tar.gz | tar --gunzip --extract --strip-components=1 --exclude="*md" --exclude="test*" --directory=./mason
+ fi
+ 
+ if [ ! -f ./mason_packages/.link/bin/mapnik-config ]; then
+@@ -38,5 +38,5 @@ if [ ! -f ./mason_packages/.link/bin/map
+     # NOTE: sync this version with the `mapnik_version` in package.json (which is used for windows builds)
+     # In the future we could pull from that version automatically if mason were to support knowing the right dep
+     # versions to install automatically. Until then there is not much point since the deps are still hardcoded here.
+-    install mapnik 3.0.15
++    install mapnik f64c757
+ fi
+--- a/package.json
++++ b/package.json
+@@ -4,8 +4,8 @@
+   "url": "http://github.com/mapnik/node-mapnik",
+   "homepage": "http://mapnik.org",
+   "author": "Dane Springmeyer <dane at mapbox.com> (mapnik.org)",
+-  "version": "3.6.2",
+-  "mapnik_version":"v3.0.15",
++  "version": "3.6.2-dev-v3.0.16",
++  "mapnik_version":"v3.0.16",
+   "main": "./lib/mapnik.js",
+   "binary": {
+     "module_name": "mapnik",
+@@ -45,18 +45,18 @@
+       "node-pre-gyp"
+   ],
+   "bin": {
++    "mapnik-index.js": "./bin/mapnik-index.js",
+     "mapnik-inspect.js": "./bin/mapnik-inspect.js",
+     "mapnik-render.js": "./bin/mapnik-render.js",
+     "mapnik-shapeindex.js": "./bin/mapnik-shapeindex.js"
+   },
+   "scripts": {
+-    "prepublish": "npm ls",
++    "prepublishOnly": "npm ls",
+     "test": "jshint bin lib/index.js lib/mapnik.js && mocha -R spec --timeout 50000",
+     "install": "node-pre-gyp install --fallback-to-build",
+     "docs": "documentation build src/*.cpp src/mapnik_plugins.hpp --polyglot -o documentation -f html --github --name Mapnik"
+   },
+   "devDependencies": {
+-    "node-gyp": "^3.6.1",
+     "aws-sdk": "2.0.12",
+     "jshint": "^2.5.10",
+     "mocha": "2.x",
+--- a/scripts/build-appveyor.bat
++++ b/scripts/build-appveyor.bat
+@@ -75,6 +75,12 @@ SET PROJ_LIB=%MAPNIK_SDK%\share\proj
+ SET GDAL_DATA=%MAPNIK_SDK%\share\gdal
+ SET ICU_DATA=%MAPNIK_SDK%\share\icu
+ 
++:: workaround node-gyp/request node v0.10.x breakage
++IF "%nodejs_version:~0,1%"=="0" npm install https://github.com/springmeyer/node-gyp/tarball/v3.x
++IF %ERRORLEVEL% NEQ 0 GOTO ERROR
++IF "%nodejs_version:~0,1%"=="4" npm install node-gyp at 4.x
++IF %ERRORLEVEL% NEQ 0 GOTO ERROR
++
+ :: actually install deps + compile node-mapnik
+ ECHO building node-mapnik
+ :: --msvs_version=2015 is passed along to node-gyp here
+--- a/scripts/postinstall.sh
++++ b/scripts/postinstall.sh
+@@ -5,6 +5,30 @@ set -o pipefail
+ MODULE_PATH=./lib/binding
+ MAPNIK_SDK=./mason_packages/.link
+ 
++# Check if we are using Mason's mapnik
++if [[ ! "$(which mapnik-config)" -ef "$MAPNIK_SDK/bin/mapnik-config" ]]; then
++  echo "
++var path = require('path');
++module.exports.paths = {
++    'fonts':         '$(mapnik-config --fonts)',
++    'input_plugins': '$(mapnik-config --input-plugins)',
++    'mapnik_index':  '$(which mapnik-index)',
++    'shape_index':   '$(which shapeindex)'
++};
++" > ${MODULE_PATH}/mapnik_settings.js
++# once https://github.com/mapnik/mapnik/pull/3759 is fixed
++# this can be enabled
++#  echo "
++#module.exports.env = {
++#    'ICU_DATA':      '$(mapnik-config --icu-data)',
++#    'GDAL_DATA':     '$(mapnik-config --gdal-data)',
++#    'PROJ_LIB':      '$(mapnik-config --proj-lib)'
++#};
++#" >> ${MODULE_PATH}/mapnik_settings.js
++
++  exit 0;
++fi
++
+ mkdir -p ${MODULE_PATH}/bin/
+ 
+ # the below switch is used since on osx the default cp
+--- a/src/mapnik_color.cpp
++++ b/src/mapnik_color.cpp
+@@ -13,7 +13,7 @@ Nan::Persistent<v8::FunctionTemplate> Co
+ /**
+  * **`mapnik.Color`**
+  *
+- * A `mapnik.Color` object used for handling and converting colors 
++ * A `mapnik.Color` object used for handling and converting colors
+  *
+  * @class Color
+  * @param {string|number} value either an array of [r, g, b, a],
+@@ -81,12 +81,12 @@ NAN_METHOD(Color::New)
+     color_ptr c_p;
+     try
+     {
+-        if (info.Length() == 1 && 
++        if (info.Length() == 1 &&
+             info[0]->IsString())
+         {
+             c_p = std::make_shared<mapnik::color>(TOSTR(info[0]));
+         }
+-        else if (info.Length() == 2 && 
++        else if (info.Length() == 2 &&
+                  info[0]->IsString() &&
+                  info[1]->IsBoolean())
+         {
+@@ -95,7 +95,7 @@ NAN_METHOD(Color::New)
+         else if (info.Length() == 3 &&
+                  info[0]->IsNumber() &&
+                  info[1]->IsNumber() &&
+-                 info[2]->IsNumber()) 
++                 info[2]->IsNumber())
+         {
+             int r = info[0]->IntegerValue();
+             int g = info[1]->IntegerValue();
+@@ -106,12 +106,12 @@ NAN_METHOD(Color::New)
+                 return;
+             }
+             c_p = std::make_shared<mapnik::color>(r,g,b);
+-        } 
++        }
+         else if (info.Length() == 4 &&
+                  info[0]->IsNumber() &&
+                  info[1]->IsNumber() &&
+                  info[2]->IsNumber() &&
+-                 info[3]->IsBoolean()) 
++                 info[3]->IsBoolean())
+         {
+             int r = info[0]->IntegerValue();
+             int g = info[1]->IntegerValue();
+@@ -122,12 +122,12 @@ NAN_METHOD(Color::New)
+                 return;
+             }
+             c_p = std::make_shared<mapnik::color>(r,g,b,255,info[3]->BooleanValue());
+-        } 
++        }
+         else if (info.Length() == 4 &&
+                  info[0]->IsNumber() &&
+                  info[1]->IsNumber() &&
+                  info[2]->IsNumber() &&
+-                 info[3]->IsNumber()) 
++                 info[3]->IsNumber())
+         {
+             int r = info[0]->IntegerValue();
+             int g = info[1]->IntegerValue();
+@@ -139,13 +139,13 @@ NAN_METHOD(Color::New)
+                 return;
+             }
+             c_p = std::make_shared<mapnik::color>(r,g,b,a);
+-        } 
++        }
+         else if (info.Length() == 5 &&
+                  info[0]->IsNumber() &&
+                  info[1]->IsNumber() &&
+                  info[2]->IsNumber() &&
+                  info[3]->IsNumber() &&
+-                 info[4]->IsBoolean()) 
++                 info[4]->IsBoolean())
+         {
+             int r = info[0]->IntegerValue();
+             int g = info[1]->IntegerValue();
+@@ -157,8 +157,8 @@ NAN_METHOD(Color::New)
+                 return;
+             }
+             c_p = std::make_shared<mapnik::color>(r,g,b,a,info[4]->BooleanValue());
+-        } 
+-        else 
++        }
++        else
+         {
+             Nan::ThrowTypeError("invalid arguments: colors can be created from a string, integer r,g,b values, or integer r,g,b,a values");
+             return;
+@@ -183,10 +183,11 @@ v8::Local<v8::Value> Color::NewInstance(
+     Color* c = new Color();
+     c->this_ = std::make_shared<mapnik::color>(color);
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(c);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Color instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+-
+ NAN_GETTER(Color::get_prop)
+ {
+     Color* c = Nan::ObjectWrap::Unwrap<Color>(info.Holder());
+--- a/src/mapnik_datasource.cpp
++++ b/src/mapnik_datasource.cpp
+@@ -147,7 +147,9 @@ v8::Local<v8::Value> Datasource::NewInst
+     Datasource* d = new Datasource();
+     d->datasource_ = ds_ptr;
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(d);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Datasource instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+ NAN_METHOD(Datasource::parameters)
+--- a/src/mapnik_feature.cpp
++++ b/src/mapnik_feature.cpp
+@@ -114,7 +114,9 @@ NAN_METHOD(Feature::fromJSON)
+         }
+         Feature* feat = new Feature(f);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(feat);
+-        info.GetReturnValue().Set(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Feature instance");
++        else info.GetReturnValue().Set(maybe_local.ToLocalChecked());
+     }
+     catch (std::exception const& ex)
+     {
+@@ -132,7 +134,9 @@ v8::Local<v8::Value> Feature::NewInstanc
+     Nan::EscapableHandleScope scope;
+     Feature* f = new Feature(f_ptr);
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(f);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Feature instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+ /**
+--- a/src/mapnik_featureset.cpp
++++ b/src/mapnik_featureset.cpp
+@@ -5,7 +5,7 @@ Nan::Persistent<v8::FunctionTemplate> Fe
+ 
+ /**
+  * **`mapnik.Featureset`**
+- * 
++ *
+  * An iterator of {@link mapnik.Feature} objects.
+  *
+  * @class Featureset
+@@ -74,10 +74,10 @@ NAN_METHOD(Featureset::next)
+         }
+         catch (std::exception const& ex)
+         {
+-            // It is not immediately obvious how this could cause an exception, a check of featureset plugin 
++            // It is not immediately obvious how this could cause an exception, a check of featureset plugin
+             // implementations resulted in no obvious way that an exception could be raised. Therefore, it
+             // is not obvious currently what could raise this exception. However, since a plugin could possibly
+-            // be developed outside of mapnik core plugins that could raise here we are probably best still 
++            // be developed outside of mapnik core plugins that could raise here we are probably best still
+             // wrapping this in a try catch.
+             /* LCOV_EXCL_START */
+             Nan::ThrowError(ex.what());
+@@ -98,5 +98,7 @@ v8::Local<v8::Value> Featureset::NewInst
+     Featureset* fs = new Featureset();
+     fs->this_ = fsp;
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(fs);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Featureset instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+--- a/src/mapnik_geometry.cpp
++++ b/src/mapnik_geometry.cpp
+@@ -88,7 +88,9 @@ v8::Local<v8::Value> Geometry::NewInstan
+     Nan::EscapableHandleScope scope;
+     Geometry* g = new Geometry(f);
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(g);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Geometry instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+ /**
+--- a/src/mapnik_grid_view.cpp
++++ b/src/mapnik_grid_view.cpp
+@@ -83,7 +83,9 @@ v8::Local<v8::Value> GridView::NewInstan
+     GridView* gv = new GridView(JSGrid);
+     gv->this_ = std::make_shared<mapnik::grid_view>(JSGrid->get()->get_view(x,y,w,h));
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(gv);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new GridView instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+ NAN_METHOD(GridView::width)
+@@ -301,7 +303,7 @@ NAN_METHOD(GridView::encodeSync)
+             }
+ 
+             resolution = bind_opt->IntegerValue();
+-            
++
+             if (resolution == 0)
+             {
+                 Nan::ThrowTypeError("'resolution' can not be zero");
+--- a/src/mapnik_image.cpp
++++ b/src/mapnik_image.cpp
+@@ -49,7 +49,7 @@ Nan::Persistent<v8::FunctionTemplate> Im
+ 
+ /**
+  * **`mapnik.Image`**
+- * 
++ *
+  * Create a new image object (surface) that can be used for rendering data to.
+  * @class Image
+  * @param {number} width - width in pixels
+@@ -109,7 +109,7 @@ void Image::Initialize(v8::Local<v8::Obj
+     Nan::SetPrototypeMethod(lcons, "resize", resize);
+     Nan::SetPrototypeMethod(lcons, "resizeSync", resizeSync);
+     Nan::SetPrototypeMethod(lcons, "data", data);
+-    
++
+     // properties
+     ATTR(lcons, "scaling", get_scaling, set_scaling);
+     ATTR(lcons, "offset", get_offset, set_offset);
+@@ -265,7 +265,7 @@ NAN_METHOD(Image::New)
+                 return;
+             }
+         }
+-        
++
+         try {
+             Image* im = new Image(info[0]->IntegerValue(),
+                                   info[1]->IntegerValue(),
+@@ -360,7 +360,7 @@ struct visitor_get_pixel
+         std::uint32_t val = mapnik::get_pixel<std::uint32_t>(data, x_, y_);
+         return scope.Escape(Nan::New<v8::Uint32>(val));
+     }
+-    
++
+     v8::Local<v8::Value> operator() (mapnik::image_gray32s const& data)
+     {
+         Nan::EscapableHandleScope scope;
+@@ -406,7 +406,7 @@ struct visitor_get_pixel
+   private:
+     int x_;
+     int y_;
+-        
++
+ };
+ 
+ /**
+@@ -535,11 +535,11 @@ NAN_METHOD(Image::setPixel)
+     else if (info[2]->IsObject())
+     {
+         v8::Local<v8::Object> obj = info[2]->ToObject();
+-        if (obj->IsNull() || obj->IsUndefined() || !Nan::New(Color::constructor)->HasInstance(obj)) 
++        if (obj->IsNull() || obj->IsUndefined() || !Nan::New(Color::constructor)->HasInstance(obj))
+         {
+             Nan::ThrowTypeError("A numeric or color value is expected as third arg");
+         }
+-        else 
++        else
+         {
+             Color * color = Nan::ObjectWrap::Unwrap<Color>(obj);
+             mapnik::set_pixel(*im->this_,x,y,*(color->get()));
+@@ -553,9 +553,9 @@ NAN_METHOD(Image::setPixel)
+ }
+ 
+ /**
+- * Compare the pixels of one image to the pixels of another. Returns the number 
+- * of pixels that are different. So, if the images are identical then it returns `0`. 
+- * And if the images share no common pixels it returns the total number of pixels 
++ * Compare the pixels of one image to the pixels of another. Returns the number
++ * of pixels that are different. So, if the images are identical then it returns `0`.
++ * And if the images share no common pixels it returns the total number of pixels
+  * in an image which is equivalent to `im.width()*im.height()`.
+  *
+  * @name compare
+@@ -563,10 +563,10 @@ NAN_METHOD(Image::setPixel)
+  * @memberof Image
+  * @param {mapnik.Image} image - another {@link mapnik.Image} instance to compare to
+  * @param {Object} [options]
+- * @param {number} [options.threshold=16] - A value that should be `0` or greater to 
+- * determine if the pixels match. Defaults to 16 which means that `rgba(0,0,0,0)` 
++ * @param {number} [options.threshold=16] - A value that should be `0` or greater to
++ * determine if the pixels match. Defaults to 16 which means that `rgba(0,0,0,0)`
+  * would be considered the same as `rgba(15,15,15,0)`.
+- * @param {boolean} [options.alpha=true] - `alpha` value, along with `rgb`, is considered 
++ * @param {boolean} [options.alpha=true] - `alpha` value, along with `rgb`, is considered
+  * when comparing pixels
+  * @returns {number} quantified visual difference between these two images in "number of
+  * pixels" (i.e. `80` pixels are different);
+@@ -574,20 +574,20 @@ NAN_METHOD(Image::setPixel)
+  * // start with the exact same images
+  * var img1 = new mapnik.Image(2,2);
+  * var img2 = new mapnik.Image(2,2);
+- * console.log(img1.compare(img2)); // 0 
+- * 
++ * console.log(img1.compare(img2)); // 0
++ *
+  * // change 1 pixel in img2
+  * img2.setPixel(0,0, new mapnik.Color('green'));
+- * console.log(img1.compare(img2)); // 1 
+- * 
++ * console.log(img1.compare(img2)); // 1
++ *
+  * // difference in color at first pixel
+  * img1.setPixel(0,0, new mapnik.Color('red'));
+- * console.log(img1.compare(img2)); // 1 
+- * 
++ * console.log(img1.compare(img2)); // 1
++ *
+  * // two pixels different
+  * img2.setPixel(0,1, new mapnik.Color('red'));
+- * console.log(img1.compare(img2)); // 2 
+- * 
++ * console.log(img1.compare(img2)); // 2
++ *
+  * // all pixels different
+  * img2.setPixel(1,1, new mapnik.Color('blue'));
+  * img2.setPixel(1,0, new mapnik.Color('blue'));
+@@ -653,7 +653,7 @@ NAN_METHOD(Image::compare)
+  * @name filterSync
+  * @instance
+  * @memberof Image
+- * @param {string} filter - can be `blur`, `emboss`, `sharpen`, 
++ * @param {string} filter - can be `blur`, `emboss`, `sharpen`,
+  * `sobel`, or `gray`.
+  * @example
+  * var img = new mapnik.Image(5, 5);
+@@ -704,7 +704,7 @@ typedef struct {
+  * @name filter
+  * @instance
+  * @memberof Image
+- * @param {string} filter - can be `blur`, `emboss`, `sharpen`, 
++ * @param {string} filter - can be `blur`, `emboss`, `sharpen`,
+  * `sobel`, or `gray`.
+  * @param {Function} callback - `function(err, img)`
+  * @example
+@@ -726,7 +726,7 @@ NAN_METHOD(Image::filter)
+         Nan::ThrowTypeError("last argument must be a callback function");
+         return;
+     }
+-    
++
+     Image* im = Nan::ObjectWrap::Unwrap<Image>(info.Holder());
+     if (!info[0]->IsString())
+     {
+@@ -735,7 +735,7 @@ NAN_METHOD(Image::filter)
+     }
+     filter_image_baton_t *closure = new filter_image_baton_t();
+     closure->filter = TOSTR(info[0]);
+-    
++
+     // ensure callback is a function
+     v8::Local<v8::Value> callback = info[info.Length()-1];
+     closure->request.data = closure;
+@@ -828,11 +828,11 @@ v8::Local<v8::Value> Image::_fillSync(Na
+         else if (info[0]->IsObject())
+         {
+             v8::Local<v8::Object> obj = info[0]->ToObject();
+-            if (obj->IsNull() || obj->IsUndefined() || !Nan::New(Color::constructor)->HasInstance(obj)) 
++            if (obj->IsNull() || obj->IsUndefined() || !Nan::New(Color::constructor)->HasInstance(obj))
+             {
+                 Nan::ThrowTypeError("A numeric or color value is expected");
+             }
+-            else 
++            else
+             {
+                 Color * color = Nan::ObjectWrap::Unwrap<Color>(obj);
+                 mapnik::fill(*im->this_,*(color->get()));
+@@ -886,9 +886,9 @@ typedef struct {
+  *   if (err) throw err;
+  *   var colors = img.getPixel(0,0, {get_color: true});
+  *   pixel is colored blue
+- *   console.log(color.b); // 255   
++ *   console.log(color.b); // 255
+  * });
+- * 
++ *
+  * // or fill with rgb string
+  * img.fill('rgba(255,255,255,0)', function(err, img) { ... });
+  */
+@@ -898,7 +898,7 @@ NAN_METHOD(Image::fill)
+         info.GetReturnValue().Set(_fillSync(info));
+         return;
+     }
+-    
++
+     Image* im = Nan::ObjectWrap::Unwrap<Image>(info.Holder());
+     fill_image_baton_t *closure = new fill_image_baton_t();
+     if (info[0]->IsUint32())
+@@ -919,13 +919,13 @@ NAN_METHOD(Image::fill)
+     else if (info[0]->IsObject())
+     {
+         v8::Local<v8::Object> obj = info[0]->ToObject();
+-        if (obj->IsNull() || obj->IsUndefined() || !Nan::New(Color::constructor)->HasInstance(obj)) 
++        if (obj->IsNull() || obj->IsUndefined() || !Nan::New(Color::constructor)->HasInstance(obj))
+         {
+             delete closure;
+             Nan::ThrowTypeError("A numeric or color value is expected");
+             return;
+         }
+-        else 
++        else
+         {
+             Color * color = Nan::ObjectWrap::Unwrap<Color>(obj);
+             closure->c = *(color->get());
+@@ -1219,7 +1219,7 @@ v8::Local<v8::Value> Image::_premultiply
+  * @example
+  * var img = new mapnik.Image(5,5);
+  * img.premultiply(function(err, img) {
+- *   if (err) throw err;   
++ *   if (err) throw err;
+  *   // your custom code with premultiplied img
+  * })
+  */
+@@ -1342,7 +1342,7 @@ typedef struct {
+  * @example
+  * var img = new mapnik.Image(2,2);
+  * console.log(img.isSolid()); // true
+- * 
++ *
+  * // change a pixel
+  * img.setPixel(0,0, new mapnik.Color('green'));
+  * console.log(img.isSolid()); // false
+@@ -1450,7 +1450,7 @@ typedef struct {
+     uv_work_t request;
+     Image* im1;
+     image_ptr im2;
+-    mapnik::image_dtype type;  
++    mapnik::image_dtype type;
+     double offset;
+     double scaling;
+     Nan::Persistent<v8::Function> cb;
+@@ -1483,14 +1483,14 @@ NAN_METHOD(Image::copy)
+         info.GetReturnValue().Set(_copySync(info));
+         return;
+     }
+-    
++
+     Image* im1 = Nan::ObjectWrap::Unwrap<Image>(info.Holder());
+     double offset = 0.0;
+     bool scaling_or_offset_set = false;
+     double scaling = 1.0;
+     mapnik::image_dtype type = im1->this_->get_dtype();
+     v8::Local<v8::Object> options = Nan::New<v8::Object>();
+-    
++
+     if (info.Length() >= 2)
+     {
+         if (info[0]->IsNumber())
+@@ -1524,7 +1524,7 @@ NAN_METHOD(Image::copy)
+             return;
+         }
+     }
+-    
++
+     if (options->Has(Nan::New("scaling").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> scaling_val = options->Get(Nan::New("scaling").ToLocalChecked());
+@@ -1539,7 +1539,7 @@ NAN_METHOD(Image::copy)
+             return;
+         }
+     }
+-    
++
+     if (options->Has(Nan::New("offset").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> offset_val = options->Get(Nan::New("offset").ToLocalChecked());
+@@ -1560,7 +1560,7 @@ NAN_METHOD(Image::copy)
+         scaling = im1->this_->get_scaling();
+         offset = im1->this_->get_offset();
+     }
+-    
++
+     copy_image_baton_t *closure = new copy_image_baton_t();
+     closure->request.data = closure;
+     closure->im1 = im1;
+@@ -1615,8 +1615,9 @@ void Image::EIO_AfterCopy(uv_work_t* req
+     {
+         Image* im = new Image(closure->im2);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-        v8::Local<v8::Object> image_obj = Nan::New(constructor)->GetFunction()->NewInstance(1, &ext);
+-        v8::Local<v8::Value> argv[2] = { Nan::Null(), image_obj };
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        v8::Local<v8::Value> argv[2] = { Nan::Null(), maybe_local.ToLocalChecked() };
+         Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 2, argv);
+     }
+     closure->im1->Unref();
+@@ -1686,7 +1687,7 @@ v8::Local<v8::Value> Image::_copySync(Na
+             return scope.Escape(Nan::Undefined());
+         }
+     }
+-    
++
+     if (options->Has(Nan::New("scaling").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> scaling_val = options->Get(Nan::New("scaling").ToLocalChecked());
+@@ -1701,7 +1702,7 @@ v8::Local<v8::Value> Image::_copySync(Na
+             return scope.Escape(Nan::Undefined());
+         }
+     }
+-    
++
+     if (options->Has(Nan::New("offset").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> offset_val = options->Get(Nan::New("offset").ToLocalChecked());
+@@ -1733,7 +1734,9 @@ v8::Local<v8::Value> Image::_copySync(Na
+                                                     );
+         Image* new_im = new Image(imagep);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(new_im);
+-        return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        return scope.Escape(maybe_local.ToLocalChecked());
+     }
+     catch (std::exception const& ex)
+     {
+@@ -1779,7 +1782,7 @@ typedef struct {
+  * });
+  */
+ NAN_METHOD(Image::resize)
+-{    
++{
+     // ensure callback is a function
+     v8::Local<v8::Value> callback = info[info.Length() - 1];
+     if (!info[info.Length()-1]->IsFunction()) {
+@@ -1794,7 +1797,7 @@ NAN_METHOD(Image::resize)
+     double filter_factor = 1.0;
+     mapnik::scaling_method_e scaling_method = mapnik::SCALING_NEAR;
+     v8::Local<v8::Object> options = Nan::New<v8::Object>();
+-    
++
+     if (info.Length() >= 3)
+     {
+         if (info[0]->IsNumber())
+@@ -1845,7 +1848,7 @@ NAN_METHOD(Image::resize)
+             return;
+         }
+     }
+-    if (options->Has(Nan::New("offset_x").ToLocalChecked())) 
++    if (options->Has(Nan::New("offset_x").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> bind_opt = options->Get(Nan::New("offset_x").ToLocalChecked());
+         if (!bind_opt->IsNumber())
+@@ -1855,7 +1858,7 @@ NAN_METHOD(Image::resize)
+         }
+         offset_x = bind_opt->IntegerValue();
+     }
+-    if (options->Has(Nan::New("offset_y").ToLocalChecked())) 
++    if (options->Has(Nan::New("offset_y").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> bind_opt = options->Get(Nan::New("offset_y").ToLocalChecked());
+         if (!bind_opt->IsNumber())
+@@ -1884,7 +1887,7 @@ NAN_METHOD(Image::resize)
+             return;
+         }
+     }
+-    
++
+     if (options->Has(Nan::New("filter_factor").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> ff_val = options->Get(Nan::New("filter_factor").ToLocalChecked());
+@@ -1917,7 +1920,7 @@ NAN_METHOD(Image::resize)
+ struct resize_visitor
+ {
+ 
+-    resize_visitor(mapnik::image_any const& im1, 
++    resize_visitor(mapnik::image_any const& im1,
+                    mapnik::scaling_method_e scaling_method,
+                    double image_ratio_x,
+                    double image_ratio_y,
+@@ -1938,7 +1941,7 @@ struct resize_visitor
+         {
+             throw std::runtime_error("RGBA8 images must be premultiplied prior to using resize");
+         }
+-        mapnik::scale_image_agg(im2, 
++        mapnik::scale_image_agg(im2,
+                                 mapnik::util::get<mapnik::image_rgba8>(im1_),
+                                 scaling_method_,
+                                 image_ratio_x_,
+@@ -1951,7 +1954,7 @@ struct resize_visitor
+     template <typename T>
+     void operator()(T & im2) const
+     {
+-        mapnik::scale_image_agg(im2, 
++        mapnik::scale_image_agg(im2,
+                                 mapnik::util::get<T>(im1_),
+                                 scaling_method_,
+                                 image_ratio_x_,
+@@ -1960,7 +1963,7 @@ struct resize_visitor
+                                 offset_y_,
+                                 filter_factor_);
+     }
+-    
++
+     void operator()(mapnik::image_null &) const
+     {
+         // Should be caught earlier so no test coverage should reach here.
+@@ -1968,7 +1971,7 @@ struct resize_visitor
+         throw std::runtime_error("Can not resize null images");
+         /* LCOV_EXCL_STOP */
+     }
+-    
++
+     void operator()(mapnik::image_gray8s &) const
+     {
+         throw std::runtime_error("Mapnik currently does not support resizing signed 8 bit integer rasters");
+@@ -1978,27 +1981,27 @@ struct resize_visitor
+     {
+         throw std::runtime_error("Mapnik currently does not support resizing signed 16 bit integer rasters");
+     }
+-    
++
+     void operator()(mapnik::image_gray32 &) const
+     {
+         throw std::runtime_error("Mapnik currently does not support resizing unsigned 32 bit integer rasters");
+     }
+-    
++
+     void operator()(mapnik::image_gray32s &) const
+     {
+         throw std::runtime_error("Mapnik currently does not support resizing signed 32 bit integer rasters");
+     }
+-    
++
+     void operator()(mapnik::image_gray64 &) const
+     {
+         throw std::runtime_error("Mapnik currently does not support resizing unsigned 64 bit integer rasters");
+     }
+-    
++
+     void operator()(mapnik::image_gray64s &) const
+     {
+         throw std::runtime_error("Mapnik currently does not support resizing signed 64 bit integer rasters");
+     }
+-    
++
+     void operator()(mapnik::image_gray64f &) const
+     {
+         throw std::runtime_error("Mapnik currently does not support resizing 64 bit floating point rasters");
+@@ -2030,8 +2033,8 @@ void Image::EIO_Resize(uv_work_t* req)
+         double offset = closure->im1->this_->get_offset();
+         double scaling = closure->im1->this_->get_scaling();
+ 
+-        closure->im2 = std::make_shared<mapnik::image_any>(closure->size_x, 
+-                                                           closure->size_y, 
++        closure->im2 = std::make_shared<mapnik::image_any>(closure->size_x,
++                                                           closure->size_y,
+                                                            closure->im1->this_->get_dtype(),
+                                                            true,
+                                                            true,
+@@ -2046,7 +2049,7 @@ void Image::EIO_Resize(uv_work_t* req)
+             closure->error_name = "Image width or height is zero or less then zero.";
+             return;
+         }
+-        double image_ratio_x = static_cast<double>(closure->size_x) / im_width; 
++        double image_ratio_x = static_cast<double>(closure->size_x) / im_width;
+         double image_ratio_y = static_cast<double>(closure->size_y) / im_height;
+         resize_visitor visit(*(closure->im1->this_),
+                              closure->scaling_method,
+@@ -2077,8 +2080,9 @@ void Image::EIO_AfterResize(uv_work_t* r
+     {
+         Image* im = new Image(closure->im2);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-        v8::Local<v8::Object> image_obj = Nan::New(constructor)->GetFunction()->NewInstance(1, &ext);
+-        v8::Local<v8::Value> argv[2] = { Nan::Null(), image_obj };
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        v8::Local<v8::Value> argv[2] = { Nan::Null(), maybe_local.ToLocalChecked() };
+         Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 2, argv);
+     }
+     closure->im1->Unref();
+@@ -2158,7 +2162,7 @@ v8::Local<v8::Value> Image::_resizeSync(
+     {
+         Nan::ThrowTypeError("Resize requires at least a width and height parameter");
+         return scope.Escape(Nan::Undefined());
+-    }    
++    }
+     if (info.Length() >= 3)
+     {
+         if (info[2]->IsObject())
+@@ -2171,7 +2175,7 @@ v8::Local<v8::Value> Image::_resizeSync(
+             return scope.Escape(Nan::Undefined());
+         }
+     }
+-    if (options->Has(Nan::New("offset_x").ToLocalChecked())) 
++    if (options->Has(Nan::New("offset_x").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> bind_opt = options->Get(Nan::New("offset_x").ToLocalChecked());
+         if (!bind_opt->IsNumber())
+@@ -2181,7 +2185,7 @@ v8::Local<v8::Value> Image::_resizeSync(
+         }
+         offset_x = bind_opt->IntegerValue();
+     }
+-    if (options->Has(Nan::New("offset_y").ToLocalChecked())) 
++    if (options->Has(Nan::New("offset_y").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> bind_opt = options->Get(Nan::New("offset_y").ToLocalChecked());
+         if (!bind_opt->IsNumber())
+@@ -2191,7 +2195,7 @@ v8::Local<v8::Value> Image::_resizeSync(
+         }
+         offset_y = bind_opt->IntegerValue();
+     }
+-    
++
+     if (options->Has(Nan::New("scaling_method").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> scaling_val = options->Get(Nan::New("scaling_method").ToLocalChecked());
+@@ -2211,7 +2215,7 @@ v8::Local<v8::Value> Image::_resizeSync(
+             return scope.Escape(Nan::Undefined());
+         }
+     }
+-    
++
+     if (options->Has(Nan::New("filter_factor").ToLocalChecked()))
+     {
+         v8::Local<v8::Value> ff_val = options->Get(Nan::New("filter_factor").ToLocalChecked());
+@@ -2243,16 +2247,16 @@ v8::Local<v8::Value> Image::_resizeSync(
+         double offset = im->this_->get_offset();
+         double scaling = im->this_->get_scaling();
+ 
+-        image_ptr imagep = std::make_shared<mapnik::image_any>(width, 
+-                                                           height, 
++        image_ptr imagep = std::make_shared<mapnik::image_any>(width,
++                                                           height,
+                                                            im->this_->get_dtype(),
+                                                            true,
+                                                            true,
+                                                            false);
+         imagep->set_offset(offset);
+         imagep->set_scaling(scaling);
+-        double image_ratio_x = static_cast<double>(width) / im_width; 
+-        double image_ratio_y = static_cast<double>(height) / im_height; 
++        double image_ratio_x = static_cast<double>(width) / im_width;
++        double image_ratio_y = static_cast<double>(height) / im_height;
+         resize_visitor visit(*(im->this_),
+                              scaling_method,
+                              image_ratio_x,
+@@ -2263,7 +2267,9 @@ v8::Local<v8::Value> Image::_resizeSync(
+         mapnik::util::apply_visitor(visit, *imagep);
+         Image* new_im = new Image(imagep);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(new_im);
+-        return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        return scope.Escape(maybe_local.ToLocalChecked());
+     }
+     catch (std::exception const& ex)
+     {
+@@ -2372,7 +2378,9 @@ v8::Local<v8::Value> Image::_openSync(Na
+                 }
+                 Image* im = new Image(imagep);
+                 v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-                return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++                Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++                if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++                return scope.Escape(maybe_local.ToLocalChecked());
+             }
+         }
+         Nan::ThrowTypeError(("Unsupported image format:" + filename).c_str());
+@@ -2413,11 +2421,11 @@ typedef struct {
+  * @memberof Image
+  * @static
+  * @param {string} path - path to the image you want to load
+- * @param {Function} callback - 
++ * @param {Function} callback -
+  * @example
+  * mapnik.Image.open('./path/to/image.jpg', function(err, img) {
+  *   if (err) throw err;
+- *   // img is now an Image object   
++ *   // img is now an Image object
+  * });
+  */
+ NAN_METHOD(Image::open)
+@@ -2508,8 +2516,9 @@ void Image::EIO_AfterOpen(uv_work_t* req
+     {
+         Image* im = new Image(closure->im);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-        v8::Local<v8::Object> image_obj = Nan::New(constructor)->GetFunction()->NewInstance(1, &ext);
+-        v8::Local<v8::Value> argv[2] = { Nan::Null(), image_obj };
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        v8::Local<v8::Value> argv[2] = { Nan::Null(), maybe_local.ToLocalChecked() };
+         Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 2, argv);
+     }
+     closure->cb.Reset();
+@@ -2564,13 +2573,13 @@ v8::Local<v8::Value> Image::_fromSVGSync
+ {
+     Nan::EscapableHandleScope scope;
+ 
+-    if (!fromFile && (info.Length() < 1 || !info[0]->IsObject())) 
++    if (!fromFile && (info.Length() < 1 || !info[0]->IsObject()))
+     {
+         Nan::ThrowTypeError("must provide a buffer argument");
+         return scope.Escape(Nan::Undefined());
+     }
+ 
+-    if (fromFile && (info.Length() < 1 || !info[0]->IsString())) 
++    if (fromFile && (info.Length() < 1 || !info[0]->IsString()))
+     {
+         Nan::ThrowTypeError("must provide a filename argument");
+         return scope.Escape(Nan::Undefined());
+@@ -2579,9 +2588,10 @@ v8::Local<v8::Value> Image::_fromSVGSync
+ 
+     double scale = 1.0;
+     std::uint32_t max_size = 2048;
+-    if (info.Length() >= 2) 
++    bool strict = false;
++    if (info.Length() >= 2)
+     {
+-        if (!info[1]->IsObject()) 
++        if (!info[1]->IsObject())
+         {
+             Nan::ThrowTypeError("optional second arg must be an options object");
+             return scope.Escape(Nan::Undefined());
+@@ -2590,7 +2600,7 @@ v8::Local<v8::Value> Image::_fromSVGSync
+         if (options->Has(Nan::New("scale").ToLocalChecked()))
+         {
+             v8::Local<v8::Value> scale_opt = options->Get(Nan::New("scale").ToLocalChecked());
+-            if (!scale_opt->IsNumber()) 
++            if (!scale_opt->IsNumber())
+             {
+                 Nan::ThrowTypeError("'scale' must be a number");
+                 return scope.Escape(Nan::Undefined());
+@@ -2607,16 +2617,26 @@ v8::Local<v8::Value> Image::_fromSVGSync
+             v8::Local<v8::Value> opt = options->Get(Nan::New("max_size").ToLocalChecked());
+             if (!opt->IsNumber())
+             {
+-                Nan::ThrowTypeError("max_size must be a positive integer");
++                Nan::ThrowTypeError("'max_size' must be a positive integer");
+                 return scope.Escape(Nan::Undefined());
+             }
+             auto max_size_val = opt->IntegerValue();
+             if (max_size_val < 0 || max_size_val > 65535) {
+-                Nan::ThrowTypeError("max_size must be a positive integer between 0 and 65535");
++                Nan::ThrowTypeError("'max_size' must be a positive integer between 0 and 65535");
+                 return scope.Escape(Nan::Undefined());
+             }
+             max_size = static_cast<std::uint32_t>(max_size_val);
+         }
++        if (options->Has(Nan::New("strict").ToLocalChecked()))
++        {
++            v8::Local<v8::Value> opt = options->Get(Nan::New("strict").ToLocalChecked());
++            if (!opt->IsBoolean())
++            {
++                Nan::ThrowTypeError("'strict' must be a boolean value");
++                return scope.Escape(Nan::Undefined());
++            }
++            strict = opt->BooleanValue();
++        }
+     }
+ 
+     try
+@@ -2626,15 +2646,15 @@ v8::Local<v8::Value> Image::_fromSVGSync
+         vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
+         svg_path_adapter svg_path(stl_storage);
+         svg_converter_type svg(svg_path, marker_path->attributes());
+-        svg_parser p(svg);
++        svg_parser p(svg, strict);
+         if (fromFile)
+         {
+-            if (!p.parse(TOSTR(info[0])))
++            p.parse(TOSTR(info[0]));
++            if (!p.err_handler().error_messages().empty())
+             {
+-                std::ostringstream errorMessage("");
++                std::ostringstream errorMessage;
+                 errorMessage << "SVG parse error:" << std::endl;
+-                auto const& errors = p.error_messages();
+-                for (auto error : errors) {
++                for (auto const& error : p.err_handler().error_messages()) {
+                     errorMessage <<  error << std::endl;
+                 }
+                 Nan::ThrowTypeError(errorMessage.str().c_str());
+@@ -2644,18 +2664,18 @@ v8::Local<v8::Value> Image::_fromSVGSync
+         else
+         {
+             v8::Local<v8::Object> obj = info[0]->ToObject();
+-            if (obj->IsNull() || obj->IsUndefined() || !node::Buffer::HasInstance(obj)) 
++            if (obj->IsNull() || obj->IsUndefined() || !node::Buffer::HasInstance(obj))
+             {
+                 Nan::ThrowTypeError("first argument is invalid, must be a Buffer");
+                 return scope.Escape(Nan::Undefined());
+             }
+             std::string svg_buffer(node::Buffer::Data(obj),node::Buffer::Length(obj));
+-            if (!p.parse_from_string(svg_buffer))
++            p.parse_from_string(svg_buffer);
++            if (!p.err_handler().error_messages().empty())
+             {
+-                std::ostringstream errorMessage("");
++                std::ostringstream errorMessage;
+                 errorMessage << "SVG parse error:" << std::endl;
+-                auto const& errors = p.error_messages();
+-                for (auto error : errors) {
++                for (auto const& error : p.err_handler().error_messages()) {
+                     errorMessage <<  error << std::endl;
+                 }
+                 Nan::ThrowTypeError(errorMessage.str().c_str());
+@@ -2677,7 +2697,7 @@ v8::Local<v8::Value> Image::_fromSVGSync
+         double opacity = 1;
+         double svg_width = svg.width() * scale;
+         double svg_height = svg.height() * scale;
+-        
++
+         if (svg_width <= 0 || svg_height <= 0)
+         {
+             Nan::ThrowTypeError("image created from svg must have a width and height greater then zero");
+@@ -2718,7 +2738,9 @@ v8::Local<v8::Value> Image::_fromSVGSync
+         image_ptr imagep = std::make_shared<mapnik::image_any>(im);
+         Image *im2 = new Image(imagep);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(im2);
+-        return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        return scope.Escape(maybe_local.ToLocalChecked());
+     }
+     catch (std::exception const& ex)
+     {
+@@ -2739,6 +2761,7 @@ typedef struct {
+     bool error;
+     double scale;
+     std::uint32_t max_size;
++    bool strict;
+     std::string error_name;
+     Nan::Persistent<v8::Function> cb;
+ } svg_file_ptr_baton_t;
+@@ -2751,6 +2774,7 @@ typedef struct {
+     bool error;
+     double scale;
+     std::uint32_t max_size;
++    bool strict;
+     std::string error_name;
+     Nan::Persistent<v8::Object> buffer;
+     Nan::Persistent<v8::Function> cb;
+@@ -2773,7 +2797,7 @@ typedef struct {
+  * @example
+  * mapnik.Image.fromSVG('./path/to/image.svg', {scale: 0.5}, function(err, img) {
+  *   if (err) throw err;
+- *   // new img object (at 50% scale)  
++ *   // new img object (at 50% scale)
+  * });
+  */
+ NAN_METHOD(Image::fromSVG)
+@@ -2783,7 +2807,7 @@ NAN_METHOD(Image::fromSVG)
+         return;
+     }
+ 
+-    if (info.Length() < 2 || !info[0]->IsString()) 
++    if (info.Length() < 2 || !info[0]->IsString())
+     {
+         Nan::ThrowTypeError("must provide a filename argument");
+         return;
+@@ -2798,9 +2822,10 @@ NAN_METHOD(Image::fromSVG)
+ 
+     double scale = 1.0;
+     std::uint32_t max_size = 2048;
+-    if (info.Length() >= 3) 
++    bool strict = false;
++    if (info.Length() >= 3)
+     {
+-        if (!info[1]->IsObject()) 
++        if (!info[1]->IsObject())
+         {
+             Nan::ThrowTypeError("optional second arg must be an options object");
+             return;
+@@ -2809,7 +2834,7 @@ NAN_METHOD(Image::fromSVG)
+         if (options->Has(Nan::New("scale").ToLocalChecked()))
+         {
+             v8::Local<v8::Value> scale_opt = options->Get(Nan::New("scale").ToLocalChecked());
+-            if (!scale_opt->IsNumber()) 
++            if (!scale_opt->IsNumber())
+             {
+                 Nan::ThrowTypeError("'scale' must be a number");
+                 return;
+@@ -2826,16 +2851,26 @@ NAN_METHOD(Image::fromSVG)
+             v8::Local<v8::Value> opt = options->Get(Nan::New("max_size").ToLocalChecked());
+             if (!opt->IsNumber())
+             {
+-                Nan::ThrowTypeError("max_size must be a positive integer");
++                Nan::ThrowTypeError("'max_size' must be a positive integer");
+                 return;
+             }
+             auto max_size_val = opt->IntegerValue();
+             if (max_size_val < 0 || max_size_val > 65535) {
+-                Nan::ThrowTypeError("max_size must be a positive integer between 0 and 65535");
++                Nan::ThrowTypeError("'max_size' must be a positive integer between 0 and 65535");
+                 return;
+             }
+             max_size = static_cast<std::uint32_t>(max_size_val);
+         }
++        if (options->Has(Nan::New("strict").ToLocalChecked()))
++        {
++            v8::Local<v8::Value> opt = options->Get(Nan::New("strict").ToLocalChecked());
++            if (!opt->IsBoolean())
++            {
++                Nan::ThrowTypeError("'strict' must be a boolean value");
++                return;
++            }
++            strict = opt->BooleanValue();
++        }
+     }
+ 
+     svg_file_ptr_baton_t *closure = new svg_file_ptr_baton_t();
+@@ -2844,6 +2879,7 @@ NAN_METHOD(Image::fromSVG)
+     closure->error = false;
+     closure->scale = scale;
+     closure->max_size = max_size;
++    closure->strict = strict;
+     closure->cb.Reset(callback.As<v8::Function>());
+     uv_queue_work(uv_default_loop(), &closure->request, EIO_FromSVG, (uv_after_work_cb)EIO_AfterFromSVG);
+     return;
+@@ -2860,13 +2896,13 @@ void Image::EIO_FromSVG(uv_work_t* req)
+         vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
+         svg_path_adapter svg_path(stl_storage);
+         svg_converter_type svg(svg_path, marker_path->attributes());
+-        svg_parser p(svg);
+-        if (!p.parse(closure->filename))
++        svg_parser p(svg, closure->strict);
++        p.parse(closure->filename);
++        if (!p.err_handler().error_messages().empty())
+         {
+-            std::ostringstream errorMessage("");
++            std::ostringstream errorMessage;
+             errorMessage << "SVG parse error:" << std::endl;
+-            auto const& errors = p.error_messages();
+-            for (auto error : errors) {
++            for (auto const& error : p.err_handler().error_messages()) {
+                 errorMessage <<  error << std::endl;
+             }
+             closure->error = true;
+@@ -2937,7 +2973,7 @@ void Image::EIO_FromSVG(uv_work_t* req)
+         // it is a good idea to keep this. Therefore, any exceptions thrown will fail gracefully.
+         // LCOV_EXCL_START
+         closure->error = true;
+-        closure->error_name = "Failed to load: " + closure->filename;
++        closure->error_name = ex.what();
+         // LCOV_EXCL_STOP
+     }
+ }
+@@ -2955,8 +2991,9 @@ void Image::EIO_AfterFromSVG(uv_work_t*
+     {
+         Image* im = new Image(closure->im);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-        v8::Local<v8::Object> image_obj = Nan::New(constructor)->GetFunction()->NewInstance(1, &ext);
+-        v8::Local<v8::Value> argv[2] = { Nan::Null(), image_obj };
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        v8::Local<v8::Value> argv[2] = { Nan::Null(), maybe_local.ToLocalChecked() };
+         Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 2, argv);
+     }
+     closure->cb.Reset();
+@@ -2973,12 +3010,13 @@ void Image::EIO_AfterFromSVG(uv_work_t*
+  * @param {number} [options.scale] - scale the image. For example passing `0.5` as scale would render
+  * your SVG at 50% the original size.
+  * @param {number} [options.max_size] - the maximum allowed size of the svg dimensions * scale. The default is 2048.
++ * @param {boolean} [options.strict] - enable `strict` parsing mode e.g throw on unsupported element/attribute. The default is `false`.
+  * This option can be passed a smaller or larger size in order to control the final size of the image allocated for
+  * rasterizing the SVG.
+  * @param {Function} callback = `function(err, img)`
+  * @example
+  * var buffer = fs.readFileSync('./path/to/image.svg');
+- * mapnik.Image.fromSVGBytesSync(buffer, function(err, img) {
++ * mapnik.Image.fromSVGBytes(buffer, function(err, img) {
+  *   if (err) throw err;
+  *   // your custom code with `img`
+  * });
+@@ -3010,9 +3048,10 @@ NAN_METHOD(Image::fromSVGBytes)
+ 
+     double scale = 1.0;
+     std::uint32_t max_size = 2048;
+-    if (info.Length() >= 3) 
++    bool strict = true;
++    if (info.Length() >= 3)
+     {
+-        if (!info[1]->IsObject()) 
++        if (!info[1]->IsObject())
+         {
+             Nan::ThrowTypeError("optional second arg must be an options object");
+             return;
+@@ -3021,7 +3060,7 @@ NAN_METHOD(Image::fromSVGBytes)
+         if (options->Has(Nan::New("scale").ToLocalChecked()))
+         {
+             v8::Local<v8::Value> scale_opt = options->Get(Nan::New("scale").ToLocalChecked());
+-            if (!scale_opt->IsNumber()) 
++            if (!scale_opt->IsNumber())
+             {
+                 Nan::ThrowTypeError("'scale' must be a number");
+                 return;
+@@ -3038,16 +3077,26 @@ NAN_METHOD(Image::fromSVGBytes)
+             v8::Local<v8::Value> opt = options->Get(Nan::New("max_size").ToLocalChecked());
+             if (!opt->IsNumber())
+             {
+-                Nan::ThrowTypeError("max_size must be a positive integer");
++                Nan::ThrowTypeError("'max_size' must be a positive integer");
+                 return;
+             }
+             auto max_size_val = opt->IntegerValue();
+             if (max_size_val < 0 || max_size_val > 65535) {
+-                Nan::ThrowTypeError("max_size must be a positive integer between 0 and 65535");
++                Nan::ThrowTypeError("'max_size' must be a positive integer between 0 and 65535");
+                 return;
+             }
+             max_size = static_cast<std::uint32_t>(max_size_val);
+         }
++        if (options->Has(Nan::New("strict").ToLocalChecked()))
++        {
++            v8::Local<v8::Value> opt = options->Get(Nan::New("strict").ToLocalChecked());
++            if (!opt->IsBoolean())
++            {
++                Nan::ThrowTypeError("'strict' must be a boolean value");
++                return;
++            }
++            strict = opt->BooleanValue();
++        }
+     }
+ 
+     svg_mem_ptr_baton_t *closure = new svg_mem_ptr_baton_t();
+@@ -3058,6 +3107,7 @@ NAN_METHOD(Image::fromSVGBytes)
+     closure->data = node::Buffer::Data(obj);
+     closure->scale = scale;
+     closure->max_size = max_size;
++    closure->strict = strict;
+     closure->dataLength = node::Buffer::Length(obj);
+     uv_queue_work(uv_default_loop(), &closure->request, EIO_FromSVGBytes, (uv_after_work_cb)EIO_AfterFromSVGBytes);
+     return;
+@@ -3074,15 +3124,15 @@ void Image::EIO_FromSVGBytes(uv_work_t*
+         vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
+         svg_path_adapter svg_path(stl_storage);
+         svg_converter_type svg(svg_path, marker_path->attributes());
+-        svg_parser p(svg);
++        svg_parser p(svg, closure->strict);
+ 
+         std::string svg_buffer(closure->data,closure->dataLength);
+-        if (!p.parse_from_string(svg_buffer))
++        p.parse_from_string(svg_buffer);
++        if (!p.err_handler().error_messages().empty())
+         {
+-            std::ostringstream errorMessage("");
++            std::ostringstream errorMessage;
+             errorMessage << "SVG parse error:" << std::endl;
+-            auto const& errors = p.error_messages();
+-            for (auto error : errors) {
++            for (auto const& error : p.err_handler().error_messages()) {
+                 errorMessage <<  error << std::endl;
+             }
+             closure->error = true;
+@@ -3180,9 +3230,9 @@ void Image::EIO_AfterFromSVGBytes(uv_wor
+ }
+ 
+ /**
+- * Create an image of the existing buffer. 
+- * 
+- * Note: the buffer must live as long as the image. 
++ * Create an image of the existing buffer.
++ *
++ * Note: the buffer must live as long as the image.
+  * It is recommended that you do not use this method. Be warned!
+  *
+  * @name fromBufferSync
+@@ -3214,7 +3264,7 @@ v8::Local<v8::Value> Image::_fromBufferS
+     unsigned width = info[0]->IntegerValue();
+     unsigned height = info[1]->IntegerValue();
+ 
+-    if (width <= 0 || height <= 0) 
++    if (width <= 0 || height <= 0)
+     {
+         Nan::ThrowTypeError("width and height must be greater then zero");
+         return scope.Escape(Nan::Undefined());
+@@ -3288,10 +3338,11 @@ v8::Local<v8::Value> Image::_fromBufferS
+         image_ptr imagep = std::make_shared<mapnik::image_any>(im_wrapper);
+         Image* im = new Image(imagep);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-        v8::Local<v8::Value> image_instance = Nan::New(constructor)->GetFunction()->NewInstance(1, &ext);
+-        v8::Local<v8::Object> image_obj = image_instance->ToObject();
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        v8::Local<v8::Object> image_obj = maybe_local.ToLocalChecked()->ToObject();
+         image_obj->Set(Nan::New("_buffer").ToLocalChecked(),obj);
+-        return scope.Escape(image_instance);
++        return scope.Escape(maybe_local.ToLocalChecked());
+     }
+     catch (std::exception const& ex)
+     {
+@@ -3343,7 +3394,9 @@ v8::Local<v8::Value> Image::_fromBytesSy
+             image_ptr imagep = std::make_shared<mapnik::image_any>(reader->read(0,0,reader->width(),reader->height()));
+             Image* im = new Image(imagep);
+             v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-            return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++            Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++            if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++            return scope.Escape(maybe_local.ToLocalChecked());
+         }
+         // The only way this is ever reached is if the reader factory in
+         // mapnik was not providing an image type it should. This should never
+@@ -3361,7 +3414,7 @@ v8::Local<v8::Value> Image::_fromBytesSy
+ }
+ 
+ /**
+- * Create an image from a byte stream buffer. 
++ * Create an image from a byte stream buffer.
+  *
+  * @name fromBytes
+  * @param {Buffer} buffer - image buffer
+@@ -3373,9 +3426,9 @@ v8::Local<v8::Value> Image::_fromBytesSy
+  * @memberof Image
+  * @example
+  * var buffer = fs.readFileSync('./path/to/image.png');
+- * mapnik.Image.fromBytesSync(buffer, function(err, img) {
++ * mapnik.Image.fromBytes(buffer, function(err, img) {
+  *   if (err) throw err;
+- *   // your custom code with `img` object   
++ *   // your custom code with `img` object
+  * });
+  */
+ NAN_METHOD(Image::fromBytes)
+@@ -3502,7 +3555,7 @@ void Image::EIO_AfterFromBytes(uv_work_t
+     else if (closure->im == nullptr)
+     {
+         /* LCOV_EXCL_START */
+-        // The only way this is ever reached is if the reader factory in 
++        // The only way this is ever reached is if the reader factory in
+         // mapnik was not providing an image type it should. This should never
+         // be occuring so marking this out from coverage
+         v8::Local<v8::Value> argv[1] = { Nan::Error("Failed to load from buffer") };
+@@ -3512,8 +3565,9 @@ void Image::EIO_AfterFromBytes(uv_work_t
+     {
+         Image* im = new Image(closure->im);
+         v8::Local<v8::Value> ext = Nan::New<v8::External>(im);
+-        v8::Local<v8::Object> image_obj = Nan::New(constructor)->GetFunction()->NewInstance(1, &ext);
+-        v8::Local<v8::Value> argv[2] = { Nan::Null(), image_obj };
++        Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++        if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Image instance");
++        v8::Local<v8::Value> argv[2] = { Nan::Null(), maybe_local.ToLocalChecked() };
+         Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 2, argv);
+     }
+     closure->cb.Reset();
+@@ -3622,17 +3676,17 @@ typedef struct {
+  * @example
+  * var img = new mapnik.Image.open('./path/to/image.png');
+  * myImage.encode('png', function(err, encoded) {
+- *   if (err) throw err;   
++ *   if (err) throw err;
+  *   // write buffer to new file
+  *   fs.writeFileSync('myimage.png', encoded);
+  * });
+- * 
++ *
+  * // encoding an image object with a mapnik.Palette
+  * var im = new mapnik.Image(256, 256);
+  * var pal = new mapnik.Palette(new Buffer('\xff\x09\x93\xFF\x01\x02\x03\x04','ascii'));
+  * im.encode('png', {palette: pal}, function(err, encode) {
+  *   if (err) throw err;
+- *   // your custom code with `encode` image buffer  
++ *   // your custom code with `encode` image buffer
+  * });
+  */
+ NAN_METHOD(Image::encode)
+@@ -3794,12 +3848,12 @@ NAN_METHOD(Image::saveSync)
+ v8::Local<v8::Value> Image::_saveSync(Nan::NAN_METHOD_ARGS_TYPE info) {
+     Nan::EscapableHandleScope scope;
+     Image* im = Nan::ObjectWrap::Unwrap<Image>(info.Holder());
+-    
++
+     if (info.Length() == 0 || !info[0]->IsString()){
+         Nan::ThrowTypeError("filename required to save file");
+         return scope.Escape(Nan::Undefined());
+     }
+-    
++
+     std::string filename = TOSTR(info[0]);
+     std::string format("");
+ 
+@@ -3854,13 +3908,13 @@ typedef struct {
+  * @example
+  * img.save('image.png', 'png', function(err) {
+  *   if (err) throw err;
+- *   // your custom code   
++ *   // your custom code
+  * });
+  */
+ NAN_METHOD(Image::save)
+ {
+     Image* im = Nan::ObjectWrap::Unwrap<Image>(info.Holder());
+-    
++
+     if (info.Length() == 0 || !info[0]->IsString()){
+         Nan::ThrowTypeError("filename required to save file");
+         return;
+@@ -3872,7 +3926,7 @@ NAN_METHOD(Image::save)
+     }
+     // ensure callback is a function
+     v8::Local<v8::Value> callback = info[info.Length()-1];
+-    
++
+     std::string filename = TOSTR(info[0]);
+     std::string format("");
+ 
+@@ -3912,7 +3966,7 @@ void Image::EIO_Save(uv_work_t* req)
+     try
+     {
+         mapnik::save_to_file(*(closure->im->this_),
+-                             closure->filename, 
++                             closure->filename,
+                              closure->format);
+     }
+     catch (std::exception const& ex)
+@@ -4157,7 +4211,7 @@ void Image::EIO_AfterComposite(uv_work_t
+ 
+     composite_image_baton_t *closure = static_cast<composite_image_baton_t *>(req->data);
+ 
+-    if (closure->error) 
++    if (closure->error)
+     {
+         v8::Local<v8::Value> argv[1] = { Nan::Error(closure->error_name.c_str()) };
+         Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(closure->cb), 1, argv);
+@@ -4190,8 +4244,8 @@ NAN_SETTER(Image::set_scaling)
+     if (!value->IsNumber())
+     {
+         Nan::ThrowError("Must provide a number");
+-    } 
+-    else 
++    }
++    else
+     {
+         double val = value->NumberValue();
+         if (val == 0.0)
+@@ -4209,8 +4263,8 @@ NAN_SETTER(Image::set_offset)
+     if (!value->IsNumber())
+     {
+         Nan::ThrowError("Must provide a number");
+-    } 
+-    else 
++    }
++    else
+     {
+         double val = value->NumberValue();
+         im->this_->set_offset(val);
+@@ -4234,4 +4288,3 @@ NAN_METHOD(Image::data)
+     // TODO - make this zero copy
+     info.GetReturnValue().Set(Nan::CopyBuffer(reinterpret_cast<const char *>(im->this_->bytes()), im->this_->size()).ToLocalChecked());
+ }
+-
+--- a/src/mapnik_image_view.cpp
++++ b/src/mapnik_image_view.cpp
+@@ -1,4 +1,3 @@
+-
+ // mapnik
+ #include <mapnik/color.hpp>             // for color
+ #include <mapnik/image_view.hpp>        // for image_view, etc
+@@ -99,7 +98,9 @@ v8::Local<v8::Value> ImageView::NewInsta
+     ImageView* imv = new ImageView(JSImage);
+     imv->this_ = std::make_shared<mapnik::image_view_any>(mapnik::create_view(*(JSImage->get()),x,y,w,h));
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(imv);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new ImageView instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+ typedef struct {
+@@ -155,7 +156,7 @@ struct visitor_get_pixel_view
+ {
+     visitor_get_pixel_view(int x, int y)
+         : x_(x), y_(y) {}
+-    
++
+     v8::Local<v8::Value> operator() (mapnik::image_view_null const& data)
+     {
+         // This should never be reached because the width and height of 0 for a null
+@@ -200,7 +201,7 @@ struct visitor_get_pixel_view
+         std::uint32_t val = mapnik::get_pixel<std::uint32_t>(data, x_, y_);
+         return scope.Escape(Nan::New<v8::Uint32>(val));
+     }
+-    
++
+     v8::Local<v8::Value> operator() (mapnik::image_view_gray32s const& data)
+     {
+         Nan::EscapableHandleScope scope;
+@@ -246,7 +247,7 @@ struct visitor_get_pixel_view
+   private:
+     int x_;
+     int y_;
+-        
++
+ };
+ 
+ void ImageView::EIO_AfterIsSolid(uv_work_t* req)
+@@ -585,5 +586,3 @@ NAN_METHOD(ImageView::save)
+     }
+     return;
+ }
+-
+-
+--- a/src/mapnik_layer.cpp
++++ b/src/mapnik_layer.cpp
+@@ -111,7 +111,9 @@ v8::Local<v8::Value> Layer::NewInstance(
+     // copy new mapnik::layer into the shared_ptr
+     l->layer_ = std::make_shared<mapnik::layer>(lay_ref);
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(l);
+-    return scope.Escape(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Layer instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+ NAN_GETTER(Layer::get_prop)
+@@ -147,25 +149,25 @@ NAN_GETTER(Layer::get_prop)
+         }
+         return;
+     }
+-    else if (a == "minimum_scale_denominator") 
++    else if (a == "minimum_scale_denominator")
+     {
+-        info.GetReturnValue().Set(Nan::New<v8::Number>(l->layer_->minimum_scale_denominator()));   
++        info.GetReturnValue().Set(Nan::New<v8::Number>(l->layer_->minimum_scale_denominator()));
+     }
+-    else if (a == "maximum_scale_denominator") 
++    else if (a == "maximum_scale_denominator")
+     {
+-        info.GetReturnValue().Set(Nan::New<v8::Number>(l->layer_->maximum_scale_denominator()));   
++        info.GetReturnValue().Set(Nan::New<v8::Number>(l->layer_->maximum_scale_denominator()));
+     }
+-    else if (a == "queryable") 
++    else if (a == "queryable")
+     {
+-        info.GetReturnValue().Set(Nan::New<v8::Boolean>(l->layer_->queryable()));   
++        info.GetReturnValue().Set(Nan::New<v8::Boolean>(l->layer_->queryable()));
+     }
+-    else if (a == "clear_label_cache") 
++    else if (a == "clear_label_cache")
+     {
+-        info.GetReturnValue().Set(Nan::New<v8::Boolean>(l->layer_->clear_label_cache()));   
++        info.GetReturnValue().Set(Nan::New<v8::Boolean>(l->layer_->clear_label_cache()));
+     }
+-    else // if (a == "active") 
++    else // if (a == "active")
+     {
+-        info.GetReturnValue().Set(Nan::New<v8::Boolean>(l->layer_->active()));   
++        info.GetReturnValue().Set(Nan::New<v8::Boolean>(l->layer_->active()));
+     }
+ }
+ 
+@@ -283,7 +285,7 @@ NAN_METHOD(Layer::describe)
+ 
+     v8::Local<v8::Object> description = Nan::New<v8::Object>();
+     mapnik::layer const& layer = *l->layer_;
+-        
++
+     description->Set(Nan::New("name").ToLocalChecked(), Nan::New<v8::String>(layer.name()).ToLocalChecked());
+ 
+     description->Set(Nan::New("srs").ToLocalChecked(), Nan::New<v8::String>(layer.srs()).ToLocalChecked());
+--- a/src/mapnik_map.cpp
++++ b/src/mapnik_map.cpp
+@@ -611,7 +611,7 @@ typedef struct {
+  * @param {String|number} [options.layer] - layer name (string) or index (positive integer, 0 index)
+  * to query. If left blank, will query all layers.
+  * @param {Function} callback
+- * @returns {Array} array - An array of `Featureset` objects and layer names, which each contain their own 
++ * @returns {Array} array - An array of `Featureset` objects and layer names, which each contain their own
+  * `Feature` objects.
+  * @example
+  * // iterate over the first layer returned and get all attribute information for each feature
+@@ -626,7 +626,7 @@ typedef struct {
+  *   }
+  *   console.log(attributes); // => [{"attr_key": "attr_value"}, {...}, {...}]
+  * });
+- * 
++ *
+  */
+ NAN_METHOD(Map::queryMapPoint)
+ {
+@@ -635,7 +635,7 @@ NAN_METHOD(Map::queryMapPoint)
+ }
+ 
+ /**
+- * Query a `Mapnik#Map` object to retrieve layer and feature data based on geographic 
++ * Query a `Mapnik#Map` object to retrieve layer and feature data based on geographic
+  * coordinates of the source data (use `Map#queryMapPoint` to query with XY coordinates).
+  *
+  * @name queryPoint
+@@ -647,7 +647,7 @@ NAN_METHOD(Map::queryMapPoint)
+  * @param {String|number} [options.layer] - layer name (string) or index (positive integer, 0 index)
+  * to query. If left blank, will query all layers.
+  * @param {Function} callback
+- * @returns {Array} array - An array of `Featureset` objects and layer names, which each contain their own 
++ * @returns {Array} array - An array of `Featureset` objects and layer names, which each contain their own
+  * `Feature` objects.
+  * @example
+  * // query based on web mercator coordinates
+@@ -662,7 +662,7 @@ NAN_METHOD(Map::queryMapPoint)
+  *   }
+  *   console.log(attributes); // => [{"attr_key": "attr_value"}, {...}, {...}]
+  * });
+- * 
++ *
+  */
+ NAN_METHOD(Map::queryPoint)
+ {
+@@ -1456,7 +1456,9 @@ NAN_METHOD(Map::clone)
+     Map* m2 = new Map();
+     m2->map_ = std::make_shared<mapnik::Map>(*m->map_);
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(m2);
+-    info.GetReturnValue().Set(Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Map instance");
++    else info.GetReturnValue().Set(maybe_local.ToLocalChecked());
+ }
+ 
+ /**
+@@ -1667,8 +1669,8 @@ struct vector_tile_baton_t {
+  * @param {Object} [options={}]
+  * @param {Number} [options.buffer_size=0] size of the buffer on the image
+  * @param {Number} [options.scale=1.0] scale the image
+- * @param {Number} [options.scale_denominator=0.0] 
+- * @param {Number} [options.offset_x=0] pixel offset along the x-axis 
++ * @param {Number} [options.scale_denominator=0.0]
++ * @param {Number} [options.offset_x=0] pixel offset along the x-axis
+  * @param {Number} [options.offset_y=0] pixel offset along the y-axis
+  * @param {String} [options.image_scaling] must be a valid scaling method (used when rendering a vector tile)
+  * @param {String} [options.image_format] must be a string and valid image format (used when rendering a vector tile)
+@@ -1676,23 +1678,23 @@ struct vector_tile_baton_t {
+  * @param {Boolean} [options.strictly_simple=] ensure all geometry is valid according to
+  * OGC Simple definition (used when rendering a vector tile)
+  * @param {Boolean} [options.multi_polygon_union] union all multipolygons (used when rendering a vector tile)
+- * @param {String} [options.fill_type] the fill type used in determining what are holes and what are outer rings. See the 
++ * @param {String} [options.fill_type] the fill type used in determining what are holes and what are outer rings. See the
+  * [Clipper documentation](http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/PolyFillType.htm)
+  * to learn more about fill types. (used when rendering a vector tile)
+  * @param {String} [options.threading_mode] (used when rendering a vector tile)
+- * @param {Number} [options.simplify_distance] Simplification works to generalize 
+- * geometries before encoding into vector tiles.simplification distance The 
++ * @param {Number} [options.simplify_distance] Simplification works to generalize
++ * geometries before encoding into vector tiles.simplification distance The
+  * `simplify_distance` value works in integer space over a 4096 pixel grid and uses
+  * the [Douglas-Peucker algorithm](https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm).
+  * (used when rendering a vector tile)
+- * @param {Object} [options.variables] Mapnik 3.x ONLY: A javascript object 
+- * containing key value pairs that should be passed into Mapnik as variables 
+- * for rendering and for datasource queries. For example if you passed 
++ * @param {Object} [options.variables] Mapnik 3.x ONLY: A javascript object
++ * containing key value pairs that should be passed into Mapnik as variables
++ * for rendering and for datasource queries. For example if you passed
+  * `vtile.render(map,image,{ variables : {zoom:1} },cb)` then the `@zoom`
+  * variable would be usable in Mapnik symbolizers like `line-width:"@zoom"`
+- * and as a token in Mapnik postgis sql sub-selects like 
++ * and as a token in Mapnik postgis sql sub-selects like
+  * `(select * from table where some_field > @zoom)` as tmp (used when rendering a vector tile)
+- * @param {Boolean} [options.process_all_rings] if `true`, don't assume winding order and ring order of 
++ * @param {Boolean} [options.process_all_rings] if `true`, don't assume winding order and ring order of
+  * polygons are correct according to the [`2.0` Mapbox Vector Tile specification](https://github.com/mapbox/vector-tile-spec)
+  * (used when rendering a vector tile)
+  * @returns {mapnik.Map} rendered image tile
+@@ -1714,7 +1716,7 @@ struct vector_tile_baton_t {
+  * var vtile = new mapnik.VectorTile(9,112,195);
+  * map.render(vtile, {}, function(err, vtile) {
+  *     if (err) throw err;
+- *     console.log(vtile); // => vector tile object with data from xml 
++ *     console.log(vtile); // => vector tile object with data from xml
+  * });
+  */
+ NAN_METHOD(Map::render)
+--- a/src/mapnik_memory_datasource.cpp
++++ b/src/mapnik_memory_datasource.cpp
+@@ -46,6 +46,7 @@ MemoryDatasource::~MemoryDatasource()
+ 
+ NAN_METHOD(MemoryDatasource::New)
+ {
++    std::clog << "WARNING: MemoryDatasource is deprecated and will be removed in node-mapnik >= 3.7.x\n";
+     if (!info.IsConstructCall())
+     {
+         Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword");
+@@ -112,7 +113,9 @@ v8::Local<v8::Value> MemoryDatasource::N
+     MemoryDatasource* d = new MemoryDatasource();
+     d->datasource_ = ds_ptr;
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(d);
+-    return scope.Escape( Nan::New(constructor)->GetFunction()->NewInstance(1, &ext));
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new MemoryDatasource instance");
++    return scope.Escape(maybe_local.ToLocalChecked());
+ }
+ 
+ NAN_METHOD(MemoryDatasource::parameters)
+--- a/src/mapnik_projection.cpp
++++ b/src/mapnik_projection.cpp
+@@ -10,7 +10,7 @@ Nan::Persistent<v8::FunctionTemplate> Pr
+ 
+ /**
+  * **`mapnik.Projection`**
+- * 
++ *
+  * A geographical projection: this class makes it possible to translate between
+  * locations in different projections
+  *
+@@ -79,7 +79,7 @@ NAN_METHOD(Projection::New)
+             lazy = lazy_opt->BooleanValue();
+         }
+     }
+-            
++
+     try
+     {
+         Projection* p = new Projection(TOSTR(info[0]), lazy);
+--- a/src/mapnik_vector_tile.cpp
++++ b/src/mapnik_vector_tile.cpp
+@@ -1396,8 +1396,9 @@ NAN_METHOD(VectorTile::layer)
+         }
+     }
+     v8::Local<v8::Value> ext = Nan::New<v8::External>(v);
+-    v8::Local<v8::Object> vt_obj = Nan::New(constructor)->GetFunction()->NewInstance(1, &ext);
+-    info.GetReturnValue().Set(vt_obj);
++    Nan::MaybeLocal<v8::Object> maybe_local = Nan::NewInstance(Nan::New(constructor)->GetFunction(), 1, &ext);
++    if (maybe_local.IsEmpty()) Nan::ThrowError("Could not create new Layer instance");
++    else info.GetReturnValue().Set(maybe_local.ToLocalChecked());
+     return;
+ }
+ 
+--- /dev/null
++++ b/test/data/images/san-marino.svg
+@@ -0,0 +1,92 @@
++<svg xmlns="http://www.w3.org/2000/svg" height="480" width="640" viewBox="0 0 640 480">
++  <g fill-rule="evenodd" stroke-width="1pt">
++    <path fill="#19b6ef" d="M0 240h640v240H0z"/>
++    <path fill="#fff" d="M0 0h640v240H0z"/>
++  </g>
++  <path d="M317.07 339.221c52.45-39.239 108.96-119.306 42.74-161.41-12.336-2.388-26.107-1.672-32.713 3.582-3.501-1.99-6.288-1.83-9.79 1.91-2.466-3.025-4.935-4.379-10.028-2.865-10.188-5.173-19.42-6.288-31.517-3.105-57.623 34.622-22.366 116.76 41.308 161.888z" fill-rule="evenodd" stroke="#7d6c00" stroke-width="2.3686254" fill="#fd0"/>
++  <g stroke="#3a9d4f">
++    <path stroke-linejoin="round" d="M414.08 250.106s5.903-7.939 6.106-7.939c5.904-3.46 6.515-7.938 6.515-7.938 5.903-1.833 4.07-6.718 4.477-7.328 2.852-3.053 1.833-6.108 1.426-7.126 0-.812 2.036-8.345-.814-9.362.135-8.008-4.818-7.261-8.754-2.036-4.207 1.221-5.157 4.682-3.664 8.55-5.497 0-5.7 7.939-4.071 12.416-7.328-.203-3.257 7.939-3.461 8.347-2.442 1.221 1.832 12.824 2.24 12.416zM367.857 318.3l3.664 2.239c.746 2.781 3.325 4.547 5.294 4.072.95 4.274 5.563 3.665 8.956 1.221 2.714 3.936 [...]
++    <path stroke-linejoin="round" d="M404.502 266.397c-4.14-3.122-6.446-6.853-5.7-10.586-2.713-3.664-4.614-5.903-2.035-9.16 0 0-2.036-7.329-2.036-7.532-5.292-2.035-3.053-6.513-1.629-8.142-2.51-3.461-2.578-7.126-.203-10.382-.068-6.515 4.546-4.071 8.345 0 0 0 6.311 4.479 1.63 8.55 4.681 1.629 6.107 5.698 3.46 7.327 4.071 1.833 4.681 5.497 2.442 7.94 4.14 3.326 2.579 7.465 3.868 11.196l-8.142 10.789z" fill-rule="evenodd" stroke-width="2.3686254" fill="#4fd46b"/>
++    <path stroke-linejoin="round" d="M411.831 236.064c-.203-.203-6.92-8.753-5.089-9.364-.406-2.647-2.441-5.497-1.22-8.142-3.325-3.325-3.394-7.26-.815-10.38-2.239-3.054-1.221-7.125 1.832-9.772-.95-5.022 2.579-6.175 5.7-7.126 2.307-8.075 6.038-5.971 8.142.203 3.19 2.782 2.715 6.99 1.63 10.18 3.799 2.578 1.492 5.766-.204 7.124l-9.976 27.277z" fill-rule="evenodd" stroke-width="2.3686254" fill="#4fd46b"/>
++    <path stroke-linejoin="round" d="M410.815 193.106l-5.7-5.7c1.473-3.02 2.659-8.344-1.627-10.789-2.364-5.757-14.182-12.892-16.083.815-1.799-4.136-5.563-8.21-8.345-3.46-6.175-5.292-9.5-3.665-6.311 3.053 0 0-2.848 4.478 4.682 7.939.611.61-2.442 8.142 6.515 8.345-1.696 2.579 1.086 6.175 4.682 5.903-2.579 3.19 1.764 6.583 4.477 5.294-1.154 3.528-1.086 5.225 3.868 5.7l5.497 6.31 4.477 6.106 3.868-29.516z" fill-rule="evenodd" stroke-width="2.3686254" fill="#4fd46b"/>
++    <path d="M414.28 246.508c.288-.288 10.938-24.757 12.378-32.243M415.43 203.05s1.726 19.864-3.167 34.545M382.615 182.895s21.879 21.015 23.893 29.651M397.873 180.596s1.439 17.274 7.484 34.259M436.45 243.343s-21.879 18.425-32.53 34.545M415.712 307.84s-28.788 4.03-41.454 4.318M406.218 320.215s-35.698-.864-38.29-3.454M388.361 273.859c0 .287-18.136 30.226-18.712 40.015" stroke-linecap="round" stroke-width="2.2203781" fill="none"/>
++  </g>
++  <path d="M316.87 333.441c-37.768-35.624-76.454-102.482-37.972-136.27 6.84 3.88 14.903.409 26.03-3.98 3.368 3.674 7.654 4.594 11.942 1.837 4.797 2.042 8.37.408 10.718-2.144 10.922 6.33 24.906 9.596 28.172 3.37 37.87 35.93-.511 103.095-38.89 137.187z" fill-rule="evenodd" stroke="#7d6c00" stroke-width="2.3686254" fill="#65c7ff"/>
++  <path d="M317.086 332.408c-16.219-16.307-31.017-34.385-42.347-57.66 1.939-1.632 2.84-2.138 3.861-4.997 5.818.818 8.88 1.021 16.536-.306 1.53 5.717 1.837 10.514 5.511 15.311l7.656-15.005c5.205 1.226 11.637 1.533 16.535 0 3.165 4.288 2.042 10.72 7.656 15.618 3.368-9.9 6.738-10.615 10.106-15.924 5.002 1.736 8.167 1.021 12.25-.307 2.143 2.45 1.072 2.41 4.975 6.007-10.233 20.32-24.265 40.728-42.739 57.263z" fill-rule="evenodd" fill="#8fc753"/>
++  <path d="M272.65 164.304a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM269.158 156.594a3.346 3.346 0 1 1-6.691 0 3.346 3.346 0 0 1 6.691 0zM265.085 149.465a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM262.321 142.482a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM262.757 134.918a3.346 3.346 0 1 1-6.691 0 3.346 3.346 0 0 1 6.691 0zM280.42 122.407a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0z" fill-rule="evenodd" stroke="#000" stroke-width="1.1110219000000001 [...]
++  <path d="M273.814 123.571a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM266.54 127.935a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM288.943 122.552a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM298.254 123.28a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM306.546 122.843a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0z" fill-rule="evenodd" stroke="#000" stroke-width="1.1110219000000001" fill="#fff"/>
++  <path d="M325.874 117.504a8.583 8.583 0 1 1-17.166 0 8.583 8.583 0 0 1 17.166 0z" fill-rule="evenodd" stroke="#7d6c00" stroke-width="1.110941" fill="#fd0"/>
++  <path d="M334.913 122.698a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM343.642 123.425a3.346 3.346 0 1 1-6.691 0 3.346 3.346 0 0 1 6.691 0zM352.08 122.988a3.346 3.346 0 1 1-6.693 0 3.346 3.346 0 0 1 6.692 0zM359.207 122.698a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM368.082 123.716a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM375.064 128.08a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0z" fill-rule="evenodd" stroke="#000" stroke-width="1.1110219000000001 [...]
++  <path d="M269.414 151.697c2.85 5.42 5.698 11.05 8.548 16.47h79.23l9.174-15.846c-5.352-3.683-9.035-6.533-16.68-4.795-4.31-6.185-9.035-7.366-16.054-6.671-2.086-2.154-3.963-3.475-7.508-3.961l-16.678.416c-4.38.416-7.716 3.753-7.924 3.753-7.09-.835-13.552-.627-15.22 6.254-6.463-1.599-11.05.14-16.888 4.38z" fill-rule="evenodd" stroke="#ac0000" stroke-width="2.3686254" fill="#e40000"/>
++  <path d="M377.974 135.354a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM378.556 143.21a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM376.082 150.484a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM373.027 156.448a3.346 3.346 0 1 1-6.692 0 3.346 3.346 0 0 1 6.692 0zM369.39 164.013a3.346 3.346 0 1 1-6.69 0 3.346 3.346 0 0 1 6.69 0z" fill-rule="evenodd" stroke="#000" stroke-width="1.1110219000000001" fill="#fff"/>
++  <path d="M322.566 154.424a4.946 4.946 0 1 1-9.893 0 4.946 4.946 0 0 1 9.893 0z" fill-rule="evenodd" stroke="#000" stroke-width="1.1105424000000002" fill="#fff"/>
++  <path d="M323.546 143.045a5.964 5.964 0 1 1-11.93 0 5.964 5.964 0 0 1 11.93 0z" fill-rule="evenodd" stroke="#000" stroke-width="1.11051072" fill="#fff"/>
++  <path d="M322.685 131.995a5.383 5.383 0 1 1-10.765 0 5.383 5.383 0 0 1 10.765 0z" fill-rule="evenodd" stroke="#000" stroke-width="1.10935854" fill="#fff"/>
++  <path d="M315.487 109.055c0-.926-.028-4.165.037-4.295l-3.572-.064.102-3.175 3.1-.037.037-2.775h4.395v2.544h3.47l-.072 3.378-3.6-.037-.03 4.526-3.867-.065z" fill-rule="evenodd" stroke="#7d6c00" stroke-width="1.1110219000000001" fill="#fd0"/>
++  <path d="M277.56 168.17c-7.092-12.023-17.51-28.367-11.053-35.444 8.955-10.143 29.953-.973 43.367-6.881.972 11.468-2.224 30.44 2.92 34.403l-4.796 4.17c-2.92-3.753-8.418-8.782-15.22.208-3.892-3.403-8.316-2.805-10.4 1.72-1.982.267-1.867 1.06-4.819 1.824zM357.68 167.754c7.09-12.023 17.51-28.367 11.051-35.444-8.955-10.143-29.952-.973-43.366-6.882-.973 11.469 2.223 30.441-2.92 34.404l4.795 4.17c4.614-6.489 10.373-6.699 15.22.207 3.893-3.403 7.925-2.936 10.4 1.721 1.983.267 1.868 1.06 4.82 1 [...]
++  <path d="M277.343 177.132c28.495-2.918 54.904-1.877 79.23 0l3.127-8.967c-27.66-5.003-46.773-5.628-82.982-.624l.625 9.59z" fill-rule="evenodd" stroke="#7d6c00" stroke-width="2.3686254" fill="#fd0"/>
++  <path d="M314.121 329.377c.205-1.43.408-2.762.613-4.191 2.834.763 4.996.468 7.35-.402.815-1.225 1.633-2.45 2.45-3.676l-1.838-2.142c-1.615.348-2.941 1.85-3.98 3.158-1.628.077-3.064-.71-4.595-1.016l-1.53-6.43c-1.52-1.795-4.671-1.668-3.982 1.531l.307 2.45c.613 1.531.841 3.639 1.837 4.785v2.511c1.123 1.141 2.246 2.28 3.368 3.422zM315.337 311.087c-2.13 1.056-4.659-.78-7.349-1.837-2.45-.168-4.419 1.872-7.349 1.224.535-1.59 1.837-1.837 2.757-2.756-.673-4.131 1.53-5.512 2.144-5.512.61 0 3.061 [...]
++  <path d="M300.779 366.089c7.066-11.472 56.259-34.508 102.422-84.251-46.99 45.243-76.357 56.35-114.812 83.974l12.39.277z" fill-rule="evenodd" stroke="#e9bf00" stroke-width="2.3686254" fill="#ffe100"/>
++  <path d="M368.406 313.186a3.582 3.582 0 1 1-7.163 0 3.582 3.582 0 0 1 7.163 0zM402.786 278.323a4.06 4.06 0 1 1-8.118 0 4.06 4.06 0 0 1 8.118 0zM414.252 248.713a3.582 3.582 0 1 1-7.163 0 3.582 3.582 0 0 1 7.163 0zM403.02 210.28a3.582 3.582 0 1 1-7.164 0 3.582 3.582 0 0 1 7.164 0z" fill-rule="evenodd" stroke="#68300e" stroke-width="1.1110219000000001" fill="#9d4916"/>
++  <path d="M279.125 269.595v-15.148l-1.54-1.283v-3.594l2.824-.257.513-16.945-1.797-1.028-.257-2.823s2.054.77 2.054.257.513-3.339.513-3.339-1.282-.256-1.282-.77 1.539-1.796 1.539-1.796-.77-.772-1.026-1.285-.77-2.823-.77-2.823l.77-2.825-.513-1.54-1.285-2.311 1.798-1.797s-.513-2.31-.513-2.824 1.282-2.567 1.539-2.825c.258-.256 2.312-3.08 2.312-3.08l4.364-1.027 5.135.77 2.824 1.798.513 4.62s-.513 2.824-.77 2.824-2.31 1.028-2.31 1.028-2.569.256-2.825 0 .77 3.081.77 3.081v3.08l-.256 3.851s0 1. [...]
++  <path fill-rule="evenodd" d="M282.923 269.495v-11.938h6.686v12.416l-6.686-.478zM314.438 270.444l.238-12.178h5.97v11.938l-6.208.24zM345.486 270.211l-.478-11.46 6.448-.24v11.94l-5.97-.24zM284.588 234.149h3.82v6.208h-3.82zM314.92 234.399h5.254v5.97h-5.253zM345.953 234.865h4.537v5.73h-4.537z"/>
++  <path d="M286.57 206.965c4.108 4.62 4.365 4.62 4.365 4.62M317.12 206.965c.769 1.539 2.053 4.877 3.594 5.133M349.984 207.73s1.284 3.595 3.081 4.108" stroke="#a8a8a8" stroke-width="1.1110219000000001" fill="none"/>
++  <path d="M282.206 194.022c12.012-3.883-2.806-11.648-5.267 0-3.886.628-4.389 3.511-12.789 2.259-20.313 33.102-5.267 86.518 54.169 141.816-106.457-90.594-63.194-157.604-33.714-155.077 16.034 1.096 7.945 21.096-2.399 11.002z" fill-rule="evenodd" fill="#b97700"/>
++  <path d="M285.554 177.049s9.781 2.633 9.781 6.77M295.332 176.299s6.771 3.008 8.275 5.642M348.751 177.432s-8.653 1.129-10.534 3.76M335.575 178.181s-4.888 4.138-4.514 5.265M334.46 196.237c-.753-.376-4.138-4.89-3.387-10.533M301.345 193.24s2.257-2.634 2.257-7.525M317.153 183.828l.376 10.909M326.93 193.24c0-.754 3.01-7.9-.376-11.286M306.242 180.447s-2.633 7.147-.75 13.165M325.431 186.843s-4.137 1.128-6.02 3.01M307.742 187.959c0-.375 4.514-1.128 6.018 1.506" stroke="#7d6c00" stroke-width="2 [...]
++  <path d="M300.63 301.86c.19.096 3.745-.674 3.745-2.403 1.826-1.152.48-4.419.48-4.419l-3.361-.673-4.613-5.187c-.223-1.6.322-3.104-.671-4.802-3.17.833-4.995 3.49-6.053 6.531.77.962.866 2.018 2.307 2.882 1.504.257 2.528-.64 3.938-.383.736 1.28.51 2.37.767 3.555 1.923 1.344 2.307 3.266 3.46 4.898zM296.498 279.672v-6.148l-4.419-.193c-.545.93-1.57 1.378-2.21 2.21l-3.074 1.538c1.281 1.537 2.85 2.402 3.843 3.17 2.242.673 4.1.673 5.86-.577zM282.656 288.8l-2.402-4.036c1.473-.48 3.33-.288 4.707. [...]
++  <path d="M353.115 193.19c-12.011-3.884 2.807-11.65 5.267 0 3.886.627 4.39 3.51 12.79 2.258 20.313 33.102 5.266 86.518-54.17 141.816 106.457-90.594 63.194-157.604 33.715-155.077-16.034 1.096-7.946 21.096 2.398 11.002z" fill-rule="evenodd" fill="#b97700"/>
++  <path d="M354.331 284.67c-.191 0-3.073 2.112-3.073 2.112-1.378.544-2.753 1.089-4.13 1.634l-4.42.095-.961-3.074 3.363-2.978c-2.85-.416-5.7.705-7.974 2.787 0 0 0 3.361 1.922 4.995 1.153 1.44 4.514 4.035 4.514 4.035 2.114.416 4.131.063 5.476-1.058 1.76-2.85 3.523-5.699 5.283-8.549zM331.078 314.835c1.443.385 11.337-12.776 11.337-12.776-.865-2.465-2.787-4.259-4.9-5.38 0 0-4.805 5.667-4.9 7.589-.767 1.729-2.976 8.357-2.017 9.223-.096.192-.48 2.88.48 1.344z" fill-rule="evenodd" fill="#c76e2e"/>
++  <path stroke-linejoin="round" d="M266.366 317.4c-14.817-12.887-34.809-19.991-62.716-10.35 7.51 3.248 15.628 4.364 22.529 7.915l40.187 2.435z" fill-rule="evenodd" stroke="#004100" stroke-width="2.3686254" fill="#006800"/>
++  <path d="M223.44 308.256c29.227.608 37.752 7.913 36.23 6.696" stroke="#00a400" stroke-linecap="round" stroke-width="2.2203781" fill="none"/>
++  <path stroke-linejoin="round" d="M266.965 318.916c-8.728 1.724-20.804 10.154-24.356 9.741-9.54-1.11-18.454-4.975-27.704-7.915-3.842-1.221-7.713 0-11.57 0 32.78-15.526 43.943-13.396 63.63-1.826z" fill-rule="evenodd" stroke="#004100" stroke-width="2.2203781" fill="#006800"/>
++  <path stroke-linejoin="round" d="M245.361 296.08s-10.959 1.52-15.83 1.825c-4.873-.303-11.955-4.842-19.79-13.09-4.088-4.48-13.395-3.958-13.395-3.958 20.602-4.365 36.634-.204 49.015 15.222zM230.436 274.775c-14.92-.914-33.49-14.308-37.751-30.139-.002.202 5.479 3.45 4.566 4.263 24.457 6.19 26.081 11.161 33.185 25.876zM255.405 300.344c2.13-13.498 2.74-22.427-3.653-30.444-5.277-6.09-6.596-9.743-10.35-18.268-1.116 17.76-4.974 32.474 14.003 48.712zM231.952 262.899c11.06-16.136 12.99-28.314 11 [...]
++  <path stroke-linejoin="round" d="M222.225 184.96c11.06 16.136 9.336 31.36 7.61 50.54-.305-1.523-3.958-10.96-4.26-10.96-16.441-10.351-5.48-29.534-3.35-39.58z" fill-rule="evenodd" stroke="#004100" stroke-width="2.3686254" fill="#006800"/>
++  <path stroke-linejoin="round" d="M231.353 209.93c26.79-13.498 16.438-30.648 21.31-43.84-18.57 13.802-21.006 28.515-21.31 43.84z" fill-rule="evenodd" stroke="#004100" stroke-width="2.3686254" fill="#006800"/>
++  <path d="M235 206.581c3.35-9.437 10.048-25.573 10.656-25.573M227.088 226.37c-.608-6.7-3.956-24.662-4.26-26.488" stroke="#00a400" stroke-linecap="round" stroke-width="2.2203781" fill="none"/>
++  <path stroke-linejoin="round" d="M228.304 256.502c-14.92-.914-31.055-21.31-35.316-37.141-.001.201 5.479 3.45 4.566 4.262 21.412 9.538 23.646 18.165 30.75 32.88zM223.874 242.494c-11.06-16.136-12.99-28.314-11.264-47.494.305 1.522 3.958 10.96 4.261 10.96 16.44 10.35 9.133 26.488 7.003 36.534zM233.785 214.194c27.703-12.28 19.178-25.167 27.399-38.665-18.571 13.802-27.095 23.34-27.4 38.665z" fill-rule="evenodd" stroke="#004100" stroke-width="2.3686254" fill="#006800"/>
++  <path d="M235 211.445c11.266-11.265 15.223-20.703 15.223-20.703" stroke="#00a400" stroke-linecap="round" stroke-width="2.2203781" fill="none"/>
++  <g fill-rule="evenodd">
++    <path d="M333.56 366.355l13.49.275c-44.787-41.942-130.599-60.205-118.667-137.39-12.298 83.701 70.117 91.41 105.177 137.115z" stroke="#e9bf00" stroke-width="2.3686254" fill="#ffe100"/>
++    <path d="M235.417 212.661a4.298 4.298 0 1 1-8.596 0 4.298 4.298 0 0 1 8.596 0zM232.785 236.297a4.06 4.06 0 1 1-8.118 0 4.06 4.06 0 0 1 8.118 0zM236.6 269.978a3.582 3.582 0 1 1-7.164 0 3.582 3.582 0 0 1 7.164 0zM267.876 307.223a3.582 3.582 0 1 1-7.163 0 3.582 3.582 0 0 1 7.163 0zM272.412 317.907a3.582 3.582 0 1 1-7.163 0 3.582 3.582 0 0 1 7.163 0z" stroke="#68300e" stroke-width="1.1110219000000001" fill="#9d4916"/>
++  </g>
++  <g fill-rule="evenodd" fill="#fff">
++    <g stroke="#000" stroke-width=".667">
++      <path d="M288.203 349.032c-2.355-2.134-3.853-3.503-4.777-5.828l-14.044-1.528c-.063 2.675-.126 5.349-.191 8.024l19.012-.668z" stroke-width="1.1110219000000001"/>
++      <path stroke-linejoin="round" d="M185.313 339.57c8.157 1.507 20.456-.752 24.472 4.518 4.822 5.465-15.093 13.872-12.241 18.6 6.16 6.517 12.5 3.83 19.394.226 1.624-3.523 2.878-9.804 3.766-11.672-2.51-5.773-9.253-8.601-7.53-17.32 11.37-4.249 33.23-3.897 35.583-2.258 1.848 3.623.187 5.273.564 8.16-1.883 3.64-6.728 9.81-6.738 13.074 11.93 4.203 15.074-.648 25.806-.363 12.575.155 20.225 3.531 22.955-1.467-1.87-4.315-13.403-.805-17.78-3.577-2.19-.74-3.604-2.5-5.496-4.44s-7.21-2.04-8.007- [...]
++      <path d="M184.732 337.954a3.63 3.63 0 1 1-7.26 0 3.63 3.63 0 0 1 7.26 0zM183.78 355.911a3.63 3.63 0 1 1-7.26 0 3.63 3.63 0 0 1 7.26 0z" stroke-width="1.1110219000000001"/>
++    </g>
++    <g stroke="#000" stroke-width=".667">
++      <path d="M346.253 349.097c2.355-2.134 3.852-3.503 4.777-5.828l14.043-1.528.192 8.024-19.012-.668z" stroke-width="1.1110219000000001"/>
++      <path stroke-linejoin="round" d="M449.143 339.636c-8.157 1.506-20.457-.753-24.473 4.517-4.822 5.465 15.093 13.872 12.242 18.6-6.16 6.517-12.5 3.83-19.394.226-1.624-3.523-2.878-9.804-3.766-11.671 2.51-5.774 9.253-8.602 7.53-17.32-11.371-4.25-33.23-3.898-35.584-2.26-1.847 3.624-.187 5.274-.563 8.161 1.882 3.64 6.728 9.81 6.738 13.074-11.93 4.203-15.075-.648-25.807-.363-12.574.155-20.225 3.531-22.955-1.467 1.87-4.315 13.404-.805 17.781-3.577 2.19-.74 3.603-2.5 5.496-4.44s7.21-2.04 8. [...]
++      <path d="M449.723 338.02a3.63 3.63 0 1 0 7.261 0 3.63 3.63 0 0 0-7.26 0zM450.675 355.976a3.63 3.63 0 1 0 7.26 0 3.63 3.63 0 0 0-7.26 0z" stroke-width="1.1110219000000001"/>
++    </g>
++    <path d="M316.986 329.343c-3.231-.606-4.38-.433-6.57-.65-1.715 5.271-3.427 10.541-5.141 15.812 7.938.716 15.29.716 15.29.651-4.816-.976-3.644-15.748-3.579-15.813z"/>
++  </g>
++  <g font-size="9" font-family="Trebuchet MS" font-weight="bold">
++    <text y="344.274" x="448.605" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="344.274" x="448.605">L</tspan>
++    </text>
++    <text y="344.622" x="453.64" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="344.622" x="453.64">I</tspan>
++    </text>
++    <text y="345.056" x="456.678" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="345.056" x="456.678">B</tspan>
++    </text>
++    <text y="345.49" x="462.58" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="345.49" x="462.58">E</tspan>
++    </text>
++    <text y="345.576" x="468.309" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="345.576" x="468.309">R</tspan>
++    </text>
++    <text y="345.403" x="473.952" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="345.403" x="473.952">T</tspan>
++    </text>
++    <text y="344.535" x="479.247" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="344.535" x="479.247">A</tspan>
++    </text>
++    <text y="344.274" x="485.497" transform="translate(-464.91 -233.28) scale(1.6657)">
++      <tspan y="344.274" x="485.497">S</tspan>
++    </text>
++  </g>
++  <path d="M231.353 318.616c10.047 1.218 24.052.304 30.14-.001M216.128 284.203c8.525 6.698 27.096 10.654 26.791 10.654M253.573 296.696c-2.74-14.004-5.783-17.353-8.219-26.183M201.82 254.67c14.31 6.393 16.44 10.654 25.573 17.047M232.569 257.718c1.219-17.355 3.654-21.922 7.917-25.88M201.82 229.718c5.177 5.785 22.225 23.746 22.225 23.746M217.044 213.877c6.395 4.566 6.395 21.005 6.395 21.005" stroke="#00a400" stroke-linecap="round" stroke-width="2.2203781" fill="none"/>
++</svg>
+--- a/test/image.svg.test.js
++++ b/test/image.svg.test.js
+@@ -25,10 +25,10 @@ describe('mapnik.Image SVG', function()
+         }, /first argument is invalid, must be a Buffer/);
+         assert.throws(function() {
+           new mapnik.Image.fromSVGBytesSync(new Buffer('asdfasdf'));
+-        }, /SVG parse error:\s+Unable to parse 'asdfasdf'/);
++        }, /SVG error: unable to parse "asdfasdf"/);
+         assert.throws(function() {
+           mapnik.Image.fromSVGSync('./test/data/SVG_DOES_NOT_EXIST.svg');
+-        }, /SVG parse error:\s+Unable to open '.\/test\/data\/SVG_DOES_NOT_EXIST.svg'/);
++        }, /SVG error: unbale to open "\.\/test\/data\/SVG_DOES_NOT_EXIST\.svg"/);
+         assert.throws(function() {
+           mapnik.Image.fromSVGSync('./test/data/vector_tile/tile0.expected-svg.svg', 256);
+         }, /optional second arg must be an options object/);
+@@ -73,7 +73,7 @@ describe('mapnik.Image SVG', function()
+         }, /image created from svg must have a width and height greater then zero/);
+         mapnik.Image.fromSVGBytes(new Buffer('a'), { scale: 1 }, function(err, res) {
+             assert.ok(err);
+-            assert.ok(err.message.match(/Unable to parse 'a'/));
++            assert.ok(err.message.match(/SVG error: unable to parse "a"/));
+             var svgdata = "<svg width='1000000000000' height='1000000000000'><g id='a'><ellipse fill='#FFFFFF' stroke='#000000' stroke-width='4' cx='50' cy='50' rx='25' ry='25'/></g></svg>";
+             var buffer = new Buffer(svgdata);
+             mapnik.Image.fromSVGBytes(buffer, { scale: 1 }, function(err, img) {
+@@ -149,7 +149,7 @@ describe('mapnik.Image SVG', function()
+         done();
+       });
+     });
+-    
++
+     it('should err with async file w/o width or height as Bytes', function(done) {
+         var svgdata = "<svg width='0' height='0'><g id='a'><ellipse fill='#FFFFFF' stroke='#000000' stroke-width='4' cx='50' cy='50' rx='25' ry='25'/></g></svg>";
+         var buffer = new Buffer(svgdata);
+@@ -164,7 +164,7 @@ describe('mapnik.Image SVG', function()
+     it('should err with async invalid buffer', function(done) {
+       mapnik.Image.fromSVGBytes(new Buffer('asdfasdf'), function(err, svg) {
+         assert.ok(err);
+-        assert.ok(err.message.match(/SVG parse error:\s+Unable to parse 'asdfasdf'/));
++        assert.ok(err.message.match(/SVG error: unable to parse "asdfasdf"/));
+         assert.equal(svg, undefined);
+         done();
+       });
+@@ -173,7 +173,7 @@ describe('mapnik.Image SVG', function()
+     it('should err with async non-existent file', function(done) {
+       mapnik.Image.fromSVG('./test/data/SVG_DOES_NOT_EXIST.svg', function(err, svg) {
+         assert.ok(err);
+-        assert.ok(err.message.match(/SVG parse error:\s+Unable to open '.\/test\/data\/SVG_DOES_NOT_EXIST.svg'/));
++        assert.ok(err.message.match(/SVG error: unbale to open "\.\/test\/data\/SVG_DOES_NOT_EXIST\.svg"/));
+         assert.equal(svg, undefined);
+         done();
+       });
+@@ -196,7 +196,7 @@ describe('mapnik.Image SVG', function()
+         assert.equal(img.height(), 256);
+         assert.equal(img.encodeSync('png32').length, 17571);
+     });
+-    
++
+     it('#fromSVGSync load from SVG file - 2', function() {
+         var img = mapnik.Image.fromSVG('./test/data/vector_tile/tile0.expected-svg.svg');
+         assert.ok(img);
diff --git a/debian/patches/use-packaged-dependencies.patch b/debian/patches/use-packaged-dependencies.patch
index 5ecd507..dec79eb 100644
--- a/debian/patches/use-packaged-dependencies.patch
+++ b/debian/patches/use-packaged-dependencies.patch
@@ -4,7 +4,7 @@ Forwarded: not-needed
 
 --- a/binding.gyp
 +++ b/binding.gyp
-@@ -59,12 +59,7 @@
+@@ -35,12 +35,7 @@
          './mason_packages/.link/include/cairo',
          './src',
          "<!(nodejs -e \"require('nan')\")",

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/node-mapnik.git



More information about the Pkg-javascript-commits mailing list