From 71b475edfd8c46a874658ac4a8ce6e21640a6c3f Mon Sep 17 00:00:00 2001 From: Richard Lau Date: Tue, 27 Mar 2018 11:43:43 -0400 Subject: [PATCH 1/6] tools: add node-report update script --- tools/update-node-report.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 tools/update-node-report.sh diff --git a/tools/update-node-report.sh b/tools/update-node-report.sh new file mode 100755 index 00000000000000..e0b2c6894be680 --- /dev/null +++ b/tools/update-node-report.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Shell script to update ESLint in the source tree to the latest release. + +# Depends on npm and node being in $PATH. + +# This script must be be in the tools directory when it runs because it uses +# $BASH_SOURCE[0] to determine directories to work in. + +cd "$( dirname "${BASH_SOURCE[0]}" )/../deps/" +rm -rf node-report +mkdir node-report-tmp +cd node-report-tmp +npm init --yes + +LATEST=`npm view node-report version` +wget "https://github.com/nodejs/node-report/archive/v${LATEST}.tar.gz" +tar xfz "v${LATEST}.tar.gz" + +cd "node-report-${LATEST}" +npm install --global-style --no-bin-links --production --no-package-lock --ignore-scripts + +# Install dmn if it is not in path. +type -P dmn || npm install -g dmn + +# Use dmn to remove some unneeded files. +dmn -f clean + +cd ../.. +mv "node-report-tmp/node-report-${LATEST}" node-report +rm -rf node-report-tmp/ From 5b0ec0c73be5574edbe8b6f54f9aa6f1adb2535e Mon Sep 17 00:00:00 2001 From: Richard Lau Date: Tue, 27 Mar 2018 12:49:29 -0400 Subject: [PATCH 2/6] deps: add node-report@2.2.1 --- deps/node-report/.gitignore | 45 + deps/node-report/.npmignore | 4 + deps/node-report/CHANGES.md | 144 + deps/node-report/CONTRIBUTING.md | 39 + deps/node-report/GOVERNANCE.md | 5 + deps/node-report/LICENCE.md | 13 + deps/node-report/MAINTAINER.md | 15 + deps/node-report/README.md | 128 + deps/node-report/binding.gyp | 33 + deps/node-report/demo/api_call.js | 37 + deps/node-report/demo/exception.js | 32 + deps/node-report/demo/fatalerror.js | 43 + deps/node-report/demo/loop.js | 58 + deps/node-report/index.js | 16 + deps/node-report/node_modules/nan/LICENSE.md | 13 + deps/node-report/node_modules/nan/README.md | 456 +++ .../node_modules/nan/include_dirs.js | 1 + deps/node-report/node_modules/nan/nan.h | 2761 +++++++++++++++++ .../node_modules/nan/nan_callbacks.h | 88 + .../node_modules/nan/nan_callbacks_12_inl.h | 512 +++ .../nan/nan_callbacks_pre_12_inl.h | 520 ++++ .../node_modules/nan/nan_converters.h | 72 + .../node_modules/nan/nan_converters_43_inl.h | 48 + .../nan/nan_converters_pre_43_inl.h | 42 + .../nan/nan_define_own_property_helper.h | 29 + .../nan/nan_implementation_12_inl.h | 399 +++ .../nan/nan_implementation_pre_12_inl.h | 263 ++ deps/node-report/node_modules/nan/nan_json.h | 166 + .../node_modules/nan/nan_maybe_43_inl.h | 369 +++ .../node_modules/nan/nan_maybe_pre_43_inl.h | 316 ++ deps/node-report/node_modules/nan/nan_new.h | 340 ++ .../node_modules/nan/nan_object_wrap.h | 155 + .../node_modules/nan/nan_persistent_12_inl.h | 132 + .../nan/nan_persistent_pre_12_inl.h | 242 ++ .../node_modules/nan/nan_private.h | 73 + .../node_modules/nan/nan_string_bytes.h | 305 ++ .../nan/nan_typedarray_contents.h | 90 + deps/node-report/node_modules/nan/nan_weak.h | 432 +++ .../node-report/node_modules/nan/package.json | 97 + .../node_modules/nan/tools/1to2.js | 412 +++ .../node_modules/nan/tools/README.md | 14 + .../node_modules/nan/tools/package.json | 19 + deps/node-report/package.json | 29 + deps/node-report/src/module.cc | 454 +++ deps/node-report/src/node_report.cc | 1029 ++++++ deps/node-report/src/node_report.h | 118 + deps/node-report/src/utilities.cc | 553 ++++ deps/node-report/test/common.js | 193 ++ .../test/test-api-bad-processobj.js | 25 + .../test/test-api-bad-processversion.js | 25 + .../test/test-api-bad-processversions.js | 27 + deps/node-report/test/test-api-getreport.js | 25 + deps/node-report/test/test-api-nohooks.js | 24 + .../test/test-api-noversioninfo.js | 29 + deps/node-report/test/test-api-pass-error.js | 29 + deps/node-report/test/test-api-uvhandles.js | 151 + deps/node-report/test/test-api.js | 23 + deps/node-report/test/test-exception.js | 37 + deps/node-report/test/test-fatal-error.js | 39 + deps/node-report/test/test-signal.js | 66 + 60 files changed, 11854 insertions(+) create mode 100644 deps/node-report/.gitignore create mode 100644 deps/node-report/.npmignore create mode 100644 deps/node-report/CHANGES.md create mode 100644 deps/node-report/CONTRIBUTING.md create mode 100644 deps/node-report/GOVERNANCE.md create mode 100644 deps/node-report/LICENCE.md create mode 100644 deps/node-report/MAINTAINER.md create mode 100644 deps/node-report/README.md create mode 100644 deps/node-report/binding.gyp create mode 100644 deps/node-report/demo/api_call.js create mode 100644 deps/node-report/demo/exception.js create mode 100644 deps/node-report/demo/fatalerror.js create mode 100644 deps/node-report/demo/loop.js create mode 100644 deps/node-report/index.js create mode 100644 deps/node-report/node_modules/nan/LICENSE.md create mode 100644 deps/node-report/node_modules/nan/README.md create mode 100644 deps/node-report/node_modules/nan/include_dirs.js create mode 100644 deps/node-report/node_modules/nan/nan.h create mode 100644 deps/node-report/node_modules/nan/nan_callbacks.h create mode 100644 deps/node-report/node_modules/nan/nan_callbacks_12_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_callbacks_pre_12_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_converters.h create mode 100644 deps/node-report/node_modules/nan/nan_converters_43_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_converters_pre_43_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_define_own_property_helper.h create mode 100644 deps/node-report/node_modules/nan/nan_implementation_12_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_implementation_pre_12_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_json.h create mode 100644 deps/node-report/node_modules/nan/nan_maybe_43_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_maybe_pre_43_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_new.h create mode 100644 deps/node-report/node_modules/nan/nan_object_wrap.h create mode 100644 deps/node-report/node_modules/nan/nan_persistent_12_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_persistent_pre_12_inl.h create mode 100644 deps/node-report/node_modules/nan/nan_private.h create mode 100644 deps/node-report/node_modules/nan/nan_string_bytes.h create mode 100644 deps/node-report/node_modules/nan/nan_typedarray_contents.h create mode 100644 deps/node-report/node_modules/nan/nan_weak.h create mode 100644 deps/node-report/node_modules/nan/package.json create mode 100755 deps/node-report/node_modules/nan/tools/1to2.js create mode 100644 deps/node-report/node_modules/nan/tools/README.md create mode 100644 deps/node-report/node_modules/nan/tools/package.json create mode 100644 deps/node-report/package.json create mode 100644 deps/node-report/src/module.cc create mode 100644 deps/node-report/src/node_report.cc create mode 100644 deps/node-report/src/node_report.h create mode 100644 deps/node-report/src/utilities.cc create mode 100644 deps/node-report/test/common.js create mode 100644 deps/node-report/test/test-api-bad-processobj.js create mode 100644 deps/node-report/test/test-api-bad-processversion.js create mode 100644 deps/node-report/test/test-api-bad-processversions.js create mode 100644 deps/node-report/test/test-api-getreport.js create mode 100644 deps/node-report/test/test-api-nohooks.js create mode 100644 deps/node-report/test/test-api-noversioninfo.js create mode 100644 deps/node-report/test/test-api-pass-error.js create mode 100644 deps/node-report/test/test-api-uvhandles.js create mode 100644 deps/node-report/test/test-api.js create mode 100644 deps/node-report/test/test-exception.js create mode 100644 deps/node-report/test/test-fatal-error.js create mode 100644 deps/node-report/test/test-signal.js diff --git a/deps/node-report/.gitignore b/deps/node-report/.gitignore new file mode 100644 index 00000000000000..1767441e001566 --- /dev/null +++ b/deps/node-report/.gitignore @@ -0,0 +1,45 @@ +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +*.node + +# Project files +*.project +*.cproject + +# Build directories +/build/ +/node_modules/ + +# Package files +NodeReport*.txt +node-report*.txt +npm-debug.log +nodereport-*.tgz +nodereport_test.log diff --git a/deps/node-report/.npmignore b/deps/node-report/.npmignore new file mode 100644 index 00000000000000..cc94b9764a91d2 --- /dev/null +++ b/deps/node-report/.npmignore @@ -0,0 +1,4 @@ +* +!src/** +!binding.gyp +!index.js diff --git a/deps/node-report/CHANGES.md b/deps/node-report/CHANGES.md new file mode 100644 index 00000000000000..8131b2d1cd1728 --- /dev/null +++ b/deps/node-report/CHANGES.md @@ -0,0 +1,144 @@ +2017-09-26, Version 2.2.1 +========================= + + * Update README to show support for Node.js 8 (Richard Chamberlain) + + * Remove use of std::map to sort version strings (Richard Chamberlain) + + * Restructure node_report.cc, move functions to utilities.cc (Richard Chamberlain) + + * Fix compile and linking issues on Alpine Linux (Richard Chamberlain) + + +2017-05-30, Version 2.2.0 +========================= + + * Additional information for libuv handles (Richard Lau) + + * node_report.cc: Fix CreateMessage call (Howard Hellyer) + + * Allow Error object to be passed to node-report (Howard Hellyer) + + * windows: fix compile time error on mktime (Howard Hellyer) + + * report: add average CPU consumption (Bidisha Pyne) + + * Fix the use of %p to format handle pointers on non-Windows platforms. (Howard Hellyer) + + * report: add word-size of the process (LAKSHMI SWETHA GOPIREDDY) + + +2017-03-23, Version 2.1.2 +========================= + + * Report compile time and runtime glibc version (Richard Lau) + + * Improve useability of node-report demos (Richard Chamberlain) + + * Fix return code from uncaught exception handler (Richard Chamberlain) + + * Increase tap timeout for CI testing (Richard Chamberlain) + + * test: Move OS version tests to common.js (Richard Lau) + + * docs: update platform support (Richard Lau) + + * smartos: enable node-report on SmartOS (Howard Hellyer) + + +2017-02-22, Version 2.1.1 +========================= + + * windows: fix reporting of machine name (Richard Chamberlain) + + * test: fix test-api-getreport.js (Richard Lau) + + * aix: improve readability of os version (Richard Lau) + + +2017-02-13, Version 2.1.0 +========================= + + * Provide getReport API to return the contents of node-report. (Howard Hellyer) + + +2017-02-09, Version 2.0.0 +========================= + + * mac: Fix compilation errors (Howard Hellyer) + + * Rename nodereport module to node-report (Richard Chamberlain) + + * Fix source directory for install target (Richard Lau) + + * aix: skip command line check for test-fatal-error (Richard Lau) + + * Add the list of library files loaded by the process to nodereport. (Howard Hellyer) + + * docs: AIX supports triggering on USR2 signal (Richard Lau) + + * Fix behaviour on exception to match node default (Richard Chamberlain) + + * Adds the command line used to start the node process to nodereport. (Howard Hellyer) + + * Opt-in hooks and signal by default (Richard Chamberlain) + + * Fix for clang warning: libstdc++ is deprecated (Richard Chamberlain) + + +2016-12-12, Version 1.0.7 +========================= + + * Fix version reporting in NodeReport section (Richard Lau) + + * Fix fprintf calls on Windows (Richard Lau) + + +2016-11-18, Version 1.0.6 +========================= + + * Fix test-exception.js for PPC (Richard Lau) + + * Improve README.md (Jeremiah Senkpiel) + + * Improvement to Windows version reporting (Richard Lau) + + * Convert testcases to use tap (Richard Lau) + + +2016-11-10, Version 1.0.5 +========================= + + * Fix for failure in fatal error (OOM) test (Richard Chamberlain) + + * Add support for nodereport on AIX (Richard Chamberlain) + + * Deleting AUTHORS file. (Richard Chamberlain) + + * Correct Javascript to JavaScript in README.md (Richard Chamberlain) + + * Correct upper-case NPM, should be lower-case (Richard Chamberlain) + + * Remove specific URLs for NPM (Richard Chamberlain) + + * Add MAINTAINER.md file to document NPM release procedure (Richard Chamberlain) + + * Set/correct package metadata in package.json (Richard Chamberlain) + + * README documentation improvements (Richard Chamberlain) + + * .gitignore the test autorun log file (Sam Roberts) + + * test: require this module using correct syntax (Sam Roberts) + + * .npmignore: do not pack unnecessary files (Sam Roberts) + + * .gitignore: ignore npm ephemera and node reports (Sam Roberts) + + * Need to define __STDC_FORMAT_MACROS for some glibc versions (Richard Chamberlain) + + +2016-10-28, Version 1.0.4 +========================= + + * First release! diff --git a/deps/node-report/CONTRIBUTING.md b/deps/node-report/CONTRIBUTING.md new file mode 100644 index 00000000000000..0ab8f950f16da8 --- /dev/null +++ b/deps/node-report/CONTRIBUTING.md @@ -0,0 +1,39 @@ +# Contributing to node-report + +## Code of Conduct + +The [Node.js Code of Conduct][] applies to this repo. + +[Node.js Code of Conduct]: https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md + +## Code Contributions + +The node-report project falls under the governance of the post-mortem +working group which is documented in: +https://github.com/nodejs/post-mortem/blob/master/GOVERNANCE.md + +## Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +* (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +* (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +* (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/deps/node-report/GOVERNANCE.md b/deps/node-report/GOVERNANCE.md new file mode 100644 index 00000000000000..4e521ba6fffbe3 --- /dev/null +++ b/deps/node-report/GOVERNANCE.md @@ -0,0 +1,5 @@ +# node-report Project Governance + +The node-report project falls under the governance of the post-mortem +working group which is documented in: +https://github.com/nodejs/post-mortem/blob/master/GOVERNANCE.md. diff --git a/deps/node-report/LICENCE.md b/deps/node-report/LICENCE.md new file mode 100644 index 00000000000000..53b01630891134 --- /dev/null +++ b/deps/node-report/LICENCE.md @@ -0,0 +1,13 @@ +The MIT License (MIT) +===================== + +Copyright (c) 2016 node-report contributors +-------------------------------------------------- + +*nodereport contributors listed in * + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE diff --git a/deps/node-report/MAINTAINER.md b/deps/node-report/MAINTAINER.md new file mode 100644 index 00000000000000..09b36a62963a77 --- /dev/null +++ b/deps/node-report/MAINTAINER.md @@ -0,0 +1,15 @@ +# Instructions for maintainers of the node-report project + +## Publishing to the npm registry + +The node-report project is published as an npm native module + +For each publish to npm: + + - update the version property in the package.json file, incrementing the major, minor and patch level as appropriate + - update the CHANGES.md file with a list of commits since last release + - commit CHANGES.md and package.json to node-report master branch + - tag commit with an annotated tag + - git checkout and npm publish the node-report package + +Suggested tooling is the slt-release script documented here: https://github.com/strongloop/strong-tools diff --git a/deps/node-report/README.md b/deps/node-report/README.md new file mode 100644 index 00000000000000..f7657a95aa9704 --- /dev/null +++ b/deps/node-report/README.md @@ -0,0 +1,128 @@ +# node-report + +Delivers a human-readable diagnostic summary, written to file. + +The report is intended for development, test and production +use, to capture and preserve information for problem determination. +It includes JavaScript and native stack traces, heap statistics, +platform information and resource usage etc. With the report enabled, +reports can be triggered on unhandled exceptions, fatal errors, signals +and calls to a JavaScript API. + +Supports Node.js versions 4, 6 and 8 on AIX, Linux, MacOS, SmartOS and Windows. + +## Usage + +```bash +npm install node-report +node -r node-report app.js +``` +A report will be triggered automatically on unhandled exceptions and fatal +error events (for example out of memory errors), and can also be triggered +by sending a USR2 signal to a Node.js process (not supported on Windows). + +A report can also be triggered via an API call from a JavaScript +application. + +```js +var nodereport = require('node-report'); +nodereport.triggerReport(); +``` +The content of a report can also be returned as a JavaScript string via an +API call from a JavaScript application. + +```js +var nodereport = require('nodereport'); +var report_str = nodereport.getReport(); +console.log(report_str); +``` +The API can be used without adding the automatic exception and fatal error +hooks and the signal handler, as follows: + +```js +var nodereport = require('node-report/api'); +nodereport.triggerReport(); +``` + +Content of the report consists of a header section containing the event +type, date, time, PID and Node version, sections containing JavaScript and +native stack traces, a section containing V8 heap information, a section +containing libuv handle information and an OS platform information section +showing CPU and memory usage and system limits. An example report can be +triggered using the Node.js REPL: + +``` +$ node +> nodereport = require('node-report') +> nodereport.triggerReport() +Writing Node.js report to file: node-report.20161020.091102.8480.001.txt +Node.js report completed +> +``` + +When a report is triggered, start and end messages are issued to stderr +and the filename of the report is returned to the caller. The default filename +includes the date, time, PID and a sequence number. Alternatively, a filename +can be specified as a parameter on the `triggerReport()` call. + +```js +nodereport.triggerReport("myReportName"); +``` + +Both `triggerReport()` and `getReport()` can take an optional `Error` object +as a parameter. If an `Error` object is provided, the message and stack trace +from the object will be included in the report in the `JavaScript Exception +Details` section. +When using node-report to handle errors in a callback or an exception handler +this allows the report to include the location of the original error as well +as where it was handled. +If both a filename and `Error` object are passed to `triggerReport()` the +`Error` object should be the second parameter. + +```js +try { + process.chdir('/foo/foo'); +} catch (err) { + nodereport.triggerReport(err); +} + ... +}); +``` + +## Configuration + +Additional configuration is available using the following APIs: + +```js +var nodereport = require('node-report/api'); +nodereport.setEvents("exception+fatalerror+signal+apicall"); +nodereport.setSignal("SIGUSR2|SIGQUIT"); +nodereport.setFileName("stdout|stderr|"); +nodereport.setDirectory(""); +nodereport.setVerbose("yes|no"); +``` + +Configuration on module initialization is also available via environment variables: + +```bash +export NODEREPORT_EVENTS=exception+fatalerror+signal+apicall +export NODEREPORT_SIGNAL=SIGUSR2|SIGQUIT +export NODEREPORT_FILENAME=stdout|stderr| +export NODEREPORT_DIRECTORY= +export NODEREPORT_VERBOSE=yes|no +``` + +## Examples + +To see examples of reports generated from these events you can run the +demonstration applications provided in the node-report github repository. These are +Node.js applications which will prompt you to trigger the required event. + +1. `api.js` - report triggered by JavaScript API call. +2. `exception.js` - report triggered by unhandled exception. +3. `fatalerror.js` - report triggered by fatal error on JavaScript heap out of memory. +4. `loop.js` - looping application, report triggered using kill `-USR2 `. + +## License + +[Licensed under the MIT License.](LICENSE.md) diff --git a/deps/node-report/binding.gyp b/deps/node-report/binding.gyp new file mode 100644 index 00000000000000..be69b7921a8b8d --- /dev/null +++ b/deps/node-report/binding.gyp @@ -0,0 +1,33 @@ +{ + "targets": [ + { + "target_name": "api", + "sources": [ "src/node_report.cc", "src/module.cc", "src/utilities.cc" ], + "include_dirs": [ 'node-report example'); + response.write('

node-report example: report triggered by JavaScript API call

'); + response.write('

Click on button below to trigger a report. The application will continue.'); + response.write('

'); + response.write('
'); + response.write('

Click on button below to terminate the application.'); + response.write('

'); + response.write('
'); + response.write(':8080/ or http://localhost:8080/'); + +setTimeout(function(){ + console.log('api_call.js: application timeout expired, exiting.'); + process.exit(0); +}, 60000); diff --git a/deps/node-report/demo/exception.js b/deps/node-report/demo/exception.js new file mode 100644 index 00000000000000..9686b4423271b8 --- /dev/null +++ b/deps/node-report/demo/exception.js @@ -0,0 +1,32 @@ +// Example - generation of report on uncaught exception +require('node-report'); +var http = require("http"); + +function my_listener(request, response) { + switch (request.url) { + case '/': + response.writeHead(200, "OK",{'Content-Type': 'text/html'}); + response.write('node-report example'); + response.write('

node-report example: report triggered on uncaught exception

'); + response.write('

Click on button below to throw an exception. The exception is not caught by the application.'); + response.write('

The node-report module will produce a report then terminate the application.'); + response.write('

'); + response.write('
'); + response.write(':8080/ or http://localhost:8080/'); + +setTimeout(function() { + console.log('exception.js: application timeout expired, exiting.'); + process.exit(0); +}, 60000); diff --git a/deps/node-report/demo/fatalerror.js b/deps/node-report/demo/fatalerror.js new file mode 100644 index 00000000000000..6ca26a8c17576d --- /dev/null +++ b/deps/node-report/demo/fatalerror.js @@ -0,0 +1,43 @@ +// Example - generation of report on fatal error (JavaScript heap OOM) +require('node-report'); +var http = require('http'); + +function my_listener(request, response) { + switch (request.url) { + case '/': + response.writeHead(200, "OK",{'Content-Type': 'text/html'}); + response.write('node-report example'); + response.write('

node-report example: report triggered on fatal error (heap OOM)

'); + response.write('

Click on button below to initiate excessive memory usage.'); + response.write('

The application will fail when the heap is full, and the node-report module will produce a report.'); + response.write('

'); + response.write('
'); + response.write(' to change'); +console.log('fatalerror.js: Go to http://:8080/ or http://localhost:8080/'); + +setTimeout(function(){ + console.log('fatalerror.js: application timeout expired, exiting.'); + process.exit(0); +}, 60000); diff --git a/deps/node-report/demo/loop.js b/deps/node-report/demo/loop.js new file mode 100644 index 00000000000000..9c95f1130fbe5e --- /dev/null +++ b/deps/node-report/demo/loop.js @@ -0,0 +1,58 @@ +// Example - generation of report via signal for a looping application +// Note: node-report signal trigger is not supported on Windows +require('node-report'); +var http = require("http"); + +function my_listener(request, response) { + switch (request.url) { + case '/loop': + console.log("loop.js: going to busy loop now, use 'kill -USR2 " + process.pid + "' to trigger report"); + var list = []; + for (var i=0; i<10000000000; i++) { + for (var j=0; i<1000; i++) { + list.push(new MyRecord()); + } + for (var j=0; i<1000; i++) { + list[j].id += 1; + list[j].account += 2; + } + for (var j=0; i<1000; i++) { + list.pop(); + } + } + // drop through to refresh page + case '/': + response.writeHead(200, "OK",{'Content-Type': 'text/html'}); + response.write('node-report example'); + response.write('

node-report example: report triggered using USR2 signal

'); + response.write('

Click on button below to enter JavaScript busy loop, then'); + response.write(' use "kill -USR2 ' + process.pid + '" in a terminal window to trigger report'); + response.write('

'); + response.write('
'); + response.write('

When busy loop completes, click on button below to terminate the application.'); + response.write('

