From 5d0436fbeafeb0498d82430d38650b65a5c4220d Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Tue, 31 Oct 2017 20:56:44 -0400 Subject: [PATCH 1/6] doc: update license to include node-inspect This also updates the license builder. PR-URL: https://github.com/nodejs/node/pull/16659 Reviewed-By: Anatoli Papirovski Reviewed-By: Richard Lau Reviewed-By: Gireesh Punathil Reviewed-By: Joyee Cheung Reviewed-By: Jeremiah Senkpiel Reviewed-By: Gibson Fahnestock Reviewed-By: Yuta Hiroto Reviewed-By: James M Snell Reviewed-By: Michael Dawson --- LICENSE | 23 +++++++++++++++++++++++ tools/license-builder.sh | 3 +++ 2 files changed, 26 insertions(+) diff --git a/LICENSE b/LICENSE index a34f642b3cb..28723292ba5 100644 --- a/LICENSE +++ b/LICENSE @@ -1145,3 +1145,26 @@ The externally maintained libraries used by Node.js are: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ + +- node-inspect, located at deps/node-inspect, is licensed as follows: + """ + Copyright Node.js contributors. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + """ diff --git a/tools/license-builder.sh b/tools/license-builder.sh index 6abeb76b1df..39b0a15b2b2 100755 --- a/tools/license-builder.sh +++ b/tools/license-builder.sh @@ -85,4 +85,7 @@ addlicense "nghttp2" "deps/nghttp2" "$(cat ${rootdir}/deps/nghttp2/COPYING)" # remark-cli addlicense "remark-cli" "tools/remark-cli" "$(cat ${rootdir}/tools/remark-cli/LICENSE)" +# node-inspect +addlicense "node-inspect" "deps/node-inspect" "$(cat ${rootdir}/deps/node-inspect/LICENSE)" + mv $tmplicense $licensefile From a5f3b3a6dab18e32ee5e7d0d79a63cec0d5d5cc5 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 3 Nov 2017 20:13:18 +0100 Subject: [PATCH 2/6] src: add method to compute storage in WriteWrap `WriteWrap` instances may contain extra storage space. `self_size()` returns the size of the *entire* struct, member fields as well as storage space, so it is not an accurate measure for the storage space available. Add a method `ExtraSize()` (like the existing `Extra()` for accessing the storage memory) that yields the wanted value, and use it in the HTTP2 impl to fix a crash. PR-URL: https://github.com/nodejs/node/pull/16727 Refs: https://github.com/nodejs/node/pull/16669 Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- src/node_http2_core-inl.h | 4 ++-- src/stream_base-inl.h | 4 ++++ src/stream_base.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/node_http2_core-inl.h b/src/node_http2_core-inl.h index eda8a93ee79..c78e5d673f4 100644 --- a/src/node_http2_core-inl.h +++ b/src/node_http2_core-inl.h @@ -503,7 +503,7 @@ inline void Nghttp2Session::SendPendingData() { while ((srcLength = nghttp2_session_mem_send(session_, &src)) > 0) { if (req == nullptr) { req = AllocateSend(); - destRemaining = req->self_size(); + destRemaining = req->ExtraSize(); dest = req->Extra(); } DEBUG_HTTP2("Nghttp2Session %s: nghttp2 has %d bytes to send\n", @@ -525,7 +525,7 @@ inline void Nghttp2Session::SendPendingData() { srcRemaining -= destRemaining; srcOffset += destRemaining; req = AllocateSend(); - destRemaining = req->self_size(); + destRemaining = req->ExtraSize(); dest = req->Extra(); } diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 667c0a9ffbd..e1e50802f2a 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -160,6 +160,10 @@ char* WriteWrap::Extra(size_t offset) { offset; } +size_t WriteWrap::ExtraSize() const { + return storage_size_ - ROUND_UP(sizeof(*this), kAlignSize); +} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/stream_base.h b/src/stream_base.h index 9833a82636d..20cb0155c9d 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -77,6 +77,7 @@ class WriteWrap: public ReqWrap, size_t extra = 0); inline void Dispose(); inline char* Extra(size_t offset = 0); + inline size_t ExtraSize() const; inline StreamBase* wrap() const { return wrap_; } From 92f86632d534125aa7a86fe11a34d7b794b22991 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Fri, 3 Nov 2017 12:18:52 +0100 Subject: [PATCH 3/6] deps: cherry-pick e7f4e9e from upstream libuv Original commit message: tty, win: get SetWinEventHook pointer at startup SetWinEventHook is not available on some Windows versions. Fixes: https://github.com/nodejs/node/issues/16603 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig PR-URL: https://github.com/nodejs/node/pull/16724 Fixes: https://github.com/https://github.com/nodejs/node/issues/16603 Reviewed-By: Colin Ihrig Reviewed-By: Ben Noordhuis Reviewed-By: Refael Ackermann Reviewed-By: Gibson Fahnestock --- deps/uv/src/win/tty.c | 17 ++++++++++------- deps/uv/src/win/winapi.c | 10 ++++++++++ deps/uv/src/win/winapi.h | 22 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 4cd1c72129c..05a11e88305 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -2285,13 +2285,16 @@ static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) { uv__tty_console_width = sb_info.dwSize.X; uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; - if (!SetWinEventHook(EVENT_CONSOLE_LAYOUT, - EVENT_CONSOLE_LAYOUT, - NULL, - uv__tty_console_resize_event, - 0, - 0, - WINEVENT_OUTOFCONTEXT)) + if (pSetWinEventHook == NULL) + return 0; + + if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT, + EVENT_CONSOLE_LAYOUT, + NULL, + uv__tty_console_resize_event, + 0, + 0, + WINEVENT_OUTOFCONTEXT)) return 0; while (GetMessage(&msg, NULL, 0, 0)) { diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index aa5d719fbea..4ccdf0a5f97 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -52,11 +52,15 @@ sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; /* Powrprof.dll function pointer */ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; +/* User32.dll function pointer */ +sSetWinEventHook pSetWinEventHook; + void uv_winapi_init(void) { HMODULE ntdll_module; HMODULE kernel32_module; HMODULE powrprof_module; + HMODULE user32_module; ntdll_module = GetModuleHandleA("ntdll.dll"); if (ntdll_module == NULL) { @@ -156,4 +160,10 @@ void uv_winapi_init(void) { GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification"); } + user32_module = LoadLibraryA("user32.dll"); + if (user32_module != NULL) { + pSetWinEventHook = (sSetWinEventHook) + GetProcAddress(user32_module, "SetWinEventHook"); + } + } diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 6c699bfe170..cc54b79b08d 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4725,6 +4725,25 @@ typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification) HANDLE Recipient, _PHPOWERNOTIFY RegistrationHandle); +/* from Winuser.h */ +typedef VOID (CALLBACK* WINEVENTPROC) + (HWINEVENTHOOK hWinEventHook, + DWORD event, + HWND hwnd, + LONG idObject, + LONG idChild, + DWORD idEventThread, + DWORD dwmsEventTime); + +typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook) + (UINT eventMin, + UINT eventMax, + HMODULE hmodWinEventProc, + WINEVENTPROC lpfnWinEventProc, + DWORD idProcess, + DWORD idThread, + UINT dwflags); + /* Ntdll function pointers */ extern sRtlNtStatusToDosError pRtlNtStatusToDosError; @@ -4753,4 +4772,7 @@ extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; /* Powrprof.dll function pointer */ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; +/* User32.dll function pointer */ +extern sSetWinEventHook pSetWinEventHook; + #endif /* UV_WIN_WINAPI_H_ */ From 04ffa36e2307ede5a5d94afc3cca659b70fb4011 Mon Sep 17 00:00:00 2001 From: Weijia Wang <381152119@qq.com> Date: Tue, 31 Oct 2017 23:51:59 +0800 Subject: [PATCH 4/6] tools: add fixer for no-let-in-for-declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/16642 Refs: https://github.com/nodejs/node/issues/16636 Reviewed-By: Anatoli Papirovski Reviewed-By: Gireesh Punathil Reviewed-By: Tobias Nießen --- .../test-eslint-no-let-in-for-declaration.js | 3 +++ tools/eslint-rules/no-let-in-for-declaration.js | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-eslint-no-let-in-for-declaration.js b/test/parallel/test-eslint-no-let-in-for-declaration.js index b6b7c357455..c3c1e17a729 100644 --- a/test/parallel/test-eslint-no-let-in-for-declaration.js +++ b/test/parallel/test-eslint-no-let-in-for-declaration.js @@ -24,14 +24,17 @@ ruleTester.run('no-let-in-for-declaration', rule, { invalid: [ { code: 'for (let foo = 1;;);', + output: 'for (var foo = 1;;);', errors: [{ message }] }, { code: 'for (let foo in bar);', + output: 'for (var foo in bar);', errors: [{ message }] }, { code: 'for (let foo of bar);', + output: 'for (var foo of bar);', errors: [{ message }] } ] diff --git a/tools/eslint-rules/no-let-in-for-declaration.js b/tools/eslint-rules/no-let-in-for-declaration.js index 8b1a6783e07..34ad2d5761f 100644 --- a/tools/eslint-rules/no-let-in-for-declaration.js +++ b/tools/eslint-rules/no-let-in-for-declaration.js @@ -14,7 +14,7 @@ module.exports = { create(context) { - + const sourceCode = context.getSourceCode(); const msg = 'Use of `let` as the loop variable in a for-loop is ' + 'not recommended. Please use `var` instead.'; @@ -23,7 +23,12 @@ module.exports = { */ function testForLoop(node) { if (node.init && node.init.kind === 'let') { - context.report(node.init, msg); + context.report({ + node: node.init, + message: msg, + fix: (fixer) => + fixer.replaceText(sourceCode.getFirstToken(node.init), 'var') + }); } } @@ -33,7 +38,12 @@ module.exports = { */ function testForInOfLoop(node) { if (node.left && node.left.kind === 'let') { - context.report(node.left, msg); + context.report({ + node: node.left, + message: msg, + fix: (fixer) => + fixer.replaceText(sourceCode.getFirstToken(node.left), 'var') + }); } } From 7eb5ee3ca8afdb3ca22d329195ae1f9dc4313081 Mon Sep 17 00:00:00 2001 From: Yosuke Furukawa Date: Wed, 1 Nov 2017 01:19:36 +0900 Subject: [PATCH 5/6] http, http2: add 103 Early Hints status code PR-URL: https://github.com/nodejs/node/pull/16644 Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig Reviewed-By: Anna Henningsen --- lib/_http_server.js | 1 + src/node_http2.h | 1 + test/parallel/test-http2-binding.js | 1 + 3 files changed, 3 insertions(+) diff --git a/lib/_http_server.js b/lib/_http_server.js index bfbab222264..04161ac024b 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -44,6 +44,7 @@ const STATUS_CODES = { 100: 'Continue', 101: 'Switching Protocols', 102: 'Processing', // RFC 2518, obsoleted by RFC 4918 + 103: 'Early Hints', 200: 'OK', 201: 'Created', 202: 'Accepted', diff --git a/src/node_http2.h b/src/node_http2.h index 39ed27249d3..a19e032ccef 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -158,6 +158,7 @@ HTTP_KNOWN_HEADER_MAX V(CONTINUE, 100) \ V(SWITCHING_PROTOCOLS, 101) \ V(PROCESSING, 102) \ + V(EARLY_HINTS, 103) \ V(OK, 200) \ V(CREATED, 201) \ V(ACCEPTED, 202) \ diff --git a/test/parallel/test-http2-binding.js b/test/parallel/test-http2-binding.js index 5b7a74a0324..8935e569f50 100644 --- a/test/parallel/test-http2-binding.js +++ b/test/parallel/test-http2-binding.js @@ -31,6 +31,7 @@ const expectedStatusCodes = { HTTP_STATUS_CONTINUE: 100, HTTP_STATUS_SWITCHING_PROTOCOLS: 101, HTTP_STATUS_PROCESSING: 102, + HTTP_STATUS_EARLY_HINTS: 103, HTTP_STATUS_OK: 200, HTTP_STATUS_CREATED: 201, HTTP_STATUS_ACCEPTED: 202, From 291ff72f859df3c4c3849021419f37cd542840a6 Mon Sep 17 00:00:00 2001 From: "Mark S. Everitt" Date: Tue, 31 Oct 2017 20:03:28 +0000 Subject: [PATCH 6/6] tls: accept array of protocols in TLSSocket Brings the ALPNProtocols & NPNProtocols options of TLSSocket in line with the documentation. i.e. an array of strings for protocols may be used, not only a buffer. PR-URL: https://github.com/nodejs/node/pull/16655 Fixes: https://github.com/node/issues/16643 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Anatoli Papirovski --- lib/_tls_wrap.js | 22 +++--- ...et-constructor-alpn-npn-options-parsing.js | 78 +++++++++++++++++++ 2 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 test/parallel/test-tls-socket-constructor-alpn-npn-options-parsing.js diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index d7e349b239c..1bd76a7f97c 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -280,11 +280,15 @@ function initRead(tls, wrapped) { * Provides a wrap of socket stream to do encrypted communication. */ -function TLSSocket(socket, options) { - if (options === undefined) - this._tlsOptions = {}; - else - this._tlsOptions = options; +function TLSSocket(socket, opts) { + const tlsOptions = Object.assign({}, opts); + + if (tlsOptions.NPNProtocols) + tls.convertNPNProtocols(tlsOptions.NPNProtocols, tlsOptions); + if (tlsOptions.ALPNProtocols) + tls.convertALPNProtocols(tlsOptions.ALPNProtocols, tlsOptions); + + this._tlsOptions = tlsOptions; this._secureEstablished = false; this._securePending = false; this._newSessionPending = false; @@ -1099,11 +1103,7 @@ exports.connect = function(...args /* [port,] [host,] [options,] [cb] */) { 'options.minDHSize is not a positive number: ' + options.minDHSize); - const NPN = {}; - const ALPN = {}; const context = options.secureContext || tls.createSecureContext(options); - tls.convertNPNProtocols(options.NPNProtocols, NPN); - tls.convertALPNProtocols(options.ALPNProtocols, ALPN); var socket = new TLSSocket(options.socket, { pipe: !!options.path, @@ -1112,8 +1112,8 @@ exports.connect = function(...args /* [port,] [host,] [options,] [cb] */) { requestCert: true, rejectUnauthorized: options.rejectUnauthorized !== false, session: options.session, - NPNProtocols: NPN.NPNProtocols, - ALPNProtocols: ALPN.ALPNProtocols, + NPNProtocols: options.NPNProtocols, + ALPNProtocols: options.ALPNProtocols, requestOCSP: options.requestOCSP }); diff --git a/test/parallel/test-tls-socket-constructor-alpn-npn-options-parsing.js b/test/parallel/test-tls-socket-constructor-alpn-npn-options-parsing.js new file mode 100644 index 00000000000..fec06c94eec --- /dev/null +++ b/test/parallel/test-tls-socket-constructor-alpn-npn-options-parsing.js @@ -0,0 +1,78 @@ +'use strict'; + +// Test that TLSSocket can take arrays of strings for ALPNProtocols and +// NPNProtocols. + +const common = require('../common'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const tls = require('tls'); + +new tls.TLSSocket(null, { + ALPNProtocols: ['http/1.1'], + NPNProtocols: ['http/1.1'] +}); + +if (!process.features.tls_npn) + common.skip('node compiled without NPN feature of OpenSSL'); + +if (!process.features.tls_alpn) + common.skip('node compiled without ALPN feature of OpenSSL'); + +const assert = require('assert'); +const net = require('net'); +const fixtures = require('../common/fixtures'); + +const key = fixtures.readKey('agent1-key.pem'); +const cert = fixtures.readKey('agent1-cert.pem'); + +const protocols = []; + +const server = net.createServer(common.mustCall((s) => { + const tlsSocket = new tls.TLSSocket(s, { + isServer: true, + server, + key, + cert, + ALPNProtocols: ['http/1.1'], + NPNProtocols: ['http/1.1'] + }); + + tlsSocket.on('secure', common.mustCall(() => { + protocols.push({ + alpnProtocol: tlsSocket.alpnProtocol, + npnProtocol: tlsSocket.npnProtocol + }); + tlsSocket.end(); + })); +}, 2)); + +server.listen(0, common.mustCall(() => { + const alpnOpts = { + port: server.address().port, + rejectUnauthorized: false, + ALPNProtocols: ['h2', 'http/1.1'] + }; + const npnOpts = { + port: server.address().port, + rejectUnauthorized: false, + NPNProtocols: ['h2', 'http/1.1'] + }; + + tls.connect(alpnOpts, function() { + this.end(); + + tls.connect(npnOpts, function() { + this.end(); + + server.close(); + + assert.deepStrictEqual(protocols, [ + { alpnProtocol: 'http/1.1', npnProtocol: false }, + { alpnProtocol: false, npnProtocol: 'http/1.1' } + ]); + }); + }); +}));