From 07187804cec6dd8a32e21d71a562303c11e674cc Mon Sep 17 00:00:00 2001 From: Benjamin Coe Date: Thu, 9 Aug 2018 16:52:41 -0700 Subject: [PATCH 01/77] fs: implement mkdir recursive (mkdirp) Implements mkdirp functionality in node_file.cc. The Benefit of implementing in C++ layer is that the logic is more easily shared between the Promise and callback implementation and there are notable performance improvements. This commit is part of the Tooling Group Initiative. Refs: https://github.com/nodejs/user-feedback/pull/70 PR-URL: https://github.com/nodejs/node/pull/21875 Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: Jon Moss Reviewed-By: Ron Korving Reviewed-By: James M Snell Reviewed-By: Michael Dawson Reviewed-By: Anatoli Papirovski Reviewed-By: Sam Ruby Reviewed-By: Joyee Cheung --- benchmark/fs/bench-mkdirp.js | 23 +++++ doc/api/fs.md | 35 +++++-- lib/fs.js | 45 ++++++--- lib/internal/fs/promises.js | 18 +++- src/node_file.cc | 158 ++++++++++++++++++++++++++++-- src/node_file.h | 42 ++++++++ test/parallel/test-fs-mkdir.js | 107 +++++++++++++++++++- test/parallel/test-fs-promises.js | 49 ++++++++- 8 files changed, 441 insertions(+), 36 deletions(-) create mode 100644 benchmark/fs/bench-mkdirp.js diff --git a/benchmark/fs/bench-mkdirp.js b/benchmark/fs/bench-mkdirp.js new file mode 100644 index 00000000000000..96a792c35a48e4 --- /dev/null +++ b/benchmark/fs/bench-mkdirp.js @@ -0,0 +1,23 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const tmpdir = require('../../test/common/tmpdir'); +tmpdir.refresh(); +let dirc = 0; + +const bench = common.createBenchmark(main, { + n: [1e4], +}); + +function main({ n }) { + bench.start(); + (function r(cntr) { + if (cntr-- <= 0) + return bench.end(n); + const pathname = `${tmpdir.path}/${++dirc}/${++dirc}/${++dirc}/${++dirc}`; + fs.mkdir(pathname, { createParents: true }, (err) => { + r(cntr); + }); + }(n)); +} diff --git a/doc/api/fs.md b/doc/api/fs.md index 25cb3fc7f87ee2..d7cfcf46347af7 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -2139,7 +2139,7 @@ changes: Synchronous lstat(2). -## fs.mkdir(path[, mode], callback) +## fs.mkdir(path[, options], callback) * `path` {string|Buffer|URL} -* `mode` {integer} Not supported on Windows. **Default:** `0o777`. +* `options` {Object|integer} + * `recursive` {boolean} **Default:** `false` + * `mode` {integer} Not supported on Windows. **Default:** `0o777`. * `callback` {Function} * `err` {Error} Asynchronously creates a directory. No arguments other than a possible exception are given to the completion callback. +The optional `options` argument can be an integer specifying mode (permission +and sticky bits), or an object with a `mode` property and a `recursive` +property indicating whether parent folders should be created. + +```js +// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist. +fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => { + if (err) throw err; +}); +``` + See also: mkdir(2). -## fs.mkdirSync(path[, mode]) +## fs.mkdirSync(path[, options]) * `path` {string|Buffer|URL} -* `mode` {integer} Not supported on Windows. **Default:** `0o777`. +* `options` {Object|integer} + * `recursive` {boolean} **Default:** `false` + * `mode` {integer} Not supported on Windows. **Default:** `0o777`. Synchronously creates a directory. Returns `undefined`. This is the synchronous version of [`fs.mkdir()`][]. @@ -4100,18 +4115,24 @@ changes: Asynchronous lstat(2). The `Promise` is resolved with the [`fs.Stats`][] object for the given symbolic link `path`. -### fsPromises.mkdir(path[, mode]) +### fsPromises.mkdir(path[, options]) * `path` {string|Buffer|URL} -* `mode` {integer} **Default:** `0o777` +* `options` {Object|integer} + * `recursive` {boolean} **Default:** `false` + * `mode` {integer} Not supported on Windows. **Default:** `0o777`. * Returns: {Promise} Asynchronously creates a directory then resolves the `Promise` with no arguments upon success. +The optional `options` argument can be an integer specifying mode (permission +and sticky bits), or an object with a `mode` property and a `recursive` +property indicating whether parent folders should be created. + ### fsPromises.mkdtemp(prefix[, options]) +```C +napi_status napi_add_finalizer(napi_env env, + napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, + napi_ref* result); +``` + + - `[in] env`: The environment that the API is invoked under. + - `[in] js_object`: The JavaScript object to which the native data will be + attached. + - `[in] native_object`: The native data that will be attached to the JavaScript + object. + - `[in] finalize_cb`: Native callback that will be used to free the + native data when the JavaScript object is ready for garbage-collection. + - `[in] finalize_hint`: Optional contextual hint that is passed to the + finalize callback. + - `[out] result`: Optional reference to the JavaScript object. + +Returns `napi_ok` if the API succeeded. + +Adds a `napi_finalize` callback which will be called when the JavaScript object +in `js_object` is ready for garbage collection. This API is similar to +`napi_wrap()` except that +* the native data cannot be retrieved later using `napi_unwrap()`, +* nor can it be removed later using `napi_remove_wrap()`, and +* the API can be called multiple times with different data items in order to + attach each of them to the JavaScript object. + +*Caution*: The optional returned reference (if obtained) should be deleted via +[`napi_delete_reference`][] ONLY in response to the finalize callback +invocation. If it is deleted before then, then the finalize callback may never +be invoked. Therefore, when obtaining a reference a finalize callback is also +required in order to enable correct disposal of the reference. + ## Simple Asynchronous Operations Addon modules often need to leverage async helpers from libuv as part of their @@ -4559,6 +4616,7 @@ This API may only be called from the main thread. [Working with JavaScript Values]: #n_api_working_with_javascript_values [Working with JavaScript Values - Abstract Operations]: #n_api_working_with_javascript_values_abstract_operations +[`napi_add_finalizer`]: #n_api_napi_add_finalizer [`napi_async_init`]: #n_api_napi_async_init [`napi_cancel_async_work`]: #n_api_napi_cancel_async_work [`napi_close_escapable_handle_scope`]: #n_api_napi_close_escapable_handle_scope diff --git a/src/node_api.cc b/src/node_api.cc index ef4ec29708c0d4..690579f573bdf2 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -1157,6 +1157,63 @@ class ThreadSafeFunction : public node::AsyncResource { bool handles_closing; }; +enum WrapType { + retrievable, + anonymous +}; + +template static inline +napi_status Wrap(napi_env env, + napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, + napi_ref* result) { + NAPI_PREAMBLE(env); + CHECK_ARG(env, js_object); + + v8::Isolate* isolate = env->isolate; + v8::Local context = isolate->GetCurrentContext(); + + v8::Local value = v8impl::V8LocalValueFromJsValue(js_object); + RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg); + v8::Local obj = value.As(); + + if (wrap_type == retrievable) { + // If we've already wrapped this object, we error out. + RETURN_STATUS_IF_FALSE(env, + !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper)) + .FromJust(), + napi_invalid_arg); + } else if (wrap_type == anonymous) { + // If no finalize callback is provided, we error out. + CHECK_ARG(env, finalize_cb); + } + + v8impl::Reference* reference = nullptr; + if (result != nullptr) { + // The returned reference should be deleted via napi_delete_reference() + // ONLY in response to the finalize callback invocation. (If it is deleted + // before then, then the finalize callback will never be invoked.) + // Therefore a finalize callback is required when returning a reference. + CHECK_ARG(env, finalize_cb); + reference = v8impl::Reference::New( + env, obj, 0, false, finalize_cb, native_object, finalize_hint); + *result = reinterpret_cast(reference); + } else { + // Create a self-deleting reference. + reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb, + native_object, finalize_cb == nullptr ? nullptr : finalize_hint); + } + + if (wrap_type == retrievable) { + CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper), + v8::External::New(isolate, reference)).FromJust()); + } + + return GET_RETURN_STATUS(env); +} + } // end of namespace v8impl // Intercepts the Node-V8 module registration callback. Converts parameters @@ -2859,41 +2916,12 @@ napi_status napi_wrap(napi_env env, napi_finalize finalize_cb, void* finalize_hint, napi_ref* result) { - NAPI_PREAMBLE(env); - CHECK_ARG(env, js_object); - - v8::Isolate* isolate = env->isolate; - v8::Local context = isolate->GetCurrentContext(); - - v8::Local value = v8impl::V8LocalValueFromJsValue(js_object); - RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg); - v8::Local obj = value.As(); - - // If we've already wrapped this object, we error out. - RETURN_STATUS_IF_FALSE(env, - !obj->HasPrivate(context, NAPI_PRIVATE_KEY(context, wrapper)).FromJust(), - napi_invalid_arg); - - v8impl::Reference* reference = nullptr; - if (result != nullptr) { - // The returned reference should be deleted via napi_delete_reference() - // ONLY in response to the finalize callback invocation. (If it is deleted - // before then, then the finalize callback will never be invoked.) - // Therefore a finalize callback is required when returning a reference. - CHECK_ARG(env, finalize_cb); - reference = v8impl::Reference::New( - env, obj, 0, false, finalize_cb, native_object, finalize_hint); - *result = reinterpret_cast(reference); - } else { - // Create a self-deleting reference. - reference = v8impl::Reference::New(env, obj, 0, true, finalize_cb, - native_object, finalize_cb == nullptr ? nullptr : finalize_hint); - } - - CHECK(obj->SetPrivate(context, NAPI_PRIVATE_KEY(context, wrapper), - v8::External::New(isolate, reference)).FromJust()); - - return GET_RETURN_STATUS(env); + return v8impl::Wrap(env, + js_object, + native_object, + finalize_cb, + finalize_hint, + result); } napi_status napi_unwrap(napi_env env, napi_value obj, void** result) { @@ -4138,3 +4166,17 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func) { CHECK(func != nullptr); return reinterpret_cast(func)->Ref(); } + +napi_status napi_add_finalizer(napi_env env, + napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, + napi_ref* result) { + return v8impl::Wrap(env, + js_object, + native_object, + finalize_cb, + finalize_hint, + result); +} diff --git a/src/node_api.h b/src/node_api.h index 1b2a392a0a0b1c..10a2c8ff3098be 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -695,6 +695,12 @@ NAPI_EXTERN napi_status napi_get_value_bigint_words(napi_env env, int* sign_bit, size_t* word_count, uint64_t* words); +NAPI_EXTERN napi_status napi_add_finalizer(napi_env env, + napi_value js_object, + void* native_object, + napi_finalize finalize_cb, + void* finalize_hint, + napi_ref* result); #endif // NAPI_EXPERIMENTAL EXTERN_C_END diff --git a/test/addons-napi/test_general/testFinalizer.js b/test/addons-napi/test_general/testFinalizer.js new file mode 100644 index 00000000000000..d5df4c8c724f98 --- /dev/null +++ b/test/addons-napi/test_general/testFinalizer.js @@ -0,0 +1,33 @@ +'use strict'; +// Flags: --expose-gc + +const common = require('../../common'); +const test_general = require(`./build/${common.buildType}/test_general`); +const assert = require('assert'); + +let finalized = {}; +const callback = common.mustCall(2); + +// Add two items to be finalized and ensure the callback is called for each. +test_general.addFinalizerOnly(finalized, callback); +test_general.addFinalizerOnly(finalized, callback); + +// Ensure attached items cannot be retrieved. +common.expectsError(() => test_general.unwrap(finalized), + { type: Error, message: 'Invalid argument' }); + +// Ensure attached items cannot be removed. +common.expectsError(() => test_general.removeWrap(finalized), + { type: Error, message: 'Invalid argument' }); +finalized = null; +global.gc(); + +// Add an item to an object that is already wrapped, and ensure that its +// finalizer as well as the wrap finalizer gets called. +let finalizeAndWrap = {}; +test_general.wrap(finalizeAndWrap); +test_general.addFinalizerOnly(finalizeAndWrap, common.mustCall()); +finalizeAndWrap = null; +global.gc(); +assert.strictEqual(test_general.derefItemWasCalled(), true, + 'finalize callback was called'); diff --git a/test/addons-napi/test_general/test_general.c b/test/addons-napi/test_general/test_general.c index 5a363d0b168f89..498aec4983c0c8 100644 --- a/test/addons-napi/test_general/test_general.c +++ b/test/addons-napi/test_general/test_general.c @@ -1,3 +1,4 @@ +#define NAPI_EXPERIMENTAL #include #include #include "../common.h" @@ -177,6 +178,17 @@ static napi_value wrap(napi_env env, napi_callback_info info) { return NULL; } +static napi_value unwrap(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value wrapped; + void* data; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &wrapped, NULL, NULL)); + NAPI_CALL(env, napi_unwrap(env, wrapped, &data)); + + return NULL; +} + static napi_value remove_wrap(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value wrapped; @@ -232,6 +244,33 @@ static napi_value testNapiRun(napi_env env, napi_callback_info info) { return result; } +static void finalizer_only_callback(napi_env env, void* data, void* hint) { + napi_ref js_cb_ref = data; + napi_value js_cb, undefined; + NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, js_cb_ref, &js_cb)); + NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NAPI_CALL_RETURN_VOID(env, + napi_call_function(env, undefined, js_cb, 0, NULL, NULL)); + NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, js_cb_ref)); +} + +static napi_value add_finalizer_only(napi_env env, napi_callback_info info) { + size_t argc = 2; + napi_value argv[2]; + napi_ref js_cb_ref; + + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &js_cb_ref)); + NAPI_CALL(env, + napi_add_finalizer(env, + argv[0], + js_cb_ref, + finalizer_only_callback, + NULL, + NULL)); + return NULL; +} + static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { DECLARE_NAPI_PROPERTY("testStrictEquals", testStrictEquals), @@ -246,7 +285,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup), DECLARE_NAPI_PROPERTY("testNapiTypeof", testNapiTypeof), DECLARE_NAPI_PROPERTY("wrap", wrap), + DECLARE_NAPI_PROPERTY("unwrap", unwrap), DECLARE_NAPI_PROPERTY("removeWrap", remove_wrap), + DECLARE_NAPI_PROPERTY("addFinalizerOnly", add_finalizer_only), DECLARE_NAPI_PROPERTY("testFinalizeWrap", test_finalize_wrap), DECLARE_NAPI_PROPERTY("finalizeWasCalled", finalize_was_called), DECLARE_NAPI_PROPERTY("derefItemWasCalled", deref_item_was_called), From 6e5cd4dc8aa195600fbe4109f085644940ea41df Mon Sep 17 00:00:00 2001 From: Lucas Woo Date: Fri, 31 Aug 2018 11:57:33 +0800 Subject: [PATCH 12/77] =?UTF-8?q?test:=20checks=20on=20napi=20factory=20wr?= =?UTF-8?q?ap=E2=80=99s=20finalization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/22396 PR-URL: https://github.com/nodejs/node/pull/22612 Reviewed-By: James M Snell Reviewed-By: Gabriel Schulhof --- test/addons-napi/7_factory_wrap/binding.cc | 11 +++++--- test/addons-napi/7_factory_wrap/myobject.cc | 9 +++++++ test/addons-napi/7_factory_wrap/myobject.h | 1 + test/addons-napi/7_factory_wrap/test.js | 29 ++++++++++++++------- test/addons-napi/8_passing_wrapped/test.js | 5 ++-- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/test/addons-napi/7_factory_wrap/binding.cc b/test/addons-napi/7_factory_wrap/binding.cc index d98132457875a1..e937516c894a90 100644 --- a/test/addons-napi/7_factory_wrap/binding.cc +++ b/test/addons-napi/7_factory_wrap/binding.cc @@ -15,9 +15,14 @@ napi_value CreateObject(napi_env env, napi_callback_info info) { napi_value Init(napi_env env, napi_value exports) { NAPI_CALL(env, MyObject::Init(env)); - NAPI_CALL(env, - // NOLINTNEXTLINE (readability/null_usage) - napi_create_function(env, "exports", -1, CreateObject, NULL, &exports)); + napi_property_descriptor descriptors[] = { + DECLARE_NAPI_GETTER("finalizeCount", MyObject::GetFinalizeCount), + DECLARE_NAPI_PROPERTY("createObject", CreateObject), + }; + + NAPI_CALL(env, napi_define_properties( + env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); + return exports; } diff --git a/test/addons-napi/7_factory_wrap/myobject.cc b/test/addons-napi/7_factory_wrap/myobject.cc index 4e1d79c1febc17..b7cc9c534f366a 100644 --- a/test/addons-napi/7_factory_wrap/myobject.cc +++ b/test/addons-napi/7_factory_wrap/myobject.cc @@ -1,6 +1,8 @@ #include "myobject.h" #include "../common.h" +static int finalize_count = 0; + MyObject::MyObject() : env_(nullptr), wrapper_(nullptr) {} MyObject::~MyObject() { napi_delete_reference(env_, wrapper_); } @@ -8,10 +10,17 @@ MyObject::~MyObject() { napi_delete_reference(env_, wrapper_); } void MyObject::Destructor(napi_env env, void* nativeObject, void* /*finalize_hint*/) { + ++finalize_count; MyObject* obj = static_cast(nativeObject); delete obj; } +napi_value MyObject::GetFinalizeCount(napi_env env, napi_callback_info info) { + napi_value result; + NAPI_CALL(env, napi_create_int32(env, finalize_count, &result)); + return result; +} + napi_ref MyObject::constructor; napi_status MyObject::Init(napi_env env) { diff --git a/test/addons-napi/7_factory_wrap/myobject.h b/test/addons-napi/7_factory_wrap/myobject.h index 28ca94d16e30dd..172fcd3ca49295 100644 --- a/test/addons-napi/7_factory_wrap/myobject.h +++ b/test/addons-napi/7_factory_wrap/myobject.h @@ -7,6 +7,7 @@ class MyObject { public: static napi_status Init(napi_env env); static void Destructor(napi_env env, void* nativeObject, void* finalize_hint); + static napi_value GetFinalizeCount(napi_env env, napi_callback_info info); static napi_status NewInstance(napi_env env, napi_value arg, napi_value* instance); diff --git a/test/addons-napi/7_factory_wrap/test.js b/test/addons-napi/7_factory_wrap/test.js index 20108e14b629bc..8aaf1b0ba91ee7 100644 --- a/test/addons-napi/7_factory_wrap/test.js +++ b/test/addons-napi/7_factory_wrap/test.js @@ -1,14 +1,25 @@ 'use strict'; +// Flags: --expose-gc + const common = require('../../common'); const assert = require('assert'); -const createObject = require(`./build/${common.buildType}/binding`); +const test = require(`./build/${common.buildType}/binding`); -const obj = createObject(10); -assert.strictEqual(obj.plusOne(), 11); -assert.strictEqual(obj.plusOne(), 12); -assert.strictEqual(obj.plusOne(), 13); +assert.strictEqual(test.finalizeCount, 0); +(() => { + const obj = test.createObject(10); + assert.strictEqual(obj.plusOne(), 11); + assert.strictEqual(obj.plusOne(), 12); + assert.strictEqual(obj.plusOne(), 13); +})(); +global.gc(); +assert.strictEqual(test.finalizeCount, 1); -const obj2 = createObject(20); -assert.strictEqual(obj2.plusOne(), 21); -assert.strictEqual(obj2.plusOne(), 22); -assert.strictEqual(obj2.plusOne(), 23); +(() => { + const obj2 = test.createObject(20); + assert.strictEqual(obj2.plusOne(), 21); + assert.strictEqual(obj2.plusOne(), 22); + assert.strictEqual(obj2.plusOne(), 23); +})(); +global.gc(); +assert.strictEqual(test.finalizeCount, 2); diff --git a/test/addons-napi/8_passing_wrapped/test.js b/test/addons-napi/8_passing_wrapped/test.js index 7793133f7750ba..525993c96d3bad 100644 --- a/test/addons-napi/8_passing_wrapped/test.js +++ b/test/addons-napi/8_passing_wrapped/test.js @@ -6,11 +6,12 @@ const assert = require('assert'); const addon = require(`./build/${common.buildType}/binding`); let obj1 = addon.createObject(10); -const obj2 = addon.createObject(20); +let obj2 = addon.createObject(20); const result = addon.add(obj1, obj2); assert.strictEqual(result, 30); // Make sure the native destructor gets called. obj1 = null; +obj2 = null; global.gc(); -assert.strictEqual(addon.finalizeCount(), 1); +assert.strictEqual(addon.finalizeCount(), 2); From 17733d3c423d60f6bc0ad163115c518c23c6119e Mon Sep 17 00:00:00 2001 From: MaleDong Date: Wed, 22 Aug 2018 12:15:00 +0800 Subject: [PATCH 13/77] lib: remove unnecessary symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove `(...)`, because this is a simple,sensitive expression. PR-URL: https://github.com/nodejs/node/pull/22455 Reviewed-By: Weijia Wang Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Tobias Nießen Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/_stream_readable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 07e2c41beec21b..2b9600f0fd6647 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -147,7 +147,7 @@ function Readable(options) { // Checking for a Stream.Duplex instance is faster here instead of inside // the ReadableState constructor, at least with V8 6.5 - const isDuplex = (this instanceof Stream.Duplex); + const isDuplex = this instanceof Stream.Duplex; this._readableState = new ReadableState(options, this, isDuplex); From 00a8511934e10a25b0afc2b7437a24f9b0fd0e59 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 6 Sep 2018 15:27:57 -0700 Subject: [PATCH 14/77] test: minor refactor in common/index.js PR-URL: https://github.com/nodejs/node/pull/22738 Reviewed-By: Colin Ihrig Reviewed-By: Refael Ackermann Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: George Adams --- test/common/index.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/common/index.js b/test/common/index.js index ed2c28aea4c773..0da37360bc4aa1 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -143,16 +143,14 @@ const PIPE = (() => { return path.join(pipePrefix, pipeName); })(); -let hasIPv6; -{ +const hasIPv6 = (() => { const iFaces = os.networkInterfaces(); const re = isWindows ? /Loopback Pseudo-Interface/ : /lo/; - hasIPv6 = Object.keys(iFaces).some(function(name) { - return re.test(name) && iFaces[name].some(function(info) { - return info.family === 'IPv6'; - }); + return Object.keys(iFaces).some((name) => { + return re.test(name) && + iFaces[name].some(({ family }) => family === 'IPv6'); }); -} +})(); /* * Check that when running a test with From 873ebeba54bc11298df80cfc15ca8ba27b6e938d Mon Sep 17 00:00:00 2001 From: Sagi Tsofan Date: Tue, 11 Sep 2018 01:14:10 +0300 Subject: [PATCH 15/77] doc: document http2 timeouts New default timeout values of "2 minutes" were added into documentation inside 2 classes under "Event: 'timeout'": 1) Class: Http2SecureServer 2) Class: Http2Server New sections for `.setTimeout()` method were added inside `Http2SecureServer` & `Http2Server` docs. PR-URL: https://github.com/nodejs/node/pull/22798 Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- doc/api/http2.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/doc/api/http2.md b/doc/api/http2.md index fac5a5f23be7aa..7aec57e1111291 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1615,6 +1615,7 @@ added: v8.4.0 The `'timeout'` event is emitted when there is no activity on the Server for a given number of milliseconds set using `http2server.setTimeout()`. +**Default:** 2 minutes. #### server.close([callback]) + +* `msecs` {number} **Default:** `120000` (2 minutes) +* `callback` {Function} +* Returns: {Http2Server} + +Used to set the timeout value for http2 server requests, +and sets a callback function that is called when there is no activity +on the `Http2Server` after `msecs` milliseconds. + +The given callback is registered as a listener on the `'timeout'` event. + +In case of no callback function were assigned, a new `ERR_INVALID_CALLBACK` +error will be thrown. + ### Class: Http2SecureServer + +* `msecs` {number} **Default:** `120000` (2 minutes) +* `callback` {Function} +* Returns: {Http2SecureServer} + +Used to set the timeout value for http2 secure server requests, +and sets a callback function that is called when there is no activity +on the `Http2SecureServer` after `msecs` milliseconds. + +The given callback is registered as a listener on the `'timeout'` event. + +In case of no callback function were assigned, a new `ERR_INVALID_CALLBACK` +error will be thrown. + ### http2.createServer(options[, onRequestHandler]) + +* `filename` {string} Filename to be used to construct the relative require + function. +* Returns: {[`require`][]} Require function + +```js +const { createRequireFromPath } = require('module'); +const requireUtil = createRequireFromPath('../src/utils'); + +// require `../src/utils/some-tool` +requireUtil('./some-tool'); +``` + [`__dirname`]: #modules_dirname [`__filename`]: #modules_filename [`Error`]: errors.html#errors_class_error [`module` object]: #modules_the_module_object [`path.dirname()`]: path.html#path_path_dirname_path [GLOBAL_FOLDERS]: #modules_loading_from_the_global_folders +[`require`]: #modules_require [exports shortcut]: #modules_exports_shortcut [module resolution]: #modules_all_together [module wrapper]: #modules_the_module_wrapper diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 1e93791237c92f..3083cdbb8bce3f 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -23,6 +23,7 @@ const { NativeModule } = require('internal/bootstrap/loaders'); const util = require('util'); +const { pathToFileURL } = require('internal/url'); const vm = require('vm'); const assert = require('assert').ok; const fs = require('fs'); @@ -54,7 +55,6 @@ module.exports = Module; let asyncESM; let ModuleJob; let createDynamicModule; -let pathToFileURL; let decorateErrorStack; function lazyLoadESM() { @@ -63,7 +63,6 @@ function lazyLoadESM() { createDynamicModule = require( 'internal/modules/esm/create_dynamic_module'); decorateErrorStack = require('internal/util').decorateErrorStack; - pathToFileURL = require('internal/url').pathToFileURL; } const { @@ -745,6 +744,13 @@ Module.runMain = function() { process._tickCallback(); }; +Module.createRequireFromPath = (filename) => { + const m = new Module(filename); + m.filename = filename; + m.paths = Module._nodeModulePaths(path.dirname(filename)); + return makeRequireFunction(m); +}; + Module._initPaths = function() { const isWindows = process.platform === 'win32'; diff --git a/test/parallel/test-module-create-require.js b/test/parallel/test-module-create-require.js new file mode 100644 index 00000000000000..03ed31939fba67 --- /dev/null +++ b/test/parallel/test-module-create-require.js @@ -0,0 +1,12 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const path = require('path'); + +const { createRequireFromPath } = require('module'); + +const p = path.resolve(__dirname, '..', 'fixtures', 'fake.js'); + +const req = createRequireFromPath(p); +assert.strictEqual(req('./baz'), 'perhaps I work'); From 217fb2ed5576e1ca78d9035a95c28a0aab31d9ec Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 9 Sep 2018 15:38:48 +0200 Subject: [PATCH 22/77] worker: correct (de)initialization order - Initialize `thread_exit_async_` only once the thread has been started. This is done since it is only triggered from the thread when it is exiting. - Move the final `uv_run` to the `Worker` destructor. This makes sure that it is always run, regardless of whether the thread is actually started or not. - Always dispose the `Isolate` before cleaning up the libuv event loop. This now matches the reverse order of initialization. Fixes: https://github.com/nodejs/node/issues/22736 PR-URL: https://github.com/nodejs/node/pull/22773 Reviewed-By: James M Snell --- src/node_worker.cc | 35 ++++++++++++------- .../test-worker-invalid-workerdata.js | 15 ++++++++ 2 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 test/parallel/test-worker-invalid-workerdata.js diff --git a/src/node_worker.cc b/src/node_worker.cc index d70cb42dfff44a..fa192d1291ec84 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -71,14 +71,6 @@ Worker::Worker(Environment* env, Local wrap) CHECK_NE(isolate_, nullptr); CHECK_EQ(uv_loop_init(&loop_), 0); - thread_exit_async_.reset(new uv_async_t); - thread_exit_async_->data = this; - CHECK_EQ(uv_async_init(env->event_loop(), - thread_exit_async_.get(), - [](uv_async_t* handle) { - static_cast(handle->data)->OnThreadStopped(); - }), 0); - { // Enter an environment capable of executing code in the child Isolate // (and only in it). @@ -242,9 +234,6 @@ void Worker::Run() { DisposeIsolate(); - // Need to run the loop one more time to close the platform's uv_async_t - uv_run(&loop_, UV_RUN_ONCE); - { Mutex::ScopedLock lock(mutex_); CHECK(thread_exit_async_); @@ -256,6 +245,13 @@ void Worker::Run() { } void Worker::DisposeIsolate() { + if (env_) { + CHECK_NOT_NULL(isolate_); + Locker locker(isolate_); + Isolate::Scope isolate_scope(isolate_); + env_.reset(); + } + if (isolate_ == nullptr) return; @@ -331,12 +327,16 @@ Worker::~Worker() { CHECK(stopped_); CHECK(thread_joined_); CHECK_EQ(child_port_, nullptr); - CheckedUvLoopClose(&loop_); // This has most likely already happened within the worker thread -- this // is just in case Worker creation failed early. DisposeIsolate(); + // Need to run the loop one more time to close the platform's uv_async_t + uv_run(&loop_, UV_RUN_ONCE); + + CheckedUvLoopClose(&loop_); + Debug(this, "Worker %llu destroyed", thread_id_); } @@ -360,10 +360,19 @@ void Worker::StartThread(const FunctionCallbackInfo& args) { w->env()->add_sub_worker_context(w); w->stopped_ = false; + w->thread_joined_ = false; + + w->thread_exit_async_.reset(new uv_async_t); + w->thread_exit_async_->data = w; + CHECK_EQ(uv_async_init(w->env()->event_loop(), + w->thread_exit_async_.get(), + [](uv_async_t* handle) { + static_cast(handle->data)->OnThreadStopped(); + }), 0); + CHECK_EQ(uv_thread_create(&w->tid_, [](void* arg) { static_cast(arg)->Run(); }, static_cast(w)), 0); - w->thread_joined_ = false; } void Worker::StopThread(const FunctionCallbackInfo& args) { diff --git a/test/parallel/test-worker-invalid-workerdata.js b/test/parallel/test-worker-invalid-workerdata.js new file mode 100644 index 00000000000000..d0cb1753eb4b64 --- /dev/null +++ b/test/parallel/test-worker-invalid-workerdata.js @@ -0,0 +1,15 @@ +// Flags: --experimental-worker +'use strict'; +require('../common'); +const assert = require('assert'); +const { Worker } = require('worker_threads'); + +// This tests verifies that failing to serialize workerData does not keep +// the process alive. +// Refs: https://github.com/nodejs/node/issues/22736 + +assert.throws(() => { + new Worker('./worker.js', { + workerData: { fn: () => {} } + }); +}, /DataCloneError/); From e5d67f7b069a7fb5848c856af496a0f58be762d4 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 9 Sep 2018 13:07:52 +0200 Subject: [PATCH 23/77] tools: implement update-authors in JS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the previous Perl script with a Node.js variant that explicitly supports `Author:` and, in particular, GitHub’s standard `Co-authored-by:` metadata tags. PR-URL: https://github.com/nodejs/node/pull/22771 Reviewed-By: Michaël Zasso Reviewed-By: Daniel Bevenius Reviewed-By: Tobias Nießen Reviewed-By: Luigi Pinca Reviewed-By: Matheus Marchini Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- tools/update-authors.js | 50 +++++++++++++++++++++++++++++++++++++++++ tools/update-authors.sh | 22 ------------------ 2 files changed, 50 insertions(+), 22 deletions(-) create mode 100755 tools/update-authors.js delete mode 100755 tools/update-authors.sh diff --git a/tools/update-authors.js b/tools/update-authors.js new file mode 100755 index 00000000000000..1c48eaec85c823 --- /dev/null +++ b/tools/update-authors.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node +// Usage: tools/update-author.js [--dry] +// Passing --dry will redirect output to stdout rather than write to 'AUTHORS'. +'use strict'; +const { spawn } = require('child_process'); +const fs = require('fs'); +const readline = require('readline'); + +const log = spawn( + 'git', + // Inspect author name/email and body. + ['log', '--reverse', '--format=Author: %aN <%aE>\n%b'], { + stdio: ['inherit', 'pipe', 'inherit'] + }); +const rl = readline.createInterface({ input: log.stdout }); + +let output; +if (process.argv.includes('--dry')) + output = process.stdout; +else + output = fs.createWriteStream('AUTHORS'); + +output.write('# Authors ordered by first contribution.\n\n'); + +const seen = new Set(); + +// Support regular git author metadata, as well as `Author:` and +// `Co-authored-by:` in the message body. Both have been used in the past +// to indicate multiple authors per commit, with the latter standardized +// by GitHub now. +const authorRe = + /(^Author:|^Co-authored-by:)\s+(?[^<]+)\s+(?<[^>]+>)/i; +rl.on('line', (line) => { + const match = line.match(authorRe); + if (!match) return; + + const { author, email } = match.groups; + if (seen.has(email) || + /@chromium\.org/.test(email) || + email === '') { + return; + } + + seen.add(email); + output.write(`${author} ${email}\n`); +}); + +rl.on('close', () => { + output.end('\n# Generated by tools/update-authors.js\n'); +}); diff --git a/tools/update-authors.sh b/tools/update-authors.sh deleted file mode 100755 index d07d9c9ff73c43..00000000000000 --- a/tools/update-authors.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -git log --reverse --format='%aN <%aE>' | perl -we ' - -BEGIN { - %seen = (), @authors = (); -} - -while (<>) { - next if $seen{$_}; - next if /\@chromium.org/; - next if //; - $seen{$_} = push @authors, $_; -} - -END { - print "# Authors ordered by first contribution.\n"; - print "\n", @authors, "\n"; - print "# Generated by tools/update-authors.sh\n"; -} - -' > AUTHORS From e52ea8b59309d111cf4bb0cd9e9b4ac0cb3e5b82 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 9 Sep 2018 13:09:34 +0200 Subject: [PATCH 24/77] doc: update AUTHORS list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This includes some re-ordering due to the newly added support for co-authored commits. PR-URL: https://github.com/nodejs/node/pull/22771 Reviewed-By: Michaël Zasso Reviewed-By: Daniel Bevenius Reviewed-By: Tobias Nießen Reviewed-By: Luigi Pinca Reviewed-By: Matheus Marchini Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- .mailmap | 7 +++- AUTHORS | 107 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 100 insertions(+), 14 deletions(-) diff --git a/.mailmap b/.mailmap index 6f8f98d022ddfb..f5462dbb992482 100644 --- a/.mailmap +++ b/.mailmap @@ -131,6 +131,7 @@ Gabriel de Perthuis Gareth Ellis Garwah Lam Geoffrey Bugaisky gbugaisky +Gerhard Stoebich Gibson Fahnestock Gil Pedersen Graham Fairweather Xotic750 @@ -204,6 +205,7 @@ Jérémy Lal Juan Sebastian Velez Posada Kai Sasaki Lewuathe Karl Skomski +Kat Marchán Kathy Truong k3kathy Kazuyuki Yamada Keith M Wesolowski @@ -238,6 +240,7 @@ Matheus Marchini Matheus Marchini Matt Lang matt-in-a-hat Matt Reed matthewreed26 +Matteo Collina Matthias Bastian piepmatz Mathias Buus Mathias Pettersson @@ -364,6 +367,7 @@ Tadashi SAWADA Takahiro ANDO Tarun Batra Tarun Ted Young +Teppei Sato Thomas Hunter II Thomas Lee Thomas Reggi @@ -391,7 +395,8 @@ Vladimir de Turckheim vsemozhetbyt Vse Mozhet Byt Wang Xinyong Weijia Wang <381152119@qq.com> -Weijia Wang <381152119@qq.com> starkewang +Weijia Wang <381152119@qq.com> +Weijia Wang <381152119@qq.com> Wei-Wei Wu Willi Eggeling Will Hayslett diff --git a/AUTHORS b/AUTHORS index 68469ee76329e2..299800b059fe21 100644 --- a/AUTHORS +++ b/AUTHORS @@ -650,7 +650,7 @@ Micleusanu Nicu Alejandro Oviedo Garcia Ben Burns Julian Duque -teppeis +Teppei Sato Rudi Cilibrasi Tim Ruffles CGavrila @@ -754,14 +754,14 @@ Felipe Batista Rebecca Turner Tyler Anton João Reis -Kat Marchán +Kat Marchán Ryan Petschek Pierre Inglebert Ivan Yan Sangmin Yoon Mark Plomer Phillip Johnsen -Matteo Collina +Matteo Collina jomo Gireesh Punathil Lucien Greathouse @@ -1432,23 +1432,25 @@ Ahmad Nassri Tom Atkinson Tobias Nießen Joseph Gentle +Arunesh Chandra +Gabriel Schulhof +Ian Halliday +Sampson Gao +Taylor Woll Zero King Raphael Okon JR McEntee Lovell Fuller Jason Marsh Vinay Hiremath -Gabriel Schulhof alejandro dave-k Steven Uppinder Chugh Karl Cheng -Taylor Woll Tarun Batra Nao YONASHIRO Christopher Luke -Sampson Gao John Paul Bamberg Cody Deckard Fabio Campinho @@ -1488,7 +1490,7 @@ Madara Uchiha Gil Tayar Glenn Schlereth Artur G Vieira -Flarna +Gerhard Stoebich Sreepurna Jasti Rafael Fragoso Andrei Cioromila @@ -1658,6 +1660,8 @@ Piotr Mionskowski Cyril Lakech Eduard Bondarenko Adina Shanholtz +Guy Bedford +Jan Krems Miguel Martins Yury Popov George Bezerra @@ -1670,7 +1674,6 @@ Alex Gresnel <31708810+agresnel@users.noreply.github.com> Will Young Martijn Schrage Halil İbrahim Şener -Guy Bedford Antoine Amara Mani Maghsoudlou Bartek Szczepański @@ -1884,7 +1887,6 @@ Ashish Kaila c0b <14798161+c0b@users.noreply.github.com> Damian Alec Perkins -Teppei Sato Jinwoo Lee Peter Marton Erwin W. Ramadhan @@ -2154,9 +2156,7 @@ Nick Filatov Jesse Gorzinski Pieter Mees Malcolm White -Gerhard Stoebich Matei Copot -ikasumiwt Gurin, Sebastian Indranil Dasgupta Harry Sarson @@ -2187,7 +2187,6 @@ Kyle Martin Denis Fäcke Daylor Yanes Carrie Coxwell -BeniCheni Masashi Hirano Brandon Ruggles Allen Yonghuang Wang @@ -2218,6 +2217,7 @@ Abhimanyu Vashisht Sagir Khan Kael Zhang Unknown +Krzysztof Taborski Blaine Bublitz Shailesh Shekhawat Davis Okoth @@ -2236,5 +2236,86 @@ Shelley Vohr Deepjyoti Mondal Brett Kiefer Kevin Thomas +ZaneHannanAU +Fernando Doglio +Renée Kooi +Jo Colina +itaysabato +Victor Belozyorov +Joonas Rouhiainen +GauthamBanasandra +Hugo Josefson +Sam Ruby +Haroon Khan +Developer Davo +Jacek Pospychała +MaleDong +iwko +Sohail Rajdev +Niicck +Denys Otrishko +Sergey Zelenov +Travis Fischer +Dominic Farolino +Octavian Soldea +XhmikosR +AdityaSrivast +Javier Gonzalez +RidgeA +Ryuichi Sakagami +hectorcoronado +Petras <15868923+kimberlake@users.noreply.github.com> +Kevin Lacabane <5239883+klacabane@users.noreply.github.com> +Simionescu, Radu +mariotsi +prayag21 <10997858+prayag21@users.noreply.github.com> +Bruno Pinho +Anto Aravinth +Helio Frota <00hf11@gmail.com> +Tim Ruffles +Jacob Page +sagulati +conectado +Vitor Bruno de Oliveira Barth +cclauss +James Ide +MaleDong +bhavayAnand9 +Brandon Lee <40652534+brandonlwt@users.noreply.github.com> +Oryan Moshe +Michael Sommer +Eugene Y. Q. Shen +Rishabh Singh +Marco Levrero +Ouyang Yadong +yahavfuchs +Thomas Leah +Musa Hamwala +James Bromwell +Jeremy Apthorp +Eugen Cazacu <32613393+oygen87@users.noreply.github.com> +James Bromwell <943160+thw0rted@users.noreply.github.com> +Csaba Palfi +Ryan Petrich +Andreas Girgensohn +Caleb Sander +Dzmitry_Prudnikau +Ian McKellar +Jennifer Bland +Kyle Fuller +ZYSzys +Neeraj Laad +Scott Van Gilder +Yaniv Friedensohn +Lars-Magnus Skog +Lucas Woo +Troels Liebe Bentsen +pranshuchittora +lakamsani +Chris White +Ben Newman +Szymon Marczak +Tessei Kameyama +Chakravarthy S M -# Generated by tools/update-authors.sh +# Generated by tools/update-authors.js From e268b643a692ce1c349e9131c8e074748f48ac86 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 7 Sep 2018 15:37:31 -0700 Subject: [PATCH 25/77] src: move getActiveResources/Handles to node_process.cc PR-URL: https://github.com/nodejs/node/pull/22758 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: Refael Ackermann --- src/node.cc | 55 -------------------------------------------- src/node_internals.h | 2 ++ src/node_process.cc | 55 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 55 deletions(-) diff --git a/src/node.cc b/src/node.cc index 22480f6d21a1d1..a94ac07591ab0e 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1102,61 +1102,6 @@ static MaybeLocal ExecuteString(Environment* env, } -static void GetActiveRequests(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - Local ary = Array::New(args.GetIsolate()); - Local ctx = env->context(); - Local fn = env->push_values_to_array_function(); - Local argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; - size_t idx = 0; - - for (auto w : *env->req_wrap_queue()) { - if (w->persistent().IsEmpty()) - continue; - argv[idx] = w->GetOwner(); - if (++idx >= arraysize(argv)) { - fn->Call(ctx, ary, idx, argv).ToLocalChecked(); - idx = 0; - } - } - - if (idx > 0) { - fn->Call(ctx, ary, idx, argv).ToLocalChecked(); - } - - args.GetReturnValue().Set(ary); -} - - -// Non-static, friend of HandleWrap. Could have been a HandleWrap method but -// implemented here for consistency with GetActiveRequests(). -void GetActiveHandles(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - Local ary = Array::New(env->isolate()); - Local ctx = env->context(); - Local fn = env->push_values_to_array_function(); - Local argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; - size_t idx = 0; - - for (auto w : *env->handle_wrap_queue()) { - if (!HandleWrap::HasRef(w)) - continue; - argv[idx] = w->GetOwner(); - if (++idx >= arraysize(argv)) { - fn->Call(ctx, ary, idx, argv).ToLocalChecked(); - idx = 0; - } - } - if (idx > 0) { - fn->Call(ctx, ary, idx, argv).ToLocalChecked(); - } - - args.GetReturnValue().Set(ary); -} - - NO_RETURN void Abort() { DumpBacktrace(stderr); fflush(stderr); diff --git a/src/node_internals.h b/src/node_internals.h index 68bb156c042fcf..4c5dc88a0e7b05 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -888,6 +888,8 @@ void Abort(const v8::FunctionCallbackInfo& args); void Chdir(const v8::FunctionCallbackInfo& args); void CPUUsage(const v8::FunctionCallbackInfo& args); void Cwd(const v8::FunctionCallbackInfo& args); +void GetActiveHandles(const v8::FunctionCallbackInfo& args); +void GetActiveRequests(const v8::FunctionCallbackInfo& args); void Hrtime(const v8::FunctionCallbackInfo& args); void HrtimeBigInt(const v8::FunctionCallbackInfo& args); void Kill(const v8::FunctionCallbackInfo& args); diff --git a/src/node_process.cc b/src/node_process.cc index 92618e12f7bd12..1990228785280b 100644 --- a/src/node_process.cc +++ b/src/node_process.cc @@ -1,5 +1,7 @@ #include "node.h" #include "node_internals.h" +#include "base_object.h" +#include "base_object-inl.h" #include "env-inl.h" #include "util-inl.h" #include "uv.h" @@ -777,5 +779,58 @@ void GetParentProcessId(Local property, info.GetReturnValue().Set(Integer::New(info.GetIsolate(), uv_os_getppid())); } +void GetActiveRequests(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + Local ary = Array::New(args.GetIsolate()); + Local ctx = env->context(); + Local fn = env->push_values_to_array_function(); + Local argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; + size_t idx = 0; + + for (auto w : *env->req_wrap_queue()) { + if (w->persistent().IsEmpty()) + continue; + argv[idx] = w->GetOwner(); + if (++idx >= arraysize(argv)) { + fn->Call(ctx, ary, idx, argv).ToLocalChecked(); + idx = 0; + } + } + + if (idx > 0) { + fn->Call(ctx, ary, idx, argv).ToLocalChecked(); + } + + args.GetReturnValue().Set(ary); +} + + +// Non-static, friend of HandleWrap. Could have been a HandleWrap method but +// implemented here for consistency with GetActiveRequests(). +void GetActiveHandles(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + Local ary = Array::New(env->isolate()); + Local ctx = env->context(); + Local fn = env->push_values_to_array_function(); + Local argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; + size_t idx = 0; + + for (auto w : *env->handle_wrap_queue()) { + if (!HandleWrap::HasRef(w)) + continue; + argv[idx] = w->GetOwner(); + if (++idx >= arraysize(argv)) { + fn->Call(ctx, ary, idx, argv).ToLocalChecked(); + idx = 0; + } + } + if (idx > 0) { + fn->Call(ctx, ary, idx, argv).ToLocalChecked(); + } + + args.GetReturnValue().Set(ary); +} } // namespace node From 415eac82213c2d6f7cfe58dc2168b575ced475e1 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 7 Sep 2018 16:19:03 -0700 Subject: [PATCH 26/77] src: move DebugPortGetter/Setter to node_process.cc PR-URL: https://github.com/nodejs/node/pull/22758 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: Refael Ackermann --- src/node.cc | 27 --------------------------- src/node_internals.h | 5 +++++ src/node_process.cc | 29 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/node.cc b/src/node.cc index a94ac07591ab0e..0f380efdcaf438 100644 --- a/src/node.cc +++ b/src/node.cc @@ -160,7 +160,6 @@ using v8::Object; using v8::ObjectTemplate; using v8::Promise; using v8::PropertyAttribute; -using v8::PropertyCallbackInfo; using v8::ReadOnly; using v8::Script; using v8::ScriptCompiler; @@ -1733,32 +1732,6 @@ static Local GetFeatures(Environment* env) { return scope.Escape(obj); } - -static void DebugPortGetter(Local property, - const PropertyCallbackInfo& info) { - Environment* env = Environment::GetCurrent(info); - Mutex::ScopedLock lock(process_mutex); - int port = env->options()->debug_options->port(); -#if HAVE_INSPECTOR - if (port == 0) { - if (auto io = env->inspector_agent()->io()) - port = io->port(); - } -#endif // HAVE_INSPECTOR - info.GetReturnValue().Set(port); -} - - -static void DebugPortSetter(Local property, - Local value, - const PropertyCallbackInfo& info) { - Environment* env = Environment::GetCurrent(info); - Mutex::ScopedLock lock(process_mutex); - env->options()->debug_options->host_port.port = - value->Int32Value(env->context()).FromMaybe(0); -} - - static void DebugProcess(const FunctionCallbackInfo& args); static void DebugEnd(const FunctionCallbackInfo& args); diff --git a/src/node_internals.h b/src/node_internals.h index 4c5dc88a0e7b05..2f2473f28572ae 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -910,6 +910,11 @@ void EnvSetter(v8::Local property, void EnvQuery(v8::Local property, const v8::PropertyCallbackInfo& info); void EnvEnumerator(const v8::PropertyCallbackInfo& info); +void DebugPortGetter(v8::Local property, + const v8::PropertyCallbackInfo& info); +void DebugPortSetter(v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info); void GetParentProcessId(v8::Local property, const v8::PropertyCallbackInfo& info); diff --git a/src/node_process.cc b/src/node_process.cc index 1990228785280b..f6a5424f56547b 100644 --- a/src/node_process.cc +++ b/src/node_process.cc @@ -7,6 +7,10 @@ #include "uv.h" #include "v8.h" +#if HAVE_INSPECTOR +#include "inspector_io.h" +#endif + #include // PATH_MAX #include @@ -833,4 +837,29 @@ void GetActiveHandles(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(ary); } +void DebugPortGetter(Local property, + const PropertyCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info); + Mutex::ScopedLock lock(process_mutex); + int port = env->options()->debug_options->port(); +#if HAVE_INSPECTOR + if (port == 0) { + if (auto io = env->inspector_agent()->io()) + port = io->port(); + } +#endif // HAVE_INSPECTOR + info.GetReturnValue().Set(port); +} + + +void DebugPortSetter(Local property, + Local value, + const PropertyCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info); + Mutex::ScopedLock lock(process_mutex); + env->options()->debug_options->host_port.port = + value->Int32Value(env->context()).FromMaybe(0); +} + + } // namespace node From 536c6ed69e504952cc5ffc04c45c00e21f9d8607 Mon Sep 17 00:00:00 2001 From: Mohammed Essehemy Date: Fri, 14 Sep 2018 20:17:14 +0200 Subject: [PATCH 27/77] doc: fix typo in dns docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/22866 Reviewed-By: Vse Mozhet Byt Reviewed-By: Tobias Nießen Reviewed-By: Richard Lau --- doc/api/dns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/dns.md b/doc/api/dns.md index 1d988d8b574e23..cbe0e8628d71f7 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -1078,7 +1078,7 @@ implications for some applications, see the [`UV_THREADPOOL_SIZE`][] documentation for more information. Note that various networking APIs will call `dns.lookup()` internally to resolve -host names. If that is an issue, consider resolving the hostname to and address +host names. If that is an issue, consider resolving the hostname to an address using `dns.resolve()` and using the address instead of a host name. Also, some networking APIs (such as [`socket.connect()`][] and [`dgram.createSocket()`][]) allow the default resolver, `dns.lookup()`, to be replaced. From 14d1b7a4318441073f5e4652a15f2761f06b7ba7 Mon Sep 17 00:00:00 2001 From: Bryan English Date: Wed, 12 Sep 2018 21:32:29 -0700 Subject: [PATCH 28/77] doc: add withFileTypes option to fsPromises.readdir PR-URL: https://github.com/nodejs/node/pull/22833 Reviewed-By: Anatoli Papirovski Reviewed-By: Vse Mozhet Byt Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- doc/api/fs.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/api/fs.md b/doc/api/fs.md index a16f5902766361..338569a4deb445 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4191,11 +4191,16 @@ a colon, Node.js will open a file system stream, as described by ### fsPromises.readdir(path[, options]) * `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} **Default:** `'utf8'` + * `withFileTypes` {boolean} **Default:** `false` * Returns: {Promise} Reads the contents of a directory then resolves the `Promise` with an array @@ -4206,6 +4211,9 @@ object with an `encoding` property specifying the character encoding to use for the filenames. If the `encoding` is set to `'buffer'`, the filenames returned will be passed as `Buffer` objects. +If `options.withFileTypes` is set to `true`, the resolved array will contain +[`fs.Dirent`][] objects. + ### fsPromises.readFile(path[, options]) Type: Runtime @@ -48,6 +59,18 @@ The `OutgoingMessage.prototype.flush()` method is deprecated. Use ### DEP0002: require('\_linklist') + Type: End-of-Life @@ -55,6 +78,17 @@ The `_linklist` module is deprecated. Please use a userland alternative. ### DEP0003: \_writableState.buffer + Type: Runtime @@ -63,6 +97,20 @@ The `_writableState.buffer` property is deprecated. Use the ### DEP0004: CryptoStream.prototype.readyState + Type: End-of-Life @@ -70,6 +118,18 @@ The `CryptoStream.prototype.readyState` property was removed. ### DEP0005: Buffer() constructor + Type: Runtime (supports [`--pending-deprecation`][]) @@ -98,6 +158,18 @@ outside `node_modules` in order to better target developers, rather than users. ### DEP0006: child\_process options.customFds + Type: Runtime @@ -107,6 +179,21 @@ option should be used instead. ### DEP0007: Replace cluster worker.suicide with worker.exitedAfterDisconnect + Type: End-of-Life @@ -119,6 +206,15 @@ precisely describe the actual semantics and was unnecessarily emotion-laden. ### DEP0008: require('constants') + Type: Documentation-only @@ -129,6 +225,18 @@ to the `constants` property exposed by the relevant module. For instance, ### DEP0009: crypto.pbkdf2 without digest + Type: End-of-Life @@ -140,6 +248,17 @@ undefined `digest` will throw a `TypeError`. ### DEP0010: crypto.createCredentials + Type: Runtime @@ -148,6 +267,17 @@ The [`crypto.createCredentials()`][] API is deprecated. Please use ### DEP0011: crypto.Credentials + Type: Runtime @@ -156,6 +286,20 @@ instead. ### DEP0012: Domain.dispose + Type: End-of-Life @@ -164,6 +308,15 @@ explicitly via error event handlers set on the domain instead. ### DEP0013: fs asynchronous function without callback + Type: End-of-Life @@ -172,6 +325,23 @@ in Node.js 10.0.0 onwards. (See https://github.com/nodejs/node/pull/12562.) ### DEP0014: fs.read legacy String interface + Type: End-of-Life @@ -180,6 +350,23 @@ API as mentioned in the documentation instead. ### DEP0015: fs.readSync legacy String interface + Type: End-of-Life @@ -188,6 +375,15 @@ The [`fs.readSync()`][] legacy `String` interface is deprecated. Use the ### DEP0016: GLOBAL/root + Type: Runtime @@ -196,6 +392,15 @@ and should no longer be used. ### DEP0017: Intl.v8BreakIterator + Type: End-of-Life @@ -204,6 +409,12 @@ See [`Intl.Segmenter`](https://github.com/tc39/proposal-intl-segmenter). ### DEP0018: Unhandled promise rejections + Type: Runtime @@ -213,6 +424,17 @@ code. ### DEP0019: require('.') resolved outside directory + Type: Runtime @@ -222,6 +444,17 @@ release. ### DEP0020: Server.connections + Type: Runtime @@ -230,6 +463,17 @@ The [`Server.connections`][] property is deprecated. Please use the ### DEP0021: Server.listenFD + Type: Runtime @@ -238,6 +482,12 @@ The `Server.listenFD()` method is deprecated. Please use ### DEP0022: os.tmpDir() + Type: Runtime @@ -245,6 +495,17 @@ The `os.tmpDir()` API is deprecated. Please use [`os.tmpdir()`][] instead. ### DEP0023: os.getNetworkInterfaces() + Type: Runtime @@ -253,6 +514,15 @@ The `os.getNetworkInterfaces()` method is deprecated. Please use the ### DEP0024: REPLServer.prototype.convertToContext() + Type: End-of-Life @@ -260,6 +530,17 @@ The `REPLServer.prototype.convertToContext()` API has been removed. ### DEP0025: require('sys') + Type: Runtime @@ -267,6 +548,17 @@ The `sys` module is deprecated. Please use the [`util`][] module instead. ### DEP0026: util.print() + Type: Runtime @@ -275,6 +567,17 @@ instead. ### DEP0027: util.puts() + Type: Runtime @@ -282,6 +585,17 @@ The [`util.puts()`][] API is deprecated. Please use [`console.log()`][] instead. ### DEP0028: util.debug() + Type: Runtime @@ -290,6 +604,17 @@ instead. ### DEP0029: util.error() + Type: Runtime @@ -298,6 +623,15 @@ instead. ### DEP0030: SlowBuffer + Type: Documentation-only @@ -306,6 +640,15 @@ The [`SlowBuffer`][] class is deprecated. Please use ### DEP0031: ecdh.setPublicKey() + Type: Documentation-only @@ -314,6 +657,17 @@ API is not useful. ### DEP0032: domain module + Type: Documentation-only @@ -321,6 +675,17 @@ The [`domain`][] module is deprecated and should not be used. ### DEP0033: EventEmitter.listenerCount() + Type: Documentation-only @@ -329,6 +694,17 @@ deprecated. Please use [`emitter.listenerCount(eventName)`][] instead. ### DEP0034: fs.exists(path, callback) + Type: Documentation-only @@ -337,6 +713,16 @@ The [`fs.exists(path, callback)`][] API is deprecated. Please use ### DEP0035: fs.lchmod(path, mode, callback) + Type: Documentation-only @@ -344,13 +730,74 @@ The [`fs.lchmod(path, mode, callback)`][] API is deprecated. ### DEP0036: fs.lchmodSync(path, mode) + Type: Documentation-only The [`fs.lchmodSync(path, mode)`][] API is deprecated. + +### DEP0037: fs.lchown(path, uid, gid, callback) + + +Type: Deprecation revoked + +The [`fs.lchown(path, uid, gid, callback)`][] API is deprecated. + + +### DEP0038: fs.lchownSync(path, uid, gid) + + +Type: Deprecation revoked + +The [`fs.lchownSync(path, uid, gid)`][] API is deprecated. + ### DEP0039: require.extensions + Type: Documentation-only @@ -358,6 +805,12 @@ The [`require.extensions`][] property is deprecated. ### DEP0040: punycode module + Type: Documentation-only @@ -366,6 +819,20 @@ instead. ### DEP0041: NODE\_REPL\_HISTORY\_FILE environment variable + Type: End-of-Life @@ -374,6 +841,20 @@ The `NODE_REPL_HISTORY_FILE` environment variable was removed. Please use ### DEP0042: tls.CryptoStream + Type: End-of-Life @@ -382,6 +863,26 @@ The [`tls.CryptoStream`][] class was removed. Please use ### DEP0043: tls.SecurePair + Type: Documentation-only @@ -390,6 +891,19 @@ The [`tls.SecurePair`][] class is deprecated. Please use ### DEP0044: util.isArray() + Type: Documentation-only @@ -398,6 +912,19 @@ instead. ### DEP0045: util.isBoolean() + Type: Documentation-only @@ -405,6 +932,19 @@ The [`util.isBoolean()`][] API is deprecated. ### DEP0046: util.isBuffer() + Type: Documentation-only @@ -413,6 +953,19 @@ The [`util.isBuffer()`][] API is deprecated. Please use ### DEP0047: util.isDate() + Type: Documentation-only @@ -420,6 +973,19 @@ The [`util.isDate()`][] API is deprecated. ### DEP0048: util.isError() + Type: Documentation-only @@ -427,6 +993,19 @@ The [`util.isError()`][] API is deprecated. ### DEP0049: util.isFunction() + Type: Documentation-only @@ -434,6 +1013,19 @@ The [`util.isFunction()`][] API is deprecated. ### DEP0050: util.isNull() + Type: Documentation-only @@ -441,6 +1033,19 @@ The [`util.isNull()`][] API is deprecated. ### DEP0051: util.isNullOrUndefined() + Type: Documentation-only @@ -448,6 +1053,19 @@ The [`util.isNullOrUndefined()`][] API is deprecated. ### DEP0052: util.isNumber() + Type: Documentation-only @@ -455,6 +1073,19 @@ The [`util.isNumber()`][] API is deprecated. ### DEP0053 util.isObject() + Type: Documentation-only @@ -462,6 +1093,19 @@ The [`util.isObject()`][] API is deprecated. ### DEP0054: util.isPrimitive() + Type: Documentation-only @@ -469,6 +1113,19 @@ The [`util.isPrimitive()`][] API is deprecated. ### DEP0055: util.isRegExp() + Type: Documentation-only @@ -476,6 +1133,19 @@ The [`util.isRegExp()`][] API is deprecated. ### DEP0056: util.isString() + Type: Documentation-only @@ -483,6 +1153,19 @@ The [`util.isString()`][] API is deprecated. ### DEP0057: util.isSymbol() + Type: Documentation-only @@ -490,6 +1173,19 @@ The [`util.isSymbol()`][] API is deprecated. ### DEP0058: util.isUndefined() + Type: Documentation-only @@ -497,6 +1193,15 @@ The [`util.isUndefined()`][] API is deprecated. ### DEP0059: util.log() + Type: Documentation-only @@ -504,6 +1209,15 @@ The [`util.log()`][] API is deprecated. ### DEP0060: util.\_extend() + Type: Documentation-only @@ -511,6 +1225,15 @@ The [`util._extend()`][] API is deprecated. ### DEP0061: fs.SyncWriteStream + Type: Runtime @@ -519,6 +1242,12 @@ API. No alternative API is available. Please use a userland alternative. ### DEP0062: node --debug + Type: Runtime @@ -528,6 +1257,12 @@ instead. ### DEP0063: ServerResponse.prototype.writeHeader() + Type: Documentation-only @@ -539,6 +1274,26 @@ officially supported API. ### DEP0064: tls.createSecurePair() + Type: Runtime @@ -547,6 +1302,15 @@ The `tls.createSecurePair()` API was deprecated in documentation in Node.js ### DEP0065: repl.REPL_MODE_MAGIC and NODE_REPL_MODE=magic + Type: End-of-Life @@ -561,6 +1325,12 @@ removed. Please use `sloppy` instead. ### DEP0066: outgoingMessage.\_headers, outgoingMessage.\_headerNames + Type: Documentation-only @@ -576,6 +1346,12 @@ were never documented as officially supported properties. ### DEP0067: OutgoingMessage.prototype.\_renderHeaders + Type: Documentation-only @@ -587,6 +1363,12 @@ an officially supported API. ### DEP0068: node debug + Type: Runtime @@ -595,6 +1377,18 @@ a V8-inspector based CLI debugger available through `node inspect`. ### DEP0069: vm.runInDebugContext(string) + Type: End-of-Life @@ -604,6 +1398,15 @@ DebugContext was an experimental API. ### DEP0070: async_hooks.currentId() + Type: End-of-Life @@ -614,6 +1417,15 @@ This change was made while `async_hooks` was an experimental API. ### DEP0071: async_hooks.triggerId() + Type: End-of-Life @@ -624,6 +1436,15 @@ This change was made while `async_hooks` was an experimental API. ### DEP0072: async_hooks.AsyncResource.triggerId() + Type: End-of-Life @@ -634,6 +1455,15 @@ This change was made while `async_hooks` was an experimental API. ### DEP0073: Several internal properties of net.Server + Type: End-of-Life @@ -645,6 +1475,12 @@ code, no replacement API is provided. ### DEP0074: REPLServer.bufferedCommand + Type: Runtime @@ -653,6 +1489,12 @@ The `REPLServer.bufferedCommand` property was deprecated in favor of ### DEP0075: REPLServer.parseREPLKeyword() + Type: Runtime @@ -660,6 +1502,15 @@ Type: Runtime ### DEP0076: tls.parseCertString() + Type: Runtime @@ -683,6 +1534,12 @@ difference is that `querystring.parse()` does url decoding: ### DEP0077: Module.\_debug() + Type: Runtime @@ -693,6 +1550,12 @@ supported API. ### DEP0078: REPLServer.turnOffEditorMode() + Type: Runtime @@ -700,6 +1563,15 @@ Type: Runtime ### DEP0079: Custom inspection function on Objects via .inspect() + Type: Runtime @@ -710,6 +1582,12 @@ may be specified. ### DEP0080: path.\_makeLong() + Type: Documentation-only @@ -719,6 +1597,12 @@ and replaced with an identical, public `path.toNamespacedPath()` method. ### DEP0081: fs.truncate() using a file descriptor + Type: Runtime @@ -728,6 +1612,12 @@ file descriptors. ### DEP0082: REPLServer.prototype.memory() + Type: Runtime @@ -736,6 +1626,12 @@ the `REPLServer` itself. Do not use this function. ### DEP0083: Disabling ECDH by setting ecdhCurve to false + Type: Runtime @@ -746,6 +1642,12 @@ the client. Use the `ciphers` parameter instead. ### DEP0084: requiring bundled internal dependencies + Type: Runtime @@ -777,6 +1679,17 @@ code modification is necessary if that is done. ### DEP0085: AsyncHooks Sensitive API + Type: End-of-Life @@ -786,6 +1699,17 @@ API instead. ### DEP0086: Remove runInAsyncIdScope + Type: End-of-Life @@ -795,6 +1719,14 @@ details. ### DEP0089: require('assert') + Type: Documentation-only @@ -804,6 +1736,12 @@ same as the legacy assert but it will always use strict equality checks. ### DEP0090: Invalid GCM authentication tag lengths + Type: Runtime @@ -816,6 +1754,12 @@ is not included in this list will be considered invalid in compliance with ### DEP0091: crypto.DEFAULT_ENCODING + Type: Runtime @@ -823,6 +1767,12 @@ The [`crypto.DEFAULT_ENCODING`][] property is deprecated. ### DEP0092: Top-level `this` bound to `module.exports` + Type: Documentation-only @@ -832,6 +1782,12 @@ or `module.exports` instead. ### DEP0093: crypto.fips is deprecated and replaced. + Type: Documentation-only @@ -840,6 +1796,12 @@ and `crypto.getFips()` instead. ### DEP0094: Using `assert.fail()` with more than one argument. + Type: Runtime @@ -849,6 +1811,12 @@ method. ### DEP0095: timers.enroll() + Type: Runtime @@ -857,6 +1825,12 @@ Type: Runtime ### DEP0096: timers.unenroll() + Type: Runtime @@ -865,6 +1839,12 @@ Type: Runtime ### DEP0097: MakeCallback with domain property + Type: Runtime @@ -874,6 +1854,15 @@ should start using the `async_context` variant of `MakeCallback` or ### DEP0098: AsyncHooks Embedder AsyncResource.emitBefore and AsyncResource.emitAfter APIs + Type: Runtime @@ -887,6 +1876,12 @@ https://github.com/nodejs/node/pull/18513 for more details. ### DEP0099: async context-unaware node::MakeCallback C++ APIs + Type: Compile-time @@ -896,6 +1891,14 @@ parameter. ### DEP0100: process.assert() + Type: Runtime @@ -905,6 +1908,12 @@ This was never a documented feature. ### DEP0101: --with-lttng + Type: End-of-Life @@ -912,6 +1921,12 @@ The `--with-lttng` compile-time option has been removed. ### DEP0102: Using `noAssert` in Buffer#(read|write) operations. + Type: End-of-Life @@ -921,6 +1936,15 @@ could lead to hard to find errors and crashes. ### DEP0103: process.binding('util').is[...] typechecks + Type: Documentation-only (supports [`--pending-deprecation`][]) @@ -932,6 +1956,12 @@ This deprecation has been superseded by the deprecation of the ### DEP0104: process.env string coercion + Type: Documentation-only (supports [`--pending-deprecation`][]) @@ -943,6 +1973,12 @@ assigning it to `process.env`. ### DEP0105: decipher.finaltol + Type: Runtime @@ -952,6 +1988,12 @@ is recommended to use [`decipher.final()`][] instead. ### DEP0106: crypto.createCipher and crypto.createDecipher + Type: Documentation-only @@ -964,6 +2006,12 @@ initialization vectors. It is recommended to derive a key using ### DEP0107: tls.convertNPNProtocols() + Type: Runtime @@ -972,6 +2020,12 @@ core and obsoleted by the removal of NPN (Next Protocol Negotiation) support. ### DEP0108: zlib.bytesRead + Type: Documentation-only @@ -982,6 +2036,12 @@ expose values under these names. ### DEP0110: vm.Script cached data + Type: Documentation-only @@ -990,6 +2050,12 @@ The `produceCachedData` option is deprecated. Use ### DEP0111: process.binding() + Type: Documentation-only @@ -1033,6 +2099,8 @@ only. Use of `process.binding()` by userland code is unsupported. [`fs.exists(path, callback)`]: fs.html#fs_fs_exists_path_callback [`fs.lchmod(path, mode, callback)`]: fs.html#fs_fs_lchmod_path_mode_callback [`fs.lchmodSync(path, mode)`]: fs.html#fs_fs_lchmodsync_path_mode +[`fs.lchown(path, uid, gid, callback)`]: fs.html#fs_fs_lchown_path_uid_gid_callback +[`fs.lchownSync(path, uid, gid)`]: fs.html#fs_fs_lchownsync_path_uid_gid [`fs.read()`]: fs.html#fs_fs_read_fd_buffer_offset_length_position_callback [`fs.readSync()`]: fs.html#fs_fs_readsync_fd_buffer_offset_length_position [`fs.stat()`]: fs.html#fs_fs_stat_path_options_callback From 1cf6e3e284332dbb12afc72ef04caac1c564588a Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Wed, 12 Sep 2018 20:47:56 -0700 Subject: [PATCH 32/77] fs: fix promisified fs.readdir withFileTypes PR-URL: https://github.com/nodejs/node/pull/22832 Reviewed-By: Bryan English Reviewed-By: Rich Trott Reviewed-By: Richard Lau Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat --- lib/internal/fs/promises.js | 3 ++- test/parallel/test-fs-readdir-types.js | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 33a4fb6579ea66..31535a2b2b5378 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -311,7 +311,8 @@ async function readdir(path, options) { path = toPathIfFileURL(path); validatePath(path); const result = await binding.readdir(pathModule.toNamespacedPath(path), - options.encoding, !!options.withTypes, + options.encoding, + !!options.withFileTypes, kUsePromises); return options.withFileTypes ? getDirectoryEntriesPromise(path, result) : diff --git a/test/parallel/test-fs-readdir-types.js b/test/parallel/test-fs-readdir-types.js index 75452895cc178e..0faaeb00dadeb1 100644 --- a/test/parallel/test-fs-readdir-types.js +++ b/test/parallel/test-fs-readdir-types.js @@ -57,6 +57,14 @@ fs.readdir(readdirDir, { assertDirents(dirents); })); +// Check the promisified version +assert.doesNotReject(async () => { + const dirents = await fs.promises.readdir(readdirDir, { + withFileTypes: true + }); + assertDirents(dirents); +}); + // Check for correct types when the binding returns unknowns const UNKNOWN = constants.UV_DIRENT_UNKNOWN; const oldReaddir = binding.readdir; From 466ed2eecb5476366df04a12dace1d7134c9cecf Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 10 Sep 2018 12:06:45 +0200 Subject: [PATCH 33/77] src: fix `--prof-process` CLI argument handling Make sure that options after `--prof-process` are not treated as Node.js options. Fixes: https://github.com/nodejs/node/issues/22786 PR-URL: https://github.com/nodejs/node/pull/22790 Reviewed-By: Joyee Cheung Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Bryan English Reviewed-By: Trivikram Kamat --- lib/internal/bootstrap/node.js | 4 ++- src/node_options.cc | 2 ++ .../parallel/test-tick-processor-arguments.js | 34 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-tick-processor-arguments.js diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index db880514f9c64e..daa7fd5cbc0b79 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -642,9 +642,11 @@ for (const [ from, expansion ] of aliases) { let isAccepted = true; for (const to of expansion) { - if (!to.startsWith('-')) continue; + if (!to.startsWith('-') || to === '--') continue; const recursiveExpansion = aliases.get(to); if (recursiveExpansion) { + if (recursiveExpansion[0] === to) + recursiveExpansion.splice(0, 1); expansion.push(...recursiveExpansion); continue; } diff --git a/src/node_options.cc b/src/node_options.cc index 2cd0a0b45fc198..46f529cff2e961 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -108,6 +108,8 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--prof-process", "process V8 profiler output generated using --prof", &EnvironmentOptions::prof_process); + // Options after --prof-process are passed through to the prof processor. + AddAlias("--prof-process", { "--prof-process", "--" }); AddOption("--redirect-warnings", "write warnings to file instead of stderr", &EnvironmentOptions::redirect_warnings, diff --git a/test/parallel/test-tick-processor-arguments.js b/test/parallel/test-tick-processor-arguments.js new file mode 100644 index 00000000000000..606dbd03c8f6c4 --- /dev/null +++ b/test/parallel/test-tick-processor-arguments.js @@ -0,0 +1,34 @@ +'use strict'; +const common = require('../common'); +const tmpdir = require('../common/tmpdir'); +const fs = require('fs'); +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +if (!common.isMainThread) + common.skip('chdir not available in workers'); +if (!common.enoughTestMem) + common.skip('skipped due to memory requirements'); +if (common.isAIX) + common.skip('does not work on AIX'); + +tmpdir.refresh(); +process.chdir(tmpdir.path); + +// Generate log file. +spawnSync(process.execPath, [ '--prof', '-p', '42' ]); + +const logfile = fs.readdirSync('.').filter((name) => name.endsWith('.log'))[0]; +assert(logfile); + +// Make sure that the --preprocess argument is passed through correctly, +// as an example flag listed in deps/v8/tools/tickprocessor.js. +// Any of the other flags there should work for this test too, if --preprocess +// is ever removed. +const { stdout } = spawnSync( + process.execPath, + [ '--prof-process', '--preprocess', logfile ], + { encoding: 'utf8' }); + +// Make sure that the result is valid JSON. +JSON.parse(stdout); From 572d01c25ef7f67d2bfc182d3439b0b2a025d33e Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 6 Sep 2018 22:31:07 +0200 Subject: [PATCH 34/77] tracing: remove shutdown-on-signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This feature cannot be reasonably implemented this way without inherently being susceptible to race conditions that lead to hangs, crashes, etc. What’s more, implementing this for some signals only (and it can only be implemented for some signals at all) may lead to the impression that it is a guaranteed feature, when really consumers of the tracing output *need* to be able to handle abrupt ends meaningfully. Fixes: https://github.com/nodejs/node/issues/14802 Fixes: https://github.com/nodejs/node/issues/22528 PR-URL: https://github.com/nodejs/node/pull/22734 Reviewed-By: James M Snell Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Ruben Bridgewater Reviewed-By: Matteo Collina --- src/node.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index d38a014e42e087..fe6293f62a2adc 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2052,7 +2052,6 @@ void SetupProcessObject(Environment* env, void SignalExit(int signo) { uv_tty_reset_mode(); - v8_platform.StopTracingAgent(); #ifdef __FreeBSD__ // FreeBSD has a nasty bug, see RegisterSignalHandler for details struct sigaction sa; From 2f5fad00a19ee7e4d9ae30a2249cac2296cfaf74 Mon Sep 17 00:00:00 2001 From: William Chargin Date: Sat, 11 Aug 2018 11:23:42 -0700 Subject: [PATCH 35/77] path: remove unnecessary if statement There is an `if`-statement in `normalizeString` (a helper function for `path.normalize`) whose `else`-branch is never taken. This patch removes it. PR-URL: https://github.com/nodejs/node/pull/22273 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- lib/path.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/path.js b/lib/path.js index 90129f1f52989e..c8d92f14af04de 100644 --- a/lib/path.js +++ b/lib/path.js @@ -77,18 +77,16 @@ function normalizeString(path, allowAboveRoot, separator, isPathSeparator) { res.charCodeAt(res.length - 2) !== CHAR_DOT) { if (res.length > 2) { const lastSlashIndex = res.lastIndexOf(separator); - if (lastSlashIndex !== res.length - 1) { - if (lastSlashIndex === -1) { - res = ''; - lastSegmentLength = 0; - } else { - res = res.slice(0, lastSlashIndex); - lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); - } - lastSlash = i; - dots = 0; - continue; + if (lastSlashIndex === -1) { + res = ''; + lastSegmentLength = 0; + } else { + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); } + lastSlash = i; + dots = 0; + continue; } else if (res.length === 2 || res.length === 1) { res = ''; lastSegmentLength = 0; From 75422abf00a1c495d984bb532d4aea51a80f2762 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 15 Sep 2018 17:09:05 -0700 Subject: [PATCH 36/77] tools: update ESLint to 5.6.0 Update ESLint to 5.6.0. PR-URL: https://github.com/nodejs/node/pull/22882 Reviewed-By: Vse Mozhet Byt Reviewed-By: George Adams Reviewed-By: Ruben Bridgewater Reviewed-By: Trivikram Kamat --- .../eslint/lib/rules/func-names.js | 97 +- .../eslint/lib/rules/no-constant-condition.js | 2 + .../eslint/node_modules/acorn/AUTHORS | 2 + .../eslint/node_modules/acorn/README.md | 2 +- .../node_modules/acorn/dist/acorn.es.js | 5 +- .../eslint/node_modules/acorn/dist/acorn.js | 5 +- .../eslint/node_modules/acorn/package.json | 8 +- .../eslint/node_modules/color-name/README.md | 6 +- .../eslint/node_modules/color-name/index.js | 12 +- .../eslint/node_modules/debug/.coveralls.yml | 1 - .../eslint/node_modules/debug/Makefile | 58 -- .../eslint/node_modules/debug/README.md | 73 +- .../eslint/node_modules/debug/dist/debug.js | 885 ++++++++++++++++++ .../eslint/node_modules/debug/karma.conf.js | 70 -- .../eslint/node_modules/debug/package.json | 26 +- .../eslint/node_modules/debug/src/browser.js | 164 ++-- .../eslint/node_modules/debug/src/common.js | 248 +++++ .../eslint/node_modules/debug/src/debug.js | 225 ----- .../eslint/node_modules/debug/src/index.js | 7 +- .../eslint/node_modules/debug/src/node.js | 133 ++- .../eslint/node_modules/lodash/README.md | 6 +- .../node_modules/lodash/_baseMergeDeep.js | 2 +- .../node_modules/lodash/_hasUnicodeWord.js | 2 +- .../eslint/node_modules/lodash/_safeGet.js | 8 +- .../eslint/node_modules/lodash/core.js | 2 +- .../eslint/node_modules/lodash/core.min.js | 4 +- .../node_modules/lodash/fp/_baseConvert.js | 24 +- .../eslint/node_modules/lodash/fp/_mapping.js | 10 - .../eslint/node_modules/lodash/lodash.js | 36 +- .../eslint/node_modules/lodash/lodash.min.js | 256 ++--- .../eslint/node_modules/lodash/package.json | 2 +- .../eslint/node_modules/ms/index.js | 46 +- .../eslint/node_modules/ms/package.json | 12 +- .../eslint/node_modules/ms/readme.md | 25 +- .../eslint/node_modules/regexpp/index.d.ts | 12 +- tools/node_modules/eslint/package.json | 2 +- 36 files changed, 1692 insertions(+), 786 deletions(-) delete mode 100644 tools/node_modules/eslint/node_modules/debug/.coveralls.yml delete mode 100644 tools/node_modules/eslint/node_modules/debug/Makefile create mode 100644 tools/node_modules/eslint/node_modules/debug/dist/debug.js delete mode 100644 tools/node_modules/eslint/node_modules/debug/karma.conf.js create mode 100644 tools/node_modules/eslint/node_modules/debug/src/common.js delete mode 100644 tools/node_modules/eslint/node_modules/debug/src/debug.js diff --git a/tools/node_modules/eslint/lib/rules/func-names.js b/tools/node_modules/eslint/lib/rules/func-names.js index a4f5d105d8923a..31f302918116e6 100644 --- a/tools/node_modules/eslint/lib/rules/func-names.js +++ b/tools/node_modules/eslint/lib/rules/func-names.js @@ -33,11 +33,31 @@ module.exports = { url: "https://eslint.org/docs/rules/func-names" }, - schema: [ - { - enum: ["always", "as-needed", "never"] - } - ], + schema: { + definitions: { + value: { + enum: [ + "always", + "as-needed", + "never" + ] + } + }, + items: [ + { + $ref: "#/definitions/value" + }, + { + type: "object", + properties: { + generators: { + $ref: "#/definitions/value" + } + }, + additionalProperties: false + } + ] + }, messages: { unnamed: "Unexpected unnamed {{name}}.", named: "Unexpected named {{name}}." @@ -45,8 +65,23 @@ module.exports = { }, create(context) { - const never = context.options[0] === "never"; - const asNeeded = context.options[0] === "as-needed"; + + /** + * Returns the config option for the given node. + * @param {ASTNode} node - A node to get the config for. + * @returns {string} The config option. + */ + function getConfigForNode(node) { + if ( + node.generator && + context.options.length > 1 && + context.options[1].generators + ) { + return context.options[1].generators; + } + + return context.options[0] || "always"; + } /** * Determines whether the current FunctionExpression node is a get, set, or @@ -83,6 +118,32 @@ module.exports = { (parent.type === "AssignmentPattern" && parent.right === node); } + /** + * Reports that an unnamed function should be named + * @param {ASTNode} node - The node to report in the event of an error. + * @returns {void} + */ + function reportUnexpectedUnnamedFunction(node) { + context.report({ + node, + messageId: "unnamed", + data: { name: astUtils.getFunctionNameWithKind(node) } + }); + } + + /** + * Reports that a named function should be unnamed + * @param {ASTNode} node - The node to report in the event of an error. + * @returns {void} + */ + function reportUnexpectedNamedFunction(node) { + context.report({ + node, + messageId: "named", + data: { name: astUtils.getFunctionNameWithKind(node) } + }); + } + return { "FunctionExpression:exit"(node) { @@ -94,23 +155,19 @@ module.exports = { } const hasName = Boolean(node.id && node.id.name); - const name = astUtils.getFunctionNameWithKind(node); + const config = getConfigForNode(node); - if (never) { + if (config === "never") { if (hasName) { - context.report({ - node, - messageId: "named", - data: { name } - }); + reportUnexpectedNamedFunction(node); + } + } else if (config === "as-needed") { + if (!hasName && !hasInferredName(node)) { + reportUnexpectedUnnamedFunction(node); } } else { - if (!hasName && (asNeeded ? !hasInferredName(node) : !isObjectOrClassMethod(node))) { - context.report({ - node, - messageId: "unnamed", - data: { name } - }); + if (!hasName && !isObjectOrClassMethod(node)) { + reportUnexpectedUnnamedFunction(node); } } } diff --git a/tools/node_modules/eslint/lib/rules/no-constant-condition.js b/tools/node_modules/eslint/lib/rules/no-constant-condition.js index 724da974127f51..48b1fbf689f966 100644 --- a/tools/node_modules/eslint/lib/rules/no-constant-condition.js +++ b/tools/node_modules/eslint/lib/rules/no-constant-condition.js @@ -207,6 +207,8 @@ module.exports = { "ForStatement:exit": checkConstantConditionLoopInSet, FunctionDeclaration: enterFunction, "FunctionDeclaration:exit": exitFunction, + FunctionExpression: enterFunction, + "FunctionExpression:exit": exitFunction, YieldExpression: () => loopsInCurrentScope.clear() }; diff --git a/tools/node_modules/eslint/node_modules/acorn/AUTHORS b/tools/node_modules/eslint/node_modules/acorn/AUTHORS index b605ab4fbc9cd9..c5ac22cbd7c6ba 100644 --- a/tools/node_modules/eslint/node_modules/acorn/AUTHORS +++ b/tools/node_modules/eslint/node_modules/acorn/AUTHORS @@ -41,6 +41,7 @@ Kevin Irish Kevin Kwok krator laosb +luckyzeng Marek Marijn Haverbeke Martin Carlberg @@ -63,6 +64,7 @@ PlNG Prayag Verma ReadmeCritic r-e-d +Renée Kooi Richard Gibson Rich Harris Sebastian McKenzie diff --git a/tools/node_modules/eslint/node_modules/acorn/README.md b/tools/node_modules/eslint/node_modules/acorn/README.md index 956cd56e2495c3..de53f513f49e2f 100644 --- a/tools/node_modules/eslint/node_modules/acorn/README.md +++ b/tools/node_modules/eslint/node_modules/acorn/README.md @@ -464,4 +464,4 @@ looseParser.extend("readToken", function(nextMethod) { - [`acorn5-object-spread`](https://github.com/adrianheine/acorn5-object-spread): Parse [Object Rest/Spread Properties proposal](https://github.com/tc39/proposal-object-rest-spread) - [`acorn-object-rest-spread`](https://github.com/victor-homyakov/acorn-object-rest-spread): Parse [Object Rest/Spread Properties proposal](https://github.com/tc39/proposal-object-rest-spread) - [`acorn-es7`](https://github.com/angelozerr/acorn-es7): Parse [decorator syntax proposal](https://github.com/wycats/javascript-decorators) - - [`acorn-static-class-property-initializer`](https://github.com/victor-homyakov/acorn-static-class-property-initializer): Partial support for static class properties from [ES Class Fields & Static Properties Proposal](https://github.com/tc39/proposal-class-public-fields) to support static property initializers in [React components written as ES6+ classes](https://babeljs.io/blog/2015/06/07/react-on-es6-plus) + - [`acorn-static-class-property-initializer`](https://github.com/victor-homyakov/acorn-static-class-property-initializer): Partial support for static class properties from [ES Class Fields & Static Properties Proposal](https://github.com/tc39/proposal-class-public-fields) to support static property initializers in [React components written as ES6+ classes](https://babeljs.io/blog/2015/07/07/react-on-es6-plus) diff --git a/tools/node_modules/eslint/node_modules/acorn/dist/acorn.es.js b/tools/node_modules/eslint/node_modules/acorn/dist/acorn.es.js index 46b8c61947df5d..332c3392d0895f 100644 --- a/tools/node_modules/eslint/node_modules/acorn/dist/acorn.es.js +++ b/tools/node_modules/eslint/node_modules/acorn/dist/acorn.es.js @@ -2341,6 +2341,7 @@ pp$3.parseTemplate = function(ref) { var curElt = this.parseTemplateElement({isTagged: isTagged}); node.quasis = [curElt]; while (!curElt.tail) { + if (this$1.type === types.eof) { this$1.raise(this$1.pos, "Unterminated template literal"); } this$1.expect(types.dollarBraceL); node.expressions.push(this$1.parseExpression()); this$1.expect(types.braceR); @@ -3020,7 +3021,7 @@ types.star.updateContext = function(prevType) { types.name.updateContext = function(prevType) { var allowed = false; - if (this.options.ecmaVersion >= 6) { + if (this.options.ecmaVersion >= 6 && prevType !== types.dot) { if (this.value === "of" && !this.exprAllowed || this.value === "yield" && this.inGeneratorContext()) { allowed = true; } @@ -5268,7 +5269,7 @@ pp$8.readWord = function() { // [dammit]: acorn_loose.js // [walk]: util/walk.js -var version = "5.7.2"; +var version = "5.7.3"; // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and diff --git a/tools/node_modules/eslint/node_modules/acorn/dist/acorn.js b/tools/node_modules/eslint/node_modules/acorn/dist/acorn.js index bab34a2e8d4a10..dada6a37a56339 100644 --- a/tools/node_modules/eslint/node_modules/acorn/dist/acorn.js +++ b/tools/node_modules/eslint/node_modules/acorn/dist/acorn.js @@ -2347,6 +2347,7 @@ pp$3.parseTemplate = function(ref) { var curElt = this.parseTemplateElement({isTagged: isTagged}); node.quasis = [curElt]; while (!curElt.tail) { + if (this$1.type === types.eof) { this$1.raise(this$1.pos, "Unterminated template literal"); } this$1.expect(types.dollarBraceL); node.expressions.push(this$1.parseExpression()); this$1.expect(types.braceR); @@ -3026,7 +3027,7 @@ types.star.updateContext = function(prevType) { types.name.updateContext = function(prevType) { var allowed = false; - if (this.options.ecmaVersion >= 6) { + if (this.options.ecmaVersion >= 6 && prevType !== types.dot) { if (this.value === "of" && !this.exprAllowed || this.value === "yield" && this.inGeneratorContext()) { allowed = true; } @@ -5274,7 +5275,7 @@ pp$8.readWord = function() { // [dammit]: acorn_loose.js // [walk]: util/walk.js -var version = "5.7.2"; +var version = "5.7.3"; // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and diff --git a/tools/node_modules/eslint/node_modules/acorn/package.json b/tools/node_modules/eslint/node_modules/acorn/package.json index d3e07d86c6e8ce..5e17c40f378c86 100644 --- a/tools/node_modules/eslint/node_modules/acorn/package.json +++ b/tools/node_modules/eslint/node_modules/acorn/package.json @@ -133,6 +133,9 @@ { "name": "laosb" }, + { + "name": "luckyzeng" + }, { "name": "Marek" }, @@ -199,6 +202,9 @@ { "name": "r-e-d" }, + { + "name": "Renée Kooi" + }, { "name": "Richard Gibson" }, @@ -291,5 +297,5 @@ "test": "node test/run.js && node test/lint.js", "test:test262": "node bin/run_test262.js" }, - "version": "5.7.2" + "version": "5.7.3" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/color-name/README.md b/tools/node_modules/eslint/node_modules/color-name/README.md index 8126b969ab00ec..3611a6b523fe85 100644 --- a/tools/node_modules/eslint/node_modules/color-name/README.md +++ b/tools/node_modules/eslint/node_modules/color-name/README.md @@ -2,9 +2,9 @@ A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-col [![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/) - -```js -var colors = require('color-name'); + +```js +var colors = require('color-name'); colors.red //[255,0,0] ``` diff --git a/tools/node_modules/eslint/node_modules/color-name/index.js b/tools/node_modules/eslint/node_modules/color-name/index.js index 21dbc8c5ce0c4b..e91e40f6b2a577 100644 --- a/tools/node_modules/eslint/node_modules/color-name/index.js +++ b/tools/node_modules/eslint/node_modules/color-name/index.js @@ -3,9 +3,9 @@ module.exports = { "aliceblue": [240, 248, 255], "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], "beige": [245, 245, 220], "bisque": [255, 228, 196], "black": [0, 0, 0], @@ -143,9 +143,9 @@ module.exports = { "thistle": [216, 191, 216], "tomato": [255, 99, 71], "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], "whitesmoke": [245, 245, 245], "yellow": [255, 255, 0], "yellowgreen": [154, 205, 50] diff --git a/tools/node_modules/eslint/node_modules/debug/.coveralls.yml b/tools/node_modules/eslint/node_modules/debug/.coveralls.yml deleted file mode 100644 index 20a70685817913..00000000000000 --- a/tools/node_modules/eslint/node_modules/debug/.coveralls.yml +++ /dev/null @@ -1 +0,0 @@ -repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve diff --git a/tools/node_modules/eslint/node_modules/debug/Makefile b/tools/node_modules/eslint/node_modules/debug/Makefile deleted file mode 100644 index 3ddd1360e6a95e..00000000000000 --- a/tools/node_modules/eslint/node_modules/debug/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 -THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) -THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) - -# BIN directory -BIN := $(THIS_DIR)/node_modules/.bin - -# Path -PATH := node_modules/.bin:$(PATH) -SHELL := /bin/bash - -# applications -NODE ?= $(shell which node) -YARN ?= $(shell which yarn) -PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm)) -BROWSERIFY ?= $(NODE) $(BIN)/browserify - -install: node_modules - -browser: dist/debug.js - -node_modules: package.json - @NODE_ENV= $(PKG) install - @touch node_modules - -dist/debug.js: src/*.js node_modules - @mkdir -p dist - @$(BROWSERIFY) \ - --standalone debug \ - . > dist/debug.js - -lint: - @eslint *.js src/*.js - -test-node: - @istanbul cover node_modules/mocha/bin/_mocha -- test/**.js - @cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js - -test-browser: - @$(MAKE) browser - @karma start --single-run - -test-all: - @concurrently \ - "make test-node" \ - "make test-browser" - -test: - @if [ "x$(BROWSER)" = "x" ]; then \ - $(MAKE) test-node; \ - else \ - $(MAKE) test-browser; \ - fi - -clean: - rimraf dist coverage - -.PHONY: browser install clean lint test test-all test-node test-browser diff --git a/tools/node_modules/eslint/node_modules/debug/README.md b/tools/node_modules/eslint/node_modules/debug/README.md index 8e754d17b164ad..b6e88368a0651c 100644 --- a/tools/node_modules/eslint/node_modules/debug/README.md +++ b/tools/node_modules/eslint/node_modules/debug/README.md @@ -70,7 +70,9 @@ Here are some examples: screen shot 2017-08-08 at 12 53 38 pm screen shot 2017-08-08 at 12 53 25 pm -#### Windows note +#### Windows command prompt notes + +##### CMD On Windows the environment variable is set using the `set` command. @@ -78,14 +80,32 @@ On Windows the environment variable is set using the `set` command. set DEBUG=*,-not_this ``` -Note that PowerShell uses different syntax to set environment variables. +Example: + +```cmd +set DEBUG=* & node app.js +``` + +##### PowerShell (VS Code default) + +PowerShell uses different syntax to set environment variables. ```cmd $env:DEBUG = "*,-not_this" ``` +Example: + +```cmd +$env:DEBUG='app';node app.js +``` + Then, run the program to be debugged as usual. +npm script example: +```js + "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js", +``` ## Namespace Colors @@ -248,6 +268,55 @@ error('now goes to stdout via console.info'); log('still goes to stdout, but via console.info now'); ``` +## Extend +You can simply extend debugger +```js +const log = require('debug')('auth'); + +//creates new debug instance with extended namespace +const logSign = log.extend('sign'); +const logLogin = log.extend('login'); + +log('hello'); // auth hello +logSign('hello'); //auth:sign hello +logLogin('hello'); //auth:login hello +``` + +## Set dynamically + +You can also enable debug dynamically by calling the `enable()` method : + +```js +let debug = require('debug'); + +console.log(1, debug.enabled('test')); + +debug.enable('test'); +console.log(2, debug.enabled('test')); + +debug.disable(); +console.log(3, debug.enabled('test')); + +``` + +print : +``` +1 false +2 true +3 false +``` + +Usage : +`enable(namespaces)` +`namespaces` can include modes separated by a colon and wildcards. + +Note that calling `enable()` completely overrides previously set DEBUG variable : + +``` +$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))' +=> false +``` + ## Checking whether a debug target is enabled After you've created a debug instance, you can determine whether or not it is diff --git a/tools/node_modules/eslint/node_modules/debug/dist/debug.js b/tools/node_modules/eslint/node_modules/debug/dist/debug.js new file mode 100644 index 00000000000000..33951e1642fa80 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/debug/dist/debug.js @@ -0,0 +1,885 @@ +"use strict"; + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +(function (f) { + if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object" && typeof module !== "undefined") { + module.exports = f(); + } else if (typeof define === "function" && define.amd) { + define([], f); + } else { + var g; + + if (typeof window !== "undefined") { + g = window; + } else if (typeof global !== "undefined") { + g = global; + } else if (typeof self !== "undefined") { + g = self; + } else { + g = this; + } + + g.debug = f(); + } +})(function () { + var define, module, exports; + return function () { + function r(e, n, t) { + function o(i, f) { + if (!n[i]) { + if (!e[i]) { + var c = "function" == typeof require && require; + if (!f && c) return c(i, !0); + if (u) return u(i, !0); + var a = new Error("Cannot find module '" + i + "'"); + throw a.code = "MODULE_NOT_FOUND", a; + } + + var p = n[i] = { + exports: {} + }; + e[i][0].call(p.exports, function (r) { + var n = e[i][1][r]; + return o(n || r); + }, p, p.exports, r, e, n, t); + } + + return n[i].exports; + } + + for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) { + o(t[i]); + } + + return o; + } + + return r; + }()({ + 1: [function (require, module, exports) { + /** + * Helpers. + */ + var s = 1000; + var m = s * 60; + var h = m * 60; + var d = h * 24; + var w = d * 7; + var y = d * 365.25; + /** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + + module.exports = function (val, options) { + options = options || {}; + + var type = _typeof(val); + + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + + throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val)); + }; + /** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + + + function parse(str) { + str = String(str); + + if (str.length > 100) { + return; + } + + var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str); + + if (!match) { + return; + } + + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + + case 'weeks': + case 'week': + case 'w': + return n * w; + + case 'days': + case 'day': + case 'd': + return n * d; + + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + + default: + return undefined; + } + } + /** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + + function fmtShort(ms) { + var msAbs = Math.abs(ms); + + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + + return ms + 'ms'; + } + /** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + + function fmtLong(ms) { + var msAbs = Math.abs(ms); + + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + + return ms + ' ms'; + } + /** + * Pluralization helper. + */ + + + function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); + } + }, {}], + 2: [function (require, module, exports) { + // shim for using process in browser + var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + + function defaultClearTimeout() { + throw new Error('clearTimeout has not been defined'); + } + + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + })(); + + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } // if setTimeout wasn't available but was latter defined + + + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch (e) { + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch (e) { + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + } + + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } // if clearTimeout wasn't available but was latter defined + + + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e) { + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e) { + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + } + + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + + draining = false; + + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + + var timeout = runTimeout(cleanUpNextTick); + draining = true; + var len = queue.length; + + while (len) { + currentQueue = queue; + queue = []; + + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + + queueIndex = -1; + len = queue.length; + } + + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + + queue.push(new Item(fun, args)); + + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; // v8 likes predictible objects + + + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + process.prependListener = noop; + process.prependOnceListener = noop; + + process.listeners = function (name) { + return []; + }; + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { + return '/'; + }; + + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + + process.umask = function () { + return 0; + }; + }, {}], + 3: [function (require, module, exports) { + /** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require('ms'); + Object.keys(env).forEach(function (key) { + createDebug[key] = env[key]; + }); + /** + * Active `debug` instances. + */ + + createDebug.instances = []; + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + + createDebug.formatters = {}; + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + + function selectColor(namespace) { + var hash = 0; + + for (var i = 0; i < namespace.length; i++) { + hash = (hash << 5) - hash + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + + createDebug.selectColor = selectColor; + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + + function createDebug(namespace) { + var prevTime; + + function debug() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + // Disabled? + if (!debug.enabled) { + return; + } + + var self = debug; // Set `diff` timestamp + + var curr = Number(new Date()); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } // Apply any `formatters` transformations + + + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return match; + } + + index++; + var formatter = createDebug.formatters[format]; + + if (typeof formatter === 'function') { + var val = args[index]; + match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format` + + args.splice(index, 1); + index--; + } + + return match; + }); // Apply env-specific formatting (colors, etc.) + + createDebug.formatArgs.call(self, args); + var logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = createDebug.enabled(namespace); + debug.useColors = createDebug.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + debug.extend = extend; // Debug.formatArgs = formatArgs; + // debug.rawLog = rawLog; + // env-specific initialization logic for debug instances + + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + createDebug.instances.push(debug); + return debug; + } + + function destroy() { + var index = createDebug.instances.indexOf(this); + + if (index !== -1) { + createDebug.instances.splice(index, 1); + return true; + } + + return false; + } + + function extend(namespace, delimiter) { + return createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + } + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + + + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.names = []; + createDebug.skips = []; + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < createDebug.instances.length; i++) { + var instance = createDebug.instances[i]; + instance.enabled = createDebug.enabled(instance.namespace); + } + } + /** + * Disable debug output. + * + * @api public + */ + + + function disable() { + createDebug.enable(''); + } + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + + + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + var i; + var len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + + + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + + return val; + } + + createDebug.enable(createDebug.load()); + return createDebug; + } + + module.exports = setup; + }, { + "ms": 1 + }], + 4: [function (require, module, exports) { + (function (process) { + /* eslint-env browser */ + + /** + * This is the web browser implementation of `debug()`. + */ + exports.log = log; + exports.formatArgs = formatArgs; + exports.save = save; + exports.load = load; + exports.useColors = useColors; + exports.storage = localstorage(); + /** + * Colors. + */ + + exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33']; + /** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + // eslint-disable-next-line complexity + + function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } // Internet Explorer and Edge do not support colors. + + + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + + + return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773 + typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker + typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/); + } + /** + * Colorize log arguments if enabled. + * + * @api public + */ + + + function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function (match) { + if (match === '%%') { + return; + } + + index++; + + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + args.splice(lastC, 0, c); + } + /** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + + + function log() { + var _console; + + // This hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments); + } + /** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + + + function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) {// Swallow + // XXX (@Qix-) should we be logging these? + } + } + /** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + + + function load() { + var r; + + try { + r = exports.storage.getItem('debug'); + } catch (error) {} // Swallow + // XXX (@Qix-) should we be logging these? + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + + + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; + } + /** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + + + function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) {// Swallow + // XXX (@Qix-) should we be logging these? + } + } + + module.exports = require('./common')(exports); + var formatters = module.exports.formatters; + /** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + + formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } + }; + }).call(this, require('_process')); + }, { + "./common": 3, + "_process": 2 + }] + }, {}, [4])(4); +}); diff --git a/tools/node_modules/eslint/node_modules/debug/karma.conf.js b/tools/node_modules/eslint/node_modules/debug/karma.conf.js deleted file mode 100644 index 103a82d15bd72b..00000000000000 --- a/tools/node_modules/eslint/node_modules/debug/karma.conf.js +++ /dev/null @@ -1,70 +0,0 @@ -// Karma configuration -// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC) - -module.exports = function(config) { - config.set({ - - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: '', - - - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['mocha', 'chai', 'sinon'], - - - // list of files / patterns to load in the browser - files: [ - 'dist/debug.js', - 'test/*spec.js' - ], - - - // list of files to exclude - exclude: [ - 'src/node.js' - ], - - - // preprocess matching files before serving them to the browser - // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: { - }, - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['progress'], - - - // web server port - port: 9876, - - - // enable / disable colors in the output (reporters and logs) - colors: true, - - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - logLevel: config.LOG_INFO, - - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['PhantomJS'], - - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: false, - - // Concurrency level - // how many browser should be started simultaneous - concurrency: Infinity - }) -} diff --git a/tools/node_modules/eslint/node_modules/debug/package.json b/tools/node_modules/eslint/node_modules/debug/package.json index 5314944bf546ee..a3599c3158dfa6 100644 --- a/tools/node_modules/eslint/node_modules/debug/package.json +++ b/tools/node_modules/eslint/node_modules/debug/package.json @@ -20,28 +20,35 @@ } ], "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" }, "deprecated": false, "description": "small debugging utility", "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/preset-env": "^7.0.0", "browserify": "14.4.0", "chai": "^3.5.0", "concurrently": "^3.1.0", - "coveralls": "^2.11.15", - "eslint": "^3.12.1", + "coveralls": "^3.0.2", "istanbul": "^0.4.5", - "karma": "^1.3.0", + "karma": "^3.0.0", "karma-chai": "^0.1.0", "karma-mocha": "^1.3.0", "karma-phantomjs-launcher": "^1.0.2", - "karma-sinon": "^1.0.5", - "mocha": "^3.2.0", + "mocha": "^5.2.0", "mocha-lcov-reporter": "^1.2.0", "rimraf": "^2.5.4", - "sinon": "^1.17.6", - "sinon-chai": "^2.8.0" + "xo": "^0.23.0" }, + "files": [ + "src", + "node.js", + "dist/debug.js", + "LICENSE", + "README.md" + ], "homepage": "https://github.com/visionmedia/debug#readme", "keywords": [ "debug", @@ -55,5 +62,6 @@ "type": "git", "url": "git://github.com/visionmedia/debug.git" }, - "version": "3.1.0" + "unpkg": "./dist/debug.js", + "version": "3.2.5" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/debug/src/browser.js b/tools/node_modules/eslint/node_modules/debug/src/browser.js index f5149ff5296aa1..b7d4f15ce478a3 100644 --- a/tools/node_modules/eslint/node_modules/debug/src/browser.js +++ b/tools/node_modules/eslint/node_modules/debug/src/browser.js @@ -1,38 +1,23 @@ +"use strict"; + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +/* eslint-env browser */ + /** * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. */ - -exports = module.exports = require('./debug'); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; exports.load = load; exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - +exports.storage = localstorage(); /** * Colors. */ -exports.colors = [ - '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', - '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', - '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', - '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', - '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', - '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', - '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', - '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', - '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', - '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', - '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' -]; - +exports.colors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33']; /** * Currently only WebKit-based Web Inspectors, Firefox >= v31, * and the Firebug extension (any Firefox version) are known @@ -40,84 +25,65 @@ exports.colors = [ * * TODO: add a `localStorage` variable to explicitly enable/disable colors */ +// eslint-disable-next-line complexity function useColors() { // NB: In an Electron preload script, document will be defined but not fully // initialized. Since we know we're in Chrome, we'll just detect this case // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { return true; - } + } // Internet Explorer and Edge do not support colors. + - // Internet Explorer and Edge do not support colors. if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { return false; - } - - // is webkit? http://stackoverflow.com/a/16459606/376773 + } // Is webkit? http://stackoverflow.com/a/16459606/376773 // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; - } -}; + return typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773 + typeof window !== 'undefined' && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker + typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/); +} /** * Colorize log arguments if enabled. * * @api public */ -function formatArgs(args) { - var useColors = this.useColors; - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff); - if (!useColors) return; + if (!this.useColors) { + return; + } var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - - // the final "%c" is somewhat tricky, because there could be other + args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other // arguments passed either before or after the %c, so we need to // figure out the correct index to insert the CSS into + var index = 0; var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; + args[0].replace(/%[a-zA-Z%]/g, function (match) { + if (match === '%%') { + return; + } + index++; - if ('%c' === match) { - // we only are interested in the *last* %c + + if (match === '%c') { + // We only are interested in the *last* %c // (the user may have provided their own) lastC = index; } }); - args.splice(lastC, 0, c); } - /** * Invokes `console.log()` when available. * No-op when `console.log` is not a "function". @@ -125,14 +91,14 @@ function formatArgs(args) { * @api public */ + function log() { - // this hackery is required for IE8/9, where + var _console; + + // This hackery is required for IE8/9, where // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); + return (typeof console === "undefined" ? "undefined" : _typeof(console)) === 'object' && console.log && (_console = console).log.apply(_console, arguments); } - /** * Save `namespaces`. * @@ -140,16 +106,18 @@ function log() { * @api private */ + function save(namespaces) { try { - if (null == namespaces) { - exports.storage.removeItem('debug'); + if (namespaces) { + exports.storage.setItem('debug', namespaces); } else { - exports.storage.debug = namespaces; + exports.storage.removeItem('debug'); } - } catch(e) {} + } catch (error) {// Swallow + // XXX (@Qix-) should we be logging these? + } } - /** * Load `namespaces`. * @@ -157,26 +125,23 @@ function save(namespaces) { * @api private */ + function load() { var r; - try { - r = exports.storage.debug; - } catch(e) {} + try { + r = exports.storage.getItem('debug'); + } catch (error) {} // Swallow + // XXX (@Qix-) should we be logging these? // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + + if (!r && typeof process !== 'undefined' && 'env' in process) { r = process.env.DEBUG; } return r; } - -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - /** * Localstorage attempts to return the localstorage. * @@ -188,8 +153,27 @@ exports.enable(load()); * @api private */ + function localstorage() { try { - return window.localStorage; - } catch (e) {} + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) {// Swallow + // XXX (@Qix-) should we be logging these? + } } + +module.exports = require('./common')(exports); +var formatters = module.exports.formatters; +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; diff --git a/tools/node_modules/eslint/node_modules/debug/src/common.js b/tools/node_modules/eslint/node_modules/debug/src/common.js new file mode 100644 index 00000000000000..a153ed532ad3ad --- /dev/null +++ b/tools/node_modules/eslint/node_modules/debug/src/common.js @@ -0,0 +1,248 @@ +"use strict"; + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require('ms'); + Object.keys(env).forEach(function (key) { + createDebug[key] = env[key]; + }); + /** + * Active `debug` instances. + */ + + createDebug.instances = []; + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + + createDebug.formatters = {}; + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + + function selectColor(namespace) { + var hash = 0; + + for (var i = 0; i < namespace.length; i++) { + hash = (hash << 5) - hash + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + + createDebug.selectColor = selectColor; + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + + function createDebug(namespace) { + var prevTime; + + function debug() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + // Disabled? + if (!debug.enabled) { + return; + } + + var self = debug; // Set `diff` timestamp + + var curr = Number(new Date()); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } // Apply any `formatters` transformations + + + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function (match, format) { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return match; + } + + index++; + var formatter = createDebug.formatters[format]; + + if (typeof formatter === 'function') { + var val = args[index]; + match = formatter.call(self, val); // Now we need to remove `args[index]` since it's inlined in the `format` + + args.splice(index, 1); + index--; + } + + return match; + }); // Apply env-specific formatting (colors, etc.) + + createDebug.formatArgs.call(self, args); + var logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = createDebug.enabled(namespace); + debug.useColors = createDebug.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + debug.extend = extend; // Debug.formatArgs = formatArgs; + // debug.rawLog = rawLog; + // env-specific initialization logic for debug instances + + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + createDebug.instances.push(debug); + return debug; + } + + function destroy() { + var index = createDebug.instances.indexOf(this); + + if (index !== -1) { + createDebug.instances.splice(index, 1); + return true; + } + + return false; + } + + function extend(namespace, delimiter) { + return createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + } + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + + + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.names = []; + createDebug.skips = []; + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < createDebug.instances.length; i++) { + var instance = createDebug.instances[i]; + instance.enabled = createDebug.enabled(instance.namespace); + } + } + /** + * Disable debug output. + * + * @api public + */ + + + function disable() { + createDebug.enable(''); + } + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + + + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + var i; + var len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + + + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + + return val; + } + + createDebug.enable(createDebug.load()); + return createDebug; +} + +module.exports = setup; diff --git a/tools/node_modules/eslint/node_modules/debug/src/debug.js b/tools/node_modules/eslint/node_modules/debug/src/debug.js deleted file mode 100644 index 77e6384a339760..00000000000000 --- a/tools/node_modules/eslint/node_modules/debug/src/debug.js +++ /dev/null @@ -1,225 +0,0 @@ - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = require('ms'); - -/** - * Active `debug` instances. - */ -exports.instances = []; - -/** - * The currently active debug mode names, and names to skip. - */ - -exports.names = []; -exports.skips = []; - -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; - -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ - -function selectColor(namespace) { - var hash = 0, i; - - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return exports.colors[Math.abs(hash) % exports.colors.length]; -} - -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - -function createDebug(namespace) { - - var prevTime; - - function debug() { - // disabled? - if (!debug.enabled) return; - - var self = debug; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - debug.destroy = destroy; - - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } - - exports.instances.push(debug); - - return debug; -} - -function destroy () { - var index = exports.instances.indexOf(this); - if (index !== -1) { - exports.instances.splice(index, 1); - return true; - } else { - return false; - } -} - -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - -function enable(namespaces) { - exports.save(namespaces); - - exports.names = []; - exports.skips = []; - - var i; - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - - for (i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } - - for (i = 0; i < exports.instances.length; i++) { - var instance = exports.instances[i]; - instance.enabled = exports.enabled(instance.namespace); - } -} - -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} diff --git a/tools/node_modules/eslint/node_modules/debug/src/index.js b/tools/node_modules/eslint/node_modules/debug/src/index.js index cabcbcda135e86..9fb731212c53a9 100644 --- a/tools/node_modules/eslint/node_modules/debug/src/index.js +++ b/tools/node_modules/eslint/node_modules/debug/src/index.js @@ -1,9 +1,10 @@ +"use strict"; + /** - * Detect Electron renderer process, which is node, but we should + * Detect Electron renderer / nwjs process, which is node, but we should * treat as a browser. */ - -if (typeof process === 'undefined' || process.type === 'renderer') { +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { module.exports = require('./browser.js'); } else { module.exports = require('./node.js'); diff --git a/tools/node_modules/eslint/node_modules/debug/src/node.js b/tools/node_modules/eslint/node_modules/debug/src/node.js index d666fb9c00919b..7932fdba35cba1 100644 --- a/tools/node_modules/eslint/node_modules/debug/src/node.js +++ b/tools/node_modules/eslint/node_modules/debug/src/node.js @@ -1,44 +1,37 @@ +"use strict"; + /** * Module dependencies. */ - var tty = require('tty'); -var util = require('util'); +var util = require('util'); /** * This is the Node.js implementation of `debug()`. - * - * Expose `debug()` as the module. */ -exports = module.exports = require('./debug'); + exports.init = init; exports.log = log; exports.formatArgs = formatArgs; exports.save = save; exports.load = load; exports.useColors = useColors; - /** * Colors. */ -exports.colors = [ 6, 2, 3, 4, 5, 1 ]; +exports.colors = [6, 2, 3, 4, 5, 1]; try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies var supportsColor = require('supports-color'); - if (supportsColor && supportsColor.level >= 2) { - exports.colors = [ - 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, - 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, - 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 214, 215, 220, 221 - ]; + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 220, 221]; } -} catch (err) { - // swallow - we only care if `supports-color` is available; it doesn't have to be. -} +} catch (error) {} // Swallow - we only care if `supports-color` is available; it doesn't have to be. /** * Build up the default `inspectOpts` object from the environment variables. @@ -46,74 +39,54 @@ try { * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js */ + exports.inspectOpts = Object.keys(process.env).filter(function (key) { return /^debug_/i.test(key); }).reduce(function (obj, key) { - // camel-case - var prop = key - .substring(6) - .toLowerCase() - .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); + // Camel-case + var prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, function (_, k) { + return k.toUpperCase(); + }); // Coerce string value into JS value - // coerce string value into JS value var val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) val = true; - else if (/^(no|off|false|disabled)$/i.test(val)) val = false; - else if (val === 'null') val = null; - else val = Number(val); + + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } obj[prop] = val; return obj; }, {}); - /** * Is stdout a TTY? Colored output is enabled when `true`. */ function useColors() { - return 'colors' in exports.inspectOpts - ? Boolean(exports.inspectOpts.colors) - : tty.isatty(process.stderr.fd); + return 'colors' in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd); } - -/** - * Map %o to `util.inspect()`, all on a single line. - */ - -exports.formatters.o = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts) - .split('\n').map(function(str) { - return str.trim() - }).join(' '); -}; - -/** - * Map %o to `util.inspect()`, allowing multiple lines if needed. - */ - -exports.formatters.O = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; - /** * Adds ANSI color escape codes if enabled. * * @api public */ + function formatArgs(args) { - var name = this.namespace; - var useColors = this.useColors; + var name = this.namespace, + useColors = this.useColors; if (useColors) { var c = this.color; - var colorCode = '\u001b[3' + (c < 8 ? c : '8;5;' + c); - var prefix = ' ' + colorCode + ';1m' + name + ' ' + '\u001b[0m'; - + var colorCode = "\x1B[3" + (c < 8 ? c : '8;5;' + c); + var prefix = " ".concat(colorCode, ";1m").concat(name, " \x1B[0m"); args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push(colorCode + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + "\x1B[0m"); } else { args[0] = getDate() + name + ' ' + args[0]; } @@ -122,19 +95,18 @@ function formatArgs(args) { function getDate() { if (exports.inspectOpts.hideDate) { return ''; - } else { - return new Date().toISOString() + ' '; } -} + return new Date().toISOString() + ' '; +} /** * Invokes `util.format()` with the specified arguments and writes to stderr. */ + function log() { return process.stderr.write(util.format.apply(util, arguments) + '\n'); } - /** * Save `namespaces`. * @@ -142,16 +114,16 @@ function log() { * @api private */ + function save(namespaces) { - if (null == namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { // If you set a process.env field to null or undefined, it gets cast to the // string 'null' or 'undefined'. Just delete instead. delete process.env.DEBUG; - } else { - process.env.DEBUG = namespaces; } } - /** * Load `namespaces`. * @@ -159,10 +131,10 @@ function save(namespaces) { * @api private */ + function load() { return process.env.DEBUG; } - /** * Init logic for `debug` instances. * @@ -170,17 +142,32 @@ function load() { * differently for a particular `debug` instance. */ -function init (debug) { - debug.inspectOpts = {}; +function init(debug) { + debug.inspectOpts = {}; var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; } } +module.exports = require('./common')(exports); +var formatters = module.exports.formatters; +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts).replace(/\s*\n\s*/g, ' '); +}; /** - * Enable namespaces listed in `process.env.DEBUG` initially. + * Map %O to `util.inspect()`, allowing multiple lines if needed. */ -exports.enable(load()); + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; diff --git a/tools/node_modules/eslint/node_modules/lodash/README.md b/tools/node_modules/eslint/node_modules/lodash/README.md index 817667cd54daa6..ba111a5a54ff20 100644 --- a/tools/node_modules/eslint/node_modules/lodash/README.md +++ b/tools/node_modules/eslint/node_modules/lodash/README.md @@ -1,4 +1,4 @@ -# lodash v4.17.10 +# lodash v4.17.11 The [Lodash](https://lodash.com/) library exported as [Node.js](https://nodejs.org/) modules. @@ -28,12 +28,12 @@ var at = require('lodash/at'); var curryN = require('lodash/fp/curryN'); ``` -See the [package source](https://github.com/lodash/lodash/tree/4.17.10-npm) for more details. +See the [package source](https://github.com/lodash/lodash/tree/4.17.11-npm) for more details. **Note:**
Install [n_](https://www.npmjs.com/package/n_) for Lodash use in the Node.js < 6 REPL. ## Support -Tested in Chrome 63-64, Firefox 57-58, IE 11, Edge 14, Safari 10-11, Node.js 4-9, & PhantomJS 2.1.1.
+Tested in Chrome 68-69, Firefox 61-62, IE 11, Edge 17, Safari 10-11, Node.js 6-10, & PhantomJS 2.1.1.
Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available. diff --git a/tools/node_modules/eslint/node_modules/lodash/_baseMergeDeep.js b/tools/node_modules/eslint/node_modules/lodash/_baseMergeDeep.js index 2ed7283eacc153..4679e8dce4b605 100644 --- a/tools/node_modules/eslint/node_modules/lodash/_baseMergeDeep.js +++ b/tools/node_modules/eslint/node_modules/lodash/_baseMergeDeep.js @@ -74,7 +74,7 @@ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, sta if (isArguments(objValue)) { newValue = toPlainObject(objValue); } - else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + else if (!isObject(objValue) || isFunction(objValue)) { newValue = initCloneObject(srcValue); } } diff --git a/tools/node_modules/eslint/node_modules/lodash/_hasUnicodeWord.js b/tools/node_modules/eslint/node_modules/lodash/_hasUnicodeWord.js index a35d6e504d4b83..95d52c444ce280 100644 --- a/tools/node_modules/eslint/node_modules/lodash/_hasUnicodeWord.js +++ b/tools/node_modules/eslint/node_modules/lodash/_hasUnicodeWord.js @@ -1,5 +1,5 @@ /** Used to detect strings that need a more robust regexp to match words. */ -var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; +var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; /** * Checks if `string` contains a word composed of Unicode symbols. diff --git a/tools/node_modules/eslint/node_modules/lodash/_safeGet.js b/tools/node_modules/eslint/node_modules/lodash/_safeGet.js index 2cc3137895b3e1..411b062053fc65 100644 --- a/tools/node_modules/eslint/node_modules/lodash/_safeGet.js +++ b/tools/node_modules/eslint/node_modules/lodash/_safeGet.js @@ -7,9 +7,11 @@ * @returns {*} Returns the property value. */ function safeGet(object, key) { - return key == '__proto__' - ? undefined - : object[key]; + if (key == '__proto__') { + return; + } + + return object[key]; } module.exports = safeGet; diff --git a/tools/node_modules/eslint/node_modules/lodash/core.js b/tools/node_modules/eslint/node_modules/lodash/core.js index 96b34773e8d21b..e333c15b986734 100644 --- a/tools/node_modules/eslint/node_modules/lodash/core.js +++ b/tools/node_modules/eslint/node_modules/lodash/core.js @@ -13,7 +13,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '4.17.10'; + var VERSION = '4.17.11'; /** Error message constants. */ var FUNC_ERROR_TEXT = 'Expected a function'; diff --git a/tools/node_modules/eslint/node_modules/lodash/core.min.js b/tools/node_modules/eslint/node_modules/lodash/core.min.js index 54360a3c4ad2eb..bd1e5453f3617b 100644 --- a/tools/node_modules/eslint/node_modules/lodash/core.min.js +++ b/tools/node_modules/eslint/node_modules/lodash/core.min.js @@ -25,5 +25,5 @@ return G(2,n)},o.pick=$n,o.slice=function(n,t,r){var e=null==n?0:n.length;return return t(n),n},o.thru=function(n,t){return t(n)},o.toArray=function(n){return M(n)?n.length?A(n):[]:W(n)},o.values=W,o.extend=Bn,Y(o,o),o.clone=function(n){return V(n)?Nn(n)?A(n):k(n,_n(n)):n},o.escape=function(n){return(n=Q(n))&&rn.test(n)?n.replace(tn,fn):n},o.every=function(n,t,r){return t=r?Z:t,f(n,g(t))},o.find=An,o.forEach=z,o.has=function(n,t){return null!=n&&pn.call(n,t)},o.head=q,o.identity=X,o.indexOf=P,o.isArguments=n,o.isArray=Nn,o.isBoolean=function(n){return true===n||false===n||H(n)&&"[object Boolean]"==hn.call(n); },o.isDate=function(n){return H(n)&&"[object Date]"==hn.call(n)},o.isEmpty=function(t){return M(t)&&(Nn(t)||L(t)||U(t.splice)||n(t))?!t.length:!_n(t).length},o.isEqual=function(n,t){return b(n,t)},o.isFinite=function(n){return typeof n=="number"&&gn(n)},o.isFunction=U,o.isNaN=function(n){return K(n)&&n!=+n},o.isNull=function(n){return null===n},o.isNumber=K,o.isObject=V,o.isRegExp=function(n){return H(n)&&"[object RegExp]"==hn.call(n)},o.isString=L,o.isUndefined=function(n){return n===Z},o.last=function(n){ var t=null==n?0:n.length;return t?n[t-1]:Z},o.max=function(n){return n&&n.length?a(n,X,v):Z},o.min=function(n){return n&&n.length?a(n,X,_):Z},o.noConflict=function(){return on._===this&&(on._=vn),this},o.noop=function(){},o.reduce=C,o.result=function(n,t,r){return t=null==n?Z:n[t],t===Z&&(t=r),U(t)?t.call(n):t},o.size=function(n){return null==n?0:(n=M(n)?n:_n(n),n.length)},o.some=function(n,t,r){return t=r?Z:t,E(n,g(t))},o.uniqueId=function(n){var t=++sn;return Q(n)+t},o.each=z,o.first=q,Y(o,function(){ -var n={};return s(o,function(t,r){pn.call(o.prototype,r)||(n[r]=t)}),n}(),{chain:false}),o.VERSION="4.17.10",mn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:an)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);o.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Nn(u)?u:[],n)}return this[r](function(r){return t.apply(Nn(r)?r:[],n); -})}}),o.prototype.toJSON=o.prototype.valueOf=o.prototype.value=function(){return w(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(on._=o, define(function(){return o})):cn?((cn.exports=o)._=o,un._=o):on._=o}).call(this); +var n={};return s(o,function(t,r){pn.call(o.prototype,r)||(n[r]=t)}),n}(),{chain:false}),o.VERSION="4.17.11",mn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:an)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);o.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Nn(u)?u:[],n)}return this[r](function(r){return t.apply(Nn(r)?r:[],n); +})}}),o.prototype.toJSON=o.prototype.valueOf=o.prototype.value=function(){return w(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(on._=o, define(function(){return o})):cn?((cn.exports=o)._=o,un._=o):on._=o}).call(this); \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/lodash/fp/_baseConvert.js b/tools/node_modules/eslint/node_modules/lodash/fp/_baseConvert.js index fcc28f26bd0a0f..9baf8e19022440 100644 --- a/tools/node_modules/eslint/node_modules/lodash/fp/_baseConvert.js +++ b/tools/node_modules/eslint/node_modules/lodash/fp/_baseConvert.js @@ -136,8 +136,7 @@ function wrapImmutable(func, cloner) { * @returns {Function|Object} Returns the converted function or object. */ function baseConvert(util, name, func, options) { - var setPlaceholder, - isLib = typeof name == 'function', + var isLib = typeof name == 'function', isObj = name === Object(name); if (isObj) { @@ -158,10 +157,10 @@ function baseConvert(util, name, func, options) { 'rearg': 'rearg' in options ? options.rearg : true }; - var forceCurry = ('curry' in options) && options.curry, + var defaultHolder = isLib ? func : fallbackHolder, + forceCurry = ('curry' in options) && options.curry, forceFixed = ('fixed' in options) && options.fixed, forceRearg = ('rearg' in options) && options.rearg, - placeholder = isLib ? func : fallbackHolder, pristine = isLib ? func.runInContext() : undefined; var helpers = isLib ? func : { @@ -466,7 +465,7 @@ function baseConvert(util, name, func, options) { * @param {Function} func The function to wrap. * @returns {Function} Returns the converted function. */ - function wrap(name, func) { + function wrap(name, func, placeholder) { var result, realName = mapping.aliasToReal[name] || name, wrapped = func, @@ -511,17 +510,15 @@ function baseConvert(util, name, func, options) { }; } result.convert = createConverter(realName, func); - if (mapping.placeholder[realName]) { - setPlaceholder = true; - result.placeholder = func.placeholder = placeholder; - } + result.placeholder = func.placeholder = placeholder; + return result; } /*--------------------------------------------------------------------------*/ if (!isObj) { - return wrap(name, func); + return wrap(name, func, defaultHolder); } var _ = func; @@ -531,7 +528,7 @@ function baseConvert(util, name, func, options) { each(mapping.aryMethod[aryKey], function(key) { var func = _[mapping.remap[key] || key]; if (func) { - pairs.push([key, wrap(key, func)]); + pairs.push([key, wrap(key, func, _)]); } }); }); @@ -557,9 +554,8 @@ function baseConvert(util, name, func, options) { }); _.convert = convertLib; - if (setPlaceholder) { - _.placeholder = placeholder; - } + _.placeholder = _; + // Assign aliases. each(keys(_), function(key) { each(mapping.realToAlias[key] || [], function(alias) { diff --git a/tools/node_modules/eslint/node_modules/lodash/fp/_mapping.js b/tools/node_modules/eslint/node_modules/lodash/fp/_mapping.js index 8f5ddf2d0911f0..a642ec05846947 100644 --- a/tools/node_modules/eslint/node_modules/lodash/fp/_mapping.js +++ b/tools/node_modules/eslint/node_modules/lodash/fp/_mapping.js @@ -261,16 +261,6 @@ exports.mutate = { } }; -/** Used to track methods with placeholder support */ -exports.placeholder = { - 'bind': true, - 'bindKey': true, - 'curry': true, - 'curryRight': true, - 'partial': true, - 'partialRight': true -}; - /** Used to map real names to their aliases. */ exports.realToAlias = (function() { var hasOwnProperty = Object.prototype.hasOwnProperty, diff --git a/tools/node_modules/eslint/node_modules/lodash/lodash.js b/tools/node_modules/eslint/node_modules/lodash/lodash.js index cd8df6fe67f220..cb139dd81ebee6 100644 --- a/tools/node_modules/eslint/node_modules/lodash/lodash.js +++ b/tools/node_modules/eslint/node_modules/lodash/lodash.js @@ -12,7 +12,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '4.17.10'; + var VERSION = '4.17.11'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; @@ -276,7 +276,7 @@ var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); /** Used to detect strings that need a more robust regexp to match words. */ - var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; /** Used to assign default `context` object properties. */ var contextProps = [ @@ -1224,20 +1224,6 @@ return result; } - /** - * Gets the value at `key`, unless `key` is "__proto__". - * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. - */ - function safeGet(object, key) { - return key == '__proto__' - ? undefined - : object[key]; - } - /** * Converts `set` to an array of its values. * @@ -3695,7 +3681,7 @@ if (isArguments(objValue)) { newValue = toPlainObject(objValue); } - else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + else if (!isObject(objValue) || isFunction(objValue)) { newValue = initCloneObject(srcValue); } } @@ -6618,6 +6604,22 @@ return array; } + /** + * Gets the value at `key`, unless `key` is "__proto__". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function safeGet(object, key) { + if (key == '__proto__') { + return; + } + + return object[key]; + } + /** * Sets metadata for `func`. * diff --git a/tools/node_modules/eslint/node_modules/lodash/lodash.min.js b/tools/node_modules/eslint/node_modules/lodash/lodash.min.js index fced00b390bcd4..c911263442db41 100644 --- a/tools/node_modules/eslint/node_modules/lodash/lodash.min.js +++ b/tools/node_modules/eslint/node_modules/lodash/lodash.min.js @@ -6,132 +6,132 @@ return true}function i(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,En="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",kn=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+En+mn,"g"),In=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Bn={}; -Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object Boolean]"]=Bn["[object DataView]"]=Bn["[object Date]"]=Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object WeakMap]"]=false; -var Ln={};Ln["[object Arguments]"]=Ln["[object Array]"]=Ln["[object ArrayBuffer]"]=Ln["[object DataView]"]=Ln["[object Boolean]"]=Ln["[object Date]"]=Ln["[object Float32Array]"]=Ln["[object Float64Array]"]=Ln["[object Int8Array]"]=Ln["[object Int16Array]"]=Ln["[object Int32Array]"]=Ln["[object Map]"]=Ln["[object Number]"]=Ln["[object Object]"]=Ln["[object RegExp]"]=Ln["[object Set]"]=Ln["[object String]"]=Ln["[object Symbol]"]=Ln["[object Uint8Array]"]=Ln["[object Uint8ClampedArray]"]=Ln["[object Uint16Array]"]=Ln["[object Uint32Array]"]=true, -Ln["[object Error]"]=Ln["[object Function]"]=Ln["[object WeakMap]"]=false;var Un={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Cn=parseFloat,Dn=parseInt,Mn=typeof global=="object"&&global&&global.Object===Object&&global,Tn=typeof self=="object"&&self&&self.Object===Object&&self,$n=Mn||Tn||Function("return this")(),Fn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Nn=Fn&&typeof module=="object"&&module&&!module.nodeType&&module,Pn=Nn&&Nn.exports===Fn,Zn=Pn&&Mn.process,qn=function(){ -try{var n=Nn&&Nn.f&&Nn.f("util").types;return n?n:Zn&&Zn.binding&&Zn.binding("util")}catch(n){}}(),Vn=qn&&qn.isArrayBuffer,Kn=qn&&qn.isDate,Gn=qn&&qn.isMap,Hn=qn&&qn.isRegExp,Jn=qn&&qn.isSet,Yn=qn&&qn.isTypedArray,Qn=b("length"),Xn=x({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I", -"\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C", -"\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i", -"\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r", -"\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij", -"\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),nt=x({"&":"&","<":"<",">":">",'"':""","'":"'"}),tt=x({"&":"&","<":"<",">":">",""":'"',"'":"'"}),rt=function x(mn){function An(n){if(du(n)&&!of(n)&&!(n instanceof Un)){if(n instanceof On)return n;if(ii.call(n,"__wrapped__"))return $e(n)}return new On(n)}function En(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Un(n){this.__wrapped__=n, -this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Mn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!gu(n))return n;if(u=of(n)){if(f=me(n),!c)return Ur(n,f)}else{var s=_o(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(cf(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Ln[s])return i?n:{};f=Ee(n,s,c)}}if(o||(o=new Zn), -i=o.get(n))return i;if(o.set(n,f),hf(n))return n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}),f;if(lf(n))return n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))}),f;var a=l?a?ve:_e:a?Wu:zu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=zu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Yu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ni("Expected a function"); -return yo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,k(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++ut}function Rt(n,t){return null!=n&&ii.call(n,t)}function zt(n,t){return null!=n&&t in Yu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Vu(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,k(t))),s=Ui(p.length,s), -l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_r.length?t:kt(t,hr(r,0,-1)),r=null==t?t:t[De(qe(r))],null==r?T:n(r,t,e)}function Ut(n){return du(n)&&"[object Arguments]"==Ot(n)}function Ct(n){ -return du(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return du(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!du(n)&&!du(t))t=n!==n&&t!==t;else n:{var i=of(n),o=of(t),f=i?"[object Array]":_o(n),c=o?"[object Array]":_o(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&cf(n)){if(!cf(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Zn),t=i||pf(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{ -if(!(1&r)&&(i=a&&ii.call(n,"__wrapped__"),f=o&&ii.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Zn),t=Mt(n,t,r,e,u);break n}if(c)t:if(u||(u=new Zn),i=1&r,f=_e(n),o=f.length,c=_e(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:ii.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++at?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[Tu],k(ye())), -n=Gt(n,function(n){return{a:c(t,function(t){return t(n)}),b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e=f?c:c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return Ru(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++et||9007199254740991t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Vu(u);++e=u){for(;e>>1,o=n[i];null!==o&&!ju(o)&&(r?o<=t:ot.length?n:kt(n,hr(t,0,-1)),null==n||delete n[De(qe(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++ie)return e?br(n[0]):[];for(var u=-1,i=Vu(e);++u=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=vi?vi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new _i(t).set(new _i(n)), -t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length)}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=ju(n),o=t!==T,f=null===t,c=t===t,a=ju(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&nu?T:i,u=1),t=Yu(t);++eo&&f[0]!==a&&f[o-1]!==a?[]:L(f,a), -o-=c.length,or?r?or(t,n):t:(r=or(t,Si(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Vu(l+c),h=this&&this!==$n&&this instanceof i?f:t;++at||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Br(e,r,h[4]):r,i[4]=e?L(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Lr(e,r,h[6]):r,i[6]=e?L(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ui(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1], -r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===T?c?0:n.length:Li(i[9]-a,0),!f&&24&t&&(t&=-25),Le((h?fo:go)(t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),i),n,t)}function ce(n,t,r,e){return n===T||au(n,ri[r])&&!ii.call(e,r)?t:n}function ae(n,t,r,e,u,i){return gu(n)&&gu(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return bu(n)?T:n}function se(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t;var c=-1,a=true,l=2&r?new Nn:T; -for(i.set(n,t),i.set(t,n);++cr&&(r=Li(e+r,0)),_(n,ye(t,3),r)):-1}function Ne(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=Au(r),u=0>r?Li(e+u,0):Ui(u,e-1)),_(n,ye(t,3),u,true)}function Pe(n){return(null==n?0:n.length)?wt(n,1):[]}function Ze(n){ -return n&&n.length?n[0]:T}function qe(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ve(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ke(n){return null==n?n:Ti.call(n)}function Ge(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(su(n))return t=Li(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function He(t,r){if(!t||!t.length)return[];var e=Ge(t);return null==r?e:c(e,function(t){return n(r,T,t)})}function Je(n){return n=An(n),n.__chain__=true,n}function Ye(n,t){ -return t(n)}function Qe(){return this}function Xe(n,t){return(of(n)?r:eo)(n,ye(t,3))}function nu(n,t){return(of(n)?e:uo)(n,ye(t,3))}function tu(n,t){return(of(n)?c:Gt)(n,ye(t,3))}function ru(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function eu(n,t){var r;if(typeof t!="function")throw new ni("Expected a function");return n=Au(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),r}}function uu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=uu.placeholder, -n}function iu(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=iu.placeholder,n}function ou(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Ko();if(u(n))return o(n);var r,e=yo;r=n-_,n=t-(n-p),r=g?Ui(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Ko(),r=u(n);if(c=arguments,a=this,p=n,r){if(h===T)return _=n=p,h=yo(i,t),v?e(n):s;if(g)return h=yo(i,t),e(p)}return h===T&&(h=yo(i,t)), -s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ni("Expected a function");return t=ku(t)||0,gu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Li(ku(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&ao(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Ko())},f}function fu(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e),r.cache=i.set(u,e)||i,e)}if(typeof n!="function"||null!=t&&typeof t!="function")throw new ni("Expected a function"); -return r.cache=new(fu.Cache||Fn),r}function cu(n){if(typeof n!="function")throw new ni("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function au(n,t){return n===t||n!==n&&t!==t}function lu(n){return null!=n&&vu(n.length)&&!pu(n)}function su(n){return du(n)&&lu(n)}function hu(n){if(!du(n))return false;var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!bu(n); -}function pu(n){return!!gu(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function _u(n){return typeof n=="number"&&n==Au(n)}function vu(n){return typeof n=="number"&&-1=n}function gu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function du(n){return null!=n&&typeof n=="object"}function yu(n){return typeof n=="number"||du(n)&&"[object Number]"==Ot(n)}function bu(n){return!(!du(n)||"[object Object]"!=Ot(n))&&(n=gi(n), -null===n||(n=ii.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ui.call(n)==ai))}function xu(n){return typeof n=="string"||!of(n)&&du(n)&&"[object String]"==Ot(n)}function ju(n){return typeof n=="symbol"||du(n)&&"[object Symbol]"==Ot(n)}function wu(n){if(!n)return[];if(lu(n))return xu(n)?M(n):Ur(n);if(ji&&n[ji]){n=n[ji]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=_o(n),("[object Map]"==t?W:"[object Set]"==t?U:Lu)(n)}function mu(n){return n?(n=ku(n), -n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Au(n){n=mu(n);var t=n%1;return n===n?t?n-t:n:0}function Eu(n){return n?pt(Au(n),0,4294967295):0}function ku(n){if(typeof n=="number")return n;if(ju(n))return F;if(gu(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=gu(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Dn(n.slice(2),t?2:8):vn.test(n)?F:+n}function Su(n){return Cr(n,Wu(n))}function Ou(n){return null==n?"":yr(n); -}function Iu(n,t,r){return n=null==n?T:kt(n,t),n===T?r:n}function Ru(n,t){return null!=n&&we(n,t,zt)}function zu(n){return lu(n)?qn(n):Vt(n)}function Wu(n){if(lu(n))n=qn(n,true);else if(gu(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&ii.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in Yu(n))t.push(r);n=t}return n}function Bu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){return t(n,r[0])})}function Lu(n){return null==n?[]:S(n,zu(n)); -}function Uu(n){return Tf(Ou(n).toLowerCase())}function Cu(n){return(n=Ou(n))&&n.replace(xn,Xn).replace(Sn,"")}function Du(n,t,r){return n=Ou(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Mu(n){return function(){return n}}function Tu(n){return n}function $u(n){return qt(typeof n=="function"?n:_t(n,1))}function Fu(n,t,e){var u=zu(t),i=Et(t,u);null!=e||gu(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=Et(t,zu(t)));var o=!(gu(e)&&"chain"in e&&!e.chain),f=pu(n);return r(i,function(r){ -var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Ur(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Nu(){}function Pu(n){return Ie(n)?b(De(n)):rr(n)}function Zu(){return[]}function qu(){return false}mn=null==mn?$n:rt.defaults($n.Object(),mn,rt.pick($n,Wn));var Vu=mn.Array,Ku=mn.Date,Gu=mn.Error,Hu=mn.Function,Ju=mn.Math,Yu=mn.Object,Qu=mn.RegExp,Xu=mn.String,ni=mn.TypeError,ti=Vu.prototype,ri=Yu.prototype,ei=mn["__core-js_shared__"],ui=Hu.prototype.toString,ii=ri.hasOwnProperty,oi=0,fi=function(){ -var n=/[^.]+$/.exec(ei&&ei.keys&&ei.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ci=ri.toString,ai=ui.call(Yu),li=$n._,si=Qu("^"+ui.call(ii).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),hi=Pn?mn.Buffer:T,pi=mn.Symbol,_i=mn.Uint8Array,vi=hi?hi.g:T,gi=B(Yu.getPrototypeOf,Yu),di=Yu.create,yi=ri.propertyIsEnumerable,bi=ti.splice,xi=pi?pi.isConcatSpreadable:T,ji=pi?pi.iterator:T,wi=pi?pi.toStringTag:T,mi=function(){try{var n=je(Yu,"defineProperty"); -return n({},"",{}),n}catch(n){}}(),Ai=mn.clearTimeout!==$n.clearTimeout&&mn.clearTimeout,Ei=Ku&&Ku.now!==$n.Date.now&&Ku.now,ki=mn.setTimeout!==$n.setTimeout&&mn.setTimeout,Si=Ju.ceil,Oi=Ju.floor,Ii=Yu.getOwnPropertySymbols,Ri=hi?hi.isBuffer:T,zi=mn.isFinite,Wi=ti.join,Bi=B(Yu.keys,Yu),Li=Ju.max,Ui=Ju.min,Ci=Ku.now,Di=mn.parseInt,Mi=Ju.random,Ti=ti.reverse,$i=je(mn,"DataView"),Fi=je(mn,"Map"),Ni=je(mn,"Promise"),Pi=je(mn,"Set"),Zi=je(mn,"WeakMap"),qi=je(Yu,"create"),Vi=Zi&&new Zi,Ki={},Gi=Me($i),Hi=Me(Fi),Ji=Me(Ni),Yi=Me(Pi),Qi=Me(Zi),Xi=pi?pi.prototype:T,no=Xi?Xi.valueOf:T,to=Xi?Xi.toString:T,ro=function(){ -function n(){}return function(t){return gu(t)?di?di(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=En.prototype,An.prototype.constructor=An,On.prototype=ro(En.prototype),On.prototype.constructor=On,Un.prototype=ro(En.prototype),Un.prototype.constructor=Un,Mn.prototype.clear=function(){this.__data__=qi?qi(null):{},this.size=0},Mn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n], -this.size-=n?1:0,n},Mn.prototype.get=function(n){var t=this.__data__;return qi?(n=t[n],"__lodash_hash_undefined__"===n?T:n):ii.call(t,n)?t[n]:T},Mn.prototype.has=function(n){var t=this.__data__;return qi?t[n]!==T:ii.call(t,n)},Mn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=qi&&t===T?"__lodash_hash_undefined__":t,this},Tn.prototype.clear=function(){this.__data__=[],this.size=0},Tn.prototype.delete=function(n){var t=this.__data__;return n=ft(t,n),!(0>n)&&(n==t.length-1?t.pop():bi.call(t,n,1), ---this.size,true)},Tn.prototype.get=function(n){var t=this.__data__;return n=ft(t,n),0>n?T:t[n][1]},Tn.prototype.has=function(n){return-1e?(++this.size,r.push([n,t])):r[e][1]=t,this},Fn.prototype.clear=function(){this.size=0,this.__data__={hash:new Mn,map:new(Fi||Tn),string:new Mn}},Fn.prototype.delete=function(n){return n=be(this,n).delete(n),this.size-=n?1:0,n},Fn.prototype.get=function(n){return be(this,n).get(n); +}function A(n,t){for(var r=-1,e=Array(n);++r"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,kn="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",En=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+kn+mn,"g"),In=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Un={}; +Un["[object Float32Array]"]=Un["[object Float64Array]"]=Un["[object Int8Array]"]=Un["[object Int16Array]"]=Un["[object Int32Array]"]=Un["[object Uint8Array]"]=Un["[object Uint8ClampedArray]"]=Un["[object Uint16Array]"]=Un["[object Uint32Array]"]=true,Un["[object Arguments]"]=Un["[object Array]"]=Un["[object ArrayBuffer]"]=Un["[object Boolean]"]=Un["[object DataView]"]=Un["[object Date]"]=Un["[object Error]"]=Un["[object Function]"]=Un["[object Map]"]=Un["[object Number]"]=Un["[object Object]"]=Un["[object RegExp]"]=Un["[object Set]"]=Un["[object String]"]=Un["[object WeakMap]"]=false; +var Bn={};Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object DataView]"]=Bn["[object Boolean]"]=Bn["[object Date]"]=Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object Symbol]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true, +Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object WeakMap]"]=false;var Ln={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Cn=parseFloat,Dn=parseInt,Mn=typeof global=="object"&&global&&global.Object===Object&&global,Tn=typeof self=="object"&&self&&self.Object===Object&&self,$n=Mn||Tn||Function("return this")(),Fn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Nn=Fn&&typeof module=="object"&&module&&!module.nodeType&&module,Pn=Nn&&Nn.exports===Fn,Zn=Pn&&Mn.process,qn=function(){ +try{var n=Nn&&Nn.require&&Nn.require("util").types;return n?n:Zn&&Zn.binding&&Zn.binding("util")}catch(n){}}(),Vn=qn&&qn.isArrayBuffer,Kn=qn&&qn.isDate,Gn=qn&&qn.isMap,Hn=qn&&qn.isRegExp,Jn=qn&&qn.isSet,Yn=qn&&qn.isTypedArray,Qn=b("length"),Xn=x({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e", +"\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a", +"\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I", +"\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r", +"\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ", +"\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),nt=x({"&":"&","<":"<",">":">",'"':""","'":"'"}),tt=x({"&":"&","<":"<",">":">",""":'"',"'":"'"}),rt=function x(mn){function An(n){if(yu(n)&&!ff(n)&&!(n instanceof Ln)){if(n instanceof On)return n;if(oi.call(n,"__wrapped__"))return Fe(n)}return new On(n)}function kn(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Ln(n){ +this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Mn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!du(n))return n;if(u=ff(n)){if(f=me(n),!c)return Lr(n,f)}else{var s=vo(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(af(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Bn[s])return i?n:{};f=ke(n,s,c)}}if(o||(o=new Zn), +i=o.get(n))return i;if(o.set(n,f),pf(n))return n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}),f;if(sf(n))return n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))}),f;var a=l?a?ve:_e:a?Uu:Wu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=Wu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Qu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ti("Expected a function"); +return bo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,E(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++ut}function Rt(n,t){return null!=n&&oi.call(n,t)}function zt(n,t){return null!=n&&t in Qu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Ku(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,E(t))),s=Ci(p.length,s), +l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_r.length?t:Et(t,hr(r,0,-1)),r=null==t?t:t[Me(Ve(r))],null==r?T:n(r,t,e)}function Lt(n){return yu(n)&&"[object Arguments]"==Ot(n)}function Ct(n){ +return yu(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return yu(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)return true;if(null==n||null==t||!yu(n)&&!yu(t))return n!==n&&t!==t;n:{var i=ff(n),o=ff(t),f=i?"[object Array]":vo(n),c=o?"[object Array]":vo(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&af(n)){if(!af(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Zn),t=i||_f(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{ +if(!(1&r)&&(i=a&&oi.call(n,"__wrapped__"),f=o&&oi.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Zn),t=Mt(n,t,r,e,u);break n}if(c)t:if(u||(u=new Zn),i=1&r,f=_e(n),o=f.length,c=_e(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:oi.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++at?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[$u],E(ye())),n=Gt(n,function(n,r,u){return{a:c(t,function(t){return t(n)}), +b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e=f){e=c;break n}e=c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return zu(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++et||9007199254740991t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Ku(u);++e=u){for(;e>>1,o=n[i];null!==o&&!wu(o)&&(r?o<=t:ot.length?n:Et(n,hr(t,0,-1)),null==n||delete n[Me(Ve(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++ie)return e?br(n[0]):[];for(var u=-1,i=Ku(e);++u=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=gi?gi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new vi(t).set(new vi(n)),t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length); +}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=wu(n),o=t!==T,f=null===t,c=t===t,a=wu(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&nu?T:i,u=1),t=Qu(t);++eo&&f[0]!==a&&f[o-1]!==a?[]:B(f,a),o-=c.length,or?r?or(t,n):t:(r=or(t,Oi(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Ku(l+c),h=this&&this!==$n&&this instanceof i?f:t;++at||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Ur(e,r,h[4]):r,i[4]=e?B(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Br(e,r,h[6]):r,i[6]=e?B(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ci(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1], +r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===T?c?0:n.length:Li(i[9]-a,0),!f&&24&t&&(t&=-25),c=t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),Le((h?co:yo)(c,i),n,t)}function ce(n,t,r,e){return n===T||lu(n,ei[r])&&!oi.call(e,r)?t:n}function ae(n,t,r,e,u,i){return du(n)&&du(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return xu(n)?T:n}function se(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t; +var c=-1,a=true,l=2&r?new Nn:T;for(i.set(n,t),i.set(t,n);++cr&&(r=Li(e+r,0)),_(n,ye(t,3),r)):-1}function Pe(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=ku(r),u=0>r?Li(e+u,0):Ci(u,e-1)),_(n,ye(t,3),u,true)}function Ze(n){return(null==n?0:n.length)?wt(n,1):[]; +}function qe(n){return n&&n.length?n[0]:T}function Ve(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ke(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ge(n){return null==n?n:$i.call(n)}function He(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(hu(n))return t=Li(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function Je(t,r){if(!t||!t.length)return[];var e=He(t);return null==r?e:c(e,function(t){return n(r,T,t)})}function Ye(n){return n=An(n),n.__chain__=true,n; +}function Qe(n,t){return t(n)}function Xe(){return this}function nu(n,t){return(ff(n)?r:uo)(n,ye(t,3))}function tu(n,t){return(ff(n)?e:io)(n,ye(t,3))}function ru(n,t){return(ff(n)?c:Gt)(n,ye(t,3))}function eu(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function uu(n,t){var r;if(typeof t!="function")throw new ti("Expected a function");return n=ku(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),r}}function iu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=iu.placeholder, +n}function ou(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=ou.placeholder,n}function fu(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Go();if(u(n))return o(n);var r,e=bo;r=n-_,n=t-(n-p),r=g?Ci(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Go(),r=u(n);if(c=arguments,a=this,p=n,r){if(h===T)return _=n=p,h=bo(i,t),v?e(n):s;if(g)return h=bo(i,t),e(p)}return h===T&&(h=bo(i,t)), +s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ti("Expected a function");return t=Su(t)||0,du(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Li(Su(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&lo(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Go())},f}function cu(n,t){if(typeof n!="function"||null!=t&&typeof t!="function")throw new ti("Expected a function");var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e), +r.cache=i.set(u,e)||i,e)};return r.cache=new(cu.Cache||Fn),r}function au(n){if(typeof n!="function")throw new ti("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function lu(n,t){return n===t||n!==n&&t!==t}function su(n){return null!=n&&gu(n.length)&&!_u(n)}function hu(n){return yu(n)&&su(n)}function pu(n){if(!yu(n))return false; +var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!xu(n)}function _u(n){return!!du(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function vu(n){return typeof n=="number"&&n==ku(n)}function gu(n){return typeof n=="number"&&-1=n}function du(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function yu(n){return null!=n&&typeof n=="object"; +}function bu(n){return typeof n=="number"||yu(n)&&"[object Number]"==Ot(n)}function xu(n){return!(!yu(n)||"[object Object]"!=Ot(n))&&(n=di(n),null===n||(n=oi.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ii.call(n)==li))}function ju(n){return typeof n=="string"||!ff(n)&&yu(n)&&"[object String]"==Ot(n)}function wu(n){return typeof n=="symbol"||yu(n)&&"[object Symbol]"==Ot(n)}function mu(n){if(!n)return[];if(su(n))return ju(n)?M(n):Lr(n);if(wi&&n[wi]){n=n[wi]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value); +return r}return t=vo(n),("[object Map]"==t?W:"[object Set]"==t?L:Lu)(n)}function Au(n){return n?(n=Su(n),n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function ku(n){n=Au(n);var t=n%1;return n===n?t?n-t:n:0}function Eu(n){return n?pt(ku(n),0,4294967295):0}function Su(n){if(typeof n=="number")return n;if(wu(n))return F;if(du(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=du(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Dn(n.slice(2),t?2:8):vn.test(n)?F:+n; +}function Ou(n){return Cr(n,Uu(n))}function Iu(n){return null==n?"":yr(n)}function Ru(n,t,r){return n=null==n?T:Et(n,t),n===T?r:n}function zu(n,t){return null!=n&&we(n,t,zt)}function Wu(n){return su(n)?qn(n):Vt(n)}function Uu(n){if(su(n))n=qn(n,true);else if(du(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&oi.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in Qu(n))t.push(r);n=t}return n}function Bu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){ +return t(n,r[0])})}function Lu(n){return null==n?[]:S(n,Wu(n))}function Cu(n){return $f(Iu(n).toLowerCase())}function Du(n){return(n=Iu(n))&&n.replace(xn,Xn).replace(Sn,"")}function Mu(n,t,r){return n=Iu(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Tu(n){return function(){return n}}function $u(n){return n}function Fu(n){return qt(typeof n=="function"?n:_t(n,1))}function Nu(n,t,e){var u=Wu(t),i=kt(t,u);null!=e||du(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=kt(t,Wu(t))); +var o=!(du(e)&&"chain"in e&&!e.chain),f=_u(n);return r(i,function(r){var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Lr(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Pu(){}function Zu(n){return Ie(n)?b(Me(n)):rr(n)}function qu(){return[]}function Vu(){return false}mn=null==mn?$n:rt.defaults($n.Object(),mn,rt.pick($n,Wn));var Ku=mn.Array,Gu=mn.Date,Hu=mn.Error,Ju=mn.Function,Yu=mn.Math,Qu=mn.Object,Xu=mn.RegExp,ni=mn.String,ti=mn.TypeError,ri=Ku.prototype,ei=Qu.prototype,ui=mn["__core-js_shared__"],ii=Ju.prototype.toString,oi=ei.hasOwnProperty,fi=0,ci=function(){ +var n=/[^.]+$/.exec(ui&&ui.keys&&ui.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ai=ei.toString,li=ii.call(Qu),si=$n._,hi=Xu("^"+ii.call(oi).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),pi=Pn?mn.Buffer:T,_i=mn.Symbol,vi=mn.Uint8Array,gi=pi?pi.allocUnsafe:T,di=U(Qu.getPrototypeOf,Qu),yi=Qu.create,bi=ei.propertyIsEnumerable,xi=ri.splice,ji=_i?_i.isConcatSpreadable:T,wi=_i?_i.iterator:T,mi=_i?_i.toStringTag:T,Ai=function(){try{var n=je(Qu,"defineProperty"); +return n({},"",{}),n}catch(n){}}(),ki=mn.clearTimeout!==$n.clearTimeout&&mn.clearTimeout,Ei=Gu&&Gu.now!==$n.Date.now&&Gu.now,Si=mn.setTimeout!==$n.setTimeout&&mn.setTimeout,Oi=Yu.ceil,Ii=Yu.floor,Ri=Qu.getOwnPropertySymbols,zi=pi?pi.isBuffer:T,Wi=mn.isFinite,Ui=ri.join,Bi=U(Qu.keys,Qu),Li=Yu.max,Ci=Yu.min,Di=Gu.now,Mi=mn.parseInt,Ti=Yu.random,$i=ri.reverse,Fi=je(mn,"DataView"),Ni=je(mn,"Map"),Pi=je(mn,"Promise"),Zi=je(mn,"Set"),qi=je(mn,"WeakMap"),Vi=je(Qu,"create"),Ki=qi&&new qi,Gi={},Hi=Te(Fi),Ji=Te(Ni),Yi=Te(Pi),Qi=Te(Zi),Xi=Te(qi),no=_i?_i.prototype:T,to=no?no.valueOf:T,ro=no?no.toString:T,eo=function(){ +function n(){}return function(t){return du(t)?yi?yi(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=kn.prototype,An.prototype.constructor=An,On.prototype=eo(kn.prototype),On.prototype.constructor=On,Ln.prototype=eo(kn.prototype),Ln.prototype.constructor=Ln,Mn.prototype.clear=function(){this.__data__=Vi?Vi(null):{},this.size=0},Mn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n], +this.size-=n?1:0,n},Mn.prototype.get=function(n){var t=this.__data__;return Vi?(n=t[n],"__lodash_hash_undefined__"===n?T:n):oi.call(t,n)?t[n]:T},Mn.prototype.has=function(n){var t=this.__data__;return Vi?t[n]!==T:oi.call(t,n)},Mn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=Vi&&t===T?"__lodash_hash_undefined__":t,this},Tn.prototype.clear=function(){this.__data__=[],this.size=0},Tn.prototype.delete=function(n){var t=this.__data__;return n=ft(t,n),!(0>n)&&(n==t.length-1?t.pop():xi.call(t,n,1), +--this.size,true)},Tn.prototype.get=function(n){var t=this.__data__;return n=ft(t,n),0>n?T:t[n][1]},Tn.prototype.has=function(n){return-1e?(++this.size,r.push([n,t])):r[e][1]=t,this},Fn.prototype.clear=function(){this.size=0,this.__data__={hash:new Mn,map:new(Ni||Tn),string:new Mn}},Fn.prototype.delete=function(n){return n=be(this,n).delete(n),this.size-=n?1:0,n},Fn.prototype.get=function(n){return be(this,n).get(n); },Fn.prototype.has=function(n){return be(this,n).has(n)},Fn.prototype.set=function(n,t){var r=be(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Nn.prototype.add=Nn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.clear=function(){this.__data__=new Tn,this.size=0},Zn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Zn.prototype.get=function(n){ -return this.__data__.get(n)},Zn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Fi||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Fn(e)}return r.set(n,t),this.size=r.size,this};var eo=Fr(mt),uo=Fr(At,true),io=Nr(),oo=Nr(true),fo=Vi?function(n,t){return Vi.set(n,t),n}:Tu,co=mi?function(n,t){return mi(n,"toString",{configurable:true,enumerable:false,value:Mu(t),writable:true})}:Tu,ao=Ai||function(n){ -return $n.clearTimeout(n)},lo=Pi&&1/U(new Pi([,-0]))[1]==$?function(n){return new Pi(n)}:Nu,so=Vi?function(n){return Vi.get(n)}:Nu,ho=Ii?function(n){return null==n?[]:(n=Yu(n),i(Ii(n),function(t){return yi.call(n,t)}))}:Zu,po=Ii?function(n){for(var t=[];n;)a(t,ho(n)),n=gi(n);return t}:Zu,_o=Ot;($i&&"[object DataView]"!=_o(new $i(new ArrayBuffer(1)))||Fi&&"[object Map]"!=_o(new Fi)||Ni&&"[object Promise]"!=_o(Ni.resolve())||Pi&&"[object Set]"!=_o(new Pi)||Zi&&"[object WeakMap]"!=_o(new Zi))&&(_o=function(n){ -var t=Ot(n);if(n=(n="[object Object]"==t?n.constructor:T)?Me(n):"")switch(n){case Gi:return"[object DataView]";case Hi:return"[object Map]";case Ji:return"[object Promise]";case Yi:return"[object Set]";case Qi:return"[object WeakMap]"}return t});var vo=ei?pu:qu,go=Ue(fo),yo=ki||function(n,t){return $n.setTimeout(n,t)},bo=Ue(co),xo=function(n){n=fu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(tn,function(n,r,e,u){ -t.push(e?u.replace(hn,"$1"):r||n)}),t}),jo=fr(function(n,t){return su(n)?yt(n,wt(t,1,su,true)):[]}),wo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),ye(r,2)):[]}),mo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),T,r):[]}),Ao=fr(function(n){var t=c(n,Er);return t.length&&t[0]===n[0]?Wt(t):[]}),Eo=fr(function(n){var t=qe(n),r=c(n,Er);return t===qe(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),ko=fr(function(n){var t=qe(n),r=c(n,Er);return(t=typeof t=="function"?t:T)&&r.pop(), -r.length&&r[0]===n[0]?Wt(r,T,t):[]}),So=fr(Ve),Oo=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Io=fr(function(n){return br(wt(n,1,su,true))}),Ro=fr(function(n){var t=qe(n);return su(t)&&(t=T),br(wt(n,1,su,true),ye(t,2))}),zo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return br(wt(n,1,su,true),T,t)}),Wo=fr(function(n,t){return su(n)?yt(n,t):[]}),Bo=fr(function(n){return mr(i(n,su))}),Lo=fr(function(n){var t=qe(n);return su(t)&&(t=T), -mr(i(n,su),ye(t,2))}),Uo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return mr(i(n,su),T,t)}),Co=fr(Ge),Do=fr(function(n){var t=n.length,t=1=t}),uf=Ut(function(){return arguments}())?Ut:function(n){return du(n)&&ii.call(n,"callee")&&!yi.call(n,"callee")},of=Vu.isArray,ff=Vn?k(Vn):Ct,cf=Ri||qu,af=Kn?k(Kn):Dt,lf=Gn?k(Gn):Tt,sf=Hn?k(Hn):Nt,hf=Jn?k(Jn):Pt,pf=Yn?k(Yn):Zt,_f=ee(Kt),vf=ee(function(n,t){return n<=t}),gf=$r(function(n,t){ -if(ze(t)||lu(t))Cr(t,zu(t),n);else for(var r in t)ii.call(t,r)&&ot(n,r,t[r])}),df=$r(function(n,t){Cr(t,Wu(t),n)}),yf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),bf=$r(function(n,t,r,e){Cr(t,zu(t),n,e)}),xf=pe(ht),jf=fr(function(n,t){n=Yu(n);var r=-1,e=t.length,u=2--n)return t.apply(this,arguments)}},An.ary=ru,An.assign=gf,An.assignIn=df,An.assignInWith=yf,An.assignWith=bf,An.at=xf,An.before=eu,An.bind=Go,An.bindAll=Ff,An.bindKey=Ho,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return of(n)?n:[n]},An.chain=Je,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Li(Au(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Vu(Si(r/t));et?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[]; -},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=Au(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:Au(e),0>e&&(e+=u),e=r>e?0:Eu(e);r>>0,r?(n=Ou(n))&&(typeof t=="string"||null!=t&&!sf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ni("Expected a function");return r=null==r?0:Li(Au(r),0), -fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:Au(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n), -n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ni("Expected a function");return gu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ou(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Ye,An.toArray=wu,An.toPairs=Rf,An.toPairsIn=zf,An.toPath=function(n){return of(n)?c(n,De):ju(n)?[n]:Ur(xo(Ou(n)))},An.toPlainObject=Su,An.transform=function(n,t,e){var u=of(n),i=u||cf(n)||pf(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:gu(n)&&pu(o)?ro(gi(n)):{}; -}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return ru(n,1)},An.union=Io,An.unionBy=Ro,An.unionWith=zo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=Ge,An.unzipWith=He,An.update=function(n,t,r){return null==n?n:lr(n,t,kr(r)(kt(n,t)),void 0)},An.updateWith=function(n,t,r,e){ -return e=typeof e=="function"?e:T,null!=n&&(n=lr(n,t,kr(r)(kt(n,t)),e)),n},An.values=Lu,An.valuesIn=function(n){return null==n?[]:S(n,Wu(n))},An.without=Wo,An.words=Du,An.wrap=function(n,t){return Xo(kr(t),n)},An.xor=Bo,An.xorBy=Lo,An.xorWith=Uo,An.zip=Co,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Do,An.entries=Rf,An.entriesIn=zf,An.extend=df,An.extendWith=yf,Fu(An,An),An.add=Yf,An.attempt=$f,An.camelCase=Wf,An.capitalize=Uu, -An.ceil=Qf,An.clamp=function(n,t,r){return r===T&&(r=t,t=T),r!==T&&(r=ku(r),r=r===r?r:0),t!==T&&(t=ku(t),t=t===t?t:0),pt(ku(n),t,r)},An.clone=function(n){return _t(n,4)},An.cloneDeep=function(n){return _t(n,5)},An.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,5,t)},An.cloneWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,4,t)},An.conformsTo=function(n,t){return null==t||gt(n,t,zu(t))},An.deburr=Cu,An.defaultTo=function(n,t){return null==n||n!==n?t:n},An.divide=Xf,An.endsWith=function(n,t,r){ -n=Ou(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(Au(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=au,An.escape=function(n){return(n=Ou(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Ou(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=of(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=$o,An.findIndex=Fe,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=Fo,An.findLastIndex=Ne,An.findLastKey=function(n,t){return p(n,ye(t,3),At); -},An.floor=nc,An.forEach=Xe,An.forEachRight=nu,An.forIn=function(n,t){return null==n?n:io(n,ye(t,3),Wu)},An.forInRight=function(n,t){return null==n?n:oo(n,ye(t,3),Wu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Iu,An.gt=rf,An.gte=ef,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=Ru,An.head=Ze,An.identity=Tu,An.includes=function(n,t,r,e){return n=lu(n)?n:Lu(n),r=r&&!e?Au(r):0,e=n.length,0>r&&(r=Li(e+r,0)),xu(n)?r<=e&&-1r&&(r=Li(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=mu(t),r===T?(r=t,t=0):r=mu(r),n=ku(n),n>=Ui(t,r)&&n=n},An.isSet=hf,An.isString=xu,An.isSymbol=ju,An.isTypedArray=pf,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return du(n)&&"[object WeakMap]"==_o(n)},An.isWeakSet=function(n){return du(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Wi.call(n,t)},An.kebabCase=Bf,An.last=qe,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=Au(r),u=0>u?Li(e+u,0):Ui(u,e-1)), -t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=_(n,d,u,true);return n},An.lowerCase=Lf,An.lowerFirst=Uf,An.lt=_f,An.lte=vf,An.max=function(n){return n&&n.length?xt(n,Tu,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,Tu)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,Tu,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=Zu,An.stubFalse=qu,An.stubObject=function(){return{}},An.stubString=function(){ -return""},An.stubTrue=function(){return true},An.multiply=tc,An.nth=function(n,t){return n&&n.length?Qt(n,Au(t)):T},An.noConflict=function(){return $n._===this&&($n._=li),this},An.noop=Nu,An.now=Ko,An.pad=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Oi(t),r)+n+ne(Si(t),r))},An.padEnd=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&et){var e=n;n=t,t=e}return r||n%1||t%1?(r=Mi(),Ui(n+r*(t-n+Cn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=of(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,eo)},An.reduceRight=function(n,t,r){var e=of(n)?s:j,u=3>arguments.length; -return e(n,ye(t,4),r,u,uo)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),or(Ou(n),t)},An.replace=function(){var n=arguments,t=Ou(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++en||9007199254740991=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),sf(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=Qu(u.source,Ou(_n.exec(u))+"g")), -u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1e.__dir__?"Right":"")}),e},Un.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Un.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({ -iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Un.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Un.prototype[n]=function(){return this.__filtered__?new Un(this):this[r](1)}}),Un.prototype.compact=function(){return this.filter(Tu)},Un.prototype.find=function(n){return this.filter(n).head()},Un.prototype.findLast=function(n){return this.reverse().find(n); -},Un.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Un(this):this.map(function(r){return Lt(r,n,t)})}),Un.prototype.reject=function(n){return this.filter(cu(ye(n)))},Un.prototype.slice=function(n,t){n=Au(n);var r=this;return r.__filtered__&&(0t)?new Un(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=Au(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Un.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Un.prototype.toArray=function(){return this.take(4294967295); -},mt(Un.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){function t(n){return n=u.apply(An,a([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Un,l=f[0],s=c||of(o);s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false);var h=this.__chain__,p=!!this.__actions__.length,l=i&&!h,c=c&&!p;return!i&&s?(o=c?o:new Un(this),o=n.apply(o,f),o.__actions__.push({ -func:Ye,args:[t],thisArg:T}),new On(o,h)):l&&c?n.apply(this,f):(o=this.thru(t),l?e?o.value()[0]:o.value():o)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ti[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(of(u)?u:[],n)}return this[r](function(r){return t.apply(of(r)?r:[],n)})}}),mt(Un.prototype,function(n,t){var r=An[t];if(r){var e=r.name+""; -(Ki[e]||(Ki[e]=[])).push({name:t,func:r})}}),Ki[Jr(T,2).name]=[{name:"wrapper",func:T}],Un.prototype.clone=function(){var n=new Un(this.__wrapped__);return n.__actions__=Ur(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ur(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ur(this.__views__),n},Un.prototype.reverse=function(){if(this.__filtered__){var n=new Un(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n; -},Un.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=of(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){for(var t,r=this;r instanceof En;){ -var e=$e(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Un?(this.__actions__.length&&(n=new Un(this)),n=n.reverse(),n.__actions__.push({func:Ye,args:[Ke],thisArg:T}),new On(n,this.__chain__)):this.thru(Ke)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,ji&&(An.prototype[ji]=Qe), -An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?($n._=rt, define(function(){return rt})):Nn?((Nn.exports=rt)._=rt,Fn._=rt):$n._=rt}).call(this); +return this.__data__.get(n)},Zn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Ni||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Fn(e)}return r.set(n,t),this.size=r.size,this};var uo=Fr(mt),io=Fr(At,true),oo=Nr(),fo=Nr(true),co=Ki?function(n,t){return Ki.set(n,t),n}:$u,ao=Ai?function(n,t){return Ai(n,"toString",{configurable:true,enumerable:false,value:Tu(t),writable:true})}:$u,lo=ki||function(n){ +return $n.clearTimeout(n)},so=Zi&&1/L(new Zi([,-0]))[1]==$?function(n){return new Zi(n)}:Pu,ho=Ki?function(n){return Ki.get(n)}:Pu,po=Ri?function(n){return null==n?[]:(n=Qu(n),i(Ri(n),function(t){return bi.call(n,t)}))}:qu,_o=Ri?function(n){for(var t=[];n;)a(t,po(n)),n=di(n);return t}:qu,vo=Ot;(Fi&&"[object DataView]"!=vo(new Fi(new ArrayBuffer(1)))||Ni&&"[object Map]"!=vo(new Ni)||Pi&&"[object Promise]"!=vo(Pi.resolve())||Zi&&"[object Set]"!=vo(new Zi)||qi&&"[object WeakMap]"!=vo(new qi))&&(vo=function(n){ +var t=Ot(n);if(n=(n="[object Object]"==t?n.constructor:T)?Te(n):"")switch(n){case Hi:return"[object DataView]";case Ji:return"[object Map]";case Yi:return"[object Promise]";case Qi:return"[object Set]";case Xi:return"[object WeakMap]"}return t});var go=ui?_u:Vu,yo=Ce(co),bo=Si||function(n,t){return $n.setTimeout(n,t)},xo=Ce(ao),jo=function(n){n=cu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(tn,function(n,r,e,u){ +t.push(e?u.replace(hn,"$1"):r||n)}),t}),wo=fr(function(n,t){return hu(n)?yt(n,wt(t,1,hu,true)):[]}),mo=fr(function(n,t){var r=Ve(t);return hu(r)&&(r=T),hu(n)?yt(n,wt(t,1,hu,true),ye(r,2)):[]}),Ao=fr(function(n,t){var r=Ve(t);return hu(r)&&(r=T),hu(n)?yt(n,wt(t,1,hu,true),T,r):[]}),ko=fr(function(n){var t=c(n,kr);return t.length&&t[0]===n[0]?Wt(t):[]}),Eo=fr(function(n){var t=Ve(n),r=c(n,kr);return t===Ve(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),So=fr(function(n){var t=Ve(n),r=c(n,kr);return(t=typeof t=="function"?t:T)&&r.pop(), +r.length&&r[0]===n[0]?Wt(r,T,t):[]}),Oo=fr(Ke),Io=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Ro=fr(function(n){return br(wt(n,1,hu,true))}),zo=fr(function(n){var t=Ve(n);return hu(t)&&(t=T),br(wt(n,1,hu,true),ye(t,2))}),Wo=fr(function(n){var t=Ve(n),t=typeof t=="function"?t:T;return br(wt(n,1,hu,true),T,t)}),Uo=fr(function(n,t){return hu(n)?yt(n,t):[]}),Bo=fr(function(n){return mr(i(n,hu))}),Lo=fr(function(n){var t=Ve(n);return hu(t)&&(t=T), +mr(i(n,hu),ye(t,2))}),Co=fr(function(n){var t=Ve(n),t=typeof t=="function"?t:T;return mr(i(n,hu),T,t)}),Do=fr(He),Mo=fr(function(n){var t=n.length,t=1=t}),of=Lt(function(){return arguments}())?Lt:function(n){return yu(n)&&oi.call(n,"callee")&&!bi.call(n,"callee")},ff=Ku.isArray,cf=Vn?E(Vn):Ct,af=zi||Vu,lf=Kn?E(Kn):Dt,sf=Gn?E(Gn):Tt,hf=Hn?E(Hn):Nt,pf=Jn?E(Jn):Pt,_f=Yn?E(Yn):Zt,vf=ee(Kt),gf=ee(function(n,t){return n<=t}),df=$r(function(n,t){ +if(ze(t)||su(t))Cr(t,Wu(t),n);else for(var r in t)oi.call(t,r)&&ot(n,r,t[r])}),yf=$r(function(n,t){Cr(t,Uu(t),n)}),bf=$r(function(n,t,r,e){Cr(t,Uu(t),n,e)}),xf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),jf=pe(ht),wf=fr(function(n,t){n=Qu(n);var r=-1,e=t.length,u=2--n)return t.apply(this,arguments)}},An.ary=eu,An.assign=df,An.assignIn=yf,An.assignInWith=bf,An.assignWith=xf,An.at=jf,An.before=uu,An.bind=Ho,An.bindAll=Nf,An.bindKey=Jo,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return ff(n)?n:[n]},An.chain=Ye,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Li(ku(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Ku(Oi(r/t));et?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:ku(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[]; +},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=ku(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:ku(e),0>e&&(e+=u),e=r>e?0:Eu(e);r>>0,r?(n=Iu(n))&&(typeof t=="string"||null!=t&&!hf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ti("Expected a function");return r=null==r?0:Li(ku(r),0), +fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:ku(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:ku(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n), +n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ti("Expected a function");return du(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),fu(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Qe,An.toArray=mu,An.toPairs=zf,An.toPairsIn=Wf,An.toPath=function(n){return ff(n)?c(n,Me):wu(n)?[n]:Lr(jo(Iu(n)))},An.toPlainObject=Ou,An.transform=function(n,t,e){var u=ff(n),i=u||af(n)||_f(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:du(n)&&_u(o)?eo(di(n)):{}; +}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return eu(n,1)},An.union=Ro,An.unionBy=zo,An.unionWith=Wo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=He,An.unzipWith=Je,An.update=function(n,t,r){return null!=n&&(r=Er(r),n=lr(n,t,r(Et(n,t)),void 0)),n},An.updateWith=function(n,t,r,e){ +return e=typeof e=="function"?e:T,null!=n&&(r=Er(r),n=lr(n,t,r(Et(n,t)),e)),n},An.values=Lu,An.valuesIn=function(n){return null==n?[]:S(n,Uu(n))},An.without=Uo,An.words=Mu,An.wrap=function(n,t){return nf(Er(t),n)},An.xor=Bo,An.xorBy=Lo,An.xorWith=Co,An.zip=Do,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Mo,An.entries=zf,An.entriesIn=Wf,An.extend=yf,An.extendWith=bf,Nu(An,An),An.add=Qf,An.attempt=Ff,An.camelCase=Uf,An.capitalize=Cu, +An.ceil=Xf,An.clamp=function(n,t,r){return r===T&&(r=t,t=T),r!==T&&(r=Su(r),r=r===r?r:0),t!==T&&(t=Su(t),t=t===t?t:0),pt(Su(n),t,r)},An.clone=function(n){return _t(n,4)},An.cloneDeep=function(n){return _t(n,5)},An.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,5,t)},An.cloneWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,4,t)},An.conformsTo=function(n,t){return null==t||gt(n,t,Wu(t))},An.deburr=Du,An.defaultTo=function(n,t){return null==n||n!==n?t:n},An.divide=nc,An.endsWith=function(n,t,r){ +n=Iu(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(ku(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=lu,An.escape=function(n){return(n=Iu(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Iu(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=ff(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=Fo,An.findIndex=Ne,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=No,An.findLastIndex=Pe,An.findLastKey=function(n,t){return p(n,ye(t,3),At); +},An.floor=tc,An.forEach=nu,An.forEachRight=tu,An.forIn=function(n,t){return null==n?n:oo(n,ye(t,3),Uu)},An.forInRight=function(n,t){return null==n?n:fo(n,ye(t,3),Uu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Ru,An.gt=ef,An.gte=uf,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=zu,An.head=qe,An.identity=$u,An.includes=function(n,t,r,e){return n=su(n)?n:Lu(n),r=r&&!e?ku(r):0,e=n.length,0>r&&(r=Li(e+r,0)),ju(n)?r<=e&&-1r&&(r=Li(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=Au(t),r===T?(r=t,t=0):r=Au(r),n=Su(n),n>=Ci(t,r)&&n=n},An.isSet=pf,An.isString=ju,An.isSymbol=wu,An.isTypedArray=_f,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return yu(n)&&"[object WeakMap]"==vo(n)},An.isWeakSet=function(n){return yu(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Ui.call(n,t)},An.kebabCase=Bf,An.last=Ve,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=ku(r),u=0>u?Li(e+u,0):Ci(u,e-1)), +t===t)n:{for(r=u+1;r--;)if(n[r]===t){n=r;break n}n=r}else n=_(n,d,u,true);return n},An.lowerCase=Lf,An.lowerFirst=Cf,An.lt=vf,An.lte=gf,An.max=function(n){return n&&n.length?xt(n,$u,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,$u)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,$u,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=qu,An.stubFalse=Vu,An.stubObject=function(){ +return{}},An.stubString=function(){return""},An.stubTrue=function(){return true},An.multiply=rc,An.nth=function(n,t){return n&&n.length?Qt(n,ku(t)):T},An.noConflict=function(){return $n._===this&&($n._=si),this},An.noop=Pu,An.now=Go,An.pad=function(n,t,r){n=Iu(n);var e=(t=ku(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Ii(t),r)+n+ne(Oi(t),r))},An.padEnd=function(n,t,r){n=Iu(n);var e=(t=ku(t))?D(n):0;return t&&et){var e=n;n=t,t=e}return r||n%1||t%1?(r=Ti(),Ci(n+r*(t-n+Cn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=ff(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,uo)},An.reduceRight=function(n,t,r){ +var e=ff(n)?s:j,u=3>arguments.length;return e(n,ye(t,4),r,u,io)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:ku(t),or(Iu(n),t)},An.replace=function(){var n=arguments,t=Iu(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++en||9007199254740991=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),hf(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=Xu(u.source,Iu(_n.exec(u))+"g")), +u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1e.__dir__?"Right":"")}),e},Ln.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Ln.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({ +iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Ln.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Ln.prototype[n]=function(){return this.__filtered__?new Ln(this):this[r](1)}}),Ln.prototype.compact=function(){return this.filter($u)},Ln.prototype.find=function(n){return this.filter(n).head()},Ln.prototype.findLast=function(n){return this.reverse().find(n); +},Ln.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Ln(this):this.map(function(r){return Bt(r,n,t)})}),Ln.prototype.reject=function(n){return this.filter(au(ye(n)))},Ln.prototype.slice=function(n,t){n=ku(n);var r=this;return r.__filtered__&&(0t)?new Ln(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=ku(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Ln.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Ln.prototype.toArray=function(){return this.take(4294967295); +},mt(Ln.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){var t=this.__wrapped__,o=e?[1]:arguments,f=t instanceof Ln,c=o[0],l=f||ff(t),s=function(n){return n=u.apply(An,a([n],o)),e&&h?n[0]:n};l&&r&&typeof c=="function"&&1!=c.length&&(f=l=false);var h=this.__chain__,p=!!this.__actions__.length,c=i&&!h,f=f&&!p;return!i&&l?(t=f?t:new Ln(this),t=n.apply(t,o),t.__actions__.push({ +func:Qe,args:[s],thisArg:T}),new On(t,h)):c&&f?n.apply(this,o):(t=this.thru(s),c?e?t.value()[0]:t.value():t)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ri[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(ff(u)?u:[],n)}return this[r](function(r){return t.apply(ff(r)?r:[],n)})}}),mt(Ln.prototype,function(n,t){var r=An[t];if(r){var e=r.name+""; +(Gi[e]||(Gi[e]=[])).push({name:t,func:r})}}),Gi[Jr(T,2).name]=[{name:"wrapper",func:T}],Ln.prototype.clone=function(){var n=new Ln(this.__wrapped__);return n.__actions__=Lr(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Lr(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Lr(this.__views__),n},Ln.prototype.reverse=function(){if(this.__filtered__){var n=new Ln(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n; +},Ln.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=ff(t),u=0>r,i=e?t.length:0;n=0;for(var o=i,f=this.__views__,c=-1,a=f.length;++c=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){for(var t,r=this;r instanceof kn;){ +var e=Fe(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Ln?(this.__actions__.length&&(n=new Ln(this)),n=n.reverse(),n.__actions__.push({func:Qe,args:[Ge],thisArg:T}),new On(n,this.__chain__)):this.thru(Ge)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,wi&&(An.prototype[wi]=Xe), +An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?($n._=rt, define(function(){return rt})):Nn?((Nn.exports=rt)._=rt,Fn._=rt):$n._=rt}).call(this); \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/lodash/package.json b/tools/node_modules/eslint/node_modules/lodash/package.json index 9c58484573782d..73236b6290042b 100644 --- a/tools/node_modules/eslint/node_modules/lodash/package.json +++ b/tools/node_modules/eslint/node_modules/lodash/package.json @@ -39,5 +39,5 @@ "scripts": { "test": "echo \"See https://travis-ci.org/lodash-archive/lodash-cli for testing details.\"" }, - "version": "4.17.10" + "version": "4.17.11" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/ms/index.js b/tools/node_modules/eslint/node_modules/ms/index.js index 6a522b16b3a3bf..72297501f9b9bb 100644 --- a/tools/node_modules/eslint/node_modules/ms/index.js +++ b/tools/node_modules/eslint/node_modules/ms/index.js @@ -6,6 +6,7 @@ var s = 1000; var m = s * 60; var h = m * 60; var d = h * 24; +var w = d * 7; var y = d * 365.25; /** @@ -49,7 +50,7 @@ function parse(str) { if (str.length > 100) { return; } - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( str ); if (!match) { @@ -64,6 +65,10 @@ function parse(str) { case 'yr': case 'y': return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; case 'days': case 'day': case 'd': @@ -106,16 +111,17 @@ function parse(str) { */ function fmtShort(ms) { - if (ms >= d) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { return Math.round(ms / d) + 'd'; } - if (ms >= h) { + if (msAbs >= h) { return Math.round(ms / h) + 'h'; } - if (ms >= m) { + if (msAbs >= m) { return Math.round(ms / m) + 'm'; } - if (ms >= s) { + if (msAbs >= s) { return Math.round(ms / s) + 's'; } return ms + 'ms'; @@ -130,23 +136,27 @@ function fmtShort(ms) { */ function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; } /** * Pluralization helper. */ -function plural(ms, n, name) { - if (ms < n) { - return; - } - if (ms < n * 1.5) { - return Math.floor(ms / n) + ' ' + name; - } - return Math.ceil(ms / n) + ' ' + name + 's'; +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); } diff --git a/tools/node_modules/eslint/node_modules/ms/package.json b/tools/node_modules/eslint/node_modules/ms/package.json index c68b37f98a8d60..c59290ffb9edea 100644 --- a/tools/node_modules/eslint/node_modules/ms/package.json +++ b/tools/node_modules/eslint/node_modules/ms/package.json @@ -4,13 +4,13 @@ }, "bundleDependencies": false, "deprecated": false, - "description": "Tiny milisecond conversion utility", + "description": "Tiny millisecond conversion utility", "devDependencies": { - "eslint": "3.19.0", + "eslint": "4.12.1", "expect.js": "0.3.1", - "husky": "0.13.3", - "lint-staged": "3.4.1", - "mocha": "3.4.1" + "husky": "0.14.3", + "lint-staged": "5.0.0", + "mocha": "4.0.1" }, "eslintConfig": { "extends": "eslint:recommended", @@ -42,5 +42,5 @@ "precommit": "lint-staged", "test": "mocha tests.js" }, - "version": "2.0.0" + "version": "2.1.1" } \ No newline at end of file diff --git a/tools/node_modules/eslint/node_modules/ms/readme.md b/tools/node_modules/eslint/node_modules/ms/readme.md index 84a9974cccd81f..bb767293ac740d 100644 --- a/tools/node_modules/eslint/node_modules/ms/readme.md +++ b/tools/node_modules/eslint/node_modules/ms/readme.md @@ -17,35 +17,44 @@ ms('1m') // 60000 ms('5s') // 5000 ms('1y') // 31557600000 ms('100') // 100 +ms('-3 days') // -259200000 +ms('-1h') // -3600000 +ms('-200') // -200 ``` -### Convert from milliseconds +### Convert from Milliseconds ```js ms(60000) // "1m" ms(2 * 60000) // "2m" +ms(-3 * 60000) // "-3m" ms(ms('10 hours')) // "10h" ``` -### Time format written-out +### Time Format Written-Out ```js ms(60000, { long: true }) // "1 minute" ms(2 * 60000, { long: true }) // "2 minutes" +ms(-3 * 60000, { long: true }) // "-3 minutes" ms(ms('10 hours'), { long: true }) // "10 hours" ``` ## Features -- Works both in [node](https://nodejs.org) and in the browser. -- If a number is supplied to `ms`, a string with a unit is returned. -- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`). -- If you pass a string with a number and a valid unit, the number of equivalent ms is returned. +- Works both in [Node.js](https://nodejs.org) and in the browser +- If a number is supplied to `ms`, a string with a unit is returned +- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`) +- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned -## Caught a bug? +## Related Packages + +- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time. + +## Caught a Bug? 1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device 2. Link the package to the global module directory: `npm link` -3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms! +3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms! As always, you can run the tests using: `npm test` diff --git a/tools/node_modules/eslint/node_modules/regexpp/index.d.ts b/tools/node_modules/eslint/node_modules/regexpp/index.d.ts index 7c825fc261894e..d3b1d48e5ba30e 100644 --- a/tools/node_modules/eslint/node_modules/regexpp/index.d.ts +++ b/tools/node_modules/eslint/node_modules/regexpp/index.d.ts @@ -138,9 +138,9 @@ declare module 'regexpp/ast' { dotAll: boolean; global: boolean; ignoreCase: boolean; - multiline: boolean; - sticky: boolean; - unicode: boolean; + multiline: boolean; + sticky: boolean; + unicode: boolean; } } @@ -189,9 +189,9 @@ declare module 'regexpp/validator' { onCharacter?(start: number, end: number, value: number): void; onBackreference?(start: number, end: number, ref: number | string): void; onCharacterClassEnter?(start: number, negate: boolean): void; - onCharacterClassLeave?(start: number, end: number, negate: boolean): void; - onCharacterClassRange?(start: number, end: number, min: number, max: number): void; - } + onCharacterClassLeave?(start: number, end: number, negate: boolean): void; + onCharacterClassRange?(start: number, end: number, min: number, max: number): void; + } } export class RegExpValidator { constructor(options?: RegExpValidator.Options); diff --git a/tools/node_modules/eslint/package.json b/tools/node_modules/eslint/package.json index c4006cf592ba12..d78882d19aa445 100644 --- a/tools/node_modules/eslint/package.json +++ b/tools/node_modules/eslint/package.json @@ -135,5 +135,5 @@ "release": "node Makefile.js release", "test": "node Makefile.js test" }, - "version": "5.5.0" + "version": "5.6.0" } \ No newline at end of file From 3120dab920b15cb590bbde014f983ca61466c581 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Mon, 10 Sep 2018 06:23:59 +0200 Subject: [PATCH 37/77] src: move no_async_hooks_checks to env This commit moves the setting of AsyncHooks no_force_checks to the Environment constructor instead of from the Start function in node.cc. PR-URL: https://github.com/nodejs/node/pull/22784 Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- src/env.cc | 3 +++ src/node.cc | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/env.cc b/src/env.cc index bb2160d73d6367..0d3bfc808d43dc 100644 --- a/src/env.cc +++ b/src/env.cc @@ -161,6 +161,9 @@ Environment::Environment(IsolateData* isolate_data, isolate()->GetHeapProfiler()->AddBuildEmbedderGraphCallback( BuildEmbedderGraph, this); + if (options_->no_force_async_hooks_checks) { + async_hooks_.no_force_checks(); + } } Environment::~Environment() { diff --git a/src/node.cc b/src/node.cc index fe6293f62a2adc..2576f016c1477a 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2896,12 +2896,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data, return 12; // Signal internal error. } - // TODO(addaleax): Maybe access this option directly instead of setting - // a boolean member of Environment. Ditto below for trace_sync_io. - if (env.options()->no_force_async_hooks_checks) { - env.async_hooks()->no_force_checks(); - } - { Environment::AsyncCallbackScope callback_scope(&env); env.async_hooks()->push_async_ids(1, 0); From dfef9a9afbb80e19234db29ecd94729c366fb2b0 Mon Sep 17 00:00:00 2001 From: Mohit kumar Bajoria Date: Wed, 12 Sep 2018 23:16:11 +0530 Subject: [PATCH 38/77] doc: add missing options for crypto sign.sign() Fixes: https://github.com/nodejs/node/issues/22813 PR-URL: https://github.com/nodejs/node/pull/22824 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Richard Lau --- doc/api/crypto.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index a027efba85e7df..30cdc4c9b67c63 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1124,6 +1124,8 @@ changes: * `privateKey` {string | Object} - `key` {string} - `passphrase` {string} + - `padding` {integer} + - `saltLength` {integer} * `outputFormat` {string} * Returns: {Buffer | string} From 5cb642eb27ff6bdbf16389e9df9d1c732553273c Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 4 Sep 2018 15:18:44 +0200 Subject: [PATCH 39/77] assert: add default operator to `assert.fail()` This makes sure `assert.fail()` contains an operator instead of being undefined. On top of that it also fixes the `err.generatedMessage` property. Before, it was not always set correct. PR-URL: https://github.com/nodejs/node/pull/22694 Reviewed-By: John-David Dalton Reviewed-By: Matteo Collina --- lib/assert.js | 21 ++++++++++++++----- test/parallel/test-assert-fail-deprecation.js | 8 ++++--- test/parallel/test-assert-fail.js | 10 +++++---- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 2b7628a8a32500..69618862f2182c 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -86,8 +86,9 @@ function innerFail(obj) { function fail(actual, expected, message, operator, stackStartFn) { const argsLen = arguments.length; + let internalMessage; if (argsLen === 0) { - message = 'Failed'; + internalMessage = 'Failed'; } else if (argsLen === 1) { message = actual; actual = undefined; @@ -105,13 +106,23 @@ function fail(actual, expected, message, operator, stackStartFn) { operator = '!='; } - innerFail({ + if (message instanceof Error) throw message; + + const errArgs = { actual, expected, - message, - operator, + operator: operator === undefined ? 'fail' : operator, stackStartFn: stackStartFn || fail - }); + }; + if (message !== undefined) { + errArgs.message = message; + } + const err = new AssertionError(errArgs); + if (internalMessage) { + err.message = internalMessage; + err.generatedMessage = true; + } + throw err; } assert.fail = fail; diff --git a/test/parallel/test-assert-fail-deprecation.js b/test/parallel/test-assert-fail-deprecation.js index 68ebcd612d31df..97cba760e03836 100644 --- a/test/parallel/test-assert-fail-deprecation.js +++ b/test/parallel/test-assert-fail-deprecation.js @@ -19,7 +19,8 @@ assert.throws(() => { message: '\'first\' != \'second\'', operator: '!=', actual: 'first', - expected: 'second' + expected: 'second', + generatedMessage: true }); // Three args @@ -29,9 +30,10 @@ assert.throws(() => { code: 'ERR_ASSERTION', name: 'AssertionError [ERR_ASSERTION]', message: 'another custom message', - operator: undefined, + operator: 'fail', actual: 'ignored', - expected: 'ignored' + expected: 'ignored', + generatedMessage: false }); // Three args with custom Error diff --git a/test/parallel/test-assert-fail.js b/test/parallel/test-assert-fail.js index e8336e8f2169ef..4410cc85442707 100644 --- a/test/parallel/test-assert-fail.js +++ b/test/parallel/test-assert-fail.js @@ -10,9 +10,10 @@ assert.throws( code: 'ERR_ASSERTION', name: 'AssertionError [ERR_ASSERTION]', message: 'Failed', - operator: undefined, + operator: 'fail', actual: undefined, - expected: undefined + expected: undefined, + generatedMessage: true } ); @@ -23,9 +24,10 @@ assert.throws(() => { code: 'ERR_ASSERTION', name: 'AssertionError [ERR_ASSERTION]', message: 'custom message', - operator: undefined, + operator: 'fail', actual: undefined, - expected: undefined + expected: undefined, + generatedMessage: false }); // One arg = Error From 143365329d8ad7ff4d6f8a5ca1fbe274bc16a2cb Mon Sep 17 00:00:00 2001 From: James M Snell Date: Thu, 13 Sep 2018 09:31:48 -0700 Subject: [PATCH 40/77] http2: add http2stream.endAfterHeaders property Indicates is the END_STREAM flag was set on the received HEADERS frame PR-URL: https://github.com/nodejs/node/pull/22843 Fixes: https://github.com/nodejs/node/issues/22497 Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Colin Ihrig --- doc/api/http2.md | 11 +++++ lib/internal/http2/core.js | 9 +++- test/parallel/test-http2-endafterheaders.js | 50 +++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-http2-endafterheaders.js diff --git a/doc/api/http2.md b/doc/api/http2.md index 7aec57e1111291..feeb66aa88c108 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -958,6 +958,17 @@ added: v8.4.0 Set to `true` if the `Http2Stream` instance has been destroyed and is no longer usable. +#### http2stream.endAfterHeaders + + +* {boolean} + +Set the `true` if the `END_STREAM` flag was set in the request or response +HEADERS frame received, indicating that no additional data should be received +and the readable side of the `Http2Stream` will be closed. + #### http2stream.pending -* `buffer` {Buffer} A `Buffer` containing the bytes to decode. +* `buffer` {Buffer|TypedArray|DataView} A `Buffer`, or `TypedArray`, or + `DataView` containing the bytes to decode. * Returns: {string} Returns any remaining input stored in the internal buffer as a string. Bytes @@ -79,10 +80,11 @@ changes: character instead of one for each individual byte. --> -* `buffer` {Buffer} A `Buffer` containing the bytes to decode. +* `buffer` {Buffer|TypedArray|DataView} A `Buffer`, or `TypedArray`, or + `DataView` containing the bytes to decode. * Returns: {string} Returns a decoded string, ensuring that any incomplete multibyte characters at -the end of the `Buffer` are omitted from the returned string and stored in an -internal buffer for the next call to `stringDecoder.write()` or -`stringDecoder.end()`. + the end of the `Buffer`, or `TypedArray`, or `DataView` are omitted from the + returned string and stored in an internal buffer for the next call to + `stringDecoder.write()` or `stringDecoder.end()`. diff --git a/lib/string_decoder.js b/lib/string_decoder.js index b32249ad9e5830..e5f396cab30d3b 100644 --- a/lib/string_decoder.js +++ b/lib/string_decoder.js @@ -73,7 +73,7 @@ StringDecoder.prototype.write = function write(buf) { return buf; if (!ArrayBuffer.isView(buf)) throw new ERR_INVALID_ARG_TYPE('buf', - ['Buffer', 'Uint8Array', 'ArrayBufferView'], + ['Buffer', 'TypedArray', 'DataView'], buf); return decode(this[kNativeDecoder], buf); }; diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js index 6e4f4b121d20d7..c4607672b0420c 100644 --- a/test/parallel/test-string-decoder.js +++ b/test/parallel/test-string-decoder.js @@ -97,6 +97,17 @@ assert.strictEqual(decoder.lastTotal, 3); assert.strictEqual(decoder.end(), '\ufffd'); +// ArrayBufferView tests +const arrayBufferViewStr = 'String for ArrayBufferView tests\n'; +const inputBuffer = Buffer.from(arrayBufferViewStr.repeat(8), 'utf8'); +for (const expectView of common.getArrayBufferViews(inputBuffer)) { + assert.strictEqual( + decoder.write(expectView), + inputBuffer.toString('utf8') + ); + assert.strictEqual(decoder.end(), ''); +} + decoder = new StringDecoder('utf8'); assert.strictEqual(decoder.write(Buffer.from('E18B', 'hex')), ''); assert.strictEqual(decoder.end(), '\ufffd'); @@ -174,8 +185,8 @@ common.expectsError( { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, - message: 'The "buf" argument must be one of type Buffer, Uint8Array, or' + - ' ArrayBufferView. Received type object' + message: 'The "buf" argument must be one of type Buffer, TypedArray,' + + ' or DataView. Received type object' } ); From 2a3dea596747eb4dcfccbad7b772a31ac8d9a818 Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Sat, 15 Sep 2018 12:38:01 -0700 Subject: [PATCH 45/77] doc: update 6.x to 8.x in backporting wiki PR-URL: https://github.com/nodejs/node/pull/22879 Reviewed-By: Vse Mozhet Byt Reviewed-By: Luigi Pinca --- doc/guides/backporting-to-release-lines.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/guides/backporting-to-release-lines.md b/doc/guides/backporting-to-release-lines.md index 751df9137d2fc4..7dee8b0e640eed 100644 --- a/doc/guides/backporting-to-release-lines.md +++ b/doc/guides/backporting-to-release-lines.md @@ -26,8 +26,8 @@ commits be cherry-picked or backported. ## How to submit a backport pull request -For the following steps, let's assume that a backport is needed for the v6.x -release line. All commands will use the `v6.x-staging` branch as the target +For the following steps, let's assume that a backport is needed for the v8.x +release line. All commands will use the `v8.x-staging` branch as the target branch. In order to submit a backport pull request to another branch, simply replace that with the staging branch for the targeted release line. @@ -40,10 +40,10 @@ replace that with the staging branch for the targeted release line. # the origin remote points to your fork, and the upstream remote points # to git://github.com/nodejs/node cd $NODE_DIR -# If v6.x-staging is checked out `pull` should be used instead of `fetch` -git fetch upstream v6.x-staging:v6.x-staging -f +# If v8.x-staging is checked out `pull` should be used instead of `fetch` +git fetch upstream v8.x-staging:v8.x-staging -f # Assume we want to backport PR #10157 -git checkout -b backport-10157-to-v6.x v6.x-staging +git checkout -b backport-10157-to-v8.x v8.x-staging # Ensure there are no test artifacts from previous builds # Note that this command deletes all files and directories # not under revision control below the ./test directory. @@ -72,19 +72,19 @@ hint: and commit the result with 'git commit' 7. Make sure `make -j4 test` passes. 8. Push the changes to your fork 9. Open a pull request: - 1. Be sure to target the `v6.x-staging` branch in the pull request. + 1. Be sure to target the `v8.x-staging` branch in the pull request. 2. Include the backport target in the pull request title in the following - format — `[v6.x backport] `. - Example: `[v6.x backport] process: improve performance of nextTick` + format — `[v8.x backport] `. + Example: `[v8.x backport] process: improve performance of nextTick` 3. Check the checkbox labeled "Allow edits from maintainers". 4. In the description add a reference to the original PR 5. Run a [`node-test-pull-request`][] CI job (with `REBASE_ONTO` set to the default ``) 10. If during the review process conflicts arise, use the following to rebase: - `git pull --rebase upstream v6.x-staging` + `git pull --rebase upstream v8.x-staging` -After the PR lands replace the `backport-requested-v6.x` label on the original -PR with `backported-to-v6.x`. +After the PR lands replace the `backport-requested-v8.x` label on the original +PR with `backported-to-v8.x`. [Release Schedule]: https://github.com/nodejs/Release#release-schedule1 [Release Plan]: https://github.com/nodejs/Release#release-plan From 325b82a28256871f5a57c74eb4c0dda214748903 Mon Sep 17 00:00:00 2001 From: Eugene Ostroukhov Date: Sat, 8 Sep 2018 19:45:10 -0700 Subject: [PATCH 46/77] inspector: enable Inspector JS API in workers PR-URL: https://github.com/nodejs/node/pull/22769 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- lib/inspector.js | 2 +- lib/internal/util/inspector.js | 4 +-- lib/internal/worker.js | 4 ++- src/inspector/main_thread_interface.cc | 7 ---- src/inspector/main_thread_interface.h | 1 - src/inspector/tracing_agent.cc | 13 +++++--- src/inspector_agent.cc | 30 ++++++++++++++--- src/inspector_agent.h | 4 ++- src/node.cc | 2 +- src/node_worker.cc | 32 +++++++++++++++++-- src/node_worker.h | 3 +- test/common/README.md | 5 +++ test/common/index.js | 11 ++++--- test/parallel/test-bootstrap-modules.js | 2 +- .../test-inspector-port-zero-cluster.js | 1 + .../parallel/test-inspector-tracing-domain.js | 1 + .../test-trace-events-dynamic-enable.js | 1 + test/parallel/test-warn-sigprof.js | 2 ++ ...st-inspector-async-hook-setup-at-signal.js | 2 ++ test/sequential/test-inspector-contexts.js | 6 +++- .../sequential/test-inspector-port-cluster.js | 1 + 21 files changed, 99 insertions(+), 35 deletions(-) diff --git a/lib/inspector.js b/lib/inspector.js index 8827158757e126..6988eccf82c9ef 100644 --- a/lib/inspector.js +++ b/lib/inspector.js @@ -14,7 +14,7 @@ const util = require('util'); const { Connection, open, url } = process.binding('inspector'); const { originalConsole } = require('internal/process/per_thread'); -if (!Connection || !require('internal/worker').isMainThread) +if (!Connection) throw new ERR_INSPECTOR_NOT_AVAILABLE(); const connectionSymbol = Symbol('connectionProperty'); diff --git a/lib/internal/util/inspector.js b/lib/internal/util/inspector.js index 3dd73415ded862..634d3302333584 100644 --- a/lib/internal/util/inspector.js +++ b/lib/internal/util/inspector.js @@ -1,8 +1,6 @@ 'use strict'; -// TODO(addaleax): Figure out how to integrate the inspector with workers. -const hasInspector = process.config.variables.v8_enable_inspector === 1 && - require('internal/worker').isMainThread; +const hasInspector = process.config.variables.v8_enable_inspector === 1; const inspector = hasInspector ? require('inspector') : undefined; let session; diff --git a/lib/internal/worker.js b/lib/internal/worker.js index 402fc30b591d2d..4f797dd9e0094c 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -17,6 +17,7 @@ const { MessagePort, MessageChannel } = internalBinding('messaging'); const { handle_onclose } = internalBinding('symbols'); const { clearAsyncIdStack } = require('internal/async_hooks'); const { serializeError, deserializeError } = require('internal/error-serdes'); +const { pathToFileURL } = require('url'); util.inherits(MessagePort, EventEmitter); @@ -257,8 +258,9 @@ class Worker extends EventEmitter { } } + const url = options.eval ? null : pathToFileURL(filename); // Set up the C++ handle for the worker, as well as some internal wiring. - this[kHandle] = new WorkerImpl(); + this[kHandle] = new WorkerImpl(url); this[kHandle].onexit = (code) => this[kOnExit](code); this[kPort] = this[kHandle].messagePort; this[kPort].on('message', (data) => this[kOnMessage](data)); diff --git a/src/inspector/main_thread_interface.cc b/src/inspector/main_thread_interface.cc index d8ee737ce2fce0..d3f553caac8f9f 100644 --- a/src/inspector/main_thread_interface.cc +++ b/src/inspector/main_thread_interface.cc @@ -354,13 +354,6 @@ void MainThreadHandle::Reset() { main_thread_ = nullptr; } -Agent* MainThreadHandle::GetInspectorAgent() { - Mutex::ScopedLock scoped_lock(block_lock_); - if (main_thread_ == nullptr) - return nullptr; - return main_thread_->inspector_agent(); -} - std::unique_ptr MainThreadHandle::MakeDelegateThreadSafe( std::unique_ptr delegate) { diff --git a/src/inspector/main_thread_interface.h b/src/inspector/main_thread_interface.h index db79db43821a89..7092310e553c19 100644 --- a/src/inspector/main_thread_interface.h +++ b/src/inspector/main_thread_interface.h @@ -54,7 +54,6 @@ class MainThreadHandle : public std::enable_shared_from_this { return ++next_object_id_; } bool Post(std::unique_ptr request); - Agent* GetInspectorAgent(); std::unique_ptr MakeDelegateThreadSafe( std::unique_ptr delegate); bool Expired(); diff --git a/src/inspector/tracing_agent.cc b/src/inspector/tracing_agent.cc index 6e962b289ab36f..fe69e6f863e2a6 100644 --- a/src/inspector/tracing_agent.cc +++ b/src/inspector/tracing_agent.cc @@ -74,11 +74,14 @@ DispatchResponse TracingAgent::start( if (categories_set.empty()) return DispatchResponse::Error("At least one category should be enabled"); - trace_writer_ = env_->tracing_agent_writer()->agent()->AddClient( - categories_set, - std::unique_ptr( - new InspectorTraceWriter(frontend_.get())), - tracing::Agent::kIgnoreDefaultCategories); + auto* writer = env_->tracing_agent_writer(); + if (writer != nullptr) { + trace_writer_ = env_->tracing_agent_writer()->agent()->AddClient( + categories_set, + std::unique_ptr( + new InspectorTraceWriter(frontend_.get())), + tracing::Agent::kIgnoreDefaultCategories); + } return DispatchResponse::OK(); } diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index da19eefe368efd..c8bface6bf5372 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -189,6 +189,12 @@ static int StartDebugSignalHandler() { const int CONTEXT_GROUP_ID = 1; +std::string GetWorkerLabel(node::Environment* env) { + std::ostringstream result; + result << "Worker[" << env->thread_id() << "]"; + return result.str(); +} + class ChannelImpl final : public v8_inspector::V8Inspector::Channel, public protocol::FrontendChannel { public: @@ -373,10 +379,13 @@ void NotifyClusterWorkersDebugEnabled(Environment* env) { class NodeInspectorClient : public V8InspectorClient { public: - explicit NodeInspectorClient(node::Environment* env) : env_(env) { + explicit NodeInspectorClient(node::Environment* env, bool is_main) + : env_(env), is_main_(is_main) { client_ = V8Inspector::create(env->isolate(), this); // TODO(bnoordhuis) Make name configurable from src/node.cc. - ContextInfo info(GetHumanReadableProcessName()); + std::string name = + is_main_ ? GetHumanReadableProcessName() : GetWorkerLabel(env); + ContextInfo info(name); info.is_default = true; contextCreated(env->context(), info); } @@ -593,6 +602,7 @@ class NodeInspectorClient : public V8InspectorClient { } node::Environment* env_; + bool is_main_; bool running_nested_loop_ = false; std::unique_ptr client_; std::unordered_map> channels_; @@ -610,13 +620,23 @@ Agent::Agent(Environment* env) : parent_env_(env), debug_options_(env->options()->debug_options) {} -Agent::~Agent() = default; +Agent::~Agent() { + if (start_io_thread_async.data == this) { + start_io_thread_async.data = nullptr; + // This is global, will never get freed + uv_close(reinterpret_cast(&start_io_thread_async), nullptr); + } +} bool Agent::Start(const std::string& path, - std::shared_ptr options) { + std::shared_ptr options, + bool is_main) { + if (options == nullptr) { + options = std::make_shared(); + } path_ = path; debug_options_ = options; - client_ = std::make_shared(parent_env_); + client_ = std::make_shared(parent_env_, is_main); if (parent_env_->is_main_thread()) { CHECK_EQ(0, uv_async_init(parent_env_->event_loop(), &start_io_thread_async, diff --git a/src/inspector_agent.h b/src/inspector_agent.h index d9e2232dcc4d7b..79ae8d4cd99404 100644 --- a/src/inspector_agent.h +++ b/src/inspector_agent.h @@ -47,7 +47,9 @@ class Agent { ~Agent(); // Create client_, may create io_ if option enabled - bool Start(const std::string& path, std::shared_ptr options); + bool Start(const std::string& path, + std::shared_ptr options, + bool is_worker); // Stop and destroy io_ void Stop(); diff --git a/src/node.cc b/src/node.cc index 657822b68bad63..91d90c5bc6c44c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -327,7 +327,7 @@ static struct { // right away on the websocket port and fails to bind/etc, this will return // false. return env->inspector_agent()->Start( - script_path == nullptr ? "" : script_path, options); + script_path == nullptr ? "" : script_path, options, true); } bool InspectorStarted(Environment* env) { diff --git a/src/node_worker.cc b/src/node_worker.cc index fa192d1291ec84..e9f591c2e143e5 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -35,10 +35,26 @@ namespace { uint64_t next_thread_id = 1; Mutex next_thread_id_mutex; +#if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR +void StartWorkerInspector(Environment* child, const std::string& url) { + child->inspector_agent()->Start(url, nullptr, false); +} + +void WaitForWorkerInspectorToStop(Environment* child) { + child->inspector_agent()->WaitForDisconnect(); + child->inspector_agent()->Stop(); +} + +#else +// No-ops +void StartWorkerInspector(Environment* child, const std::string& url) {} +void WaitForWorkerInspectorToStop(Environment* child) {} +#endif + } // anonymous namespace -Worker::Worker(Environment* env, Local wrap) - : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_WORKER) { +Worker::Worker(Environment* env, Local wrap, const std::string& url) + : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_WORKER), url_(url) { // Generate a new thread id. { Mutex::ScopedLock next_thread_id_lock(next_thread_id_mutex); @@ -155,6 +171,7 @@ void Worker::Run() { env_->async_hooks()->pop_async_id(1); Debug(this, "Loaded environment for worker %llu", thread_id_); + StartWorkerInspector(env_.get(), url_); } { @@ -215,6 +232,7 @@ void Worker::Run() { env_->stop_sub_worker_contexts(); env_->RunCleanup(); RunAtExit(env_.get()); + WaitForWorkerInspectorToStop(env_.get()); { Mutex::ScopedLock stopped_lock(stopped_mutex_); @@ -350,7 +368,15 @@ void Worker::New(const FunctionCallbackInfo& args) { return; } - new Worker(env, args.This()); + std::string url; + // Argument might be a string or URL + if (args.Length() == 1 && !args[0]->IsNullOrUndefined()) { + Utf8Value value( + args.GetIsolate(), + args[0]->ToString(env->context()).FromMaybe(v8::Local())); + url.append(value.out(), value.length()); + } + new Worker(env, args.This(), url); } void Worker::StartThread(const FunctionCallbackInfo& args) { diff --git a/src/node_worker.h b/src/node_worker.h index 33df36e04ce670..8491ad221b6dde 100644 --- a/src/node_worker.h +++ b/src/node_worker.h @@ -12,7 +12,7 @@ namespace worker { // A worker thread, as represented in its parent thread. class Worker : public AsyncWrap { public: - Worker(Environment* env, v8::Local wrap); + Worker(Environment* env, v8::Local wrap, const std::string& url); ~Worker(); // Run the worker. This is only called from the worker thread. @@ -52,6 +52,7 @@ class Worker : public AsyncWrap { uv_loop_t loop_; DeleteFnPtr isolate_data_; DeleteFnPtr env_; + const std::string url_; v8::Isolate* isolate_ = nullptr; DeleteFnPtr array_buffer_allocator_; diff --git a/test/common/README.md b/test/common/README.md index 28d9bd04f0a8b6..0b3a7e9201e4f6 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -361,6 +361,11 @@ was disabled at compile time. Skip the rest of the tests in the current file when the Node.js executable was compiled with a pointer size smaller than 64 bits. +### skipIfWorker() + +Skip the rest of the tests in the current file when not running on a main +thread. + ## ArrayStream Module The `ArrayStream` module provides a simple `Stream` that pushes elements from diff --git a/test/common/index.js b/test/common/index.js index 0da37360bc4aa1..f48652bb06bb11 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -613,10 +613,6 @@ function skipIfInspectorDisabled() { if (process.config.variables.v8_enable_inspector === 0) { skip('V8 inspector is disabled'); } - if (!isMainThread) { - // TODO(addaleax): Fix me. - skip('V8 inspector is not available in Workers'); - } } function skipIf32Bits() { @@ -625,6 +621,12 @@ function skipIf32Bits() { } } +function skipIfWorker() { + if (!isMainThread) { + skip('This test only works on a main thread'); + } +} + function getArrayBufferViews(buf) { const { buffer, byteOffset, byteLength } = buf; @@ -743,6 +745,7 @@ module.exports = { skipIf32Bits, skipIfEslintMissing, skipIfInspectorDisabled, + skipIfWorker, get localhostIPv6() { return '::1'; }, diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index 81563355d246ff..fdd651d3eeed84 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -11,4 +11,4 @@ const list = process.moduleLoadList.slice(); const assert = require('assert'); -assert(list.length <= 74, list); +assert(list.length <= 75, list); diff --git a/test/parallel/test-inspector-port-zero-cluster.js b/test/parallel/test-inspector-port-zero-cluster.js index e522056571d1c2..0330f1d50e6f70 100644 --- a/test/parallel/test-inspector-port-zero-cluster.js +++ b/test/parallel/test-inspector-port-zero-cluster.js @@ -3,6 +3,7 @@ const common = require('../common'); common.skipIfInspectorDisabled(); +common.skipIfWorker(); // Assert that even when started with `--inspect=0` workers are assigned // consecutive (i.e. deterministically predictable) debug ports diff --git a/test/parallel/test-inspector-tracing-domain.js b/test/parallel/test-inspector-tracing-domain.js index 241e0dbec777f4..e86996eb5c5892 100644 --- a/test/parallel/test-inspector-tracing-domain.js +++ b/test/parallel/test-inspector-tracing-domain.js @@ -3,6 +3,7 @@ const common = require('../common'); common.skipIfInspectorDisabled(); +common.skipIfWorker(); // https://github.com/nodejs/node/issues/22767 const assert = require('assert'); const { Session } = require('inspector'); diff --git a/test/parallel/test-trace-events-dynamic-enable.js b/test/parallel/test-trace-events-dynamic-enable.js index a32949f8ec5994..24a186c15a85c7 100644 --- a/test/parallel/test-trace-events-dynamic-enable.js +++ b/test/parallel/test-trace-events-dynamic-enable.js @@ -3,6 +3,7 @@ const common = require('../common'); common.skipIfInspectorDisabled(); +common.skipIfWorker(); // https://github.com/nodejs/node/issues/22767 const assert = require('assert'); const { performance } = require('perf_hooks'); diff --git a/test/parallel/test-warn-sigprof.js b/test/parallel/test-warn-sigprof.js index e5335215d743b6..c3986a27be1703 100644 --- a/test/parallel/test-warn-sigprof.js +++ b/test/parallel/test-warn-sigprof.js @@ -10,6 +10,8 @@ common.skipIfInspectorDisabled(); if (common.isWindows) common.skip('test does not apply to Windows'); +common.skipIfWorker(); // Worker inspector never has a server running + common.expectWarning('Warning', 'process.on(SIGPROF) is reserved while debugging', common.noWarnCode); diff --git a/test/sequential/test-inspector-async-hook-setup-at-signal.js b/test/sequential/test-inspector-async-hook-setup-at-signal.js index 6f8ccfacb9964c..139678a1e5a493 100644 --- a/test/sequential/test-inspector-async-hook-setup-at-signal.js +++ b/test/sequential/test-inspector-async-hook-setup-at-signal.js @@ -6,6 +6,8 @@ common.skipIf32Bits(); const { NodeInstance } = require('../common/inspector-helper.js'); const assert = require('assert'); +common.skipIfWorker(); // Signal starts a server for a main thread inspector + const script = ` process._rawDebug('Waiting until a signal enables the inspector...'); let waiting = setInterval(waitUntilDebugged, 50); diff --git a/test/sequential/test-inspector-contexts.js b/test/sequential/test-inspector-contexts.js index d2285e82536326..793868e3bc072c 100644 --- a/test/sequential/test-inspector-contexts.js +++ b/test/sequential/test-inspector-contexts.js @@ -33,7 +33,11 @@ async function testContextCreatedAndDestroyed() { // the PID. strictEqual(name.includes(`[${process.pid}]`), true); } else { - strictEqual(`${process.argv0}[${process.pid}]`, name); + let expects = `${process.argv0}[${process.pid}]`; + if (!common.isMainThread) { + expects = `Worker[${require('worker_threads').threadId}]`; + } + strictEqual(expects, name); } strictEqual(origin, '', JSON.stringify(contextCreated)); diff --git a/test/sequential/test-inspector-port-cluster.js b/test/sequential/test-inspector-port-cluster.js index f7bebd926e9780..b58dbd83b6159a 100644 --- a/test/sequential/test-inspector-port-cluster.js +++ b/test/sequential/test-inspector-port-cluster.js @@ -3,6 +3,7 @@ const common = require('../common'); common.skipIfInspectorDisabled(); +common.skipIfWorker(); const assert = require('assert'); const cluster = require('cluster'); From 9ca9e815f468a3cddd768472130543c9b7187d17 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 28 Aug 2018 03:57:23 +0800 Subject: [PATCH 47/77] errors: add useOriginalName to internal/errors This allows us to tell the type of the errors without using instanceof, which is necessary in WPT harness. PR-URL: https://github.com/nodejs/node/pull/22556 Reviewed-By: John-David Dalton Reviewed-By: Gus Caplan Reviewed-By: Ruben Bridgewater Reviewed-By: Refael Ackermann --- lib/internal/errors.js | 12 ++++++- .../test-internal-error-original-names.js | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-internal-error-original-names.js diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 9ecad0aee920eb..8f438d343a10d6 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -151,6 +151,8 @@ function makeSystemErrorWithCode(key) { }; } +let useOriginalName = false; + function makeNodeErrorWithCode(Base, key) { return class NodeError extends Base { constructor(...args) { @@ -158,6 +160,9 @@ function makeNodeErrorWithCode(Base, key) { } get name() { + if (useOriginalName) { + return super.name; + } return `${super.name} [${key}]`; } @@ -439,7 +444,12 @@ module.exports = { getMessage, SystemError, codes, - E // This is exported only to facilitate testing. + // This is exported only to facilitate testing. + E, + // This allows us to tell the type of the errors without using + // instanceof, which is necessary in WPT harness. + get useOriginalName() { return useOriginalName; }, + set useOriginalName(value) { useOriginalName = value; } }; // To declare an error message, use the E(sym, val, def) function above. The sym diff --git a/test/parallel/test-internal-error-original-names.js b/test/parallel/test-internal-error-original-names.js new file mode 100644 index 00000000000000..195e39b199cd4c --- /dev/null +++ b/test/parallel/test-internal-error-original-names.js @@ -0,0 +1,35 @@ +// Flags: --expose-internals + +'use strict'; + +// This tests `internal/errors.useOriginalName` +// This testing feature is needed to allows us to assert the types of +// errors without using instanceof, which is necessary in WPT harness. +// Refs: https://github.com/nodejs/node/pull/22556 + +require('../common'); +const assert = require('assert'); +const errors = require('internal/errors'); + + +errors.E('TEST_ERROR_1', 'Error for testing purposes: %s', + Error); +{ + const err = new errors.codes.TEST_ERROR_1('test'); + assert(err instanceof Error); + assert.strictEqual(err.name, 'Error [TEST_ERROR_1]'); +} + +{ + errors.useOriginalName = true; + const err = new errors.codes.TEST_ERROR_1('test'); + assert(err instanceof Error); + assert.strictEqual(err.name, 'Error'); +} + +{ + errors.useOriginalName = false; + const err = new errors.codes.TEST_ERROR_1('test'); + assert(err instanceof Error); + assert.strictEqual(err.name, 'Error [TEST_ERROR_1]'); +} From e07e57311953ff7d26a71a5208ddf045f7f6fc5d Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Mon, 27 Aug 2018 14:02:18 +0800 Subject: [PATCH 48/77] build: do not lint fixtures in make lint-md PR-URL: https://github.com/nodejs/node/pull/22549 Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Rich Trott Reviewed-By: Refael Ackermann --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5325abe40c0307..5fc2bb0c58f553 100644 --- a/Makefile +++ b/Makefile @@ -1087,7 +1087,8 @@ tools/.docmdlintstamp: $(LINT_MD_DOC_FILES) LINT_MD_TARGETS = src lib benchmark test tools/doc tools/icu LINT_MD_ROOT_DOCS := $(wildcard *.md) LINT_MD_MISC_FILES := $(shell find $(LINT_MD_TARGETS) -type f \ - -not -path '*node_modules*' -name '*.md') $(LINT_MD_ROOT_DOCS) + -not -path '*node_modules*' -not -path 'test/fixtures/*' -name '*.md') \ + $(LINT_MD_ROOT_DOCS) run-lint-misc-md = tools/lint-md.js -q -f $(LINT_MD_MISC_FILES) # Lint other changed markdown files maintained by us tools/.miscmdlintstamp: $(LINT_MD_MISC_FILES) From 97f6ff3ba7d148064687f9dfa5bac2198b070d58 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Mon, 17 Sep 2018 14:31:55 -0700 Subject: [PATCH 49/77] doc: add boneskull as collaborator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/22917 Reviewed-By: Rich Trott Reviewed-By: Tobias Nießen Reviewed-By: Vse Mozhet Byt Reviewed-By: Gus Caplan --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 953d1a449c5bd3..15cbb2133351f3 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,8 @@ For more information about the governance of the Node.js project, see **Benedikt Meurer** <benedikt.meurer@gmail.com> * [bnoordhuis](https://github.com/bnoordhuis) - **Ben Noordhuis** <info@bnoordhuis.nl> +* [boneskull](https://github.com/boneskull) - +**Christopher Hiller** <boneskull@boneskull.com> (he/him) * [brendanashworth](https://github.com/brendanashworth) - **Brendan Ashworth** <brendan.ashworth@me.com> * [BridgeAR](https://github.com/BridgeAR) - From 97979b7fffd2549bdc898ded18a1603bdf4a31a1 Mon Sep 17 00:00:00 2001 From: Kyle Farnung Date: Mon, 10 Sep 2018 13:48:48 -0700 Subject: [PATCH 50/77] tools,win: fix find_python error On a machine without `python.exe` in the PATH the script was failing with: ```console > .\vcbuild.bat Looking for Python 2.x 2> was unexpected at this time. ``` Escaping the `>` seems to resolve it. PR-URL: https://github.com/nodejs/node/pull/22797 Reviewed-By: Richard Lau Reviewed-By: Refael Ackermann --- tools/msvs/find_python.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/msvs/find_python.cmd b/tools/msvs/find_python.cmd index 212b5275c318ae..1692ec1c30ad7e 100644 --- a/tools/msvs/find_python.cmd +++ b/tools/msvs/find_python.cmd @@ -26,7 +26,7 @@ EXIT /B :: Query registry sub-tree for InstallPath :find-key -FOR /F "delims=" %%a IN ('REG QUERY %1 /s 2> NUL ^| findstr "2." ^| findstr InstallPath') DO IF NOT ERRORLEVEL 1 CALL :find-path %%a +FOR /F "delims=" %%a IN ('REG QUERY %1 /s 2^> NUL ^| findstr "2." ^| findstr InstallPath') DO IF NOT ERRORLEVEL 1 CALL :find-path %%a EXIT /B :: Parse the value of %1 as the path for python.exe From 85fca5d77d6f96c352dc30e7718b7818c2f0822b Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Thu, 13 Sep 2018 16:46:57 -0700 Subject: [PATCH 51/77] tools: merge custom cpplint with cpplint v1.3.0 Merged https://github.com/cpplint/cpplint/blob/master/cpplint.py with our customized version to enable better IDE/editor integration. Made file executable. PR-URL: https://github.com/nodejs/node/pull/22864 Reviewed-By: Anna Henningsen Reviewed-By: Daniel Bevenius --- tools/cpplint.py | 625 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 491 insertions(+), 134 deletions(-) mode change 100644 => 100755 tools/cpplint.py diff --git a/tools/cpplint.py b/tools/cpplint.py old mode 100644 new mode 100755 index d96713aa80a1ff..8afcae72a3d833 --- a/tools/cpplint.py +++ b/tools/cpplint.py @@ -44,7 +44,9 @@ import codecs import copy import getopt +import glob import logging +import itertools import math # for log import os import re @@ -52,24 +54,53 @@ import string import sys import unicodedata +import xml.etree.ElementTree try: xrange except NameError: xrange = range +# if empty, use defaults +_header_extensions = set([]) +# if empty, use defaults +_valid_extensions = set([]) + +# Files with any of these extensions are considered to be +# header files (and will undergo different style checks). +# This set can be extended by using the --headers +# option (also supported in CPPLINT.cfg) +def GetHeaderExtensions(): + if not _header_extensions: + return set(['h', 'hpp', 'hxx', 'h++', 'cuh']) + return _header_extensions + +# The allowed extensions for file names +# This is set by --extensions flag +def GetAllExtensions(): + if not _valid_extensions: + return GetHeaderExtensions().union(set(['c', 'cc', 'cpp', 'cxx', 'c++', 'cu'])) + return _valid_extensions + +def GetNonHeaderExtensions(): + return GetAllExtensions().difference(GetHeaderExtensions()) logger = logging.getLogger('testrunner') _USAGE = """ -Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] - [--counting=total|toplevel|detailed] [--root=subdir] - [--linelength=digits] [--logfile=filename] +Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit] + [--filter=-x,+y,...] + [--counting=total|toplevel|detailed] [--repository=path] + [--root=subdir] [--linelength=digits] [--recursive] + [--exclude=path] + [--headers=ext1,ext2] + [--logfile=filename] + [--extensions=hpp,cpp,...] [file] ... The style guidelines this tries to follow are those in - https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml + https://google.github.io/styleguide/cppguide.html Every problem is given a confidence score from 1-5, with 5 meaning we are certain of the problem, and 1 meaning it could be a legitimate construct. @@ -80,17 +111,26 @@ suppresses errors of all categories on that line. The files passed in will be linted; at least one file must be provided. - Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the - extensions with the --extensions flag. + Default linted extensions are %s. + Other file types will be ignored. + Change the extensions with the --extensions flag. Flags: - output=vs7 - By default, the output is formatted to ease emacs parsing. Visual Studio - compatible output (vs7) may also be used. Other formats are unsupported. + output=emacs|eclipse|vs7|junit + By default, the output is formatted to ease emacs parsing. Output + compatible with eclipse (eclipse), Visual Studio (vs7), and JUnit + XML parsers such as those used in Jenkins and Bamboo may also be + used. Other formats are unsupported. verbose=# Specify a number 0-5 to restrict errors to certain verbosity levels. + Errors with lower verbosity levels have lower confidence and are more + likely to be false positives. + + quiet + Supress output other than linting errors, such as information about + which files have been processed and excluded. filter=-x,+y,... Specify a comma-separated list of category-filters to apply: only @@ -114,17 +154,40 @@ also be printed. If 'detailed' is provided, then a count is provided for each category like 'build/class'. + repository=path + The top level directory of the repository, used to derive the header + guard CPP variable. By default, this is determined by searching for a + path that contains .git, .hg, or .svn. When this flag is specified, the + given path is used instead. This option allows the header guard CPP + variable to remain consistent even if members of a team have different + repository root directories (such as when checking out a subdirectory + with SVN). In addition, users of non-mainstream version control systems + can use this flag to ensure readable header guard CPP variables. + + Examples: + Assuming that Alice checks out ProjectName and Bob checks out + ProjectName/trunk and trunk contains src/chrome/ui/browser.h, then + with no --repository flag, the header guard CPP variable will be: + + Alice => TRUNK_SRC_CHROME_BROWSER_UI_BROWSER_H_ + Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_ + + If Alice uses the --repository=trunk flag and Bob omits the flag or + uses --repository=. then the header guard CPP variable will be: + + Alice => SRC_CHROME_BROWSER_UI_BROWSER_H_ + Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_ + root=subdir - The root directory used for deriving header guard CPP variable. - By default, the header guard CPP variable is calculated as the relative - path to the directory that contains .git, .hg, or .svn. When this flag - is specified, the relative path is calculated from the specified - directory. If the specified directory does not exist, this flag is - ignored. + The root directory used for deriving header guard CPP variables. This + directory is relative to the top level directory of the repository which + by default is determined by searching for a directory that contains .git, + .hg, or .svn but can also be controlled with the --repository flag. If + the specified directory does not exist, this flag is ignored. Examples: - Assuming that src/.git exists, the header guard CPP variables for - src/chrome/browser/ui/browser.h are: + Assuming that src is the top level directory of the repository, the + header guard CPP variables for src/chrome/browser/ui/browser.h are: No flag => CHROME_BROWSER_UI_BROWSER_H_ --root=chrome => BROWSER_UI_BROWSER_H_ @@ -137,14 +200,36 @@ Examples: --linelength=120 + recursive + Search for files to lint recursively. Each directory given in the list + of files to be linted is replaced by all files that descend from that + directory. Files with extensions not in the valid extensions list are + excluded. + + exclude=path + Exclude the given path from the list of files to be linted. Relative + paths are evaluated relative to the current directory and shell globbing + is performed. This flag can be provided multiple times to exclude + multiple files. + + Examples: + --exclude=one.cc + --exclude=src/*.cc + --exclude=src/*.cc --exclude=test/*.cc + extensions=extension,extension,... The allowed file extensions that cpplint will check Examples: - --extensions=hpp,cpp + --extensions=%s + + headers=extension,extension,... + The allowed header extensions that cpplint will consider to be header files + (by default, only files with extensions %s + will be assumed to be headers) - logfile=filename - Write TAP output to a logfile. + Examples: + --headers=%s cpplint.py supports per-directory configurations specified in CPPLINT.cfg files. CPPLINT.cfg file can contain a number of key=value pairs. @@ -154,6 +239,7 @@ filter=+filter1,-filter2,... exclude_files=regex linelength=80 + root=subdir "set noparent" option prevents cpplint from traversing directory tree upwards looking for more .cfg files in parent directories. This option @@ -165,22 +251,28 @@ "exclude_files" allows to specify a regular expression to be matched against a file name. If the expression matches, the file is skipped and not run - through liner. + through the linter. + + "linelength" specifies the allowed line length for the project. - "linelength" allows to specify the allowed line length for the project. + The "root" option is similar in function to the --root flag (see example + above). CPPLINT.cfg has an effect on files in the same directory and all - sub-directories, unless overridden by a nested configuration file. + subdirectories, unless overridden by a nested configuration file. Example file: filter=-build/include_order,+build/include_alpha - exclude_files=.*\.cc + exclude_files=.*\\.cc The above example disables build/include_order warning and enables build/include_alpha as well as excludes all .cc from being processed by linter, in the current directory (where the .cfg - file is located) and all sub-directories. -""" + file is located) and all subdirectories. +""" % (list(GetAllExtensions()), + ','.join(list(GetAllExtensions())), + GetHeaderExtensions(), + ','.join(GetHeaderExtensions())) # We categorize each error message we print. Here are the categories. # We want an explicit list so we can list them all in cpplint --filter=. @@ -200,6 +292,7 @@ 'build/include_alpha', 'build/include_order', 'build/include_what_you_use', + 'build/namespaces_literals', 'build/namespaces', 'build/printf_format', 'build/storage_class', @@ -270,6 +363,7 @@ '-build/include', '-build/include_alpha', '-build/include_order', + '-build/include_subdir', '-legal/copyright', ] @@ -447,7 +541,8 @@ r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$') # Pattern for matching FileInfo.BaseName() against test file name -_TEST_FILE_SUFFIX = r'(_test|_unittest|_regtest)$' +_test_suffixes = ['_test', '_regtest', '_unittest'] +_TEST_FILE_SUFFIX = '(' + '|'.join(_test_suffixes) + r')$' # Pattern that matches only complete whitespace, possibly across multiple lines. _EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL) @@ -461,7 +556,7 @@ ] # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE -_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) +_CHECK_REPLACEMENT = dict([(macro_var, {}) for macro_var in _CHECK_MACROS]) for op, replacement in [('==', 'EQ'), ('!=', 'NE'), ('>=', 'GE'), ('>', 'GT'), @@ -504,6 +599,7 @@ _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') + # These constants define types of headers for use with # _IncludeState.CheckNextIncludeOrder(). _C_SYS_HEADER = 1 @@ -546,13 +642,54 @@ # This is set by --root flag. _root = None +# The top level repository directory. If set, _root is calculated relative to +# this directory instead of the directory containing version control artifacts. +# This is set by the --repository flag. +_repository = None + +# Files to exclude from linting. This is set by the --exclude flag. +_excludes = None + +# Whether to supress PrintInfo messages +_quiet = False + # The allowed line length of files. # This is set by --linelength flag. _line_length = 80 -# The allowed extensions for file names -# This is set by --extensions flag. -_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh']) +try: + xrange(1, 0) +except NameError: + # -- pylint: disable=redefined-builtin + xrange = range + +try: + unicode +except NameError: + # -- pylint: disable=redefined-builtin + basestring = unicode = str + +try: + long(2) +except NameError: + # -- pylint: disable=redefined-builtin + long = int + +if sys.version_info < (3,): + # -- pylint: disable=no-member + # BINARY_TYPE = str + itervalues = dict.itervalues + iteritems = dict.iteritems +else: + # BINARY_TYPE = bytes + itervalues = dict.values + iteritems = dict.items + +def unicode_escape_decode(x): + if sys.version_info < (3,): + return codecs.unicode_escape_decode(x)[0] + else: + return x # {str, bool}: a map from error categories to booleans which indicate if the # category should be suppressed for every line. @@ -670,7 +807,7 @@ def Search(pattern, s): def _IsSourceExtension(s): """File extension (excluding dot) matches a source file extension.""" - return s in ('c', 'cc', 'cpp', 'cxx') + return s in GetNonHeaderExtensions() class _IncludeState(object): @@ -710,6 +847,8 @@ class _IncludeState(object): def __init__(self): self.include_list = [[]] + self._section = None + self._last_header = None self.ResetSection('') def FindHeader(self, header): @@ -853,9 +992,16 @@ def __init__(self): # output format: # "emacs" - format that emacs can parse (default) + # "eclipse" - format that eclipse can parse # "vs7" - format that Microsoft Visual Studio 7 can parse + # "junit" - format that Jenkins, Bamboo, etc can parse self.output_format = 'emacs' + # For JUnit output, save errors and failures until the end so that they + # can be written into the XML + self._junit_errors = [] + self._junit_failures = [] + def SetOutputFormat(self, output_format): """Sets the output format for errors.""" self.output_format = output_format @@ -924,10 +1070,69 @@ def IncrementErrorCount(self, category): def PrintErrorCounts(self): """Print a summary of errors by category, and the total.""" - for category, count in self.errors_by_category.iteritems(): - sys.stderr.write('Category \'%s\' errors found: %d\n' % + for category, count in sorted(iteritems(self.errors_by_category)): + self.PrintInfo('Category \'%s\' errors found: %d\n' % (category, count)) - sys.stderr.write('Total errors found: %d\n' % self.error_count) + if self.error_count > 0: + self.PrintInfo('Total errors found: %d\n' % self.error_count) + + def PrintInfo(self, message): + if not _quiet and self.output_format != 'junit': + sys.stderr.write(message) + + def PrintError(self, message): + if self.output_format == 'junit': + self._junit_errors.append(message) + else: + sys.stderr.write(message) + + def AddJUnitFailure(self, filename, linenum, message, category, confidence): + self._junit_failures.append((filename, linenum, message, category, + confidence)) + + def FormatJUnitXML(self): + num_errors = len(self._junit_errors) + num_failures = len(self._junit_failures) + + testsuite = xml.etree.ElementTree.Element('testsuite') + testsuite.attrib['name'] = 'cpplint' + testsuite.attrib['errors'] = str(num_errors) + testsuite.attrib['failures'] = str(num_failures) + + if num_errors == 0 and num_failures == 0: + testsuite.attrib['tests'] = str(1) + xml.etree.ElementTree.SubElement(testsuite, 'testcase', name='passed') + + else: + testsuite.attrib['tests'] = str(num_errors + num_failures) + if num_errors > 0: + testcase = xml.etree.ElementTree.SubElement(testsuite, 'testcase') + testcase.attrib['name'] = 'errors' + error = xml.etree.ElementTree.SubElement(testcase, 'error') + error.text = '\n'.join(self._junit_errors) + if num_failures > 0: + # Group failures by file + failed_file_order = [] + failures_by_file = {} + for failure in self._junit_failures: + failed_file = failure[0] + if failed_file not in failed_file_order: + failed_file_order.append(failed_file) + failures_by_file[failed_file] = [] + failures_by_file[failed_file].append(failure) + # Create a testcase for each file + for failed_file in failed_file_order: + failures = failures_by_file[failed_file] + testcase = xml.etree.ElementTree.SubElement(testsuite, 'testcase') + testcase.attrib['name'] = failed_file + failure = xml.etree.ElementTree.SubElement(testcase, 'failure') + template = '{0}: {1} [{2}] [{3}]' + texts = [template.format(f[1], f[2], f[3], f[4]) for f in failures] + failure.text = '\n'.join(texts) + + xml_decl = '\n' + return xml_decl + xml.etree.ElementTree.tostring(testsuite, 'utf-8').decode('utf-8') + _cpplint_state = _CppLintState() @@ -1173,7 +1378,7 @@ def Error(filename, linenum, category, confidence, message): if _ShouldPrintError(category, confidence, linenum): _cpplint_state.IncrementErrorCount(category) if _cpplint_state.output_format == 'vs7': - sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( + _cpplint_state.PrintError('%s(%s): warning: %s [%s] [%d]\n' % ( filename, linenum, message, category, confidence)) elif _cpplint_state.output_format == 'eclipse': sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( @@ -1188,9 +1393,9 @@ def Error(filename, linenum, category, confidence, message): ' ...') logger.info(template % locals()) else: - sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( - filename, linenum, message, category, confidence)) - + final_message = '%s:%s: %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence) + sys.stderr.write(final_message) # Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( @@ -1748,7 +1953,12 @@ def GetHeaderGuardCPPVariable(filename): fileinfo = FileInfo(filename) file_path_from_root = fileinfo.RepositoryName() if _root: - file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root) + suffix = os.sep + # On Windows using directory separator will leave us with + # "bogus escape error" unless we properly escape regex. + if suffix == '\\': + suffix += '\\' + file_path_from_root = re.sub('^' + _root + suffix, '', file_path_from_root) return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_' @@ -1775,6 +1985,11 @@ def CheckForHeaderGuard(filename, clean_lines, error): if Search(r'//\s*NOLINT\(build/header_guard\)', i): return + # Allow pragma once instead of header guards + for i in raw_lines: + if Search(r'^\s*#pragma\s+once', i): + return + cppvar = GetHeaderGuardCPPVariable(filename) ifndef = '' @@ -1851,28 +2066,30 @@ def CheckForHeaderGuard(filename, clean_lines, error): def CheckHeaderFileIncluded(filename, include_state, error): - """Logs an error if a .cc file does not include its header.""" + """Logs an error if a source file does not include its header.""" # Do not check test files fileinfo = FileInfo(filename) if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()): return - headerfile = filename[0:len(filename) - len(fileinfo.Extension())] + '.h' - if not os.path.exists(headerfile): - return - headername = FileInfo(headerfile).RepositoryName() - first_include = 0 - for section_list in include_state.include_list: - for f in section_list: - if headername in f[0] or f[0] in headername: - return - if not first_include: - first_include = f[1] + for ext in GetHeaderExtensions(): + basefilename = filename[0:len(filename) - len(fileinfo.Extension())] + headerfile = basefilename + '.' + ext + if not os.path.exists(headerfile): + continue + headername = FileInfo(headerfile).RepositoryName() + first_include = None + for section_list in include_state.include_list: + for f in section_list: + if headername in f[0] or f[0] in headername: + return + if not first_include: + first_include = f[1] - error(filename, first_include, 'build/include', 5, - '%s should include its header file %s' % (fileinfo.RepositoryName(), - headername)) + error(filename, first_include, 'build/include', 5, + '%s should include its header file %s' % (fileinfo.RepositoryName(), + headername)) def CheckForBadCharacters(filename, lines, error): @@ -1893,7 +2110,7 @@ def CheckForBadCharacters(filename, lines, error): error: The function to call with any errors found. """ for linenum, line in enumerate(lines): - if u'\ufffd' in line: + if unicode_escape_decode('\ufffd') in line: error(filename, linenum, 'readability/utf8', 5, 'Line contains invalid UTF-8 (or Unicode replacement character).') if '\0' in line: @@ -2537,7 +2754,7 @@ def Update(self, filename, clean_lines, linenum, error): # class LOCKABLE API Object { # }; class_decl_match = Match( - r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?' + r'^(\s*(?:template\s*<[\w\s<>,:=]*>\s*)?' r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))' r'(.*)$', line) if (class_decl_match and @@ -2785,6 +3002,7 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, constructor_args[i] = constructor_arg i += 1 + variadic_args = [arg for arg in constructor_args if '&&...' in arg] defaulted_args = [arg for arg in constructor_args if '=' in arg] noarg_constructor = (not constructor_args or # empty arg list # 'void' arg specifier @@ -2795,7 +3013,10 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, # all but at most one arg defaulted (len(constructor_args) >= 1 and not noarg_constructor and - len(defaulted_args) >= len(constructor_args) - 1)) + len(defaulted_args) >= len(constructor_args) - 1) or + # variadic arguments with zero or one argument + (len(constructor_args) <= 2 and + len(variadic_args) >= 1)) initializer_list_constructor = bool( onearg_constructor and Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0])) @@ -2808,7 +3029,7 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, onearg_constructor and not initializer_list_constructor and not copy_constructor): - if defaulted_args: + if defaulted_args or variadic_args: error(filename, linenum, 'runtime/explicit', 5, 'Constructors callable with one argument ' 'should be marked explicit.') @@ -3046,7 +3267,7 @@ def CheckComment(line, filename, linenum, next_line_start, error): # If the comment contains an alphanumeric character, there # should be a space somewhere between it and the // unless # it's a /// or //! Doxygen comment. - if (Match(r'(?://[^ ]*\w)|(?:////\s*$)', comment) and + if (Match(r'//[^ ]*\w', comment) and not Match(r'(///|//\!)(\s+|$)', comment)): error(filename, linenum, 'whitespace/comments', 4, 'Should have a space between // and comment') @@ -3568,7 +3789,6 @@ def IsDecltype(clean_lines, linenum, column): return True return False - def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): """Checks for additional blank line issues related to sections. @@ -3901,6 +4121,14 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error): # outputting warnings for the matching closing brace, if there are # nested blocks with trailing semicolons, we will get the error # messages in reversed order. + + # We need to check the line forward for NOLINT + raw_lines = clean_lines.raw_lines + ParseNolintSuppressions(filename, raw_lines[endlinenum-1], endlinenum-1, + error) + ParseNolintSuppressions(filename, raw_lines[endlinenum], endlinenum, + error) + error(filename, endlinenum, 'readability/braces', 4, "You don't need a ; after a }") @@ -3978,12 +4206,12 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error): return if closing_linenum > opening_linenum: # Opening line after the {. Ignore comments here since we checked above. - body = list(opening_line[opening_pos+1:]) + bodylist = list(opening_line[opening_pos+1:]) # All lines until closing line, excluding closing line, with comments. - body.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum]) + bodylist.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum]) # Closing line before the }. Won't (and can't) have comments. - body.append(clean_lines.elided[closing_linenum][:closing_pos-1]) - body = '\n'.join(body) + bodylist.append(clean_lines.elided[closing_linenum][:closing_pos-1]) + body = '\n'.join(bodylist) else: # If statement has brackets and fits on a single line. body = opening_line[opening_pos+1:closing_pos-1] @@ -4318,7 +4546,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, # Check if the line is a header guard. is_header_guard = False - if file_extension == 'h': + if file_extension in GetHeaderExtensions(): cppvar = GetHeaderGuardCPPVariable(filename) if (line.startswith('#ifndef %s' % cppvar) or line.startswith('#define %s' % cppvar) or @@ -4332,16 +4560,23 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, # # The "$Id:...$" comment may also get very long without it being the # developers fault. + # + # Doxygen documentation copying can get pretty long when using an overloaded + # function declaration if (not line.startswith('#include') and not is_header_guard and not Match(r'^\s*//.*http(s?)://\S*$', line) and not Match(r'^\s*//\s*[^\s]*$', line) and - not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): + not Match(r'^// \$Id:.*#[0-9]+ \$$', line) and + not Match(r'^\s*/// [@\\](copydoc|copydetails|copybrief) .*$', line)): line_width = GetLineWidth(line) if line_width > _line_length: error(filename, linenum, 'whitespace/line_length', 2, 'Lines should be <= %i characters long' % _line_length) if (cleansed_line.count(';') > 1 and + # allow simple single line lambdas + not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}\n\r]*\}', + line) and # for loops are allowed two ;'s (and may run over two lines). cleansed_line.find('for') == -1 and (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or @@ -4401,8 +4636,11 @@ def _DropCommonSuffixes(filename): Returns: The filename with the common suffix removed. """ - for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', - 'inl.h', 'impl.h', 'internal.h'): + for suffix in itertools.chain( + ('%s.%s' % (test_suffix.lstrip('_'), ext) + for test_suffix, ext in itertools.product(_test_suffixes, GetNonHeaderExtensions())), + ('%s.%s' % (suffix, ext) + for suffix, ext in itertools.product(['inl', 'imp', 'internal'], GetHeaderExtensions()))): if (filename.endswith(suffix) and len(filename) > len(suffix) and filename[-len(suffix) - 1] in ('-', '_')): return filename[:-len(suffix) - 1] @@ -4437,6 +4675,10 @@ def _ClassifyInclude(fileinfo, include, is_system): # those already checked for above. is_cpp_h = include in _CPP_HEADERS + # Headers with C++ extensions shouldn't be considered C system headers + if is_system and os.path.splitext(include)[1] in ['.hpp', '.hxx', '.h++']: + is_system = False + if is_system: if is_cpp_h: return _CPP_SYS_HEADER @@ -4449,9 +4691,11 @@ def _ClassifyInclude(fileinfo, include, is_system): target_dir, target_base = ( os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) + target_dir_pub = os.path.normpath(target_dir + '/../public') + target_dir_pub = target_dir_pub.replace('\\', '/') if target_base == include_base and ( include_dir == target_dir or - include_dir == os.path.normpath(target_dir + '/../public')): + include_dir == target_dir_pub): return _LIKELY_MY_HEADER # If the target and include share some initial basename @@ -4495,7 +4739,7 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): # naming convention but not the include convention. match = Match(r'#include\s*"([^/]+\.h)"', line) if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)): - error(filename, linenum, 'build/include', 4, + error(filename, linenum, 'build/include_subdir', 4, 'Include the directory when naming .h files') # we shouldn't include a file more than once. actually, there are a @@ -4510,11 +4754,16 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): error(filename, linenum, 'build/include', 4, '"%s" already included at %s:%s' % (include, filename, duplicate_line)) - elif (include.endswith('.cc') and + return + + for extension in GetNonHeaderExtensions(): + if (include.endswith('.' + extension) and os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)): - error(filename, linenum, 'build/include', 4, - 'Do not include .cc files from other packages') - elif not _THIRD_PARTY_HEADERS_PATTERN.match(include): + error(filename, linenum, 'build/include', 4, + 'Do not include .' + extension + ' files from other packages') + return + + if not _THIRD_PARTY_HEADERS_PATTERN.match(include): include_state.include_list[-1].append((include, linenum)) # We want to ensure that headers appear in the right order: @@ -4568,7 +4817,7 @@ def _GetTextInside(text, start_pattern): # Give opening punctuations to get the matching close-punctuations. matching_punctuation = {'(': ')', '{': '}', '[': ']'} - closing_punctuation = set(matching_punctuation.itervalues()) + closing_punctuation = set(itervalues(matching_punctuation)) # Find the position to start extracting text. match = re.search(start_pattern, text, re.M) @@ -4670,7 +4919,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, CheckGlobalStatic(filename, clean_lines, linenum, error) CheckPrintf(filename, clean_lines, linenum, error) - if file_extension == 'h': + if file_extension in GetHeaderExtensions(): # TODO(unknown): check that 1-arg constructors are explicit. # How to tell it's a constructor? # (handled in CheckForNonStandardConstructs for now) @@ -4731,9 +4980,14 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, % (match.group(1), match.group(2))) if Search(r'\busing namespace\b', line): - error(filename, linenum, 'build/namespaces', 5, - 'Do not use namespace using-directives. ' - 'Use using-declarations instead.') + if Search(r'\bliterals\b', line): + error(filename, linenum, 'build/namespaces_literals', 5, + 'Do not use namespace using-directives. ' + 'Use using-declarations instead.') + else: + error(filename, linenum, 'build/namespaces', 5, + 'Do not use namespace using-directives. ' + 'Use using-declarations instead.') # Detect variable-length arrays. match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) @@ -4777,7 +5031,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, # Check for use of unnamed namespaces in header files. Registration # macros are typically OK, so we allow use of "namespace {" on lines # that end with backslashes. - if (file_extension == 'h' + if (file_extension in GetHeaderExtensions() and Search(r'\bnamespace\s*{', line) and line[-1] != '\\'): error(filename, linenum, 'build/namespaces', 4, @@ -5377,7 +5631,7 @@ def FilesBelongToSameModule(filename_cc, filename_h): some false positives. This should be sufficiently rare in practice. Args: - filename_cc: is the path for the .cc file + filename_cc: is the path for the source (e.g. .cc) file filename_h: is the path for the header path Returns: @@ -5385,20 +5639,23 @@ def FilesBelongToSameModule(filename_cc, filename_h): bool: True if filename_cc and filename_h belong to the same module. string: the additional prefix needed to open the header file. """ + fileinfo_cc = FileInfo(filename_cc) + if not fileinfo_cc.Extension().lstrip('.') in GetNonHeaderExtensions(): + return (False, '') - fileinfo = FileInfo(filename_cc) - if not fileinfo.IsSource(): + fileinfo_h = FileInfo(filename_h) + if not fileinfo_h.Extension().lstrip('.') in GetHeaderExtensions(): return (False, '') - filename_cc = filename_cc[:-len(fileinfo.Extension())] - matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()) + + filename_cc = filename_cc[:-(len(fileinfo_cc.Extension()))] + matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo_cc.BaseName()) if matched_test_suffix: filename_cc = filename_cc[:-len(matched_test_suffix.group(1))] + filename_cc = filename_cc.replace('/public/', '/') filename_cc = filename_cc.replace('/internal/', '/') - if not filename_h.endswith('.h'): - return (False, '') - filename_h = filename_h[:-len('.h')] + filename_h = filename_h[:-(len(fileinfo_h.Extension()))] if filename_h.endswith('-inl'): filename_h = filename_h[:-len('-inl')] filename_h = filename_h.replace('/public/', '/') @@ -5508,7 +5765,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, # include_dict is modified during iteration, so we iterate over a copy of # the keys. - header_keys = include_dict.keys() + header_keys = list(include_dict.keys()) for header in header_keys: (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) fullpath = common_path + header @@ -5520,11 +5777,13 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, # didn't include it in the .h file. # TODO(unknown): Do a better job of finding .h files so we are confident that # not having the .h file means there isn't one. - if filename.endswith('.cc') and not header_found: - return + if not header_found: + for extension in GetNonHeaderExtensions(): + if filename.endswith('.' + extension): + return # All the lines have been processed, report the errors found. - for required_header_unstripped in required: + for required_header_unstripped in sorted(required, key=required.__getitem__): template = required[required_header_unstripped][1] if required_header_unstripped.strip('<>"') not in include_dict: error(filename, required[required_header_unstripped][0], @@ -5663,11 +5922,9 @@ def IsBlockInNameSpace(nesting_state, is_forward_declaration): Whether or not the new block is directly in a namespace. """ if is_forward_declaration: - if len(nesting_state.stack) >= 1 and ( - isinstance(nesting_state.stack[-1], _NamespaceInfo)): - return True - else: - return False + return len(nesting_state.stack) >= 1 and ( + isinstance(nesting_state.stack[-1], _NamespaceInfo)) + return (len(nesting_state.stack) > 1 and nesting_state.stack[-1].check_namespace_indentation and @@ -5717,7 +5974,7 @@ def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum, def ProcessLine(filename, file_extension, clean_lines, line, include_state, function_state, nesting_state, error, - extra_check_functions=[]): + extra_check_functions=None): """Processes a single line in the file. Args: @@ -5756,8 +6013,9 @@ def ProcessLine(filename, file_extension, clean_lines, line, CheckMakePairUsesDeduction(filename, clean_lines, line, error) CheckRedundantVirtual(filename, clean_lines, line, error) CheckRedundantOverrideOrFinal(filename, clean_lines, line, error) - for check_fn in extra_check_functions: - check_fn(filename, clean_lines, line, error) + if extra_check_functions: + for check_fn in extra_check_functions: + check_fn(filename, clean_lines, line, error) def FlagCxx11Features(filename, clean_lines, linenum, error): """Flag those c++11 features that we only allow in certain places. @@ -5831,7 +6089,7 @@ def FlagCxx14Features(filename, clean_lines, linenum, error): def ProcessFileData(filename, file_extension, lines, error, - extra_check_functions=[]): + extra_check_functions=None): """Performs lint checks and reports any errors to the given error function. Args: @@ -5859,7 +6117,7 @@ def ProcessFileData(filename, file_extension, lines, error, RemoveMultiLineComments(filename, lines, error) clean_lines = CleansedLines(lines) - if file_extension == 'h': + if file_extension in GetHeaderExtensions(): CheckForHeaderGuard(filename, clean_lines, error) for line in xrange(clean_lines.NumLines()): @@ -5930,9 +6188,8 @@ def ProcessConfigOverrides(filename): if base_name: pattern = re.compile(val) if pattern.match(base_name): - sys.stderr.write('Ignoring "%s": file excluded by "%s". ' - 'File path component "%s" matches ' - 'pattern "%s"\n' % + _cpplint_state.PrintInfo('Ignoring "%s": file excluded by ' + '"%s". File path component "%s" matches pattern "%s"\n' % (filename, cfg_file, base_name, val)) return False elif name == 'linelength': @@ -5940,26 +6197,47 @@ def ProcessConfigOverrides(filename): try: _line_length = int(val) except ValueError: - sys.stderr.write('Line length must be numeric.') + _cpplint_state.PrintError('Line length must be numeric.') + elif name == 'extensions': + global _valid_extensions + try: + extensions = [ext.strip() for ext in val.split(',')] + _valid_extensions = set(extensions) + except ValueError: + sys.stderr.write('Extensions should be a comma-separated list of values;' + 'for example: extensions=hpp,cpp\n' + 'This could not be parsed: "%s"' % (val,)) + elif name == 'headers': + global _header_extensions + try: + extensions = [ext.strip() for ext in val.split(',')] + _header_extensions = set(extensions) + except ValueError: + sys.stderr.write('Extensions should be a comma-separated list of values;' + 'for example: extensions=hpp,cpp\n' + 'This could not be parsed: "%s"' % (val,)) + elif name == 'root': + global _root + _root = val else: - sys.stderr.write( + _cpplint_state.PrintError( 'Invalid configuration option (%s) in file %s\n' % (name, cfg_file)) except IOError: - sys.stderr.write( + _cpplint_state.PrintError( "Skipping config file '%s': Can't open for reading\n" % cfg_file) keep_looking = False # Apply all the accumulated filters in reverse order (top-level directory # config options having the least priority). - for filter in reversed(cfg_filters): - _AddFilters(filter) + for cfg_filter in reversed(cfg_filters): + _AddFilters(cfg_filter) return True -def ProcessFile(filename, vlevel, extra_check_functions=[]): +def ProcessFile(filename, vlevel, extra_check_functions=None): """Does google-lint on a single file. Args: @@ -6008,7 +6286,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): lf_lines.append(linenum + 1) except IOError: - sys.stderr.write( + _cpplint_state.PrintError( "Skipping input '%s': Can't open for reading\n" % filename) _RestoreFilters() return @@ -6018,9 +6296,9 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): # When reading from stdin, the extension is unknown, so no cpplint tests # should rely on the extension. - if filename != '-' and file_extension not in _valid_extensions: - sys.stderr.write('Ignoring %s; not a valid file name ' - '(%s)\n' % (filename, ', '.join(_valid_extensions))) + if filename != '-' and file_extension not in GetAllExtensions(): + _cpplint_state.PrintError('Ignoring %s; not a valid file name ' + '(%s)\n' % (filename, ', '.join(GetAllExtensions()))) else: ProcessFileData(filename, file_extension, lines, Error, extra_check_functions) @@ -6043,6 +6321,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): Error(filename, linenum, 'whitespace/newline', 1, 'Unexpected \\r (^M) found; better to use only \\n') + _cpplint_state.PrintInfo('Done processing %s\n' % filename) _RestoreFilters() @@ -6053,10 +6332,11 @@ def PrintUsage(message): message: The optional error message. """ sys.stderr.write(_USAGE) + if message: sys.exit('\nFATAL ERROR: ' + message) else: - sys.exit(1) + sys.exit(0) def PrintCategories(): @@ -6085,8 +6365,13 @@ def ParseArguments(args): 'filter=', 'logfile=', 'root=', + 'repository=', 'linelength=', - 'extensions=']) + 'extensions=', + 'exclude=', + 'headers=', + 'quiet', + 'recursive']) except getopt.GetoptError: PrintUsage('Invalid arguments.') @@ -6094,14 +6379,15 @@ def ParseArguments(args): output_format = _OutputFormat() filters = '' counting_style = '' + recursive = False for (opt, val) in opts: if opt == '--help': PrintUsage(None) elif opt == '--output': - if val not in ('emacs', 'vs7', 'eclipse', 'tap'): + if val not in ('emacs', 'vs7', 'eclipse', 'junit', 'tap'): PrintUsage( - 'The only allowed output formats are emacs, vs7, eclipse and tap.') + 'The only allowed output formats are emacs, vs7, eclipse, junit and tap.') output_format = val elif opt == '--verbose': verbosity = int(val) @@ -6116,24 +6402,50 @@ def ParseArguments(args): elif opt == '--root': global _root _root = val + elif opt == '--repository': + global _repository + _repository = val elif opt == '--linelength': global _line_length try: _line_length = int(val) except ValueError: PrintUsage('Line length must be digits.') + elif opt == '--exclude': + global _excludes + if not _excludes: + _excludes = set() + _excludes.update(glob.glob(val)) elif opt == '--extensions': global _valid_extensions try: _valid_extensions = set(val.split(',')) except ValueError: + PrintUsage('Extensions must be comma seperated list.') + elif opt == '--headers': + global _header_extensions + try: + _header_extensions = set(val.split(',')) + except ValueError: + PrintUsage('Extensions must be comma seperated list.') + elif opt == '--recursive': PrintUsage('Extensions must be comma separated list.') elif opt == '--logfile': + recursive = True + elif opt == '--quiet': logger.addHandler(logging.FileHandler(val, mode='wb')) + global _quiet + _quiet = True if not filenames: PrintUsage('No files were specified.') + if recursive: + filenames = _ExpandDirectories(filenames) + + if _excludes: + filenames = _FilterExcludedFiles(filenames) + _SetOutputFormat(output_format) _SetVerboseLevel(verbosity) _SetFilters(filters) @@ -6141,27 +6453,72 @@ def ParseArguments(args): return filenames +def _ExpandDirectories(filenames): + """Searches a list of filenames and replaces directories in the list with + all files descending from those directories. Files with extensions not in + the valid extensions list are excluded. + + Args: + filenames: A list of files or directories + + Returns: + A list of all files that are members of filenames or descended from a + directory in filenames + """ + expanded = set() + for filename in filenames: + if not os.path.isdir(filename): + expanded.add(filename) + continue + + for root, _, files in os.walk(filename): + for loopfile in files: + fullname = os.path.join(root, loopfile) + if fullname.startswith('.' + os.path.sep): + fullname = fullname[len('.' + os.path.sep):] + expanded.add(fullname) + + filtered = [] + for filename in expanded: + if os.path.splitext(filename)[1][1:] in GetAllExtensions(): + filtered.append(filename) + + return filtered + +def _FilterExcludedFiles(filenames): + """Filters out files listed in the --exclude command line switch. File paths + in the switch are evaluated relative to the current working directory + """ + exclude_paths = [os.path.abspath(f) for f in _excludes] + return [f for f in filenames if os.path.abspath(f) not in exclude_paths] def main(): filenames = ParseArguments(sys.argv[1:]) + backup_err = sys.stderr + try: + # Change stderr to write with replacement characters so we don't die + # if we try to print something containing non-ASCII characters. + sys.stderr = codecs.StreamReaderWriter(sys.stderr, + codecs.getreader('utf8'), + codecs.getwriter('utf8'), + 'replace') - # Change stderr to write with replacement characters so we don't die - # if we try to print something containing non-ASCII characters. - sys.stderr = codecs.StreamReaderWriter(sys.stderr, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), - 'replace') + logger.addHandler(logging.StreamHandler(sys.stdout)) + logger.setLevel(logging.INFO) - logger.addHandler(logging.StreamHandler(sys.stdout)) - logger.setLevel(logging.INFO) + _cpplint_state.ResetErrorCounts() + for filename in filenames: + ProcessFile(filename.decode('utf-8'), _cpplint_state.verbose_level) + _cpplint_state.PrintErrorCounts() - if _cpplint_state.output_format == 'tap': - logger.info('TAP version 13') + if _cpplint_state.output_format == 'tap': + logger.info('TAP version 13') - _cpplint_state.ResetErrorCounts() - for filename in filenames: - ProcessFile(filename.decode('utf-8'), _cpplint_state.verbose_level) - _cpplint_state.PrintErrorCounts() + if _cpplint_state.output_format == 'junit': + sys.stderr.write(_cpplint_state.FormatJUnitXML()) + + finally: + sys.stderr = backup_err sys.exit(_cpplint_state.error_count > 0) From 6f66e4923fde0a5a2163f926d2a07565e9b41332 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Mon, 17 Sep 2018 07:43:46 +0200 Subject: [PATCH 52/77] deps: add missing HandleScope in FieldType::PrintTo Refs: https://github.com/nodejs/node/issues/22775 PR-URL: https://github.com/nodejs/node/pull/22890 Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen Reviewed-By: Refael Ackermann --- common.gypi | 2 +- deps/v8/src/field-type.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index 5a9842b57ea9d2..0279c577a14b57 100644 --- a/common.gypi +++ b/common.gypi @@ -29,7 +29,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.26', + 'v8_embedder_string': '-node.27', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/src/field-type.cc b/deps/v8/src/field-type.cc index 3b51095323c06b..2eebebe3d616ea 100644 --- a/deps/v8/src/field-type.cc +++ b/deps/v8/src/field-type.cc @@ -78,6 +78,7 @@ void FieldType::PrintTo(std::ostream& os) { os << "None"; } else { DCHECK(IsClass()); + HandleScope scope(Map::cast(this)->GetIsolate()); os << "Class(" << static_cast(*AsClass()) << ")"; } } From 2b0ce98350ef1a71d892a0e4aaa849a1db59125b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Mon, 17 Sep 2018 13:44:42 +0200 Subject: [PATCH 53/77] crypto: remove unused scrypt validation parameter PR-URL: https://github.com/nodejs/node/pull/22902 Reviewed-By: Daniel Bevenius Reviewed-By: Colin Ihrig Reviewed-By: Anna Henningsen Reviewed-By: Rich Trott --- lib/internal/crypto/scrypt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/crypto/scrypt.js b/lib/internal/crypto/scrypt.js index 68ae4f6f7d5385..c5dfc08cf353ae 100644 --- a/lib/internal/crypto/scrypt.js +++ b/lib/internal/crypto/scrypt.js @@ -70,7 +70,7 @@ function handleError(keybuf, password, salt, N, r, p, maxmem, wrap) { throw ex; // Scrypt operation failed, exception object contains details. } -function check(password, salt, keylen, options, callback) { +function check(password, salt, keylen, options) { if (_scrypt === undefined) throw new ERR_CRYPTO_SCRYPT_NOT_SUPPORTED(); From 6975e0867612914dff04113fafc3119c67ed858c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Thu, 13 Sep 2018 00:48:35 +0200 Subject: [PATCH 54/77] crypto: fix edge case in authenticated encryption Restricting the authentication tag length and calling update or setAAD before setAuthTag caused an incorrect authentication tag to be passed to OpenSSL: The auth_tag_len_ field was already set, so the implementation assumed that the tag itself was known as well. PR-URL: https://github.com/nodejs/node/pull/22828 Reviewed-By: Daniel Bevenius --- src/node_crypto.cc | 9 +++-- src/node_crypto.h | 9 +++-- test/parallel/test-crypto-authenticated.js | 40 +++++++++++++--------- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 75aedabf7eac5c..b4a6aaa87dd075 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2891,6 +2891,10 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo& args) { return args.GetReturnValue().Set(false); } + // TODO(tniessen): Throw if the authentication tag has already been set. + if (cipher->auth_tag_state_ == kAuthTagPassedToOpenSSL) + return args.GetReturnValue().Set(true); + unsigned int tag_len = Buffer::Length(args[0]); const int mode = EVP_CIPHER_CTX_mode(cipher->ctx_.get()); if (mode == EVP_CIPH_GCM_MODE) { @@ -2923,6 +2927,7 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo& args) { // Note: we don't use std::min() here to work around a header conflict. cipher->auth_tag_len_ = tag_len; + cipher->auth_tag_state_ = kAuthTagKnown; if (cipher->auth_tag_len_ > sizeof(cipher->auth_tag_)) cipher->auth_tag_len_ = sizeof(cipher->auth_tag_); @@ -2934,14 +2939,14 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo& args) { bool CipherBase::MaybePassAuthTagToOpenSSL() { - if (!auth_tag_set_ && auth_tag_len_ != kNoAuthTagLength) { + if (auth_tag_state_ == kAuthTagKnown) { if (!EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_SET_TAG, auth_tag_len_, reinterpret_cast(auth_tag_))) { return false; } - auth_tag_set_ = true; + auth_tag_state_ = kAuthTagPassedToOpenSSL; } return true; } diff --git a/src/node_crypto.h b/src/node_crypto.h index 86aa3ba4ba8395..1a93ae7a47e2cf 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -363,6 +363,11 @@ class CipherBase : public BaseObject { kErrorMessageSize, kErrorState }; + enum AuthTagState { + kAuthTagUnknown, + kAuthTagKnown, + kAuthTagPassedToOpenSSL + }; static const unsigned kNoAuthTagLength = static_cast(-1); void Init(const char* cipher_type, @@ -404,7 +409,7 @@ class CipherBase : public BaseObject { : BaseObject(env, wrap), ctx_(nullptr), kind_(kind), - auth_tag_set_(false), + auth_tag_state_(kAuthTagUnknown), auth_tag_len_(kNoAuthTagLength), pending_auth_failed_(false) { MakeWeak(); @@ -413,7 +418,7 @@ class CipherBase : public BaseObject { private: DeleteFnPtr ctx_; const CipherKind kind_; - bool auth_tag_set_; + AuthTagState auth_tag_state_; unsigned int auth_tag_len_; char auth_tag_[EVP_GCM_TLS_TAG_LEN]; bool pending_auth_failed_; diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index 4b2d8526ddb46e..dc19a7b2ab81ef 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -579,27 +579,35 @@ for (const test of TEST_CASES) { } // Test that the authentication tag can be set at any point before calling -// final() in GCM mode. +// final() in GCM or OCB mode. { const plain = Buffer.from('Hello world', 'utf8'); const key = Buffer.from('0123456789abcdef', 'utf8'); const iv = Buffer.from('0123456789ab', 'utf8'); - const cipher = crypto.createCipheriv('aes-128-gcm', key, iv); - const ciphertext = Buffer.concat([cipher.update(plain), cipher.final()]); - const authTag = cipher.getAuthTag(); - - for (const authTagBeforeUpdate of [true, false]) { - const decipher = crypto.createDecipheriv('aes-128-gcm', key, iv); - if (authTagBeforeUpdate) { - decipher.setAuthTag(authTag); - } - const resultUpdate = decipher.update(ciphertext); - if (!authTagBeforeUpdate) { - decipher.setAuthTag(authTag); + for (const mode of ['gcm', 'ocb']) { + for (const authTagLength of mode === 'gcm' ? [undefined, 8] : [8]) { + const cipher = crypto.createCipheriv(`aes-128-${mode}`, key, iv, { + authTagLength + }); + const ciphertext = Buffer.concat([cipher.update(plain), cipher.final()]); + const authTag = cipher.getAuthTag(); + + for (const authTagBeforeUpdate of [true, false]) { + const decipher = crypto.createDecipheriv(`aes-128-${mode}`, key, iv, { + authTagLength + }); + if (authTagBeforeUpdate) { + decipher.setAuthTag(authTag); + } + const resultUpdate = decipher.update(ciphertext); + if (!authTagBeforeUpdate) { + decipher.setAuthTag(authTag); + } + const resultFinal = decipher.final(); + const result = Buffer.concat([resultUpdate, resultFinal]); + assert(result.equals(plain)); + } } - const resultFinal = decipher.final(); - const result = Buffer.concat([resultUpdate, resultFinal]); - assert(result.equals(plain)); } } From 57f2c121e2469cdba43bf87d63480f4be77cbb4c Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 17 Sep 2018 15:34:31 +0200 Subject: [PATCH 55/77] test: don't inspect values if not necessary The inspection triggered on each assert call eagerly even tough the assertion was never triggered. That caused significant CPU overhead. PR-URL: https://github.com/nodejs/node/pull/22903 Reviewed-By: Anna Henningsen Reviewed-By: Rich Trott --- test/common/heap.js | 25 ++++++++++++++----- test/internet/test-trace-events-dns.js | 7 +++++- test/parallel/test-trace-events-fs-sync.js | 7 +++++- .../test-worker-message-port-transfer-self.js | 12 ++++++--- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/test/common/heap.js b/test/common/heap.js index a02de9a60651f4..bd8b588b4b0e1b 100644 --- a/test/common/heap.js +++ b/test/common/heap.js @@ -33,10 +33,17 @@ class State { (node) => [expectedChild.name, 'Node / ' + expectedChild.name] .includes(node.name); - assert(snapshot.some((node) => { + const hasChild = snapshot.some((node) => { return node.outgoingEdges.map((edge) => edge.toNode).some(check); - }), `expected to find child ${util.inspect(expectedChild)} ` + - `in ${util.inspect(snapshot)}`); + }); + // Don't use assert with a custom message here. Otherwise the + // inspection in the message is done eagerly and wastes a lot of CPU + // time. + if (!hasChild) { + throw new Error( + 'expected to find child ' + + `${util.inspect(expectedChild)} in ${util.inspect(snapshot)}`); + } } } } @@ -57,9 +64,15 @@ class State { node.value.constructor.name === expectedChild.name); }; - assert(graph.some((node) => node.edges.some(check)), - `expected to find child ${util.inspect(expectedChild)} ` + - `in ${util.inspect(snapshot)}`); + // Don't use assert with a custom message here. Otherwise the + // inspection in the message is done eagerly and wastes a lot of CPU + // time. + const hasChild = graph.some((node) => node.edges.some(check)); + if (!hasChild) { + throw new Error( + 'expected to find child ' + + `${util.inspect(expectedChild)} in ${util.inspect(snapshot)}`); + } } } } diff --git a/test/internet/test-trace-events-dns.js b/test/internet/test-trace-events-dns.js index e1cfd6a597acca..9e5a0ccb026c1a 100644 --- a/test/internet/test-trace-events-dns.js +++ b/test/internet/test-trace-events-dns.js @@ -49,7 +49,12 @@ for (const tr in tests) { { encoding: 'utf8' }); // Make sure the operation is successful. - assert.strictEqual(proc.status, 0, `${tr}:\n${util.inspect(proc)}`); + // Don't use assert with a custom message here. Otherwise the + // inspection in the message is done eagerly and wastes a lot of CPU + // time. + if (proc.status !== 0) { + throw new Error(`${tr}:\n${util.inspect(proc)}`); + } const file = path.join(tmpdir.path, traceFile); diff --git a/test/parallel/test-trace-events-fs-sync.js b/test/parallel/test-trace-events-fs-sync.js index 71ffc9da726f1b..54222bcb333f51 100644 --- a/test/parallel/test-trace-events-fs-sync.js +++ b/test/parallel/test-trace-events-fs-sync.js @@ -136,7 +136,12 @@ for (const tr in tests) { } // Make sure the operation is successful. - assert.strictEqual(proc.status, 0, `${tr}:\n${util.inspect(proc)}`); + // Don't use assert with a custom message here. Otherwise the + // inspection in the message is done eagerly and wastes a lot of CPU + // time. + if (proc.status !== 0) { + throw new Error(`${tr}:\n${util.inspect(proc)}`); + } // Confirm that trace log file is created. assert(fs.existsSync(traceFile)); diff --git a/test/parallel/test-worker-message-port-transfer-self.js b/test/parallel/test-worker-message-port-transfer-self.js index 4fe12c0a88d81d..c6f29163dfc643 100644 --- a/test/parallel/test-worker-message-port-transfer-self.js +++ b/test/parallel/test-worker-message-port-transfer-self.js @@ -27,14 +27,18 @@ assert.throws(common.mustCall(() => { port2.onmessage = common.mustCall((message) => { assert.strictEqual(message, 2); - assert(util.inspect(port1).includes('active: true'), util.inspect(port1)); - assert(util.inspect(port2).includes('active: true'), util.inspect(port2)); + const inspectedPort1 = util.inspect(port1); + const inspectedPort2 = util.inspect(port2); + assert(inspectedPort1.includes('active: true'), inspectedPort1); + assert(inspectedPort2.includes('active: true'), inspectedPort2); port1.close(); tick(10, () => { - assert(util.inspect(port1).includes('active: false'), util.inspect(port1)); - assert(util.inspect(port2).includes('active: false'), util.inspect(port2)); + const inspectedPort1 = util.inspect(port1); + const inspectedPort2 = util.inspect(port2); + assert(inspectedPort1.includes('active: false'), inspectedPort1); + assert(inspectedPort2.includes('active: false'), inspectedPort2); }); }); port1.postMessage(2); From bf7d7cf9f8cdfc8512ac8d7d7a4609e753dcef89 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 13 Sep 2018 13:59:13 -0700 Subject: [PATCH 56/77] test: remove string literal message from assertion Remove string literal message in assert.strictEqual() call in napi test testFinalizer.js. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/addons-napi/test_general/testFinalizer.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/addons-napi/test_general/testFinalizer.js b/test/addons-napi/test_general/testFinalizer.js index d5df4c8c724f98..b440ed5e501ad8 100644 --- a/test/addons-napi/test_general/testFinalizer.js +++ b/test/addons-napi/test_general/testFinalizer.js @@ -29,5 +29,4 @@ test_general.wrap(finalizeAndWrap); test_general.addFinalizerOnly(finalizeAndWrap, common.mustCall()); finalizeAndWrap = null; global.gc(); -assert.strictEqual(test_general.derefItemWasCalled(), true, - 'finalize callback was called'); +assert.strictEqual(test_general.derefItemWasCalled(), true); From 8595d9079f5ab5b423029e566818454bfc69a05e Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 13 Sep 2018 13:56:36 -0700 Subject: [PATCH 57/77] test: remove string literal message in assertions Remove string literal message in assert.strictEqual() calls in test-async-await.js. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/async-hooks/test-async-await.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/async-hooks/test-async-await.js b/test/async-hooks/test-async-await.js index 7f88cd9b18176f..f5e886e9d50001 100644 --- a/test/async-hooks/test-async-await.js +++ b/test/async-hooks/test-async-await.js @@ -64,15 +64,15 @@ const timeout = common.platformTimeout(10); function checkPromisesInitState() { for (const initState of promisesInitState.values()) { - assert.strictEqual(initState, 'resolved', - 'promise initialized without being resolved'); + // Promise should not be initialized without being resolved. + assert.strictEqual(initState, 'resolved'); } } function checkPromisesExecutionState() { for (const executionState of promisesExecutionState.values()) { - assert.strictEqual(executionState, 'after', - 'mismatch between before and after hook calls'); + // Check for mismatch between before and after hook calls. + assert.strictEqual(executionState, 'after'); } } From b9af09dbbccb6d62bccae97f1e12173c6fc9599f Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sat, 1 Sep 2018 22:47:37 -0700 Subject: [PATCH 58/77] test: improve assertion in test-inspector.js Remove an unecessary string literal from assert.strictEqual() call in test-inspector.js. The string literal is printed instead of the value that causes an error. Removing the string literal allows the value that caused the error to be printed. This improves the troubleshooting experience when the test fails due to that assertion. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/sequential/test-inspector.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/sequential/test-inspector.js b/test/sequential/test-inspector.js index ba1fce25a04fad..d641015a3c9954 100644 --- a/test/sequential/test-inspector.js +++ b/test/sequential/test-inspector.js @@ -33,8 +33,7 @@ function checkBadPath(err) { } function checkException(message) { - assert.strictEqual(message.exceptionDetails, undefined, - 'An exception occurred during execution'); + assert.strictEqual(message.exceptionDetails, undefined); } function assertScopeValues({ result }, expected) { From 05bec3c5a1dde0a915a34487fdb5277c23755814 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 2 Sep 2018 10:55:33 -0700 Subject: [PATCH 59/77] test: simplify assertion in http2 tests In test-http2-timeout-large-write.js and test-http2-timeout-large-write-file.js: Use assert.ok() on a boolean that the test itself creates and sets, rather than assert.strictEqual(). This allows us to use a static message without running afoul of the upcoming "do not use string literals with assert.strictEqual()" lint rule. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/sequential/test-http2-timeout-large-write-file.js | 2 +- test/sequential/test-http2-timeout-large-write.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/sequential/test-http2-timeout-large-write-file.js b/test/sequential/test-http2-timeout-large-write-file.js index 910e7a0fc497bd..bb366cfff04091 100644 --- a/test/sequential/test-http2-timeout-large-write-file.js +++ b/test/sequential/test-http2-timeout-large-write-file.js @@ -48,7 +48,7 @@ server.on('stream', common.mustCall((stream) => { })); server.setTimeout(serverTimeout); server.on('timeout', () => { - assert.strictEqual(didReceiveData, false, 'Should not timeout'); + assert.ok(!didReceiveData, 'Should not timeout'); }); server.listen(0, common.mustCall(() => { diff --git a/test/sequential/test-http2-timeout-large-write.js b/test/sequential/test-http2-timeout-large-write.js index a15fb46af6d28a..73114776df0a0e 100644 --- a/test/sequential/test-http2-timeout-large-write.js +++ b/test/sequential/test-http2-timeout-large-write.js @@ -40,13 +40,13 @@ server.on('stream', common.mustCall((stream) => { stream.write(content); stream.setTimeout(serverTimeout); stream.on('timeout', () => { - assert.strictEqual(didReceiveData, false, 'Should not timeout'); + assert.ok(!didReceiveData, 'Should not timeout'); }); stream.end(); })); server.setTimeout(serverTimeout); server.on('timeout', () => { - assert.strictEqual(didReceiveData, false, 'Should not timeout'); + assert.ok(!didReceiveData, 'Should not timeout'); }); server.listen(0, common.mustCall(() => { From f04466ea397931c05c2e5312f1c77abe7ebadeea Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 12 Sep 2018 20:16:23 -0700 Subject: [PATCH 60/77] test: refactor flag check Refactor test-vm-run-in-new-context so that check for `--expose-gc` flag will not run afoul of an upcoming lint rule that checks that string literals are not used for the `message` argument of `assert.strictEqual()`. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/parallel/test-vm-run-in-new-context.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-vm-run-in-new-context.js b/test/parallel/test-vm-run-in-new-context.js index e844cd6816bba3..51577668cfe7f8 100644 --- a/test/parallel/test-vm-run-in-new-context.js +++ b/test/parallel/test-vm-run-in-new-context.js @@ -26,8 +26,8 @@ const common = require('../common'); const assert = require('assert'); const vm = require('vm'); -assert.strictEqual(typeof global.gc, 'function', - 'Run this test with --expose-gc'); +if (typeof global.gc !== 'function') + assert.fail('Run this test with --expose-gc'); // Run a string const result = vm.runInNewContext('\'passed\';'); From 4fe60349333e188480c4446ad62398a8c68ef114 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 12 Sep 2018 20:24:28 -0700 Subject: [PATCH 61/77] test: remove string literal from assertion Remove string literal from `assert.strictEqual()` call `message` parameter and make it a comment above the assertion instead. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/parallel/test-next-tick-domain.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-next-tick-domain.js b/test/parallel/test-next-tick-domain.js index 5c526197926df7..3e55ef3225fc40 100644 --- a/test/parallel/test-next-tick-domain.js +++ b/test/parallel/test-next-tick-domain.js @@ -27,5 +27,5 @@ const origNextTick = process.nextTick; require('domain'); -assert.strictEqual(origNextTick, process.nextTick, - 'Requiring domain should not change nextTick'); +// Requiring domain should not change nextTick. +assert.strictEqual(origNextTick, process.nextTick); From 136c4a8886df147fa6beec5f10388476fee41a92 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 12 Sep 2018 21:08:53 -0700 Subject: [PATCH 62/77] test: remove string literal message from assertion Remove string literal from assert.strictEqual message to improve output of AssertionError. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/parallel/test-http-information-processing.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-http-information-processing.js b/test/parallel/test-http-information-processing.js index af589477f05dd1..43d1bdafdf4dd1 100644 --- a/test/parallel/test-http-information-processing.js +++ b/test/parallel/test-http-information-processing.js @@ -36,8 +36,8 @@ server.listen(0, function() { }); req.on('response', function(res) { - assert.strictEqual(countdown.remaining, 1, - 'Full response received before all 102 Processing'); + // Check that all 102 Processing received before full response received. + assert.strictEqual(countdown.remaining, 1); assert.strictEqual(200, res.statusCode, `Final status code was ${res.statusCode}, not 200.`); res.setEncoding('utf8'); From f2703b29ece5189d66dba3f257d1bc3160428f1f Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 12 Sep 2018 21:10:45 -0700 Subject: [PATCH 63/77] test: remove string literal arg from assertion Remove unnecessary string literal from assert.deepStrictEqual() call. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/parallel/test-fs-readfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-fs-readfile.js b/test/parallel/test-fs-readfile.js index 118f2e43aab500..648bf692d1dcc8 100644 --- a/test/parallel/test-fs-readfile.js +++ b/test/parallel/test-fs-readfile.js @@ -54,6 +54,6 @@ for (const e of fileInfo) { fs.readFile(e.name, common.mustCall((err, buf) => { console.log(`Validating readFile on file ${e.name} of length ${e.len}`); assert.ifError(err); - assert.deepStrictEqual(buf, e.contents, 'Incorrect file contents'); + assert.deepStrictEqual(buf, e.contents); })); } From bd247525d6265efec61958dbed34f0afca6a0318 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 13 Sep 2018 13:04:09 -0700 Subject: [PATCH 64/77] test: remove string literal from assertion Remove string literal as assertion message in call to assert.strictEqual() in test-dns-resolveany-bad-ancount. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/parallel/test-dns-resolveany-bad-ancount.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-dns-resolveany-bad-ancount.js b/test/parallel/test-dns-resolveany-bad-ancount.js index 4b13421b316aee..71fcbe03cd58f1 100644 --- a/test/parallel/test-dns-resolveany-bad-ancount.js +++ b/test/parallel/test-dns-resolveany-bad-ancount.js @@ -40,8 +40,8 @@ server.bind(0, common.mustCall(async () => { assert.strictEqual(err.syscall, 'queryAny'); assert.strictEqual(err.hostname, 'example.org'); const descriptor = Object.getOwnPropertyDescriptor(err, 'message'); - assert.strictEqual(descriptor.enumerable, - false, 'The error message should be non-enumerable'); + // The error message should be non-enumerable. + assert.strictEqual(descriptor.enumerable, false); server.close(); })); })); From 6f23ec6fc057b03e2da7a12036900ae61c069b48 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 13 Sep 2018 13:40:11 -0700 Subject: [PATCH 65/77] test: remove string literal from assertion Remove string literal as assertion message in call to assert.strictEqual() in test-dns-lookup. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/parallel/test-dns-lookup.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-dns-lookup.js b/test/parallel/test-dns-lookup.js index 3413bcffd8abe9..c9b54b9faf95ef 100644 --- a/test/parallel/test-dns-lookup.js +++ b/test/parallel/test-dns-lookup.js @@ -134,8 +134,8 @@ dns.lookup('example.com', common.mustCall((error, result, addressType) => { assert.strictEqual(tickValue, 1); assert.strictEqual(error.code, 'ENOENT'); const descriptor = Object.getOwnPropertyDescriptor(error, 'message'); - assert.strictEqual(descriptor.enumerable, - false, 'The error message should be non-enumerable'); + // The error message should be non-enumerable. + assert.strictEqual(descriptor.enumerable, false); })); // Make sure that the error callback is called From 3bf9c17674150093bcf157b739eaa39ef66ff4b9 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 13 Sep 2018 13:47:57 -0700 Subject: [PATCH 66/77] test: prepare test-assert for strictEqual linting Make minor modifications to test-assert.js to prepare it for linting rule that forbids the use of string literals for the third argument of assert.strictEqual(). Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- test/parallel/test-assert.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 6449fe1c3f0cf1..257c7f5c06ebf7 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -304,11 +304,11 @@ try { } try { - assert.strictEqual(1, 2, 'oh no'); + assert.strictEqual(1, 2, 'oh no'); // eslint-disable-line no-restricted-syntax } catch (e) { assert.strictEqual(e.message, 'oh no'); - assert.strictEqual(e.generatedMessage, false, - 'Message incorrectly marked as generated'); + // Message should not be marked as generated. + assert.strictEqual(e.generatedMessage, false); } { From 0fd614d605c012217f57b6577814ebd4c0ead9c6 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 30 Jul 2018 16:33:41 -0700 Subject: [PATCH 67/77] tools: prevent string literals in some assertions String literals provided as the third argument to assert.strictEqual() or assert.deepStrictEqual() will mask the values that are causing issues. Use a lint rule to prevent such usage. Backport-PR-URL: https://github.com/nodejs/node/pull/22912 PR-URL: https://github.com/nodejs/node/pull/22849 Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen Reviewed-By: Trivikram Kamat Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- .eslintrc.js | 5 +++++ lib/.eslintrc.yaml | 4 ++++ test/.eslintrc.yaml | 4 ++++ .../test-timers-same-timeout-wrong-list-deleted.js | 8 +++----- test/parallel/test-timers-unref-reuse-no-exposed-list.js | 6 ++---- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 9c3a78d81cd27a..e4192c3539925c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -156,6 +156,7 @@ module.exports = { ], /* eslint-disable max-len */ // If this list is modified, please copy the change to lib/.eslintrc.yaml + // and test/.eslintrc.yaml. 'no-restricted-syntax': [ 'error', { @@ -166,6 +167,10 @@ module.exports = { selector: "CallExpression[callee.object.name='assert'][callee.property.name='rejects'][arguments.length<2]", message: 'assert.rejects() must be invoked with at least two arguments.', }, + { + selector: "CallExpression[callee.object.name='assert'][callee.property.name='strictEqual'][arguments.2.type='Literal']", + message: 'Do not use a literal for the third argument of assert.strictEqual()' + }, { selector: "CallExpression[callee.object.name='assert'][callee.property.name='throws'][arguments.1.type='Literal']:not([arguments.1.regex])", message: 'Use an object as second argument of assert.throws()', diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index e7cab0ad931b4d..a1a0b9490a9177 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -2,10 +2,14 @@ rules: no-restricted-syntax: # Config copied from .eslintrc.js - error + - selector: "CallExpression[callee.object.name='assert'][callee.property.name='deepStrictEqual'][arguments.2.type='Literal']" + message: "Do not use a literal for the third argument of assert.deepStrictEqual()" - selector: "CallExpression[callee.object.name='assert'][callee.property.name='doesNotThrow']" message: "Please replace `assert.doesNotThrow()` and add a comment next to the code instead." - selector: "CallExpression[callee.object.name='assert'][callee.property.name='rejects'][arguments.length<2]" message: "assert.rejects() must be invoked with at least two arguments." + - selector: "CallExpression[callee.object.name='assert'][callee.property.name='strictEqual'][arguments.2.type='Literal']" + message: "Do not use a literal for the third argument of assert.strictEqual()" - selector: "CallExpression[callee.object.name='assert'][callee.property.name='throws'][arguments.1.type='Literal']:not([arguments.1.regex])" message: "Use an object as second argument of assert.throws()" - selector: "CallExpression[callee.object.name='assert'][callee.property.name='throws'][arguments.length<2]" diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml index 25026fec5a103a..63d2127d738597 100644 --- a/test/.eslintrc.yaml +++ b/test/.eslintrc.yaml @@ -23,10 +23,14 @@ rules: no-restricted-syntax: # Config copied from .eslintrc.js - error + - selector: "CallExpression[callee.object.name='assert'][callee.property.name='deepStrictEqual'][arguments.2.type='Literal']" + message: "Do not use a literal for the third argument of assert.deepStrictEqual()" - selector: "CallExpression[callee.object.name='assert'][callee.property.name='doesNotThrow']" message: "Please replace `assert.doesNotThrow()` and add a comment next to the code instead." - selector: "CallExpression[callee.object.name='assert'][callee.property.name='rejects'][arguments.length<2]" message: "assert.rejects() must be invoked with at least two arguments." + - selector: "CallExpression[callee.object.name='assert'][callee.property.name='strictEqual'][arguments.2.type='Literal']" + message: "Do not use a literal for the third argument of assert.strictEqual()" - selector: "CallExpression[callee.object.name='assert'][callee.property.name='throws'][arguments.1.type='Literal']:not([arguments.1.regex])" message: "Use an object as second argument of assert.throws()" - selector: "CallExpression[callee.object.name='assert'][callee.property.name='throws'][arguments.length<2]" diff --git a/test/parallel/test-timers-same-timeout-wrong-list-deleted.js b/test/parallel/test-timers-same-timeout-wrong-list-deleted.js index c66ba0a57efa11..8ad267cd16f699 100644 --- a/test/parallel/test-timers-same-timeout-wrong-list-deleted.js +++ b/test/parallel/test-timers-same-timeout-wrong-list-deleted.js @@ -37,7 +37,7 @@ const handle1 = setTimeout(common.mustCall(function() { // Make sure our clearTimeout succeeded. One timer finished and // the other was canceled, so none should be active. - assert.strictEqual(activeTimers.length, 0, 'Timers remain.'); + assert.strictEqual(activeTimers.length, 0); })); })); }), 1); @@ -53,11 +53,9 @@ const handle1 = setTimeout(common.mustCall(function() { // Make sure our clearTimeout succeeded. One timer finished and // the other was canceled, so none should be active. - assert.strictEqual(activeTimers.length, 3, - 'There should be 3 timers in the list.'); + assert.strictEqual(activeTimers.length, 3); assert(shortTimer instanceof Timer, 'The shorter timer is not in the list.'); - assert.strictEqual(longTimers.length, 2, - 'Both longer timers should be in the list.'); + assert.strictEqual(longTimers.length, 2); // When this callback completes, `listOnTimeout` should now look at the // correct list and refrain from removing the new TIMEOUT list which diff --git a/test/parallel/test-timers-unref-reuse-no-exposed-list.js b/test/parallel/test-timers-unref-reuse-no-exposed-list.js index 33b2da2f9e214f..269a2b5e85fc1d 100644 --- a/test/parallel/test-timers-unref-reuse-no-exposed-list.js +++ b/test/parallel/test-timers-unref-reuse-no-exposed-list.js @@ -4,11 +4,9 @@ require('../common'); const assert = require('assert'); const timer1 = setTimeout(() => {}, 1).unref(); -assert.strictEqual(timer1._handle._list, undefined, - 'timer1._handle._list should be undefined'); +assert.strictEqual(timer1._handle._list, undefined); // Check that everything works even if the handle was not re-used. setTimeout(() => {}, 1); const timer2 = setTimeout(() => {}, 1).unref(); -assert.strictEqual(timer2._handle._list, undefined, - 'timer2._handle._list should be undefined'); +assert.strictEqual(timer2._handle._list, undefined); From 6f02cc56a573040dc345dbcbdf42f622dd44d2fb Mon Sep 17 00:00:00 2001 From: Alexey Kozyatinskiy Date: Fri, 10 Aug 2018 13:09:49 -0700 Subject: [PATCH 68/77] deps: cherry-pick dbfcc48 from upstream V8 Original commit message: ``` [inspector] added V8InspectorClient::resourceNameToUrl Some clients (see Node.js) use platform path as ScriptOrigin. Reporting platform path in protocol makes using protocol much harder. This CL introduced V8InspectorClient::resourceNameToUrl method that is called for any reported using protocol url. V8Inspector uses url internally as well so protocol client may generate pattern for blackboxing with file urls only and does not need to build complicated regexp that covers files urls and platform paths on different platforms. R=lushnikov@chromium.org TBR=yangguo@chromium.org Bug: none Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;luci.chromium.try:linux_chromium_rel_ng;master.tryserver.blink:linux_trusty_blink_rel Change-Id: Iff302e7441df922fa5d689fe510f5a9bfd470b9b Reviewed-on: https://chromium-review.googlesource.com/1164624 Commit-Queue: Aleksey Kozyatinskiy Reviewed-by: Alexei Filippov Cr-Commit-Position: refs/heads/master@{#55029} ``` Refs: https://github.com/v8/v8/commit/dbfcc48 Backport-PR-URL: https://github.com/nodejs/node/pull/22918 PR-URL: https://github.com/nodejs/node/pull/22251 Reviewed-By: Eugene Ostroukhov Reviewed-By: Tiancheng "Timothy" Gu --- common.gypi | 2 +- deps/v8/include/v8-inspector.h | 5 + .../src/inspector/v8-debugger-agent-impl.cc | 5 +- deps/v8/src/inspector/v8-debugger-script.cc | 102 ++++++++------- deps/v8/src/inspector/v8-debugger-script.h | 11 +- deps/v8/src/inspector/v8-debugger.cc | 13 +- .../src/inspector/v8-profiler-agent-impl.cc | 46 ++++--- deps/v8/src/inspector/v8-stack-trace-impl.cc | 24 +++- deps/v8/src/inspector/v8-stack-trace-impl.h | 4 +- .../resource-name-to-url-expected.txt | 122 ++++++++++++++++++ .../debugger/resource-name-to-url.js | 49 +++++++ deps/v8/test/inspector/inspector-test.cc | 15 +++ deps/v8/test/inspector/isolate-data.cc | 29 +++++ deps/v8/test/inspector/isolate-data.h | 4 + 14 files changed, 352 insertions(+), 79 deletions(-) create mode 100644 deps/v8/test/inspector/debugger/resource-name-to-url-expected.txt create mode 100644 deps/v8/test/inspector/debugger/resource-name-to-url.js diff --git a/common.gypi b/common.gypi index 0279c577a14b57..e9e05049dbb265 100644 --- a/common.gypi +++ b/common.gypi @@ -29,7 +29,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.27', + 'v8_embedder_string': '-node.28', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/include/v8-inspector.h b/deps/v8/include/v8-inspector.h index 6de8234fb83bcf..cb5ceff037b131 100644 --- a/deps/v8/include/v8-inspector.h +++ b/deps/v8/include/v8-inspector.h @@ -214,6 +214,11 @@ class V8_EXPORT V8InspectorClient { virtual bool canExecuteScripts(int contextGroupId) { return true; } virtual void maxAsyncCallStackDepthChanged(int depth) {} + + virtual std::unique_ptr resourceNameToUrl( + const StringView& resourceName) { + return nullptr; + } }; // These stack trace ids are intended to be passed between debuggers and be diff --git a/deps/v8/src/inspector/v8-debugger-agent-impl.cc b/deps/v8/src/inspector/v8-debugger-agent-impl.cc index 6b3c0ab88708b7..6edf59445f92c4 100644 --- a/deps/v8/src/inspector/v8-debugger-agent-impl.cc +++ b/deps/v8/src/inspector/v8-debugger-agent-impl.cc @@ -1444,7 +1444,7 @@ void V8DebuggerAgentImpl::didParseSource( protocol::StringUtil::parseJSON(inspected->auxData())); } bool isLiveEdit = script->isLiveEdit(); - bool hasSourceURL = script->hasSourceURL(); + bool hasSourceURLComment = script->hasSourceURLComment(); bool isModule = script->isModule(); String16 scriptId = script->scriptId(); String16 scriptURL = script->sourceURL(); @@ -1464,7 +1464,8 @@ void V8DebuggerAgentImpl::didParseSource( Maybe executionContextAuxDataParam( std::move(executionContextAuxData)); const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; - const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; + const bool* hasSourceURLParam = + hasSourceURLComment ? &hasSourceURLComment : nullptr; const bool* isModuleParam = isModule ? &isModule : nullptr; std::unique_ptr stack = V8StackTraceImpl::capture(m_inspector->debugger(), contextGroupId, 1); diff --git a/deps/v8/src/inspector/v8-debugger-script.cc b/deps/v8/src/inspector/v8-debugger-script.cc index d632df3f66c747..3ceb2af65202c8 100644 --- a/deps/v8/src/inspector/v8-debugger-script.cc +++ b/deps/v8/src/inspector/v8-debugger-script.cc @@ -6,6 +6,7 @@ #include "src/inspector/inspected-context.h" #include "src/inspector/string-util.h" +#include "src/inspector/v8-inspector-impl.h" #include "src/inspector/wasm-translation.h" #include "src/utils.h" @@ -110,41 +111,11 @@ class ActualScript : public V8DebuggerScript { public: ActualScript(v8::Isolate* isolate, v8::Local script, - bool isLiveEdit) + bool isLiveEdit, V8InspectorClient* client) : V8DebuggerScript(isolate, String16::fromInteger(script->Id()), - GetNameOrSourceUrl(script)), + GetScriptURL(script, client)), m_isLiveEdit(isLiveEdit) { - v8::Local tmp; - if (script->SourceURL().ToLocal(&tmp)) m_sourceURL = toProtocolString(tmp); - if (script->SourceMappingURL().ToLocal(&tmp)) - m_sourceMappingURL = toProtocolString(tmp); - m_startLine = script->LineOffset(); - m_startColumn = script->ColumnOffset(); - std::vector lineEnds = script->LineEnds(); - CHECK(lineEnds.size()); - int source_length = lineEnds[lineEnds.size() - 1]; - if (lineEnds.size()) { - m_endLine = static_cast(lineEnds.size()) + m_startLine - 1; - if (lineEnds.size() > 1) { - m_endColumn = source_length - lineEnds[lineEnds.size() - 2] - 1; - } else { - m_endColumn = source_length + m_startColumn; - } - } else { - m_endLine = m_startLine; - m_endColumn = m_startColumn; - } - - USE(script->ContextId().To(&m_executionContextId)); - - if (script->Source().ToLocal(&tmp)) { - m_source = toProtocolString(tmp); - } - - m_isModule = script->IsModule(); - - m_script.Reset(m_isolate, script); - m_script.AnnotateStrongRetainer(kGlobalDebuggerScriptHandleLabel); + Initialize(script); } bool isLiveEdit() const override { return m_isLiveEdit; } @@ -248,10 +219,18 @@ class ActualScript : public V8DebuggerScript { } private: - String16 GetNameOrSourceUrl(v8::Local script) { - v8::Local name; - if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) - return toProtocolString(name); + String16 GetScriptURL(v8::Local script, + V8InspectorClient* client) { + v8::Local sourceURL; + if (script->SourceURL().ToLocal(&sourceURL) && sourceURL->Length() > 0) + return toProtocolString(sourceURL); + v8::Local v8Name; + if (script->Name().ToLocal(&v8Name) && v8Name->Length() > 0) { + String16 name = toProtocolString(v8Name); + std::unique_ptr url = + client->resourceNameToUrl(toStringView(name)); + return url ? toString16(url->string()) : name; + } return String16(); } @@ -259,6 +238,41 @@ class ActualScript : public V8DebuggerScript { return m_script.Get(m_isolate); } + void Initialize(v8::Local script) { + v8::Local tmp; + m_hasSourceURLComment = + script->SourceURL().ToLocal(&tmp) && tmp->Length() > 0; + if (script->SourceMappingURL().ToLocal(&tmp)) + m_sourceMappingURL = toProtocolString(tmp); + m_startLine = script->LineOffset(); + m_startColumn = script->ColumnOffset(); + std::vector lineEnds = script->LineEnds(); + CHECK(lineEnds.size()); + int source_length = lineEnds[lineEnds.size() - 1]; + if (lineEnds.size()) { + m_endLine = static_cast(lineEnds.size()) + m_startLine - 1; + if (lineEnds.size() > 1) { + m_endColumn = source_length - lineEnds[lineEnds.size() - 2] - 1; + } else { + m_endColumn = source_length + m_startColumn; + } + } else { + m_endLine = m_startLine; + m_endColumn = m_startColumn; + } + + USE(script->ContextId().To(&m_executionContextId)); + + if (script->Source().ToLocal(&tmp)) { + m_source = toProtocolString(tmp); + } + + m_isModule = script->IsModule(); + + m_script.Reset(m_isolate, script); + m_script.AnnotateStrongRetainer(kGlobalDebuggerScriptHandleLabel); + } + String16 m_sourceMappingURL; bool m_isLiveEdit = false; bool m_isModule = false; @@ -392,9 +406,9 @@ class WasmVirtualScript : public V8DebuggerScript { std::unique_ptr V8DebuggerScript::Create( v8::Isolate* isolate, v8::Local scriptObj, - bool isLiveEdit) { + bool isLiveEdit, V8InspectorClient* client) { return std::unique_ptr( - new ActualScript(isolate, scriptObj, isLiveEdit)); + new ActualScript(isolate, scriptObj, isLiveEdit, client)); } std::unique_ptr V8DebuggerScript::CreateWasm( @@ -412,12 +426,11 @@ V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, String16 id, V8DebuggerScript::~V8DebuggerScript() {} -const String16& V8DebuggerScript::sourceURL() const { - return m_sourceURL.isEmpty() ? m_url : m_sourceURL; -} - void V8DebuggerScript::setSourceURL(const String16& sourceURL) { - m_sourceURL = sourceURL; + if (sourceURL.length() > 0) { + m_hasSourceURLComment = true; + m_url = sourceURL; + } } bool V8DebuggerScript::setBreakpoint(const String16& condition, @@ -425,5 +438,4 @@ bool V8DebuggerScript::setBreakpoint(const String16& condition, v8::HandleScope scope(m_isolate); return script()->SetBreakpoint(toV8String(m_isolate, condition), loc, id); } - } // namespace v8_inspector diff --git a/deps/v8/src/inspector/v8-debugger-script.h b/deps/v8/src/inspector/v8-debugger-script.h index 3e3885ed52e1fd..ceaa5076c79bba 100644 --- a/deps/v8/src/inspector/v8-debugger-script.h +++ b/deps/v8/src/inspector/v8-debugger-script.h @@ -40,13 +40,14 @@ namespace v8_inspector { // Forward declaration. +class V8InspectorClient; class WasmTranslation; class V8DebuggerScript { public: static std::unique_ptr Create( v8::Isolate* isolate, v8::Local script, - bool isLiveEdit); + bool isLiveEdit, V8InspectorClient* client); static std::unique_ptr CreateWasm( v8::Isolate* isolate, WasmTranslation* wasmTranslation, v8::Local underlyingScript, String16 id, @@ -55,9 +56,9 @@ class V8DebuggerScript { virtual ~V8DebuggerScript(); const String16& scriptId() const { return m_id; } - const String16& url() const { return m_url; } - bool hasSourceURL() const { return !m_sourceURL.isEmpty(); } - const String16& sourceURL() const; + bool hasSourceURLComment() const { return m_hasSourceURLComment; } + const String16& sourceURL() const { return m_url; } + virtual const String16& sourceMappingURL() const = 0; virtual const String16& source() const = 0; virtual const String16& hash() const = 0; @@ -95,7 +96,7 @@ class V8DebuggerScript { String16 m_id; String16 m_url; - String16 m_sourceURL; + bool m_hasSourceURLComment = false; int m_executionContextId = 0; v8::Isolate* m_isolate; diff --git a/deps/v8/src/inspector/v8-debugger.cc b/deps/v8/src/inspector/v8-debugger.cc index 28212a19938629..6e4e6a1752e3ab 100644 --- a/deps/v8/src/inspector/v8-debugger.cc +++ b/deps/v8/src/inspector/v8-debugger.cc @@ -227,13 +227,15 @@ void V8Debugger::getCompiledScripts( v8::Local script = scripts.Get(i); if (!script->WasCompiled()) continue; if (script->IsEmbedded()) { - result.push_back(V8DebuggerScript::Create(m_isolate, script, false)); + result.push_back(V8DebuggerScript::Create(m_isolate, script, false, + m_inspector->client())); continue; } int contextId; if (!script->ContextId().To(&contextId)) continue; if (m_inspector->contextGroupId(contextId) != contextGroupId) continue; - result.push_back(V8DebuggerScript::Create(m_isolate, script, false)); + result.push_back(V8DebuggerScript::Create(m_isolate, script, false, + m_inspector->client())); } } @@ -542,13 +544,14 @@ void V8Debugger::ScriptCompiled(v8::Local script, }); } else if (m_ignoreScriptParsedEventsCounter == 0) { v8::Isolate* isolate = m_isolate; + V8InspectorClient* client = m_inspector->client(); m_inspector->forEachSession( m_inspector->contextGroupId(contextId), - [&isolate, &script, &has_compile_error, - &is_live_edited](V8InspectorSessionImpl* session) { + [&isolate, &script, &has_compile_error, &is_live_edited, + &client](V8InspectorSessionImpl* session) { if (!session->debuggerAgent()->enabled()) return; session->debuggerAgent()->didParseSource( - V8DebuggerScript::Create(isolate, script, is_live_edited), + V8DebuggerScript::Create(isolate, script, is_live_edited, client), !has_compile_error); }); } diff --git a/deps/v8/src/inspector/v8-profiler-agent-impl.cc b/deps/v8/src/inspector/v8-profiler-agent-impl.cc index 59a99d79d54c2f..f14815fdc4b031 100644 --- a/deps/v8/src/inspector/v8-profiler-agent-impl.cc +++ b/deps/v8/src/inspector/v8-profiler-agent-impl.cc @@ -7,6 +7,7 @@ #include #include "src/base/atomicops.h" +#include "src/debug/debug-interface.h" #include "src/flags.h" // TODO(jgruber): Remove include and DEPS entry. #include "src/inspector/protocol/Protocol.h" #include "src/inspector/string-util.h" @@ -31,6 +32,15 @@ static const char typeProfileStarted[] = "typeProfileStarted"; namespace { +String16 resourceNameToUrl(V8InspectorImpl* inspector, + v8::Local v8Name) { + String16 name = toProtocolString(v8Name); + if (!inspector) return name; + std::unique_ptr url = + inspector->client()->resourceNameToUrl(toStringView(name)); + return url ? toString16(url->string()) : name; +} + std::unique_ptr> buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) { unsigned lineCount = node->GetHitLineCount(); @@ -51,13 +61,14 @@ buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) { } std::unique_ptr buildInspectorObjectFor( - v8::Isolate* isolate, const v8::CpuProfileNode* node) { + V8InspectorImpl* inspector, const v8::CpuProfileNode* node) { + v8::Isolate* isolate = inspector->isolate(); v8::HandleScope handleScope(isolate); auto callFrame = protocol::Runtime::CallFrame::create() .setFunctionName(toProtocolString(node->GetFunctionName())) .setScriptId(String16::fromInteger(node->GetScriptId())) - .setUrl(toProtocolString(node->GetScriptResourceName())) + .setUrl(resourceNameToUrl(inspector, node->GetScriptResourceName())) .setLineNumber(node->GetLineNumber() - 1) .setColumnNumber(node->GetColumnNumber() - 1) .build(); @@ -107,18 +118,19 @@ std::unique_ptr> buildInspectorObjectForTimestamps( return array; } -void flattenNodesTree(v8::Isolate* isolate, const v8::CpuProfileNode* node, +void flattenNodesTree(V8InspectorImpl* inspector, + const v8::CpuProfileNode* node, protocol::Array* list) { - list->addItem(buildInspectorObjectFor(isolate, node)); + list->addItem(buildInspectorObjectFor(inspector, node)); const int childrenCount = node->GetChildrenCount(); for (int i = 0; i < childrenCount; i++) - flattenNodesTree(isolate, node->GetChild(i), list); + flattenNodesTree(inspector, node->GetChild(i), list); } std::unique_ptr createCPUProfile( - v8::Isolate* isolate, v8::CpuProfile* v8profile) { + V8InspectorImpl* inspector, v8::CpuProfile* v8profile) { auto nodes = protocol::Array::create(); - flattenNodesTree(isolate, v8profile->GetTopDownRoot(), nodes.get()); + flattenNodesTree(inspector, v8profile->GetTopDownRoot(), nodes.get()); return protocol::Profiler::Profile::create() .setNodes(std::move(nodes)) .setStartTime(static_cast(v8profile->GetStartTime())) @@ -320,7 +332,7 @@ std::unique_ptr createCoverageRange( } Response coverageToProtocol( - v8::Isolate* isolate, const v8::debug::Coverage& coverage, + V8InspectorImpl* inspector, const v8::debug::Coverage& coverage, std::unique_ptr>* out_result) { std::unique_ptr> result = @@ -361,8 +373,10 @@ Response coverageToProtocol( } String16 url; v8::Local name; - if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) { + if (script->SourceURL().ToLocal(&name) && name->Length()) { url = toProtocolString(name); + } else if (script->Name().ToLocal(&name) && name->Length()) { + url = resourceNameToUrl(inspector, name); } result->addItem(protocol::Profiler::ScriptCoverage::create() .setScriptId(String16::fromInteger(script->Id())) @@ -384,7 +398,7 @@ Response V8ProfilerAgentImpl::takePreciseCoverage( } v8::HandleScope handle_scope(m_isolate); v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(m_isolate); - return coverageToProtocol(m_isolate, coverage, out_result); + return coverageToProtocol(m_session->inspector(), coverage, out_result); } Response V8ProfilerAgentImpl::getBestEffortCoverage( @@ -393,12 +407,12 @@ Response V8ProfilerAgentImpl::getBestEffortCoverage( v8::HandleScope handle_scope(m_isolate); v8::debug::Coverage coverage = v8::debug::Coverage::CollectBestEffort(m_isolate); - return coverageToProtocol(m_isolate, coverage, out_result); + return coverageToProtocol(m_session->inspector(), coverage, out_result); } namespace { std::unique_ptr> -typeProfileToProtocol(v8::Isolate* isolate, +typeProfileToProtocol(V8InspectorImpl* inspector, const v8::debug::TypeProfile& type_profile) { std::unique_ptr> result = protocol::Array::create(); @@ -426,8 +440,10 @@ typeProfileToProtocol(v8::Isolate* isolate, } String16 url; v8::Local name; - if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) { + if (script->SourceURL().ToLocal(&name) && name->Length()) { url = toProtocolString(name); + } else if (script->Name().ToLocal(&name) && name->Length()) { + url = resourceNameToUrl(inspector, name); } result->addItem(protocol::Profiler::ScriptTypeProfile::create() .setScriptId(String16::fromInteger(script->Id())) @@ -462,7 +478,7 @@ Response V8ProfilerAgentImpl::takeTypeProfile( v8::HandleScope handle_scope(m_isolate); v8::debug::TypeProfile type_profile = v8::debug::TypeProfile::Collect(m_isolate); - *out_result = typeProfileToProtocol(m_isolate, type_profile); + *out_result = typeProfileToProtocol(m_session->inspector(), type_profile); return Response::OK(); } @@ -491,7 +507,7 @@ std::unique_ptr V8ProfilerAgentImpl::stopProfiling( m_profiler->StopProfiling(toV8String(m_isolate, title)); std::unique_ptr result; if (profile) { - if (serialize) result = createCPUProfile(m_isolate, profile); + if (serialize) result = createCPUProfile(m_session->inspector(), profile); profile->Delete(); } --m_startedProfilesCount; diff --git a/deps/v8/src/inspector/v8-stack-trace-impl.cc b/deps/v8/src/inspector/v8-stack-trace-impl.cc index 8c208aaf8a26c2..8d385d0d6d8ad7 100644 --- a/deps/v8/src/inspector/v8-stack-trace-impl.cc +++ b/deps/v8/src/inspector/v8-stack-trace-impl.cc @@ -7,6 +7,7 @@ #include #include "src/inspector/v8-debugger.h" +#include "src/inspector/v8-inspector-impl.h" #include "src/inspector/wasm-translation.h" namespace v8_inspector { @@ -71,7 +72,10 @@ std::unique_ptr buildInspectorObjectCommon( std::unique_ptr> inspectorFrames = protocol::Array::create(); for (size_t i = 0; i < frames.size(); i++) { - inspectorFrames->addItem(frames[i]->buildInspectorObject()); + V8InspectorClient* client = nullptr; + if (debugger && debugger->inspector()) + client = debugger->inspector()->client(); + inspectorFrames->addItem(frames[i]->buildInspectorObject(client)); } std::unique_ptr stackTrace = protocol::Runtime::StackTrace::create() @@ -115,7 +119,9 @@ StackFrame::StackFrame(v8::Local v8Frame) m_scriptId(String16::fromInteger(v8Frame->GetScriptId())), m_sourceURL(toProtocolString(v8Frame->GetScriptNameOrSourceURL())), m_lineNumber(v8Frame->GetLineNumber() - 1), - m_columnNumber(v8Frame->GetColumn() - 1) { + m_columnNumber(v8Frame->GetColumn() - 1), + m_hasSourceURLComment(v8Frame->GetScriptName() != + v8Frame->GetScriptNameOrSourceURL()) { DCHECK_NE(v8::Message::kNoLineNumberInfo, m_lineNumber + 1); DCHECK_NE(v8::Message::kNoColumnInfo, m_columnNumber + 1); } @@ -135,12 +141,20 @@ int StackFrame::lineNumber() const { return m_lineNumber; } int StackFrame::columnNumber() const { return m_columnNumber; } -std::unique_ptr StackFrame::buildInspectorObject() - const { +std::unique_ptr StackFrame::buildInspectorObject( + V8InspectorClient* client) const { + String16 frameUrl = m_sourceURL; + if (client && !m_hasSourceURLComment && frameUrl.length() > 0) { + std::unique_ptr url = + client->resourceNameToUrl(toStringView(m_sourceURL)); + if (url) { + frameUrl = toString16(url->string()); + } + } return protocol::Runtime::CallFrame::create() .setFunctionName(m_functionName) .setScriptId(m_scriptId) - .setUrl(m_sourceURL) + .setUrl(frameUrl) .setLineNumber(m_lineNumber) .setColumnNumber(m_columnNumber) .build(); diff --git a/deps/v8/src/inspector/v8-stack-trace-impl.h b/deps/v8/src/inspector/v8-stack-trace-impl.h index 87d2b0f0270823..513aa41b909c52 100644 --- a/deps/v8/src/inspector/v8-stack-trace-impl.h +++ b/deps/v8/src/inspector/v8-stack-trace-impl.h @@ -33,7 +33,8 @@ class StackFrame { const String16& sourceURL() const; int lineNumber() const; // 0-based. int columnNumber() const; // 0-based. - std::unique_ptr buildInspectorObject() const; + std::unique_ptr buildInspectorObject( + V8InspectorClient* client) const; bool isEqual(StackFrame* frame) const; private: @@ -42,6 +43,7 @@ class StackFrame { String16 m_sourceURL; int m_lineNumber; // 0-based. int m_columnNumber; // 0-based. + bool m_hasSourceURLComment; }; class V8StackTraceImpl : public V8StackTrace { diff --git a/deps/v8/test/inspector/debugger/resource-name-to-url-expected.txt b/deps/v8/test/inspector/debugger/resource-name-to-url-expected.txt new file mode 100644 index 00000000000000..2e6e589b2517d3 --- /dev/null +++ b/deps/v8/test/inspector/debugger/resource-name-to-url-expected.txt @@ -0,0 +1,122 @@ +Tests V8InspectorClient::resourceNameToUrl. +Check script with url: +{ + method : Debugger.scriptParsed + params : { + endColumn : 16 + endLine : 0 + executionContextId : + hasSourceURL : false + hash : 033b33d191ed51ed823355d865eb871d811403e2 + isLiveEdit : false + isModule : false + length : 16 + scriptId : + sourceMapURL : + startColumn : 0 + startLine : 0 + url : prefix://url + } +} +Check script with sourceURL comment: +{ + method : Debugger.scriptParsed + params : { + endColumn : 37 + endLine : 0 + executionContextId : + hasSourceURL : true + hash : 06c136ce206c5f505f32af524e6ec71b5baa0bbb + isLiveEdit : false + isModule : false + length : 37 + scriptId : + sourceMapURL : + startColumn : 0 + startLine : 0 + url : foo.js + } +} +Check script failed to parse: +{ + method : Debugger.scriptFailedToParse + params : { + endColumn : 15 + endLine : 0 + executionContextId : + hasSourceURL : false + hash : 033b33d191ed51ed1f44cd0465eb871d811403e2 + isModule : false + length : 15 + scriptId : + sourceMapURL : + startColumn : 0 + startLine : 0 + url : prefix://url + } +} +Check script failed to parse with sourceURL comment: +{ + method : Debugger.scriptFailedToParse + params : { + endColumn : 36 + endLine : 0 + executionContextId : + hasSourceURL : true + hash : 23a2885951475580023e2a742563d78876d8f05e + isModule : false + length : 36 + scriptId : + sourceMapURL : + startColumn : 0 + startLine : 0 + url : foo.js + } +} +Test runtime stack trace: +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 42 + type : number + value : 42 + } + ] + executionContextId : + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 14 + functionName : foo + lineNumber : 2 + scriptId : + url : prefix://url + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : + url : boo.js + } + [2] : { + columnNumber : 4 + functionName : + lineNumber : 4 + scriptId : + url : prefix://url + } + ] + } + timestamp : + type : log + } +} +Test debugger stack trace: +[ + [0] : prefix://url + [1] : boo.js + [2] : prefix://url +] diff --git a/deps/v8/test/inspector/debugger/resource-name-to-url.js b/deps/v8/test/inspector/debugger/resource-name-to-url.js new file mode 100644 index 00000000000000..620c7a2864b406 --- /dev/null +++ b/deps/v8/test/inspector/debugger/resource-name-to-url.js @@ -0,0 +1,49 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +let {session, contextGroup, Protocol} = InspectorTest.start( + 'Tests V8InspectorClient::resourceNameToUrl.'); + +(async function test(){ + Protocol.Runtime.enable(); + await Protocol.Debugger.enable(); + contextGroup.addScript(`inspector.setResourceNamePrefix('prefix://')`); + await Protocol.Debugger.onceScriptParsed(); + + InspectorTest.log('Check script with url:'); + contextGroup.addScript('function foo(){}', 0, 0, 'url'); + InspectorTest.logMessage(await Protocol.Debugger.onceScriptParsed()); + + InspectorTest.log('Check script with sourceURL comment:'); + contextGroup.addScript('function foo(){} //# sourceURL=foo.js', 0, 0, 'url'); + InspectorTest.logMessage(await Protocol.Debugger.onceScriptParsed()); + + InspectorTest.log('Check script failed to parse:'); + contextGroup.addScript('function foo(){', 0, 0, 'url'); + InspectorTest.logMessage(await Protocol.Debugger.onceScriptFailedToParse()); + + InspectorTest.log('Check script failed to parse with sourceURL comment:'); + contextGroup.addScript('function foo(){ //# sourceURL=foo.js', 0, 0, 'url'); + InspectorTest.logMessage(await Protocol.Debugger.onceScriptFailedToParse()); + + InspectorTest.log('Test runtime stack trace:'); + contextGroup.addScript(` + function foo() { + console.log(42); + } + eval('foo(); //# sourceURL=boo.js'); + `, 0, 0, 'url'); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + InspectorTest.log('Test debugger stack trace:'); + contextGroup.addScript(` + function foo() { + debugger; + } + eval('foo(); //# sourceURL=boo.js'); + `, 0, 0, 'url'); + const {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + InspectorTest.logMessage(callFrames.map(frame => frame.url)); + InspectorTest.completeTest(); +})(); diff --git a/deps/v8/test/inspector/inspector-test.cc b/deps/v8/test/inspector/inspector-test.cc index 668a9463d5b9cf..93a8b1d3f21880 100644 --- a/deps/v8/test/inspector/inspector-test.cc +++ b/deps/v8/test/inspector/inspector-test.cc @@ -712,6 +712,9 @@ class InspectorExtension : public IsolateData::SetupGlobalTask { ToV8String(isolate, "setAllowCodeGenerationFromStrings"), v8::FunctionTemplate::New( isolate, &InspectorExtension::SetAllowCodeGenerationFromStrings)); + inspector->Set(ToV8String(isolate, "setResourceNamePrefix"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::SetResourceNamePrefix)); global->Set(ToV8String(isolate, "inspector"), inspector); } @@ -973,6 +976,18 @@ class InspectorExtension : public IsolateData::SetupGlobalTask { args.GetIsolate()->GetCurrentContext()->AllowCodeGenerationFromStrings( args[0].As()->Value()); } + + static void SetResourceNamePrefix( + const v8::FunctionCallbackInfo& args) { + if (args.Length() != 1 || !args[0]->IsString()) { + fprintf(stderr, "Internal error: setResourceNamePrefix('prefix')."); + Exit(); + } + v8::Isolate* isolate = args.GetIsolate(); + v8::Local context = isolate->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + data->SetResourceNamePrefix(v8::Local::Cast(args[0])); + } }; bool RunExtraCode(v8::Isolate* isolate, v8::Local context, diff --git a/deps/v8/test/inspector/isolate-data.cc b/deps/v8/test/inspector/isolate-data.cc index a18ef90ca04b98..04c449927eb767 100644 --- a/deps/v8/test/inspector/isolate-data.cc +++ b/deps/v8/test/inspector/isolate-data.cc @@ -422,3 +422,32 @@ void IsolateData::maxAsyncCallStackDepthChanged(int depth) { if (!log_max_async_call_stack_depth_changed_) return; fprintf(stdout, "maxAsyncCallStackDepthChanged: %d\n", depth); } + +void IsolateData::SetResourceNamePrefix(v8::Local prefix) { + resource_name_prefix_.Reset(v8::Isolate::GetCurrent(), prefix); +} + +namespace { +class StringBufferImpl : public v8_inspector::StringBuffer { + public: + StringBufferImpl(v8::Isolate* isolate, v8::Local string) + : data_(ToVector(string)), + view_(data_.start(), data_.length()) {} + const v8_inspector::StringView& string() override { return view_; } + + private: + v8::internal::Vector data_; + v8_inspector::StringView view_; +}; +} // anonymous namespace + +std::unique_ptr IsolateData::resourceNameToUrl( + const v8_inspector::StringView& resourceName) { + if (resource_name_prefix_.IsEmpty()) return nullptr; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Local name = ToString(isolate, resourceName); + v8::Local prefix = resource_name_prefix_.Get(isolate); + v8::Local url = v8::String::Concat(prefix, name); + return std::unique_ptr(new StringBufferImpl(isolate, url)); +} diff --git a/deps/v8/test/inspector/isolate-data.h b/deps/v8/test/inspector/isolate-data.h index 5eb9803a7416fb..d0a263e573827c 100644 --- a/deps/v8/test/inspector/isolate-data.h +++ b/deps/v8/test/inspector/isolate-data.h @@ -76,6 +76,7 @@ class IsolateData : public v8_inspector::V8InspectorClient { void FireContextCreated(v8::Local context, int context_group_id); void FireContextDestroyed(v8::Local context); void FreeContext(v8::Local context); + void SetResourceNamePrefix(v8::Local prefix); private: struct VectorCompare { @@ -114,6 +115,8 @@ class IsolateData : public v8_inspector::V8InspectorClient { v8_inspector::V8StackTrace*) override; bool isInspectableHeapObject(v8::Local) override; void maxAsyncCallStackDepthChanged(int depth) override; + std::unique_ptr resourceNameToUrl( + const v8_inspector::StringView& resourceName) override; // The isolate gets deleted by its {Dispose} method, not by the default // deleter. Therefore we have to define a custom deleter for the unique_ptr to @@ -141,6 +144,7 @@ class IsolateData : public v8_inspector::V8InspectorClient { bool log_console_api_message_calls_ = false; bool log_max_async_call_stack_depth_changed_ = false; v8::Global not_inspectable_private_; + v8::Global resource_name_prefix_; DISALLOW_COPY_AND_ASSIGN(IsolateData); }; From ce58979c86bdd3616cd8be5c5a61cf8818c436f9 Mon Sep 17 00:00:00 2001 From: Alexey Kozyatinskiy Date: Thu, 30 Aug 2018 14:58:38 -0700 Subject: [PATCH 69/77] src: added URL::FromFilePath method Method returns file URL from native file path. Backport-PR-URL: https://github.com/nodejs/node/pull/22918 PR-URL: https://github.com/nodejs/node/pull/22251 Reviewed-By: Eugene Ostroukhov Reviewed-By: Tiancheng "Timothy" Gu --- src/node_url.cc | 13 +++++++++++++ src/node_url.h | 2 ++ test/cctest/test_url.cc | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/node_url.cc b/src/node_url.cc index 4d57027dd29ce9..acc423d931b603 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -2348,6 +2348,19 @@ std::string URL::ToFilePath() const { #endif } +URL URL::FromFilePath(const std::string& file_path) { + URL url("file://"); + std::string escaped_file_path; + for (size_t i = 0; i < file_path.length(); ++i) { + escaped_file_path += file_path[i]; + if (file_path[i] == '%') + escaped_file_path += "25"; + } + URL::Parse(escaped_file_path.c_str(), escaped_file_path.length(), kPathStart, + &url.context_, true, nullptr, false); + return url; +} + // This function works by calling out to a JS function that creates and // returns the JS URL object. Be mindful of the JS<->Native boundary // crossing that is required. diff --git a/src/node_url.h b/src/node_url.h index b2eadf9923a7ea..5e61aee4efbd5a 100644 --- a/src/node_url.h +++ b/src/node_url.h @@ -169,6 +169,8 @@ class URL { // Get the path of the file: URL in a format consumable by native file system // APIs. Returns an empty string if something went wrong. std::string ToFilePath() const; + // Get the file URL from native file system path. + static URL FromFilePath(const std::string& file_path); const Local ToObject(Environment* env) const; diff --git a/test/cctest/test_url.cc b/test/cctest/test_url.cc index 088634152a79c1..2e9b06e3a4783a 100644 --- a/test/cctest/test_url.cc +++ b/test/cctest/test_url.cc @@ -109,3 +109,36 @@ TEST_F(URLTest, ToFilePath) { #undef T } + +TEST_F(URLTest, FromFilePath) { + URL file_url; +#ifdef _WIN32 + file_url = URL::FromFilePath("C:\\Program Files\\"); + EXPECT_EQ("file:", file_url.protocol()); + EXPECT_EQ("/C:/Program%20Files/", file_url.path()); + + file_url = URL::FromFilePath("C:\\a\\b\\c"); + EXPECT_EQ("file:", file_url.protocol()); + EXPECT_EQ("/C:/a/b/c", file_url.path()); + + file_url = URL::FromFilePath("b:\\a\\%%.js"); + EXPECT_EQ("file:", file_url.protocol()); + EXPECT_EQ("/b:/a/%25%25.js", file_url.path()); + + file_url = URL::FromFilePath("\\\\host\\a\\b\\c"); + EXPECT_EQ("file:", file_url.protocol()); + EXPECT_EQ("host/a/b/c", file_url.path()); +#else + file_url = URL::FromFilePath("/"); + EXPECT_EQ("file:", file_url.protocol()); + EXPECT_EQ("/", file_url.path()); + + file_url = URL::FromFilePath("/a/b/c"); + EXPECT_EQ("file:", file_url.protocol()); + EXPECT_EQ("/a/b/c", file_url.path()); + + file_url = URL::FromFilePath("/a/%%.js"); + EXPECT_EQ("file:", file_url.protocol()); + EXPECT_EQ("/a/%25%25.js", file_url.path()); +#endif +} From 7f985da32155b301d670e31f51d1d8257a488ac3 Mon Sep 17 00:00:00 2001 From: Alexey Kozyatinskiy Date: Thu, 30 Aug 2018 14:59:34 -0700 Subject: [PATCH 70/77] inspector: implemented V8InspectorClient::resourceNameToUrl This method is required by inspector to report normalized urls over the protocol. Backport-PR-URL: https://github.com/nodejs/node/pull/22918 Fixes https://github.com/nodejs/node/issues/22223 PR-URL: https://github.com/nodejs/node/pull/22251 Reviewed-By: Eugene Ostroukhov Reviewed-By: Tiancheng "Timothy" Gu --- src/inspector_agent.cc | 32 +++++++++++++++ test/cctest/test_url.cc | 4 -- .../test-inspector-multisession-js.js | 6 ++- test/parallel/test-v8-coverage.js | 2 +- test/sequential/test-inspector-bindings.js | 6 ++- .../test-inspector-break-when-eval.js | 5 ++- .../test-inspector-debug-brk-flag.js | 2 +- test/sequential/test-inspector-exception.js | 3 +- .../test-inspector-resource-name-to-url.js | 40 +++++++++++++++++++ test/sequential/test-inspector.js | 6 +-- 10 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 test/sequential/test-inspector-resource-name-to-url.js diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index c8bface6bf5372..63b92663532e06 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -6,6 +6,7 @@ #include "inspector/tracing_agent.h" #include "node/inspector/protocol/Protocol.h" #include "node_internals.h" +#include "node_url.h" #include "v8-inspector.h" #include "v8-platform.h" @@ -375,6 +376,25 @@ void NotifyClusterWorkersDebugEnabled(Environment* env) { MakeCallback(env->isolate(), process_object, emit_fn.As(), arraysize(argv), argv, {0, 0}); } + +#ifdef _WIN32 +bool IsFilePath(const std::string& path) { + // '\\' + if (path.length() > 2 && path[0] == '\\' && path[1] == '\\') + return true; + // '[A-Z]:[/\\]' + if (path.length() < 3) + return false; + if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) + return path[1] == ':' && (path[2] == '/' || path[2] == '\\'); + return false; +} +#else +bool IsFilePath(const std::string& path) { + return path.length() && path[0] == '/'; +} +#endif // __POSIX__ + } // namespace class NodeInspectorClient : public V8InspectorClient { @@ -601,6 +621,18 @@ class NodeInspectorClient : public V8InspectorClient { return env_->isolate_data()->platform()->CurrentClockTimeMillis(); } + std::unique_ptr resourceNameToUrl( + const StringView& resource_name_view) override { + std::string resource_name = + protocol::StringUtil::StringViewToUtf8(resource_name_view); + if (!IsFilePath(resource_name)) + return nullptr; + node::url::URL url = node::url::URL::FromFilePath(resource_name); + // TODO(ak239spb): replace this code with url.href(). + // Refs: https://github.com/nodejs/node/issues/22610 + return Utf8ToStringView(url.protocol() + "//" + url.path()); + } + node::Environment* env_; bool is_main_; bool running_nested_loop_ = false; diff --git a/test/cctest/test_url.cc b/test/cctest/test_url.cc index 2e9b06e3a4783a..ddef534b57485f 100644 --- a/test/cctest/test_url.cc +++ b/test/cctest/test_url.cc @@ -124,10 +124,6 @@ TEST_F(URLTest, FromFilePath) { file_url = URL::FromFilePath("b:\\a\\%%.js"); EXPECT_EQ("file:", file_url.protocol()); EXPECT_EQ("/b:/a/%25%25.js", file_url.path()); - - file_url = URL::FromFilePath("\\\\host\\a\\b\\c"); - EXPECT_EQ("file:", file_url.protocol()); - EXPECT_EQ("host/a/b/c", file_url.path()); #else file_url = URL::FromFilePath("/"); EXPECT_EQ("file:", file_url.protocol()); diff --git a/test/parallel/test-inspector-multisession-js.js b/test/parallel/test-inspector-multisession-js.js index 097b77e2c24231..92879d3ff3a7df 100644 --- a/test/parallel/test-inspector-multisession-js.js +++ b/test/parallel/test-inspector-multisession-js.js @@ -1,3 +1,4 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); @@ -6,6 +7,7 @@ common.skipIfInspectorDisabled(); const assert = require('assert'); const { Session } = require('inspector'); const path = require('path'); +const { pathToFileURL } = require('url'); function debugged() { return 42; @@ -32,8 +34,8 @@ async function test() { await new Promise((resolve, reject) => { session1.post('Debugger.setBreakpointByUrl', { - 'lineNumber': 9, - 'url': path.resolve(__dirname, __filename), + 'lineNumber': 12, + 'url': pathToFileURL(path.resolve(__dirname, __filename)).toString(), 'columnNumber': 0, 'condition': '' }, (error, result) => { diff --git a/test/parallel/test-v8-coverage.js b/test/parallel/test-v8-coverage.js index ad5100b42ea8d9..91581a5a073460 100644 --- a/test/parallel/test-v8-coverage.js +++ b/test/parallel/test-v8-coverage.js @@ -97,7 +97,7 @@ function getFixtureCoverage(fixtureFile, coverageDirectory) { for (const coverageFile of coverageFiles) { const coverage = require(path.join(coverageDirectory, coverageFile)); for (const fixtureCoverage of coverage.result) { - if (fixtureCoverage.url.indexOf(`${path.sep}${fixtureFile}`) !== -1) { + if (fixtureCoverage.url.indexOf(`/${fixtureFile}`) !== -1) { return fixtureCoverage; } } diff --git a/test/sequential/test-inspector-bindings.js b/test/sequential/test-inspector-bindings.js index bea8b552202087..f5583c1d7bc6d6 100644 --- a/test/sequential/test-inspector-bindings.js +++ b/test/sequential/test-inspector-bindings.js @@ -1,9 +1,11 @@ +// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); const assert = require('assert'); const inspector = require('inspector'); const path = require('path'); +const { pathToFileURL } = require('url'); // This test case will set a breakpoint 4 lines below function debuggedFunction() { @@ -84,8 +86,8 @@ function testSampleDebugSession() { }, TypeError); session.post('Debugger.enable', () => cbAsSecondArgCalled = true); session.post('Debugger.setBreakpointByUrl', { - 'lineNumber': 12, - 'url': path.resolve(__dirname, __filename), + 'lineNumber': 14, + 'url': pathToFileURL(path.resolve(__dirname, __filename)).toString(), 'columnNumber': 0, 'condition': '' }); diff --git a/test/sequential/test-inspector-break-when-eval.js b/test/sequential/test-inspector-break-when-eval.js index 8be5285221d513..e7529f786a9859 100644 --- a/test/sequential/test-inspector-break-when-eval.js +++ b/test/sequential/test-inspector-break-when-eval.js @@ -5,6 +5,7 @@ common.skipIfInspectorDisabled(); const assert = require('assert'); const { NodeInstance } = require('../common/inspector-helper.js'); const fixtures = require('../common/fixtures'); +const { pathToFileURL } = require('url'); const script = fixtures.path('inspector-global-function.js'); @@ -26,7 +27,7 @@ async function breakOnLine(session) { const commands = [ { 'method': 'Debugger.setBreakpointByUrl', 'params': { 'lineNumber': 9, - 'url': script, + 'url': pathToFileURL(script).toString(), 'columnNumber': 0, 'condition': '' } @@ -45,7 +46,7 @@ async function breakOnLine(session) { } ]; session.send(commands); - await session.waitForBreakOnLine(9, script); + await session.waitForBreakOnLine(9, pathToFileURL(script).toString()); } async function stepOverConsoleStatement(session) { diff --git a/test/sequential/test-inspector-debug-brk-flag.js b/test/sequential/test-inspector-debug-brk-flag.js index 0e5df52560d2b1..d488eea2626584 100644 --- a/test/sequential/test-inspector-debug-brk-flag.js +++ b/test/sequential/test-inspector-debug-brk-flag.js @@ -24,7 +24,7 @@ async function testBreakpointOnStart(session) { ]; session.send(commands); - await session.waitForBreakOnLine(0, session.scriptPath()); + await session.waitForBreakOnLine(0, session.scriptURL()); } async function runTests() { diff --git a/test/sequential/test-inspector-exception.js b/test/sequential/test-inspector-exception.js index ef67e1d9a57264..4a41e8826a50d1 100644 --- a/test/sequential/test-inspector-exception.js +++ b/test/sequential/test-inspector-exception.js @@ -7,6 +7,7 @@ common.skipIfInspectorDisabled(); const assert = require('assert'); const { NodeInstance } = require('../common/inspector-helper.js'); +const { pathToFileURL } = require('url'); const script = fixtures.path('throws_error.js'); @@ -29,7 +30,7 @@ async function testBreakpointOnStart(session) { ]; await session.send(commands); - await session.waitForBreakOnLine(0, script); + await session.waitForBreakOnLine(0, pathToFileURL(script).toString()); } diff --git a/test/sequential/test-inspector-resource-name-to-url.js b/test/sequential/test-inspector-resource-name-to-url.js new file mode 100644 index 00000000000000..41a98ba219b24c --- /dev/null +++ b/test/sequential/test-inspector-resource-name-to-url.js @@ -0,0 +1,40 @@ +'use strict'; +const common = require('../common'); + +common.skipIfInspectorDisabled(); + +(async function test() { + const { strictEqual } = require('assert'); + const { Session } = require('inspector'); + const { promisify } = require('util'); + const vm = require('vm'); + const session = new Session(); + session.connect(); + session.post = promisify(session.post); + await session.post('Debugger.enable'); + await check('http://example.com', 'http://example.com'); + await check(undefined, 'evalmachine.'); + await check('file:///foo.js', 'file:///foo.js'); + await check('file:///foo.js', 'file:///foo.js'); + await check('foo.js', 'foo.js'); + await check('[eval]', '[eval]'); + await check('%.js', '%.js'); + + if (common.isWindows) { + await check('C:\\foo.js', 'file:///C:/foo.js'); + await check('C:\\a\\b\\c\\foo.js', 'file:///C:/a/b/c/foo.js'); + await check('a:\\%.js', 'file:///a:/%25.js'); + } else { + await check('/foo.js', 'file:///foo.js'); + await check('/a/b/c/d/foo.js', 'file:///a/b/c/d/foo.js'); + await check('/%%%.js', 'file:///%25%25%25.js'); + } + + async function check(filename, expected) { + const promise = + new Promise((resolve) => session.once('inspectorNotification', resolve)); + new vm.Script('42', { filename }).runInThisContext(); + const { params: { url } } = await promise; + strictEqual(url, expected); + } +})(); diff --git a/test/sequential/test-inspector.js b/test/sequential/test-inspector.js index d641015a3c9954..2a7a2ef4bf34ba 100644 --- a/test/sequential/test-inspector.js +++ b/test/sequential/test-inspector.js @@ -68,7 +68,7 @@ async function testBreakpointOnStart(session) { ]; await session.send(commands); - await session.waitForBreakOnLine(0, session.scriptPath()); + await session.waitForBreakOnLine(0, session.scriptURL()); } async function testBreakpoint(session) { @@ -76,7 +76,7 @@ async function testBreakpoint(session) { const commands = [ { 'method': 'Debugger.setBreakpointByUrl', 'params': { 'lineNumber': 5, - 'url': session.scriptPath(), + 'url': session.scriptURL(), 'columnNumber': 0, 'condition': '' } @@ -91,7 +91,7 @@ async function testBreakpoint(session) { `Script source is wrong: ${scriptSource}`); await session.waitForConsoleOutput('log', ['A message', 5]); - const paused = await session.waitForBreakOnLine(5, session.scriptPath()); + const paused = await session.waitForBreakOnLine(5, session.scriptURL()); const scopeId = paused.params.callFrames[0].scopeChain[0].object.objectId; console.log('[test]', 'Verify we can read current application state'); From f29786698cd17d5bf35a3d32d892e653109d4d36 Mon Sep 17 00:00:00 2001 From: Daniel Beckert Date: Mon, 17 Sep 2018 16:26:31 -0300 Subject: [PATCH 71/77] deps: cherry-pick 9a23bdd from upstream V8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [Isolate] Fix Isolate::PrintCurrentStackTrace for interpreted frames Previously we were getting the code object from the stack, so printed incorrect position details for interpreted frames. BUG=v8:7916 Change-Id: I2f87584117d88b7db3f3b9bdbfe793c4d3e33fe9 Reviewed-on: https://chromium-review.googlesource.com/1126313 Reviewed-by: Toon Verwaest Commit-Queue: Ross McIlroy Cr-Commit-Position: refs/heads/master@{#54253} Refs: https://github.com/v8/v8/commit/9a23bdd7ea2eba9a7a4439a7844e72fbf42bb3c4 Refs: https://github.com/nodejs/node/issues/21988 PR-URL: https://github.com/nodejs/node/pull/22910 Reviewed-By: Matheus Marchini Reviewed-By: Michaël Zasso --- common.gypi | 2 +- deps/v8/src/isolate.cc | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/common.gypi b/common.gypi index e9e05049dbb265..39afdc4d95a28d 100644 --- a/common.gypi +++ b/common.gypi @@ -29,7 +29,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.28', + 'v8_embedder_string': '-node.29', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index bb50ae493d5eea..0bdfef5e81b319 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -1661,8 +1661,17 @@ void Isolate::PrintCurrentStackTrace(FILE* out) { Handle receiver(frame->receiver(), this); Handle function(frame->function(), this); - Handle code(AbstractCode::cast(frame->LookupCode()), this); - const int offset = static_cast(frame->pc() - code->InstructionStart()); + Handle code; + int offset; + if (frame->is_interpreted()) { + InterpretedFrame* interpreted_frame = InterpretedFrame::cast(frame); + code = handle(AbstractCode::cast(interpreted_frame->GetBytecodeArray()), + this); + offset = interpreted_frame->GetBytecodeOffset(); + } else { + code = handle(AbstractCode::cast(frame->LookupCode()), this); + offset = static_cast(frame->pc() - code->InstructionStart()); + } JSStackFrame site(this, receiver, function, code, offset); Handle line = site.ToString().ToHandleChecked(); From c68adddcb012f3781da80fbbc4af2f7e112d7ff0 Mon Sep 17 00:00:00 2001 From: MaleDong Date: Fri, 14 Sep 2018 16:13:14 +0800 Subject: [PATCH 72/77] lib,doc: remove unused parameter, improve docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) Remove 'callback' in 'check' function, because we don't check or use that directly. 2) Make 'digest' clearer in the documentation. PR-URL: https://github.com/nodejs/node/pull/22858 Reviewed-By: Tobias Nießen Reviewed-By: Luigi Pinca --- doc/api/crypto.md | 6 ++++++ lib/internal/crypto/pbkdf2.js | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 739daa1a72eea2..2331af12aceae7 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1808,6 +1808,9 @@ otherwise `err` will be `null`. By default, the successfully generated `derivedKey` will be passed to the callback as a [`Buffer`][]. An error will be thrown if any of the input arguments specify invalid values or types. +If `digest` is `null`, `'sha1'` will be used. This behavior will be deprecated +in a future version of Node.js. + The `iterations` argument must be a number set as high as possible. The higher the number of iterations, the more secure the derived key will be, but will take a longer amount of time to complete. @@ -1871,6 +1874,9 @@ applied to derive a key of the requested byte length (`keylen`) from the If an error occurs an `Error` will be thrown, otherwise the derived key will be returned as a [`Buffer`][]. +If `digest` is `null`, `'sha1'` will be used. This behavior will be deprecated +in a future version of Node.js. + The `iterations` argument must be a number set as high as possible. The higher the number of iterations, the more secure the derived key will be, but will take a longer amount of time to complete. diff --git a/lib/internal/crypto/pbkdf2.js b/lib/internal/crypto/pbkdf2.js index 9cbfb3dc64211d..5b2d59eb759115 100644 --- a/lib/internal/crypto/pbkdf2.js +++ b/lib/internal/crypto/pbkdf2.js @@ -22,7 +22,7 @@ function pbkdf2(password, salt, iterations, keylen, digest, callback) { } ({ password, salt, iterations, keylen, digest } = - check(password, salt, iterations, keylen, digest, callback)); + check(password, salt, iterations, keylen, digest)); if (typeof callback !== 'function') throw new ERR_INVALID_CALLBACK(); @@ -42,7 +42,7 @@ function pbkdf2(password, salt, iterations, keylen, digest, callback) { function pbkdf2Sync(password, salt, iterations, keylen, digest) { ({ password, salt, iterations, keylen, digest } = - check(password, salt, iterations, keylen, digest, pbkdf2Sync)); + check(password, salt, iterations, keylen, digest)); const keybuf = Buffer.alloc(keylen); handleError(keybuf, password, salt, iterations, digest); const encoding = getDefaultEncoding(); @@ -50,7 +50,7 @@ function pbkdf2Sync(password, salt, iterations, keylen, digest) { return keybuf.toString(encoding); } -function check(password, salt, iterations, keylen, digest, callback) { +function check(password, salt, iterations, keylen, digest) { if (typeof digest !== 'string') { if (digest !== null) throw new ERR_INVALID_ARG_TYPE('digest', ['string', 'null'], digest); From 89439ac512a325992b39ff182e1df9f3115c1cab Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Sun, 16 Sep 2018 20:49:11 -0700 Subject: [PATCH 73/77] tools: synchronize deepStrictEqual() message rules Update ESLint config to include a rule about assert.deepStrictEqual() messages and string literals. The rule is included in lib and test, but should be included everywhere else as well. PR-URL: https://github.com/nodejs/node/pull/22887 Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Teddy Katz Reviewed-By: Richard Lau --- .eslintrc.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index e4192c3539925c..8347d066ed22ec 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -159,6 +159,10 @@ module.exports = { // and test/.eslintrc.yaml. 'no-restricted-syntax': [ 'error', + { + selector: "CallExpression[callee.object.name='assert'][callee.property.name='deepStrictEqual'][arguments.2.type='Literal']", + message: 'Do not use a literal for the third argument of assert.deepStrictEqual()' + }, { selector: "CallExpression[callee.object.name='assert'][callee.property.name='doesNotThrow']", message: 'Please replace `assert.doesNotThrow()` and add a comment next to the code instead.' From d46ce6559f1ccf05e8cfc9b8c97a307ac0aa54d9 Mon Sep 17 00:00:00 2001 From: isurusiri Date: Mon, 30 Apr 2018 21:43:29 +0530 Subject: [PATCH 74/77] doc: explain how to invoke gc Currently the documentation for Wrapping C++ Objects doesn't explain how to destruct an object by explicitly invoking the garbage collector. This commit includes a modification to docs that explains how to force the garbage collector to clear objects using V8's command line flags. Fixes: https://github.com/nodejs/node/issues/19876 PR-URL: https://github.com/nodejs/node/pull/20431 Reviewed-By: James M Snell Reviewed-By: Yang Guo --- doc/api/addons.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/api/addons.md b/doc/api/addons.md index 483f2ad27d7feb..5e06336a85a4a0 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -848,6 +848,13 @@ console.log(obj.plusOne()); // Prints: 13 ``` +The destructor for a wrapper object will run when the object is +garbage-collected. For destructor testing, there are command-line flags that +can be used to make it possible to force garbage collection. These flags are +provided by the underlying V8 JavaScript engine. They are subject to change +or removal at any time. They are not documented by Node.js or V8, and they +should never be used outside of testing. + ### Factory of wrapped objects Alternatively, it is possible to use a factory pattern to avoid explicitly From d4278a0e9fff5b0058297a62a04aac81e6533e70 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Wed, 12 Sep 2018 11:07:00 +0200 Subject: [PATCH 75/77] doc, win: improve os.setPriority documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/22817 Fixes: https://github.com/nodejs/node/issues/22799 Reviewed-By: Tobias Nießen Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig --- doc/api/os.md | 3 +++ test/parallel/test-os-process-priority.js | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/api/os.md b/doc/api/os.md index a0ff5e7ff17bf0..ad5736d7690016 100644 --- a/doc/api/os.md +++ b/doc/api/os.md @@ -371,6 +371,9 @@ priority classes, `priority` is mapped to one of six priority constants in mapping may cause the return value to be slightly different on Windows. To avoid confusion, it is recommended to set `priority` to one of the priority constants. +On Windows setting priority to `PRIORITY_HIGHEST` requires elevated user, +otherwise the set priority will be silently reduced to `PRIORITY_HIGH`. + ## os.tmpdir()