'); + response.write('
'); + response.write(':8080/ or http://localhost:8080/'); + +setTimeout(function() { + console.log('loop.js: timeout expired, exiting.'); + process.exit(0); +}, 60000); diff --git a/deps/node-report/index.js b/deps/node-report/index.js new file mode 100644 index 00000000000000..94ba55673e472f --- /dev/null +++ b/deps/node-report/index.js @@ -0,0 +1,16 @@ +// Main module entry point for node-report + +const api = require('./api'); + +// NODEREPORT_EVENTS env var overrides the defaults +const options = process.env.NODEREPORT_EVENTS || 'exception+fatalerror+signal+apicall'; +api.setEvents(options); + +exports.triggerReport = api.triggerReport; +exports.getReport = api.getReport; +exports.setEvents = api.setEvents; +exports.setCoreDump = api.setCoreDump; +exports.setSignal = api.setSignal; +exports.setFileName = api.setFileName; +exports.setDirectory = api.setDirectory; +exports.setVerbose = api.setVerbose; diff --git a/deps/node-report/node_modules/nan/LICENSE.md b/deps/node-report/node_modules/nan/LICENSE.md new file mode 100644 index 00000000000000..dddd13d5c1ddf8 --- /dev/null +++ b/deps/node-report/node_modules/nan/LICENSE.md @@ -0,0 +1,13 @@ +The MIT License (MIT) +===================== + +Copyright (c) 2018 NAN contributors +----------------------------------- + +*NAN contributors listed at * + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/node-report/node_modules/nan/README.md b/deps/node-report/node_modules/nan/README.md new file mode 100644 index 00000000000000..b4851baab4f1ec --- /dev/null +++ b/deps/node-report/node_modules/nan/README.md @@ -0,0 +1,456 @@ +Native Abstractions for Node.js +=============================== + +**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8 and 9.** + +***Current version: 2.10.0*** + +*(See [CHANGELOG.md](https://github.com/nodejs/nan/blob/master/CHANGELOG.md) for complete ChangeLog)* + +[![NPM](https://nodei.co/npm/nan.png?downloads=true&downloadRank=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6&height=3)](https://nodei.co/npm/nan/) + +[![Build Status](https://api.travis-ci.org/nodejs/nan.svg?branch=master)](http://travis-ci.org/nodejs/nan) +[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan) + +Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.12 to 4.0, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. + +This project also contains some helper utilities that make addon development a bit more pleasant. + + * **[News & Updates](#news)** + * **[Usage](#usage)** + * **[Example](#example)** + * **[API](#api)** + * **[Tests](#tests)** + * **[Knowns issues](#issues)** + * **[Governance & Contributing](#governance)** + + + +## News & Updates + + + +## Usage + +Simply add **NAN** as a dependency in the *package.json* of your Node addon: + +``` bash +$ npm install --save nan +``` + +Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: + +``` python +"include_dirs" : [ + "` when compiling your addon. + + + +## Example + +Just getting started with Nan? Take a look at the **[Node Add-on Examples](https://github.com/nodejs/node-addon-examples)**. + +Refer to a [quick-start **Nan** Boilerplate](https://github.com/fcanas/node-native-boilerplate) for a ready-to-go project that utilizes basic Nan functionality. + +For a simpler example, see the **[async pi estimation example](https://github.com/nodejs/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. + +Yet another example is **[nan-example-eol](https://github.com/CodeCharmLtd/nan-example-eol)**. It shows newline detection implemented as a native addon. + +Also take a look at our comprehensive **[C++ test suite](https://github.com/nodejs/nan/tree/master/test/cpp)** which has a plethora of code snippets for your pasting pleasure. + + + +## API + +Additional to the NAN documentation below, please consult: + +* [The V8 Getting Started * Guide](https://github.com/v8/v8/wiki/Getting%20Started%20with%20Embedding) +* [The V8 Embedders * Guide](https://github.com/v8/v8/wiki/Embedder%27s%20Guide) +* [V8 API Documentation](http://v8docs.nodesource.com/) +* [Node Add-on Documentation](https://nodejs.org/api/addons.html) + + + +### JavaScript-accessible methods + +A _template_ is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated from JavaScript. See the V8 Embedders Guide section on [Templates](https://github.com/v8/v8/wiki/Embedder%27s-Guide#templates) for further information. + +In order to expose functionality to JavaScript via a template, you must provide it to V8 in a form that it understands. Across the versions of V8 supported by NAN, JavaScript-accessible method signatures vary widely, NAN fully abstracts method declaration and provides you with an interface that is similar to the most recent V8 API but is backward-compatible with older versions that still use the now-deceased `v8::Argument` type. + +* **Method argument types** + - Nan::FunctionCallbackInfo + - Nan::PropertyCallbackInfo + - Nan::ReturnValue +* **Method declarations** + - Method declaration + - Getter declaration + - Setter declaration + - Property getter declaration + - Property setter declaration + - Property enumerator declaration + - Property deleter declaration + - Property query declaration + - Index getter declaration + - Index setter declaration + - Index enumerator declaration + - Index deleter declaration + - Index query declaration +* Method and template helpers + - Nan::SetMethod() + - Nan::SetPrototypeMethod() + - Nan::SetAccessor() + - Nan::SetNamedPropertyHandler() + - Nan::SetIndexedPropertyHandler() + - Nan::SetTemplate() + - Nan::SetPrototypeTemplate() + - Nan::SetInstanceTemplate() + - Nan::SetCallHandler() + - Nan::SetCallAsFunctionHandler() + +### Scopes + +A _local handle_ is a pointer to an object. All V8 objects are accessed using handles, they are necessary because of the way the V8 garbage collector works. + +A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope. + +The creation of `HandleScope` objects is different across the supported versions of V8. Therefore, NAN provides its own implementations that can be used safely across these. + + - Nan::HandleScope + - Nan::EscapableHandleScope + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://github.com/v8/v8/wiki/Embedder%27s%20Guide#handles-and-garbage-collection). + +### Persistent references + +An object reference that is independent of any `HandleScope` is a _persistent_ reference. Where a `Local` handle only lives as long as the `HandleScope` in which it was allocated, a `Persistent` handle remains valid until it is explicitly disposed. + +Due to the evolution of the V8 API, it is necessary for NAN to provide a wrapper implementation of the `Persistent` classes to supply compatibility across the V8 versions supported. + + - Nan::PersistentBase & v8::PersistentBase + - Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits + - Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits + - Nan::Persistent + - Nan::Global + - Nan::WeakCallbackInfo + - Nan::WeakCallbackType + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://developers.google.com/v8/embed#handles). + +### New + +NAN provides a `Nan::New()` helper for the creation of new JavaScript objects in a way that's compatible across the supported versions of V8. + + - Nan::New() + - Nan::Undefined() + - Nan::Null() + - Nan::True() + - Nan::False() + - Nan::EmptyString() + + +### Converters + +NAN contains functions that convert `v8::Value`s to other `v8::Value` types and native types. Since type conversion is not guaranteed to succeed, they return `Nan::Maybe` types. These converters can be used in place of `value->ToX()` and `value->XValue()` (where `X` is one of the types, e.g. `Boolean`) in a way that provides a consistent interface across V8 versions. Newer versions of V8 use the new `v8::Maybe` and `v8::MaybeLocal` types for these conversions, older versions don't have this functionality so it is provided by NAN. + + - Nan::To() + +### Maybe Types + +The `Nan::MaybeLocal` and `Nan::Maybe` types are monads that encapsulate `v8::Local` handles that _may be empty_. + +* **Maybe Types** + - Nan::MaybeLocal + - Nan::Maybe + - Nan::Nothing + - Nan::Just +* **Maybe Helpers** + - Nan::Call() + - Nan::ToDetailString() + - Nan::ToArrayIndex() + - Nan::Equals() + - Nan::NewInstance() + - Nan::GetFunction() + - Nan::Set() + - Nan::DefineOwnProperty() + - Nan::ForceSet() + - Nan::Get() + - Nan::GetPropertyAttributes() + - Nan::Has() + - Nan::Delete() + - Nan::GetPropertyNames() + - Nan::GetOwnPropertyNames() + - Nan::SetPrototype() + - Nan::ObjectProtoToString() + - Nan::HasOwnProperty() + - Nan::HasRealNamedProperty() + - Nan::HasRealIndexedProperty() + - Nan::HasRealNamedCallbackProperty() + - Nan::GetRealNamedPropertyInPrototypeChain() + - Nan::GetRealNamedProperty() + - Nan::CallAsFunction() + - Nan::CallAsConstructor() + - Nan::GetSourceLine() + - Nan::GetLineNumber() + - Nan::GetStartColumn() + - Nan::GetEndColumn() + - Nan::CloneElementAt() + - Nan::HasPrivate() + - Nan::GetPrivate() + - Nan::SetPrivate() + - Nan::DeletePrivate() + - Nan::MakeMaybe() + +### Script + +NAN provides a `v8::Script` helpers as the API has changed over the supported versions of V8. + + - Nan::CompileScript() + - Nan::RunScript() + + +### JSON + +The _JSON_ object provides the c++ versions of the methods offered by the `JSON` object in javascript. V8 exposes these methods via the `v8::JSON` object. + + - Nan::JSON.Parse + - Nan::JSON.Stringify + +Refer to the V8 JSON object in the [V8 documentation](https://v8docs.nodesource.com/node-7.4/da/d6f/classv8_1_1_j_s_o_n.html) for more information about these methods and their arguments. + +### Errors + +NAN includes helpers for creating, throwing and catching Errors as much of this functionality varies across the supported versions of V8 and must be abstracted. + +Note that an Error object is simply a specialized form of `v8::Value`. + +Also consult the V8 Embedders Guide section on [Exceptions](https://developers.google.com/v8/embed#exceptions) for more information. + + - Nan::Error() + - Nan::RangeError() + - Nan::ReferenceError() + - Nan::SyntaxError() + - Nan::TypeError() + - Nan::ThrowError() + - Nan::ThrowRangeError() + - Nan::ThrowReferenceError() + - Nan::ThrowSyntaxError() + - Nan::ThrowTypeError() + - Nan::FatalException() + - Nan::ErrnoException() + - Nan::TryCatch + + +### Buffers + +NAN's `node::Buffer` helpers exist as the API has changed across supported Node versions. Use these methods to ensure compatibility. + + - Nan::NewBuffer() + - Nan::CopyBuffer() + - Nan::FreeCallback() + +### Nan::Callback + +`Nan::Callback` makes it easier to use `v8::Function` handles as callbacks. A class that wraps a `v8::Function` handle, protecting it from garbage collection and making it particularly useful for storage and use across asynchronous execution. + + - Nan::Callback + +### Asynchronous work helpers + +`Nan::AsyncWorker`, `Nan::AsyncProgressWorker` and `Nan::AsyncProgressQueueWorker` are helper classes that make working with asynchronous code easier. + + - Nan::AsyncWorker + - Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker + - Nan::AsyncProgressQueueWorker + - Nan::AsyncQueueWorker + +### Strings & Bytes + +Miscellaneous string & byte encoding and decoding functionality provided for compatibility across supported versions of V8 and Node. Implemented by NAN to ensure that all encoding types are supported, even for older versions of Node where they are missing. + + - Nan::Encoding + - Nan::Encode() + - Nan::DecodeBytes() + - Nan::DecodeWrite() + + +### Object Wrappers + +The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects. + + - Nan::ObjectWrap + + +### V8 internals + +The hooks to access V8 internals—including GC and statistics—are different across the supported versions of V8, therefore NAN provides its own hooks that call the appropriate V8 methods. + + - NAN_GC_CALLBACK() + - Nan::AddGCEpilogueCallback() + - Nan::RemoveGCEpilogueCallback() + - Nan::AddGCPrologueCallback() + - Nan::RemoveGCPrologueCallback() + - Nan::GetHeapStatistics() + - Nan::SetCounterFunction() + - Nan::SetCreateHistogramFunction() + - Nan::SetAddHistogramSampleFunction() + - Nan::IdleNotification() + - Nan::LowMemoryNotification() + - Nan::ContextDisposedNotification() + - Nan::GetInternalFieldPointer() + - Nan::SetInternalFieldPointer() + - Nan::AdjustExternalMemory() + + +### Miscellaneous V8 Helpers + + - Nan::Utf8String + - Nan::GetCurrentContext() + - Nan::SetIsolateData() + - Nan::GetIsolateData() + - Nan::TypedArrayContents + + +### Miscellaneous Node Helpers + + - Nan::AsyncResource + - Nan::MakeCallback() + - NAN_MODULE_INIT() + - Nan::Export() + + + + + + +### Tests + +To run the NAN tests do: + +``` sh +npm install +npm run-script rebuild-tests +npm test +``` + +Or just: + +``` sh +npm install +make test +``` + + + +## Known issues + +### Compiling against Node.js 0.12 on OSX + +With new enough compilers available on OSX, the versions of V8 headers corresponding to Node.js 0.12 +do not compile anymore. The error looks something like: + +``` +❯ CXX(target) Release/obj.target/accessors/cpp/accessors.o +In file included from ../cpp/accessors.cpp:9: +In file included from ../../nan.h:51: +In file included from /Users/ofrobots/.node-gyp/0.12.18/include/node/node.h:61: +/Users/ofrobots/.node-gyp/0.12.18/include/node/v8.h:5800:54: error: 'CreateHandle' is a protected member of 'v8::HandleScope' + return Handle(reinterpret_cast(HandleScope::CreateHandle( + ~~~~~~~~~~~~~^~~~~~~~~~~~ +``` + +This can be worked around by patching your local versions of v8.h corresponding to Node 0.12 to make +`v8::Handle` a friend of `v8::HandleScope`. Since neither Node.js not V8 support this release line anymore +this patch cannot be released by either project in an official release. + +For this reason, we do not test against Node.js 0.12 on OSX in this project's CI. If you need to support +that configuration, you will need to either get an older compiler, or apply a source patch to the version +of V8 headers as a workaround. + + + +## Governance & Contributing + +NAN is governed by the [Node.js Addon API Working Group](https://github.com/nodejs/CTC/blob/master/WORKING_GROUPS.md#addon-api) + +### Addon API Working Group (WG) + +The NAN project is jointly governed by a Working Group which is responsible for high-level guidance of the project. + +Members of the WG are also known as Collaborators, there is no distinction between the two, unlike other Node.js projects. + +The WG has final authority over this project including: + +* Technical direction +* Project governance and process (including this policy) +* Contribution policy +* GitHub repository hosting +* Maintaining the list of additional Collaborators + +For the current list of WG members, see the project [README.md](./README.md#collaborators). + +Individuals making significant and valuable contributions are made members of the WG and given commit-access to the project. These individuals are identified by the WG and their addition to the WG is discussed via GitHub and requires unanimous consensus amongst those WG members participating in the discussion with a quorum of 50% of WG members required for acceptance of the vote. + +_Note:_ If you make a significant contribution and are not considered for commit-access log an issue or contact a WG member directly. + +For the current list of WG members / Collaborators, see the project [README.md](./README.md#collaborators). + +### Consensus Seeking Process + +The WG follows a [Consensus Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making) decision making model. + +Modifications of the contents of the NAN repository are made on a collaborative basis. Anybody with a GitHub account may propose a modification via pull request and it will be considered by the WG. All pull requests must be reviewed and accepted by a WG member with sufficient expertise who is able to take full responsibility for the change. In the case of pull requests proposed by an existing WG member, an additional WG member is required for sign-off. Consensus should be sought if additional WG members participate and there is disagreement around a particular modification. + +If a change proposal cannot reach a consensus, a WG member can call for a vote amongst the members of the WG. Simple majority wins. + + + +## Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +* (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +* (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +* (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + + + +### WG Members / Collaborators + + + + + + + + + + +
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
David SiegelGitHub/agnatTwitter/@agnat
Michael Ira KrufkyGitHub/mkrufkyTwitter/@mkrufky
+ +## Licence & copyright + +Copyright (c) 2018 NAN WG Members / Collaborators (listed above). + +Native Abstractions for Node.js is licensed under an MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/deps/node-report/node_modules/nan/include_dirs.js b/deps/node-report/node_modules/nan/include_dirs.js new file mode 100644 index 00000000000000..4f1dfb41667b9b --- /dev/null +++ b/deps/node-report/node_modules/nan/include_dirs.js @@ -0,0 +1 @@ +console.log(require('path').relative('.', __dirname)); diff --git a/deps/node-report/node_modules/nan/nan.h b/deps/node-report/node_modules/nan/nan.h new file mode 100644 index 00000000000000..29f084e7695467 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan.h @@ -0,0 +1,2761 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors: + * - Rod Vagg + * - Benjamin Byholm + * - Trevor Norris + * - Nathan Rajlich + * - Brett Lawson + * - Ben Noordhuis + * - David Siegel + * - Michael Ira Krufky + * + * MIT License + * + * Version 2.10.0: current Node 9.8.0, Node 12: 0.12.18, Node 10: 0.10.48, iojs: 3.3.1 + * + * See https://github.com/nodejs/nan for the latest update to this file + **********************************************************************************/ + +#ifndef NAN_H_ +#define NAN_H_ + +#include + +#define NODE_0_10_MODULE_VERSION 11 +#define NODE_0_12_MODULE_VERSION 14 +#define ATOM_0_21_MODULE_VERSION 41 +#define IOJS_1_0_MODULE_VERSION 42 +#define IOJS_1_1_MODULE_VERSION 43 +#define IOJS_2_0_MODULE_VERSION 44 +#define IOJS_3_0_MODULE_VERSION 45 +#define NODE_4_0_MODULE_VERSION 46 +#define NODE_5_0_MODULE_VERSION 47 +#define NODE_6_0_MODULE_VERSION 48 +#define NODE_7_0_MODULE_VERSION 51 +#define NODE_8_0_MODULE_VERSION 57 +#define NODE_9_0_MODULE_VERSION 59 + +#ifdef _MSC_VER +# define NAN_HAS_CPLUSPLUS_11 (_MSC_VER >= 1800) +#else +# define NAN_HAS_CPLUSPLUS_11 (__cplusplus >= 201103L) +#endif + +#if NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION && !NAN_HAS_CPLUSPLUS_11 +# error This version of node/NAN/v8 requires a C++11 compiler +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(_MSC_VER) +# pragma warning( push ) +# pragma warning( disable : 4530 ) +# include +# include +# include +# pragma warning( pop ) +#else +# include +# include +# include +#endif + +// uv helpers +#ifdef UV_VERSION_MAJOR +# ifndef UV_VERSION_PATCH +# define UV_VERSION_PATCH 0 +# endif +# define NAUV_UVVERSION ((UV_VERSION_MAJOR << 16) | \ + (UV_VERSION_MINOR << 8) | \ + (UV_VERSION_PATCH)) +#else +# define NAUV_UVVERSION 0x000b00 +#endif + +#if NAUV_UVVERSION < 0x000b0b +# ifdef WIN32 +# include +# else +# include +# endif +#endif + +namespace Nan { + +#define NAN_INLINE inline // TODO(bnoordhuis) Remove in v3.0.0. + +#if defined(__GNUC__) && \ + !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS) +# define NAN_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) && \ + !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS) +# define NAN_DEPRECATED __declspec(deprecated) +#else +# define NAN_DEPRECATED +#endif + +#if NAN_HAS_CPLUSPLUS_11 +# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&) = delete; +# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&) = delete; +# define NAN_DISALLOW_MOVE(CLASS) \ + CLASS(CLASS&&) = delete; /* NOLINT(build/c++11) */ \ + void operator=(CLASS&&) = delete; +#else +# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&); +# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&); +# define NAN_DISALLOW_MOVE(CLASS) +#endif + +#define NAN_DISALLOW_ASSIGN_COPY(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_COPY(CLASS) + +#define NAN_DISALLOW_ASSIGN_MOVE(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define NAN_DISALLOW_COPY_MOVE(CLASS) \ + NAN_DISALLOW_COPY(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define NAN_DISALLOW_ASSIGN_COPY_MOVE(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_COPY(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define TYPE_CHECK(T, S) \ + while (false) { \ + *(static_cast(0)) = static_cast(0); \ + } + +//=== RegistrationFunction ===================================================== + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + typedef v8::Handle ADDON_REGISTER_FUNCTION_ARGS_TYPE; +#else + typedef v8::Local ADDON_REGISTER_FUNCTION_ARGS_TYPE; +#endif + +#define NAN_MODULE_INIT(name) \ + void name(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) + +//=== CallbackInfo ============================================================= + +#include "nan_callbacks.h" // NOLINT(build/include) + +//============================================================================== + +#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION) +typedef v8::Script UnboundScript; +typedef v8::Script BoundScript; +#else +typedef v8::UnboundScript UnboundScript; +typedef v8::Script BoundScript; +#endif + +#if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION) +typedef v8::String::ExternalAsciiStringResource + ExternalOneByteStringResource; +#else +typedef v8::String::ExternalOneByteStringResource + ExternalOneByteStringResource; +#endif + +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) +template +class NonCopyablePersistentTraits : + public v8::NonCopyablePersistentTraits {}; +template +class CopyablePersistentTraits : + public v8::CopyablePersistentTraits {}; + +template +class PersistentBase : + public v8::PersistentBase {}; + +template > +class Persistent; +#else +template class NonCopyablePersistentTraits; +template class PersistentBase; +template class WeakCallbackData; +template > +class Persistent; +#endif // NODE_MODULE_VERSION + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# include "nan_maybe_43_inl.h" // NOLINT(build/include) +#else +# include "nan_maybe_pre_43_inl.h" // NOLINT(build/include) +#endif + +#include "nan_converters.h" // NOLINT(build/include) +#include "nan_new.h" // NOLINT(build/include) + +#if NAUV_UVVERSION < 0x000b17 +#define NAUV_WORK_CB(func) \ + void func(uv_async_t *async, int) +#else +#define NAUV_WORK_CB(func) \ + void func(uv_async_t *async) +#endif + +#if NAUV_UVVERSION >= 0x000b0b + +typedef uv_key_t nauv_key_t; + +inline int nauv_key_create(nauv_key_t *key) { + return uv_key_create(key); +} + +inline void nauv_key_delete(nauv_key_t *key) { + uv_key_delete(key); +} + +inline void* nauv_key_get(nauv_key_t *key) { + return uv_key_get(key); +} + +inline void nauv_key_set(nauv_key_t *key, void *value) { + uv_key_set(key, value); +} + +#else + +/* Implement thread local storage for older versions of libuv. + * This is essentially a backport of libuv commit 5d2434bf + * written by Ben Noordhuis, adjusted for names and inline. + */ + +#ifndef WIN32 + +typedef pthread_key_t nauv_key_t; + +inline int nauv_key_create(nauv_key_t* key) { + return -pthread_key_create(key, NULL); +} + +inline void nauv_key_delete(nauv_key_t* key) { + if (pthread_key_delete(*key)) + abort(); +} + +inline void* nauv_key_get(nauv_key_t* key) { + return pthread_getspecific(*key); +} + +inline void nauv_key_set(nauv_key_t* key, void* value) { + if (pthread_setspecific(*key, value)) + abort(); +} + +#else + +typedef struct { + DWORD tls_index; +} nauv_key_t; + +inline int nauv_key_create(nauv_key_t* key) { + key->tls_index = TlsAlloc(); + if (key->tls_index == TLS_OUT_OF_INDEXES) + return UV_ENOMEM; + return 0; +} + +inline void nauv_key_delete(nauv_key_t* key) { + if (TlsFree(key->tls_index) == FALSE) + abort(); + key->tls_index = TLS_OUT_OF_INDEXES; +} + +inline void* nauv_key_get(nauv_key_t* key) { + void* value = TlsGetValue(key->tls_index); + if (value == NULL) + if (GetLastError() != ERROR_SUCCESS) + abort(); + return value; +} + +inline void nauv_key_set(nauv_key_t* key, void* value) { + if (TlsSetValue(key->tls_index, value) == FALSE) + abort(); +} + +#endif +#endif + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template +v8::Local New(v8::Handle); +#endif + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + typedef v8::WeakCallbackType WeakCallbackType; +#else +struct WeakCallbackType { + enum E {kParameter, kInternalFields}; + E type; + WeakCallbackType(E other) : type(other) {} // NOLINT(runtime/explicit) + inline bool operator==(E other) { return other == this->type; } + inline bool operator!=(E other) { return !operator==(other); } +}; +#endif + +template class WeakCallbackInfo; + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# include "nan_persistent_12_inl.h" // NOLINT(build/include) +#else +# include "nan_persistent_pre_12_inl.h" // NOLINT(build/include) +#endif + +namespace imp { + static const size_t kMaxLength = 0x3fffffff; + // v8::String::REPLACE_INVALID_UTF8 was introduced + // in node.js v0.10.29 and v0.8.27. +#if NODE_MAJOR_VERSION > 0 || \ + NODE_MINOR_VERSION > 10 || \ + NODE_MINOR_VERSION == 10 && NODE_PATCH_VERSION >= 29 || \ + NODE_MINOR_VERSION == 8 && NODE_PATCH_VERSION >= 27 + static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8; +#else + static const unsigned kReplaceInvalidUtf8 = 0; +#endif +} // end of namespace imp + +//=== HandleScope ============================================================== + +class HandleScope { + v8::HandleScope scope; + + public: +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + inline HandleScope() : scope(v8::Isolate::GetCurrent()) {} + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(v8::Isolate::GetCurrent()); + } +#else + inline HandleScope() : scope() {} + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(); + } +#endif + + private: + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. + HandleScope(const HandleScope &); + void operator=(const HandleScope &); + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } +}; + +class EscapableHandleScope { + public: +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + inline EscapableHandleScope() : scope(v8::Isolate::GetCurrent()) {} + + inline static int NumberOfHandles() { + return v8::EscapableHandleScope::NumberOfHandles(v8::Isolate::GetCurrent()); + } + + template + inline v8::Local Escape(v8::Local value) { + return scope.Escape(value); + } + + private: + v8::EscapableHandleScope scope; +#else + inline EscapableHandleScope() : scope() {} + + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(); + } + + template + inline v8::Local Escape(v8::Local value) { + return scope.Close(value); + } + + private: + v8::HandleScope scope; +#endif + + private: + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. + EscapableHandleScope(const EscapableHandleScope &); + void operator=(const EscapableHandleScope &); + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } +}; + +//=== TryCatch ================================================================= + +class TryCatch { + v8::TryCatch try_catch_; + friend void FatalException(const TryCatch&); + + public: +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + TryCatch() : try_catch_(v8::Isolate::GetCurrent()) {} +#endif + + inline bool HasCaught() const { return try_catch_.HasCaught(); } + + inline bool CanContinue() const { return try_catch_.CanContinue(); } + + inline v8::Local ReThrow() { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + return New(try_catch_.ReThrow()); +#else + return try_catch_.ReThrow(); +#endif + } + + inline v8::Local Exception() const { + return try_catch_.Exception(); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline v8::MaybeLocal StackTrace() const { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(try_catch_.StackTrace(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } +#else + inline MaybeLocal StackTrace() const { + return try_catch_.StackTrace(); + } +#endif + + inline v8::Local Message() const { + return try_catch_.Message(); + } + + inline void Reset() { try_catch_.Reset(); } + + inline void SetVerbose(bool value) { try_catch_.SetVerbose(value); } + + inline void SetCaptureMessage(bool value) { + try_catch_.SetCaptureMessage(value); + } +}; + +v8::Local MakeCallback(v8::Local target, + v8::Local func, + int argc, + v8::Local* argv); +v8::Local MakeCallback(v8::Local target, + v8::Local symbol, + int argc, + v8::Local* argv); +v8::Local MakeCallback(v8::Local target, + const char* method, + int argc, + v8::Local* argv); + +// === AsyncResource =========================================================== + +class AsyncResource { + public: + AsyncResource( + v8::Local name + , v8::Local resource = New()) { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + + if (resource.IsEmpty()) { + resource = New(); + } + + context = node::EmitAsyncInit(isolate, resource, name); +#endif + } + + AsyncResource( + const char* name + , v8::Local resource = New()) { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + + if (resource.IsEmpty()) { + resource = New(); + } + + v8::Local name_string = + New(name).ToLocalChecked(); + context = node::EmitAsyncInit(isolate, resource, name_string); +#endif + } + + ~AsyncResource() { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + node::EmitAsyncDestroy(isolate, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, func, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, symbol, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, method, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv, context); +#endif + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncResource) +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + node::async_context context; +#endif +}; + +//============ ================================================================= + +/* node 0.12 */ +#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION + inline + void SetCounterFunction(v8::CounterLookupCallback cb) { + v8::Isolate::GetCurrent()->SetCounterFunction(cb); + } + + inline + void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) { + v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb); + } + + inline + void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) { + v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline bool IdleNotification(int idle_time_in_ms) { + return v8::Isolate::GetCurrent()->IdleNotificationDeadline( + idle_time_in_ms * 0.001); + } +# else + inline bool IdleNotification(int idle_time_in_ms) { + return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms); + } +#endif + + inline void LowMemoryNotification() { + v8::Isolate::GetCurrent()->LowMemoryNotification(); + } + + inline void ContextDisposedNotification() { + v8::Isolate::GetCurrent()->ContextDisposedNotification(); + } +#else + inline + void SetCounterFunction(v8::CounterLookupCallback cb) { + v8::V8::SetCounterFunction(cb); + } + + inline + void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) { + v8::V8::SetCreateHistogramFunction(cb); + } + + inline + void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) { + v8::V8::SetAddHistogramSampleFunction(cb); + } + + inline bool IdleNotification(int idle_time_in_ms) { + return v8::V8::IdleNotification(idle_time_in_ms); + } + + inline void LowMemoryNotification() { + v8::V8::LowMemoryNotification(); + } + + inline void ContextDisposedNotification() { + v8::V8::ContextDisposedNotification(); + } +#endif + +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) // Node 0.12 + inline v8::Local Undefined() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::Undefined(v8::Isolate::GetCurrent()))); +# else + return v8::Undefined(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local Null() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::Null(v8::Isolate::GetCurrent()))); +# else + return v8::Null(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local True() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::True(v8::Isolate::GetCurrent()))); +# else + return v8::True(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local False() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::False(v8::Isolate::GetCurrent()))); +# else + return v8::False(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local EmptyString() { + return v8::String::Empty(v8::Isolate::GetCurrent()); + } + + inline int AdjustExternalMemory(int bc) { + return static_cast( + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); + } + + inline void SetTemplate( + v8::Local templ + , const char *name + , v8::Local value) { + templ->Set(v8::Isolate::GetCurrent(), name, value); + } + + inline void SetTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + inline v8::Local GetCurrentContext() { + return v8::Isolate::GetCurrent()->GetCurrentContext(); + } + + inline void* GetInternalFieldPointer( + v8::Local object + , int index) { + return object->GetAlignedPointerFromInternalField(index); + } + + inline void SetInternalFieldPointer( + v8::Local object + , int index + , void* value) { + object->SetAlignedPointerInInternalField(index, value); + } + +# define NAN_GC_CALLBACK(name) \ + void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags) + +#if NODE_MODULE_VERSION <= NODE_4_0_MODULE_VERSION + typedef v8::Isolate::GCEpilogueCallback GCEpilogueCallback; + typedef v8::Isolate::GCPrologueCallback GCPrologueCallback; +#else + typedef v8::Isolate::GCCallback GCEpilogueCallback; + typedef v8::Isolate::GCCallback GCPrologueCallback; +#endif + + inline void AddGCEpilogueCallback( + GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); + } + + inline void RemoveGCEpilogueCallback( + GCEpilogueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); + } + + inline void AddGCPrologueCallback( + GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); + } + + inline void RemoveGCPrologueCallback( + GCPrologueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); + } + + inline void GetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); + } + +# define X(NAME) \ + inline v8::Local NAME(const char *msg) { \ + EscapableHandleScope scope; \ + return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + v8::Local NAME(v8::Local msg) { \ + return v8::Exception::NAME(msg); \ + } \ + \ + inline void Throw ## NAME(const char *msg) { \ + HandleScope scope; \ + v8::Isolate::GetCurrent()->ThrowException( \ + v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline void Throw ## NAME(v8::Local msg) { \ + HandleScope scope; \ + v8::Isolate::GetCurrent()->ThrowException( \ + v8::Exception::NAME(msg)); \ + } + + X(Error) + X(RangeError) + X(ReferenceError) + X(SyntaxError) + X(TypeError) + +# undef X + + inline void ThrowError(v8::Local error) { + v8::Isolate::GetCurrent()->ThrowException(error); + } + + inline MaybeLocal NewBuffer( + char *data + , size_t length +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + , node::Buffer::FreeCallback callback +#else + , node::smalloc::FreeCallback callback +#endif + , void *hint + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(length <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New( + v8::Isolate::GetCurrent(), data, length, callback, hint); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), data, length, callback, + hint); +#endif + } + + inline MaybeLocal CopyBuffer( + const char *data + , uint32_t size + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::Copy( + v8::Isolate::GetCurrent(), data, size); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); +#endif + } + + inline MaybeLocal NewBuffer(uint32_t size) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New( + v8::Isolate::GetCurrent(), size); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), size); +#endif + } + + inline MaybeLocal NewBuffer( + char* data + , uint32_t size + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); +#else + return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); +#endif + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value, + v8::NewStringType::kNormal, length); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source source(s, origin); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source source(s); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(script->BindToCurrentContext() + ->Run(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(script->Run(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } +#else + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::ScriptCompiler::Source source(s, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + v8::ScriptCompiler::Source source(s); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + EscapableHandleScope scope; + return scope.Escape(script->BindToCurrentContext()->Run()); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + return script->Run(); + } +#endif + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, func, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, symbol, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, method, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + inline void FatalException(const TryCatch& try_catch) { + node::FatalException(v8::Isolate::GetCurrent(), try_catch.try_catch_); + } + + inline v8::Local ErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return node::ErrnoException(v8::Isolate::GetCurrent(), errorno, syscall, + message, path); + } + + NAN_DEPRECATED inline v8::Local NanErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return ErrnoException(errorno, syscall, message, path); + } + + template + inline void SetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(0, data); + } + + template + inline T *GetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData(0)); + } + +class Utf8String { + public: + inline explicit Utf8String(v8::Local from) : + length_(0), str_(str_st_) { + HandleScope scope; + if (!from.IsEmpty()) { + v8::Local string = from->ToString(); + if (!string.IsEmpty()) { + size_t len = 3 * string->Length() + 1; + assert(len <= INT_MAX); + if (len > sizeof (str_st_)) { + str_ = static_cast(malloc(len)); + assert(str_ != 0); + } + const int flags = + v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8; + length_ = string->WriteUtf8(str_, static_cast(len), 0, flags); + str_[length_] = '\0'; + } + } + } + + inline int length() const { + return length_; + } + + inline char* operator*() { return str_; } + inline const char* operator*() const { return str_; } + + inline ~Utf8String() { + if (str_ != str_st_) { + free(str_); + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String) + + int length_; + char *str_; + char str_st_[1024]; +}; + +#else // Node 0.8 and 0.10 + inline v8::Local Undefined() { + EscapableHandleScope scope; + return scope.Escape(New(v8::Undefined())); + } + + inline v8::Local Null() { + EscapableHandleScope scope; + return scope.Escape(New(v8::Null())); + } + + inline v8::Local True() { + EscapableHandleScope scope; + return scope.Escape(New(v8::True())); + } + + inline v8::Local False() { + EscapableHandleScope scope; + return scope.Escape(New(v8::False())); + } + + inline v8::Local EmptyString() { + return v8::String::Empty(); + } + + inline int AdjustExternalMemory(int bc) { + return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); + } + + inline void SetTemplate( + v8::Local templ + , const char *name + , v8::Local value) { + templ->Set(name, value); + } + + inline void SetTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + inline v8::Local GetCurrentContext() { + return v8::Context::GetCurrent(); + } + + inline void* GetInternalFieldPointer( + v8::Local object + , int index) { + return object->GetPointerFromInternalField(index); + } + + inline void SetInternalFieldPointer( + v8::Local object + , int index + , void* value) { + object->SetPointerInInternalField(index, value); + } + +# define NAN_GC_CALLBACK(name) \ + void name(v8::GCType type, v8::GCCallbackFlags flags) + + inline void AddGCEpilogueCallback( + v8::GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); + } + inline void RemoveGCEpilogueCallback( + v8::GCEpilogueCallback callback) { + v8::V8::RemoveGCEpilogueCallback(callback); + } + inline void AddGCPrologueCallback( + v8::GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCPrologueCallback(callback, gc_type_filter); + } + inline void RemoveGCPrologueCallback( + v8::GCPrologueCallback callback) { + v8::V8::RemoveGCPrologueCallback(callback); + } + inline void GetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::V8::GetHeapStatistics(heap_statistics); + } + +# define X(NAME) \ + inline v8::Local NAME(const char *msg) { \ + EscapableHandleScope scope; \ + return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + v8::Local NAME(v8::Local msg) { \ + return v8::Exception::NAME(msg); \ + } \ + \ + inline void Throw ## NAME(const char *msg) { \ + HandleScope scope; \ + v8::ThrowException(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + void Throw ## NAME(v8::Local errmsg) { \ + HandleScope scope; \ + v8::ThrowException(v8::Exception::NAME(errmsg)); \ + } + + X(Error) + X(RangeError) + X(ReferenceError) + X(SyntaxError) + X(TypeError) + +# undef X + + inline void ThrowError(v8::Local error) { + v8::ThrowException(error); + } + + inline MaybeLocal NewBuffer( + char *data + , size_t length + , node::Buffer::free_callback callback + , void *hint + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(length <= imp::kMaxLength && "too large buffer"); + return scope.Escape( + New(node::Buffer::New(data, length, callback, hint)->handle_)); + } + + inline MaybeLocal CopyBuffer( + const char *data + , uint32_t size + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION + return scope.Escape(New(node::Buffer::New(data, size)->handle_)); +#else + return scope.Escape( + New(node::Buffer::New(const_cast(data), size)->handle_)); +#endif + } + + inline MaybeLocal NewBuffer(uint32_t size) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + assert(size <= imp::kMaxLength && "too large buffer"); + return scope.Escape(New(node::Buffer::New(size)->handle_)); + } + + inline void FreeData(char *data, void *hint) { + (void) hint; // unused + delete[] data; + } + + inline MaybeLocal NewBuffer( + char* data + , uint32_t size + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); + return scope.Escape( + New(node::Buffer::New(data, size, FreeData, NULL)->handle_)); + } + +namespace imp { +inline void +widenString(std::vector *ws, const uint8_t *s, int l) { + size_t len = static_cast(l); + if (l < 0) { + len = strlen(reinterpret_cast(s)); + } + assert(len <= INT_MAX && "string too long"); + ws->resize(len); + std::copy(s, s + len, ws->begin()); // NOLINT(build/include_what_you_use) +} +} // end of namespace imp + + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + std::vector wideString; // NOLINT(build/include_what_you_use) + imp::widenString(&wideString, value, length); + return v8::String::New(wideString.data(), + static_cast(wideString.size())); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + return v8::Script::Compile(s, const_cast(&origin)); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + return v8::Script::Compile(s); + } + + inline + MaybeLocal RunScript(v8::Local script) { + return script->Run(); + } + + inline v8::Local MakeCallback( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, func, argc, argv))); + } + + inline v8::Local MakeCallback( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, symbol, argc, argv))); + } + + inline v8::Local MakeCallback( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, method, argc, argv))); + } + + inline void FatalException(const TryCatch& try_catch) { + node::FatalException(const_cast(try_catch.try_catch_)); + } + + inline v8::Local ErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return node::ErrnoException(errorno, syscall, message, path); + } + + NAN_DEPRECATED inline v8::Local NanErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return ErrnoException(errorno, syscall, message, path); + } + + + template + inline void SetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(data); + } + + template + inline T *GetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData()); + } + +class Utf8String { + public: + inline explicit Utf8String(v8::Local from) : + length_(0), str_(str_st_) { + v8::HandleScope scope; + if (!from.IsEmpty()) { + v8::Local string = from->ToString(); + if (!string.IsEmpty()) { + size_t len = 3 * string->Length() + 1; + assert(len <= INT_MAX); + if (len > sizeof (str_st_)) { + str_ = static_cast(malloc(len)); + assert(str_ != 0); + } + const int flags = + v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8; + length_ = string->WriteUtf8(str_, static_cast(len), 0, flags); + str_[length_] = '\0'; + } + } + } + + inline int length() const { + return length_; + } + + inline char* operator*() { return str_; } + inline const char* operator*() const { return str_; } + + inline ~Utf8String() { + if (str_ != str_st_) { + free(str_); + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String) + + int length_; + char *str_; + char str_st_[1024]; +}; + +#endif // NODE_MODULE_VERSION + +typedef void (*FreeCallback)(char *data, void *hint); + +typedef const FunctionCallbackInfo& NAN_METHOD_ARGS_TYPE; +typedef void NAN_METHOD_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_GETTER_ARGS_TYPE; +typedef void NAN_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_SETTER_ARGS_TYPE; +typedef void NAN_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_GETTER_ARGS_TYPE; +typedef void NAN_PROPERTY_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_SETTER_ARGS_TYPE; +typedef void NAN_PROPERTY_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_ENUMERATOR_ARGS_TYPE; +typedef void NAN_PROPERTY_ENUMERATOR_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_DELETER_ARGS_TYPE; +typedef void NAN_PROPERTY_DELETER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_QUERY_ARGS_TYPE; +typedef void NAN_PROPERTY_QUERY_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_INDEX_GETTER_ARGS_TYPE; +typedef void NAN_INDEX_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_INDEX_SETTER_ARGS_TYPE; +typedef void NAN_INDEX_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_ENUMERATOR_ARGS_TYPE; +typedef void NAN_INDEX_ENUMERATOR_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_DELETER_ARGS_TYPE; +typedef void NAN_INDEX_DELETER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_QUERY_ARGS_TYPE; +typedef void NAN_INDEX_QUERY_RETURN_TYPE; + +#define NAN_METHOD(name) \ + Nan::NAN_METHOD_RETURN_TYPE name(Nan::NAN_METHOD_ARGS_TYPE info) +#define NAN_GETTER(name) \ + Nan::NAN_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_GETTER_ARGS_TYPE info) +#define NAN_SETTER(name) \ + Nan::NAN_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , Nan::NAN_SETTER_ARGS_TYPE info) +#define NAN_PROPERTY_GETTER(name) \ + Nan::NAN_PROPERTY_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_GETTER_ARGS_TYPE info) +#define NAN_PROPERTY_SETTER(name) \ + Nan::NAN_PROPERTY_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info) +#define NAN_PROPERTY_ENUMERATOR(name) \ + Nan::NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name( \ + Nan::NAN_PROPERTY_ENUMERATOR_ARGS_TYPE info) +#define NAN_PROPERTY_DELETER(name) \ + Nan::NAN_PROPERTY_DELETER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_DELETER_ARGS_TYPE info) +#define NAN_PROPERTY_QUERY(name) \ + Nan::NAN_PROPERTY_QUERY_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_QUERY_ARGS_TYPE info) +# define NAN_INDEX_GETTER(name) \ + Nan::NAN_INDEX_GETTER_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_GETTER_ARGS_TYPE info) +#define NAN_INDEX_SETTER(name) \ + Nan::NAN_INDEX_SETTER_RETURN_TYPE name( \ + uint32_t index \ + , v8::Local value \ + , Nan::NAN_INDEX_SETTER_ARGS_TYPE info) +#define NAN_INDEX_ENUMERATOR(name) \ + Nan::NAN_INDEX_ENUMERATOR_RETURN_TYPE \ + name(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE info) +#define NAN_INDEX_DELETER(name) \ + Nan::NAN_INDEX_DELETER_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_DELETER_ARGS_TYPE info) +#define NAN_INDEX_QUERY(name) \ + Nan::NAN_INDEX_QUERY_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_QUERY_ARGS_TYPE info) + +class Callback { + public: + Callback() {} + + explicit Callback(const v8::Local &fn) : handle_(fn) {} + + ~Callback() { + handle_.Reset(); + } + + bool operator==(const Callback &other) const { + return handle_ == other.handle_; + } + + bool operator!=(const Callback &other) const { + return !operator==(other); + } + + inline + v8::Local operator*() const { return GetFunction(); } + + NAN_DEPRECATED inline v8::Local operator()( + v8::Local target + , int argc = 0 + , v8::Local argv[] = 0) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:operator()"); + return Call_(isolate, target, argc, argv, &async) + .FromMaybe(v8::Local()); +# else + return Call_(isolate, target, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + return Call_(target, argc, argv); +#endif // NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local operator()( + int argc = 0 + , v8::Local argv[] = 0) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:operator()"); + return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(), + argc, argv, &async) + .FromMaybe(v8::Local())); +# else + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif // NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + } + + inline MaybeLocal operator()( + AsyncResource* resource + , int argc = 0 + , v8::Local argv[] = 0) const { + return this->Call(argc, argv, resource); + } + + inline MaybeLocal operator()( + AsyncResource* resource + , v8::Local target + , int argc = 0 + , v8::Local argv[] = 0) const { + return this->Call(target, argc, argv, resource); + } + + // TODO(kkoopa): remove + inline void SetFunction(const v8::Local &fn) { + Reset(fn); + } + + inline void Reset(const v8::Local &fn) { + handle_.Reset(fn); + } + + inline void Reset() { + handle_.Reset(); + } + + inline v8::Local GetFunction() const { + return New(handle_); + } + + inline bool IsEmpty() const { + return handle_.IsEmpty(); + } + + // Deprecated: For async callbacks Use the versions that accept an + // AsyncResource. If this callback does not correspond to an async resource, + // that is, it is a synchronous function call on a non-empty JS stack, you + // should Nan::Call instead. + NAN_DEPRECATED inline v8::Local + Call(v8::Local target + , int argc + , v8::Local argv[]) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:Call"); + return Call_(isolate, target, argc, argv, &async) + .FromMaybe(v8::Local()); +# else + return Call_(isolate, target, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + return Call_(target, argc, argv); +#endif + } + + // Deprecated: For async callbacks Use the versions that accept an + // AsyncResource. If this callback does not correspond to an async resource, + // that is, it is a synchronous function call on a non-empty JS stack, you + // should Nan::Call instead. + NAN_DEPRECATED inline v8::Local + Call(int argc, v8::Local argv[]) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:Call"); + return Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv, + &async) + .FromMaybe(v8::Local()); +# else + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif + } + + inline MaybeLocal + Call(v8::Local target + , int argc + , v8::Local argv[] + , AsyncResource* resource) const { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return Call_(isolate, target, argc, argv, resource); +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + return Call_(isolate, target, argc, argv); +#else + return Call_(target, argc, argv); +#endif + } + + inline MaybeLocal + Call(int argc, v8::Local argv[], AsyncResource* resource) const { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return Call(isolate->GetCurrentContext()->Global(), argc, argv, resource); +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Callback) + Persistent handle_; + +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + MaybeLocal Call_(v8::Isolate *isolate + , v8::Local target + , int argc + , v8::Local argv[] + , AsyncResource* resource) const { + EscapableHandleScope scope; + v8::Local func = New(handle_); + auto maybe = resource->runInAsyncScope(target, func, argc, argv); + v8::Local local; + if (!maybe.ToLocal(&local)) return MaybeLocal(); + return scope.Escape(local); + } +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Local Call_(v8::Isolate *isolate + , v8::Local target + , int argc + , v8::Local argv[]) const { + EscapableHandleScope scope; + + v8::Local callback = New(handle_); +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + return scope.Escape(New(node::MakeCallback( + isolate + , target + , callback + , argc + , argv + ))); +# else + return scope.Escape(node::MakeCallback( + isolate + , target + , callback + , argc + , argv + )); +# endif + } +#else + v8::Local Call_(v8::Local target + , int argc + , v8::Local argv[]) const { + EscapableHandleScope scope; + + v8::Local callback = New(handle_); + return scope.Escape(New(node::MakeCallback( + target + , callback + , argc + , argv + ))); + } +#endif +}; + +inline MaybeLocal Call( + const Nan::Callback& callback + , v8::Local recv + , int argc + , v8::Local argv[]) { + return Call(*callback, recv, argc, argv); +} + +inline MaybeLocal Call( + const Nan::Callback& callback + , int argc + , v8::Local argv[]) { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + Call(*callback, isolate->GetCurrentContext()->Global(), argc, argv) + .FromMaybe(v8::Local())); +#else + EscapableHandleScope scope; + return scope.Escape( + Call(*callback, v8::Context::GetCurrent()->Global(), argc, argv) + .FromMaybe(v8::Local())); +#endif +} + +inline MaybeLocal Call( + v8::Local symbol + , v8::Local recv + , int argc + , v8::Local argv[]) { + EscapableHandleScope scope; + v8::Local fn_v = + Get(recv, symbol).FromMaybe(v8::Local()); + if (fn_v.IsEmpty() || !fn_v->IsFunction()) return v8::Local(); + v8::Local fn = fn_v.As(); + return scope.Escape( + Call(fn, recv, argc, argv).FromMaybe(v8::Local())); +} + +inline MaybeLocal Call( + const char* method + , v8::Local recv + , int argc + , v8::Local argv[]) { + EscapableHandleScope scope; + v8::Local method_string = + New(method).ToLocalChecked(); + return scope.Escape( + Call(method_string, recv, argc, argv).FromMaybe(v8::Local())); +} + +/* abstract */ class AsyncWorker { + public: + explicit AsyncWorker(Callback *callback_, + const char* resource_name = "nan:AsyncWorker") + : callback(callback_), errmsg_(NULL) { + request.data = this; + + HandleScope scope; + v8::Local obj = New(); + persistentHandle.Reset(obj); + async_resource = new AsyncResource(resource_name, obj); + } + + virtual ~AsyncWorker() { + HandleScope scope; + + if (!persistentHandle.IsEmpty()) + persistentHandle.Reset(); + delete callback; + delete[] errmsg_; + delete async_resource; + } + + virtual void WorkComplete() { + HandleScope scope; + + if (errmsg_ == NULL) + HandleOKCallback(); + else + HandleErrorCallback(); + delete callback; + callback = NULL; + } + + inline void SaveToPersistent( + const char *key, const v8::Local &value) { + HandleScope scope; + New(persistentHandle)->Set(New(key).ToLocalChecked(), value); + } + + inline void SaveToPersistent( + const v8::Local &key, const v8::Local &value) { + HandleScope scope; + New(persistentHandle)->Set(key, value); + } + + inline void SaveToPersistent( + uint32_t index, const v8::Local &value) { + HandleScope scope; + New(persistentHandle)->Set(index, value); + } + + inline v8::Local GetFromPersistent(const char *key) const { + EscapableHandleScope scope; + return scope.Escape( + New(persistentHandle)->Get(New(key).ToLocalChecked())); + } + + inline v8::Local + GetFromPersistent(const v8::Local &key) const { + EscapableHandleScope scope; + return scope.Escape(New(persistentHandle)->Get(key)); + } + + inline v8::Local GetFromPersistent(uint32_t index) const { + EscapableHandleScope scope; + return scope.Escape(New(persistentHandle)->Get(index)); + } + + virtual void Execute() = 0; + + uv_work_t request; + + virtual void Destroy() { + delete this; + } + + protected: + Persistent persistentHandle; + Callback *callback; + AsyncResource *async_resource; + + virtual void HandleOKCallback() { + HandleScope scope; + + callback->Call(0, NULL, async_resource); + } + + virtual void HandleErrorCallback() { + HandleScope scope; + + v8::Local argv[] = { + v8::Exception::Error(New(ErrorMessage()).ToLocalChecked()) + }; + callback->Call(1, argv, async_resource); + } + + void SetErrorMessage(const char *msg) { + delete[] errmsg_; + + size_t size = strlen(msg) + 1; + errmsg_ = new char[size]; + memcpy(errmsg_, msg, size); + } + + const char* ErrorMessage() const { + return errmsg_; + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncWorker) + char *errmsg_; +}; + +/* abstract */ class AsyncBareProgressWorkerBase : public AsyncWorker { + public: + explicit AsyncBareProgressWorkerBase( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressWorkerBase") + : AsyncWorker(callback_, resource_name) { + uv_async_init( + uv_default_loop() + , &async + , AsyncProgress_ + ); + async.data = this; + } + + virtual ~AsyncBareProgressWorkerBase() { + } + + virtual void WorkProgress() = 0; + + virtual void Destroy() { + uv_close(reinterpret_cast(&async), AsyncClose_); + } + + private: + inline static NAUV_WORK_CB(AsyncProgress_) { + AsyncBareProgressWorkerBase *worker = + static_cast(async->data); + worker->WorkProgress(); + } + + inline static void AsyncClose_(uv_handle_t* handle) { + AsyncBareProgressWorkerBase *worker = + static_cast(handle->data); + delete worker; + } + + protected: + uv_async_t async; +}; + +template +/* abstract */ +class AsyncBareProgressWorker : public AsyncBareProgressWorkerBase { + public: + explicit AsyncBareProgressWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressWorker") + : AsyncBareProgressWorkerBase(callback_, resource_name) { + } + + virtual ~AsyncBareProgressWorker() { + } + + class ExecutionProgress { + friend class AsyncBareProgressWorker; + public: + void Signal() const { + uv_async_send(&that_->async); + } + + void Send(const T* data, size_t count) const { + that_->SendProgress_(data, count); + } + + private: + explicit ExecutionProgress(AsyncBareProgressWorker *that) : that_(that) {} + NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress) + AsyncBareProgressWorker* const that_; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + virtual void HandleProgressCallback(const T *data, size_t size) = 0; + + private: + void Execute() /*final override*/ { + ExecutionProgress progress(this); + Execute(progress); + } + + virtual void SendProgress_(const T *data, size_t count) = 0; +}; + +template +/* abstract */ +class AsyncProgressWorkerBase : public AsyncBareProgressWorker { + public: + explicit AsyncProgressWorkerBase( + Callback *callback_, + const char* resource_name = "nan:AsyncProgressWorkerBase") + : AsyncBareProgressWorker(callback_, resource_name), asyncdata_(NULL), + asyncsize_(0) { + uv_mutex_init(&async_lock); + } + + virtual ~AsyncProgressWorkerBase() { + uv_mutex_destroy(&async_lock); + + delete[] asyncdata_; + } + + void WorkProgress() { + uv_mutex_lock(&async_lock); + T *data = asyncdata_; + size_t size = asyncsize_; + asyncdata_ = NULL; + uv_mutex_unlock(&async_lock); + + // Don't send progress events after we've already completed. + if (this->callback) { + this->HandleProgressCallback(data, size); + } + delete[] data; + } + + private: + void SendProgress_(const T *data, size_t count) { + T *new_data = new T[count]; + { + T *it = new_data; + std::copy(data, data + count, it); + } + + uv_mutex_lock(&async_lock); + T *old_data = asyncdata_; + asyncdata_ = new_data; + asyncsize_ = count; + uv_mutex_unlock(&async_lock); + + delete[] old_data; + uv_async_send(&this->async); + } + + uv_mutex_t async_lock; + T *asyncdata_; + size_t asyncsize_; +}; + +// This ensures compatibility to the previous un-templated AsyncProgressWorker +// class definition. +typedef AsyncProgressWorkerBase AsyncProgressWorker; + +template +/* abstract */ +class AsyncBareProgressQueueWorker : public AsyncBareProgressWorkerBase { + public: + explicit AsyncBareProgressQueueWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressQueueWorker") + : AsyncBareProgressWorkerBase(callback_, resource_name) { + } + + virtual ~AsyncBareProgressQueueWorker() { + } + + class ExecutionProgress { + friend class AsyncBareProgressQueueWorker; + public: + void Send(const T* data, size_t count) const { + that_->SendProgress_(data, count); + } + + private: + explicit ExecutionProgress(AsyncBareProgressQueueWorker *that) + : that_(that) {} + NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress) + AsyncBareProgressQueueWorker* const that_; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + virtual void HandleProgressCallback(const T *data, size_t size) = 0; + + private: + void Execute() /*final override*/ { + ExecutionProgress progress(this); + Execute(progress); + } + + virtual void SendProgress_(const T *data, size_t count) = 0; +}; + +template +/* abstract */ +class AsyncProgressQueueWorker : public AsyncBareProgressQueueWorker { + public: + explicit AsyncProgressQueueWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncProgressQueueWorker") + : AsyncBareProgressQueueWorker(callback_) { + uv_mutex_init(&async_lock); + } + + virtual ~AsyncProgressQueueWorker() { + uv_mutex_lock(&async_lock); + + while (!asyncdata_.empty()) { + std::pair &datapair = asyncdata_.front(); + T *data = datapair.first; + + asyncdata_.pop(); + + delete[] data; + } + + uv_mutex_unlock(&async_lock); + uv_mutex_destroy(&async_lock); + } + + void WorkComplete() { + WorkProgress(); + AsyncWorker::WorkComplete(); + } + + void WorkProgress() { + uv_mutex_lock(&async_lock); + + while (!asyncdata_.empty()) { + std::pair &datapair = asyncdata_.front(); + + T *data = datapair.first; + size_t size = datapair.second; + + asyncdata_.pop(); + uv_mutex_unlock(&async_lock); + + // Don't send progress events after we've already completed. + if (this->callback) { + this->HandleProgressCallback(data, size); + } + + delete[] data; + + uv_mutex_lock(&async_lock); + } + + uv_mutex_unlock(&async_lock); + } + + private: + void SendProgress_(const T *data, size_t count) { + T *new_data = new T[count]; + { + T *it = new_data; + std::copy(data, data + count, it); + } + + uv_mutex_lock(&async_lock); + asyncdata_.push(std::pair(new_data, count)); + uv_mutex_unlock(&async_lock); + + uv_async_send(&this->async); + } + + uv_mutex_t async_lock; + std::queue > asyncdata_; +}; + +inline void AsyncExecute (uv_work_t* req) { + AsyncWorker *worker = static_cast(req->data); + worker->Execute(); +} + +inline void AsyncExecuteComplete (uv_work_t* req) { + AsyncWorker* worker = static_cast(req->data); + worker->WorkComplete(); + worker->Destroy(); +} + +inline void AsyncQueueWorker (AsyncWorker* worker) { + uv_queue_work( + uv_default_loop() + , &worker->request + , AsyncExecute + , reinterpret_cast(AsyncExecuteComplete) + ); +} + +namespace imp { + +inline +ExternalOneByteStringResource const* +GetExternalResource(v8::Local str) { +#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION + return str->GetExternalAsciiStringResource(); +#else + return str->GetExternalOneByteStringResource(); +#endif +} + +inline +bool +IsExternal(v8::Local str) { +#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION + return str->IsExternalAscii(); +#else + return str->IsExternalOneByte(); +#endif +} + +} // end of namespace imp + +enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; + +#if NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION +# include "nan_string_bytes.h" // NOLINT(build/include) +#endif + +inline v8::Local Encode( + const void *buf, size_t len, enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + node::encoding node_enc = static_cast(encoding); + + if (encoding == UCS2) { + return node::Encode( + isolate + , reinterpret_cast(buf) + , len / 2); + } else { + return node::Encode( + isolate + , reinterpret_cast(buf) + , len + , node_enc); + } +#elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::Encode( + v8::Isolate::GetCurrent() + , buf, len + , static_cast(encoding)); +#else +# if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION + return node::Encode(buf, len, static_cast(encoding)); +# else + return imp::Encode(reinterpret_cast(buf), len, encoding); +# endif +#endif +} + +inline ssize_t DecodeBytes( + v8::Local val, enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::DecodeBytes( + v8::Isolate::GetCurrent() + , val + , static_cast(encoding)); +#else +# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION) + if (encoding == BUFFER) { + return node::DecodeBytes(val, node::BINARY); + } +# endif + return node::DecodeBytes(val, static_cast(encoding)); +#endif +} + +inline ssize_t DecodeWrite( + char *buf + , size_t len + , v8::Local val + , enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::DecodeWrite( + v8::Isolate::GetCurrent() + , buf + , len + , val + , static_cast(encoding)); +#else +# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION) + if (encoding == BUFFER) { + return node::DecodeWrite(buf, len, val, node::BINARY); + } +# endif + return node::DecodeWrite( + buf + , len + , val + , static_cast(encoding)); +#endif +} + +inline void SetPrototypeTemplate( + v8::Local templ + , const char *name + , v8::Local value +) { + HandleScope scope; + SetTemplate(templ->PrototypeTemplate(), name, value); +} + +inline void SetPrototypeTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes +) { + HandleScope scope; + SetTemplate(templ->PrototypeTemplate(), name, value, attributes); +} + +inline void SetInstanceTemplate( + v8::Local templ + , const char *name + , v8::Local value +) { + HandleScope scope; + SetTemplate(templ->InstanceTemplate(), name, value); +} + +inline void SetInstanceTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes +) { + HandleScope scope; + SetTemplate(templ->InstanceTemplate(), name, value, attributes); +} + +namespace imp { + +// Note(@agnat): Helper to distinguish different receiver types. The first +// version deals with receivers derived from v8::Template. The second version +// handles everything else. The final argument only serves as discriminator and +// is unused. +template +inline +void +SetMethodAux(T recv, + v8::Local name, + v8::Local tpl, + v8::Template *) { + recv->Set(name, tpl); +} + +template +inline +void +SetMethodAux(T recv, + v8::Local name, + v8::Local tpl, + ...) { + recv->Set(name, GetFunction(tpl).ToLocalChecked()); +} + +} // end of namespace imp + +template class HandleType> +inline void SetMethod( + HandleType recv + , const char *name + , FunctionCallback callback) { + HandleScope scope; + v8::Local t = New(callback); + v8::Local fn_name = New(name).ToLocalChecked(); + t->SetClassName(fn_name); + // Note(@agnat): Pass an empty T* as discriminator. See note on + // SetMethodAux(...) above + imp::SetMethodAux(recv, fn_name, t, static_cast(0)); +} + +inline void SetPrototypeMethod( + v8::Local recv + , const char* name, FunctionCallback callback) { + HandleScope scope; + v8::Local t = New( + callback + , v8::Local() + , New(recv)); + v8::Local fn_name = New(name).ToLocalChecked(); + recv->PrototypeTemplate()->Set(fn_name, t); + t->SetClassName(fn_name); +} + +//=== Accessors and Such ======================================================= + +inline void SetAccessor( + v8::Local tpl + , v8::Local name + , GetterCallback getter + , SetterCallback setter = 0 + , v8::Local data = v8::Local() + , v8::AccessControl settings = v8::DEFAULT + , v8::PropertyAttribute attribute = v8::None + , imp::Sig signature = imp::Sig()) { + HandleScope scope; + + imp::NativeGetter getter_ = + imp::GetterCallbackWrapper; + imp::NativeSetter setter_ = + setter ? imp::SetterCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kAccessorFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kGetterIndex + , New(reinterpret_cast(getter))); + + if (setter != 0) { + obj->SetInternalField( + imp::kSetterIndex + , New(reinterpret_cast(setter))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetAccessor( + name + , getter_ + , setter_ + , obj + , settings + , attribute + , signature); +} + +inline bool SetAccessor( + v8::Local obj + , v8::Local name + , GetterCallback getter + , SetterCallback setter = 0 + , v8::Local data = v8::Local() + , v8::AccessControl settings = v8::DEFAULT + , v8::PropertyAttribute attribute = v8::None) { + HandleScope scope; + + imp::NativeGetter getter_ = + imp::GetterCallbackWrapper; + imp::NativeSetter setter_ = + setter ? imp::SetterCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kAccessorFieldCount); + v8::Local dataobj = NewInstance(otpl).ToLocalChecked(); + + dataobj->SetInternalField( + imp::kGetterIndex + , New(reinterpret_cast(getter))); + + if (!data.IsEmpty()) { + dataobj->SetInternalField(imp::kDataIndex, data); + } + + if (setter) { + dataobj->SetInternalField( + imp::kSetterIndex + , New(reinterpret_cast(setter))); + } + +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + return obj->SetAccessor( + GetCurrentContext() + , name + , getter_ + , setter_ + , dataobj + , settings + , attribute).FromMaybe(false); +#else + return obj->SetAccessor( + name + , getter_ + , setter_ + , dataobj + , settings + , attribute); +#endif +} + +inline void SetNamedPropertyHandler( + v8::Local tpl + , PropertyGetterCallback getter + , PropertySetterCallback setter = 0 + , PropertyQueryCallback query = 0 + , PropertyDeleterCallback deleter = 0 + , PropertyEnumeratorCallback enumerator = 0 + , v8::Local data = v8::Local()) { + HandleScope scope; + + imp::NativePropertyGetter getter_ = + imp::PropertyGetterCallbackWrapper; + imp::NativePropertySetter setter_ = + setter ? imp::PropertySetterCallbackWrapper : 0; + imp::NativePropertyQuery query_ = + query ? imp::PropertyQueryCallbackWrapper : 0; + imp::NativePropertyDeleter *deleter_ = + deleter ? imp::PropertyDeleterCallbackWrapper : 0; + imp::NativePropertyEnumerator enumerator_ = + enumerator ? imp::PropertyEnumeratorCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kPropertyFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + obj->SetInternalField( + imp::kPropertyGetterIndex + , New(reinterpret_cast(getter))); + + if (setter) { + obj->SetInternalField( + imp::kPropertySetterIndex + , New(reinterpret_cast(setter))); + } + + if (query) { + obj->SetInternalField( + imp::kPropertyQueryIndex + , New(reinterpret_cast(query))); + } + + if (deleter) { + obj->SetInternalField( + imp::kPropertyDeleterIndex + , New(reinterpret_cast(deleter))); + } + + if (enumerator) { + obj->SetInternalField( + imp::kPropertyEnumeratorIndex + , New(reinterpret_cast(enumerator))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + tpl->SetHandler(v8::NamedPropertyHandlerConfiguration( + getter_, setter_, query_, deleter_, enumerator_, obj)); +#else + tpl->SetNamedPropertyHandler( + getter_ + , setter_ + , query_ + , deleter_ + , enumerator_ + , obj); +#endif +} + +inline void SetIndexedPropertyHandler( + v8::Local tpl + , IndexGetterCallback getter + , IndexSetterCallback setter = 0 + , IndexQueryCallback query = 0 + , IndexDeleterCallback deleter = 0 + , IndexEnumeratorCallback enumerator = 0 + , v8::Local data = v8::Local()) { + HandleScope scope; + + imp::NativeIndexGetter getter_ = + imp::IndexGetterCallbackWrapper; + imp::NativeIndexSetter setter_ = + setter ? imp::IndexSetterCallbackWrapper : 0; + imp::NativeIndexQuery query_ = + query ? imp::IndexQueryCallbackWrapper : 0; + imp::NativeIndexDeleter deleter_ = + deleter ? imp::IndexDeleterCallbackWrapper : 0; + imp::NativeIndexEnumerator enumerator_ = + enumerator ? imp::IndexEnumeratorCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kIndexPropertyFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + obj->SetInternalField( + imp::kIndexPropertyGetterIndex + , New(reinterpret_cast(getter))); + + if (setter) { + obj->SetInternalField( + imp::kIndexPropertySetterIndex + , New(reinterpret_cast(setter))); + } + + if (query) { + obj->SetInternalField( + imp::kIndexPropertyQueryIndex + , New(reinterpret_cast(query))); + } + + if (deleter) { + obj->SetInternalField( + imp::kIndexPropertyDeleterIndex + , New(reinterpret_cast(deleter))); + } + + if (enumerator) { + obj->SetInternalField( + imp::kIndexPropertyEnumeratorIndex + , New(reinterpret_cast(enumerator))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + tpl->SetHandler(v8::IndexedPropertyHandlerConfiguration( + getter_, setter_, query_, deleter_, enumerator_, obj)); +#else + tpl->SetIndexedPropertyHandler( + getter_ + , setter_ + , query_ + , deleter_ + , enumerator_ + , obj); +#endif +} + +inline void SetCallHandler( + v8::Local tpl + , FunctionCallback callback + , v8::Local data = v8::Local()) { + HandleScope scope; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , New(reinterpret_cast(callback))); + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj); +} + + +inline void SetCallAsFunctionHandler( + v8::Local tpl, + FunctionCallback callback, + v8::Local data = v8::Local()) { + HandleScope scope; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , New(reinterpret_cast(callback))); + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj); +} + +//=== Weak Persistent Handling ================================================= + +#include "nan_weak.h" // NOLINT(build/include) + +//=== ObjectWrap =============================================================== + +#include "nan_object_wrap.h" // NOLINT(build/include) + +//=== HiddenValue/Private ====================================================== + +#include "nan_private.h" // NOLINT(build/include) + +//=== Export ================================================================== + +inline +void +Export(ADDON_REGISTER_FUNCTION_ARGS_TYPE target, const char *name, + FunctionCallback f) { + HandleScope scope; + + Set(target, New(name).ToLocalChecked(), + GetFunction(New(f)).ToLocalChecked()); +} + +//=== Tap Reverse Binding ===================================================== + +struct Tap { + explicit Tap(v8::Local t) : t_() { + HandleScope scope; + + t_.Reset(To(t).ToLocalChecked()); + } + + ~Tap() { t_.Reset(); } // not sure if neccessary + + inline void plan(int i) { + HandleScope scope; + v8::Local arg = New(i); + Call("plan", New(t_), 1, &arg); + } + + inline void ok(bool isOk, const char *msg = NULL) { + HandleScope scope; + v8::Local args[2]; + args[0] = New(isOk); + if (msg) args[1] = New(msg).ToLocalChecked(); + Call("ok", New(t_), msg ? 2 : 1, args); + } + + inline void pass(const char * msg = NULL) { + HandleScope scope; + v8::Local hmsg; + if (msg) hmsg = New(msg).ToLocalChecked(); + Call("pass", New(t_), msg ? 1 : 0, &hmsg); + } + + inline void end() { + HandleScope scope; + Call("end", New(t_), 0, NULL); + } + + private: + Persistent t_; +}; + +#define NAN_STRINGIZE2(x) #x +#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x) +#define NAN_TEST_EXPRESSION(expression) \ + ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression + +#define NAN_EXPORT(target, function) Export(target, #function, function) + +#undef TYPE_CHECK + +//=== Generic Maybefication =================================================== + +namespace imp { + +template struct Maybefier; + +template struct Maybefier > { + inline static MaybeLocal convert(v8::Local v) { + return v; + } +}; + +template struct Maybefier > { + inline static MaybeLocal convert(MaybeLocal v) { + return v; + } +}; + +} // end of namespace imp + +template class MaybeMaybe> +inline MaybeLocal +MakeMaybe(MaybeMaybe v) { + return imp::Maybefier >::convert(v); +} + +//=== TypedArrayContents ======================================================= + +#include "nan_typedarray_contents.h" // NOLINT(build/include) + +//=== JSON ===================================================================== + +#include "nan_json.h" // NOLINT(build/include) + +} // end of namespace Nan + +#endif // NAN_H_ diff --git a/deps/node-report/node_modules/nan/nan_callbacks.h b/deps/node-report/node_modules/nan/nan_callbacks.h new file mode 100644 index 00000000000000..53ede846ac9a86 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_callbacks.h @@ -0,0 +1,88 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_H_ +#define NAN_CALLBACKS_H_ + +template class FunctionCallbackInfo; +template class PropertyCallbackInfo; +template class Global; + +typedef void(*FunctionCallback)(const FunctionCallbackInfo&); +typedef void(*GetterCallback) + (v8::Local, const PropertyCallbackInfo&); +typedef void(*SetterCallback)( + v8::Local, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyGetterCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertySetterCallback)( + v8::Local, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyEnumeratorCallback) + (const PropertyCallbackInfo&); +typedef void(*PropertyDeleterCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyQueryCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*IndexGetterCallback)( + uint32_t, + const PropertyCallbackInfo&); +typedef void(*IndexSetterCallback)( + uint32_t, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*IndexEnumeratorCallback) + (const PropertyCallbackInfo&); +typedef void(*IndexDeleterCallback)( + uint32_t, + const PropertyCallbackInfo&); +typedef void(*IndexQueryCallback)( + uint32_t, + const PropertyCallbackInfo&); + +namespace imp { +typedef v8::Local Sig; + +static const int kDataIndex = 0; + +static const int kFunctionIndex = 1; +static const int kFunctionFieldCount = 2; + +static const int kGetterIndex = 1; +static const int kSetterIndex = 2; +static const int kAccessorFieldCount = 3; + +static const int kPropertyGetterIndex = 1; +static const int kPropertySetterIndex = 2; +static const int kPropertyEnumeratorIndex = 3; +static const int kPropertyDeleterIndex = 4; +static const int kPropertyQueryIndex = 5; +static const int kPropertyFieldCount = 6; + +static const int kIndexPropertyGetterIndex = 1; +static const int kIndexPropertySetterIndex = 2; +static const int kIndexPropertyEnumeratorIndex = 3; +static const int kIndexPropertyDeleterIndex = 4; +static const int kIndexPropertyQueryIndex = 5; +static const int kIndexPropertyFieldCount = 6; + +} // end of namespace imp + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# include "nan_callbacks_12_inl.h" // NOLINT(build/include) +#else +# include "nan_callbacks_pre_12_inl.h" // NOLINT(build/include) +#endif + +#endif // NAN_CALLBACKS_H_ diff --git a/deps/node-report/node_modules/nan/nan_callbacks_12_inl.h b/deps/node-report/node_modules/nan/nan_callbacks_12_inl.h new file mode 100644 index 00000000000000..d3df79aaf0e21a --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_callbacks_12_inl.h @@ -0,0 +1,512 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_12_INL_H_ +#define NAN_CALLBACKS_12_INL_H_ + +template +class ReturnValue { + v8::ReturnValue value_; + + public: + template + explicit inline ReturnValue(const v8::ReturnValue &value) : + value_(value) {} + template + explicit inline ReturnValue(const ReturnValue& that) + : value_(that.value_) { + TYPE_CHECK(T, S); + } + + // Handle setters + template inline void Set(const v8::Local &handle) { + TYPE_CHECK(T, S); + value_.Set(handle); + } + + template inline void Set(const Global &handle) { + TYPE_CHECK(T, S); +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && \ + (V8_MINOR_VERSION > 5 || (V8_MINOR_VERSION == 5 && \ + defined(V8_BUILD_NUMBER) && V8_BUILD_NUMBER >= 8)))) + value_.Set(handle); +#else + value_.Set(*reinterpret_cast*>(&handle)); + const_cast &>(handle).Reset(); +#endif + } + + // Fast primitive setters + inline void Set(bool value) { + TYPE_CHECK(T, v8::Boolean); + value_.Set(value); + } + + inline void Set(double i) { + TYPE_CHECK(T, v8::Number); + value_.Set(i); + } + + inline void Set(int32_t i) { + TYPE_CHECK(T, v8::Integer); + value_.Set(i); + } + + inline void Set(uint32_t i) { + TYPE_CHECK(T, v8::Integer); + value_.Set(i); + } + + // Fast JS primitive setters + inline void SetNull() { + TYPE_CHECK(T, v8::Primitive); + value_.SetNull(); + } + + inline void SetUndefined() { + TYPE_CHECK(T, v8::Primitive); + value_.SetUndefined(); + } + + inline void SetEmptyString() { + TYPE_CHECK(T, v8::String); + value_.SetEmptyString(); + } + + // Convenience getter for isolate + inline v8::Isolate *GetIsolate() const { + return value_.GetIsolate(); + } + + // Pointer setter: Uncompilable to prevent inadvertent misuse. + template + inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); } +}; + +template +class FunctionCallbackInfo { + const v8::FunctionCallbackInfo &info_; + const v8::Local data_; + + public: + explicit inline FunctionCallbackInfo( + const v8::FunctionCallbackInfo &info + , v8::Local data) : + info_(info) + , data_(data) {} + + inline ReturnValue GetReturnValue() const { + return ReturnValue(info_.GetReturnValue()); + } + + inline v8::Local Callee() const { return info_.Callee(); } + inline v8::Local Data() const { return data_; } + inline v8::Local Holder() const { return info_.Holder(); } + inline bool IsConstructCall() const { return info_.IsConstructCall(); } + inline int Length() const { return info_.Length(); } + inline v8::Local operator[](int i) const { return info_[i]; } + inline v8::Local This() const { return info_.This(); } + inline v8::Isolate *GetIsolate() const { return info_.GetIsolate(); } + + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kCalleeIndex = 5; + static const int kContextSaveIndex = 6; + static const int kArgsLength = 7; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo) +}; + +template +class PropertyCallbackInfo { + const v8::PropertyCallbackInfo &info_; + const v8::Local data_; + + public: + explicit inline PropertyCallbackInfo( + const v8::PropertyCallbackInfo &info + , const v8::Local data) : + info_(info) + , data_(data) {} + + inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); } + inline v8::Local Data() const { return data_; } + inline v8::Local This() const { return info_.This(); } + inline v8::Local Holder() const { return info_.Holder(); } + inline ReturnValue GetReturnValue() const { + return ReturnValue(info_.GetReturnValue()); + } + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kThisIndex = 5; + static const int kArgsLength = 6; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfo) +}; + +namespace imp { +static +void FunctionCallbackWrapper(const v8::FunctionCallbackInfo &info) { + v8::Local obj = info.Data().As(); + FunctionCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kFunctionIndex).As()->Value())); + FunctionCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + callback(cbinfo); +} + +typedef void (*NativeFunction)(const v8::FunctionCallbackInfo &); + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +static +void GetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativeGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property.As(), value, cbinfo); +} + +typedef void (*NativeSetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); +#else +static +void GetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativeGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativeSetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); +#endif + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +static +void PropertyGetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativePropertyGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property.As(), value, cbinfo); +} + +typedef void (*NativePropertySetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void PropertyEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); +} + +typedef void (*NativePropertyEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (NativePropertyDeleter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertyQueryCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativePropertyQuery) + (v8::Local, const v8::PropertyCallbackInfo &); +#else +static +void PropertyGetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativePropertyGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativePropertySetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void PropertyEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); +} + +typedef void (*NativePropertyEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (NativePropertyDeleter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertyQueryCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativePropertyQuery) + (v8::Local, const v8::PropertyCallbackInfo &); +#endif + +static +void IndexGetterCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyGetterIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexGetter) + (uint32_t, const v8::PropertyCallbackInfo &); + +static +void IndexSetterCallbackWrapper( + uint32_t index + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexSetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertySetterIndex) + .As()->Value())); + callback(index, value, cbinfo); +} + +typedef void (*NativeIndexSetter)( + uint32_t + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void IndexEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexEnumeratorCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField( + kIndexPropertyEnumeratorIndex).As()->Value())); + callback(cbinfo); +} + +typedef void (*NativeIndexEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void IndexDeleterCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyDeleterIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexDeleter) + (uint32_t, const v8::PropertyCallbackInfo &); + +static +void IndexQueryCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyQueryIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexQuery) + (uint32_t, const v8::PropertyCallbackInfo &); +} // end of namespace imp + +#endif // NAN_CALLBACKS_12_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_callbacks_pre_12_inl.h b/deps/node-report/node_modules/nan/nan_callbacks_pre_12_inl.h new file mode 100644 index 00000000000000..c9ba4993205ec4 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_callbacks_pre_12_inl.h @@ -0,0 +1,520 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_PRE_12_INL_H_ +#define NAN_CALLBACKS_PRE_12_INL_H_ + +namespace imp { +template class ReturnValueImp; +} // end of namespace imp + +template +class ReturnValue { + v8::Isolate *isolate_; + v8::Persistent *value_; + friend class imp::ReturnValueImp; + + public: + template + explicit inline ReturnValue(v8::Isolate *isolate, v8::Persistent *p) : + isolate_(isolate), value_(p) {} + template + explicit inline ReturnValue(const ReturnValue& that) + : isolate_(that.isolate_), value_(that.value_) { + TYPE_CHECK(T, S); + } + + // Handle setters + template inline void Set(const v8::Local &handle) { + TYPE_CHECK(T, S); + value_->Dispose(); + *value_ = v8::Persistent::New(handle); + } + + template inline void Set(const Global &handle) { + TYPE_CHECK(T, S); + value_->Dispose(); + *value_ = v8::Persistent::New(handle.persistent); + const_cast &>(handle).Reset(); + } + + // Fast primitive setters + inline void Set(bool value) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Boolean); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Boolean::New(value)); + } + + inline void Set(double i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Number); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Number::New(i)); + } + + inline void Set(int32_t i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Integer); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Int32::New(i)); + } + + inline void Set(uint32_t i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Integer); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Uint32::NewFromUnsigned(i)); + } + + // Fast JS primitive setters + inline void SetNull() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Primitive); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Null()); + } + + inline void SetUndefined() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Primitive); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Undefined()); + } + + inline void SetEmptyString() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::String); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::String::Empty()); + } + + // Convenience getter for isolate + inline v8::Isolate *GetIsolate() const { + return isolate_; + } + + // Pointer setter: Uncompilable to prevent inadvertent misuse. + template + inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); } +}; + +template +class FunctionCallbackInfo { + const v8::Arguments &args_; + v8::Local data_; + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline FunctionCallbackInfo( + const v8::Arguments &args + , v8::Local data) : + args_(args) + , data_(data) + , return_value_(args.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Undefined())) {} + + inline ~FunctionCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return ReturnValue(return_value_); + } + + inline v8::Local Callee() const { return args_.Callee(); } + inline v8::Local Data() const { return data_; } + inline v8::Local Holder() const { return args_.Holder(); } + inline bool IsConstructCall() const { return args_.IsConstructCall(); } + inline int Length() const { return args_.Length(); } + inline v8::Local operator[](int i) const { return args_[i]; } + inline v8::Local This() const { return args_.This(); } + inline v8::Isolate *GetIsolate() const { return args_.GetIsolate(); } + + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kCalleeIndex = 5; + static const int kContextSaveIndex = 6; + static const int kArgsLength = 7; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo) +}; + +template +class PropertyCallbackInfoBase { + const v8::AccessorInfo &info_; + const v8::Local data_; + + public: + explicit inline PropertyCallbackInfoBase( + const v8::AccessorInfo &info + , const v8::Local data) : + info_(info) + , data_(data) {} + + inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); } + inline v8::Local Data() const { return data_; } + inline v8::Local This() const { return info_.This(); } + inline v8::Local Holder() const { return info_.Holder(); } + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kThisIndex = 5; + static const int kArgsLength = 6; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfoBase) +}; + +template +class PropertyCallbackInfo : public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Undefined())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { return return_value_; } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +namespace imp { +template +class ReturnValueImp : public ReturnValue { + public: + explicit ReturnValueImp(ReturnValue that) : + ReturnValue(that) {} + inline v8::Handle Value() { + return *ReturnValue::value_; + } +}; + +static +v8::Handle FunctionCallbackWrapper(const v8::Arguments &args) { + v8::Local obj = args.Data().As(); + FunctionCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kFunctionIndex).As()->Value())); + FunctionCallbackInfo + cbinfo(args, obj->GetInternalField(kDataIndex)); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeFunction)(const v8::Arguments &); + +static +v8::Handle GetterCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeGetter) + (v8::Local, const v8::AccessorInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativeSetter) + (v8::Local, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyGetterCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyGetter) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property, value, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertySetter) + (v8::Local, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyEnumeratorCallbackWrapper( + const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyEnumerator) + (const v8::AccessorInfo &); + +static +v8::Handle PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (NativePropertyDeleter) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyQueryCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyQuery) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle IndexGetterCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyGetterIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexGetter) + (uint32_t, const v8::AccessorInfo &); + +static +v8::Handle IndexSetterCallbackWrapper( + uint32_t index + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexSetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertySetterIndex) + .As()->Value())); + callback(index, value, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexSetter) + (uint32_t, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle IndexEnumeratorCallbackWrapper( + const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexEnumeratorCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexEnumerator) + (const v8::AccessorInfo &); + +static +v8::Handle IndexDeleterCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyDeleterIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexDeleter) + (uint32_t, const v8::AccessorInfo &); + +static +v8::Handle IndexQueryCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyQueryIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexQuery) + (uint32_t, const v8::AccessorInfo &); +} // end of namespace imp + +#endif // NAN_CALLBACKS_PRE_12_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_converters.h b/deps/node-report/node_modules/nan/nan_converters.h new file mode 100644 index 00000000000000..c0b32729464404 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_converters.h @@ -0,0 +1,72 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_H_ +#define NAN_CONVERTERS_H_ + +namespace imp { +template struct ToFactoryBase { + typedef MaybeLocal return_t; +}; +template struct ValueFactoryBase { typedef Maybe return_t; }; + +template struct ToFactory; + +template<> +struct ToFactory : ToFactoryBase { + static inline return_t convert(v8::Local val) { + if (val.IsEmpty() || !val->IsFunction()) return MaybeLocal(); + return MaybeLocal(val.As()); + } +}; + +#define X(TYPE) \ + template<> \ + struct ToFactory : ToFactoryBase { \ + static inline return_t convert(v8::Local val); \ + }; + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE) \ + template<> \ + struct ToFactory : ValueFactoryBase { \ + static inline return_t convert(v8::Local val); \ + }; + +X(bool) +X(double) +X(int64_t) +X(uint32_t) +X(int32_t) + +#undef X +} // end of namespace imp + +template +inline +typename imp::ToFactory::return_t To(v8::Local val) { + return imp::ToFactory::convert(val); +} + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# include "nan_converters_43_inl.h" +#else +# include "nan_converters_pre_43_inl.h" +#endif + +#endif // NAN_CONVERTERS_H_ diff --git a/deps/node-report/node_modules/nan/nan_converters_43_inl.h b/deps/node-report/node_modules/nan/nan_converters_43_inl.h new file mode 100644 index 00000000000000..742f543279f0e8 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_converters_43_inl.h @@ -0,0 +1,48 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_43_INL_H_ +#define NAN_CONVERTERS_43_INL_H_ + +#define X(TYPE) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::EscapableHandleScope scope(isolate); \ + return scope.Escape( \ + val->To ## TYPE(isolate->GetCurrentContext()) \ + .FromMaybe(v8::Local())); \ +} + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE, NAME) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::HandleScope scope(isolate); \ + return val->NAME ## Value(isolate->GetCurrentContext()); \ +} + +X(bool, Boolean) +X(double, Number) +X(int64_t, Integer) +X(uint32_t, Uint32) +X(int32_t, Int32) + +#undef X + +#endif // NAN_CONVERTERS_43_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_converters_pre_43_inl.h b/deps/node-report/node_modules/nan/nan_converters_pre_43_inl.h new file mode 100644 index 00000000000000..ae0518aa33d085 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_converters_pre_43_inl.h @@ -0,0 +1,42 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_PRE_43_INL_H_ +#define NAN_CONVERTERS_PRE_43_INL_H_ + +#define X(TYPE) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + return val->To ## TYPE(); \ +} + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE, NAME) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + return Just(val->NAME ## Value()); \ +} + +X(bool, Boolean) +X(double, Number) +X(int64_t, Integer) +X(uint32_t, Uint32) +X(int32_t, Int32) + +#undef X + +#endif // NAN_CONVERTERS_PRE_43_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_define_own_property_helper.h b/deps/node-report/node_modules/nan/nan_define_own_property_helper.h new file mode 100644 index 00000000000000..d710ef2293d937 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_define_own_property_helper.h @@ -0,0 +1,29 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_DEFINE_OWN_PROPERTY_HELPER_H_ +#define NAN_DEFINE_OWN_PROPERTY_HELPER_H_ + +namespace imp { + +inline Maybe DefineOwnPropertyHelper( + v8::PropertyAttribute current + , v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + return !(current & v8::DontDelete) || // configurable OR + (!(current & v8::ReadOnly) && // writable AND + !((attribs ^ current) & ~v8::ReadOnly)) // same excluding RO + ? Just(obj->ForceSet(key, value, attribs)) + : Nothing(); +} + +} // end of namespace imp + +#endif // NAN_DEFINE_OWN_PROPERTY_HELPER_H_ diff --git a/deps/node-report/node_modules/nan/nan_implementation_12_inl.h b/deps/node-report/node_modules/nan/nan_implementation_12_inl.h new file mode 100644 index 00000000000000..baacb3801782f2 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_implementation_12_inl.h @@ -0,0 +1,399 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_IMPLEMENTATION_12_INL_H_ +#define NAN_IMPLEMENTATION_12_INL_H_ +//============================================================================== +// node v0.11 implementation +//============================================================================== + +namespace imp { + +//=== Array ==================================================================== + +Factory::return_t +Factory::New() { + return v8::Array::New(v8::Isolate::GetCurrent()); +} + +Factory::return_t +Factory::New(int length) { + return v8::Array::New(v8::Isolate::GetCurrent(), length); +} + +//=== Boolean ================================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::Boolean::New(v8::Isolate::GetCurrent(), value); +} + +//=== Boolean Object =========================================================== + +Factory::return_t +Factory::New(bool value) { +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + return v8::BooleanObject::New( + v8::Isolate::GetCurrent(), value).As(); +#else + return v8::BooleanObject::New(value).As(); +#endif +} + +//=== Context ================================================================== + +Factory::return_t +Factory::New( v8::ExtensionConfiguration* extensions + , v8::Local tmpl + , v8::Local obj) { + return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj); +} + +//=== Date ===================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(double value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(v8::Date::New(isolate->GetCurrentContext(), value) + .FromMaybe(v8::Local()).As()); +} +#else +Factory::return_t +Factory::New(double value) { + return v8::Date::New(v8::Isolate::GetCurrent(), value).As(); +} +#endif + +//=== External ================================================================= + +Factory::return_t +Factory::New(void * value) { + return v8::External::New(v8::Isolate::GetCurrent(), value); +} + +//=== Function ================================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local tpl = v8::ObjectTemplate::New(isolate); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(tpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(isolate, reinterpret_cast(callback))); + + v8::Local val = v8::Local::New(isolate, data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + + return scope.Escape(v8::Function::New( isolate + , imp::FunctionCallbackWrapper + , obj)); +} + +//=== Function Template ======================================================== + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data + , v8::Local signature) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + if (callback) { + v8::EscapableHandleScope scope(isolate); + v8::Local tpl = v8::ObjectTemplate::New(isolate); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(tpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(isolate, reinterpret_cast(callback))); + v8::Local val = v8::Local::New(isolate, data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + + return scope.Escape(v8::FunctionTemplate::New( isolate + , imp::FunctionCallbackWrapper + , obj + , signature)); + } else { + return v8::FunctionTemplate::New(isolate, 0, data, signature); + } +} + +//=== Number =================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Number::New(v8::Isolate::GetCurrent(), value); +} + +//=== Number Object ============================================================ + +Factory::return_t +Factory::New(double value) { + return v8::NumberObject::New( v8::Isolate::GetCurrent() + , value).As(); +} + +//=== Integer, Int32 and Uint32 ================================================ + +template +typename IntegerFactory::return_t +IntegerFactory::New(int32_t value) { + return To(T::New(v8::Isolate::GetCurrent(), value)); +} + +template +typename IntegerFactory::return_t +IntegerFactory::New(uint32_t value) { + return To(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +Factory::return_t +Factory::New(int32_t value) { + return To( + v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +Factory::return_t +Factory::New(uint32_t value) { + return To( + v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +//=== Object =================================================================== + +Factory::return_t +Factory::New() { + return v8::Object::New(v8::Isolate::GetCurrent()); +} + +//=== Object Template ========================================================== + +Factory::return_t +Factory::New() { + return v8::ObjectTemplate::New(v8::Isolate::GetCurrent()); +} + +//=== RegExp =================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + v8::RegExp::New(isolate->GetCurrentContext(), pattern, flags) + .FromMaybe(v8::Local())); +} +#else +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); +} +#endif + +//=== Script =================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New( v8::Local source) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source src(source); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src) + .FromMaybe(v8::Local())); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source src(source, origin); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src) + .FromMaybe(v8::Local())); +} +#else +Factory::return_t +Factory::New( v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src); +} +#endif + +//=== Signature ================================================================ + +Factory::return_t +Factory::New(Factory::FTH receiver) { + return v8::Signature::New(v8::Isolate::GetCurrent(), receiver); +} + +//=== String =================================================================== + +Factory::return_t +Factory::New() { + return v8::String::Empty(v8::Isolate::GetCurrent()); +} + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::NewFromUtf8( + v8::Isolate::GetCurrent(), value, v8::NewStringType::kNormal, length); +} + +Factory::return_t +Factory::New(std::string const& value) { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), + value.data(), v8::NewStringType::kNormal, static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value, + v8::NewStringType::kNormal, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternalTwoByte(v8::Isolate::GetCurrent(), value); +} + +Factory::return_t +Factory::New(ExternalOneByteStringResource * value) { + return v8::String::NewExternalOneByte(v8::Isolate::GetCurrent(), value); +} +#else +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); +} + +Factory::return_t +Factory::New( + std::string const& value) /* NOLINT(build/include_what_you_use) */ { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value.data(), + v8::String::kNormalString, + static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), value); +} + +Factory::return_t +Factory::New(ExternalOneByteStringResource * value) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), value); +} +#endif + +//=== String Object ============================================================ + +Factory::return_t +Factory::New(v8::Local value) { + return v8::StringObject::New(value).As(); +} + +//=== Unbound Script =========================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::CompileUnboundScript( + v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::CompileUnboundScript( + v8::Isolate::GetCurrent(), &src); +} +#else +Factory::return_t +Factory::New(v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src); +} +#endif + +} // end of namespace imp + +//=== Presistents and Handles ================================================== + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template +inline v8::Local New(v8::Handle h) { + return v8::Local::New(v8::Isolate::GetCurrent(), h); +} +#endif + +template +inline v8::Local New(v8::Persistent const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +template +inline v8::Local New(Persistent const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +template +inline v8::Local New(Global const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +#endif // NAN_IMPLEMENTATION_12_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_implementation_pre_12_inl.h b/deps/node-report/node_modules/nan/nan_implementation_pre_12_inl.h new file mode 100644 index 00000000000000..1472421afa7688 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_implementation_pre_12_inl.h @@ -0,0 +1,263 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_ +#define NAN_IMPLEMENTATION_PRE_12_INL_H_ + +//============================================================================== +// node v0.10 implementation +//============================================================================== + +namespace imp { + +//=== Array ==================================================================== + +Factory::return_t +Factory::New() { + return v8::Array::New(); +} + +Factory::return_t +Factory::New(int length) { + return v8::Array::New(length); +} + +//=== Boolean ================================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::Boolean::New(value)->ToBoolean(); +} + +//=== Boolean Object =========================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::BooleanObject::New(value).As(); +} + +//=== Context ================================================================== + +Factory::return_t +Factory::New( v8::ExtensionConfiguration* extensions + , v8::Local tmpl + , v8::Local obj) { + v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); + v8::Local lctx = v8::Local::New(ctx); + ctx.Dispose(); + return lctx; +} + +//=== Date ===================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Date::New(value).As(); +} + +//=== External ================================================================= + +Factory::return_t +Factory::New(void * value) { + return v8::External::New(value); +} + +//=== Function ================================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data) { + v8::HandleScope scope; + + return scope.Close(Factory::New( + callback, data, v8::Local()) + ->GetFunction()); +} + + +//=== FunctionTemplate ========================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data + , v8::Local signature) { + if (callback) { + v8::HandleScope scope; + + v8::Local tpl = v8::ObjectTemplate::New(); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = tpl->NewInstance(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(reinterpret_cast(callback))); + + v8::Local val = v8::Local::New(data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + + // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find + // a way. Have at it though... + return scope.Close( + v8::FunctionTemplate::New(imp::FunctionCallbackWrapper + , obj + , signature)); + } else { + return v8::FunctionTemplate::New(0, data, signature); + } +} + +//=== Number =================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Number::New(value); +} + +//=== Number Object ============================================================ + +Factory::return_t +Factory::New(double value) { + return v8::NumberObject::New(value).As(); +} + +//=== Integer, Int32 and Uint32 ================================================ + +template +typename IntegerFactory::return_t +IntegerFactory::New(int32_t value) { + return To(T::New(value)); +} + +template +typename IntegerFactory::return_t +IntegerFactory::New(uint32_t value) { + return To(T::NewFromUnsigned(value)); +} + +Factory::return_t +Factory::New(int32_t value) { + return To(v8::Uint32::NewFromUnsigned(value)); +} + +Factory::return_t +Factory::New(uint32_t value) { + return To(v8::Uint32::NewFromUnsigned(value)); +} + + +//=== Object =================================================================== + +Factory::return_t +Factory::New() { + return v8::Object::New(); +} + +//=== Object Template ========================================================== + +Factory::return_t +Factory::New() { + return v8::ObjectTemplate::New(); +} + +//=== RegExp =================================================================== + +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); +} + +//=== Script =================================================================== + +Factory::return_t +Factory::New( v8::Local source) { + return v8::Script::New(source); +} +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + return v8::Script::New(source, const_cast(&origin)); +} + +//=== Signature ================================================================ + +Factory::return_t +Factory::New(Factory::FTH receiver) { + return v8::Signature::New(receiver); +} + +//=== String =================================================================== + +Factory::return_t +Factory::New() { + return v8::String::Empty(); +} + +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::New(value, length); +} + +Factory::return_t +Factory::New( + std::string const& value) /* NOLINT(build/include_what_you_use) */ { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::New(value.data(), static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::New(value, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternal(value); +} + +Factory::return_t +Factory::New(v8::String::ExternalAsciiStringResource * value) { + return v8::String::NewExternal(value); +} + +//=== String Object ============================================================ + +Factory::return_t +Factory::New(v8::Local value) { + return v8::StringObject::New(value).As(); +} + +} // end of namespace imp + +//=== Presistents and Handles ================================================== + +template +inline v8::Local New(v8::Handle h) { + return v8::Local::New(h); +} + +template +inline v8::Local New(v8::Persistent const& p) { + return v8::Local::New(p); +} + +template +inline v8::Local New(Persistent const& p) { + return v8::Local::New(p.persistent); +} + +template +inline v8::Local New(Global const& p) { + return v8::Local::New(p.persistent); +} + +#endif // NAN_IMPLEMENTATION_PRE_12_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_json.h b/deps/node-report/node_modules/nan/nan_json.h new file mode 100644 index 00000000000000..33ac8ba69a082f --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_json.h @@ -0,0 +1,166 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_JSON_H_ +#define NAN_JSON_H_ + +#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION +#define NAN_JSON_H_NEED_PARSE 1 +#else +#define NAN_JSON_H_NEED_PARSE 0 +#endif // NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION + +#if NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION +#define NAN_JSON_H_NEED_STRINGIFY 0 +#else +#define NAN_JSON_H_NEED_STRINGIFY 1 +#endif // NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION + +class JSON { + public: + JSON() { +#if NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY + Nan::HandleScope scope; + + Nan::MaybeLocal maybe_global_json = Nan::Get( + Nan::GetCurrentContext()->Global(), + Nan::New("JSON").ToLocalChecked() + ); + + assert(!maybe_global_json.IsEmpty() && "global JSON is empty"); + v8::Local val_global_json = maybe_global_json.ToLocalChecked(); + + assert(val_global_json->IsObject() && "global JSON is not an object"); + Nan::MaybeLocal maybe_obj_global_json = + Nan::To(val_global_json); + + assert(!maybe_obj_global_json.IsEmpty() && "global JSON object is empty"); + v8::Local global_json = maybe_obj_global_json.ToLocalChecked(); + +#if NAN_JSON_H_NEED_PARSE + Nan::MaybeLocal maybe_parse_method = Nan::Get( + global_json, Nan::New("parse").ToLocalChecked() + ); + + assert(!maybe_parse_method.IsEmpty() && "JSON.parse is empty"); + v8::Local parse_method = maybe_parse_method.ToLocalChecked(); + + assert(parse_method->IsFunction() && "JSON.parse is not a function"); + parse_cb_.Reset(parse_method.As()); +#endif // NAN_JSON_H_NEED_PARSE + +#if NAN_JSON_H_NEED_STRINGIFY + Nan::MaybeLocal maybe_stringify_method = Nan::Get( + global_json, Nan::New("stringify").ToLocalChecked() + ); + + assert(!maybe_stringify_method.IsEmpty() && "JSON.stringify is empty"); + v8::Local stringify_method = + maybe_stringify_method.ToLocalChecked(); + + assert( + stringify_method->IsFunction() && "JSON.stringify is not a function" + ); + stringify_cb_.Reset(stringify_method.As()); +#endif // NAN_JSON_H_NEED_STRINGIFY +#endif // NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY + } + + inline + Nan::MaybeLocal Parse(v8::Local json_string) { + Nan::EscapableHandleScope scope; +#if NAN_JSON_H_NEED_PARSE + return scope.Escape(parse(json_string)); +#else + Nan::MaybeLocal result; +#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && \ + NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION + result = v8::JSON::Parse(json_string); +#else +#if NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION + v8::Local context_or_isolate = Nan::GetCurrentContext(); +#else + v8::Isolate* context_or_isolate = v8::Isolate::GetCurrent(); +#endif // NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION + result = v8::JSON::Parse(context_or_isolate, json_string); +#endif // NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && + // NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); +#endif // NAN_JSON_H_NEED_PARSE + } + + inline + Nan::MaybeLocal Stringify(v8::Local json_object) { + Nan::EscapableHandleScope scope; + Nan::MaybeLocal result = +#if NAN_JSON_H_NEED_STRINGIFY + Nan::To(stringify(json_object)); +#else + v8::JSON::Stringify(Nan::GetCurrentContext(), json_object); +#endif // NAN_JSON_H_NEED_STRINGIFY + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); + } + + inline + Nan::MaybeLocal Stringify(v8::Local json_object, + v8::Local gap) { + Nan::EscapableHandleScope scope; + Nan::MaybeLocal result = +#if NAN_JSON_H_NEED_STRINGIFY + Nan::To(stringify(json_object, gap)); +#else + v8::JSON::Stringify(Nan::GetCurrentContext(), json_object, gap); +#endif // NAN_JSON_H_NEED_STRINGIFY + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(JSON) +#if NAN_JSON_H_NEED_PARSE + Nan::Callback parse_cb_; +#endif // NAN_JSON_H_NEED_PARSE +#if NAN_JSON_H_NEED_STRINGIFY + Nan::Callback stringify_cb_; +#endif // NAN_JSON_H_NEED_STRINGIFY + +#if NAN_JSON_H_NEED_PARSE + inline v8::Local parse(v8::Local arg) { + assert(!parse_cb_.IsEmpty() && "parse_cb_ is empty"); + AsyncResource resource("nan:JSON.parse"); + return parse_cb_.Call(1, &arg, &resource).FromMaybe(v8::Local()); + } +#endif // NAN_JSON_H_NEED_PARSE + +#if NAN_JSON_H_NEED_STRINGIFY + inline v8::Local stringify(v8::Local arg) { + assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); + AsyncResource resource("nan:JSON.stringify"); + return stringify_cb_.Call(1, &arg, &resource) + .FromMaybe(v8::Local()); + } + + inline v8::Local stringify(v8::Local arg, + v8::Local gap) { + assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); + + v8::Local argv[] = { + arg, + Nan::Null(), + gap + }; + AsyncResource resource("nan:JSON.stringify"); + return stringify_cb_.Call(3, argv, &resource) + .FromMaybe(v8::Local()); + } +#endif // NAN_JSON_H_NEED_STRINGIFY +}; + +#endif // NAN_JSON_H_ diff --git a/deps/node-report/node_modules/nan/nan_maybe_43_inl.h b/deps/node-report/node_modules/nan/nan_maybe_43_inl.h new file mode 100644 index 00000000000000..91783da65aa9cd --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_maybe_43_inl.h @@ -0,0 +1,369 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_MAYBE_43_INL_H_ +#define NAN_MAYBE_43_INL_H_ + +template +using MaybeLocal = v8::MaybeLocal; + +template +using Maybe = v8::Maybe; + +template +inline Maybe Nothing() { + return v8::Nothing(); +} + +template +inline Maybe Just(const T& t) { + return v8::Just(t); +} + +inline +MaybeLocal ToDetailString(v8::Local val) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(val->ToDetailString(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal ToArrayIndex(v8::Local val) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(val->ToArrayIndex(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +Maybe Equals(v8::Local a, v8::Local(b)) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return a->Equals(isolate->GetCurrentContext(), b); +} + +inline +MaybeLocal NewInstance(v8::Local h) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal NewInstance( + v8::Local h + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext(), argc, argv) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal NewInstance(v8::Local h) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + + +inline MaybeLocal GetFunction( + v8::Local t) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(t->GetFunction(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe Set( + v8::Local obj + , v8::Local key + , v8::Local value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Set(isolate->GetCurrentContext(), key, value); +} + +inline Maybe Set( + v8::Local obj + , uint32_t index + , v8::Local value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Set(isolate->GetCurrentContext(), index, value); +} + +#if NODE_MODULE_VERSION < NODE_4_0_MODULE_VERSION +#include "nan_define_own_property_helper.h" // NOLINT(build/include) +#endif + +inline Maybe DefineOwnProperty( + v8::Local obj + , v8::Local key + , v8::Local value + , v8::PropertyAttribute attribs = v8::None) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); +#if NODE_MODULE_VERSION >= NODE_4_0_MODULE_VERSION + return obj->DefineOwnProperty(isolate->GetCurrentContext(), key, value, + attribs); +#else + Maybe maybeCurrent = + obj->GetPropertyAttributes(isolate->GetCurrentContext(), key); + if (maybeCurrent.IsNothing()) { + return Nothing(); + } + v8::PropertyAttribute current = maybeCurrent.FromJust(); + return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs); +#endif +} + +NAN_DEPRECATED inline Maybe ForceSet( + v8::Local obj + , v8::Local key + , v8::Local value + , v8::PropertyAttribute attribs = v8::None) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + return key->IsName() + ? obj->DefineOwnProperty(isolate->GetCurrentContext(), + key.As(), value, attribs) + : Nothing(); +#else + return obj->ForceSet(isolate->GetCurrentContext(), key, value, attribs); +#endif +} + +inline MaybeLocal Get( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->Get(isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal Get(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->Get(isolate->GetCurrentContext(), index) + .FromMaybe(v8::Local())); +} + +inline v8::PropertyAttribute GetPropertyAttributes( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->GetPropertyAttributes(isolate->GetCurrentContext(), key) + .FromJust(); +} + +inline Maybe Has( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Has(isolate->GetCurrentContext(), key); +} + +inline Maybe Has(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Has(isolate->GetCurrentContext(), index); +} + +inline Maybe Delete( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Delete(isolate->GetCurrentContext(), key); +} + +inline +Maybe Delete(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Delete(isolate->GetCurrentContext(), index); +} + +inline +MaybeLocal GetPropertyNames(v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetPropertyNames(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal GetOwnPropertyNames(v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetOwnPropertyNames(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe SetPrototype( + v8::Local obj + , v8::Local prototype) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->SetPrototype(isolate->GetCurrentContext(), prototype); +} + +inline MaybeLocal ObjectProtoToString( + v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->ObjectProtoToString(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe HasOwnProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasOwnProperty(isolate->GetCurrentContext(), key); +} + +inline Maybe HasRealNamedProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealNamedProperty(isolate->GetCurrentContext(), key); +} + +inline Maybe HasRealIndexedProperty( + v8::Local obj + , uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealIndexedProperty(isolate->GetCurrentContext(), index); +} + +inline Maybe HasRealNamedCallbackProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealNamedCallbackProperty(isolate->GetCurrentContext(), key); +} + +inline MaybeLocal GetRealNamedPropertyInPrototypeChain( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetRealNamedPropertyInPrototypeChain( + isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal GetRealNamedProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->GetRealNamedProperty(isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal CallAsFunction( + v8::Local obj + , v8::Local recv + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->CallAsFunction(isolate->GetCurrentContext(), recv, argc, argv) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal CallAsConstructor( + v8::Local obj + , int argc, v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->CallAsConstructor(isolate->GetCurrentContext(), argc, argv) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal GetSourceLine(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(msg->GetSourceLine(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe GetLineNumber(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetLineNumber(isolate->GetCurrentContext()); +} + +inline Maybe GetStartColumn(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetStartColumn(isolate->GetCurrentContext()); +} + +inline Maybe GetEndColumn(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetEndColumn(isolate->GetCurrentContext()); +} + +inline MaybeLocal CloneElementAt( + v8::Local array + , uint32_t index) { +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local elem; + v8::Local obj; + if (!array->Get(context, index).ToLocal(&elem)) { + return scope.Escape(obj); + } + if (!elem->ToObject(context).ToLocal(&obj)) { + return scope.Escape(v8::Local()); + } + return scope.Escape(obj->Clone()); +#else + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(array->CloneElementAt(isolate->GetCurrentContext(), index) + .FromMaybe(v8::Local())); +#endif +} + +inline MaybeLocal Call( + v8::Local fun + , v8::Local recv + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(fun->Call(isolate->GetCurrentContext(), recv, argc, argv) + .FromMaybe(v8::Local())); +} + +#endif // NAN_MAYBE_43_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_maybe_pre_43_inl.h b/deps/node-report/node_modules/nan/nan_maybe_pre_43_inl.h new file mode 100644 index 00000000000000..3847296d5d22d6 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_maybe_pre_43_inl.h @@ -0,0 +1,316 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_MAYBE_PRE_43_INL_H_ +#define NAN_MAYBE_PRE_43_INL_H_ + +template +class MaybeLocal { + public: + inline MaybeLocal() : val_(v8::Local()) {} + + template +# if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION + inline + MaybeLocal(v8::Local that) : val_(that) {} // NOLINT(runtime/explicit) +# else + inline + MaybeLocal(v8::Local that) : // NOLINT(runtime/explicit) + val_(*reinterpret_cast*>(&that)) {} +# endif + + inline bool IsEmpty() const { return val_.IsEmpty(); } + + template + inline bool ToLocal(v8::Local *out) const { + *out = val_; + return !IsEmpty(); + } + + inline v8::Local ToLocalChecked() const { +#if defined(V8_ENABLE_CHECKS) + assert(!IsEmpty() && "ToLocalChecked is Empty"); +#endif // V8_ENABLE_CHECKS + return val_; + } + + template + inline v8::Local FromMaybe(v8::Local default_value) const { + return IsEmpty() ? default_value : v8::Local(val_); + } + + private: + v8::Local val_; +}; + +template +class Maybe { + public: + inline bool IsNothing() const { return !has_value_; } + inline bool IsJust() const { return has_value_; } + + inline T FromJust() const { +#if defined(V8_ENABLE_CHECKS) + assert(IsJust() && "FromJust is Nothing"); +#endif // V8_ENABLE_CHECKS + return value_; + } + + inline T FromMaybe(const T& default_value) const { + return has_value_ ? value_ : default_value; + } + + inline bool operator==(const Maybe &other) const { + return (IsJust() == other.IsJust()) && + (!IsJust() || FromJust() == other.FromJust()); + } + + inline bool operator!=(const Maybe &other) const { + return !operator==(other); + } + + private: + Maybe() : has_value_(false) {} + explicit Maybe(const T& t) : has_value_(true), value_(t) {} + bool has_value_; + T value_; + + template + friend Maybe Nothing(); + template + friend Maybe Just(const U& u); +}; + +template +inline Maybe Nothing() { + return Maybe(); +} + +template +inline Maybe Just(const T& t) { + return Maybe(t); +} + +inline +MaybeLocal ToDetailString(v8::Handle val) { + return MaybeLocal(val->ToDetailString()); +} + +inline +MaybeLocal ToArrayIndex(v8::Handle val) { + return MaybeLocal(val->ToArrayIndex()); +} + +inline +Maybe Equals(v8::Handle a, v8::Handle(b)) { + return Just(a->Equals(b)); +} + +inline +MaybeLocal NewInstance(v8::Handle h) { + return MaybeLocal(h->NewInstance()); +} + +inline +MaybeLocal NewInstance( + v8::Local h + , int argc + , v8::Local argv[]) { + return MaybeLocal(h->NewInstance(argc, argv)); +} + +inline +MaybeLocal NewInstance(v8::Handle h) { + return MaybeLocal(h->NewInstance()); +} + +inline +MaybeLocal GetFunction(v8::Handle t) { + return MaybeLocal(t->GetFunction()); +} + +inline Maybe Set( + v8::Handle obj + , v8::Handle key + , v8::Handle value) { + return Just(obj->Set(key, value)); +} + +inline Maybe Set( + v8::Handle obj + , uint32_t index + , v8::Handle value) { + return Just(obj->Set(index, value)); +} + +#include "nan_define_own_property_helper.h" // NOLINT(build/include) + +inline Maybe DefineOwnProperty( + v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + v8::PropertyAttribute current = obj->GetPropertyAttributes(key); + return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs); +} + +NAN_DEPRECATED inline Maybe ForceSet( + v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + return Just(obj->ForceSet(key, value, attribs)); +} + +inline MaybeLocal Get( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal(obj->Get(key)); +} + +inline MaybeLocal Get( + v8::Handle obj + , uint32_t index) { + return MaybeLocal(obj->Get(index)); +} + +inline Maybe GetPropertyAttributes( + v8::Handle obj + , v8::Handle key) { + return Just(obj->GetPropertyAttributes(key)); +} + +inline Maybe Has( + v8::Handle obj + , v8::Handle key) { + return Just(obj->Has(key)); +} + +inline Maybe Has( + v8::Handle obj + , uint32_t index) { + return Just(obj->Has(index)); +} + +inline Maybe Delete( + v8::Handle obj + , v8::Handle key) { + return Just(obj->Delete(key)); +} + +inline Maybe Delete( + v8::Handle obj + , uint32_t index) { + return Just(obj->Delete(index)); +} + +inline +MaybeLocal GetPropertyNames(v8::Handle obj) { + return MaybeLocal(obj->GetPropertyNames()); +} + +inline +MaybeLocal GetOwnPropertyNames(v8::Handle obj) { + return MaybeLocal(obj->GetOwnPropertyNames()); +} + +inline Maybe SetPrototype( + v8::Handle obj + , v8::Handle prototype) { + return Just(obj->SetPrototype(prototype)); +} + +inline MaybeLocal ObjectProtoToString( + v8::Handle obj) { + return MaybeLocal(obj->ObjectProtoToString()); +} + +inline Maybe HasOwnProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasOwnProperty(key)); +} + +inline Maybe HasRealNamedProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasRealNamedProperty(key)); +} + +inline Maybe HasRealIndexedProperty( + v8::Handle obj + , uint32_t index) { + return Just(obj->HasRealIndexedProperty(index)); +} + +inline Maybe HasRealNamedCallbackProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasRealNamedCallbackProperty(key)); +} + +inline MaybeLocal GetRealNamedPropertyInPrototypeChain( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal( + obj->GetRealNamedPropertyInPrototypeChain(key)); +} + +inline MaybeLocal GetRealNamedProperty( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal(obj->GetRealNamedProperty(key)); +} + +inline MaybeLocal CallAsFunction( + v8::Handle obj + , v8::Handle recv + , int argc + , v8::Handle argv[]) { + return MaybeLocal(obj->CallAsFunction(recv, argc, argv)); +} + +inline MaybeLocal CallAsConstructor( + v8::Handle obj + , int argc + , v8::Local argv[]) { + return MaybeLocal(obj->CallAsConstructor(argc, argv)); +} + +inline +MaybeLocal GetSourceLine(v8::Handle msg) { + return MaybeLocal(msg->GetSourceLine()); +} + +inline Maybe GetLineNumber(v8::Handle msg) { + return Just(msg->GetLineNumber()); +} + +inline Maybe GetStartColumn(v8::Handle msg) { + return Just(msg->GetStartColumn()); +} + +inline Maybe GetEndColumn(v8::Handle msg) { + return Just(msg->GetEndColumn()); +} + +inline MaybeLocal CloneElementAt( + v8::Handle array + , uint32_t index) { + return MaybeLocal(array->CloneElementAt(index)); +} + +inline MaybeLocal Call( + v8::Local fun + , v8::Local recv + , int argc + , v8::Local argv[]) { + return MaybeLocal(fun->Call(recv, argc, argv)); +} + +#endif // NAN_MAYBE_PRE_43_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_new.h b/deps/node-report/node_modules/nan/nan_new.h new file mode 100644 index 00000000000000..cdf8bbe40b9b72 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_new.h @@ -0,0 +1,340 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_NEW_H_ +#define NAN_NEW_H_ + +namespace imp { // scnr + +// TODO(agnat): Generalize +template v8::Local To(v8::Local i); + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template struct FactoryBase { + typedef v8::Local return_t; +}; + +template struct MaybeFactoryBase { + typedef MaybeLocal return_t; +}; + +template struct Factory; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); + static inline return_t New(int length); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(bool value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(bool value); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( v8::ExtensionConfiguration* extensions = NULL + , v8::Local tmpl = v8::Local() + , v8::Local obj = v8::Local()); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New(double value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(void *value); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( FunctionCallback callback + , v8::Local data = v8::Local()); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( FunctionCallback callback = NULL + , v8::Local data = v8::Local() + , v8::Local signature = v8::Local()); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(double value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(double value); +}; + +template +struct IntegerFactory : FactoryBase { + typedef typename FactoryBase::return_t return_t; + static inline return_t New(int32_t value); + static inline return_t New(uint32_t value); +}; + +template <> +struct Factory : IntegerFactory {}; + +template <> +struct Factory : IntegerFactory {}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(int32_t value); + static inline return_t New(uint32_t value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( + v8::Local pattern, v8::RegExp::Flags flags); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( v8::Local source); + static inline return_t New( v8::Local source + , v8::ScriptOrigin const& origin); +}; + +template <> +struct Factory : FactoryBase { + typedef v8::Local FTH; + static inline return_t New(FTH receiver = FTH()); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New(); + static inline return_t New(const char *value, int length = -1); + static inline return_t New(const uint16_t *value, int length = -1); + static inline return_t New(std::string const& value); + + static inline return_t New(v8::String::ExternalStringResource * value); + static inline return_t New(ExternalOneByteStringResource * value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(v8::Local value); +}; + +} // end of namespace imp + +#if (NODE_MODULE_VERSION >= 12) + +namespace imp { + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( v8::Local source); + static inline return_t New( v8::Local source + , v8::ScriptOrigin const& origin); +}; + +} // end of namespace imp + +# include "nan_implementation_12_inl.h" + +#else // NODE_MODULE_VERSION >= 12 + +# include "nan_implementation_pre_12_inl.h" + +#endif + +//=== API ====================================================================== + +template +typename imp::Factory::return_t +New() { + return imp::Factory::New(); +} + +template +typename imp::Factory::return_t +New(A0 arg0) { + return imp::Factory::New(arg0); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1) { + return imp::Factory::New(arg0, arg1); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1, A2 arg2) { + return imp::Factory::New(arg0, arg1, arg2); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1, A2 arg2, A3 arg3) { + return imp::Factory::New(arg0, arg1, arg2, arg3); +} + +// Note(agnat): When passing overloaded function pointers to template functions +// as generic arguments the compiler needs help in picking the right overload. +// These two functions handle New and New with +// all argument variations. + +// v8::Function and v8::FunctionTemplate with one or two arguments +template +typename imp::Factory::return_t +New( FunctionCallback callback + , v8::Local data = v8::Local()) { + return imp::Factory::New(callback, data); +} + +// v8::Function and v8::FunctionTemplate with three arguments +template +typename imp::Factory::return_t +New( FunctionCallback callback + , v8::Local data = v8::Local() + , A2 a2 = A2()) { + return imp::Factory::New(callback, data, a2); +} + +// Convenience + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template inline v8::Local New(v8::Handle h); +#endif + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +template + inline v8::Local New(v8::Persistent const& p); +#else +template inline v8::Local New(v8::Persistent const& p); +#endif +template +inline v8::Local New(Persistent const& p); +template +inline v8::Local New(Global const& p); + +inline +imp::Factory::return_t +New(bool value) { + return New(value); +} + +inline +imp::Factory::return_t +New(int32_t value) { + return New(value); +} + +inline +imp::Factory::return_t +New(uint32_t value) { + return New(value); +} + +inline +imp::Factory::return_t +New(double value) { + return New(value); +} + +inline +imp::Factory::return_t +New(std::string const& value) { // NOLINT(build/include_what_you_use) + return New(value); +} + +inline +imp::Factory::return_t +New(const char * value, int length) { + return New(value, length); +} + +inline +imp::Factory::return_t +New(const uint16_t * value, int length) { + return New(value, length); +} + +inline +imp::Factory::return_t +New(const char * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(const uint16_t * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(v8::String::ExternalStringResource * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(ExternalOneByteStringResource * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(v8::Local pattern, v8::RegExp::Flags flags) { + return New(pattern, flags); +} + +#endif // NAN_NEW_H_ diff --git a/deps/node-report/node_modules/nan/nan_object_wrap.h b/deps/node-report/node_modules/nan/nan_object_wrap.h new file mode 100644 index 00000000000000..a4d96178f0b0a2 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_object_wrap.h @@ -0,0 +1,155 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_OBJECT_WRAP_H_ +#define NAN_OBJECT_WRAP_H_ + +class ObjectWrap { + public: + ObjectWrap() { + refs_ = 0; + } + + + virtual ~ObjectWrap() { + if (persistent().IsEmpty()) { + return; + } + + assert(persistent().IsNearDeath()); + persistent().ClearWeak(); + persistent().Reset(); + } + + + template + static inline T* Unwrap(v8::Local object) { + assert(!object.IsEmpty()); + assert(object->InternalFieldCount() > 0); + // Cast to ObjectWrap before casting to T. A direct cast from void + // to T won't work right when T has more than one base class. + void* ptr = GetInternalFieldPointer(object, 0); + ObjectWrap* wrap = static_cast(ptr); + return static_cast(wrap); + } + + + inline v8::Local handle() const { + return New(handle_); + } + + + inline Persistent& persistent() { + return handle_; + } + + + protected: + inline void Wrap(v8::Local object) { + assert(persistent().IsEmpty()); + assert(object->InternalFieldCount() > 0); + SetInternalFieldPointer(object, 0, this); + persistent().Reset(object); + MakeWeak(); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + inline void MakeWeak() { + persistent().v8::PersistentBase::SetWeak( + this, WeakCallback, v8::WeakCallbackType::kParameter); + persistent().MarkIndependent(); + } + +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + + inline void MakeWeak() { + persistent().v8::PersistentBase::SetWeak(this, WeakCallback); + persistent().MarkIndependent(); + } + +#else + + inline void MakeWeak() { + persistent().persistent.MakeWeak(this, WeakCallback); + persistent().MarkIndependent(); + } + +#endif + + /* Ref() marks the object as being attached to an event loop. + * Refed objects will not be garbage collected, even if + * all references are lost. + */ + virtual void Ref() { + assert(!persistent().IsEmpty()); + persistent().ClearWeak(); + refs_++; + } + + /* Unref() marks an object as detached from the event loop. This is its + * default state. When an object with a "weak" reference changes from + * attached to detached state it will be freed. Be careful not to access + * the object after making this call as it might be gone! + * (A "weak reference" means an object that only has a + * persistant handle.) + * + * DO NOT CALL THIS FROM DESTRUCTOR + */ + virtual void Unref() { + assert(!persistent().IsEmpty()); + assert(!persistent().IsWeak()); + assert(refs_ > 0); + if (--refs_ == 0) + MakeWeak(); + } + + int refs_; // ro + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap) +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + static void + WeakCallback(v8::WeakCallbackInfo const& info) { + ObjectWrap* wrap = info.GetParameter(); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + + static void + WeakCallback(v8::WeakCallbackData const& data) { + ObjectWrap* wrap = data.GetParameter(); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#else + + static void WeakCallback(v8::Persistent value, void *data) { + ObjectWrap *wrap = static_cast(data); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#endif + Persistent handle_; +}; + + +#endif // NAN_OBJECT_WRAP_H_ diff --git a/deps/node-report/node_modules/nan/nan_persistent_12_inl.h b/deps/node-report/node_modules/nan/nan_persistent_12_inl.h new file mode 100644 index 00000000000000..d9649e867606c6 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_persistent_12_inl.h @@ -0,0 +1,132 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PERSISTENT_12_INL_H_ +#define NAN_PERSISTENT_12_INL_H_ + +template class Persistent : + public v8::Persistent { + public: + inline Persistent() : v8::Persistent() {} + + template inline Persistent(v8::Local that) : + v8::Persistent(v8::Isolate::GetCurrent(), that) {} + + template + inline + Persistent(const v8::Persistent &that) : // NOLINT(runtime/explicit) + v8::Persistent(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type); + + private: + inline T *operator*() const { return *PersistentBase::persistent; } + + template + inline void Copy(const Persistent &that) { + TYPE_CHECK(T, S); + + this->Reset(); + + if (!that.IsEmpty()) { + this->Reset(that); + M::Copy(that, this); + } + } +}; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +template +class Global : public v8::Global { + public: + inline Global() : v8::Global() {} + + template inline Global(v8::Local that) : + v8::Global(v8::Isolate::GetCurrent(), that) {} + + template + inline + Global(const v8::PersistentBase &that) : // NOLINT(runtime/explicit) + v8::Global(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + reinterpret_cast*>(this)->SetWeak( + parameter, callback, type); + } +}; +#else +template +class Global : public v8::UniquePersistent { + public: + inline Global() : v8::UniquePersistent() {} + + template inline Global(v8::Local that) : + v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} + + template + inline + Global(const v8::PersistentBase &that) : // NOLINT(runtime/explicit) + v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + reinterpret_cast*>(this)->SetWeak( + parameter, callback, type); + } +}; +#endif + +#endif // NAN_PERSISTENT_12_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_persistent_pre_12_inl.h b/deps/node-report/node_modules/nan/nan_persistent_pre_12_inl.h new file mode 100644 index 00000000000000..4c9c59da70b66a --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_persistent_pre_12_inl.h @@ -0,0 +1,242 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PERSISTENT_PRE_12_INL_H_ +#define NAN_PERSISTENT_PRE_12_INL_H_ + +template +class PersistentBase { + v8::Persistent persistent; + template + friend v8::Local New(const PersistentBase &p); + template + friend v8::Local New(const Persistent &p); + template + friend v8::Local New(const Global &p); + template friend class ReturnValue; + + public: + inline PersistentBase() : + persistent() {} + + inline void Reset() { + persistent.Dispose(); + persistent.Clear(); + } + + template + inline void Reset(const v8::Local &other) { + TYPE_CHECK(T, S); + + if (!persistent.IsEmpty()) { + persistent.Dispose(); + } + + if (other.IsEmpty()) { + persistent.Clear(); + } else { + persistent = v8::Persistent::New(other); + } + } + + template + inline void Reset(const PersistentBase &other) { + TYPE_CHECK(T, S); + + if (!persistent.IsEmpty()) { + persistent.Dispose(); + } + + if (other.IsEmpty()) { + persistent.Clear(); + } else { + persistent = v8::Persistent::New(other.persistent); + } + } + + inline bool IsEmpty() const { return persistent.IsEmpty(); } + + inline void Empty() { persistent.Clear(); } + + template + inline bool operator==(const PersistentBase &that) const { + return this->persistent == that.persistent; + } + + template + inline bool operator==(const v8::Local &that) const { + return this->persistent == that; + } + + template + inline bool operator!=(const PersistentBase &that) const { + return !operator==(that); + } + + template + inline bool operator!=(const v8::Local &that) const { + return !operator==(that); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type); + + inline void ClearWeak() { persistent.ClearWeak(); } + + inline void MarkIndependent() { persistent.MarkIndependent(); } + + inline bool IsIndependent() const { return persistent.IsIndependent(); } + + inline bool IsNearDeath() const { return persistent.IsNearDeath(); } + + inline bool IsWeak() const { return persistent.IsWeak(); } + + private: + inline explicit PersistentBase(v8::Persistent that) : + persistent(that) { } + inline explicit PersistentBase(T *val) : persistent(val) {} + template friend class Persistent; + template friend class Global; + friend class ObjectWrap; +}; + +template +class NonCopyablePersistentTraits { + public: + typedef Persistent > + NonCopyablePersistent; + static const bool kResetInDestructor = false; + template + inline static void Copy(const Persistent &source, + NonCopyablePersistent *dest) { + Uncompilable(); + } + + template inline static void Uncompilable() { + TYPE_CHECK(O, v8::Primitive); + } +}; + +template +struct CopyablePersistentTraits { + typedef Persistent > CopyablePersistent; + static const bool kResetInDestructor = true; + template + static inline void Copy(const Persistent &source, + CopyablePersistent *dest) {} +}; + +template class Persistent : + public PersistentBase { + public: + inline Persistent() {} + + template inline Persistent(v8::Handle that) + : PersistentBase(v8::Persistent::New(that)) { + TYPE_CHECK(T, S); + } + + inline Persistent(const Persistent &that) : PersistentBase() { + Copy(that); + } + + template + inline Persistent(const Persistent &that) : + PersistentBase() { + Copy(that); + } + + inline Persistent &operator=(const Persistent &that) { + Copy(that); + return *this; + } + + template + inline Persistent &operator=(const Persistent &that) { + Copy(that); + return *this; + } + + inline ~Persistent() { + if (M::kResetInDestructor) this->Reset(); + } + + private: + inline T *operator*() const { return *PersistentBase::persistent; } + + template + inline void Copy(const Persistent &that) { + TYPE_CHECK(T, S); + + this->Reset(); + + if (!that.IsEmpty()) { + this->persistent = v8::Persistent::New(that.persistent); + M::Copy(that, this); + } + } +}; + +template +class Global : public PersistentBase { + struct RValue { + inline explicit RValue(Global* obj) : object(obj) {} + Global* object; + }; + + public: + inline Global() : PersistentBase(0) { } + + template + inline Global(v8::Local that) // NOLINT(runtime/explicit) + : PersistentBase(v8::Persistent::New(that)) { + TYPE_CHECK(T, S); + } + + template + inline Global(const PersistentBase &that) // NOLINT(runtime/explicit) + : PersistentBase(that) { + TYPE_CHECK(T, S); + } + /** + * Move constructor. + */ + inline Global(RValue rvalue) // NOLINT(runtime/explicit) + : PersistentBase(rvalue.object->persistent) { + rvalue.object->Reset(); + } + inline ~Global() { this->Reset(); } + /** + * Move via assignment. + */ + template + inline Global &operator=(Global rhs) { + TYPE_CHECK(T, S); + this->Reset(rhs.persistent); + rhs.Reset(); + return *this; + } + /** + * Cast operator for moves. + */ + inline operator RValue() { return RValue(this); } + /** + * Pass allows returning uniques from functions, etc. + */ + Global Pass() { return Global(RValue(this)); } + + private: + Global(Global &); + void operator=(Global &); + template friend class ReturnValue; +}; + +#endif // NAN_PERSISTENT_PRE_12_INL_H_ diff --git a/deps/node-report/node_modules/nan/nan_private.h b/deps/node-report/node_modules/nan/nan_private.h new file mode 100644 index 00000000000000..15f44cc8c29386 --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_private.h @@ -0,0 +1,73 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PRIVATE_H_ +#define NAN_PRIVATE_H_ + +inline Maybe +HasPrivate(v8::Local object, v8::Local key) { + HandleScope scope; +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->HasPrivate(context, private_key); +#else + return Just(!object->GetHiddenValue(key).IsEmpty()); +#endif +} + +inline MaybeLocal +GetPrivate(v8::Local object, v8::Local key) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + v8::MaybeLocal v = object->GetPrivate(context, private_key); + return scope.Escape(v.ToLocalChecked()); +#else + EscapableHandleScope scope; + v8::Local v = object->GetHiddenValue(key); + if (v.IsEmpty()) { + v = Undefined(); + } + return scope.Escape(v); +#endif +} + +inline Maybe SetPrivate( + v8::Local object, + v8::Local key, + v8::Local value) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + HandleScope scope; + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->SetPrivate(context, private_key, value); +#else + return Just(object->SetHiddenValue(key, value)); +#endif +} + +inline Maybe DeletePrivate( + v8::Local object, + v8::Local key) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + HandleScope scope; + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->DeletePrivate(isolate->GetCurrentContext(), private_key); +#else + return Just(object->DeleteHiddenValue(key)); +#endif +} + +#endif // NAN_PRIVATE_H_ + diff --git a/deps/node-report/node_modules/nan/nan_string_bytes.h b/deps/node-report/node_modules/nan/nan_string_bytes.h new file mode 100644 index 00000000000000..a2e6437d12b74c --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_string_bytes.h @@ -0,0 +1,305 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef NAN_STRING_BYTES_H_ +#define NAN_STRING_BYTES_H_ + +// Decodes a v8::Local or Buffer to a raw char* + +namespace imp { + +using v8::Local; +using v8::Object; +using v8::String; +using v8::Value; + + +//// Base 64 //// + +#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) + + + +//// HEX //// + +static bool contains_non_ascii_slow(const char* buf, size_t len) { + for (size_t i = 0; i < len; ++i) { + if (buf[i] & 0x80) return true; + } + return false; +} + + +static bool contains_non_ascii(const char* src, size_t len) { + if (len < 16) { + return contains_non_ascii_slow(src, len); + } + + const unsigned bytes_per_word = sizeof(void*); + const unsigned align_mask = bytes_per_word - 1; + const unsigned unaligned = reinterpret_cast(src) & align_mask; + + if (unaligned > 0) { + const unsigned n = bytes_per_word - unaligned; + if (contains_non_ascii_slow(src, n)) return true; + src += n; + len -= n; + } + + +#if defined(__x86_64__) || defined(_WIN64) + const uintptr_t mask = 0x8080808080808080ll; +#else + const uintptr_t mask = 0x80808080l; +#endif + + const uintptr_t* srcw = reinterpret_cast(src); + + for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) { + if (srcw[i] & mask) return true; + } + + const unsigned remainder = len & align_mask; + if (remainder > 0) { + const size_t offset = len - remainder; + if (contains_non_ascii_slow(src + offset, remainder)) return true; + } + + return false; +} + + +static void force_ascii_slow(const char* src, char* dst, size_t len) { + for (size_t i = 0; i < len; ++i) { + dst[i] = src[i] & 0x7f; + } +} + + +static void force_ascii(const char* src, char* dst, size_t len) { + if (len < 16) { + force_ascii_slow(src, dst, len); + return; + } + + const unsigned bytes_per_word = sizeof(void*); + const unsigned align_mask = bytes_per_word - 1; + const unsigned src_unalign = reinterpret_cast(src) & align_mask; + const unsigned dst_unalign = reinterpret_cast(dst) & align_mask; + + if (src_unalign > 0) { + if (src_unalign == dst_unalign) { + const unsigned unalign = bytes_per_word - src_unalign; + force_ascii_slow(src, dst, unalign); + src += unalign; + dst += unalign; + len -= src_unalign; + } else { + force_ascii_slow(src, dst, len); + return; + } + } + +#if defined(__x86_64__) || defined(_WIN64) + const uintptr_t mask = ~0x8080808080808080ll; +#else + const uintptr_t mask = ~0x80808080l; +#endif + + const uintptr_t* srcw = reinterpret_cast(src); + uintptr_t* dstw = reinterpret_cast(dst); + + for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) { + dstw[i] = srcw[i] & mask; + } + + const unsigned remainder = len & align_mask; + if (remainder > 0) { + const size_t offset = len - remainder; + force_ascii_slow(src + offset, dst + offset, remainder); + } +} + + +static size_t base64_encode(const char* src, + size_t slen, + char* dst, + size_t dlen) { + // We know how much we'll write, just make sure that there's space. + assert(dlen >= base64_encoded_size(slen) && + "not enough space provided for base64 encode"); + + dlen = base64_encoded_size(slen); + + unsigned a; + unsigned b; + unsigned c; + unsigned i; + unsigned k; + unsigned n; + + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + i = 0; + k = 0; + n = slen / 3 * 3; + + while (i < n) { + a = src[i + 0] & 0xff; + b = src[i + 1] & 0xff; + c = src[i + 2] & 0xff; + + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[((a & 3) << 4) | (b >> 4)]; + dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)]; + dst[k + 3] = table[c & 0x3f]; + + i += 3; + k += 4; + } + + if (n != slen) { + switch (slen - n) { + case 1: + a = src[i + 0] & 0xff; + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[(a & 3) << 4]; + dst[k + 2] = '='; + dst[k + 3] = '='; + break; + + case 2: + a = src[i + 0] & 0xff; + b = src[i + 1] & 0xff; + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[((a & 3) << 4) | (b >> 4)]; + dst[k + 2] = table[(b & 0x0f) << 2]; + dst[k + 3] = '='; + break; + } + } + + return dlen; +} + + +static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) { + // We know how much we'll write, just make sure that there's space. + assert(dlen >= slen * 2 && + "not enough space provided for hex encode"); + + dlen = slen * 2; + for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) { + static const char hex[] = "0123456789abcdef"; + uint8_t val = static_cast(src[i]); + dst[k + 0] = hex[val >> 4]; + dst[k + 1] = hex[val & 15]; + } + + return dlen; +} + + + +static Local Encode(const char* buf, + size_t buflen, + enum Encoding encoding) { + assert(buflen <= node::Buffer::kMaxLength); + if (!buflen && encoding != BUFFER) + return New("").ToLocalChecked(); + + Local val; + switch (encoding) { + case BUFFER: + return CopyBuffer(buf, buflen).ToLocalChecked(); + + case ASCII: + if (contains_non_ascii(buf, buflen)) { + char* out = new char[buflen]; + force_ascii(buf, out, buflen); + val = New(out, buflen).ToLocalChecked(); + delete[] out; + } else { + val = New(buf, buflen).ToLocalChecked(); + } + break; + + case UTF8: + val = New(buf, buflen).ToLocalChecked(); + break; + + case BINARY: { + // TODO(isaacs) use ExternalTwoByteString? + const unsigned char *cbuf = reinterpret_cast(buf); + uint16_t * twobytebuf = new uint16_t[buflen]; + for (size_t i = 0; i < buflen; i++) { + // XXX is the following line platform independent? + twobytebuf[i] = cbuf[i]; + } + val = New(twobytebuf, buflen).ToLocalChecked(); + delete[] twobytebuf; + break; + } + + case BASE64: { + size_t dlen = base64_encoded_size(buflen); + char* dst = new char[dlen]; + + size_t written = base64_encode(buf, buflen, dst, dlen); + assert(written == dlen); + + val = New(dst, dlen).ToLocalChecked(); + delete[] dst; + break; + } + + case UCS2: { + const uint16_t* data = reinterpret_cast(buf); + val = New(data, buflen / 2).ToLocalChecked(); + break; + } + + case HEX: { + size_t dlen = buflen * 2; + char* dst = new char[dlen]; + size_t written = hex_encode(buf, buflen, dst, dlen); + assert(written == dlen); + + val = New(dst, dlen).ToLocalChecked(); + delete[] dst; + break; + } + + default: + assert(0 && "unknown encoding"); + break; + } + + return val; +} + +#undef base64_encoded_size + +} // end of namespace imp + +#endif // NAN_STRING_BYTES_H_ diff --git a/deps/node-report/node_modules/nan/nan_typedarray_contents.h b/deps/node-report/node_modules/nan/nan_typedarray_contents.h new file mode 100644 index 00000000000000..d28ae323e2276b --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_typedarray_contents.h @@ -0,0 +1,90 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_TYPEDARRAY_CONTENTS_H_ +#define NAN_TYPEDARRAY_CONTENTS_H_ + +template +class TypedArrayContents { + public: + inline explicit TypedArrayContents(v8::Local from) : + length_(0), data_(NULL) { + HandleScope scope; + + size_t length = 0; + void* data = NULL; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + if (from->IsArrayBufferView()) { + v8::Local array = + v8::Local::Cast(from); + + const size_t byte_length = array->ByteLength(); + const ptrdiff_t byte_offset = array->ByteOffset(); + v8::Local buffer = array->Buffer(); + + length = byte_length / sizeof(T); + data = static_cast(buffer->GetContents().Data()) + byte_offset; + } + +#else + + if (from->IsObject() && !from->IsNull()) { + v8::Local array = v8::Local::Cast(from); + + MaybeLocal buffer = Get(array, + New("buffer").ToLocalChecked()); + MaybeLocal byte_length = Get(array, + New("byteLength").ToLocalChecked()); + MaybeLocal byte_offset = Get(array, + New("byteOffset").ToLocalChecked()); + + if (!buffer.IsEmpty() && + !byte_length.IsEmpty() && byte_length.ToLocalChecked()->IsUint32() && + !byte_offset.IsEmpty() && byte_offset.ToLocalChecked()->IsUint32()) { + data = array->GetIndexedPropertiesExternalArrayData(); + if(data) { + length = byte_length.ToLocalChecked()->Uint32Value() / sizeof(T); + } + } + } + +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1900 || __cplusplus >= 201103L + assert(reinterpret_cast(data) % alignof (T) == 0); +#elif defined(_MSC_VER) && _MSC_VER >= 1600 || defined(__GNUC__) + assert(reinterpret_cast(data) % __alignof(T) == 0); +#else + assert(reinterpret_cast(data) % sizeof (T) == 0); +#endif + + length_ = length; + data_ = static_cast(data); + } + + inline size_t length() const { return length_; } + inline T* operator*() { return data_; } + inline const T* operator*() const { return data_; } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(TypedArrayContents) + + //Disable heap allocation + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } + + size_t length_; + T* data_; +}; + +#endif // NAN_TYPEDARRAY_CONTENTS_H_ diff --git a/deps/node-report/node_modules/nan/nan_weak.h b/deps/node-report/node_modules/nan/nan_weak.h new file mode 100644 index 00000000000000..744ffd6ea0a47b --- /dev/null +++ b/deps/node-report/node_modules/nan/nan_weak.h @@ -0,0 +1,432 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_WEAK_H_ +#define NAN_WEAK_H_ + +static const int kInternalFieldsInWeakCallback = 2; +static const int kNoInternalFieldIndex = -1; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::WeakCallbackInfo > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::PhantomCallbackData > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::PhantomCallbackData > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + v8::InternalFieldsCallbackData, void> const& +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# define NAN_WEAK_CALLBACK_DATA_TYPE_ \ + v8::WeakCallbackData > const& +# define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_ +#else +# define NAN_WEAK_CALLBACK_DATA_TYPE_ void * +# define NAN_WEAK_CALLBACK_SIG_ \ + v8::Persistent, NAN_WEAK_CALLBACK_DATA_TYPE_ +#endif + +template +class WeakCallbackInfo { + public: + typedef void (*Callback)(const WeakCallbackInfo& data); + WeakCallbackInfo( + Persistent *persistent + , Callback callback + , void *parameter + , void *field1 = 0 + , void *field2 = 0) : + callback_(callback), isolate_(0), parameter_(parameter) { + std::memcpy(&persistent_, persistent, sizeof (v8::Persistent)); + internal_fields_[0] = field1; + internal_fields_[1] = field2; + } + inline v8::Isolate *GetIsolate() const { return isolate_; } + inline T *GetParameter() const { return static_cast(parameter_); } + inline void *GetInternalField(int index) const { + assert((index == 0 || index == 1) && "internal field index out of bounds"); + if (index == 0) { + return internal_fields_[0]; + } else { + return internal_fields_[1]; + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo) + Callback callback_; + v8::Isolate *isolate_; + void *parameter_; + void *internal_fields_[kInternalFieldsInWeakCallback]; + v8::Persistent persistent_; + template friend class Persistent; + template friend class PersistentBase; +#if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION +# if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + template + static void invoke(NAN_WEAK_CALLBACK_SIG_ data); + template + static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); +# else + static void invoke(NAN_WEAK_CALLBACK_SIG_ data); + static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); +# endif +#else +# if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + template + static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); + template + static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); +# else + static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); + static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); +# endif + static WeakCallbackInfo *unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data); + static WeakCallbackInfo *unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data); +#endif +}; + + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + +template +template +void +WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrapparameter(data); + if (isFirstPass) { + cbinfo->persistent_.Reset(); + data.SetSecondPassCallback(invokeparameter); + } else { + cbinfo->callback_(*cbinfo); + delete cbinfo; + } +} + +template +template +void +WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwraptwofield(data); + if (isFirstPass) { + cbinfo->persistent_.Reset(); + data.SetSecondPassCallback(invoketwofield); + } else { + cbinfo->callback_(*cbinfo); + delete cbinfo; + } +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetParameter()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetInternalField(0)); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ +#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +# elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + +template +void +WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrapparameter(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +void +WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwraptwofield(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetParameter()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetInternalField1()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ +#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + +template +template +void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrap(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +template +WeakCallbackInfo *WeakCallbackInfo::unwrap( + NAN_WEAK_CALLBACK_DATA_TYPE_ data) { + void *parameter = data.GetParameter(); + WeakCallbackInfo *cbinfo = + static_cast*>(parameter); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_CALLBACK_SIG_ +#undef NAN_WEAK_CALLBACK_DATA_TYPE_ +#else + +template +void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrap(data); + cbinfo->persistent_.Dispose(); + cbinfo->persistent_.Clear(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrap( + NAN_WEAK_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data); + cbinfo->isolate_ = v8::Isolate::GetCurrent(); + return cbinfo; +} + +#undef NAN_WEAK_CALLBACK_SIG_ +#undef NAN_WEAK_CALLBACK_DATA_TYPE_ +#endif + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetWeak( + wcbd + , WeakCallbackInfo

