Browse Source

deps: add node-inspect 1.10.2

Squashed from:

- deps: Add node-inspect 1.10.1

This adds a reimplementation of the old CLI debugger (`node debug`)
against the new debugger protocol (`node --inspect`). This is necessary
because the old protocol won't be supported in future versions of V8.

- deps: Update node-inspect to 1.10.2

Starting with 1.10.2 the test suite should pass consistently on
windows.

- deps: Update to node-inspect 1.10.4

PR-URL: https://github.com/nodejs/node/pull/10187
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
v6
Jan Krems 8 years ago
committed by Anna Henningsen
parent
commit
8c9762e150
No known key found for this signature in database GPG Key ID: D8B9F5AEAE84E4CF
  1. 11
      deps/node-inspect/.editorconfig
  2. 147
      deps/node-inspect/.eslintrc
  3. 4
      deps/node-inspect/.gitignore
  4. 1
      deps/node-inspect/.npmrc
  5. 13
      deps/node-inspect/.travis.yml
  6. 212
      deps/node-inspect/CHANGELOG.md
  7. 183
      deps/node-inspect/CONTRIBUTING.md
  8. 5
      deps/node-inspect/GOVERNANCE.md
  9. 19
      deps/node-inspect/LICENSE
  10. 29
      deps/node-inspect/README.md
  11. 13
      deps/node-inspect/appveyor.yml
  12. 2
      deps/node-inspect/cli.js
  13. 6
      deps/node-inspect/examples/alive.js
  14. 31
      deps/node-inspect/examples/backtrace.js
  15. 16
      deps/node-inspect/examples/break.js
  16. 5
      deps/node-inspect/examples/cjs/index.js
  17. 4
      deps/node-inspect/examples/cjs/other.js
  18. 0
      deps/node-inspect/examples/empty.js
  19. 11
      deps/node-inspect/examples/exceptions.js
  20. 4
      deps/node-inspect/examples/three-lines.js
  21. 283
      deps/node-inspect/lib/_inspect.js
  22. 24
      deps/node-inspect/lib/cli.js
  23. 363
      deps/node-inspect/lib/internal/inspect_client.js
  24. 1057
      deps/node-inspect/lib/internal/inspect_repl.js
  25. 45
      deps/node-inspect/package.json
  26. 30
      deps/node-inspect/test/cli/backtrace.test.js
  27. 195
      deps/node-inspect/test/cli/break.test.js
  28. 63
      deps/node-inspect/test/cli/exceptions.test.js
  29. 77
      deps/node-inspect/test/cli/exec.test.js
  30. 22
      deps/node-inspect/test/cli/help.test.js
  31. 25
      deps/node-inspect/test/cli/invalid-args.test.js
  32. 110
      deps/node-inspect/test/cli/launch.test.js
  33. 31
      deps/node-inspect/test/cli/low-level.test.js
  34. 56
      deps/node-inspect/test/cli/preserve-breaks.test.js
  35. 32
      deps/node-inspect/test/cli/profile.test.js
  36. 43
      deps/node-inspect/test/cli/scripts.test.js
  37. 136
      deps/node-inspect/test/cli/start-cli.js
  38. 42
      deps/node-inspect/test/cli/watchers.test.js
  39. 9
      deps/node-inspect/test/node-inspect.test.js
  40. 76
      deps/node-inspect/tools/eslint-rules/align-function-arguments.js
  41. 68
      deps/node-inspect/tools/eslint-rules/align-multiline-assignment.js
  42. 30
      deps/node-inspect/tools/eslint-rules/assert-fail-single-argument.js
  43. 25
      deps/node-inspect/tools/eslint-rules/buffer-constructor.js
  44. 31
      deps/node-inspect/tools/eslint-rules/new-with-error.js
  45. 46
      deps/node-inspect/tools/eslint-rules/no-let-in-for-declaration.js
  46. 39
      deps/node-inspect/tools/eslint-rules/prefer-assert-methods.js
  47. 19
      deps/node-inspect/tools/eslint-rules/require-buffer.js
  48. 99
      deps/node-inspect/tools/eslint-rules/required-modules.js

11
deps/node-inspect/.editorconfig

@ -0,0 +1,11 @@
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

147
deps/node-inspect/.eslintrc

@ -0,0 +1,147 @@
root: true
env:
node: true
es6: true
parserOptions:
ecmaVersion: 2016
rules:
# Possible Errors
# http://eslint.org/docs/rules/#possible-errors
comma-dangle: [2, only-multiline]
no-control-regex: 2
no-debugger: 2
no-dupe-args: 2
no-dupe-keys: 2
no-duplicate-case: 2
no-empty-character-class: 2
no-ex-assign: 2
no-extra-boolean-cast: 2
no-extra-parens: [2, functions]
no-extra-semi: 2
no-func-assign: 2
no-invalid-regexp: 2
no-irregular-whitespace: 2
no-obj-calls: 2
no-proto: 2
no-template-curly-in-string: 2
no-unexpected-multiline: 2
no-unreachable: 2
no-unsafe-negation: 2
use-isnan: 2
valid-typeof: 2
# Best Practices
# http://eslint.org/docs/rules/#best-practices
dot-location: [2, property]
no-fallthrough: 2
no-global-assign: 2
no-multi-spaces: 2
no-octal: 2
no-redeclare: 2
no-self-assign: 2
no-unused-labels: 2
no-useless-call: 2
no-useless-escape: 2
no-void: 2
no-with: 2
# Strict Mode
# http://eslint.org/docs/rules/#strict-mode
strict: [2, global]
# Variables
# http://eslint.org/docs/rules/#variables
no-delete-var: 2
no-undef: 2
no-unused-vars: [2, {args: none}]
# Node.js and CommonJS
# http://eslint.org/docs/rules/#nodejs-and-commonjs
no-mixed-requires: 2
no-new-require: 2
no-path-concat: 2
no-restricted-modules: [2, sys, _linklist]
no-restricted-properties: [2, {
object: assert,
property: deepEqual,
message: Please use assert.deepStrictEqual().
}, {
property: __defineGetter__,
message: __defineGetter__ is deprecated.
}, {
property: __defineSetter__,
message: __defineSetter__ is deprecated.
}]
# Stylistic Issues
# http://eslint.org/docs/rules/#stylistic-issues
brace-style: [2, 1tbs, {allowSingleLine: true}]
comma-spacing: 2
comma-style: 2
computed-property-spacing: 2
eol-last: 2
func-call-spacing: 2
func-name-matching: 2
indent: [2, 2, {SwitchCase: 1, MemberExpression: 1}]
key-spacing: [2, {mode: minimum}]
keyword-spacing: 2
linebreak-style: [2, unix]
max-len: [2, 80, 2]
new-parens: 2
no-mixed-spaces-and-tabs: 2
no-multiple-empty-lines: [2, {max: 2, maxEOF: 0, maxBOF: 0}]
no-tabs: 2
no-trailing-spaces: 2
quotes: [2, single, avoid-escape]
semi: 2
semi-spacing: 2
space-before-blocks: [2, always]
space-before-function-paren: [2, never]
space-in-parens: [2, never]
space-infix-ops: 2
space-unary-ops: 2
# ECMAScript 6
# http://eslint.org/docs/rules/#ecmascript-6
arrow-parens: [2, always]
arrow-spacing: [2, {before: true, after: true}]
constructor-super: 2
no-class-assign: 2
no-confusing-arrow: 2
no-const-assign: 2
no-dupe-class-members: 2
no-new-symbol: 2
no-this-before-super: 2
prefer-const: [2, {ignoreReadBeforeAssign: true}]
rest-spread-spacing: 2
template-curly-spacing: 2
# Custom rules in tools/eslint-rules
align-function-arguments: 2
align-multiline-assignment: 2
assert-fail-single-argument: 2
new-with-error: [2, Error, RangeError, TypeError, SyntaxError, ReferenceError]
# Global scoped method and vars
globals:
COUNTER_HTTP_CLIENT_REQUEST: false
COUNTER_HTTP_CLIENT_RESPONSE: false
COUNTER_HTTP_SERVER_REQUEST: false
COUNTER_HTTP_SERVER_RESPONSE: false
COUNTER_NET_SERVER_CONNECTION: false
COUNTER_NET_SERVER_CONNECTION_CLOSE: false
DTRACE_HTTP_CLIENT_REQUEST: false
DTRACE_HTTP_CLIENT_RESPONSE: false
DTRACE_HTTP_SERVER_REQUEST: false
DTRACE_HTTP_SERVER_RESPONSE: false
DTRACE_NET_SERVER_CONNECTION: false
DTRACE_NET_STREAM_END: false
LTTNG_HTTP_CLIENT_REQUEST: false
LTTNG_HTTP_CLIENT_RESPONSE: false
LTTNG_HTTP_SERVER_REQUEST: false
LTTNG_HTTP_SERVER_RESPONSE: false
LTTNG_NET_SERVER_CONNECTION: false
LTTNG_NET_STREAM_END: false

4
deps/node-inspect/.gitignore

@ -0,0 +1,4 @@
node_modules/
npm-debug.log
/tmp
/.vs

1
deps/node-inspect/.npmrc

@ -0,0 +1 @@
registry=https://registry.npmjs.org

13
deps/node-inspect/.travis.yml

@ -0,0 +1,13 @@
language: node_js
node_js:
- '6.8'
before_deploy:
- git config --global user.email "jan.krems@gmail.com"
- git config --global user.name "Jan Krems"
deploy:
provider: script
script: ./node_modules/.bin/nlm release
skip_cleanup: true
'on':
branch: master
node: '6.8'

212
deps/node-inspect/CHANGELOG.md

