diff --git a/.travis.yml b/.travis.yml index 206f01d..e29fc0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -128,6 +128,7 @@ matrix: # Overrides `script` to publish coverage data to codecov script: - export PATH=$(pwd)/mason_packages/.link/bin/:${PATH} + - PATH=`echo $PATH | sed -e 's/:\.\/node_modules\/\.bin//'` # remove relative path ^^ - which llvm-cov - curl -S -f https://codecov.io/bash -o codecov - chmod +x codecov diff --git a/CHANGELOG.md b/CHANGELOG.md index b81103f..a4f9dd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 0.2.0 + +- Upgrade to use N-API and remove nan/node-pre-gyp deps # 0.1.3 diff --git a/binding.gyp b/binding.gyp index e904562..d85699c 100644 --- a/binding.gyp +++ b/binding.gyp @@ -8,14 +8,14 @@ ['AR', '<(module_root_dir)/mason_packages/.link/bin/llvm-ar'], ['NM', '<(module_root_dir)/mason_packages/.link/bin/llvm-nm'] ], - 'includes': [ 'common.gypi' ], # brings in a default set of options that are inherited from gyp + 'includes': [ 'common.gypi'], # brings in a default set of options that are inherited from gyp 'variables': { # custom variables we use specific to this file 'error_on_warnings%':'true', # can be overriden by a command line variable because of the % sign using "WERROR" (defined in Makefile) - # Use this variable to silence warnings from mason dependencies and from NAN + # Use this variable to silence warnings from mason dependencies # It's a variable to make easy to pass to # cflags (linux) and xcode (mac) 'system_includes': [ - "-isystem <(module_root_dir)/= 1.4 < 2" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, "for-each": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", @@ -287,11 +396,25 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "fs-extra": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -332,6 +455,14 @@ "wide-align": "^1.1.0" } }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -348,8 +479,21 @@ "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } }, "has": { "version": "1.0.1", @@ -365,6 +509,16 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -447,26 +601,66 @@ "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", "dev": true }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, "jmespath": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", "dev": true }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, "requires": { "graceful-fs": "^4.1.6" } }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "lodash": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", @@ -516,6 +710,35 @@ "integrity": "sha512-+oasa2DfqArIMC7F71ca8CXpDt0rEcq9sJDv+AuhBCZJg+3m2ikDAs/oskEpPpUOwta1hH48Qr+0deCkyB/0Jg==", "dev": true }, + "mason-js-sdk": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/mason-js-sdk/-/mason-js-sdk-0.1.4.tgz", + "integrity": "sha1-vrC0YA4VBCT68uuUcEXl1YtweSE=", + "requires": { + "d3-queue": "^3.0.7", + "extfs": "0.0.7", + "fs-extra": "^4.0.2", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "npmlog": "^4.1.2", + "request": "^2.83.0", + "tar": "^4.0.2" + } + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -566,11 +789,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==" - }, "needle": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz", @@ -581,6 +799,11 @@ "sax": "^1.2.4" } }, + "node-addon-api": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.5.0.tgz", + "integrity": "sha512-YsL/8dpBWxCFj3wAVAa/ceN4TlT8lACK8EgpuN0q/4ecflWHDuKpodb+tt7Rx22r/6FJ2f+IT25XSsXnZGwYgA==" + }, "node-pre-gyp": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz", @@ -637,6 +860,11 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -702,6 +930,11 @@ "resolve-protobuf-schema": "^2.0.0" } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -713,6 +946,21 @@ "integrity": "sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w==", "dev": true }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -744,6 +992,33 @@ "util-deprecate": "~1.0.1" } }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", @@ -817,6 +1092,22 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "sshpk": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", + "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -900,11 +1191,52 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } }, "url": { "version": "0.10.3", @@ -929,6 +1261,21 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", diff --git a/package.json b/package.json index ea0ac38..a7d84f1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@mapbox/vtcomposite", - "version": "0.1.3", - "description": "Skeleton for bindings to C++ libraries for Node.js using NAN", + "version": "0.2.0", + "description": "Compositing operations on Vector Tiles (c++ bindings using N-API)", "url": "http://github.com/mapbox/vtcomposite", "main": "./lib/index.js", "repository": { @@ -16,8 +16,9 @@ "author": "Mapbox", "license": "ISC", "dependencies": { - "nan": "^2.11.1", - "node-pre-gyp": "^0.12.0" + "mason-js-sdk": "^0.1.4", + "node-pre-gyp": "^0.12.0", + "node-addon-api": "^1.5.0" }, "devDependencies": { "@mapbox/cloudfriend": "^1.9.1", diff --git a/src/feature_builder.hpp b/src/feature_builder.hpp index 1fa7bd0..6a593c7 100644 --- a/src/feature_builder.hpp +++ b/src/feature_builder.hpp @@ -98,15 +98,14 @@ struct line_string_handler bool first_ = true; }; -template -using annotated_ring = std::pair, vtzero::ring_type>; - template struct polygon_handler { - using geom_type = std::vector>; - polygon_handler(geom_type& geom, int dx, int dy, int zoom_factor) - : geom_(geom), + polygon_handler(vtzero::polygon_feature_builder& builder, mapbox::geometry::box const& bbox, int dx, int dy, int zoom_factor) + : builder_(builder), + ring_{}, + bbox_(bbox), + extent_({0, 0}, {0, 0}), dx_(dx), dy_(dy), zoom_factor_(zoom_factor) {} @@ -114,8 +113,8 @@ struct polygon_handler void ring_begin(std::uint32_t count) { first_ = true; - geom_.emplace_back(); - geom_.back().first.reserve(count); + ring_.clear(); + ring_.reserve(count); } void ring_point(vtzero::point const& pt) @@ -124,7 +123,21 @@ struct polygon_handler { CoordinateType x = pt.x * zoom_factor_ - dx_; CoordinateType y = pt.y * zoom_factor_ - dy_; - geom_.back().first.emplace_back(x, y); + ring_.emplace_back(x, y); + if (first_) + { + extent_.min.x = x; + extent_.max.x = x; + extent_.min.y = y; + extent_.max.y = y; + } + else + { + if (x < extent_.min.x) extent_.min.x = x; + if (x > extent_.max.x) extent_.max.x = x; + if (y < extent_.min.y) extent_.min.y = y; + if (y > extent_.max.y) extent_.max.y = y; + } cur_x_ = pt.x; cur_y_ = pt.y; first_ = false; @@ -133,16 +146,80 @@ struct polygon_handler void ring_end(vtzero::ring_type type) { - geom_.back().second = type; + if (type == vtzero::ring_type::outer) + { + if (!boost::geometry::intersects(extent_, bbox_)) + { + skip_ = true; + } + else + { + skip_ = false; + valid_ = true; + } + } + if (!skip_ && ring_.size() > 3) + { + // only clip if not fully within bbox + if (bbox_.min.x >= extent_.min.x && + bbox_.max.x <= extent_.max.x && + bbox_.min.y >= extent_.min.y && + bbox_.max.y <= extent_.max.y) + { + builder_.add_ring(static_cast(ring_.size())); + for (auto const& pt : ring_) + { + builder_.set_point(static_cast(pt.x), static_cast(pt.y)); + }; + } + else + { + // TODO: reuse this result memory? + std::vector> result; + if (type == vtzero::ring_type::inner) + { + boost::geometry::reverse(ring_); + } + boost::geometry::intersection(ring_, bbox_, result); + for (auto&& geom : result) + { + if (type == vtzero::ring_type::inner) + { + boost::geometry::reverse(geom); + } + for (auto const& ring : geom) + { + if (ring.size() > 3) + { + builder_.add_ring(static_cast(ring.size())); + for (auto const& pt : ring) + { + builder_.set_point(static_cast(pt.x), static_cast(pt.y)); + }; + } + } + } + } + } } - geom_type& geom_; + bool valid() const + { + return valid_; + } + + vtzero::polygon_feature_builder& builder_; + mapbox::geometry::linear_ring ring_; + mapbox::geometry::box const& bbox_; + mapbox::geometry::box extent_; int const dx_; int const dy_; int const zoom_factor_; CoordinateType cur_x_ = 0; CoordinateType cur_y_ = 0; bool first_ = true; + bool skip_ = false; + bool valid_ = false; }; } // namespace detail @@ -219,50 +296,13 @@ struct overzoomed_feature_builder } void apply_geometry_polygon(vtzero::feature const& feature) { - std::vector> rings; - vtzero::decode_polygon_geometry(feature.geometry(), detail::polygon_handler(rings, dx_, dy_, zoom_factor_)); - if (!rings.empty()) + vtzero::polygon_feature_builder feature_builder{layer_builder_}; + feature_builder.copy_id(feature); + detail::polygon_handler handler(feature_builder, bbox_, dx_, dy_, zoom_factor_); + vtzero::decode_polygon_geometry(feature.geometry(), handler); + if (handler.valid()) { - vtzero::polygon_feature_builder feature_builder{layer_builder_}; - feature_builder.copy_id(feature); - bool valid = false; - bool process = false; - for (auto& r : rings) - { - if (r.second == vtzero::ring_type::outer) - { - auto extent = mapbox::geometry::envelope(r.first); - process = boost::geometry::intersects(extent, bbox_); - } - if (process) - { - std::vector> result; - if (r.second == vtzero::ring_type::inner) boost::geometry::reverse(r.first); - // ^^ reverse inner rings before clipping as we're dealing with a disassembled polygon - boost::geometry::intersection(r.first, bbox_, result); - for (auto const& p : result) - { - for (auto const& ring : p) - { - if (ring.size() > 3) - { - valid = true; - feature_builder.add_ring(static_cast(ring.size())); - if (r.second == vtzero::ring_type::outer) - { - std::for_each(ring.begin(), ring.end(), [&feature_builder](auto const& pt) { feature_builder.set_point(static_cast(pt.x), static_cast(pt.y)); }); - } - else - { - // apply points in reverse to preserve original winding order of inner rings - std::for_each(ring.rbegin(), ring.rend(), [&feature_builder](auto const& pt) { feature_builder.set_point(static_cast(pt.x), static_cast(pt.y)); }); - } - } - } - } - } - } - if (valid) finalize(feature_builder, feature); + finalize(feature_builder, feature); } } diff --git a/src/module.cpp b/src/module.cpp index 9d189d0..72b9e37 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -1,9 +1,10 @@ #include "vtcomposite.hpp" -#include +#include -NAN_MODULE_INIT(init) +Napi::Object init(Napi::Env env, Napi::Object exports) { - Nan::SetMethod(target, "composite", vtile::composite); + exports.Set(Napi::String::New(env, "composite"), Napi::Function::New(env, vtile::composite)); + return exports; } -NODE_MODULE(module, init) // NOLINT +NODE_API_MODULE(module, init) // NOLINT diff --git a/src/module_utils.hpp b/src/module_utils.hpp index 87a9691..d0a8f73 100644 --- a/src/module_utils.hpp +++ b/src/module_utils.hpp @@ -1,28 +1,13 @@ #pragma once -#include +#include namespace utils { -/* -* This is an internal function used to return callback error messages instead of -* throwing errors. -* Usage: -* -* v8::Local callback; -* return CallbackError("error message", callback); // "return" is important to -* prevent duplicate callbacks from being fired! -* -* -* "inline" is important here as well. See for more contex: -* - https://github.com/mapbox/cpp/blob/master/glossary.md#inline-keyword -* - https://github.com/mapbox/node-cpp-skel/pull/52#discussion_r126847394 for -* context -* -*/ -inline void CallbackError(std::string message, v8::Local func) +inline Napi::Value CallbackError(std::string const& message, Napi::CallbackInfo const& info) { - Nan::Callback cb(func); - v8::Local argv[1] = {Nan::Error(message.c_str())}; - Nan::Call(cb, 1, argv); + Napi::Object obj = Napi::Object::New(info.Env()); + obj.Set("message", message); + auto func = info[info.Length() - 1].As(); + return func.Call({obj}); } -} // namespace utils \ No newline at end of file +} // namespace utils diff --git a/src/vtcomposite.cpp b/src/vtcomposite.cpp index 54f34ed..8744848 100644 --- a/src/vtcomposite.cpp +++ b/src/vtcomposite.cpp @@ -1,8 +1,8 @@ // vtcomposite #include "vtcomposite.hpp" +#include "feature_builder.hpp" #include "module_utils.hpp" #include "zxy_math.hpp" -#include "feature_builder.hpp" // gzip-hpp #include #include @@ -11,9 +11,9 @@ #include #include // geometry.hpp +#include #include #include -#include // stl #include @@ -26,14 +26,13 @@ struct TileObject TileObject(int z0, int x0, int y0, - v8::Local& buffer) + Napi::Buffer const& buffer) : z{z0}, x{x0}, y{y0}, - data{node::Buffer::Data(buffer), node::Buffer::Length(buffer)}, - buffer_ref{} + data{buffer.Data(), buffer.Length()}, + buffer_ref{Napi::Persistent(buffer)} { - buffer_ref.Reset(buffer.As()); } ~TileObject() @@ -45,15 +44,11 @@ struct TileObject TileObject(TileObject const&) = delete; TileObject& operator=(TileObject const&) = delete; - // non-movable - TileObject(TileObject&&) = delete; - TileObject& operator=(TileObject&&) = delete; - int z; int x; int y; vtzero::data_view data; - Nan::Persistent buffer_ref; + Napi::Reference> buffer_ref; }; struct BatonType @@ -67,10 +62,6 @@ struct BatonType BatonType(BatonType const&) = delete; BatonType& operator=(BatonType const&) = delete; - // non-movable - BatonType(BatonType&&) = delete; - BatonType& operator=(BatonType&&) = delete; - // members std::vector> tiles{}; int z{}; @@ -85,7 +76,7 @@ namespace { template struct build_feature_from_v1 { - build_feature_from_v1(FeatureBuilder& builder) + explicit build_feature_from_v1(FeatureBuilder& builder) : builder_(builder) {} bool operator()(vtzero::feature const& feature) @@ -106,7 +97,7 @@ struct build_feature_from_v1 template struct build_feature_from_v2 { - build_feature_from_v2(FeatureBuilder& builder) + explicit build_feature_from_v2(FeatureBuilder& builder) : builder_(builder) {} bool operator()(vtzero::feature const& feature) @@ -119,12 +110,12 @@ struct build_feature_from_v2 } // namespace -struct CompositeWorker : Nan::AsyncWorker +struct CompositeWorker : Napi::AsyncWorker { - using Base = Nan::AsyncWorker; + using Base = Napi::AsyncWorker; - CompositeWorker(std::unique_ptr&& baton_data, Nan::Callback* cb) - : Base(cb, "skel:standalone-async-worker"), + CompositeWorker(std::unique_ptr&& baton_data, Napi::Function& cb) + : Base(cb), baton_data_{std::move(baton_data)}, output_buffer_{std::make_unique()} {} @@ -206,7 +197,7 @@ struct CompositeWorker : Nan::AsyncWorker throw std::invalid_argument(os.str()); } } - std::string& tile_buffer = *output_buffer_.get(); + std::string& tile_buffer = *output_buffer_; if (baton_data_->compress) { std::string temp; @@ -221,284 +212,243 @@ struct CompositeWorker : Nan::AsyncWorker // LCOV_EXCL_START catch (std::exception const& e) { - SetErrorMessage(e.what()); + SetError(e.what()); } // LCOV_EXCL_STOP } - - void HandleOKCallback() override + void OnOK() override { - std::string& tile_buffer = *output_buffer_.get(); - Nan::HandleScope scope; - const auto argc = 2u; - v8::Local argv[argc] = { - Nan::Null(), - Nan::NewBuffer(&tile_buffer[0], - static_cast(tile_buffer.size()), - [](char*, void* hint) { - delete reinterpret_cast(hint); - }, - output_buffer_.release()) - .ToLocalChecked()}; - - // Static cast done here to avoid 'cppcoreguidelines-pro-bounds-array-to-pointer-decay' warning with clang-tidy - callback->Call(argc, static_cast*>(argv), async_resource); + std::string& tile_buffer = *output_buffer_; + Napi::HandleScope scope(Env()); + Napi::Value argv = Napi::Buffer::New(Env(), + const_cast(tile_buffer.data()), + tile_buffer.size(), + [](Napi::Env, char*, std::string* s) { + delete s; + }, + output_buffer_.release()); + + Callback().Call({Env().Null(), argv}); } std::unique_ptr const baton_data_; std::unique_ptr output_buffer_; }; -NAN_METHOD(composite) +Napi::Value composite(Napi::CallbackInfo const& info) { // validate callback function - v8::Local callback_val = info[info.Length() - 1]; - if (!callback_val->IsFunction()) + std::size_t length = info.Length(); + if (length == 0) + { + Napi::Error::New(info.Env(), "last argument must be a callback function").ThrowAsJavaScriptException(); + return info.Env().Null(); + } + Napi::Value callback_val = info[length - 1]; + if (!callback_val.IsFunction()) { - Nan::ThrowError("last argument must be a callback function"); - return; + Napi::Error::New(info.Env(), "last argument must be a callback function").ThrowAsJavaScriptException(); + return info.Env().Null(); } - v8::Local callback = callback_val.As(); + Napi::Function callback = callback_val.As(); // validate tiles - if (!info[0]->IsArray()) + if (!info[0].IsArray()) { - return utils::CallbackError("first arg 'tiles' must be an array of tile objects", callback); + return utils::CallbackError("first arg 'tiles' must be an array of tile objects", info); } - v8::Local tiles = info[0].As(); - unsigned num_tiles = tiles->Length(); + Napi::Array tiles = info[0].As(); + unsigned num_tiles = tiles.Length(); if (num_tiles <= 0) { - return utils::CallbackError("'tiles' array must be of length greater than 0", callback); + return utils::CallbackError("'tiles' array must be of length greater than 0", info); } std::unique_ptr baton_data = std::make_unique(num_tiles); - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - for (unsigned t = 0; t < num_tiles; ++t) { - v8::Local tile_val = tiles->Get(t); - if (!tile_val->IsObject()) + Napi::Value tile_val = tiles.Get(t); + if (!tile_val.IsObject()) { - return utils::CallbackError("items in 'tiles' array must be objects", callback); + return utils::CallbackError("items in 'tiles' array must be objects", info); } - v8::MaybeLocal maybe_tile_obj = tile_val->ToObject(isolate->GetCurrentContext()); - if (maybe_tile_obj.IsEmpty()) - { - return utils::CallbackError("items in 'tiles' can't be empty", callback); - } - v8::Local tile_obj = maybe_tile_obj.ToLocalChecked(); + Napi::Object tile_obj = tile_val.As(); // check buffer value - if (!tile_obj->Has(Nan::New("buffer").ToLocalChecked())) - { - return utils::CallbackError("item in 'tiles' array does not include a buffer value", callback); - } - v8::Local buf_val = tile_obj->Get(Nan::New("buffer").ToLocalChecked()); - if (buf_val->IsNull() || buf_val->IsUndefined()) + if (!tile_obj.Has(Napi::String::New(info.Env(), "buffer"))) { - return utils::CallbackError("buffer value in 'tiles' array item is null or undefined", callback); + return utils::CallbackError("item in 'tiles' array does not include a buffer value", info); } - v8::MaybeLocal maybe_buffer = buf_val->ToObject(isolate->GetCurrentContext()); - if (maybe_buffer.IsEmpty()) + Napi::Value buf_val = tile_obj.Get(Napi::String::New(info.Env(), "buffer")); + if (buf_val.IsNull() || buf_val.IsUndefined()) { - return utils::CallbackError("buffer value in 'tiles' array is empty", callback); + return utils::CallbackError("buffer value in 'tiles' array item is null or undefined", info); } - v8::Local buffer = maybe_buffer.ToLocalChecked(); - if (!node::Buffer::HasInstance(buffer)) + Napi::Object buffer_obj = buf_val.As(); + if (!buffer_obj.IsBuffer()) { - return utils::CallbackError("buffer value in 'tiles' array item is not a true buffer", callback); + return utils::CallbackError("buffer value in 'tiles' array item is not a true buffer", info); } + Napi::Buffer buffer = buffer_obj.As>(); // z value - if (!tile_obj->Has(Nan::New("z").ToLocalChecked())) - { - return utils::CallbackError("item in 'tiles' array does not include a 'z' value", callback); - } - v8::Local z_val = tile_obj->Get(Nan::New("z").ToLocalChecked()); - if (!z_val->IsInt32()) + if (!tile_obj.Has(Napi::String::New(info.Env(), "z"))) { - return utils::CallbackError("'z' value in 'tiles' array item is not an int32", callback); + return utils::CallbackError("item in 'tiles' array does not include a 'z' value", info); } - v8::Maybe maybe_z = z_val->Int32Value(isolate->GetCurrentContext()); - if (maybe_z.IsNothing()) + Napi::Value z_val = tile_obj.Get(Napi::String::New(info.Env(), "z")); + if (!z_val.IsNumber()) { - return utils::CallbackError("'z' value is nothing", callback); + return utils::CallbackError("'z' value in 'tiles' array item is not an int32", info); } - int z = maybe_z.FromJust(); + + int z = z_val.As().Int32Value(); if (z < 0) { - return utils::CallbackError("'z' value must not be less than zero", callback); + return utils::CallbackError("'z' value must not be less than zero", info); } // x value - if (!tile_obj->Has(Nan::New("x").ToLocalChecked())) - { - return utils::CallbackError("item in 'tiles' array does not include a 'x' value", callback); - } - v8::Local x_val = tile_obj->Get(Nan::New("x").ToLocalChecked()); - if (!x_val->IsInt32()) + if (!tile_obj.Has(Napi::String::New(info.Env(), "x"))) { - return utils::CallbackError("'x' value in 'tiles' array item is not an int32", callback); + return utils::CallbackError("item in 'tiles' array does not include a 'x' value", info); } - v8::Maybe maybe_x = x_val->Int32Value(isolate->GetCurrentContext()); - if (maybe_x.IsNothing()) + Napi::Value x_val = tile_obj.Get(Napi::String::New(info.Env(), "x")); + if (!x_val.IsNumber()) { - return utils::CallbackError("'x' value is nothing", callback); + return utils::CallbackError("'x' value in 'tiles' array item is not an int32", info); } - int x = maybe_x.FromJust(); + + int x = x_val.As().Int32Value(); if (x < 0) { - return utils::CallbackError("'x' value must not be less than zero", callback); + return utils::CallbackError("'x' value must not be less than zero", info); } // y value - if (!tile_obj->Has(Nan::New("y").ToLocalChecked())) + if (!tile_obj.Has(Napi::String::New(info.Env(), "y"))) { - return utils::CallbackError("item in 'tiles' array does not include a 'y' value", callback); + return utils::CallbackError("item in 'tiles' array does not include a 'y' value", info); } - v8::Local y_val = tile_obj->Get(Nan::New("y").ToLocalChecked()); - if (!y_val->IsInt32()) + Napi::Value y_val = tile_obj.Get(Napi::String::New(info.Env(), "y")); + if (!y_val.IsNumber()) { - return utils::CallbackError("'y' value in 'tiles' array item is not an int32", callback); + return utils::CallbackError("'y' value in 'tiles' array item is not an int32", info); } - v8::Maybe maybe_y = y_val->Int32Value(isolate->GetCurrentContext()); - if (maybe_y.IsNothing()) - { - return utils::CallbackError("'y' value is nothing", callback); - } - int y = maybe_y.FromJust(); + + int y = y_val.As().Int32Value(); if (y < 0) { - return utils::CallbackError("'y' value must not be less than zero", callback); + return utils::CallbackError("'y' value must not be less than zero", info); } + baton_data->tiles.push_back(std::make_unique(z, x, y, buffer)); } //validate zxy maprequest object - if (!info[1]->IsObject()) + if (!info[1].IsObject()) { - return utils::CallbackError("'zxy_maprequest' must be an object", callback); + return utils::CallbackError("'zxy_maprequest' must be an object", info); } - v8::Local zxy_maprequest = v8::Local::Cast(info[1]); + Napi::Object zxy_maprequest = info[1].As(); // z value of map request object - if (!zxy_maprequest->Has(Nan::New("z").ToLocalChecked())) - { - return utils::CallbackError("item in 'tiles' array does not include a 'z' value", callback); - } - v8::Local z_val_maprequest = zxy_maprequest->Get(Nan::New("z").ToLocalChecked()); - if (!z_val_maprequest->IsInt32()) + if (!zxy_maprequest.Has(Napi::String::New(info.Env(), "z"))) { - return utils::CallbackError("'z' value in 'tiles' array item is not an int32", callback); + return utils::CallbackError("item in 'tiles' array does not include a 'z' value", info); } - v8::Maybe maybe_z_maprequest = z_val_maprequest->Int32Value(isolate->GetCurrentContext()); - if (maybe_z_maprequest.IsNothing()) + Napi::Value z_val_maprequest = zxy_maprequest.Get(Napi::String::New(info.Env(), "z")); + if (!z_val_maprequest.IsNumber()) { - return utils::CallbackError("'z' value in 'tiles' array item is nothing", callback); + return utils::CallbackError("'z' value in 'tiles' array item is not an int32", info); } - int z_maprequest = maybe_z_maprequest.FromJust(); + + int z_maprequest = z_val_maprequest.As().Int32Value(); if (z_maprequest < 0) { - return utils::CallbackError("'z' value must not be less than zero", callback); + return utils::CallbackError("'z' value must not be less than zero", info); } baton_data->z = z_maprequest; // x value of map request object - if (!zxy_maprequest->Has(Nan::New("x").ToLocalChecked())) - { - return utils::CallbackError("item in 'tiles' array does not include a 'x' value", callback); - } - v8::Local x_val_maprequest = zxy_maprequest->Get(Nan::New("x").ToLocalChecked()); - if (!x_val_maprequest->IsInt32()) + if (!zxy_maprequest.Has(Napi::String::New(info.Env(), "x"))) { - return utils::CallbackError("'x' value in 'tiles' array item is not an int32", callback); + return utils::CallbackError("item in 'tiles' array does not include a 'x' value", info); } - v8::Maybe maybe_x_maprequest = x_val_maprequest->Int32Value(isolate->GetCurrentContext()); - if (maybe_x_maprequest.IsNothing()) + Napi::Value x_val_maprequest = zxy_maprequest.Get(Napi::String::New(info.Env(), "x")); + if (!x_val_maprequest.IsNumber()) { - return utils::CallbackError("'x' value in 'tiles' array item is nothing", callback); + return utils::CallbackError("'x' value in 'tiles' array item is not an int32", info); } - int x_maprequest = maybe_x_maprequest.FromJust(); + + int x_maprequest = x_val_maprequest.As().Int32Value(); if (x_maprequest < 0) { - return utils::CallbackError("'x' value must not be less than zero", callback); + return utils::CallbackError("'x' value must not be less than zero", info); } baton_data->x = x_maprequest; // y value of maprequest object - if (!zxy_maprequest->Has(Nan::New("y").ToLocalChecked())) - { - return utils::CallbackError("item in 'tiles' array does not include a 'y' value", callback); - } - v8::Local y_val_maprequest = zxy_maprequest->Get(Nan::New("y").ToLocalChecked()); - if (!y_val_maprequest->IsInt32()) + if (!zxy_maprequest.Has(Napi::String::New(info.Env(), "y"))) { - return utils::CallbackError("'y' value in 'tiles' array item is not an int32", callback); + return utils::CallbackError("item in 'tiles' array does not include a 'y' value", info); } - v8::Maybe maybe_y_maprequest = y_val_maprequest->Int32Value(isolate->GetCurrentContext()); - if (maybe_y_maprequest.IsNothing()) + Napi::Value y_val_maprequest = zxy_maprequest.Get(Napi::String::New(info.Env(), "y")); + if (!y_val_maprequest.IsNumber()) { - return utils::CallbackError("'y' value in 'tiles' array item is nothing", callback); + return utils::CallbackError("'y' value in 'tiles' array item is not an int32", info); } - int y_maprequest = maybe_y_maprequest.FromJust(); + + int y_maprequest = y_val_maprequest.As().Int32Value(); if (y_maprequest < 0) { - return utils::CallbackError("'y' value must not be less than zero", callback); + return utils::CallbackError("'y' value must not be less than zero", info); } baton_data->y = y_maprequest; if (info.Length() > 3) // options { - if (!info[2]->IsObject()) + if (!info[2].IsObject()) { - return utils::CallbackError("'options' arg must be an object", callback); + return utils::CallbackError("'options' arg must be an object", info); } - v8::Local options = info[2]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - if (options->Has(Nan::New("buffer_size").ToLocalChecked())) + + Napi::Object options = info[2].As(); + if (options.Has(Napi::String::New(info.Env(), "buffer_size"))) { - v8::Local bs_value = options->Get(Nan::New("buffer_size").ToLocalChecked()); - if (!bs_value->IsInt32()) - { - return utils::CallbackError("'buffer_size' must be an int32", callback); - } - v8::Maybe maybe_buffer_size = bs_value->Int32Value(isolate->GetCurrentContext()); - if (maybe_buffer_size.IsNothing()) + Napi::Value bs_value = options.Get(Napi::String::New(info.Env(), "buffer_size")); + if (!bs_value.IsNumber()) { - return utils::CallbackError("'buffer_size' is nothing", callback); + return utils::CallbackError("'buffer_size' must be an int32", info); } - int buffer_size = maybe_buffer_size.FromJust(); + + int buffer_size = bs_value.As().Int32Value(); if (buffer_size < 0) { - return utils::CallbackError("'buffer_size' must be a positive int32", callback); + return utils::CallbackError("'buffer_size' must be a positive int32", info); } baton_data->buffer_size = buffer_size; } - if (options->Has(Nan::New("compress").ToLocalChecked())) + if (options.Has(Napi::String::New(info.Env(), "compress"))) { - v8::Local comp_value = options->Get(Nan::New("compress").ToLocalChecked()); - if (!comp_value->IsBoolean()) - { - return utils::CallbackError("'compress' must be a boolean", callback); - } - v8::Maybe maybe_compress = comp_value->BooleanValue(isolate->GetCurrentContext()); - if (maybe_compress.IsNothing()) + Napi::Value comp_value = options.Get(Napi::String::New(info.Env(), "compress")); + if (!comp_value.IsBoolean()) { - return utils::CallbackError("'compress' is nothing", callback); + return utils::CallbackError("'compress' must be a boolean", info); } - baton_data->compress = maybe_compress.FromJust(); + + baton_data->compress = comp_value.As().Value(); } } - // enter the threadpool, then done in the callback function call the threadpool - auto* worker = new CompositeWorker{std::move(baton_data), new Nan::Callback{callback}}; - Nan::AsyncQueueWorker(worker); + auto* worker = new CompositeWorker{std::move(baton_data), callback}; + worker->Queue(); + return info.Env().Undefined(); } - } // namespace vtile diff --git a/src/vtcomposite.hpp b/src/vtcomposite.hpp index a767be0..7420f7e 100644 --- a/src/vtcomposite.hpp +++ b/src/vtcomposite.hpp @@ -1,8 +1,8 @@ #pragma once -#include +#include namespace vtile { -NAN_METHOD(composite); +Napi::Value composite(const Napi::CallbackInfo& info); } // namespace vtile diff --git a/test/vtcomposite-param-validation.test.js b/test/vtcomposite-param-validation.test.js index 841cf4e..9cdefea 100644 --- a/test/vtcomposite-param-validation.test.js +++ b/test/vtcomposite-param-validation.test.js @@ -7,8 +7,7 @@ var mvtFixtures = require('@mapbox/mvt-fixtures'); test('failure: fails without callback function', assert => { try { - -composite(); + composite(); } catch(err) { assert.ok(/last argument must be a callback function/.test(err.message), 'expected error message'); assert.end();