::template invokeparameter + , type); + } else { + v8::Local* self = reinterpret_cast*>(this); + assert((*self)->IsObject()); + int count = (*self)->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + (*self)->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetWeak( + static_cast*>(0) + , WeakCallbackInfo

::template invoketwofield + , type); + } +} +#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetPhantom( + wcbd + , WeakCallbackInfo

::invokeparameter); + } else { + v8::Local* self = reinterpret_cast*>(this); + assert((*self)->IsObject()); + int count = (*self)->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + (*self)->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetPhantom( + static_cast*>(0) + , WeakCallbackInfo

::invoketwofield + , 0 + , count > 1 ? 1 : kNoInternalFieldIndex); + } +} +#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetPhantom( + wcbd + , WeakCallbackInfo

::invokeparameter); + } else { + v8::Local* self = reinterpret_cast*>(this); + assert((*self)->IsObject()); + int count = (*self)->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + (*self)->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetPhantom( + WeakCallbackInfo

::invoketwofield + , 0 + , count > 1 ? 1 : kNoInternalFieldIndex); + } +} +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + } else { + v8::Local* self = reinterpret_cast*>(this); + assert((*self)->IsObject()); + int count = (*self)->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = (*self)->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + } +} +#else +template +template +inline void PersistentBase::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); + } else { + v8::Local* self = reinterpret_cast*>(this); + assert((*self)->IsObject()); + int count = (*self)->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = (*self)->GetPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); + } +} +#endif + +#endif // NAN_WEAK_H_ diff --git a/deps/node-report/node_modules/nan/package.json b/deps/node-report/node_modules/nan/package.json new file mode 100644 index 00000000000000..c2d194633bfd7c --- /dev/null +++ b/deps/node-report/node_modules/nan/package.json @@ -0,0 +1,97 @@ +{ + "_from": "nan@^2.3.5", + "_id": "nan@2.10.0", + "_inBundle": false, + "_integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "_location": "/nan", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "nan@^2.3.5", + "name": "nan", + "escapedName": "nan", + "rawSpec": "^2.3.5", + "saveSpec": null, + "fetchSpec": "^2.3.5" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "_shasum": "96d0cd610ebd58d4b4de9cc0c6828cda99c7548f", + "_spec": "nan@^2.3.5", + "_where": "/home/users/riclau/sandbox/github/nodejs/deps/node-report-tmp/node-report-2.2.1", + "bugs": { + "url": "https://github.com/nodejs/nan/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "Benjamin Byholm", + "email": "bbyholm@abo.fi", + "url": "https://github.com/kkoopa/" + }, + { + "name": "Trevor Norris", + "email": "trev.norris@gmail.com", + "url": "https://github.com/trevnorris" + }, + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "https://github.com/TooTallNate" + }, + { + "name": "Brett Lawson", + "email": "brett19@gmail.com", + "url": "https://github.com/brett19" + }, + { + "name": "Ben Noordhuis", + "email": "info@bnoordhuis.nl", + "url": "https://github.com/bnoordhuis" + }, + { + "name": "David Siegel", + "email": "david@artcom.de", + "url": "https://github.com/agnat" + }, + { + "name": "Michael Ira Krufky", + "email": "mkrufky@gmail.com", + "url": "https://github.com/mkrufky" + } + ], + "deprecated": false, + "description": "Native Abstractions for Node.js: C++ header for Node 0.8 -> 9 compatibility", + "devDependencies": { + "bindings": "~1.2.1", + "commander": "^2.8.1", + "glob": "^5.0.14", + "node-gyp": "~3.6.2", + "readable-stream": "^2.1.4", + "request": "=2.81.0", + "tap": "~0.7.1", + "xtend": "~4.0.0" + }, + "homepage": "https://github.com/nodejs/nan#readme", + "license": "MIT", + "main": "include_dirs.js", + "name": "nan", + "repository": { + "type": "git", + "url": "git://github.com/nodejs/nan.git" + }, + "scripts": { + "docs": "doc/.build.sh", + "rebuild-tests": "node-gyp rebuild --msvs_version=2015 --directory test", + "test": "tap --gc --stderr test/js/*-test.js" + }, + "version": "2.10.0" +} diff --git a/deps/node-report/node_modules/nan/tools/1to2.js b/deps/node-report/node_modules/nan/tools/1to2.js new file mode 100755 index 00000000000000..337f8bf2c2bed3 --- /dev/null +++ b/deps/node-report/node_modules/nan/tools/1to2.js @@ -0,0 +1,412 @@ +#!/usr/bin/env node +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +var commander = require('commander'), + fs = require('fs'), + glob = require('glob'), + groups = [], + total = 0, + warning1 = '/* ERROR: Rewrite using Buffer */\n', + warning2 = '\\/\\* ERROR\\: Rewrite using Buffer \\*\\/\\n', + length, + i; + +fs.readFile(__dirname + '/package.json', 'utf8', function (err, data) { + if (err) { + throw err; + } + + commander + .version(JSON.parse(data).version) + .usage('[options] ') + .parse(process.argv); + + if (!process.argv.slice(2).length) { + commander.outputHelp(); + } +}); + +/* construct strings representing regular expressions + each expression contains a unique group allowing for identification of the match + the index of this key group, relative to the regular expression in question, + is indicated by the first array member */ + +/* simple substistutions, key group is the entire match, 0 */ +groups.push([0, [ + '_NAN_', + 'NODE_SET_METHOD', + 'NODE_SET_PROTOTYPE_METHOD', + 'NanAsciiString', + 'NanEscapeScope', + 'NanReturnValue', + 'NanUcs2String'].join('|')]); + +/* substitutions of parameterless macros, key group is 1 */ +groups.push([1, ['(', [ + 'NanEscapableScope', + 'NanReturnNull', + 'NanReturnUndefined', + 'NanScope'].join('|'), ')\\(\\)'].join('')]); + +/* replace TryCatch with NanTryCatch once, gobbling possible namespace, key group 2 */ +groups.push([2, '(?:(?:v8\\:\\:)?|(Nan)?)(TryCatch)']); + +/* NanNew("string") will likely not fail a ToLocalChecked(), key group 1 */ +groups.push([1, ['(NanNew)', '(\\("[^\\"]*"[^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]); + +/* Removed v8 APIs, warn that the code needs rewriting using node::Buffer, key group 2 */ +groups.push([2, ['(', warning2, ')?', '^.*?(', [ + 'GetIndexedPropertiesExternalArrayDataLength', + 'GetIndexedPropertiesExternalArrayData', + 'GetIndexedPropertiesExternalArrayDataType', + 'GetIndexedPropertiesPixelData', + 'GetIndexedPropertiesPixelDataLength', + 'HasIndexedPropertiesInExternalArrayData', + 'HasIndexedPropertiesInPixelData', + 'SetIndexedPropertiesToExternalArrayData', + 'SetIndexedPropertiesToPixelData'].join('|'), ')'].join('')]); + +/* No need for NanScope in V8-exposed methods, key group 2 */ +groups.push([2, ['((', [ + 'NAN_METHOD', + 'NAN_GETTER', + 'NAN_SETTER', + 'NAN_PROPERTY_GETTER', + 'NAN_PROPERTY_SETTER', + 'NAN_PROPERTY_ENUMERATOR', + 'NAN_PROPERTY_DELETER', + 'NAN_PROPERTY_QUERY', + 'NAN_INDEX_GETTER', + 'NAN_INDEX_SETTER', + 'NAN_INDEX_ENUMERATOR', + 'NAN_INDEX_DELETER', + 'NAN_INDEX_QUERY'].join('|'), ')\\([^\\)]*\\)\\s*\\{)\\s*NanScope\\(\\)\\s*;'].join('')]); + +/* v8::Value::ToXXXXXXX returns v8::MaybeLocal, key group 3 */ +groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->(', [ + 'Boolean', + 'Number', + 'String', + 'Object', + 'Integer', + 'Uint32', + 'Int32'].join('|'), ')\\('].join('')]); + +/* v8::Value::XXXXXXXValue returns v8::Maybe, key group 3 */ +groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->((?:', [ + 'Boolean', + 'Number', + 'Integer', + 'Uint32', + 'Int32'].join('|'), ')Value)\\('].join('')]); + +/* NAN_WEAK_CALLBACK macro was removed, write out callback definition, key group 1 */ +groups.push([1, '(NAN_WEAK_CALLBACK)\\(([^\\s\\)]+)\\)']); + +/* node::ObjectWrap and v8::Persistent have been replaced with Nan implementations, key group 1 */ +groups.push([1, ['(', [ + 'NanDisposePersistent', + 'NanObjectWrapHandle'].join('|'), ')\\s*\\(\\s*([^\\s\\)]+)'].join('')]); + +/* Since NanPersistent there is no need for NanMakeWeakPersistent, key group 1 */ +groups.push([1, '(NanMakeWeakPersistent)\\s*\\(\\s*([^\\s,]+)\\s*,\\s*']); + +/* Many methods of v8::Object and others now return v8::MaybeLocal, key group 3 */ +groups.push([3, ['([\\s])([^\\s]+)->(', [ + 'GetEndColumn', + 'GetFunction', + 'GetLineNumber', + 'NewInstance', + 'GetPropertyNames', + 'GetOwnPropertyNames', + 'GetSourceLine', + 'GetStartColumn', + 'ObjectProtoToString', + 'ToArrayIndex', + 'ToDetailString', + 'CallAsConstructor', + 'CallAsFunction', + 'CloneElementAt', + 'Delete', + 'ForceSet', + 'Get', + 'GetPropertyAttributes', + 'GetRealNamedProperty', + 'GetRealNamedPropertyInPrototypeChain', + 'Has', + 'HasOwnProperty', + 'HasRealIndexedProperty', + 'HasRealNamedCallbackProperty', + 'HasRealNamedProperty', + 'Set', + 'SetAccessor', + 'SetIndexedPropertyHandler', + 'SetNamedPropertyHandler', + 'SetPrototype'].join('|'), ')\\('].join('')]); + +/* You should get an error if any of these fail anyways, + or handle the error better, it is indicated either way, key group 2 */ +groups.push([2, ['NanNew(<(?:v8\\:\\:)?(', ['Date', 'String', 'RegExp'].join('|'), ')>)(\\([^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]); + +/* v8::Value::Equals now returns a v8::Maybe, key group 3 */ +groups.push([3, '([\\s\\(\\)])([^\\s\\(\\)]+)->(Equals)\\(([^\\s\\)]+)']); + +/* NanPersistent makes this unnecessary, key group 1 */ +groups.push([1, '(NanAssignPersistent)(?:]+>)?\\(([^,]+),\\s*']); + +/* args has been renamed to info, key group 2 */ +groups.push([2, '(\\W)(args)(\\W)']) + +/* node::ObjectWrap was replaced with NanObjectWrap, key group 2 */ +groups.push([2, '(\\W)(?:node\\:\\:)?(ObjectWrap)(\\W)']); + +/* v8::Persistent was replaced with NanPersistent, key group 2 */ +groups.push([2, '(\\W)(?:v8\\:\\:)?(Persistent)(\\W)']); + +/* counts the number of capturing groups in a well-formed regular expression, + ignoring non-capturing groups and escaped parentheses */ +function groupcount(s) { + var positive = s.match(/\((?!\?)/g), + negative = s.match(/\\\(/g); + return (positive ? positive.length : 0) - (negative ? negative.length : 0); +} + +/* compute the absolute position of each key group in the joined master RegExp */ +for (i = 1, length = groups.length; i < length; i++) { + total += groupcount(groups[i - 1][1]); + groups[i][0] += total; +} + +/* create the master RegExp, whis is the union of all the groups' expressions */ +master = new RegExp(groups.map(function (a) { return a[1]; }).join('|'), 'gm'); + +/* replacement function for String.replace, receives 21 arguments */ +function replace() { + /* simple expressions */ + switch (arguments[groups[0][0]]) { + case '_NAN_': + return 'NAN_'; + case 'NODE_SET_METHOD': + return 'NanSetMethod'; + case 'NODE_SET_PROTOTYPE_METHOD': + return 'NanSetPrototypeMethod'; + case 'NanAsciiString': + return 'NanUtf8String'; + case 'NanEscapeScope': + return 'scope.Escape'; + case 'NanReturnNull': + return 'info.GetReturnValue().SetNull'; + case 'NanReturnValue': + return 'info.GetReturnValue().Set'; + case 'NanUcs2String': + return 'v8::String::Value'; + default: + } + + /* macros without arguments */ + switch (arguments[groups[1][0]]) { + case 'NanEscapableScope': + return 'NanEscapableScope scope' + case 'NanReturnUndefined': + return 'return'; + case 'NanScope': + return 'NanScope scope'; + default: + } + + /* TryCatch, emulate negative backref */ + if (arguments[groups[2][0]] === 'TryCatch') { + return arguments[groups[2][0] - 1] ? arguments[0] : 'NanTryCatch'; + } + + /* NanNew("foo") --> NanNew("foo").ToLocalChecked() */ + if (arguments[groups[3][0]] === 'NanNew') { + return [arguments[0], '.ToLocalChecked()'].join(''); + } + + /* insert warning for removed functions as comment on new line above */ + switch (arguments[groups[4][0]]) { + case 'GetIndexedPropertiesExternalArrayData': + case 'GetIndexedPropertiesExternalArrayDataLength': + case 'GetIndexedPropertiesExternalArrayDataType': + case 'GetIndexedPropertiesPixelData': + case 'GetIndexedPropertiesPixelDataLength': + case 'HasIndexedPropertiesInExternalArrayData': + case 'HasIndexedPropertiesInPixelData': + case 'SetIndexedPropertiesToExternalArrayData': + case 'SetIndexedPropertiesToPixelData': + return arguments[groups[4][0] - 1] ? arguments[0] : [warning1, arguments[0]].join(''); + default: + } + + /* remove unnecessary NanScope() */ + switch (arguments[groups[5][0]]) { + case 'NAN_GETTER': + case 'NAN_METHOD': + case 'NAN_SETTER': + case 'NAN_INDEX_DELETER': + case 'NAN_INDEX_ENUMERATOR': + case 'NAN_INDEX_GETTER': + case 'NAN_INDEX_QUERY': + case 'NAN_INDEX_SETTER': + case 'NAN_PROPERTY_DELETER': + case 'NAN_PROPERTY_ENUMERATOR': + case 'NAN_PROPERTY_GETTER': + case 'NAN_PROPERTY_QUERY': + case 'NAN_PROPERTY_SETTER': + return arguments[groups[5][0] - 1]; + default: + } + + /* Value converstion */ + switch (arguments[groups[6][0]]) { + case 'Boolean': + case 'Int32': + case 'Integer': + case 'Number': + case 'Object': + case 'String': + case 'Uint32': + return [arguments[groups[6][0] - 2], 'NanTo(', arguments[groups[6][0] - 1]].join(''); + default: + } + + /* other value conversion */ + switch (arguments[groups[7][0]]) { + case 'BooleanValue': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'Int32Value': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'IntegerValue': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'Uint32Value': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + default: + } + + /* NAN_WEAK_CALLBACK */ + if (arguments[groups[8][0]] === 'NAN_WEAK_CALLBACK') { + return ['template\nvoid ', + arguments[groups[8][0] + 1], '(const NanWeakCallbackInfo &data)'].join(''); + } + + /* use methods on NAN classes instead */ + switch (arguments[groups[9][0]]) { + case 'NanDisposePersistent': + return [arguments[groups[9][0] + 1], '.Reset('].join(''); + case 'NanObjectWrapHandle': + return [arguments[groups[9][0] + 1], '->handle('].join(''); + default: + } + + /* use method on NanPersistent instead */ + if (arguments[groups[10][0]] === 'NanMakeWeakPersistent') { + return arguments[groups[10][0] + 1] + '.SetWeak('; + } + + /* These return Maybes, the upper ones take no arguments */ + switch (arguments[groups[11][0]]) { + case 'GetEndColumn': + case 'GetFunction': + case 'GetLineNumber': + case 'GetOwnPropertyNames': + case 'GetPropertyNames': + case 'GetSourceLine': + case 'GetStartColumn': + case 'NewInstance': + case 'ObjectProtoToString': + case 'ToArrayIndex': + case 'ToDetailString': + return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1]].join(''); + case 'CallAsConstructor': + case 'CallAsFunction': + case 'CloneElementAt': + case 'Delete': + case 'ForceSet': + case 'Get': + case 'GetPropertyAttributes': + case 'GetRealNamedProperty': + case 'GetRealNamedPropertyInPrototypeChain': + case 'Has': + case 'HasOwnProperty': + case 'HasRealIndexedProperty': + case 'HasRealNamedCallbackProperty': + case 'HasRealNamedProperty': + case 'Set': + case 'SetAccessor': + case 'SetIndexedPropertyHandler': + case 'SetNamedPropertyHandler': + case 'SetPrototype': + return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1], ', '].join(''); + default: + } + + /* Automatic ToLocalChecked(), take it or leave it */ + switch (arguments[groups[12][0]]) { + case 'Date': + case 'String': + case 'RegExp': + return ['NanNew', arguments[groups[12][0] - 1], arguments[groups[12][0] + 1], '.ToLocalChecked()'].join(''); + default: + } + + /* NanEquals is now required for uniformity */ + if (arguments[groups[13][0]] === 'Equals') { + return [arguments[groups[13][0] - 1], 'NanEquals(', arguments[groups[13][0] - 1], ', ', arguments[groups[13][0] + 1]].join(''); + } + + /* use method on replacement class instead */ + if (arguments[groups[14][0]] === 'NanAssignPersistent') { + return [arguments[groups[14][0] + 1], '.Reset('].join(''); + } + + /* args --> info */ + if (arguments[groups[15][0]] === 'args') { + return [arguments[groups[15][0] - 1], 'info', arguments[groups[15][0] + 1]].join(''); + } + + /* ObjectWrap --> NanObjectWrap */ + if (arguments[groups[16][0]] === 'ObjectWrap') { + return [arguments[groups[16][0] - 1], 'NanObjectWrap', arguments[groups[16][0] + 1]].join(''); + } + + /* Persistent --> NanPersistent */ + if (arguments[groups[17][0]] === 'Persistent') { + return [arguments[groups[17][0] - 1], 'NanPersistent', arguments[groups[17][0] + 1]].join(''); + } + + /* This should not happen. A switch is probably missing a case if it does. */ + throw 'Unhandled match: ' + arguments[0]; +} + +/* reads a file, runs replacement and writes it back */ +function processFile(file) { + fs.readFile(file, {encoding: 'utf8'}, function (err, data) { + if (err) { + throw err; + } + + /* run replacement twice, might need more runs */ + fs.writeFile(file, data.replace(master, replace).replace(master, replace), function (err) { + if (err) { + throw err; + } + }); + }); +} + +/* process file names from command line and process the identified files */ +for (i = 2, length = process.argv.length; i < length; i++) { + glob(process.argv[i], function (err, matches) { + if (err) { + throw err; + } + matches.forEach(processFile); + }); +} diff --git a/deps/node-report/node_modules/nan/tools/README.md b/deps/node-report/node_modules/nan/tools/README.md new file mode 100644 index 00000000000000..7f07e4b8256dd1 --- /dev/null +++ b/deps/node-report/node_modules/nan/tools/README.md @@ -0,0 +1,14 @@ +1to2 naively converts source code files from NAN 1 to NAN 2. There will be erroneous conversions, +false positives and missed opportunities. The input files are rewritten in place. Make sure that +you have backups. You will have to manually review the changes afterwards and do some touchups. + +```sh +$ tools/1to2.js + + Usage: 1to2 [options] + + Options: + + -h, --help output usage information + -V, --version output the version number +``` diff --git a/deps/node-report/node_modules/nan/tools/package.json b/deps/node-report/node_modules/nan/tools/package.json new file mode 100644 index 00000000000000..2dcdd789394965 --- /dev/null +++ b/deps/node-report/node_modules/nan/tools/package.json @@ -0,0 +1,19 @@ +{ + "name": "1to2", + "version": "1.0.0", + "description": "NAN 1 -> 2 Migration Script", + "main": "1to2.js", + "repository": { + "type": "git", + "url": "git://github.com/nodejs/nan.git" + }, + "contributors": [ + "Benjamin Byholm (https://github.com/kkoopa/)", + "Mathias Küsel (https://github.com/mathiask88/)" + ], + "dependencies": { + "glob": "~5.0.10", + "commander": "~2.8.1" + }, + "license": "MIT" +} diff --git a/deps/node-report/package.json b/deps/node-report/package.json new file mode 100644 index 00000000000000..f97baf70605feb --- /dev/null +++ b/deps/node-report/package.json @@ -0,0 +1,29 @@ +{ + "name": "node-report", + "version": "2.2.1", + "description": "Diagnostic Report for Node.js", + "homepage": "https://github.com/nodejs/node-report#readme", + "repository": { + "type": "git", + "url": "https://github.com/nodejs/node-report.git" + }, + "engines": { + "node": ">=4.0.0" + }, + "dependencies": { + "nan": "^2.3.5" + }, + "license": "MIT", + "contributors": [ + "Richard Chamberlain (https://github.com/rnchamberlain)" + ], + "scripts": { + "test": "tap --timeout=300 test/test*.js" + }, + "bugs": { + "url": "https://github.com/nodejs/node-report/issues" + }, + "devDependencies": { + "tap": "^8.0.0" + } +} diff --git a/deps/node-report/src/module.cc b/deps/node-report/src/module.cc new file mode 100644 index 00000000000000..af8331ffeadb80 --- /dev/null +++ b/deps/node-report/src/module.cc @@ -0,0 +1,454 @@ +#include "node_report.h" + +#include + +namespace nodereport { + +// Internal/static function declarations +static void OnFatalError(const char* location, const char* message); +bool OnUncaughtException(v8::Isolate* isolate); +#ifdef _WIN32 +static void PrintStackFromStackTrace(Isolate* isolate, FILE* fp); +#else // signal trigger functions for Unix platforms and OSX +static void SignalDumpAsyncCallback(uv_async_t* handle); +inline void* ReportSignalThreadMain(void* unused); +static int StartWatchdogThread(void* (*thread_main)(void* unused)); +static void RegisterSignalHandler(int signo, void (*handler)(int), + struct sigaction* saved_sa); +static void RestoreSignalHandler(int signo, struct sigaction* saved_sa); +static void SignalDump(int signo); +static void SetupSignalHandler(); +#endif + +// Default node-report option settings +static unsigned int nodereport_events = NR_APICALL; +static unsigned int nodereport_verbose = 0; +#ifdef _WIN32 // signal trigger not supported on Windows +static unsigned int nodereport_signal = 0; +#else // trigger signal supported on Unix platforms and OSX +static unsigned int nodereport_signal = SIGUSR2; // default signal is SIGUSR2 +static int report_signal = 0; // atomic for signal handling in progress +static uv_sem_t report_semaphore; // semaphore for hand-off to watchdog +static uv_async_t nodereport_trigger_async; // async handle for event loop +static uv_mutex_t node_isolate_mutex; // mutex for watchdog thread +static struct sigaction saved_sa; // saved signal action +#endif + +// State variables for v8 hooks and signal initialisation +static bool exception_hook_initialised = false; +static bool error_hook_initialised = false; +static bool signal_thread_initialised = false; + +static v8::Isolate* node_isolate; +extern std::string version_string; +extern std::string commandline_string; + +/******************************************************************************* + * External JavaScript API for triggering a report + * + ******************************************************************************/ +NAN_METHOD(TriggerReport) { + Nan::HandleScope scope; + v8::Isolate* isolate = info.GetIsolate(); + char filename[NR_MAXNAME + 1] = ""; + MaybeLocal error; + int err_index = 0; + + if (info[0]->IsString()) { + // Filename parameter supplied + Nan::Utf8String filename_parameter(info[0]); + if (filename_parameter.length() < NR_MAXNAME) { + snprintf(filename, sizeof(filename), "%s", *filename_parameter); + } else { + Nan::ThrowError("node-report: filename parameter is too long"); + } + err_index++; + } + + // We need to pass the JavaScript object so we can query it for a stack trace. + if (info[err_index]->IsNativeError()) { + error = info[err_index]; + } + + if (nodereport_events & NR_APICALL) { + TriggerNodeReport(isolate, kJavaScript, "JavaScript API", __func__, filename, error); + // Return value is the report filename + info.GetReturnValue().Set(Nan::New(filename).ToLocalChecked()); + } +} + +/******************************************************************************* + * External JavaScript API for returning a report + * + ******************************************************************************/ +NAN_METHOD(GetReport) { + Nan::HandleScope scope; + v8::Isolate* isolate = info.GetIsolate(); + std::ostringstream out; + + MaybeLocal error; + if (info[0]->IsNativeError()) { + error = info[0]; + } + + GetNodeReport(isolate, kJavaScript, "JavaScript API", __func__, error, out); + // Return value is the contents of a report as a string. + info.GetReturnValue().Set(Nan::New(out.str()).ToLocalChecked()); +} + +/******************************************************************************* + * External JavaScript APIs for node-report configuration + * + ******************************************************************************/ +NAN_METHOD(SetEvents) { + Nan::Utf8String parameter(info[0]); + v8::Isolate* isolate = info.GetIsolate(); + unsigned int previous_events = nodereport_events; // save previous settings + nodereport_events = ProcessNodeReportEvents(*parameter); + + // If report newly requested for fatalerror, set up the V8 callback + if ((nodereport_events & NR_FATALERROR) && (error_hook_initialised == false)) { + isolate->SetFatalErrorHandler(OnFatalError); + error_hook_initialised = true; + } + + // If report newly requested for exceptions, tell V8 to capture stack trace and set up the callback + if ((nodereport_events & NR_EXCEPTION) && (exception_hook_initialised == false)) { + isolate->SetCaptureStackTraceForUncaughtExceptions(true, 32, v8::StackTrace::kDetailed); + // The hook for uncaught exception won't get called unless the --abort_on_uncaught_exception option is set + v8::V8::SetFlagsFromString("--abort_on_uncaught_exception", sizeof("--abort_on_uncaught_exception")-1); + isolate->SetAbortOnUncaughtExceptionCallback(OnUncaughtException); + exception_hook_initialised = true; + } + +#ifndef _WIN32 + // If report newly requested on external user signal set up watchdog thread and handler + if ((nodereport_events & NR_SIGNAL) && (signal_thread_initialised == false)) { + SetupSignalHandler(); + } + // If report no longer required on external user signal, reset the OS signal handler + if (!(nodereport_events & NR_SIGNAL) && (previous_events & NR_SIGNAL)) { + RestoreSignalHandler(nodereport_signal, &saved_sa); + } +#endif +} +NAN_METHOD(SetSignal) { +#ifndef _WIN32 + Nan::Utf8String parameter(info[0]); + unsigned int previous_signal = nodereport_signal; // save previous setting + nodereport_signal = ProcessNodeReportSignal(*parameter); + + // If signal event active and selected signal has changed, switch the OS signal handler + if ((nodereport_events & NR_SIGNAL) && (nodereport_signal != previous_signal)) { + RestoreSignalHandler(previous_signal, &saved_sa); + RegisterSignalHandler(nodereport_signal, SignalDump, &saved_sa); + } +#endif +} +NAN_METHOD(SetFileName) { + Nan::Utf8String parameter(info[0]); + ProcessNodeReportFileName(*parameter); +} +NAN_METHOD(SetDirectory) { + Nan::Utf8String parameter(info[0]); + ProcessNodeReportDirectory(*parameter); +} +NAN_METHOD(SetVerbose) { + Nan::Utf8String parameter(info[0]); + nodereport_verbose = ProcessNodeReportVerboseSwitch(*parameter); +} + +/******************************************************************************* + * Callbacks for triggering report on fatal error, uncaught exception and + * external signals + ******************************************************************************/ +static void OnFatalError(const char* location, const char* message) { + if (location) { + fprintf(stderr, "FATAL ERROR: %s %s\n", location, message); + } else { + fprintf(stderr, "FATAL ERROR: %s\n", message); + } + // Trigger report if requested + if (nodereport_events & NR_FATALERROR) { + TriggerNodeReport(Isolate::GetCurrent(), kFatalError, message, location, nullptr, MaybeLocal()); + } + fflush(stderr); + raise(SIGABRT); +} + +bool OnUncaughtException(v8::Isolate* isolate) { + // Trigger report if requested + if (nodereport_events & NR_EXCEPTION) { + TriggerNodeReport(isolate, kException, "exception", __func__, nullptr, MaybeLocal()); + } + if ((commandline_string.find("abort-on-uncaught-exception") != std::string::npos) || + (commandline_string.find("abort_on_uncaught_exception") != std::string::npos)) { + return true; // abort required + } + // On versions earlier than 5.4, V8 does not provide the default behaviour + // for uncaught exception on return from this callback. Default behaviour is + // to print a stack trace and exit with rc=1, so we need to mimic that here. + int v8_major, v8_minor; + if (sscanf(v8::V8::GetVersion(), "%d.%d", &v8_major, &v8_minor) == 2) { + if (v8_major < 5 || (v8_major == 5 && v8_minor < 4)) { + fprintf(stderr, "\nUncaught exception at:\n"); +#ifdef _WIN32 + // On Windows, print the stack using StackTrace API + PrintStackFromStackTrace(isolate, stderr); +#else + // On other platforms use the Message API + Message::PrintCurrentStackTrace(isolate, stderr); +#endif + // exit direct from this callback with rc=1, to mimic V8 behaviour + exit(1); + } + } + return false; +} + +#ifdef _WIN32 +static void PrintStackFromStackTrace(Isolate* isolate, FILE* fp) { + Local stack = StackTrace::CurrentStackTrace(isolate, 255, + StackTrace::kDetailed); + // Print the JavaScript function name and source information for each frame + for (int i = 0; i < stack->GetFrameCount(); i++) { + Local frame = stack->GetFrame(i); + Nan::Utf8String fn_name_s(frame->GetFunctionName()); + Nan::Utf8String script_name(frame->GetScriptName()); + const int line_number = frame->GetLineNumber(); + const int column = frame->GetColumn(); + + if (frame->IsEval()) { + if (frame->GetScriptId() == Message::kNoScriptIdInfo) { + fprintf(fp, "at [eval]:%i:%i\n", line_number, column); + } else { + fprintf(fp, "at [eval] (%s:%i:%i)\n", *script_name, line_number, column); + } + } else { + if (fn_name_s.length() == 0) { + fprintf(fp, "%s:%i:%i\n", *script_name, line_number, column); + } else { + fprintf(fp, "%s (%s:%i:%i)\n", *fn_name_s, *script_name, line_number, column); + } + } + } +} +#else +// Signal handling functions, not supported on Windows +static void SignalDumpInterruptCallback(Isolate* isolate, void* data) { + if (report_signal != 0) { + if (nodereport_verbose) { + fprintf(stdout, "node-report: SignalDumpInterruptCallback handling signal\n"); + } + if (nodereport_events & NR_SIGNAL) { + if (nodereport_verbose) { + fprintf(stdout, "node-report: SignalDumpInterruptCallback triggering report\n"); + } + TriggerNodeReport(isolate, kSignal_JS, + node::signo_string(report_signal), __func__, nullptr, MaybeLocal()); + } + report_signal = 0; + } +} +static void SignalDumpAsyncCallback(uv_async_t* handle) { + if (report_signal != 0) { + if (nodereport_verbose) { + fprintf(stdout, "node-report: SignalDumpAsyncCallback handling signal\n"); + } + if (nodereport_events & NR_SIGNAL) { + if (nodereport_verbose) { + fprintf(stdout, "node-report: SignalDumpAsyncCallback triggering NodeReport\n"); + } + TriggerNodeReport(Isolate::GetCurrent(), kSignal_UV, + node::signo_string(report_signal), __func__, nullptr, MaybeLocal()); + } + report_signal = 0; + } +} + +/******************************************************************************* + * Utility functions for signal handling support (platforms except Windows) + * - RegisterSignalHandler() - register a raw OS signal handler + * - SignalDump() - implementation of raw OS signal handler + * - StartWatchdogThread() - create a watchdog thread + * - ReportSignalThreadMain() - implementation of watchdog thread + * - SetupSignalHandler() - initialisation of signal handlers and threads + ******************************************************************************/ +// Utility function to register an OS signal handler +static void RegisterSignalHandler(int signo, void (*handler)(int), + struct sigaction* saved_sa) { + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handler; + sigfillset(&sa.sa_mask); // mask all signals while in the handler + sigaction(signo, &sa, saved_sa); +} + +// Utility function to restore an OS signal handler to its previous setting +static void RestoreSignalHandler(int signo, struct sigaction* saved_sa) { + sigaction(signo, saved_sa, nullptr); +} + +// Raw signal handler for triggering a report - runs on an arbitrary thread +static void SignalDump(int signo) { + // Check atomic for report already pending, storing the signal number + if (__sync_val_compare_and_swap(&report_signal, 0, signo) == 0) { + uv_sem_post(&report_semaphore); // Hand-off to watchdog thread + } +} + +// Utility function to start a watchdog thread - used for processing signals +static int StartWatchdogThread(void* (*thread_main)(void* unused)) { + pthread_attr_t attr; + pthread_attr_init(&attr); + // Minimise the stack size, except on FreeBSD where the minimum is too low +#ifndef __FreeBSD__ + pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); +#endif // __FreeBSD__ + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + sigset_t sigmask; + sigfillset(&sigmask); + pthread_sigmask(SIG_SETMASK, &sigmask, &sigmask); + pthread_t thread; + const int err = pthread_create(&thread, &attr, thread_main, nullptr); + pthread_sigmask(SIG_SETMASK, &sigmask, nullptr); + pthread_attr_destroy(&attr); + if (err != 0) { + fprintf(stderr, "node-report: StartWatchdogThread pthread_create() failed: %s\n", strerror(err)); + fflush(stderr); + return -err; + } + return 0; +} + +// Watchdog thread implementation for signal-triggered report +inline void* ReportSignalThreadMain(void* unused) { + for (;;) { + uv_sem_wait(&report_semaphore); + if (nodereport_verbose) { + fprintf(stdout, "node-report: signal %s received\n", node::signo_string(report_signal)); + } + uv_mutex_lock(&node_isolate_mutex); + if (auto isolate = node_isolate) { + // Request interrupt callback for running JavaScript code + isolate->RequestInterrupt(SignalDumpInterruptCallback, nullptr); + // Event loop may be idle, so also request an async callback + uv_async_send(&nodereport_trigger_async); + } + uv_mutex_unlock(&node_isolate_mutex); + } + return nullptr; +} + +// Utility function to initialise signal handlers and threads +static void SetupSignalHandler() { + int rc = uv_sem_init(&report_semaphore, 0); + if (rc != 0) { + fprintf(stderr, "node-report: initialization failed, uv_sem_init() returned %d\n", rc); + Nan::ThrowError("node-report: initialization failed, uv_sem_init() returned error\n"); + } + rc = uv_mutex_init(&node_isolate_mutex); + if (rc != 0) { + fprintf(stderr, "node-report: initialization failed, uv_mutex_init() returned %d\n", rc); + Nan::ThrowError("node-report: initialization failed, uv_mutex_init() returned error\n"); + } + + if (StartWatchdogThread(ReportSignalThreadMain) == 0) { + rc = uv_async_init(uv_default_loop(), &nodereport_trigger_async, SignalDumpAsyncCallback); + if (rc != 0) { + fprintf(stderr, "node-report: initialization failed, uv_async_init() returned %d\n", rc); + Nan::ThrowError("node-report: initialization failed, uv_async_init() returned error\n"); + } + uv_unref(reinterpret_cast(&nodereport_trigger_async)); + RegisterSignalHandler(nodereport_signal, SignalDump, &saved_sa); + signal_thread_initialised = true; + } +} +#endif + +/******************************************************************************* + * Native module initializer function, called when the module is require'd + * + ******************************************************************************/ +void Initialize(v8::Local exports) { + v8::Isolate* isolate = Isolate::GetCurrent(); + node_isolate = isolate; + + SetLoadTime(); + SetVersionString(isolate); + SetCommandLine(); + + const char* verbose_switch = secure_getenv("NODEREPORT_VERBOSE"); + if (verbose_switch != nullptr) { + nodereport_verbose = ProcessNodeReportVerboseSwitch(verbose_switch); + } + const char* trigger_events = secure_getenv("NODEREPORT_EVENTS"); + if (trigger_events != nullptr) { + nodereport_events = ProcessNodeReportEvents(trigger_events); + } + const char* trigger_signal = secure_getenv("NODEREPORT_SIGNAL"); + if (trigger_signal != nullptr) { + nodereport_signal = ProcessNodeReportSignal(trigger_signal); + } + const char* report_name = secure_getenv("NODEREPORT_FILENAME"); + if (report_name != nullptr) { + ProcessNodeReportFileName(report_name); + } + const char* directory_name = secure_getenv("NODEREPORT_DIRECTORY"); + if (directory_name != nullptr) { + ProcessNodeReportDirectory(directory_name); + } + + // If report requested for fatalerror, set up the V8 callback + if (nodereport_events & NR_FATALERROR) { + isolate->SetFatalErrorHandler(OnFatalError); + error_hook_initialised = true; + } + + // If report requested for exceptions, tell V8 to capture stack trace and set up the callback + if (nodereport_events & NR_EXCEPTION) { + isolate->SetCaptureStackTraceForUncaughtExceptions(true, 32, v8::StackTrace::kDetailed); + // The hook for uncaught exception won't get called unless the --abort_on_uncaught_exception option is set + v8::V8::SetFlagsFromString("--abort_on_uncaught_exception", sizeof("--abort_on_uncaught_exception")-1); + isolate->SetAbortOnUncaughtExceptionCallback(OnUncaughtException); + exception_hook_initialised = true; + } + +#ifndef _WIN32 + // If report requested on external user signal set up watchdog thread and callbacks + if (nodereport_events & NR_SIGNAL) { + SetupSignalHandler(); + } +#endif + + exports->Set(Nan::New("triggerReport").ToLocalChecked(), + Nan::New(TriggerReport)->GetFunction()); + exports->Set(Nan::New("getReport").ToLocalChecked(), + Nan::New(GetReport)->GetFunction()); + exports->Set(Nan::New("setEvents").ToLocalChecked(), + Nan::New(SetEvents)->GetFunction()); + exports->Set(Nan::New("setSignal").ToLocalChecked(), + Nan::New(SetSignal)->GetFunction()); + exports->Set(Nan::New("setFileName").ToLocalChecked(), + Nan::New(SetFileName)->GetFunction()); + exports->Set(Nan::New("setDirectory").ToLocalChecked(), + Nan::New(SetDirectory)->GetFunction()); + exports->Set(Nan::New("setVerbose").ToLocalChecked(), + Nan::New(SetVerbose)->GetFunction()); + + if (nodereport_verbose) { +#ifdef _WIN32 + fprintf(stdout, "node-report: initialization complete, event flags: %#x\n", + nodereport_events); +#else + fprintf(stdout, "node-report: initialization complete, event flags: %#x signal flag: %#x\n", + nodereport_events, nodereport_signal); +#endif + } +} + +NODE_MODULE(nodereport, Initialize) + +} // namespace nodereport + diff --git a/deps/node-report/src/node_report.cc b/deps/node-report/src/node_report.cc new file mode 100644 index 00000000000000..c6e69016fed1c3 --- /dev/null +++ b/deps/node-report/src/node_report.cc @@ -0,0 +1,1029 @@ +#include "node_report.h" +#include "v8.h" +#include "uv.h" + +#include +#include +#include + +#if !defined(_MSC_VER) +#include +#endif + +#ifdef _WIN32 +#include +#include +#include +#include +#include +#include +#else +#include +// Get the standard printf format macros for C99 stdint types. +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include +#include +#include +#if defined(__linux__) || defined(__sun) +#include +#endif +#ifdef _AIX +#include // ld_info structure +#endif +// Include execinfo.h for the native backtrace API. The API is unavailable on AIX +// and on some Linux distributions, e.g. Alpine Linux. +#if !defined(_AIX) && !(defined(__linux__) && !defined(__GLIBC__)) +#include +#endif +#include +#endif + +#ifdef __APPLE__ +#include // _dyld_get_image_name() +#endif + +#ifndef _WIN32 +extern char** environ; +#endif + +namespace nodereport { + +using v8::HeapSpaceStatistics; +using v8::HeapStatistics; +using v8::Isolate; +using v8::Local; +using v8::Message; +using v8::String; +using v8::V8; + +// Internal/static function declarations +static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, MaybeLocal error, TIME_TYPE* time); +static void PrintCommandLine(std::ostream& out); +static void PrintVersionInformation(std::ostream& out); +static void PrintJavaScriptStack(std::ostream& out, Isolate* isolate, DumpEvent event, const char* location); +static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, MaybeLocal error); +static void PrintStackFromStackTrace(std::ostream& out, Isolate* isolate, DumpEvent event); +static void PrintStackFrame(std::ostream& out, Isolate* isolate, Local frame, int index, void* pc); +static void PrintNativeStack(std::ostream& out); +#ifndef _WIN32 +static void PrintResourceUsage(std::ostream& out); +#endif +static void PrintGCStatistics(std::ostream& out, Isolate* isolate); +static void PrintSystemInformation(std::ostream& out, Isolate* isolate); +static void PrintLoadedLibraries(std::ostream& out, Isolate* isolate); + +// Global variables +static int seq = 0; // sequence number for report filenames +const char* v8_states[] = {"JS", "GC", "COMPILER", "OTHER", "EXTERNAL", "IDLE"}; +static bool report_active = false; // recursion protection +char report_filename[NR_MAXNAME + 1] = ""; +char report_directory[NR_MAXPATH + 1] = ""; // defaults to current working directory +std::string version_string = UNKNOWN_NODEVERSION_STRING; +std::string commandline_string = ""; +TIME_TYPE loadtime_tm_struct; // module load time +time_t load_time; // module load time absolute + + +/******************************************************************************* + * External function to trigger a node report, writing to file. + * + * The 'name' parameter is in/out: an input filename is used if supplied, and + * the actual filename is returned. + ******************************************************************************/ +void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name, MaybeLocal error) { + // Recursion check for report in progress, bail out + if (report_active) return; + report_active = true; + + // Obtain the current time and the pid (platform dependent) + TIME_TYPE tm_struct; +#ifdef _WIN32 + GetLocalTime(&tm_struct); + DWORD pid = GetCurrentProcessId(); +#else // UNIX, OSX + struct timeval time_val; + gettimeofday(&time_val, nullptr); + localtime_r(&time_val.tv_sec, &tm_struct); + pid_t pid = getpid(); +#endif + + // Determine the required report filename. In order of priority: + // 1) supplied on API 2) configured on startup 3) default generated + char filename[NR_MAXNAME + 1] = ""; + if (name != nullptr && strlen(name) > 0) { + // Filename was specified as API parameter, use that + snprintf(filename, sizeof(filename), "%s", name); + } else if (strlen(report_filename) > 0) { + // File name was supplied via start-up option, use that + snprintf(filename, sizeof(filename), "%s", report_filename); + } else { + // Construct the report filename, with timestamp, pid and sequence number + snprintf(filename, sizeof(filename), "%s", "node-report"); + seq++; +#ifdef _WIN32 + snprintf(&filename[strlen(filename)], sizeof(filename) - strlen(filename), + ".%4d%02d%02d.%02d%02d%02d.%d.%03d.txt", + tm_struct.wYear, tm_struct.wMonth, tm_struct.wDay, + tm_struct.wHour, tm_struct.wMinute, tm_struct.wSecond, + pid, seq); +#else // UNIX, OSX + snprintf(&filename[strlen(filename)], sizeof(filename) - strlen(filename), + ".%4d%02d%02d.%02d%02d%02d.%d.%03d.txt", + tm_struct.tm_year+1900, tm_struct.tm_mon+1, tm_struct.tm_mday, + tm_struct.tm_hour, tm_struct.tm_min, tm_struct.tm_sec, + pid, seq); +#endif + } + + // Open the report file stream for writing. Supports stdout/err, user-specified or (default) generated name + std::ofstream outfile; + std::ostream* outstream = &std::cout; + if (!strncmp(filename, "stdout", sizeof("stdout") - 1)) { + outstream = &std::cout; + } else if (!strncmp(filename, "stderr", sizeof("stderr") - 1)) { + outstream = &std::cerr; + } else { + // Regular file. Append filename to directory path if one was specified + if (strlen(report_directory) > 0) { + char pathname[NR_MAXPATH + NR_MAXNAME + 1] = ""; +#ifdef _WIN32 + snprintf(pathname, sizeof(pathname), "%s%s%s", report_directory, "\\", filename); +#else + snprintf(pathname, sizeof(pathname), "%s%s%s", report_directory, "/", filename); +#endif + outfile.open(pathname, std::ios::out); + } else { + outfile.open(filename, std::ios::out); + } + // Check for errors on the file open + if (!outfile.is_open()) { + if (strlen(report_directory) > 0) { + std::cerr << "\nFailed to open Node.js report file: " << filename << " directory: " << report_directory << " (errno: " << errno << ")\n"; + } else { + std::cerr << "\nFailed to open Node.js report file: " << filename << " (errno: " << errno << ")\n"; + } + return; + } else { + std::cerr << "\nWriting Node.js report to file: " << filename << "\n"; + } + } + + // Pass our stream about by reference, not by copying it. + std::ostream &out = outfile.is_open() ? outfile : *outstream; + + WriteNodeReport(isolate, event, message, location, filename, out, error, &tm_struct); + + // Do not close stdout/stderr, only close files we opened. + if(outfile.is_open()) { + outfile.close(); + } + + std::cerr << "Node.js report completed\n"; + if (name != nullptr) { + snprintf(name, NR_MAXNAME + 1, "%s", filename); // return the report file name + } + +} + +/******************************************************************************* + * External function to trigger a node report, writing to a supplied stream. + * + *******************************************************************************/ +void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, MaybeLocal error, std::ostream& out) { + // Obtain the current time and the pid (platform dependent) + TIME_TYPE tm_struct; +#ifdef _WIN32 + GetLocalTime(&tm_struct); +#else // UNIX, OSX + struct timeval time_val; + gettimeofday(&time_val, nullptr); + localtime_r(&time_val.tv_sec, &tm_struct); +#endif + WriteNodeReport(isolate, event, message, location, nullptr, out, error, &tm_struct); +} + +/******************************************************************************* + * Internal function to coordinate and write the various sections of the node + * report to the supplied stream + *******************************************************************************/ +static void WriteNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* filename, std::ostream &out, MaybeLocal error, TIME_TYPE* tm_struct) { + +#ifdef _WIN32 + DWORD pid = GetCurrentProcessId(); +#else // UNIX, OSX + pid_t pid = getpid(); +#endif + + // Save formatting for output stream. + std::ios oldState(nullptr); + oldState.copyfmt(out); + + // File stream opened OK, now start printing the report content, starting with the title + // and header information (event, filename, timestamp and pid) + out << "================================================================================\n"; + out << "==== Node Report ===============================================================\n"; + out << "\nEvent: " << message << ", location: \"" << location << "\"\n"; + if( filename != nullptr ) { + out << "Filename: " << filename << "\n"; + } + + // Print dump event and module load date/time stamps + char timebuf[64]; +#ifdef _WIN32 + snprintf(timebuf, sizeof(timebuf), "%4d/%02d/%02d %02d:%02d:%02d", + tm_struct->wYear, tm_struct->wMonth, tm_struct->wDay, + tm_struct->wHour, tm_struct->wMinute, tm_struct->wSecond); + out << "Dump event time: "<< timebuf << "\n"; + snprintf(timebuf, sizeof(timebuf), "%4d/%02d/%02d %02d:%02d:%02d", + loadtime_tm_struct.wYear, loadtime_tm_struct.wMonth, loadtime_tm_struct.wDay, + loadtime_tm_struct.wHour, loadtime_tm_struct.wMinute, loadtime_tm_struct.wSecond); + out << "Module load time: " << timebuf << "\n"; +#else // UNIX, OSX + snprintf(timebuf, sizeof(timebuf), "%4d/%02d/%02d %02d:%02d:%02d", + tm_struct->tm_year+1900, tm_struct->tm_mon+1, tm_struct->tm_mday, + tm_struct->tm_hour, tm_struct->tm_min, tm_struct->tm_sec); + out << "Dump event time: "<< timebuf << "\n"; + snprintf(timebuf, sizeof(timebuf), "%4d/%02d/%02d %02d:%02d:%02d", + loadtime_tm_struct.tm_year+1900, loadtime_tm_struct.tm_mon+1, loadtime_tm_struct.tm_mday, + loadtime_tm_struct.tm_hour, loadtime_tm_struct.tm_min, loadtime_tm_struct.tm_sec); + out << "Module load time: " << timebuf << "\n"; +#endif + // Print native process ID + out << "Process ID: " << pid << std::endl; + + + // Print out the command line. + PrintCommandLine(out); + out << std::flush; + + // Print Node.js and OS version information + PrintVersionInformation(out); + out << std::flush; + +// Print summary JavaScript stack backtrace + PrintJavaScriptStack(out, isolate, event, location); + out << std::flush; + + // Print native stack backtrace + PrintNativeStack(out); + out << std::flush; + + // Print the stack trace and message from the Error object. + // (If one was provided.) + PrintJavaScriptErrorStack(out, isolate, error); + out << std::flush; + + // Print V8 Heap and Garbage Collector information + PrintGCStatistics(out, isolate); + out << std::flush; + + // Print OS and current thread resource usage +#ifndef _WIN32 + PrintResourceUsage(out); + out << std::flush; +#endif + + // Print libuv handle summary + out << "\n================================================================================"; + out << "\n==== Node.js libuv Handle Summary ==============================================\n"; + out << "\n(Flags: R=Ref, A=Active)\n"; + out << std::left << std::setw(7) << "Flags" << std::setw(10) << "Type" + << std::setw(4 + 2 * sizeof(void*)) << "Address" << "Details" + << std::endl; + uv_walk(uv_default_loop(), walkHandle, (void*)&out); + + // Print operating system information + PrintSystemInformation(out, isolate); + + out << "\n================================================================================\n"; + out << std::flush; + + // Restore output stream formatting. + out.copyfmt(oldState); + + report_active = false; +} + +/******************************************************************************* + * Function to print process command line. + * + ******************************************************************************/ +static void PrintCommandLine(std::ostream& out) { + if (commandline_string != "") { + out << "Command line: " << commandline_string << "\n"; + } +} + +/******************************************************************************* + * Function to print Node.js version, OS version and machine information + * + ******************************************************************************/ +static void PrintVersionInformation(std::ostream& out) { + + // Print Node.js and deps component versions + out << "\n" << version_string; + + // Print node-report module version + // e.g. node-report version: 1.0.6 (built against Node.js v6.9.1) + out << std::endl << "node-report version: " << NODEREPORT_VERSION + << " (built against Node.js v" << NODE_VERSION_STRING; +#if defined(__GLIBC__) + out << ", glibc " << __GLIBC__ << "." << __GLIBC_MINOR__; +#endif + // Print Process word size + out << ", " << sizeof(void *) * 8 << " bit" << ")" << std::endl; + + // Print operating system and machine information (Windows) +#ifdef _WIN32 + { + const DWORD level = 101; + LPSERVER_INFO_101 os_info = NULL; + NET_API_STATUS nStatus = NetServerGetInfo(NULL, level, (LPBYTE *)&os_info); + if (nStatus == NERR_Success) { + LPSTR os_name = "Windows"; + const DWORD major = os_info->sv101_version_major & MAJOR_VERSION_MASK; + const DWORD type = os_info->sv101_type; + const bool isServer = (type & SV_TYPE_DOMAIN_CTRL) || + (type & SV_TYPE_DOMAIN_BAKCTRL) || + (type & SV_TYPE_SERVER_NT); + switch (major) { + case 5: + switch (os_info->sv101_version_minor) { + case 0: + os_name = "Windows 2000"; + break; + default: + os_name = (isServer ? "Windows Server 2003" : "Windows XP"); + } + break; + case 6: + switch (os_info->sv101_version_minor) { + case 0: + os_name = (isServer ? "Windows Server 2008" : "Windows Vista"); + break; + case 1: + os_name = (isServer ? "Windows Server 2008 R2" : "Windows 7"); + break; + case 2: + os_name = (isServer ? "Windows Server 2012" : "Windows 8"); + break; + case 3: + os_name = (isServer ? "Windows Server 2012 R2" : "Windows 8.1"); + break; + default: + os_name = (isServer ? "Windows Server" : "Windows Client"); + } + break; + case 10: + os_name = (isServer ? "Windows Server 2016" : "Windows 10"); + break; + default: + os_name = (isServer ? "Windows Server" : "Windows Client"); + } + out << "\nOS version: " << os_name << "\n"; + + // Convert and print the machine name and comment fields (these are LPWSTR types) + size_t count; + char name_buf[256]; + wcstombs_s(&count, name_buf, sizeof(name_buf), os_info->sv101_name, _TRUNCATE); + if (os_info->sv101_comment != NULL) { + char comment_buf[256]; + wcstombs_s(&count, comment_buf, sizeof(comment_buf), os_info->sv101_comment, _TRUNCATE); + out << "\nMachine: " << name_buf << " " << comment_buf << "\n"; + } else { + out << "\nMachine: " << name_buf << "\n"; + } + + if (os_info != NULL) { + NetApiBufferFree(os_info); + } + } else { + // NetServerGetInfo() call failed, fallback to use GetComputerName() instead + TCHAR machine_name[256]; + DWORD machine_name_size = 256; + out << "\nOS version: Windows\n"; + if (GetComputerName(machine_name, &machine_name_size)) { + out << "\nMachine: " << machine_name << "\n"; + } + } + } +#else + // Print operating system and machine information (Unix/OSX) + struct utsname os_info; + if (uname(&os_info) >= 0) { +#if defined(_AIX) + out << "\nOS version: " << os_info.sysname << " " << os_info.version << "." + << os_info.release << "\n"; +#else + out << "\nOS version: " << os_info.sysname << " " << os_info.release << " " + << os_info.version << "\n"; +#endif + const char *(*libc_version)(); + *(void**)(&libc_version) = dlsym(RTLD_DEFAULT, "gnu_get_libc_version"); + if (libc_version != NULL) { + out << "(glibc: " << (*libc_version)() << ")" << std::endl; + } + out << "\nMachine: " << os_info.nodename << " " << os_info.machine << "\n"; + } +#endif +} + +/******************************************************************************* + * Function to print the JavaScript stack, if available + * + ******************************************************************************/ +static void PrintJavaScriptStack(std::ostream& out, Isolate* isolate, DumpEvent event, const char* location) { + out << "\n================================================================================"; + out << "\n==== JavaScript Stack Trace ====================================================\n\n"; + +#ifdef _WIN32 + switch (event) { + case kFatalError: + // Stack trace on fatal error not supported on Windows + out << "No stack trace available\n"; + break; + default: + // All other events, print the stack using StackTrace::StackTrace() and GetStackSample() APIs + PrintStackFromStackTrace(out, isolate, event); + break; + } // end switch(event) +#else // Unix, OSX + switch (event) { + case kException: + case kJavaScript: { + // Print the stack using Message::PrintCurrentStackTrace() API + std::FILE *stack_fp = std::tmpfile(); + if (stack_fp != nullptr) { + char stack_buf[64]; + Message::PrintCurrentStackTrace(isolate, stack_fp); + std::fflush(stack_fp); + std::rewind(stack_fp); + while (std::fgets(stack_buf, sizeof(stack_buf), stack_fp) != nullptr) { + out << stack_buf; + } + // Calling close on a file from tmpfile *should* delete it. + std::fclose(stack_fp); + } else { + out << "No stack trace available, unable to create temporary file\n"; + } + break; + } + case kFatalError: + out << "No stack trace available\n"; + break; + case kSignal_JS: + case kSignal_UV: + // Print the stack using StackTrace::StackTrace() and GetStackSample() APIs + PrintStackFromStackTrace(out, isolate, event); + break; + } // end switch(event) +#endif +} + +/******************************************************************************* + * Function to print a JavaScript stack from an error object + * + ******************************************************************************/ +static void PrintJavaScriptErrorStack(std::ostream& out, Isolate* isolate, MaybeLocal error) { + if (error.IsEmpty() || !error.ToLocalChecked()->IsNativeError()) { + return; + } + + out << "\n================================================================================"; + out << "\n==== JavaScript Exception Details ==============================================\n\n"; +#if NODE_MAJOR_VERSION > 5 + Local message = v8::Exception::CreateMessage(isolate, error.ToLocalChecked()); +#else + Local message = v8::Exception::CreateMessage(error.ToLocalChecked()); +#endif + Nan::Utf8String message_str(message->Get()); + + out << *message_str << "\n\n"; + + Local stack = v8::Exception::GetStackTrace(error.ToLocalChecked()); + if (stack.IsEmpty()) { + out << "No stack trace available from Exception::GetStackTrace()\n"; + return; + } + // Print the stack trace, samples are not available as the exception isn't from the current stack. + for (int i = 0; i < stack->GetFrameCount(); i++) { + PrintStackFrame(out, isolate, stack->GetFrame(i), i, nullptr); + } +} + +/******************************************************************************* + * Function to print stack using GetStackSample() and StackTrace::StackTrace() + * + ******************************************************************************/ +static void PrintStackFromStackTrace(std::ostream& out, Isolate* isolate, DumpEvent event) { + v8::RegisterState state; + v8::SampleInfo info; + void* samples[255]; + + // Initialise the register state + state.pc = nullptr; + state.fp = &state; + state.sp = &state; + + isolate->GetStackSample(state, samples, arraysize(samples), &info); + if (static_cast(info.vm_state) < arraysize(v8_states)) { + out << "JavaScript VM state: " << v8_states[info.vm_state] << "\n\n"; + } else { + out << "JavaScript VM state: \n\n"; + } + if (event == kSignal_UV) { + out << "Signal received when event loop idle, no stack trace available\n"; + return; + } + Local stack = StackTrace::CurrentStackTrace(isolate, 255, StackTrace::kDetailed); + if (stack.IsEmpty()) { + out << "\nNo stack trace available from StackTrace::CurrentStackTrace()\n"; + return; + } + // Print the stack trace, adding in the pc values from GetStackSample() if available + for (int i = 0; i < stack->GetFrameCount(); i++) { + if (static_cast(i) < info.frames_count) { + PrintStackFrame(out, isolate, stack->GetFrame(i), i, samples[i]); + } else { + PrintStackFrame(out, isolate, stack->GetFrame(i), i, nullptr); + } + } +} + +/******************************************************************************* + * Function to print a JavaScript stack frame from a V8 StackFrame object + * + ******************************************************************************/ +static void PrintStackFrame(std::ostream& out, Isolate* isolate, Local frame, int i, void* pc) { + Nan::Utf8String fn_name_s(frame->GetFunctionName()); + Nan::Utf8String script_name(frame->GetScriptName()); + const int line_number = frame->GetLineNumber(); + const int column = frame->GetColumn(); + char buf[64]; + + // First print the frame index and the instruction address + if (pc != nullptr) { +#ifdef _WIN32 + snprintf( buf, sizeof(buf), "%2d: [pc=0x%p] ", i, pc); +#else + snprintf( buf, sizeof(buf), "%2d: [pc=%p] ", i, pc); +#endif + out << buf; + } + + // Now print the JavaScript function name and source information + if (frame->IsEval()) { + if (frame->GetScriptId() == Message::kNoScriptIdInfo) { + out << "at [eval]:" << line_number << ":" << column << "\n"; + } else { + out << "at [eval] (" << *script_name << ":" << line_number << ":" + << column << ")\n"; + } + return; + } + + if (fn_name_s.length() == 0) { + out << *script_name << ":" << line_number << ":" << column << "\n"; + } else { + if (frame->IsConstructor()) { + out << *fn_name_s << " [constructor] (" << *script_name << ":" + << line_number << ":" << column << ")\n"; + } else { + out << *fn_name_s << " (" << *script_name << ":" << line_number << ":" + << column << ")\n"; + } + } +} + + +#ifdef _WIN32 +/******************************************************************************* + * Function to print a native stack backtrace + * + ******************************************************************************/ +void PrintNativeStack(std::ostream& out) { + void* frames[64]; + out << "\n================================================================================"; + out << "\n==== Native Stack Trace ========================================================\n\n"; + + HANDLE hProcess = GetCurrentProcess(); + SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + SymInitialize(hProcess, nullptr, TRUE); + char buf[64]; + + WORD numberOfFrames = CaptureStackBackTrace(2, 64, frames, nullptr); + + // Walk the frames printing symbolic information if available + for (int i = 0; i < numberOfFrames; i++) { + DWORD64 dwOffset64 = 0; + DWORD64 dwAddress = reinterpret_cast(frames[i]); + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = reinterpret_cast(buffer); + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + pSymbol->MaxNameLen = MAX_SYM_NAME; + + if (SymFromAddr(hProcess, dwAddress, &dwOffset64, pSymbol)) { + DWORD dwOffset = 0; + IMAGEHLP_LINE64 line; + line.SizeOfStruct = sizeof(line); + snprintf(buf, sizeof(buf), "%2d: [pc=0x%p]", i, reinterpret_cast(pSymbol->Address)); + out << buf << " " << pSymbol->Name << " [+"; + if (SymGetLineFromAddr64(hProcess, dwAddress, &dwOffset, &line)) { + out << dwOffset << "] in " << line.FileName << ": line: " << line.LineNumber << "\n"; + } else { + out << dwOffset64 << "]\n"; + } + } else { // SymFromAddr() failed, just print the address + snprintf(buf, sizeof(buf), "%2d: [pc=0x%p]\n", i, reinterpret_cast(dwAddress)); + out << buf; + } + } +} +#elif _AIX +/******************************************************************************* + * Function to print a native stack backtrace - AIX + * + ******************************************************************************/ +void PrintNativeStack(std::ostream& out) { + out << "\n================================================================================"; + out << "\n==== Native Stack Trace ========================================================\n\n"; + out << "Native stack trace not supported on AIX\n"; +} +#elif (defined(__linux__) && !defined(__GLIBC__)) +/******************************************************************************* + * Function to print a native stack backtrace - Alpine Linux etc + * + ******************************************************************************/ +void PrintNativeStack(std::ostream& out) { + out << "\n================================================================================"; + out << "\n==== Native Stack Trace ========================================================\n\n"; + out << "Native stack trace not supported on Linux platforms without GLIBC\n"; +} +#else +/******************************************************************************* + * Function to print a native stack backtrace - Linux/OSX + * + ******************************************************************************/ +void PrintNativeStack(std::ostream& out) { + void* frames[256]; + char buf[64]; + out << "\n================================================================================"; + out << "\n==== Native Stack Trace ========================================================\n\n"; + + // Get the native backtrace (array of instruction addresses) + const int size = backtrace(frames, arraysize(frames)); + if (size <= 0) { + out << "Native backtrace failed, error " << size << "\n"; + return; + } else if (size <=2) { + out << "No frames to print\n"; + return; + } + + // Print the native frames, omitting the top 3 frames as they are in node-report code + // backtrace_symbols_fd(frames, size, fileno(fp)); + for (int i = 2; i < size; i++) { + // print frame index and instruction address + snprintf(buf, sizeof(buf), "%2d: [pc=%p] ", i-2, frames[i]); + out << buf; + // If we can translate the address using dladdr() print additional symbolic information + Dl_info info; + if (dladdr(frames[i], &info)) { + if (info.dli_sname != nullptr) { + if (char* demangled = abi::__cxa_demangle(info.dli_sname, 0, 0, 0)) { + out << demangled; // print demangled symbol name + free(demangled); + } else { + out << info.dli_sname; // just print the symbol name + } + } + if (info.dli_fname != nullptr) { + out << " [" << info.dli_fname << "]"; // print shared object name + } + } + out << std::endl; + } +} +#endif + +/******************************************************************************* + * Function to print V8 JavaScript heap information. + * + * This uses the existing V8 HeapStatistics and HeapSpaceStatistics APIs. + * The isolate->GetGCStatistics(&heap_stats) internal V8 API could potentially + * provide some more useful information - the GC history and the handle counts + ******************************************************************************/ +static void PrintGCStatistics(std::ostream& out, Isolate* isolate) { + HeapStatistics v8_heap_stats; + isolate->GetHeapStatistics(&v8_heap_stats); + + out << "\n================================================================================"; + out << "\n==== JavaScript Heap and Garbage Collector =====================================\n"; + HeapSpaceStatistics v8_heap_space_stats; + // Loop through heap spaces + for (size_t i = 0; i < isolate->NumberOfHeapSpaces(); i++) { + isolate->GetHeapSpaceStatistics(&v8_heap_space_stats, i); + out << "\nHeap space name: " << v8_heap_space_stats.space_name(); + out << "\n Memory size: "; + WriteInteger(out, v8_heap_space_stats.space_size()); + out << " bytes, committed memory: "; + WriteInteger(out, v8_heap_space_stats.physical_space_size()); + out << " bytes\n Capacity: "; + WriteInteger(out, v8_heap_space_stats.space_used_size() + + v8_heap_space_stats.space_available_size()); + out << " bytes, used: "; + WriteInteger(out, v8_heap_space_stats.space_used_size()); + out << " bytes, available: "; + WriteInteger(out, v8_heap_space_stats.space_available_size()); + out << " bytes"; + } + + out << "\n\nTotal heap memory size: "; + WriteInteger(out, v8_heap_stats.total_heap_size()); + out << " bytes\nTotal heap committed memory: "; + WriteInteger(out, v8_heap_stats.total_physical_size()); + out << " bytes\nTotal used heap memory: "; + WriteInteger(out, v8_heap_stats.used_heap_size()); + out << " bytes\nTotal available heap memory: "; + WriteInteger(out, v8_heap_stats.total_available_size()); + out << " bytes\n\nHeap memory limit: "; + WriteInteger(out, v8_heap_stats.heap_size_limit()); + out << "\n"; +} + +#ifndef _WIN32 +/******************************************************************************* + * Function to print resource usage (Linux/OSX only). + * + ******************************************************************************/ +static void PrintResourceUsage(std::ostream& out) { + char buf[64]; + double cpu_abs; + double cpu_percentage; + time_t current_time; // current time absolute + time(¤t_time); + auto uptime = difftime(current_time, load_time); + if (uptime == 0) + uptime = 1; // avoid division by zero. + out << "\n================================================================================"; + out << "\n==== Resource Usage ============================================================\n"; + + // Process and current thread usage statistics + struct rusage stats; + out << "\nProcess total resource usage:"; + if (getrusage(RUSAGE_SELF, &stats) == 0) { +#if defined(__APPLE__) || defined(_AIX) + snprintf( buf, sizeof(buf), "%ld.%06d", stats.ru_utime.tv_sec, stats.ru_utime.tv_usec); + out << "\n User mode CPU: " << buf << " secs"; + snprintf( buf, sizeof(buf), "%ld.%06d", stats.ru_stime.tv_sec, stats.ru_stime.tv_usec); + out << "\n Kernel mode CPU: " << buf << " secs"; +#else + snprintf( buf, sizeof(buf), "%ld.%06ld", stats.ru_utime.tv_sec, stats.ru_utime.tv_usec); + out << "\n User mode CPU: " << buf << " secs"; + snprintf( buf, sizeof(buf), "%ld.%06ld", stats.ru_stime.tv_sec, stats.ru_stime.tv_usec); + out << "\n Kernel mode CPU: " << buf << " secs"; +#endif + cpu_abs = stats.ru_utime.tv_sec + 0.000001 * stats.ru_utime.tv_usec + stats.ru_stime.tv_sec + 0.000001 * stats.ru_stime.tv_usec; + cpu_percentage = (cpu_abs / uptime) * 100.0; + out << "\n Average CPU Consumption : "<< cpu_percentage << "%"; + out << "\n Maximum resident set size: "; + WriteInteger(out, stats.ru_maxrss * 1024); + out << " bytes\n Page faults: " << stats.ru_majflt << " (I/O required) " + << stats.ru_minflt << " (no I/O required)"; + out << "\n Filesystem activity: " << stats.ru_inblock << " reads " + << stats.ru_oublock << " writes"; + } +#ifdef RUSAGE_THREAD + out << "\n\nEvent loop thread resource usage:"; + if (getrusage(RUSAGE_THREAD, &stats) == 0) { +#if defined(__APPLE__) || defined(_AIX) + snprintf( buf, sizeof(buf), "%ld.%06d", stats.ru_utime.tv_sec, stats.ru_utime.tv_usec); + out << "\n User mode CPU: " << buf << " secs"; + snprintf( buf, sizeof(buf), "%ld.%06d", stats.ru_stime.tv_sec, stats.ru_stime.tv_usec); + out << "\n Kernel mode CPU: " << buf << " secs"; +#else + snprintf( buf, sizeof(buf), "%ld.%06ld", stats.ru_utime.tv_sec, stats.ru_utime.tv_usec); + out << "\n User mode CPU: " << buf << " secs"; + snprintf( buf, sizeof(buf), "%ld.%06ld", stats.ru_stime.tv_sec, stats.ru_stime.tv_usec); + out << "\n Kernel mode CPU: " << buf << " secs"; +#endif + cpu_abs = stats.ru_utime.tv_sec + 0.000001 * stats.ru_utime.tv_usec + stats.ru_stime.tv_sec + 0.000001 * stats.ru_stime.tv_usec; + cpu_percentage = (cpu_abs / uptime) * 100.0; + out << "\n Average CPU Consumption : " << cpu_percentage << "%"; + out << "\n Filesystem activity: " << stats.ru_inblock << " reads " + << stats.ru_oublock << " writes"; + } +#endif + out << std::endl; +} +#endif + +/******************************************************************************* + * Function to print operating system information. + * + ******************************************************************************/ +static void PrintSystemInformation(std::ostream& out, Isolate* isolate) { + out << "\n================================================================================"; + out << "\n==== System Information ========================================================\n"; + +#ifdef _WIN32 + out << "\nEnvironment variables\n"; + LPTSTR lpszVariable; + LPTCH lpvEnv; + + // Get pointer to the environment block + lpvEnv = GetEnvironmentStrings(); + if (lpvEnv != nullptr) { + // Variable strings are separated by null bytes, and the block is terminated by a null byte. + lpszVariable = reinterpret_cast(lpvEnv); + while (*lpszVariable) { + out << " " << lpszVariable << "\n", lpszVariable; + lpszVariable += lstrlen(lpszVariable) + 1; + } + FreeEnvironmentStrings(lpvEnv); + } +#else + out << "\nEnvironment variables\n"; + int index = 1; + char* env_var = *environ; + + while (env_var != nullptr) { + out << " " << env_var << "\n"; + env_var = *(environ + index++); + } + +const static struct { + const char* description; + int id; +} rlimit_strings[] = { + {"core file size (blocks) ", RLIMIT_CORE}, + {"data seg size (kbytes) ", RLIMIT_DATA}, + {"file size (blocks) ", RLIMIT_FSIZE}, +#if !(defined(_AIX) || defined(__sun)) + {"max locked memory (bytes) ", RLIMIT_MEMLOCK}, +#endif +#ifndef __sun + {"max memory size (kbytes) ", RLIMIT_RSS}, +#endif + {"open files ", RLIMIT_NOFILE}, + {"stack size (bytes) ", RLIMIT_STACK}, + {"cpu time (seconds) ", RLIMIT_CPU}, +#ifndef __sun + {"max user processes ", RLIMIT_NPROC}, +#endif + {"virtual memory (kbytes) ", RLIMIT_AS} +}; + + out << "\nResource limits soft limit hard limit\n"; + struct rlimit limit; + char buf[64]; + + for (size_t i = 0; i < arraysize(rlimit_strings); i++) { + if (getrlimit(rlimit_strings[i].id, &limit) == 0) { + out << " " << rlimit_strings[i].description << " "; + if (limit.rlim_cur == RLIM_INFINITY) { + out << " unlimited"; + } else { +#if defined(_AIX) || defined(__sun) + snprintf(buf, sizeof(buf), "%16ld", limit.rlim_cur); + out << buf; +#elif (defined(__linux__) && !defined(__GLIBC__)) + snprintf(buf, sizeof(buf), "%16lld", limit.rlim_cur); + out << buf; +#else + snprintf(buf, sizeof(buf), "%16" PRIu64, limit.rlim_cur); + out << buf; +#endif + } + if (limit.rlim_max == RLIM_INFINITY) { + out << " unlimited\n"; + } else { +#if defined(_AIX) + snprintf(buf, sizeof(buf), "%16ld\n", limit.rlim_max); + out << buf; +#elif (defined(__linux__) && !defined(__GLIBC__)) + snprintf(buf, sizeof(buf), "%16lld\n", limit.rlim_max); + out << buf; +#else + snprintf(buf, sizeof(buf), "%16" PRIu64 "\n", limit.rlim_max); + out << buf; +#endif + } + } + } +#endif + + out << "\nLoaded libraries\n"; + PrintLoadedLibraries(out, isolate); +} + +/******************************************************************************* + * Functions to print a list of loaded native libraries. + * + ******************************************************************************/ +#ifdef __linux__ +static int LibraryPrintCallback(struct dl_phdr_info *info, size_t size, void *data) { + std::ostream* out = reinterpret_cast(data); + if (info->dlpi_name != nullptr && *info->dlpi_name != '\0') { + *out << " " << info->dlpi_name << "\n"; + } + return 0; +} +#endif + +static void PrintLoadedLibraries(std::ostream& out, Isolate* isolate) { +#ifdef __linux__ + dl_iterate_phdr(LibraryPrintCallback, &out); +#elif __APPLE__ + int i = 0; + const char *name = _dyld_get_image_name(i); + while (name != nullptr) { + out << " " << name << "\n"; + i++; + name = _dyld_get_image_name(i); + } +#elif _AIX + // We can't tell in advance how large the buffer needs to be. + // Retry until we reach too large a size (1Mb). + const unsigned int buffer_inc = 4096; + unsigned int buffer_size = buffer_inc; + char* buffer = (char*) malloc(buffer_size); + int rc = -1; + while (buffer != nullptr && rc != 0 && buffer_size < 1024 * 1024) { + rc = loadquery(L_GETINFO, buffer, buffer_size); + if (rc == 0) { + break; + } + free(buffer); + buffer_size += buffer_inc; + buffer = (char*) malloc(buffer_size); + } + if (buffer == nullptr) { + return; // Don't try to free the buffer. + } + if (rc == 0) { + char* buf = buffer; + ld_info* cur_info = nullptr; + do { + cur_info = (ld_info*) buf; + char* member_name = cur_info->ldinfo_filename + + strlen(cur_info->ldinfo_filename) + 1; + if (*member_name != '\0') { + out << " " << cur_info->ldinfo_filename << "(" << member_name << ")\n"; + } else { + out << " " << cur_info->ldinfo_filename << "\n"; + } + buf += cur_info->ldinfo_next; + } while (cur_info->ldinfo_next != 0); + } + free(buffer); +#elif __sun + Link_map *p; + + if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &p) != -1) { + for (Link_map *l = p; l != NULL; l = l->l_next) { + out << " " << l->l_name << "\n"; + } + } + +#elif _WIN32 + // Windows implementation - get a handle to the process. + HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, GetCurrentProcessId()); + if (process_handle == NULL) { + out << "No library information available\n"; + return; + } + // Get a list of all the modules in this process + DWORD size_1 = 0, size_2 = 0; + // First call to get the size of module array needed + if (EnumProcessModules(process_handle, NULL, 0, &size_1)) { + HMODULE* modules = (HMODULE*) malloc(size_1); + if (modules == NULL) { + return; // bail out if malloc failed + } + // Second call to populate the module array + if (EnumProcessModules(process_handle, modules, size_1, &size_2)) { + for (int i = 0; + i < (size_1 / sizeof(HMODULE)) && i < (size_2 / sizeof(HMODULE)); + i++) { + TCHAR module_name[MAX_PATH]; + // Obtain and print the full pathname for each module + if (GetModuleFileNameEx(process_handle, modules[i], module_name, + sizeof(module_name) / sizeof(TCHAR))) { + out << " " << module_name << "\n"; + } + } + } + free(modules); + } else { + out << "No library information available\n"; + } + // Release the handle to the process. + CloseHandle(process_handle); +#endif +} + +} // namespace nodereport diff --git a/deps/node-report/src/node_report.h b/deps/node-report/src/node_report.h new file mode 100644 index 00000000000000..d5f66e06924f89 --- /dev/null +++ b/deps/node-report/src/node_report.h @@ -0,0 +1,118 @@ +#ifndef SRC_NODE_REPORT_H_ +#define SRC_NODE_REPORT_H_ + +#include "nan.h" + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif + +namespace nodereport { + +using v8::Isolate; +using v8::Local; +using v8::Message; +using v8::Function; +using v8::Object; +using v8::Number; +using v8::String; +using v8::Value; +using v8::StackTrace; +using v8::StackFrame; +using v8::MaybeLocal; + +// Bit-flags for node-report trigger options +#define NR_EXCEPTION 0x01 +#define NR_FATALERROR 0x02 +#define NR_SIGNAL 0x04 +#define NR_APICALL 0x08 + +// Maximum file and path name lengths +#define NR_MAXNAME 64 +#define NR_MAXPATH 1024 + +enum DumpEvent {kException, kFatalError, kSignal_JS, kSignal_UV, kJavaScript}; + +#ifdef _WIN32 +typedef SYSTEMTIME TIME_TYPE; +#else // UNIX, OSX +typedef struct tm TIME_TYPE; +#endif + +// NODEREPORT_VERSION is defined in binding.gyp +#if !defined(NODEREPORT_VERSION) +#define NODEREPORT_VERSION "dev" +#endif +#define UNKNOWN_NODEVERSION_STRING "Unable to determine Node.js version\n" + +// Function declarations - functions in src/node_report.cc +void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name, v8::MaybeLocal error); +void GetNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, v8::MaybeLocal error, std::ostream& out); + +// Function declarations - utility functions in src/utilities.cc +unsigned int ProcessNodeReportEvents(const char* args); +unsigned int ProcessNodeReportSignal(const char* args); +void ProcessNodeReportFileName(const char* args); +void ProcessNodeReportDirectory(const char* args); +unsigned int ProcessNodeReportVerboseSwitch(const char* args); +void SetLoadTime(); +void SetVersionString(Isolate* isolate); +void SetCommandLine(); +void reportEndpoints(uv_handle_t* h, std::ostringstream& out); +void reportPath(uv_handle_t* h, std::ostringstream& out); +void walkHandle(uv_handle_t* h, void* arg); +void WriteInteger(std::ostream& out, size_t value); + +// Global variable declarations - definitions are in src/node-report.c +extern char report_filename[NR_MAXNAME + 1]; +extern char report_directory[NR_MAXPATH + 1]; +extern std::string version_string; +extern std::string commandline_string; +extern TIME_TYPE loadtime_tm_struct; +extern time_t load_time; + +// Local implementation of secure_getenv() +inline const char* secure_getenv(const char* key) { +#ifndef _WIN32 + if (getuid() != geteuid() || getgid() != getegid()) + return nullptr; +#endif + return getenv(key); +} + +// Emulate arraysize() on Windows pre Visual Studio 2015 +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define arraysize(a) (sizeof(a) / sizeof(*a)) +#else +template +constexpr size_t arraysize(const T(&)[N]) { return N; } +#endif // defined( _MSC_VER ) && (_MSC_VER < 1900) + +// Emulate snprintf() on Windows pre Visual Studio 2015 +#if defined( _MSC_VER ) && (_MSC_VER < 1900) +#include +inline static int snprintf(char* buffer, size_t n, const char* format, ...) { + va_list argp; + va_start(argp, format); + int ret = _vscprintf(format, argp); + vsnprintf_s(buffer, n, _TRUNCATE, format, argp); + va_end(argp); + return ret; +} + +#define __func__ __FUNCTION__ +#endif // defined( _MSC_VER ) && (_MSC_VER < 1900) + +} // namespace nodereport + +#endif // SRC_NODE_REPORT_H_ diff --git a/deps/node-report/src/utilities.cc b/deps/node-report/src/utilities.cc new file mode 100644 index 00000000000000..5d8397926bf904 --- /dev/null +++ b/deps/node-report/src/utilities.cc @@ -0,0 +1,553 @@ +#include "node_report.h" + +#ifdef __APPLE__ +#include // _NSGetArgv() and _NSGetArgc() +#endif +#ifdef __sun +#include // psinfo_t structure +#endif +#ifdef _AIX +#include // psinfo_t structure +#endif + +namespace nodereport { + +/******************************************************************************* + * Function to process node-report config: selection of trigger events. + ******************************************************************************/ +unsigned int ProcessNodeReportEvents(const char* args) { + // Parse the supplied event types + unsigned int event_flags = 0; + const char* cursor = args; + while (*cursor != '\0') { + if (!strncmp(cursor, "exception", sizeof("exception") - 1)) { + event_flags |= NR_EXCEPTION; + cursor += sizeof("exception") - 1; + } else if (!strncmp(cursor, "fatalerror", sizeof("fatalerror") - 1)) { + event_flags |= NR_FATALERROR; + cursor += sizeof("fatalerror") - 1; + } else if (!strncmp(cursor, "signal", sizeof("signal") - 1)) { + event_flags |= NR_SIGNAL; + cursor += sizeof("signal") - 1; + } else if (!strncmp(cursor, "apicall", sizeof("apicall") - 1)) { + event_flags |= NR_APICALL; + cursor += sizeof("apicall") - 1; + } else { + std::cerr << "Unrecognised argument for node-report events option: " << cursor << "\n"; + return 0; + } + if (*cursor == '+') { + cursor++; // Hop over the '+' separator + } + } + return event_flags; +} + +/******************************************************************************* + * Function to process node-report config: selection of trigger signal. + ******************************************************************************/ +unsigned int ProcessNodeReportSignal(const char* args) { +#ifdef _WIN32 + return 0; // no-op on Windows +#else + if (strlen(args) == 0) { + std::cerr << "Missing argument for node-report signal option\n"; + } else { + // Parse the supplied switch + if (!strncmp(args, "SIGUSR2", sizeof("SIGUSR2") - 1)) { + return SIGUSR2; + } else if (!strncmp(args, "SIGQUIT", sizeof("SIGQUIT") - 1)) { + return SIGQUIT; + } else { + std::cerr << "Unrecognised argument for node-report signal option: "<< args << "\n"; + } + } + return SIGUSR2; // Default signal is SIGUSR2 +#endif +} + +/******************************************************************************* + * Function to process node-report config: specification of report file name. + ******************************************************************************/ +void ProcessNodeReportFileName(const char* args) { + if (strlen(args) == 0) { + std::cerr << "Missing argument for node-report filename option\n"; + return; + } + if (strlen(args) > NR_MAXNAME) { + std::cerr << "Supplied node-report filename too long (max " << NR_MAXNAME << " characters)\n"; + return; + } + snprintf(report_filename, sizeof(report_filename), "%s", args); +} + +/******************************************************************************* + * Function to process node-report config: specification of report directory. + ******************************************************************************/ +void ProcessNodeReportDirectory(const char* args) { + if (strlen(args) == 0) { + std::cerr << "Missing argument for node-report directory option\n"; + return; + } + if (strlen(args) > NR_MAXPATH) { + std::cerr << "Supplied node-report directory path too long (max " << NR_MAXPATH << " characters)\n"; + return; + } + snprintf(report_directory, sizeof(report_directory), "%s", args); +} + +/******************************************************************************* + * Function to process node-report config: verbose mode switch. + ******************************************************************************/ +unsigned int ProcessNodeReportVerboseSwitch(const char* args) { + if (strlen(args) == 0) { + std::cerr << "Missing argument for node-report verbose switch option\n"; + return 0; + } + // Parse the supplied switch + if (!strncmp(args, "yes", sizeof("yes") - 1) || !strncmp(args, "true", sizeof("true") - 1)) { + return 1; + } else if (!strncmp(args, "no", sizeof("no") - 1) || !strncmp(args, "false", sizeof("false") - 1)) { + return 0; + } else { + std::cerr << "Unrecognised argument for node-report verbose switch option: " << args << "\n"; + } + return 0; // Default is verbose mode off +} + +/******************************************************************************* + * Function to save the node and subcomponent version strings. This is called + * during node-report module initialisation. + *******************************************************************************/ +void SetVersionString(Isolate* isolate) { + // Catch anything thrown and gracefully return + Nan::TryCatch trycatch; + version_string = UNKNOWN_NODEVERSION_STRING; + + // Retrieve the process object + v8::Local process_prop; + if (!Nan::New("process").ToLocal(&process_prop)) return; + v8::Local global_obj = isolate->GetCurrentContext()->Global(); + v8::Local process_value; + if (!Nan::Get(global_obj, process_prop).ToLocal(&process_value)) return; + if (!process_value->IsObject()) return; + v8::Local process_obj = process_value.As(); + + // Get process.version + v8::Local version_prop; + if (!Nan::New("version").ToLocal(&version_prop)) return; + v8::Local version; + if (!Nan::Get(process_obj, version_prop).ToLocal(&version)) return; + + // e.g. Node.js version: v6.9.1 + if (version->IsString()) { + Nan::Utf8String node_version(version); + version_string = "Node.js version: "; + version_string += *node_version; + version_string += "\n"; + } + + // Get process.versions + v8::Local versions_prop; + if (!Nan::New("versions").ToLocal(&versions_prop)) return; + v8::Local versions_value; + if (!Nan::Get(process_obj, versions_prop).ToLocal(&versions_value)) return; + if (!versions_value->IsObject()) return; + v8::Local versions_obj = versions_value.As(); + + // Get component names and versions from process.versions + v8::Local components; + if (!Nan::GetOwnPropertyNames(versions_obj).ToLocal(&components)) return; + v8::Local components_obj = components.As(); + std::string comp_versions = "("; + size_t wrap = 0; + uint32_t total_components = (*components)->Length(); + for (uint32_t i = 0; i < total_components; i++) { + v8::Local name_value; + if (!Nan::Get(components_obj, i).ToLocal(&name_value)) continue; + v8::Local version_value; + if (!Nan::Get(versions_obj, name_value).ToLocal(&version_value)) continue; + + Nan::Utf8String component_name(name_value); + Nan::Utf8String component_version(version_value); + if (*component_name == nullptr || *component_version == nullptr) continue; + + if (!strcmp("node", *component_name)) { + // Put the Node.js version on the first line, if we didn't already have it + if (version_string == UNKNOWN_NODEVERSION_STRING) { + version_string = "Node.js version: v"; + version_string += *component_version; + version_string += "\n"; + } + } else { + // Other component versions follow, comma separated, wrapped at 80 characters + std::string comp_version_string = *component_name; + comp_version_string += ": "; + comp_version_string += *component_version; + if (wrap == 0) { + wrap = comp_version_string.length(); + } else { + wrap += comp_version_string.length() + 2; // includes separator + if (wrap > 80) { + comp_versions += ",\n "; + wrap = comp_version_string.length(); + } else { + comp_versions += ", "; + } + } + comp_versions += comp_version_string; + } + } + version_string += comp_versions + ")\n"; +} + +/******************************************************************************* + * Function to save the node-report module load time value. This is called + * during node-report module initialisation. + *******************************************************************************/ +void SetLoadTime() { +#ifdef _WIN32 + GetLocalTime(&loadtime_tm_struct); +#else // UNIX, OSX + struct timeval time_val; + gettimeofday(&time_val, nullptr); + localtime_r(&time_val.tv_sec, &loadtime_tm_struct); +#endif + time(&load_time); +} + +/******************************************************************************* + * Function to save the process command line. This is called during node-report + * module initialisation. + *******************************************************************************/ +void SetCommandLine() { +#ifdef __linux__ + // Read the command line from /proc/self/cmdline + char buf[64]; + FILE* cmdline_fd = fopen("/proc/self/cmdline", "r"); + if (cmdline_fd == nullptr) { + return; + } + commandline_string = ""; + int bytesread = fread(buf, 1, sizeof(buf), cmdline_fd); + while (bytesread > 0) { + for (int i = 0; i < bytesread; i++) { + // Arguments are null separated. + if (buf[i] == '\0') { + commandline_string += " "; + } else { + commandline_string += buf[i]; + } + } + bytesread = fread(buf, 1, sizeof(buf), cmdline_fd); + } + fclose(cmdline_fd); +#elif __APPLE__ + char **argv = *_NSGetArgv(); + int argc = *_NSGetArgc(); + + commandline_string = ""; + std::string separator = ""; + for (int i = 0; i < argc; i++) { + commandline_string += separator + argv[i]; + separator = " "; + } +#elif defined(_AIX) || defined(__sun) + // Read the command line from /proc/self/cmdline + char procbuf[64]; + snprintf(procbuf, sizeof(procbuf), "/proc/%d/psinfo", getpid()); + FILE* psinfo_fd = fopen(procbuf, "r"); + if (psinfo_fd == nullptr) { + return; + } + psinfo_t info; + int bytesread = fread(&info, 1, sizeof(psinfo_t), psinfo_fd); + fclose(psinfo_fd); + if (bytesread == sizeof(psinfo_t)) { + commandline_string = ""; + std::string separator = ""; +#ifdef _AIX + char **argv = *((char ***) info.pr_argv); +#else + char **argv = ((char **) info.pr_argv); +#endif + for (uint32_t i = 0; i < info.pr_argc && argv[i] != nullptr; i++) { + commandline_string += separator + argv[i]; + separator = " "; + } + } +#elif _WIN32 + commandline_string = GetCommandLine(); +#endif +} + +/******************************************************************************* + * Utility function to format libuv socket information. + *******************************************************************************/ +void reportEndpoints(uv_handle_t* h, std::ostringstream& out) { + struct sockaddr_storage addr_storage; + struct sockaddr* addr = (sockaddr*)&addr_storage; + char hostbuf[NI_MAXHOST]; + char portbuf[NI_MAXSERV]; + uv_any_handle* handle = (uv_any_handle*)h; + int addr_size = sizeof(addr_storage); + int rc = -1; + + switch (h->type) { + case UV_UDP: { + rc = uv_udp_getsockname(&(handle->udp), addr, &addr_size); + break; + } + case UV_TCP: { + rc = uv_tcp_getsockname(&(handle->tcp), addr, &addr_size); + break; + } + default: break; + } + if (rc == 0) { + // getnameinfo will format host and port and handle IPv4/IPv6. + rc = getnameinfo(addr, addr_size, hostbuf, sizeof(hostbuf), portbuf, + sizeof(portbuf), NI_NUMERICSERV); + if (rc == 0) { + out << std::string(hostbuf) << ":" << std::string(portbuf); + } + + if (h->type == UV_TCP) { + // Get the remote end of the connection. + rc = uv_tcp_getpeername(&(handle->tcp), addr, &addr_size); + if (rc == 0) { + rc = getnameinfo(addr, addr_size, hostbuf, sizeof(hostbuf), portbuf, + sizeof(portbuf), NI_NUMERICSERV); + if (rc == 0) { + out << " connected to "; + out << std::string(hostbuf) << ":" << std::string(portbuf); + } + } else if (rc == UV_ENOTCONN) { + out << " (not connected)"; + } + } + } +} + +/******************************************************************************* + * Utility function to format libuv path information. + *******************************************************************************/ +void reportPath(uv_handle_t* h, std::ostringstream& out) { + char *buffer = nullptr; + int rc = -1; + size_t size = 0; + uv_any_handle* handle = (uv_any_handle*)h; + // First call to get required buffer size. + switch (h->type) { + case UV_FS_EVENT: { + rc = uv_fs_event_getpath(&(handle->fs_event), buffer, &size); + break; + } + case UV_FS_POLL: { + rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer, &size); + break; + } + default: break; + } + if (rc == UV_ENOBUFS) { + buffer = static_cast(malloc(size)); + switch (h->type) { + case UV_FS_EVENT: { + rc = uv_fs_event_getpath(&(handle->fs_event), buffer, &size); + break; + } + case UV_FS_POLL: { + rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer, &size); + break; + } + default: break; + } + if (rc == 0) { + // buffer is not null terminated. + std::string name(buffer, size); + out << "filename: " << name; + } + free(buffer); + } +} + +/******************************************************************************* + * Utility function to walk libuv handles. + *******************************************************************************/ +void walkHandle(uv_handle_t* h, void* arg) { + std::string type; + std::ostringstream data; + std::ostream* out = reinterpret_cast(arg); + uv_any_handle* handle = (uv_any_handle*)h; + + // List all the types so we get a compile warning if we've missed one, + // (using default: supresses the compiler warning). + switch (h->type) { + case UV_UNKNOWN_HANDLE: type = "unknown"; break; + case UV_ASYNC: type = "async"; break; + case UV_CHECK: type = "check"; break; + case UV_FS_EVENT: { + type = "fs_event"; + reportPath(h, data); + break; + } + case UV_FS_POLL: { + type = "fs_poll"; + reportPath(h, data); + break; + } + case UV_HANDLE: type = "handle"; break; + case UV_IDLE: type = "idle"; break; + case UV_NAMED_PIPE: type = "pipe"; break; + case UV_POLL: type = "poll"; break; + case UV_PREPARE: type = "prepare"; break; + case UV_PROCESS: { + type = "process"; + data << "pid: " << handle->process.pid; + break; + } + case UV_STREAM: type = "stream"; break; + case UV_TCP: { + type = "tcp"; + reportEndpoints(h, data); + break; + } + case UV_TIMER: { + // TODO timeout/due is not actually public however it is present + // in all current versions of libuv. Once uv_timer_get_timeout is + // in a supported level of libuv we should test for it with dlsym + // and use it instead, in case timeout moves in the future. +#ifdef _WIN32 + uint64_t due = handle->timer.due; +#else + uint64_t due = handle->timer.timeout; +#endif + uint64_t now = uv_now(handle->timer.loop); + type = "timer"; + data << "repeat: " << uv_timer_get_repeat(&(handle->timer)); + if (due > now) { + data << ", timeout in: " << (due - now) << " ms"; + } else { + data << ", timeout expired: " << (now - due) << " ms ago"; + } + break; + } + case UV_TTY: { + int height, width, rc; + type = "tty"; + rc = uv_tty_get_winsize(&(handle->tty), &width, &height); + if (rc == 0) { + data << "width: " << width << ", height: " << height; + } + break; + } + case UV_UDP: { + type = "udp"; + reportEndpoints(h, data); + break; + } + case UV_SIGNAL: { + // SIGWINCH is used by libuv so always appears. + // See http://docs.libuv.org/en/v1.x/signal.html + type = "signal"; + data << "signum: " << handle->signal.signum + // node::signo_string() is not exported by Node.js on Windows. +#ifndef _WIN32 + << " (" << node::signo_string(handle->signal.signum) << ")" +#endif + ; + break; + } + case UV_FILE: type = "file"; break; + // We shouldn't see "max" type + case UV_HANDLE_TYPE_MAX : type = "max"; break; + } + + if (h->type == UV_TCP || h->type == UV_UDP +#ifndef _WIN32 + || h->type == UV_NAMED_PIPE +#endif + ) { + // These *must* be 0 or libuv will set the buffer sizes to the non-zero + // values they contain. + int send_size = 0; + int recv_size = 0; + if (h->type == UV_TCP || h->type == UV_UDP) { + data << ", "; + } + uv_send_buffer_size(h, &send_size); + uv_recv_buffer_size(h, &recv_size); + data << "send buffer size: " << send_size + << ", recv buffer size: " << recv_size; + } + + if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY || + h->type == UV_UDP || h->type == UV_POLL) { + uv_os_fd_t fd_v; + uv_os_fd_t* fd = &fd_v; + int rc = uv_fileno(h, fd); + // uv_os_fd_t is an int on Unix and HANDLE on Windows. +#ifndef _WIN32 + if (rc == 0) { + switch (fd_v) { + case 0: + data << ", stdin"; break; + case 1: + data << ", stdout"; break; + case 2: + data << ", stderr"; break; + default: + data << ", file descriptor: " << static_cast(fd_v); + break; + } + } +#endif + } + + if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY) { + + data << ", write queue size: " + << handle->stream.write_queue_size; + data << (uv_is_readable(&handle->stream) ? ", readable" : "") + << (uv_is_writable(&handle->stream) ? ", writable": ""); + + } + + *out << std::left << "[" << (uv_has_ref(h) ? 'R' : '-') + << (uv_is_active(h) ? 'A' : '-') << "] " << std::setw(10) << type + << std::internal << std::setw(2 + 2 * sizeof(void*)); + char prev_fill = out->fill('0'); + *out << static_cast(h) << std::left; + out->fill(prev_fill); + *out << " " << std::left << data.str() << std::endl; +} + +/******************************************************************************* + * Utility function to print out integer values with commas for readability. + ******************************************************************************/ +void WriteInteger(std::ostream& out, size_t value) { + int thousandsStack[8]; // Sufficient for max 64-bit number + int stackTop = 0; + int i; + char buf[64]; + size_t workingValue = value; + + do { + thousandsStack[stackTop++] = workingValue % 1000; + workingValue /= 1000; + } while (workingValue != 0); + + for (i = stackTop-1; i >= 0; i--) { + if (i == (stackTop-1)) { + out << thousandsStack[i]; + } else { + snprintf(buf, sizeof(buf), "%03u", thousandsStack[i]); + out << buf; + } + if (i > 0) { + out << ","; + } + } +} + +} // namespace nodereport diff --git a/deps/node-report/test/common.js b/deps/node-report/test/common.js new file mode 100644 index 00000000000000..89ab7644280d63 --- /dev/null +++ b/deps/node-report/test/common.js @@ -0,0 +1,193 @@ +'use strict'; + +const child_process = require('child_process'); +const fs = require('fs'); +const os = require('os'); + +const osMap = { + 'aix': 'AIX', + 'darwin': 'Darwin', + 'linux': 'Linux', + 'sunos': 'SunOS', + 'win32': 'Windows', +}; + +const REPORT_SECTIONS = [ + 'Node Report', + 'JavaScript Stack Trace', + 'JavaScript Heap', + 'System Information' +]; + +const reNewline = '(?:\\r*\\n)'; + +exports.findReports = (pid) => { + // Default filenames are of the form node-report..