@ -0,0 +1,212 @@
### 1.10.4
* [`1c31bf7`](https://github.com/buggerjs/node-inspect/commit/1c31bf7d1b3ea1b424ae0662526596670cb506c9) **chore:** Support embedded mode
### 1.10.3
* [`7b20379`](https://github.com/buggerjs/node-inspect/commit/7b20379069af692a9038a31a4465f72db9eb532f) **chore:** Mark .eslintrc as root
### 1.10.2
* Run tests on windows - **[@jkrems](https://github.com/jkrems)** [#16](https://github.com/buggerjs/node-inspect/pull/16)
- [`5a57f98`](https://github.com/buggerjs/node-inspect/commit/5a57f9865e02eef0763c2a7f26236c34a632ccdd) **chore:** Run tests on windows
- [`0a04b50`](https://github.com/buggerjs/node-inspect/commit/0a04b50cc8b4dc6ce868927c635c479d75ce71f4) **chore:** Bump nlm to get rid of postinstall
- [`4a8b27c`](https://github.com/buggerjs/node-inspect/commit/4a8b27cea814a37895effd2a0c1b85dbfee3a7f4) **test:** Remove unix path assumptions
### 1.10.1
* [`4ba3c72`](https://github.com/buggerjs/node-inspect/commit/4ba3c72270fae9a71343ddca11aa27980678a67c) **refactor:** Undo weird bundling into one file
### 1.10.0
* [`3e1a66a`](https://github.com/buggerjs/node-inspect/commit/3e1a66a489bef19beaa5f859e99e027274ff43cb) **feat:** Support CPU & heap profiles
### 1.9.3
* Move back to single file - **[@jkrems](https://github.com/jkrems)** [#15](https://github.com/buggerjs/node-inspect/pull/15)
- [`9877660`](https://github.com/buggerjs/node-inspect/commit/9877660a73ff0ec0885ad7f939ba62020a46b4b6) **refactor:** Wrap client in IIFE
- [`7795c53`](https://github.com/buggerjs/node-inspect/commit/7795c533f0605eb128db610a5874b27e555251ef) **refactor:** Move more code in createRepl scope
- [`be34a39`](https://github.com/buggerjs/node-inspect/commit/be34a398e823612bdf5ac90bad5222af27035a00) **refactor:** Move back to single file
- [`ab45b62`](https://github.com/buggerjs/node-inspect/commit/ab45b6273dc0d3a49d3cf46a80cb48ab79d1caf8) **refactor:** Remove single-use functions
- [`37a711e`](https://github.com/buggerjs/node-inspect/commit/37a711ed5334c06ed4d85f995e567a9f176a68d5) **style:** Stop using `new Buffer`
- [`d669dc5`](https://github.com/buggerjs/node-inspect/commit/d669dc593f5ad5ca7a48f19f0905ef66ec0e540d) **chore:** Switch to node eslint rules
- [`15e7917`](https://github.com/buggerjs/node-inspect/commit/15e79177918d96dcffd2384715faf0308e97a26c) **style:** Use var in classical for loops
### 1.9.2
* [`c9dc4be`](https://github.com/buggerjs/node-inspect/commit/c9dc4beb08236e33d64f19417682cf5b3f5aeed6) **doc:** Link directly to GOVERNANCE file
### 1.9.1
* Handle big ws frames correctly - **[@jkrems](https://github.com/jkrems)** [#14](https://github.com/buggerjs/node-inspect/pull/14)
- [`f80100e`](https://github.com/buggerjs/node-inspect/commit/f80100e932710d232d074b239cbf8fefa564c789) **fix:** Handle big ws frames correctly - see: [#10](https://github.com/buggerjs/node-inspect/issues/10)
### 1.9.0
* Support for low-level agent access - **[@jkrems](https://github.com/jkrems)** [#13](https://github.com/buggerjs/node-inspect/pull/13)
- [`90ed431`](https://github.com/buggerjs/node-inspect/commit/90ed4310c62d130637c12f8ecdb752075c43ac36) **feat:** Support for low-level agent access
### 1.8.4
* Use proper path for websocket - **[@jkrems](https://github.com/jkrems)** [#12](https://github.com/buggerjs/node-inspect/pull/12)
- [`3405225`](https://github.com/buggerjs/node-inspect/commit/3405225979dfc2058bcc6d1b90f41c060dbd1f92) **fix:** Use proper path for websocket - see: [#11](https://github.com/buggerjs/node-inspect/issues/11)
### 1.8.3
* [`6f9883d`](https://github.com/buggerjs/node-inspect/commit/6f9883d4b29419831133988981b83e891b19739a) **fix:** Breakpoints & scripts work when not paused
* [`ecb1362`](https://github.com/buggerjs/node-inspect/commit/ecb1362c842e6ed5bc28c091a32bfd540742db75) **chore:** Pin node to 6.8
### 1.8.2
* [`4219a98`](https://github.com/buggerjs/node-inspect/commit/4219a98d6514f1068feabce2945c21a0d5ba6561) **refactor:** Decouple source snippet from repl
### 1.8.1
* [`95402ee`](https://github.com/buggerjs/node-inspect/commit/95402ee5dff04057f074677d39db2f61ec74c151) **refactor:** Move `list` into CallFrame
### 1.8.0
* [`d0e6499`](https://github.com/buggerjs/node-inspect/commit/d0e6499084f5d656ef0c5fd470d3ab21f2e9a6b4) **feat:** `exec .scope`
### 1.7.0
* `breakOn{Exception,Uncaught,None}` - **[@jkrems](https://github.com/jkrems)** [#8](https://github.com/buggerjs/node-inspect/pull/8)
- [`fa8c4c7`](https://github.com/buggerjs/node-inspect/commit/fa8c4c7d7bb6972733c92da4d04fdd62c02b0e3b) **feat:** `breakOn{Exception,Uncaught,None}` - see: [#6](https://github.com/buggerjs/node-inspect/issues/6)
### 1.6.0
* Add `help` command - **[@jkrems](https://github.com/jkrems)** [#7](https://github.com/buggerjs/node-inspect/pull/7)
- [`09b37a0`](https://github.com/buggerjs/node-inspect/commit/09b37a02e04e16a38ce27f69538d3b098548b47c) **feat:** Add `help` command - see: [#5](https://github.com/buggerjs/node-inspect/issues/5)
### 1.5.0
* [`7e0fd99`](https://github.com/buggerjs/node-inspect/commit/7e0fd99fcfc65d8b647a2259df78f4cabf1d3d63) **feat:** Add `r` shortcut for `run`
### 1.4.1
* [`484d098`](https://github.com/buggerjs/node-inspect/commit/484d0983f06d6ff9639ab5197ba0a58313f532df) **chore:** Remove old implementation
### 1.4.0
* Properly tested implementation - **[@jkrems](https://github.com/jkrems)** [#4](https://github.com/buggerjs/node-inspect/pull/4)
- [`ba060d3`](https://github.com/buggerjs/node-inspect/commit/ba060d3ef65ae84df2a3a9b9f16d563f3c4b29be) **feat:** Error handling w/o args
- [`b39b3bc`](https://github.com/buggerjs/node-inspect/commit/b39b3bc07c13adc48fc8bb720889285c51e62548) **feat:** Launch child
- [`481693f`](https://github.com/buggerjs/node-inspect/commit/481693f676ee099b7787cd2426b980858e973602) **feat:** Connect debug client
- [`3bba0f2`](https://github.com/buggerjs/node-inspect/commit/3bba0f2416b2e3b4e6010de675003fcc328b16e8) **chore:** Disable lint for inactive code
- [`cc7bdfc`](https://github.com/buggerjs/node-inspect/commit/cc7bdfcf7f21ef5cd5c32c7800407238b0d4f100) **feat:** Properly fail with invalid host:port
- [`73f34f9`](https://github.com/buggerjs/node-inspect/commit/73f34f902634e9778597e129f46895aa8b643d72) **refactor:** Remove unused field
- [`6a23e0c`](https://github.com/buggerjs/node-inspect/commit/6a23e0cf3179f43ca6fc5a0fa2b1dd18ebc044b5) **refactor:** Better debug output & support node 6.6
- [`63b0f9b`](https://github.com/buggerjs/node-inspect/commit/63b0f9b6ef8bd9af0f7cb14a5938a45838731fc9) **test:** Add timeout to waitFor(pattern)
- [`cfa197b`](https://github.com/buggerjs/node-inspect/commit/cfa197bf8325a1a4ca1b296f8d6971d368bfbfbb) **refactor:** Move REPL setup into own file
- [`3f46c2c`](https://github.com/buggerjs/node-inspect/commit/3f46c2c43f836e1135b66871087aa74969f6b330) **feat:** Working repl eval
- [`6911eb1`](https://github.com/buggerjs/node-inspect/commit/6911eb1a00b964bc5683506d433fa4f665f5a82c) **feat:** Enter repeats last command
- [`7d20b7d`](https://github.com/buggerjs/node-inspect/commit/7d20b7deadf1b251ea8cf2cc9167c175624932c4) **chore:** Add missing license header
- [`23c62f8`](https://github.com/buggerjs/node-inspect/commit/23c62f8375ca7c8b71d032047e728dace02f4efa) **feat:** Print break context
- [`5dbc83d`](https://github.com/buggerjs/node-inspect/commit/5dbc83df31171f9c38a974c99340bde26f2e24ec) **feat:** Stepping and breakpoints
- [`8deb8cc`](https://github.com/buggerjs/node-inspect/commit/8deb8cc36b9fca432ab8df63a82e9de7ab5adaf0) **feat:** list for printing source
- [`1ed2ec9`](https://github.com/buggerjs/node-inspect/commit/1ed2ec9937070652be611dbb6b11dfb42cb840f8) **chore:** Disable verbose output on CI
- [`625a435`](https://github.com/buggerjs/node-inspect/commit/625a435925dd8fd980bed2dc9e3fd73dd27df4ef) **fix:** Gracefully handle delayed scriptParsed
- [`8823c60`](https://github.com/buggerjs/node-inspect/commit/8823c60d347600b2313cfdd8cb5e96fe02419a8a) **chore:** Run all the tests
- [`00506f7`](https://github.com/buggerjs/node-inspect/commit/00506f763928cc440505a81030167a11b9a84e00) **feat:** backtrace/bt
- [`e1ee02d`](https://github.com/buggerjs/node-inspect/commit/e1ee02d5cc389916489d387d07d5dd161230427a) **refactor:** Leverage util.inspect.custom
- [`5dcc319`](https://github.com/buggerjs/node-inspect/commit/5dcc31922d40f56c7435319d1538390a442e8e4b) **feat:** scripts and scripts(true)
- [`085cd5a`](https://github.com/buggerjs/node-inspect/commit/085cd5a76a961edfcaa342fff5eb09bf2f9c8983) **refactor:** Consistent import style
- [`1c60f91`](https://github.com/buggerjs/node-inspect/commit/1c60f91f233848c05d865617dc7f5aacb36270b6) **feat:** Set breakpoint before file is loaded
- [`bc82ecc`](https://github.com/buggerjs/node-inspect/commit/bc82eccb2a1a7c0f5332371254f6584e748216aa) **feat:** breakpoints to list breakpoints
- [`7f48c95`](https://github.com/buggerjs/node-inspect/commit/7f48c9510696ec400d51afaca8d23a9c292640f8) **feat:** watchers & exec
- [`0f8cd13`](https://github.com/buggerjs/node-inspect/commit/0f8cd13a092e5dbeb395ff04cbe2ed97cb986423) **feat:** clearBreakpoint
- [`0d31560`](https://github.com/buggerjs/node-inspect/commit/0d315603bdcb9f4da42fab24dc569c325151269e) **feat:** version to print v8 version
- [`df6b89d`](https://github.com/buggerjs/node-inspect/commit/df6b89df580a9afcb3b8883b0e4224cbcebb384f) **feat:** Paused & global exec
- [`9e97d73`](https://github.com/buggerjs/node-inspect/commit/9e97d73073ceffd70974d45887c84fadb9159d5c) **feat:** repl to enter exec mode
- [`9ee9f90`](https://github.com/buggerjs/node-inspect/commit/9ee9f903d6202f54ed2b3b3559da4006b65d39b5) **feat:** run & restart
* [`3a752aa`](https://github.com/buggerjs/node-inspect/commit/3a752aaa773968bfe16c5f543bd739feed598bea) **feat:** kill
* [`a67e470`](https://github.com/buggerjs/node-inspect/commit/a67e47018b20d46aeeaa7abd27eb8e7770fd0b8f) **feat:** Restore breakpoints on restart
### 1.3.3
* [`eb7a54c`](https://github.com/buggerjs/node-inspect/commit/eb7a54c6fa731ed3276072c72034046fc5ffbac6) **chore:** Switch to tap for tests
### 1.3.2
* Add notes about governance - **[@jkrems](https://github.com/jkrems)** [#3](https://github.com/buggerjs/node-inspect/pull/3)
- [`e94089d`](https://github.com/buggerjs/node-inspect/commit/e94089d93689cacf5c953e94563463d1e174452d) **chore:** Add notes about governance
### 1.3.1
* [`8767137`](https://github.com/buggerjs/node-inspect/commit/8767137c53a2f6b1d36970074ea95be9871e50e3) **style:** Remove rogue console.log
### 1.3.0
* [`3ac6232`](https://github.com/buggerjs/node-inspect/commit/3ac623219ba44b0af40ef66826610a26a46c7966) **feat:** Add `version` command
### 1.2.0
* [`86b5812`](https://github.com/buggerjs/node-inspect/commit/86b581218ccab44e6bde259a17ad1e71645a6137) **feat:** scripts & listScripts(true)
### 1.1.1
* [`feaea38`](https://github.com/buggerjs/node-inspect/commit/feaea385a981e6b72a8d99277fbf575c54e15fc6) **style:** Typo in comment
### 1.1.0
* [`c64155f`](https://github.com/buggerjs/node-inspect/commit/c64155faa552f71463842a26330aa5bcbfc31670) **feat:** repl command
### 1.0.0
* [`44c4c79`](https://github.com/buggerjs/node-inspect/commit/44c4c79af5a228ccfd8906f11409b2a33390b878) **chore:** Initial commit
* [`985873c`](https://github.com/buggerjs/node-inspect/commit/985873cfb97146b38480080f9907219c473f1f6f) **feat:** Launching the example works
* [`3d92d05`](https://github.com/buggerjs/node-inspect/commit/3d92d05cca152a2c2647aa64eefc80432638bc4d) **chore:** Proper license and passing tests
* [`b3f99d9`](https://github.com/buggerjs/node-inspect/commit/b3f99d981038b17663fcfd984d2f5d6d9b51ee18) **feat:** Futile attempts to send a valid ws frame
* [`465cfb7`](https://github.com/buggerjs/node-inspect/commit/465cfb7b295aebb48b285c26f6de9c4657fe590d) **feat:** Working ws connection
* [`da9f011`](https://github.com/buggerjs/node-inspect/commit/da9f01118e2b144f2da8cd370113a608526774a1) **fix:** Fix remote connect
* [`5ef33d7`](https://github.com/buggerjs/node-inspect/commit/5ef33d7892cc49becb4c66098fc7927bc74b014a) **feat:** Working step-by-step
* [`534e1e4`](https://github.com/buggerjs/node-inspect/commit/534e1e46b307d61d51eb4c0aab4a3b17c17aea3d) **chore:** Add bin entry
* [`8cff9cf`](https://github.com/buggerjs/node-inspect/commit/8cff9cfb0138b5ecff0f5f6a7839dbfddc0684fd) **style:** Use simpler key thingy
* [`720ec53`](https://github.com/buggerjs/node-inspect/commit/720ec53a5b251ab3caf27f06b60924efb9e03a92) **doc:** Add instructions
* [`b89ad60`](https://github.com/buggerjs/node-inspect/commit/b89ad601b885a417e6433b1609477d8453f498a1) **doc:** More helpful docs
* [`de9243c`](https://github.com/buggerjs/node-inspect/commit/de9243c95eabe733d05952229340808c3cebf129) **feat:** Watchers
* [`e16978f`](https://github.com/buggerjs/node-inspect/commit/e16978ff8e4b2b2bdccf88fd7d3905f525822981) **docs:** Working usage hints
* [`2dbc204`](https://github.com/buggerjs/node-inspect/commit/2dbc2042145fd97169fc7536186a449715e27810) **refactor:** Use proxies
* [`b8c9b14`](https://github.com/buggerjs/node-inspect/commit/b8c9b147713f63181396d5a7fe4c2f737b733b4c) **style:** Remove unused var
* [`f6b4b20`](https://github.com/buggerjs/node-inspect/commit/f6b4b20a1d28d91cfe452b995f7dbe5f7c749e89) **feat:** Nicer inspect of remote values
* [`36887c6`](https://github.com/buggerjs/node-inspect/commit/36887c66bbf26d540f087f80ddfec38462a33bdf) **fix:** Properly print watchers
* [`7729442`](https://github.com/buggerjs/node-inspect/commit/77294426157a28cc76e339cb13916a205182641e) **feat:** Add pause command
* [`e39a713`](https://github.com/buggerjs/node-inspect/commit/e39a7134873f06da37baaa9b6252cede4ad38d7a) **fix:** Properly format boolean properties
* [`f8f51d7`](https://github.com/buggerjs/node-inspect/commit/f8f51d7a01e8d74023306a08a3d6e2da63d123e1) **fix:** Properly format numeric properties
* [`89e6e08`](https://github.com/buggerjs/node-inspect/commit/89e6e087220f3c3cb628ac7541c44298485a2e04) **feat:** Add backtrace command
* [`82362ac`](https://github.com/buggerjs/node-inspect/commit/82362acfc7ce22b4cccc64889ec136dedc8895ec) **feat:** Add setBreakpoint()
* [`7064cce`](https://github.com/buggerjs/node-inspect/commit/7064ccec3b103683088d532abfe5b4e7c066948b) **feat:** Add `setBreakpoint(line)`
* [`360580e`](https://github.com/buggerjs/node-inspect/commit/360580eba4353e81311e56df018eec0ca233da11) **feat:** Add run/kill/restart
* [`b1b576e`](https://github.com/buggerjs/node-inspect/commit/b1b576e2645723a8575df544e0bfb672d60d9d91) **feat:** Add `help` command
* [`2db4660`](https://github.com/buggerjs/node-inspect/commit/2db46609cd1c8543d31ebd5dc47e4c27ec254841) **feat:** Add remaining sb() variants
* [`f2ad1ae`](https://github.com/buggerjs/node-inspect/commit/f2ad1aeedafb154043d70bb9195b10986d311d26) **fix:** Display breakpoints set into the future
* [`73272f9`](https://github.com/buggerjs/node-inspect/commit/73272f9ace1f8546f8cad1d53627dbffba50bb4e) **refactor:** Make breakpoints more inspect friendly
* [`507a71d`](https://github.com/buggerjs/node-inspect/commit/507a71de345a3de7fe144517e9f5ea264ff993e3) **feat:** Add breakpoints command
* [`5fb3e5d`](https://github.com/buggerjs/node-inspect/commit/5fb3e5d17bbcfd45b264431547b3cf0b781c7640) **docs:** Link to Command Line API docs
* [`81af501`](https://github.com/buggerjs/node-inspect/commit/81af501bbf85397e2078310c7f24a9ac5b7f02dc) **chore:** Fix license field

183
deps/node-inspect/CONTRIBUTING.md

@ -0,0 +1,183 @@
# Contributing
🎉🏅 Thanks for helping us improve this project! 🙏
This document outlines some of the practices we care about.
If you have any questions or suggestions about the process,
feel free to [open an issue](#reporting-issues)
.
## Code of Conduct
The [Node.js Code of Conduct][] applies to this repo.
[Node.js Code of Conduct]: https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md
## Code Contributions
The nodereport project falls under the governance of the diagnostics
working group which is documented in:
https://github.com/nodejs/diagnostics/blob/master/GOVERNANCE.md.
## Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
* (a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
* (b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
* (c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
* (d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
## How Can I Contribute?
### Reporting Issues
If you find any mistakes in the docs or a bug in the code,
please [open an issue in Github](https://github.com/nodejs/node-inspect/issues/new) so we can look into it.
You can also [create a PR](#contributing-code) fixing it yourself, or course.
If you report a bug, please follow these guidelines:
* Make sure the bug exists in the latest version.
* Include instructions on how to reproduce the issue.
The instructions should be as minimal as possible
and answer the three big questions:
1. What are the exact steps you took? This includes the exact versions of node, npm, and any packages involved.
1. What result are you expecting?
1. What is the actual result?
### Improving Documentation
For small documentation changes, you can use [Github's editing feature](https://help.github.com/articles/editing-files-in-another-user-s-repository/).
The only thing to keep in mind is to prefix the commit message with "docs: ".
The detault commit message generated by Github will lead to a failing CI build.
For larger updates to the documentation
it might be better to follow the [instructions for contributing code below](#contributing-code).
### Contributing Code
**Note:** If you're planning on making substantial changes,
please [open an issue first to discuss your idea](#reporting-issues).
Otherwise you might end up investing a lot of work
only to discover that it conflicts with plans the maintainers might have.
The general steps for creating a pull request are:
1. Create a branch for your change.
Always start your branch from the latest `master`.
We often prefix the branch name with our initials, e.g. `jk-a-change`.
1. Run `npm install` to install the dependencies.
1. If you're fixing a bug, be sure to write a test *first*.
That way you can validate that the test actually catches the bug and doesn't pass.
1. Make your changes to the code.
Remember to update the tests if you add new features or change behavior.
1. Run the tests via `npm test`. This will also run style checks and other validations.
You might see errors about uncommitted files.
This is expected until you commit your changes.
1. Once you're done, `git add .` and `git commit`.
Please follow the [commit message conventions](#commits--commit-messages) described below.
1. Push your branch to Github & create a PR.
#### Code Style
In addition to any linting rules the project might include,
a few general rules of thumb:
* Try to match the style of the rest of the code.
* We prefer simple code that is easy to understand over terse, expressive code.
* We try to structure projects by semantics instead of role.
E.g. we'd rather have a `tree.js` module that contains tree traversal-related helpers
than a `helpers.js` module.
* Actually, if you create helpers you might want to put those into a separate package.
That way it's easier to reuse them.
#### Commits & Commit Messages
Please follow the [angular commit message conventions](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#-git-commit-guidelines).
We use an automated tool for generating releases
that depends on the conventions to determine the next version and the content of the changelog.
Commit messages that don't follow the conventions will cause `npm test` (and thus CI) to fail.
The short summary - a commit message should look like this:
```
<type>: <subject>
<body>
<references>
<footer>
```
Everything but the first line is optional.
The empty lines between the different parts are required.
* `<type>`: One of the following:
- **feat:** Introduces a new feature. This will cause the minor version to go up.
- **fix:** A bug fix. Causes a patch version bump.
- **docs:** Changes to the documentation.
This will also cause an increase of the patch version so that the changes show up in the npm registry.
- **style:** Cleanup & lint rule fixes.
Note that often it's better to just amend the previous commit if it introduced lint errors.
- **refactor:** Changes to the code structure without fixing bugs or adding features.
- **perf:** Performance optimizations.
- **test:** Fixing existing tests or adding missing ones.
Just like with **style**, if you add tests to a feature you just introduced in the previous commit,
consider keeping the tests and the feature in the same commit instead.
- **chore:** Changes to the project setup and tools, dependency bumps, house-keeping.
* `<subject>`: A [good git commit message subject](http://chris.beams.io/posts/git-commit/#limit-50).
- Keep it brief. If possible the whole first line should have at most 50 characters.
- Use imperative mood. "Create" instead of "creates" or "created".
- No period (".") at the end.
* `<body>`: Motivation for the change and any context required for understanding the choices made.
Just like the subject, it should use imperative mood.
* `<references>`: Any URLs relevant to the PR go here.
Use one line per URL and prefix it with the kind of relationship, e.g. "Closes: " or "See: ".
If you are referencing an issue in your commit body or PR description,
never use `#123` but the full URL to the issue or PR you are referencing.
That way the reference is easy to resolve from the git history without having to "guess" the correct link
even if the commit got cherry-picked or merged into a different project.
* `<footer>`: This part only applies if your commit introduces a breaking change.
It's important this is present, otherwise the major version will not increase.
See below for an example.
##### Examples
A feature that introduces a breaking change:
```
feat: Support --yes CLI option
For existing projects all prompts can be inferred automatically.
Manual confirmation for each default provides no value in that case.
Closes https://github.com/my/project/issues/123
BREAKING CHANGE: This removes support for interactive password entry.
Users will have to login beforehand.
```
A simple bug fix:
```
fix: Handle multi-byte characters in search logic
```

5
deps/node-inspect/GOVERNANCE.md

@ -0,0 +1,5 @@
# node-inspect Project Governance
The node-inspect project falls under the governance of the diagnostics
working group which is documented in:
https://github.com/nodejs/diagnostics/blob/master/GOVERNANCE.md.

19
deps/node-inspect/LICENSE

@ -0,0 +1,19 @@
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.

29
deps/node-inspect/README.md

@ -0,0 +1,29 @@
# `node-inspect`
```bash
npm install --global node-inspect
```
For the old V8 debugger protocol,
node has two options:
1. `node --debug <file>`: Start `file` with remote debugging enabled.
2. `node debug <file>`: Start an interactive CLI debugger for `<file>`.
But for the Chrome inspector protol,
there's only one: `node --inspect <file>`.
This project tries to provide the missing second option
by re-implementing `node debug` against the new protocol.
```
Usage: node-inspect script.js
node-inspect <host>:<port>
```
#### References
* [Debugger Documentation](https://nodejs.org/api/debugger.html)
* [EPS: `node inspect` CLI debugger](https://github.com/nodejs/node-eps/pull/42)
* [Debugger Protocol Viewer](https://chromedevtools.github.io/debugger-protocol-viewer/)
* [Command Line API](https://developers.google.com/web/tools/chrome-devtools/debug/command-line/command-line-reference?hl=en)

13
deps/node-inspect/appveyor.yml

@ -0,0 +1,13 @@
environment:
nodejs_version: "6"
install:
- ps: Install-Product node $env:nodejs_version
- npm install
test_script:
- node --version
- npm --version
- npm test
build: off

2
deps/node-inspect/cli.js

@ -0,0 +1,2 @@
#!/usr/bin/env node
require('./lib/cli.js');

6
deps/node-inspect/examples/alive.js

@ -0,0 +1,6 @@
'use strict';
let x = 0;
function heartbeat() {
++x;
}
setInterval(heartbeat, 50);

31
deps/node-inspect/examples/backtrace.js

@ -0,0 +1,31 @@
'use strict';
const { exports: moduleScoped } = module;
function topFn(a, b = false) {
const l1 = a;
let t = typeof l1;
var v = t.length;
debugger;
return b || t || v || moduleScoped;
}
class Ctor {
constructor(options) {
this.options = options;
}
m() {
const mLocal = this.options;
topFn(this);
return mLocal;
}
}
(function () {
const theOptions = { x: 42 };
const arr = [theOptions];
arr.forEach(options => {
const obj = new Ctor(options);
return obj.m();
});
}());

16
deps/node-inspect/examples/break.js

@ -0,0 +1,16 @@
const x = 10;
let name = 'World';
name = 'Robin';
function sayHello() {
if (x > 0) {
console.log(`Hello ${name}`);
}
}
sayHello();
debugger;
setTimeout(sayHello, 10);
function otherFunction() {
console.log('x = %d', x);
}
setTimeout(otherFunction, 50);

5
deps/node-inspect/examples/cjs/index.js

@ -0,0 +1,5 @@
'use strict';
const { add } = require('./other');
const sum = add(40, 2);
module.exports = sum;

4
deps/node-inspect/examples/cjs/other.js

@ -0,0 +1,4 @@
'use strict';
exports.add = function add(a, b) {
return a + b;
};

0
deps/node-inspect/examples/empty.js

11
deps/node-inspect/examples/exceptions.js

@ -0,0 +1,11 @@
'use strict';
let error = null;
try {
throw new Error('Caught');
} catch (e) {
error = e;
}
if (error) {
throw new Error('Uncaught');
}

4
deps/node-inspect/examples/three-lines.js

@ -0,0 +1,4 @@
'use strict';
let x = 1;
x = x + 1;
module.exports = x;

283
deps/node-inspect/lib/_inspect.js

@ -0,0 +1,283 @@
/*
* 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.
*/
'use strict';
const { spawn } = require('child_process');
const { EventEmitter } = require('events');
const util = require('util');
const [ InspectClient, createRepl ] =
(typeof __dirname !== 'undefined') ?
// This copy of node-inspect is on-disk, relative paths make sense.
[
require('./internal/inspect_client'),
require('./internal/inspect_repl')
] :
// This copy of node-inspect is built into the node executable.
[
require('node-inspect/lib/internal/inspect_client'),
require('node-inspect/lib/internal/inspect_repl')
];
const debuglog = util.debuglog('inspect');
exports.port = 9229;
function runScript(script, scriptArgs, inspectPort, childPrint) {
return new Promise((resolve) => {
const args = [
'--inspect',
`--debug-brk=${inspectPort}`,
].concat([script], scriptArgs);
const child = spawn(process.execPath, args);
child.stdout.setEncoding('utf8');
child.stderr.setEncoding('utf8');
child.stdout.on('data', childPrint);
child.stderr.on('data', childPrint);
let output = '';
function waitForListenHint(text) {
output += text;
if (/chrome-devtools:\/\//.test(output)) {
child.stderr.removeListener('data', waitForListenHint);
resolve(child);
}
}
child.stderr.on('data', waitForListenHint);
});
}
function createAgentProxy(domain, client) {
const agent = new EventEmitter();
agent.then = (...args) => {
// TODO: potentially fetch the protocol and pretty-print it here.
const descriptor = {
[util.inspect.custom](depth, { stylize }) {
return stylize(`[Agent ${domain}]`, 'special');
},
};
return Promise.resolve(descriptor).then(...args);
};
return new Proxy(agent, {
get(target, name) {
if (name in target) return target[name];
return function callVirtualMethod(params) {
return client.callMethod(`${domain}.${name}`, params);
};
},
});
}
class NodeInspector {
constructor(options, stdin, stdout) {
this.options = options;
this.stdin = stdin;
this.stdout = stdout;
this.paused = true;
this.child = null;
if (options.script) {
this._runScript = runScript.bind(null,
options.script,
options.scriptArgs,
options.port,
this.childPrint.bind(this));
} else {
this._runScript = () => Promise.resolve(null);
}
this.client = new InspectClient(options.port, options.host);
this.domainNames = ['Debugger', 'HeapProfiler', 'Profiler', 'Runtime'];
this.domainNames.forEach((domain) => {
this[domain] = createAgentProxy(domain, this.client);
});
this.handleDebugEvent = (fullName, params) => {
const [domain, name] = fullName.split('.');
if (domain in this) {
this[domain].emit(name, params);
}
};
this.client.on('debugEvent', this.handleDebugEvent);
const startRepl = createRepl(this);
// Handle all possible exits
process.on('exit', () => this.killChild());
process.once('SIGTERM', process.exit.bind(process, 0));
process.once('SIGHUP', process.exit.bind(process, 0));
this.run()
.then(() => {
this.repl = startRepl();
this.repl.on('exit', () => {
process.exit(0);
});
this.paused = false;
})
.then(null, (error) => process.nextTick(() => { throw error; }));
}
suspendReplWhile(fn) {
this.repl.rli.pause();
this.stdin.pause();
this.paused = true;
return new Promise((resolve) => {
resolve(fn());
}).then(() => {
this.paused = false;
this.repl.rli.resume();
this.repl.displayPrompt();
this.stdin.resume();
}).then(null, (error) => process.nextTick(() => { throw error; }));
}
killChild() {
this.client.reset();
if (this.child) {
this.child.kill();
this.child = null;
}
}
run() {
this.killChild();
return this._runScript().then((child) => {
this.child = child;
let connectionAttempts = 0;
const attemptConnect = () => {
++connectionAttempts;
debuglog('connection attempt #%d', connectionAttempts);
this.stdout.write('.');
return this.client.connect()
.then(() => {
debuglog('connection established');
}, (error) => {
debuglog('connect failed', error);
// If it's failed to connect 10 times then print failed message
if (connectionAttempts >= 10) {
this.stdout.write(' failed to connect, please retry\n');
process.exit(1);
}
return new Promise((resolve) => setTimeout(resolve, 500))
.then(attemptConnect);
});
};
const { host, port } = this.options;
this.print(`connecting to ${host}:${port} ..`, true);
return attemptConnect();
});
}
clearLine() {
if (this.stdout.isTTY) {
this.stdout.cursorTo(0);
this.stdout.clearLine(1);
} else {
this.stdout.write('\b');
}
}
print(text, oneline = false) {
this.clearLine();
this.stdout.write(oneline ? text : `${text}\n`);
}
childPrint(text) {
this.print(
text.toString()
.split(/\r\n|\r|\n/g)
.filter((chunk) => !!chunk)
.map((chunk) => `< ${chunk}`)
.join('\n')
);
if (!this.paused) {
this.repl.displayPrompt(true);
}
if (/Waiting for the debugger to disconnect\.\.\.\n$/.test(text)) {
this.killChild();
}
}
}
function parseArgv([target, ...args]) {
let host = '127.0.0.1';
let port = exports.port;
let isRemote = false;
let script = target;
let scriptArgs = args;
const hostMatch = target.match(/^([^:]+):(\d+)$/);
const portMatch = target.match(/^--port=(\d+)$/);
if (hostMatch) {
// Connecting to remote debugger
// `node-inspect localhost:9229`
host = hostMatch[1];
port = parseInt(hostMatch[2], 10);
isRemote = true;
script = null;
} else if (portMatch) {
// Start debugger on custom port
// `node debug --port=8058 app.js`
port = parseInt(portMatch[1], 10);
script = args[0];
scriptArgs = args.slice(1);
}
return {
host, port,
isRemote, script, scriptArgs,
};
}
function startInspect(argv = process.argv.slice(2),
stdin = process.stdin,
stdout = process.stdout) {
/* eslint-disable no-console */
if (argv.length < 1) {
console.error('Usage: node-inspect script.js');
console.error(' node-inspect <host>:<port>');
process.exit(1);
}
const options = parseArgv(argv);
const inspector = new NodeInspector(options, stdin, stdout);
stdin.resume();
function handleUnexpectedError(e) {
console.error('There was an internal error in node-inspect. ' +
'Please report this bug.');
console.error(e.message);
console.error(e.stack);
if (inspector.child) inspector.child.kill();
process.exit(1);
}
process.on('uncaughtException', handleUnexpectedError);
/* eslint-enable no-console */
}
exports.start = startInspect;

24
deps/node-inspect/lib/cli.js

@ -0,0 +1,24 @@
/*
* 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.
*/
'use strict';
// ~= NativeModule.require('_debugger').start();
require('./_inspect').start();

363
deps/node-inspect/lib/internal/inspect_client.js

@ -0,0 +1,363 @@
/*
* 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.
*/
'use strict';
const Buffer = require('buffer').Buffer;
const crypto = require('crypto');
const { EventEmitter } = require('events');
const http = require('http');
const URL = require('url');
const util = require('util');
const debuglog = util.debuglog('inspect');
const kOpCodeText = 0x1;
const kOpCodeClose = 0x8;
const kFinalBit = 0x80;
const kReserved1Bit = 0x40;
const kReserved2Bit = 0x20;
const kReserved3Bit = 0x10;
const kOpCodeMask = 0xF;
const kMaskBit = 0x80;
const kPayloadLengthMask = 0x7F;
const kMaxSingleBytePayloadLength = 125;
const kMaxTwoBytePayloadLength = 0xFFFF;
const kTwoBytePayloadLengthField = 126;
const kEightBytePayloadLengthField = 127;
const kMaskingKeyWidthInBytes = 4;
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
function unpackError({ code, message, data }) {
const err = new Error(`${message} - ${data}`);
err.code = code;
Error.captureStackTrace(err, unpackError);
return err;
}
function encodeFrameHybi17(payload) {
var i;
const dataLength = payload.length;
let singleByteLength;
let additionalLength;
if (dataLength > kMaxTwoBytePayloadLength) {
singleByteLength = kEightBytePayloadLengthField;
additionalLength = Buffer.alloc(8);
let remaining = dataLength;
for (i = 0; i < 8; ++i) {
additionalLength[7 - i] = remaining & 0xFF;
remaining >>= 8;
}
} else if (dataLength > kMaxSingleBytePayloadLength) {
singleByteLength = kTwoBytePayloadLengthField;
additionalLength = Buffer.alloc(2);
additionalLength[0] = (dataLength & 0xFF00) >> 8;
additionalLength[1] = dataLength & 0xFF;
} else {
additionalLength = Buffer.alloc(0);
singleByteLength = dataLength;
}
const header = Buffer.from([
kFinalBit | kOpCodeText,
kMaskBit | singleByteLength,
]);
const mask = Buffer.alloc(4);
const masked = Buffer.alloc(dataLength);
for (i = 0; i < dataLength; ++i) {
masked[i] = payload[i] ^ mask[i % kMaskingKeyWidthInBytes];
}
return Buffer.concat([header, additionalLength, mask, masked]);
}
function decodeFrameHybi17(data) {
const dataAvailable = data.length;
const notComplete = { closed: false, payload: null, rest: data };
let payloadOffset = 2;
if ((dataAvailable - payloadOffset) < 0) return notComplete;
const firstByte = data[0];
const secondByte = data[1];
const final = (firstByte & kFinalBit) !== 0;
const reserved1 = (firstByte & kReserved1Bit) !== 0;
const reserved2 = (firstByte & kReserved2Bit) !== 0;
const reserved3 = (firstByte & kReserved3Bit) !== 0;
const opCode = firstByte & kOpCodeMask;
const masked = (secondByte & kMaskBit) !== 0;
const compressed = reserved1;
if (compressed) {
throw new Error('Compressed frames not supported');
}
if (!final || reserved2 || reserved3) {
throw new Error('Only compression extension is supported');
}
if (masked) {
throw new Error('Masked server frame - not supported');
}
let closed = false;
switch (opCode) {
case kOpCodeClose:
closed = true;
break;
case kOpCodeText:
break;
default:
throw new Error(`Unsupported op code ${opCode}`);
}
let payloadLength = secondByte & kPayloadLengthMask;
switch (payloadLength) {
case kTwoBytePayloadLengthField:
payloadOffset += 2;
payloadLength = (data[2] << 8) + data[3];
break;
case kEightBytePayloadLengthField:
payloadOffset += 8;
payloadLength = 0;
for (var i = 0; i < 8; ++i) {
payloadLength <<= 8;
payloadLength |= data[2 + i];
}
break;
default:
// Nothing. We already have the right size.
}
if ((dataAvailable - payloadOffset - payloadLength) < 0) return notComplete;
const payloadEnd = payloadOffset + payloadLength;
return {
payload: data.slice(payloadOffset, payloadEnd),
rest: data.slice(payloadEnd),
closed,
};
}
class Client extends EventEmitter {
constructor(port, host) {
super();
this.handleChunk = this._handleChunk.bind(this);
this._port = port;
this._host = host;
this.reset();
}
_handleChunk(chunk) {
this._unprocessed = Buffer.concat([this._unprocessed, chunk]);
while (this._unprocessed.length > 2) {
const {
closed,
payload: payloadBuffer,
rest
} = decodeFrameHybi17(this._unprocessed);
this._unprocessed = rest;
if (closed) {
this.reset();
return;
}
if (payloadBuffer === null) break;
const payloadStr = payloadBuffer.toString();
debuglog('< %s', payloadStr);
const lastChar = payloadStr[payloadStr.length - 1];
if (payloadStr[0] !== '{' || lastChar !== '}') {
throw new Error(`Payload does not look like JSON: ${payloadStr}`);
}
let payload;
try {
payload = JSON.parse(payloadStr);
} catch (parseError) {
parseError.string = payloadStr;
throw parseError;
}
const { id, method, params, result, error } = payload;
if (id) {
const handler = this._pending[id];
if (handler) {
delete this._pending[id];
handler(error, result);
}
} else if (method) {
this.emit('debugEvent', method, params);
this.emit(method, params);
} else {
throw new Error(`Unsupported response: ${payloadStr}`);
}
}
}
reset() {
if (this._http) {
this._http.destroy();
}
this._http = null;
this._lastId = 0;
this._socket = null;
this._pending = {};
this._unprocessed = Buffer.alloc(0);
}
callMethod(method, params) {
return new Promise((resolve, reject) => {
if (!this._socket) {
reject(new Error('Use `run` to start the app again.'));
return;
}
const data = { id: ++this._lastId, method, params };
this._pending[data.id] = (error, result) => {
if (error) reject(unpackError(error));
else resolve(isEmpty(result) ? undefined : result);
};
const json = JSON.stringify(data);
debuglog('> %s', json);
this._socket.write(encodeFrameHybi17(Buffer.from(json)));
});
}
_fetchJSON(urlPath) {
return new Promise((resolve, reject) => {
const httpReq = http.get({
host: this._host,
port: this._port,
path: urlPath,
});
const chunks = [];
function onResponse(httpRes) {
function parseChunks() {
const resBody = Buffer.concat(chunks).toString();
if (httpRes.statusCode !== 200) {
reject(new Error(`Unexpected ${httpRes.statusCode}: ${resBody}`));
return;
}
try {
resolve(JSON.parse(resBody));
} catch (parseError) {
reject(new Error(`Response didn't contain JSON: ${resBody}`));
return;
}
}
httpRes.on('error', reject);
httpRes.on('data', (chunk) => chunks.push(chunk));
httpRes.on('end', parseChunks);
}
httpReq.on('error', reject);
httpReq.on('response', onResponse);
});
}
connect() {
return this._discoverWebsocketPath()
.then((urlPath) => this._connectWebsocket(urlPath));
}
_discoverWebsocketPath() {
return this._fetchJSON('/json')
.then(([{ webSocketDebuggerUrl }]) =>
URL.parse(webSocketDebuggerUrl).path);
}
_connectWebsocket(urlPath) {
this.reset();
const key1 = crypto.randomBytes(16).toString('base64');
debuglog('request websocket', key1);
const httpReq = this._http = http.request({
host: this._host,
port: this._port,
path: urlPath,
headers: {
Connection: 'Upgrade',
Upgrade: 'websocket',
'Sec-WebSocket-Key': key1,
'Sec-WebSocket-Version': '13',
},
});
httpReq.on('error', (e) => {
this.emit('error', e);
});
httpReq.on('response', (httpRes) => {
if (httpRes.statusCode >= 400) {
process.stderr.write(`Unexpected HTTP code: ${httpRes.statusCode}\n`);
httpRes.pipe(process.stderr);
} else {
httpRes.pipe(process.stderr);
}
});
const handshakeListener = (res, socket) => {
// TODO: we *could* validate res.headers[sec-websocket-accept]
debuglog('websocket upgrade');
this._socket = socket;
socket.on('data', this.handleChunk);
socket.on('close', () => {
this.emit('close');
});
Promise.all([
this.callMethod('Runtime.enable'),
this.callMethod('Debugger.enable'),
this.callMethod('Debugger.setPauseOnExceptions', { state: 'none' }),
this.callMethod('Debugger.setAsyncCallStackDepth', { maxDepth: 0 }),
this.callMethod('Profiler.enable'),
this.callMethod('Profiler.setSamplingInterval', { interval: 100 }),
this.callMethod('Debugger.setBlackboxPatterns', { patterns: [] }),
this.callMethod('Runtime.runIfWaitingForDebugger'),
]).then(() => {
this.emit('ready');
}, (error) => {
this.emit('error', error);
});
};
return new Promise((resolve, reject) => {
this.once('error', reject);
this.once('ready', resolve);
httpReq.on('upgrade', handshakeListener);
httpReq.end();
});
}
}
module.exports = Client;

1057
deps/node-inspect/lib/internal/inspect_repl.js

File diff suppressed because it is too large

45
deps/node-inspect/package.json

@ -0,0 +1,45 @@
{
"name": "node-inspect",
"version": "1.10.4",
"description": "Node Inspect",
"license": "MIT",
"main": "lib/_inspect.js",
"bin": "cli.js",
"homepage": "https://github.com/buggerjs/node-inspect",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/buggerjs/node-inspect"
},
"bugs": {
"url": "https://github.com/buggerjs/node-inspect/issues"
},
"scripts": {
"pretest": "eslint --rulesdir=tools/eslint-rules lib test",
"test": "tap \"test/**/*.test.js\"",
"posttest": "nlm verify"
},
"nlm": {
"license": {
"files": [
"lib"
]
}
},
"dependencies": {},
"devDependencies": {
"eslint": "^3.10.2",
"nlm": "^3.0.0",
"tap": "^7.1.2"
},
"author": {
"name": "Jan Krems",
"email": "jan.krems@gmail.com"
},
"files": [
"*.js",
"lib"
],
"publishConfig": {
"registry": "https://registry.npmjs.org"
}
}

30
deps/node-inspect/test/cli/backtrace.test.js

@ -0,0 +1,30 @@
'use strict';
const Path = require('path');
const { test } = require('tap');
const startCLI = require('./start-cli');
test('display and navigate backtrace', (t) => {
const script = Path.join('examples', 'backtrace.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.stepCommand('c'))
.then(() => cli.command('bt'))
.then(() => {
t.match(cli.output, `#0 topFn ${script}:8:2`);
})
.then(() => cli.command('backtrace'))
.then(() => {
t.match(cli.output, `#0 topFn ${script}:8:2`);
})
.then(() => cli.quit())
.then(null, onFatal);
});

195
deps/node-inspect/test/cli/break.test.js

@ -0,0 +1,195 @@
'use strict';
const Path = require('path');
const { test } = require('tap');
const startCLI = require('./start-cli');
test('stepping through breakpoints', (t) => {
const script = Path.join('examples', 'break.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => {
t.match(
cli.output,
`break in ${script}:1`,
'pauses in the first line of the script');
t.match(
cli.output,
/> 1 \(function \([^)]+\) \{ const x = 10;/,
'shows the source and marks the current line');
})
.then(() => cli.stepCommand('n'))
.then(() => {
t.match(
cli.output,
`break in ${script}:2`,
'pauses in next line of the script');
t.match(
cli.output,
'> 2 let name = \'World\';',
'marks the 2nd line');
})
.then(() => cli.stepCommand('next'))
.then(() => {
t.match(
cli.output,
`break in ${script}:3`,
'pauses in next line of the script');
t.match(
cli.output,
'> 3 name = \'Robin\';',
'marks the 3nd line');
})
.then(() => cli.stepCommand('cont'))
.then(() => {
t.match(
cli.output,
`break in ${script}:10`,
'pauses on the next breakpoint');
t.match(
cli.output,
'>10 debugger;',
'marks the debugger line');
})
// Prepare additional breakpoints
.then(() => cli.command('sb("break.js", 6)'))
.then(() => t.notMatch(cli.output, 'Could not resolve breakpoint'))
.then(() => cli.command('sb("otherFunction()")'))
.then(() => cli.command('sb(16)'))
.then(() => t.notMatch(cli.output, 'Could not resolve breakpoint'))
.then(() => cli.command('breakpoints'))
.then(() => {
t.match(cli.output, `#0 ${script}:6`);
t.match(cli.output, `#1 ${script}:16`);
})
.then(() => cli.command('list()'))
.then(() => {
t.match(cli.output, '>10 debugger;', 'prints and marks current line');
t.strictDeepEqual(
cli.parseSourceLines(),
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
'prints 5 lines before and after');
})
.then(() => cli.command('list(2)'))
.then(() => {
t.match(cli.output, '>10 debugger;', 'prints and marks current line');
t.strictDeepEqual(
cli.parseSourceLines(),
[8, 9, 10, 11, 12],
'prints 2 lines before and after');
})
.then(() => cli.stepCommand('s'))
.then(() => cli.stepCommand(''))
.then(() => {
t.match(
cli.output,
'break in timers.js',
'entered timers.js');
})
.then(() => cli.stepCommand('cont'))
.then(() => {
t.match(
cli.output,
`break in ${script}:16`,
'found breakpoint we set above w/ line number only');
})
.then(() => cli.stepCommand('cont'))
.then(() => {
t.match(
cli.output,
`break in ${script}:6`,
'found breakpoint we set above w/ line number & script');
})
.then(() => cli.stepCommand(''))
.then(() => {
t.match(
cli.output,
`debugCommand in ${script}:14`,
'found function breakpoint we set above');
})
.then(() => cli.quit())
.then(null, onFatal);
});
test('sb before loading file', (t) => {
const script = Path.join('examples', 'cjs', 'index.js');
const otherScript = Path.join('examples', 'cjs', 'other.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('sb("other.js", 3)'))
.then(() => {
t.match(
cli.output,
'not loaded yet',
'warns that the script was not loaded yet');
})
.then(() => cli.stepCommand('cont'))
.then(() => {
t.match(
cli.output,
`break in ${otherScript}:3`,
'found breakpoint in file that was not loaded yet');
})
.then(() => cli.quit())
.then(null, onFatal);
});
test('clearBreakpoint', (t) => {
const script = Path.join('examples', 'break.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('sb("break.js", 3)'))
.then(() => cli.command('sb("break.js", 9)'))
.then(() => cli.command('breakpoints'))
.then(() => {
t.match(cli.output, `#0 ${script}:3`);
t.match(cli.output, `#1 ${script}:9`);
})
.then(() => cli.command('clearBreakpoint("break.js", 4)'))
.then(() => {
t.match(cli.output, 'Could not find breakpoint');
})
.then(() => cli.command('clearBreakpoint("not-such-script.js", 3)'))
.then(() => {
t.match(cli.output, 'Could not find breakpoint');
})
.then(() => cli.command('clearBreakpoint("break.js", 3)'))
.then(() => cli.command('breakpoints'))
.then(() => {
t.match(cli.output, `#0 ${script}:9`);
})
.then(() => cli.stepCommand('cont'))
.then(() => {
t.match(
cli.output,
`break in ${script}:9`,
'hits the 2nd breakpoint because the 1st was cleared');
})
.then(() => cli.quit())
.then(null, onFatal);
});

63
deps/node-inspect/test/cli/exceptions.test.js

@ -0,0 +1,63 @@
'use strict';
const Path = require('path');
const { test } = require('tap');
const startCLI = require('./start-cli');
test('break on (uncaught) exceptions', (t) => {
const script = Path.join('examples', 'exceptions.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => {
t.match(cli.output, `break in ${script}:1`);
})
// making sure it will die by default:
.then(() => cli.command('c'))
.then(() => cli.waitFor(/disconnect/))
// Next run: With `breakOnException` it pauses in both places
.then(() => cli.stepCommand('r'))
.then(() => {
t.match(cli.output, `break in ${script}:1`);
})
.then(() => cli.command('breakOnException'))
.then(() => cli.stepCommand('c'))
.then(() => {
t.match(cli.output, `exception in ${script}:4`);
})
.then(() => cli.stepCommand('c'))
.then(() => {
t.match(cli.output, `exception in ${script}:10`);
})
// Next run: With `breakOnUncaught` it only pauses on the 2nd exception
.then(() => cli.command('breakOnUncaught'))
.then(() => cli.stepCommand('r')) // also, the setting survives the restart
.then(() => {
t.match(cli.output, `break in ${script}:1`);
})
.then(() => cli.stepCommand('c'))
.then(() => {
t.match(cli.output, `exception in ${script}:10`);
})
// Next run: Back to the initial state! It should die again.
.then(() => cli.command('breakOnNone'))
.then(() => cli.stepCommand('r'))
.then(() => {
t.match(cli.output, `break in ${script}:1`);
})
.then(() => cli.command('c'))
.then(() => cli.waitFor(/disconnect/))
.then(() => cli.quit())
.then(null, onFatal);
});

77
deps/node-inspect/test/cli/exec.test.js

@ -0,0 +1,77 @@
'use strict';
const { test } = require('tap');
const startCLI = require('./start-cli');
test('examples/alive.js', (t) => {
const cli = startCLI(['examples/alive.js']);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('exec [typeof heartbeat, typeof process.exit]'))
.then(() => {
t.match(cli.output, '[ \'function\', \'function\' ]', 'works w/o paren');
})
.then(() => cli.command('repl'))
.then(() => {
t.match(
cli.output,
'Press Ctrl + C to leave debug repl\n> ',
'shows hint for how to leave repl');
t.notMatch(cli.output, 'debug>', 'changes the repl style');
})
.then(() => cli.command('[typeof heartbeat, typeof process.exit]'))
.then(() => cli.waitFor(/function/))
.then(() => cli.waitForPrompt())
.then(() => {
t.match(
cli.output,
'[ \'function\', \'function\' ]', 'can evaluate in the repl');
t.match(cli.output, /> $/);
})
.then(() => cli.ctrlC())
.then(() => cli.waitFor(/debug> $/))
.then(() => cli.command('exec("[typeof heartbeat, typeof process.exit]")'))
.then(() => {
t.match(cli.output, '[ \'function\', \'function\' ]', 'works w/ paren');
})
.then(() => cli.command('cont'))
.then(() => cli.command('exec [typeof heartbeat, typeof process.exit]'))
.then(() => {
t.match(
cli.output,
'[ \'undefined\', \'function\' ]',
'non-paused exec can see global but not module-scope values');
})
.then(() => cli.quit())
.then(null, onFatal);
});
test('exec .scope', (t) => {
const cli = startCLI(['examples/backtrace.js']);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.stepCommand('c'))
.then(() => cli.command('exec .scope'))
.then(() => {
t.match(
cli.output,
'\'moduleScoped\'', 'displays closure from module body');
t.match(cli.output, '\'a\'', 'displays local / function arg');
t.match(cli.output, '\'l1\'', 'displays local scope');
t.notMatch(cli.output, '\'encodeURIComponent\'', 'omits global scope');
})
.then(() => cli.quit())
.then(null, onFatal);
});

22
deps/node-inspect/test/cli/help.test.js

@ -0,0 +1,22 @@
'use strict';
const { test } = require('tap');
const startCLI = require('./start-cli');
test('examples/empty.js', (t) => {
const cli = startCLI(['examples/empty.js']);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('help'))
.then(() => {
t.match(cli.output, /run, restart, r\s+/m);
})
.then(() => cli.quit())
.then(null, onFatal);
});

25
deps/node-inspect/test/cli/invalid-args.test.js

@ -0,0 +1,25 @@
'use strict';
const { test } = require('tap');
const startCLI = require('./start-cli');
test('launch CLI w/o args', (t) => {
const cli = startCLI([]);
return cli.quit()
.then((code) => {
t.equal(code, 1, 'exits with non-zero exit code');
t.match(cli.output, /^Usage:/, 'Prints usage info');
});
});
test('launch w/ invalid host:port', (t) => {
const cli = startCLI(['localhost:914']);
return cli.quit()
.then((code) => {
t.match(
cli.output,
'failed to connect',
'Tells the user that the connection failed');
t.equal(code, 1, 'exits with non-zero exit code');
});
});

110
deps/node-inspect/test/cli/launch.test.js

@ -0,0 +1,110 @@
'use strict';
const Path = require('path');
const { test } = require('tap');
const startCLI = require('./start-cli');
test('examples/empty.js', (t) => {
const script = Path.join('examples', 'empty.js');
const cli = startCLI([script]);
return cli.waitForPrompt()
.then(() => {
t.match(cli.output, 'debug>', 'prints a prompt');
t.match(
cli.output,
'< Debugger listening on port 9229',
'forwards child output');
})
.then(() => cli.command('["hello", "world"].join(" ")'))
.then(() => {
t.match(cli.output, 'hello world', 'prints the result');
})
.then(() => cli.command(''))
.then(() => {
t.match(cli.output, 'hello world', 'repeats the last command on <enter>');
})
.then(() => cli.command('version'))
.then(() => {
t.match(cli.output, process.versions.v8, 'version prints the v8 version');
})
.then(() => cli.quit())
.then((code) => {
t.equal(code, 0, 'exits with success');
});
});
test('run after quit / restart', (t) => {
const script = Path.join('examples', 'three-lines.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.stepCommand('n'))
.then(() => {
t.match(
cli.output,
`break in ${script}:2`,
'steps to the 2nd line');
})
.then(() => cli.command('cont'))
.then(() => cli.waitFor(/disconnect/))
.then(() => {
t.match(
cli.output,
'Waiting for the debugger to disconnect',
'the child was done');
})
.then(() => {
// On windows the socket won't close by itself
return cli.command('kill');
})
.then(() => cli.command('cont'))
.then(() => cli.waitFor(/start the app/))
.then(() => {
t.match(cli.output, 'Use `run` to start the app again');
})
.then(() => cli.stepCommand('run'))
.then(() => cli.waitForPrompt())
.then(() => {
t.match(
cli.output,
`break in ${script}:1`,
'is back at the beginning');
})
.then(() => cli.stepCommand('n'))
.then(() => {
t.match(
cli.output,
`break in ${script}:2`,
'steps to the 2nd line');
})
.then(() => cli.stepCommand('restart'))
.then(() => {
t.match(
cli.output,
`break in ${script}:1`,
'is back at the beginning');
})
.then(() => cli.command('kill'))
.then(() => cli.command('cont'))
.then(() => cli.waitFor(/start the app/))
.then(() => {
t.match(cli.output, 'Use `run` to start the app again');
})
.then(() => cli.stepCommand('run'))
.then(() => cli.waitForPrompt())
.then(() => {
t.match(
cli.output,
`break in ${script}:1`,
'is back at the beginning');
})
.then(() => cli.quit())
.then(null, onFatal);
});

31
deps/node-inspect/test/cli/low-level.test.js

@ -0,0 +1,31 @@
'use strict';
const { test } = require('tap');
const startCLI = require('./start-cli');
test('Debugger agent direct access', (t) => {
const cli = startCLI(['examples/empty.js']);
const scriptPattern = /^\* (\d+): examples(?:\/|\\)empty.js/;
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('scripts'))
.then(() => {
const [, scriptId] = cli.output.match(scriptPattern);
return cli.command(
`Debugger.getScriptSource({ scriptId: '${scriptId}' })`
);
})
.then(() => {
t.match(
cli.output,
/scriptSource: '\(function \([^)]+\) \{ \\n}\);'/);
})
.then(() => cli.quit())
.then(null, onFatal);
});

56
deps/node-inspect/test/cli/preserve-breaks.test.js

@ -0,0 +1,56 @@
'use strict';
const Path = require('path');
const { test } = require('tap');
const startCLI = require('./start-cli');
test('run after quit / restart', (t) => {
const script = Path.join('examples', 'three-lines.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('breakpoints'))
.then(() => {
t.match(cli.output, 'No breakpoints yet');
})
.then(() => cli.command('sb(2)'))
.then(() => cli.command('sb(3)'))
.then(() => cli.command('breakpoints'))
.then(() => {
t.match(cli.output, `#0 ${script}:2`);
t.match(cli.output, `#1 ${script}:3`);
})
.then(() => cli.stepCommand('c')) // hit line 2
.then(() => cli.stepCommand('c')) // hit line 3
.then(() => {
t.match(cli.output, `break in ${script}:3`);
})
.then(() => cli.command('restart'))
.then(() => cli.waitFor([/break in examples/, /breakpoints restored/]))
.then(() => cli.waitForPrompt())
.then(() => {
t.match(cli.output, `break in ${script}:1`);
})
.then(() => cli.stepCommand('c'))
.then(() => {
t.match(cli.output, `break in ${script}:2`);
})
.then(() => cli.stepCommand('c'))
.then(() => {
t.match(cli.output, `break in ${script}:3`);
})
.then(() => cli.command('breakpoints'))
.then(() => {
t.match(cli.output, `#0 ${script}:2`);
t.match(cli.output, `#1 ${script}:3`);
})
.then(() => cli.quit())
.then(null, onFatal);
});

32
deps/node-inspect/test/cli/profile.test.js

@ -0,0 +1,32 @@
'use strict';
const { test } = require('tap');
const startCLI = require('./start-cli');
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
test('profiles', (t) => {
const cli = startCLI(['examples/empty.js']);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('exec console.profile()'))
.then(() => {
t.match(cli.output, 'undefined');
})
.then(() => cli.command('exec console.profileEnd()'))
.then(() => delay(250))
.then(() => {
t.match(cli.output, 'undefined');
t.match(cli.output, 'Captured new CPU profile.');
})
.then(() => cli.quit())
.then(null, onFatal);
});

43
deps/node-inspect/test/cli/scripts.test.js

@ -0,0 +1,43 @@
'use strict';
const Path = require('path');
const { test } = require('tap');
const startCLI = require('./start-cli');
test('list scripts', (t) => {
const script = Path.join('examples', 'empty.js');
const cli = startCLI([script]);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('scripts'))
.then(() => {
t.match(
cli.output,
/^\* \d+: examples(?:\/|\\)empty\.js/,
'lists the user script');
t.notMatch(
cli.output,
/\d+: module\.js <native>/,
'omits node-internal scripts');
})
.then(() => cli.command('scripts(true)'))
.then(() => {
t.match(
cli.output,
/\* \d+: examples(?:\/|\\)empty\.js/,
'lists the user script');
t.match(
cli.output,
/\d+: module\.js <native>/,
'includes node-internal scripts');
})
.then(() => cli.quit())
.then(null, onFatal);
});

136
deps/node-inspect/test/cli/start-cli.js

@ -0,0 +1,136 @@
'use strict';
const spawn = require('child_process').spawn;
const CLI =
process.env.USE_EMBEDDED_NODE_INSPECT === '1' ?
'inspect' :
require.resolve('../../cli.js');
function startCLI(args) {
const child = spawn(process.execPath, [CLI, ...args]);
let isFirstStdoutChunk = true;
const outputBuffer = [];
function bufferOutput(chunk) {
if (isFirstStdoutChunk) {
isFirstStdoutChunk = false;
outputBuffer.push(chunk.replace(/^debug>\s*/, ''));
} else {
outputBuffer.push(chunk);
}
}
function getOutput() {
return outputBuffer.join('').toString()
.replace(/^[^\n]*?[\b]/mg, '');
}
child.stdout.setEncoding('utf8');
child.stdout.on('data', bufferOutput);
child.stderr.setEncoding('utf8');
child.stderr.on('data', bufferOutput);
if (process.env.VERBOSE === '1') {
child.stdout.pipe(process.stderr);
child.stderr.pipe(process.stderr);
}
return {
flushOutput() {
const output = this.output;
outputBuffer.length = 0;
return output;
},
waitFor(pattern, timeout = 2000) {
function checkPattern(str) {
if (Array.isArray(pattern)) {
return pattern.every((p) => p.test(str));
}
return pattern.test(str);
}
return new Promise((resolve, reject) => {
function checkOutput() {
if (checkPattern(getOutput())) {
tearDown(); // eslint-disable-line no-use-before-define
resolve();
}
}
function onChildExit() {
tearDown(); // eslint-disable-line no-use-before-define
reject(new Error(
`Child quit while waiting for ${pattern}; found: ${this.output}`));
}
const timer = setTimeout(() => {
tearDown(); // eslint-disable-line no-use-before-define
reject(new Error([
`Timeout (${timeout}) while waiting for ${pattern}`,
`found: ${this.output}`,
].join('; ')));
}, timeout);
function tearDown() {
clearTimeout(timer);
child.stdout.removeListener('data', checkOutput);
child.removeListener('exit', onChildExit);
}
child.on('exit', onChildExit);
child.stdout.on('data', checkOutput);
checkOutput();
});
},
waitForPrompt(timeout = 2000) {
return this.waitFor(/>\s+$/, timeout);
},
ctrlC() {
return this.command('.interrupt');
},
get output() {
return getOutput();
},
get rawOutput() {
return outputBuffer.join('').toString();
},
parseSourceLines() {
return getOutput().split('\n')
.map((line) => line.match(/(?:\*|>)?\s*(\d+)/))
.filter((match) => match !== null)
.map((match) => +match[1]);
},
command(input) {
this.flushOutput();
child.stdin.write(input);
child.stdin.write('\n');
return this.waitForPrompt();
},
stepCommand(input) {
this.flushOutput();
child.stdin.write(input);
child.stdin.write('\n');
return this
.waitFor(
/(?:assert|break|debugCommand|exception|other|promiseRejection) in/
)
.then(() => this.waitForPrompt());
},
quit() {
return new Promise((resolve) => {
child.stdin.end();
child.on('exit', resolve);
});
},
};
}
module.exports = startCLI;

42
deps/node-inspect/test/cli/watchers.test.js

@ -0,0 +1,42 @@
'use strict';
const { test } = require('tap');
const startCLI = require('./start-cli');
test('stepping through breakpoints', (t) => {
const cli = startCLI(['examples/break.js']);
function onFatal(error) {
cli.quit();
throw error;
}
return cli.waitFor(/break/)
.then(() => cli.waitForPrompt())
.then(() => cli.command('watch("x")'))
.then(() => cli.command('watch("\\"Hello\\"")'))
.then(() => cli.command('watch("42")'))
.then(() => cli.command('watch("NaN")'))
.then(() => cli.command('watch("true")'))
.then(() => cli.command('watch("[1, 2]")'))
.then(() => cli.command('watch("process.env")'))
.then(() => cli.command('watchers'))
.then(() => {
t.match(cli.output, 'x is not defined');
})
.then(() => cli.command('unwatch("42")'))
.then(() => cli.stepCommand('n'))
.then(() => {
t.match(cli.output, '0: x = 10');
t.match(cli.output, '1: "Hello" = \'Hello\'');
t.match(cli.output, '2: NaN = NaN');
t.match(cli.output, '3: true = true');
t.match(cli.output, '4: [1, 2] = [ 1, 2 ]');
t.match(
cli.output,
/5: process\.env =\n\s+\{[\s\S]+,\n\s+\.\.\. \}/,
'shows "..." for process.env');
})
.then(() => cli.quit())
.then(null, onFatal);
});

9
deps/node-inspect/test/node-inspect.test.js

@ -0,0 +1,9 @@
'use strict';
const tap = require('tap');
const nodeInspect = require('../');
tap.equal(
9229,
nodeInspect.port,
'Uses the --inspect default port');

76
deps/node-inspect/tools/eslint-rules/align-function-arguments.js

@ -0,0 +1,76 @@
/**
* @fileoverview Align arguments in multiline function calls
* @author Rich Trott
*/
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
function checkArgumentAlignment(context, node) {
function isNodeFirstInLine(node, byEndLocation) {
const firstToken = byEndLocation === true ? context.getLastToken(node, 1) :
context.getTokenBefore(node);
const startLine = byEndLocation === true ? node.loc.end.line :
node.loc.start.line;
const endLine = firstToken ? firstToken.loc.end.line : -1;
return startLine !== endLine;
}
if (node.arguments.length === 0)
return;
var msg = '';
const first = node.arguments[0];
var currentLine = first.loc.start.line;
const firstColumn = first.loc.start.column;
const ignoreTypes = [
'ArrowFunctionExpression',
'FunctionExpression',
'ObjectExpression',
];
const args = node.arguments;
// For now, don't bother trying to validate potentially complicating things
// like closures. Different people will have very different ideas and it's
// probably best to implement configuration options.
if (args.some((node) => { return ignoreTypes.indexOf(node.type) !== -1; })) {
return;
}
if (!isNodeFirstInLine(node)) {
return;
}
var misaligned;
args.slice(1).forEach((argument) => {
if (!misaligned) {
if (argument.loc.start.line === currentLine + 1) {
if (argument.loc.start.column !== firstColumn) {
if (isNodeFirstInLine(argument)) {
msg = 'Function argument in column ' +
`${argument.loc.start.column + 1}, ` +
`expected in ${firstColumn + 1}`;
misaligned = argument;
}
}
}
}
currentLine = argument.loc.start.line;
});
if (msg)
context.report(misaligned, msg);
}
module.exports = function(context) {
return {
'CallExpression': (node) => checkArgumentAlignment(context, node)
};
};

68
deps/node-inspect/tools/eslint-rules/align-multiline-assignment.js

@ -0,0 +1,68 @@
/**
* @fileoverview Align multiline variable assignments
* @author Rich Trott
*/
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
function getBinaryExpressionStarts(binaryExpression, starts) {
function getStartsFromOneSide(side, starts) {
starts.push(side.loc.start);
if (side.type === 'BinaryExpression') {
starts = getBinaryExpressionStarts(side, starts);
}
return starts;
}
starts = getStartsFromOneSide(binaryExpression.left, starts);
starts = getStartsFromOneSide(binaryExpression.right, starts);
return starts;
}
function checkExpressionAlignment(expression) {
if (!expression)
return;
var msg = '';
switch (expression.type) {
case 'BinaryExpression':
var starts = getBinaryExpressionStarts(expression, []);
var startLine = starts[0].line;
const startColumn = starts[0].column;
starts.forEach((loc) => {
if (loc.line > startLine) {
startLine = loc.line;
if (loc.column !== startColumn) {
msg = 'Misaligned multiline assignment';
}
}
});
break;
}
return msg;
}
function testAssignment(context, node) {
const msg = checkExpressionAlignment(node.right);
if (msg)
context.report(node, msg);
}
function testDeclaration(context, node) {
node.declarations.forEach((declaration) => {
const msg = checkExpressionAlignment(declaration.init);
// const start = declaration.init.loc.start;
if (msg)
context.report(node, msg);
});
}
module.exports = function(context) {
return {
'AssignmentExpression': (node) => testAssignment(context, node),
'VariableDeclaration': (node) => testDeclaration(context, node)
};
};

30
deps/node-inspect/tools/eslint-rules/assert-fail-single-argument.js

@ -0,0 +1,30 @@
/**
* @fileoverview Prohibit use of a single argument only in `assert.fail()`. It
* is almost always an error.
* @author Rich Trott
*/
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const msg = 'assert.fail() message should be third argument';
function isAssert(node) {
return node.callee.object && node.callee.object.name === 'assert';
}
function isFail(node) {
return node.callee.property && node.callee.property.name === 'fail';
}
module.exports = function(context) {
return {
'CallExpression': function(node) {
if (isAssert(node) && isFail(node) && node.arguments.length === 1) {
context.report(node, msg);
}
}
};
};

25
deps/node-inspect/tools/eslint-rules/buffer-constructor.js

@ -0,0 +1,25 @@
/**
* @fileoverview Require use of new Buffer constructor methods in lib
* @author James M Snell
*/
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const msg = 'Use of the Buffer() constructor has been deprecated. ' +
'Please use either Buffer.alloc(), Buffer.allocUnsafe(), ' +
'or Buffer.from()';
function test(context, node) {
if (node.callee.name === 'Buffer') {
context.report(node, msg);
}
}
module.exports = function(context) {
return {
'NewExpression': (node) => test(context, node),
'CallExpression': (node) => test(context, node)
};
};

31
deps/node-inspect/tools/eslint-rules/new-with-error.js

@ -0,0 +1,31 @@
/**
* @fileoverview Require `throw new Error()` rather than `throw Error()`
* @author Rich Trott
*/
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
var errorList = context.options.length !== 0 ? context.options : ['Error'];
return {
'ThrowStatement': function(node) {
if (node.argument.type === 'CallExpression' &&
errorList.indexOf(node.argument.callee.name) !== -1) {
context.report(node, 'Use new keyword when throwing.');
}
}
};
};
module.exports.schema = {
'type': 'array',
'additionalItems': {
'type': 'string'
},
'uniqueItems': true
};

46
deps/node-inspect/tools/eslint-rules/no-let-in-for-declaration.js

@ -0,0 +1,46 @@
/**
* @fileoverview Prohibit the use of `let` as the loop variable
* in the initialization of for, and the left-hand
* iterator in forIn and forOf loops.
*
* @author Jessica Quynh Tran
*/
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
create(context) {
const msg = 'Use of `let` as the loop variable in a for-loop is ' +
'not recommended. Please use `var` instead.';
/**
* Report function to test if the for-loop is declared using `let`.
*/
function testForLoop(node) {
if (node.init && node.init.kind === 'let') {
context.report(node.init, msg);
}
}
/**
* Report function to test if the for-in or for-of loop
* is declared using `let`.
*/
function testForInOfLoop(node) {
if (node.left && node.left.kind === 'let') {
context.report(node.left, msg);
}
}
return {
'ForStatement': testForLoop,
'ForInStatement': testForInOfLoop,
'ForOfStatement': testForInOfLoop
};
}
};

39
deps/node-inspect/tools/eslint-rules/prefer-assert-methods.js

@ -0,0 +1,39 @@
'use strict';
function isAssert(node) {
return node.expression &&
node.expression.type === 'CallExpression' &&
node.expression.callee &&
node.expression.callee.name === 'assert';
}
function getFirstArg(expression) {
return expression.arguments && expression.arguments[0];
}
function parseError(method, op) {
return `'assert.${method}' should be used instead of '${op}'`;
}
const preferedAssertMethod = {
'===': 'strictEqual',
'!==': 'notStrictEqual',
'==': 'equal',
'!=': 'notEqual'
};
module.exports = function(context) {
return {
ExpressionStatement(node) {
if (isAssert(node)) {
const arg = getFirstArg(node.expression);
if (arg && arg.type === 'BinaryExpression') {
const assertMethod = preferedAssertMethod[arg.operator];
if (assertMethod) {
context.report(node, parseError(assertMethod, arg.operator));
}
}
}
}
};
};

19
deps/node-inspect/tools/eslint-rules/require-buffer.js

@ -0,0 +1,19 @@
'use strict';
module.exports = function(context) {
function flagIt(reference) {
const msg = 'Use const Buffer = require(\'buffer\').Buffer; ' +
'at the beginning of this file';
context.report(reference.identifier, msg);
}
return {
'Program:exit': function() {
const globalScope = context.getScope();
const variable = globalScope.set.get('Buffer');
if (variable) {
variable.references.forEach(flagIt);
}
}
};
};

99
deps/node-inspect/tools/eslint-rules/required-modules.js

@ -0,0 +1,99 @@
/**
* @fileoverview Require usage of specified node modules.
* @author Rich Trott
*/
'use strict';
var path = require('path');
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
// trim required module names
var requiredModules = context.options;
var foundModules = [];
// if no modules are required we don't need to check the CallExpressions
if (requiredModules.length === 0) {
return {};
}
/**
* Function to check if a node is a string literal.
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a string literal.
*/
function isString(node) {
return node && node.type === 'Literal' && typeof node.value === 'string';
}
/**
* Function to check if a node is a require call.
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a require call.
*/
function isRequireCall(node) {
return node.callee.type === 'Identifier' && node.callee.name === 'require';
}
/**
* Function to check if a node has an argument that is a required module and
* return its name.
* @param {ASTNode} node The node to check
* @returns {undefined|String} required module name or undefined
*/
function getRequiredModuleName(node) {
var moduleName;
// node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
var argValue = path.basename(node.arguments[0].value.trim());
// check if value is in required modules array
if (requiredModules.indexOf(argValue) !== -1) {
moduleName = argValue;
}
}
return moduleName;
}
return {
'CallExpression': function(node) {
if (isRequireCall(node)) {
var requiredModuleName = getRequiredModuleName(node);
if (requiredModuleName) {
foundModules.push(requiredModuleName);
}
}
},
'Program:exit': function(node) {
if (foundModules.length < requiredModules.length) {
var missingModules = requiredModules.filter(
function(module) {
return foundModules.indexOf(module === -1);
}
);
missingModules.forEach(function(moduleName) {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded.',
{ moduleName: moduleName }
);
});
}
}
};
};
module.exports.schema = {
'type': 'array',
'additionalItems': {
'type': 'string'
},
'uniqueItems': true
};
Loading…
Cancel
Save