diff --git a/package-lock.json b/package-lock.json index 8e83e810b20b..40ed0c1a7b71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,13 +7,13 @@ "@types/chai": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.6.tgz", - "integrity": "sha1-nLWn+33YO+DPyq/b2VorXdNRdi8=", + "integrity": "sha512-IzRWv/7IpaMm41KLLJcaaD/UKit/MrHu4rWs61oWiVjuk4aKWe2eopx3XyhAHhSnMyB5EeCMRr2AsJtuQ8COWA==", "dev": true }, "@types/chai-as-promised": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.0.tgz", - "integrity": "sha1-AQsEzeeOrPtucr/ds+WP4jwueLk=", + "integrity": "sha512-MFiW54UOSt+f2bRw8J7LgQeIvE/9b4oGvwU7XW30S9QGAiHGnU/fmiOprsyMkdmH2rl8xSPc0/yrQw8juXU6bQ==", "dev": true, "requires": { "@types/chai": "4.0.6" @@ -22,7 +22,7 @@ "@types/commander": { "version": "2.12.2", "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz", - "integrity": "sha1-GDBBojhC1CgUePpdI8XKeOb9CK4=", + "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==", "dev": true, "requires": { "commander": "2.3.0" @@ -31,7 +31,7 @@ "@types/fs-extra": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.5.tgz", - "integrity": "sha1-iqYDPA6HxlOwmmcRaGkWhktI7J4=", + "integrity": "sha512-tIG0GpHum5IFb8Qze/cSv0w/0gNzHB+MUDftTQaxenx46z50g51/MPkNLssLz9+uZLzCDd35bT9qtWOTXZ21Gw==", "dev": true, "requires": { "@types/node": "6.0.92" @@ -40,7 +40,7 @@ "@types/get-port": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@types/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-+eChFEPMITNkcBherj37pEldKbw=", + "integrity": "sha512-TiNg8R1kjDde5Pub9F9vCwZA/BNW9HeXP5b9j7Qucqncy/McfPZ6xze/EyBdXS5FhMIGN6Fx3vg75l5KHy3V1Q==", "dev": true }, "@types/iconv-lite": { @@ -55,37 +55,37 @@ "@types/lodash": { "version": "4.14.87", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.87.tgz", - "integrity": "sha1-Vfkhg7BIwsZEAq/kcvgzP04xmms=", + "integrity": "sha512-AqRC+aEF4N0LuNHtcjKtvF9OTfqZI0iaBoe3dA6m/W+/YZJBZjBmW/QIZ8fBeXC6cnytSY9tBoFBqZ9uSCeVsw==", "dev": true }, "@types/mocha": { "version": "2.2.44", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz", - "integrity": "sha1-HUp5jlPzUhL9WtTQQFBiAXHNW14=", + "integrity": "sha512-k2tWTQU8G4+iSMvqKi0Q9IIsWAp/n8xzdZS4Q4YVIltApoMA00wFBFdlJnmoaK1/z7B0Cy0yPe6GgXteSmdUNw==", "dev": true }, "@types/node": { "version": "6.0.92", "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz", - "integrity": "sha1-5/chrigncuEroleZaMANnM5CLF0=", + "integrity": "sha512-awEYSSTn7dauwVCYSx2CJaPTu0Z1Ht2oR1b2AD3CYao6ZRb+opb6EL43fzmD7eMFgMHzTBWSUzlWSD+S8xN0Nw==", "dev": true }, "@types/semver": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.4.0.tgz", - "integrity": "sha1-82WFNa9/H1AqzW2n2vQF/+sffuQ=", + "integrity": "sha512-PBHCvO98hNec9A491vBbh0ZNDOVxccwKL1u2pm6fs9oDgm7SEnw0lEHqHfjsYryDxnE3zaf7LvERWEXjOp1hig==", "dev": true }, "@types/sinon": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-2.3.7.tgz", - "integrity": "sha1-6Swv7TKX6uB4140doDKyZ4i0r4Y=", + "integrity": "sha512-w+LjztaZbgZWgt/y/VMP5BUAWLtSyoIJhXyW279hehLPyubDoBNwvhcj3WaSptcekuKYeTCVxrq60rdLc6ImJA==", "dev": true }, "@types/uuid": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.3.tgz", - "integrity": "sha1-EhrOJl9Vac5A9PbQ/3ijOMcyp1Q=", + "integrity": "sha512-5fRLCYhLtDb3hMWqQyH10qtF+Ud2JnNCXTCZ+9ktNdCcgslcuXkDTkFcJNk++MT29yDntDnlF1+jD+uVGumsbw==", "dev": true, "requires": { "@types/node": "6.0.92" @@ -100,7 +100,7 @@ "@types/xml2js": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.2.tgz", - "integrity": "sha1-pLhLOHn/1HEJU/2Syr/emopOhFY=", + "integrity": "sha512-8aKUBSj3oGcnuiBmDLm3BIk09RYg01mz9HlQ2u4aS17oJ25DxjQrEUVGFSBVNOfM45pQW4OjcBPplq6r/exJdA==", "dev": true, "requires": { "@types/node": "6.0.92" @@ -133,7 +133,7 @@ "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { "micromatch": "2.3.11", @@ -163,7 +163,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "array-differ": { @@ -187,7 +187,7 @@ "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true }, "array-union": { @@ -392,7 +392,7 @@ "chai-as-promised": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha1-CGRdgl3rhpbuYXJdv1kMAS6wDKA=", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "dev": true, "requires": { "check-error": "1.0.2" @@ -425,6 +425,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -436,7 +437,7 @@ "ci-info": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz", - "integrity": "sha1-A1YSWdtI0EdMi9yQ9bR7Botrv7Q=", + "integrity": "sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA==", "dev": true }, "clone": { @@ -477,7 +478,7 @@ "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { "color-name": "1.1.3" @@ -513,7 +514,7 @@ "commandpost": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.2.1.tgz", - "integrity": "sha1-LpxMdQi53HBK/vqpHKuS7mBUzGg=", + "integrity": "sha512-V1wzc+DTFsO96te2W/U+fKNRSOWtOwXhkkZH2WRLLbucrY+YrDNsRr4vtfSf83MUZVF3E6B4nwT30fqaTpzipQ==", "dev": true }, "concat-map": { @@ -613,7 +614,7 @@ "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { "type-detect": "4.0.5" @@ -696,7 +697,7 @@ "duplexify": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha1-ThUWvmiDi8kKSZlPCzmm5ZYL780=", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", "dev": true, "requires": { "end-of-stream": "1.4.0", @@ -732,7 +733,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -747,7 +748,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -768,7 +769,7 @@ "editorconfig": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.0.tgz", - "integrity": "sha1-tt1KC2ueds5I4Ga9wVOBrruIBP0=", + "integrity": "sha512-j7JBoj/bpNzvoTQylfRZSc85MlLNKWQiq5y6gwKhmqD2h1eZ+tH4AXbkhEJD468gjDna/XMx2YtSkCxBRX9OGg==", "dev": true, "requires": { "@types/commander": "2.12.2", @@ -782,13 +783,13 @@ "commander": { "version": "2.12.2", "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", "dev": true }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "dev": true, "requires": { "pseudomap": "1.0.2", @@ -1082,6 +1083,910 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", @@ -1412,7 +2317,7 @@ "gulp-filter": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", - "integrity": "sha1-XYf2YuMX5YOe92UOYg5skAj/ktA=", + "integrity": "sha512-5olRzAhFdXB2klCu1lnazP65aO9YdA/5WfC9VdInIc8PrUeDIoZfaA3Edb0yUBGhVdHv4eHKL9Fg5tUoEJ9z5A==", "dev": true, "requires": { "gulp-util": "3.0.8", @@ -1912,7 +2817,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -1927,7 +2832,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -2003,7 +2908,7 @@ "gulp-typescript": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.3.tgz", - "integrity": "sha1-MtUquXuXxM4HDAQZ2wjqOvUU1yA=", + "integrity": "sha512-Np2sJXgtDUwIAoMtlJ9uXsVmpu1FWXlKZw164hLuo56uJa7qo5W2KZ0yAYiYH/HUsaz5L0O2toMOcLIokpFCPg==", "dev": true, "requires": { "gulp-util": "3.0.8", @@ -2127,7 +3032,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -2142,7 +3047,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -2396,7 +3301,7 @@ "queue": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", - "integrity": "sha1-Wpcz2ai4vRs26TS8nFWribKOKcc=", + "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==", "dev": true, "requires": { "inherits": "2.0.3" @@ -2405,7 +3310,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -2426,7 +3331,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -2591,7 +3496,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -2606,7 +3511,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -2655,7 +3560,7 @@ "commander": { "version": "2.12.2", "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", "dev": true } } @@ -2737,7 +3642,7 @@ "husky": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz", - "integrity": "sha1-xp7XTi0neXaaF7qDmbVM4LY8EsM=", + "integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==", "dev": true, "requires": { "is-ci": "1.0.10", @@ -2762,7 +3667,7 @@ "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "indent-string": { "version": "2.1.0", @@ -2792,7 +3697,7 @@ "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, "interpret": { @@ -2804,7 +3709,7 @@ "inversify": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/inversify/-/inversify-4.5.2.tgz", - "integrity": "sha1-8keP0UDzmINrLh/ug583WI8eaps=" + "integrity": "sha512-nyXPqxMVdJDCbeq+eWSq5wEYvm6jlBNkBS+rMAXdxlEibAIXuzXXNgvETsP0MVcsWc4bAwUMhqr6X/5sUzNrFw==" }, "is": { "version": "3.2.1", @@ -2840,7 +3745,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-builtin-module": { @@ -2909,7 +3814,7 @@ "is-my-json-valid": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha1-WoRnd+LCYg0eaRBOXToDsfYIjxE=", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", "dev": true, "requires": { "generate-function": "2.0.0", @@ -2936,7 +3841,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { "isobject": "3.0.1" @@ -3182,7 +4087,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -3197,7 +4102,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -3681,7 +4586,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -3696,7 +4601,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -3743,7 +4648,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "1.1.8" } @@ -3853,7 +4758,14 @@ "named-js-regexp": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/named-js-regexp/-/named-js-regexp-1.3.3.tgz", - "integrity": "sha1-ousWVcdMuCITpPyCd337Z7iV2Mg=" + "integrity": "sha512-zIUAXzGQOp16VR0Ct89SDstU62hzAPBluNUrUrsdD7MNSRbm/vyqGhEnp+4hnsMjmX3C2wh1cbIEP0joKMFLxw==" + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true }, "native-promise-only": { "version": "0.8.1", @@ -4210,7 +5122,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, "requires": { "is-number": "3.0.0", @@ -4302,7 +5214,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -4317,7 +5229,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -4352,7 +5264,7 @@ "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { "is-equal-shallow": "0.1.3" @@ -4403,7 +5315,7 @@ "request": { "version": "2.83.0", "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", "dev": true, "requires": { "aws-sign2": "0.7.0", @@ -4469,7 +5381,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "dev": true, "requires": { "hoek": "4.2.0" @@ -4501,7 +5413,7 @@ "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "dev": true, "requires": { "boom": "4.3.1", @@ -4513,7 +5425,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", "dev": true }, "http-signature": { @@ -4530,13 +5442,13 @@ "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true }, "sntp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "dev": true, "requires": { "hoek": "4.2.0" @@ -4562,7 +5474,7 @@ "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", "dev": true, "requires": { "path-parse": "1.0.5" @@ -4587,7 +5499,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "7.1.2" @@ -4596,7 +5508,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -4612,7 +5524,7 @@ "rxjs": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.3.tgz", - "integrity": "sha1-tiIn50uE9Od730QOULXuAaG8fc0=", + "integrity": "sha512-VWockSz7xmDveeZ7wv8RvdipGGZ1NmL/m4jnpvN9BH4x1fW/TPoD23yXh+qDkbWSlajXVVfLIbGmyxa94Ls84w==", "requires": { "symbol-observable": "1.1.0" } @@ -4620,24 +5532,24 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, "samsam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha1-jR2TUOJWItow3j5EumkrUiGrfFA=", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=" + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, "sequencify": { "version": "0.0.7", @@ -4666,7 +5578,7 @@ "sinon": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", - "integrity": "sha1-Ah/WS1TLd9nS+w1Dze3652KcOjY=", + "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==", "dev": true, "requires": { "diff": "3.4.0", @@ -4682,7 +5594,7 @@ "diff": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "integrity": "sha1-sdhVB9rzlkgo3lSzfQ1zumfdpWw=", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", "dev": true } } @@ -4711,7 +5623,7 @@ "source-map-support": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", - "integrity": "sha1-IBinrSvfj68mkeX92rJr7VorrKs=", + "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", "dev": true, "requires": { "source-map": "0.6.1" @@ -4720,7 +5632,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } @@ -4815,7 +5727,7 @@ "streamfilter": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.6.tgz", - "integrity": "sha1-jQhxfKwHewg0yCYH0Pqbx3en/Lw=", + "integrity": "sha512-JM3zxd/lvOuo+EZJlZNYdQucfybA+Jr6jRtZwWlMAq1dAV0LIjZrqSNBBK62qCtflJ8rL/+cAnxy69CPhkTJNA==", "dev": true, "requires": { "readable-stream": "2.3.3" @@ -4830,7 +5742,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -4845,7 +5757,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -4918,7 +5830,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -4933,7 +5845,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -4968,7 +5880,7 @@ "symbol-observable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz", - "integrity": "sha1-XGj9jVQRXZ37cqhHIFSSIujbmzI=" + "integrity": "sha512-dQoid9tqQ+uotGhuTKEY11X4xhyYePVnqGSoSm3OGKh2E8LZ6RPULp1uXTctk33IeERlrRJYoVSBglsL05F5Uw==" }, "tar": { "version": "2.2.1", @@ -5012,7 +5924,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -5027,7 +5939,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -5095,7 +6007,7 @@ "tree-kill": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", - "integrity": "sha1-WEZ4Yje0I5AU8F2xVrZDIS1MbzY=" + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" }, "trim-newlines": { "version": "1.0.0", @@ -5106,7 +6018,7 @@ "tslib": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", - "integrity": "sha1-3GBOutZLy/aW1hPabJVKoOfqHrY=", + "integrity": "sha512-ymKWWZJST0/CkgduC2qkzjMOWr4bouhuURNXCn/inEX0L57BnRG6FhX76o7FOnsjHazCjfU2LKeSrlS2sIKQJg==", "dev": true }, "tslint": { @@ -5131,7 +6043,7 @@ "ansi-styles": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { "color-convert": "1.9.1" @@ -5140,7 +6052,7 @@ "chalk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { "ansi-styles": "3.2.0", @@ -5151,19 +6063,19 @@ "commander": { "version": "2.12.2", "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", "dev": true }, "diff": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "integrity": "sha1-sdhVB9rzlkgo3lSzfQ1zumfdpWw=", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", "dev": true }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -5224,7 +6136,7 @@ "tsutils": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.0.tgz", - "integrity": "sha1-D1K2qrvEIW5yeWtm2wKMbPFz4UQ=", + "integrity": "sha512-FuWzNJbMsp3gcZMbI3b5DomhW4Ia41vMxjN63nKWI0t7f+I3UmHfRl0TrXJTwI2LUduDG+eR1Mksp3pvtlyCFQ==", "dev": true, "requires": { "tslib": "1.8.0" @@ -5246,7 +6158,7 @@ "type-detect": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", - "integrity": "sha1-1w5byB223io4G8rKDG4MvcdjXeI=", + "integrity": "sha512-N9IvkQslUGYGC24RkJk1ba99foK6TkwC2FHAEBlQFBP0RxQZS8ZpJuAZcwiY/w9ZJHFQb1aOXBI60OdxhTrwEQ==", "dev": true }, "typescript": { @@ -5263,7 +6175,7 @@ "typescript-formatter": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-6.1.0.tgz", - "integrity": "sha1-RCWsK6uKrqmgQlHAePR6t6AgLxM=", + "integrity": "sha512-o2TJSBDSdua8yl8gXNJonM4jr4f7ZuLhsbG7zMG80iJluhE8MWI0R/mPzA3in3omwAJwkcbkc5Xxm74io/J7WA==", "dev": true, "requires": { "commandpost": "1.2.1", @@ -5300,7 +6212,7 @@ "url-parse": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha1-OhnoqqbQI93SfcxEy0/I9/7COYY=", + "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", "dev": true, "requires": { "querystringify": "1.0.0", @@ -5322,7 +6234,7 @@ "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", "dev": true }, "v8flags": { @@ -5534,7 +6446,7 @@ "vscode": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.9.tgz", - "integrity": "sha1-F87oj+YozQtTzNZ9PGeDyGY3sHQ=", + "integrity": "sha512-xhSh410NntYViiBYIPimAwF0U6NZgORtqQenlpTI/qKBGwHMtZSCJcL3/JIhfCw43HBXqPg59kA947OT3UvZKQ==", "dev": true, "requires": { "glob": "7.1.2", @@ -5556,13 +6468,13 @@ "commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -5571,13 +6483,13 @@ "diff": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha1-qoVnpu7QPFMfyJ0/cRzQ5SWd7HU=", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -5591,13 +6503,13 @@ "growl": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha1-GSa6kM8+3+KttJJ/WIC8IsZseQ8=", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", "dev": true }, "mocha": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", - "integrity": "sha1-Cu5alc9ppGGIIPXlH6MXFxF9rxs=", + "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==", "dev": true, "requires": { "browser-stdout": "1.3.0", @@ -5621,7 +6533,7 @@ "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { "has-flag": "2.0.0" @@ -5637,6 +6549,15 @@ "vscode-debugprotocol": "1.25.0" } }, + "vscode-debugadapter-testsupport": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.25.0.tgz", + "integrity": "sha512-6E2N7CoH7B0KEDvI9mFVFt4H+dRFDhtj3PmLVjNojfZ1VZZS2yfhE0XO0E5Axdhef3zTpUU6WZoeOOMVFGZGIg==", + "dev": true, + "requires": { + "vscode-debugprotocol": "1.25.0" + } + }, "vscode-debugprotocol": { "version": "1.25.0", "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0.tgz", @@ -5702,7 +6623,7 @@ "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { "isexe": "2.0.0" @@ -5722,7 +6643,7 @@ "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha1-aGwg8hMgnpSr8NG88e+qKRx4J6c=", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", "requires": { "sax": "1.2.4", "xmlbuilder": "9.0.4" diff --git a/package.json b/package.json index 9fa8ea10dfa5..149f6cbe2491 100644 --- a/package.json +++ b/package.json @@ -627,6 +627,16 @@ "type": "string", "description": "Absolute path to a file containing environment variable definitions.", "default": "" + }, + "port": { + "type": "number", + "description": "Debug port (default is 0, resulting in the use of a dynamic port).", + "default": 0 + }, + "host": { + "type": "string", + "description": "IP address of the of the local debug server (default is localhost).", + "default": "localhost" } } }, @@ -1321,6 +1331,12 @@ "description": "Port number used for debugging of unittests.", "scope": "resource" }, + "python.unitTest.debugHost": { + "type": "number", + "default": "localhost", + "description": "IP Address of the of the local unit test server (default is localhost or use 127.0.0.1).", + "scope": "resource" + }, "python.unitTest.cwd": { "type": "string", "default": null, @@ -1567,6 +1583,7 @@ "tslint-microsoft-contrib": "^5.0.1", "typescript": "^2.6.2", "typescript-formatter": "^6.0.0", - "vscode": "^1.1.5" + "vscode": "^1.1.5", + "vscode-debugadapter-testsupport": "^1.25.0" } } diff --git a/src/client/common/configSettings.ts b/src/client/common/configSettings.ts index bb1ad2d8445a..6899e248da85 100644 --- a/src/client/common/configSettings.ts +++ b/src/client/common/configSettings.ts @@ -36,6 +36,7 @@ export interface ISortImportSettings { export interface IUnitTestSettings { promptToConfigure: boolean; debugPort: number; + debugHost?: string; nosetestsEnabled: boolean; nosetestPath: string; nosetestArgs: string[]; diff --git a/src/client/common/net/socket/socketServer.ts b/src/client/common/net/socket/socketServer.ts index 24a139cb638a..698159acb3f4 100644 --- a/src/client/common/net/socket/socketServer.ts +++ b/src/client/common/net/socket/socketServer.ts @@ -1,38 +1,34 @@ -"use strict"; - -import * as net from "net"; import { EventEmitter } from 'events'; +import * as net from 'net'; import { createDeferred } from '../../helpers'; export class SocketServer extends EventEmitter { - private socketServer: net.Server = null; + private socketServer: net.Server | undefined; constructor() { super(); } public Stop() { - if (this.socketServer === null) { return; } + if (!this.socketServer) { return; } try { this.socketServer.close(); - } - catch (ex) { } - this.socketServer = null; + // tslint:disable-next-line:no-empty + } catch (ex) { } + this.socketServer = undefined; } - public Start(): Promise { + public Start(options: { port?: number, host?: string } = {}): Promise { const def = createDeferred(); this.socketServer = net.createServer(this.connectionListener.bind(this)); - this.socketServer.listen(0, function (this: SocketServer) { - def.resolve(this.socketServer.address().port); - }.bind(this)); + const port = typeof options.port === 'number' ? options.port! : 0; + const host = typeof options.host === 'string' ? options.host! : 'localhost'; + this.socketServer!.listen({ port, host }, () => { + def.resolve(this.socketServer!.address().port); + }); - this.socketServer.on("error", ex => { + this.socketServer!.on('error', ex => { console.error('Error in Socket Server', ex); - if (def.completed) { - // Ooops - debugger; - } const msg = `Failed to start the socket server. (Error: ${ex.message})`; def.reject(msg); @@ -41,14 +37,14 @@ export class SocketServer extends EventEmitter { } private connectionListener(client: net.Socket) { - client.on("close", function () { + client.on('close', () => { this.emit('close', client); - }.bind(this)); - client.on("data", function (data: Buffer) { + }); + client.on('data', (data: Buffer) => { this.emit('data', client, data); - }.bind(this)); + }); - client.on("timeout", d => { + client.on('timeout', d => { // let msg = "Debugger client timedout, " + d; }); } diff --git a/src/client/debugger/Common/Contracts.ts b/src/client/debugger/Common/Contracts.ts index e8c5635a064e..15fbc9b9dee4 100644 --- a/src/client/debugger/Common/Contracts.ts +++ b/src/client/debugger/Common/Contracts.ts @@ -1,8 +1,10 @@ -"use strict"; -import * as net from "net"; +// tslint:disable:interface-name member-access no-single-line-block-comment no-any no-stateless-class member-ordering prefer-method-signature + +'use strict'; import { ChildProcess } from 'child_process'; -import { DebugProtocol } from "vscode-debugprotocol"; -import { OutputEvent } from "vscode-debugadapter"; +import * as net from 'net'; +import { OutputEvent } from 'vscode-debugadapter'; +import { DebugProtocol } from 'vscode-debugprotocol'; export class TelemetryEvent extends OutputEvent { body: { @@ -14,25 +16,25 @@ export class TelemetryEvent extends OutputEvent { data?: any; }; constructor(output: string, data?: any) { - super(output, "telemetry"); + super(output, 'telemetry'); if (data) { this.body.data = data; } } } -export const DjangoApp = "DJANGO"; +export const DjangoApp = 'DJANGO'; export enum DebugFlags { None = 0, IgnoreCommandBursts = 1 } export class DebugOptions { - public static get WaitOnAbnormalExit(): string { return "WaitOnAbnormalExit"; } - public static get WaitOnNormalExit(): string { return "WaitOnNormalExit"; } - public static get RedirectOutput(): string { return "RedirectOutput"; } - public static get DjangoDebugging(): string { return "DjangoDebugging"; } - public static get DebugStdLib(): string { return "DebugStdLib"; } - public static get BreakOnSystemExitZero(): string { return "BreakOnSystemExitZero"; } + public static get WaitOnAbnormalExit(): string { return 'WaitOnAbnormalExit'; } + public static get WaitOnNormalExit(): string { return 'WaitOnNormalExit'; } + public static get RedirectOutput(): string { return 'RedirectOutput'; } + public static get DjangoDebugging(): string { return 'DjangoDebugging'; } + public static get DebugStdLib(): string { return 'DebugStdLib'; } + public static get BreakOnSystemExitZero(): string { return 'BreakOnSystemExitZero'; } } export interface ExceptionHandling { @@ -55,7 +57,9 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum env?: Object; envFile: string; exceptionHandling?: ExceptionHandling; - console?: "none" | "integratedTerminal" | "externalTerminal"; + console?: 'none' | 'integratedTerminal' | 'externalTerminal'; + port?: number; + host?: string; } export interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments { @@ -76,7 +80,8 @@ export enum FrameKind { None, Python, Django -}; +} + export enum enum_EXCEPTION_STATE { BREAK_MODE_NEVER = 0, BREAK_MODE_ALWAYS = 1, @@ -99,7 +104,7 @@ export enum PythonEvaluationResultFlags { MethodCall = 2, SideEffects = 4, Raw = 8, - HasRawRepr = 16, + HasRawRepr = 16 } export interface IPythonProcess extends NodeJS.EventEmitter { @@ -138,14 +143,12 @@ export interface IPythonEvaluationResult { Frame: IPythonStackFrame; } - export interface IPythonModule { ModuleId: number; Name: string; Filename: string; } - export interface IPythonThread { IsWorkerThread: boolean; Process: IPythonProcess; diff --git a/src/client/debugger/DebugClients/LocalDebugClient.ts b/src/client/debugger/DebugClients/LocalDebugClient.ts index a402aad899f2..b0ac770c5c5e 100644 --- a/src/client/debugger/DebugClients/LocalDebugClient.ts +++ b/src/client/debugger/DebugClients/LocalDebugClient.ts @@ -46,7 +46,7 @@ export class LocalDebugClient extends DebugClient { public CreateDebugServer(pythonProcess: IPythonProcess): BaseDebugServer { this.pythonProcess = pythonProcess; - this.debugServer = new LocalDebugServer(this.debugSession, this.pythonProcess); + this.debugServer = new LocalDebugServer(this.debugSession, this.pythonProcess, this.args); return this.debugServer; } diff --git a/src/client/debugger/DebugServers/DebugServerFactory.ts b/src/client/debugger/DebugServers/DebugServerFactory.ts index a5e2fa4e2690..a400ce58296a 100644 --- a/src/client/debugger/DebugServers/DebugServerFactory.ts +++ b/src/client/debugger/DebugServers/DebugServerFactory.ts @@ -1,9 +1,8 @@ -import {BaseDebugServer} from "./BaseDebugServer"; -import {LocalDebugServer} from "./LocalDebugServer"; -import {RemoteDebugServer} from "./RemoteDebugServer"; -import {DebugSession, OutputEvent} from "vscode-debugadapter"; -import {IPythonProcess, IDebugServer} from "../Common/Contracts"; +import { DebugSession } from 'vscode-debugadapter'; +import { IPythonProcess, LaunchRequestArguments } from '../Common/Contracts'; +import { BaseDebugServer } from './BaseDebugServer'; +import { LocalDebugServer } from './LocalDebugServer'; -export function CreateDebugServer(debugSession: DebugSession, pythonProcess: IPythonProcess): BaseDebugServer { - return new LocalDebugServer(debugSession, pythonProcess); +export function CreateDebugServer(debugSession: DebugSession, pythonProcess: IPythonProcess, args: LaunchRequestArguments): BaseDebugServer { + return new LocalDebugServer(debugSession, pythonProcess, args); } diff --git a/src/client/debugger/DebugServers/LocalDebugServer.ts b/src/client/debugger/DebugServers/LocalDebugServer.ts index f2eccd65e593..6fb9cae1c83d 100644 --- a/src/client/debugger/DebugServers/LocalDebugServer.ts +++ b/src/client/debugger/DebugServers/LocalDebugServer.ts @@ -3,23 +3,23 @@ import * as net from 'net'; import { EOL } from 'os'; import { DebugSession, OutputEvent } from 'vscode-debugadapter'; -import { IDebugServer, IPythonProcess } from '../Common/Contracts'; +import { IDebugServer, IPythonProcess, LaunchRequestArguments } from '../Common/Contracts'; import { BaseDebugServer } from './BaseDebugServer'; export class LocalDebugServer extends BaseDebugServer { - private debugSocketServer: net.Server = null; + private debugSocketServer: net.Server | undefined; - constructor(debugSession: DebugSession, pythonProcess: IPythonProcess) { + constructor(debugSession: DebugSession, pythonProcess: IPythonProcess, private args: LaunchRequestArguments) { super(debugSession, pythonProcess); } public Stop() { - if (this.debugSocketServer === null) { return; } + if (!this.debugSocketServer) { return; } try { this.debugSocketServer.close(); // tslint:disable-next-line:no-empty } catch { } - this.debugSocketServer = null; + this.debugSocketServer = undefined; } public async Start(): Promise { @@ -61,7 +61,7 @@ export class LocalDebugServer extends BaseDebugServer { reject(msg); }); }); - this.debugSocketServer.on('error', ex => { + this.debugSocketServer!.on('error', ex => { const exMessage = JSON.stringify(ex); let msg = ''; // tslint:disable-next-line:no-any @@ -77,8 +77,10 @@ export class LocalDebugServer extends BaseDebugServer { reject(msg); }); - this.debugSocketServer.listen(0, () => { - const server = this.debugSocketServer.address(); + const port = typeof this.args.port === 'number' ? this.args.port! : 0; + const host = typeof this.args.host === 'string' && this.args.host.trim().length > 0 ? this.args.host!.trim() : 'localhost'; + this.debugSocketServer!.listen({ port, host }, () => { + const server = this.debugSocketServer!.address(); resolve({ port: server.port }); }); }); diff --git a/src/client/jedi/commands.ts b/src/client/jedi/commands.ts deleted file mode 100644 index 347adbc9272f..000000000000 --- a/src/client/jedi/commands.ts +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -export class RequestCommands { - public static Exit: Buffer = new Buffer("exit"); - public static Ping: Buffer = new Buffer("ping"); - public static Arguments = new Buffer("args"); - public static Completions = new Buffer("comp"); - public static Definitions = new Buffer("defs"); - public static Hover = new Buffer("hovr"); - public static Usages = new Buffer("usag"); - public static Names = new Buffer("name"); -} - -export namespace ResponseCommands { - export const Pong = 'pong'; - export const TraceLog = 'tlog'; - export const Error = 'eror'; - export const Signature = "args"; - export const Completions = "comp"; - export const Definitions = "defs"; - export const Hover = "hovr"; - export const References = "usag"; - export const DocumentSymbols = "name"; -} \ No newline at end of file diff --git a/src/client/jedi/main.ts b/src/client/jedi/main.ts deleted file mode 100644 index 2a4d287831cb..000000000000 --- a/src/client/jedi/main.ts +++ /dev/null @@ -1,137 +0,0 @@ -"use strict"; - -import * as child_process from 'child_process'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { SocketClient } from './socketClient'; -import { SocketServer } from '../common/net/socket/socketServer'; -import { createDeferred, Deferred } from '../common/helpers'; -import { PythonSettings } from '../common/configSettings'; -import { EventEmitter } from 'events'; -import { CancellationToken } from 'vscode'; -import { RequestCommands } from "./commands"; - -export enum Command { - Completions, - Definition, - Hover, - References, - Signature, - DocumentSymbols -} - -const commandMapping = new Map(); -commandMapping.set(Command.Completions, RequestCommands.Completions); -commandMapping.set(Command.Definition, RequestCommands.Definitions); -commandMapping.set(Command.Hover, RequestCommands.Hover); -commandMapping.set(Command.References, RequestCommands.Usages); -commandMapping.set(Command.Signature, RequestCommands.Arguments); -commandMapping.set(Command.DocumentSymbols, RequestCommands.Names); - -export class ClientAdapter extends EventEmitter { - constructor(private outputChannel: vscode.OutputChannel, private rootDir: string) { - super(); - } - public getResult(responseParser: (data: Object) => T, command: Command, token: CancellationToken, fileName: string, columnIndex?: number, lineIndex?: number, source?: string): Promise { - const cmd = commandMapping.get(command); - return this.socketClient.getResult(cmd, token, fileName, columnIndex, lineIndex, source) - .then(responseParser); - } - private process: child_process.ChildProcess; - private socketServer: SocketServer; - private socketClient: SocketClient; - - private startDef: Deferred; - - public dispose() { - try { - if (this.process) { - this.process.stdin.write('\n'); - } - } - catch (ex) { - } - try { - this.socketClient.dispose(); - } - catch (ex) { - } - try { - this.socketServer.Stop(); - } - catch (ex) { - } - this.socketClient = null; - this.process = null; - this.socketServer = null; - this.startDef = null; - } - public start(envVariables?: { [key: string]: string }): Promise { - if (this.startDef) { - return this.startDef.promise; - } - - this.startDef = createDeferred(); - const pyFile = path.join(__dirname, '..', '..', '..', '..', 'pythonFiles', 'completionServer.py'); - const newEnv = {}; - Object.assign(newEnv, envVariables); - Object.assign(newEnv, process.env); - - this.startSocketServer().then(port => { - const def = createDeferred(); - const options = { env: newEnv, cwd: this.rootDir }; - const rootDirUri = this.rootDir ? vscode.Uri.file(this.rootDir) : undefined; - this.process = child_process.spawn(PythonSettings.getInstance(rootDirUri).pythonPath, [pyFile, port.toString()], options); - this.process.stdout.setEncoding('utf8'); - this.process.stderr.setEncoding('utf8'); - - let processStarted = false; - let handshakeDone = false; - - this.process.stdout.on('data', (data: string) => { - if (!processStarted && data.split(/\r?\n/g).some(line => line === 'Started')) { - processStarted = true; - if (processStarted && handshakeDone) { - def.resolve(); - } - return; - } - this.outputChannel.append(data); - }); - this.process.stderr.on('data', (data: string) => { - this.outputChannel.append(data); - }); - - this.socketClient.on('handshake', () => { - handshakeDone = true; - if (processStarted && handshakeDone) { - def.resolve(); - } - }); - - return def.promise; - }).then(() => { - this.startDef.resolve(); - }).catch(reason => { - this.startDef.reject(reason); - }); - - return this.startDef.promise; - } - private startSocketServer(): Promise { - this.socketServer = new SocketServer(); - this.socketClient = new SocketClient(this.socketServer, this.outputChannel); - this.socketClient.on('status', status => { - this.emit('status', status); - }); - this.socketClient.on('error', error => { - this.emit('error', error); - console.error(error); - this.outputChannel.appendLine('Error received: ' + error); - }); - this.socketClient.on('commanderror', (commandError: { command: string, id: string, trace: string }) => { - this.outputChannel.appendLine(`Unhandled command Error from Autocompletion Library. '${JSON.stringify(commandError)}'`); - }); - return this.socketServer.Start(); - } -} diff --git a/src/client/jedi/parsers/DefinitionParser.ts b/src/client/jedi/parsers/DefinitionParser.ts deleted file mode 100644 index 6b70545e48df..000000000000 --- a/src/client/jedi/parsers/DefinitionParser.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Definition, Location, Range, Uri } from 'vscode'; -import * as proxy from '../../providers/jediProxy'; -export class DefinitionParser { - public static parse(data: proxy.IDefinitionResult, possibleWord: string): Definition { - if (!data || !Array.isArray(data.definitions) || data.definitions.length === 0) { - return null; - } - const definitions = data.definitions.filter(d => d.text === possibleWord); - const definition = definitions.length > 0 ? definitions[0] : data.definitions[data.definitions.length - 1]; - const definitionResource = Uri.file(definition.fileName); - const range = new Range( - definition.range.startLine, definition.range.startColumn, - definition.range.endLine, definition.range.endColumn); - return new Location(definitionResource, range); - } -} \ No newline at end of file diff --git a/src/client/jedi/parsers/LocationParser.ts b/src/client/jedi/parsers/LocationParser.ts deleted file mode 100644 index a118e77900d6..000000000000 --- a/src/client/jedi/parsers/LocationParser.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Location, Range, Uri } from 'vscode'; -import * as proxy from '../../providers/jediProxy'; -export class LocationParser { - public static parse(data: proxy.IReferenceResult): Location[] { - if (!data || !Array(data.references) || data.references.length === 0) { - return []; - } - var references = data.references.filter(ref => { - if (!ref || typeof ref.columnIndex !== 'number' || typeof ref.lineIndex !== 'number' - || typeof ref.fileName !== 'string' || ref.columnIndex === -1 || ref.lineIndex === -1 || ref.fileName.length === 0) { - return false; - } - return true; - }).map(ref => { - var definitionResource = Uri.file(ref.fileName); - - var range = new Range(ref.lineIndex, ref.columnIndex, ref.lineIndex, ref.columnIndex); - return new Location(definitionResource, range); - }); - - return references; - } -} diff --git a/src/client/jedi/parsers/SignatureHelpParser.ts b/src/client/jedi/parsers/SignatureHelpParser.ts deleted file mode 100644 index f1993bf59322..000000000000 --- a/src/client/jedi/parsers/SignatureHelpParser.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { SignatureHelp } from 'vscode'; -import * as vscode from "vscode"; -import * as proxy from "../../providers/jediProxy"; - -const DOCSTRING_PARAM_PATTERNS = [ - "\\s*:type\\s*PARAMNAME:\\s*([^\\n, ]+)", // Sphinx - "\\s*:param\\s*(\\w?)\\s*PARAMNAME:[^\\n]+", // Sphinx param with type - "\\s*@type\\s*PARAMNAME:\\s*([^\\n, ]+)" // Epydoc -]; - -/** - * Extrct the documentation for parameters from a given docstring - * - * @param {string} paramName Name of the parameter - * @param {string} docString The docstring for the function - * @returns {string} Docstring for the parameter - */ -function extractParamDocString(paramName: string, docString: string): string { - let paramDocString = ""; - // In docstring the '*' is escaped with a backslash - paramName = paramName.replace(new RegExp("\\*", "g"), "\\\\\\*"); - - DOCSTRING_PARAM_PATTERNS.forEach(pattern => { - if (paramDocString.length > 0) { - return; - } - pattern = pattern.replace("PARAMNAME", paramName); - let regExp = new RegExp(pattern); - let matches = regExp.exec(docString); - if (matches && matches.length > 0) { - paramDocString = matches[0]; - if (paramDocString.indexOf(":") >= 0) { - paramDocString = paramDocString.substring(paramDocString.indexOf(":") + 1); - } - if (paramDocString.indexOf(":") >= 0) { - paramDocString = paramDocString.substring(paramDocString.indexOf(":") + 1); - } - } - }); - - return paramDocString.trim(); -} -export class SignatureHelpParser { - public static parse(data: proxy.IArgumentsResult): SignatureHelp { - if (!data || !Array.isArray(data.definitions) || data.definitions.length === 0) { - return new SignatureHelp(); - } - let signature = new SignatureHelp(); - signature.activeSignature = 0; - - data.definitions.forEach(def => { - signature.activeParameter = def.paramindex; - // Don't display the documentation, as vs code doesn't format the docmentation - // i.e. line feeds are not respected, long content is stripped - let sig = { - // documentation: def.docstring, - label: def.description, - parameters: [] - }; - sig.parameters = def.params.map(arg => { - if (arg.docstring.length === 0) { - arg.docstring = extractParamDocString(arg.name, def.docstring); - } - return { - documentation: arg.docstring.length > 0 ? arg.docstring : arg.description, - label: arg.description.length > 0 ? arg.description : arg.name - }; - }); - signature.signatures.push(sig); - }); - return signature; - } -} \ No newline at end of file diff --git a/src/client/jedi/parsers/SymbolInformationParser.ts b/src/client/jedi/parsers/SymbolInformationParser.ts deleted file mode 100644 index 6be8ea17c35d..000000000000 --- a/src/client/jedi/parsers/SymbolInformationParser.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { SymbolInformation, TextDocument, Range, Uri, Location } from 'vscode'; -import * as proxy from "../../providers/jediProxy"; -export class SymbolInformationParser { - public static parse(data: proxy.ISymbolResult, document: TextDocument): SymbolInformation[] { - if (!data || !Array.isArray(data.definitions) || data.definitions.length === 0) { - return []; - } - let symbols = data.definitions.filter(sym => sym.fileName === document.fileName); - return symbols.map(sym => { - const symbol = sym.kind; - const range = new Range( - sym.range.startLine, sym.range.startColumn, - sym.range.endLine, sym.range.endColumn); - const uri = Uri.file(sym.fileName); - const location = new Location(uri, range); - return new SymbolInformation(sym.text, symbol, sym.container, location); - }); - } -} \ No newline at end of file diff --git a/src/client/jedi/socketClient.ts b/src/client/jedi/socketClient.ts deleted file mode 100644 index 26b807c78f61..000000000000 --- a/src/client/jedi/socketClient.ts +++ /dev/null @@ -1,141 +0,0 @@ -"use strict"; - -import { SocketCallbackHandler } from "../common/net/socket/socketCallbackHandler"; -import { RequestCommands, ResponseCommands } from "./commands"; -import { SocketServer } from '../common/net/socket/socketServer'; -import { IdDispenser } from '../common/idDispenser'; -import { createDeferred, Deferred } from '../common/helpers'; -import { OutputChannel, CancellationToken } from 'vscode'; - -export class SocketClient extends SocketCallbackHandler { - constructor(socketServer: SocketServer, private outputChannel: OutputChannel) { - super(socketServer); - this.registerCommandHandler(ResponseCommands.Pong, this.onPong.bind(this)); - this.registerCommandHandler(ResponseCommands.Error, this.onError.bind(this)); - this.registerCommandHandler(ResponseCommands.TraceLog, this.onWriteToLog.bind(this)); - - this.registerCommandHandler(ResponseCommands.Signature, this.onResponseReceived.bind(this)); - this.registerCommandHandler(ResponseCommands.Completions, this.onResponseReceived.bind(this)); - this.registerCommandHandler(ResponseCommands.Definitions, this.onResponseReceived.bind(this)); - this.registerCommandHandler(ResponseCommands.Hover, this.onResponseReceived.bind(this)); - this.registerCommandHandler(ResponseCommands.DocumentSymbols, this.onResponseReceived.bind(this)); - this.registerCommandHandler(ResponseCommands.References, this.onResponseReceived.bind(this)); - - this.idDispenser = new IdDispenser(); - } - public getResult(command: Buffer, token: CancellationToken, fileName: string, columnIndex: number, lineIndex: number, source: string): Promise { - - const [def, id] = this.createId(token); - this.SendRawCommand(command); - this.stream.WriteString(id); - - this.stream.WriteString(fileName); - this.stream.WriteInt32(columnIndex); - this.stream.WriteInt32(lineIndex); - this.stream.WriteString(source || ''); - - return def.promise; - } - private idDispenser: IdDispenser; - private pid: number; - public dispose() { - super.dispose(); - } - protected handleHandshake(): boolean { - if (typeof this.pid !== 'number') { - this.pid = this.stream.readInt32InTransaction(); - if (typeof this.pid !== 'number') { - return false; - } - } - - this.emit('handshake'); - return true; - } - - private pendingCommands = new Map>(); - - private createId(token?: CancellationToken): [Deferred, string] { - const def = createDeferred(); - const id = this.idDispenser.Allocate().toString(); - this.pendingCommands.set(id, def); - if (token) { - token.onCancellationRequested(() => { - this.releaseId(id); - }); - } - return [def, id]; - } - private releaseId(id: string) { - this.pendingCommands.delete(id); - this.idDispenser.Free(parseInt(id)); - } - private onResponseReceived() { - const id = this.stream.readStringInTransaction(); - const responseStr = this.stream.readStringInTransaction(); - if (typeof responseStr !== 'string') { - return; - } - - if (!this.pendingCommands.has(id)) { - return; - } - const def = this.pendingCommands.get(id); - this.releaseId(id); - - let jsonResponse: {}; - try { - jsonResponse = JSON.parse(responseStr); - } - catch (ex) { - def.reject(ex); - return; - } - - def.resolve(jsonResponse); - } - private onWriteToLog() { - const message = this.stream.readStringInTransaction(); - if (typeof message !== 'string') { - return; - } - this.outputChannel.appendLine(message); - } - - public ping(message: string) { - const [def, id] = this.createId(null); - this.SendRawCommand(RequestCommands.Ping); - this.stream.WriteString(id); - this.stream.WriteString(message); - return def.promise; - } - - private onPong() { - const id = this.stream.readStringInTransaction(); - const message = this.stream.readStringInTransaction(); - if (typeof message !== 'string') { - return; - } - const def = this.pendingCommands.get(id); - this.releaseId(id); - def.resolve(message); - } - private onError() { - const cmd = this.stream.readStringInTransaction(); - const id = this.stream.readStringInTransaction(); - const trace = this.stream.readStringInTransaction(); - if (typeof trace !== 'string') { - return; - } - if (cmd === 'exit') { - return; - } - if (id.length > 0 && this.pendingCommands.has(id)) { - const def = this.pendingCommands.get(id); - this.pendingCommands.delete(id); - def.reject(new Error(`Command: ${cmd}, Id: ${id}, Python Trace: ${trace}`)); - return; - } - this.emit("commanderror", { command: cmd, id: id, trace: trace }); - } -} diff --git a/src/client/unittests/common/debugLauncher.ts b/src/client/unittests/common/debugLauncher.ts index 4e408a51fa34..dfaea804e64f 100644 --- a/src/client/unittests/common/debugLauncher.ts +++ b/src/client/unittests/common/debugLauncher.ts @@ -13,10 +13,11 @@ const HAND_SHAKE = `READY${os.EOL}`; @injectable() export class DebugLauncher implements ITestDebugLauncher { constructor( @inject(IPythonExecutionFactory) private pythonExecutionFactory: IPythonExecutionFactory) { } - public getPort(resource?: Uri): Promise { + public async getLaunchOptions(resource?: Uri): Promise<{ port: number, host: string }> { const pythonSettings = PythonSettings.getInstance(resource); - const port = pythonSettings.unitTest.debugPort; - return new Promise((resolve, reject) => getFreePort({ host: 'localhost', port }).then(resolve, reject)); + const port = await getFreePort({ host: 'localhost', port: pythonSettings.unitTest.debugPort }); + const host = typeof pythonSettings.unitTest.debugHost === 'string' && pythonSettings.unitTest.debugHost.trim().length > 0 ? pythonSettings.unitTest.debugHost.trim() : 'localhost'; + return { port, host }; } public async launchDebugger(options: launchOptions) { const cwdUri = options.cwd ? Uri.file(options.cwd) : undefined; @@ -75,7 +76,7 @@ export class DebugLauncher implements ITestDebugLauncher { remoteRoot: options.cwd, port: options.port, secret: 'my_secret', - host: 'localhost' + host: options.host }); }) .catch(reason => { diff --git a/src/client/unittests/common/types.ts b/src/client/unittests/common/types.ts index 53d7335a3255..5e939486c96a 100644 --- a/src/client/unittests/common/types.ts +++ b/src/client/unittests/common/types.ts @@ -190,12 +190,13 @@ export type launchOptions = { token?: CancellationToken; outChannel?: OutputChannel; port: number; + host: string; }; export const ITestDebugLauncher = Symbol('ITestDebugLauncher'); export interface ITestDebugLauncher { - getPort(resource?: Uri): Promise; + getLaunchOptions(resource?: Uri): Promise<{ port: number, host: string }>; launchDebugger(options: launchOptions): Promise; } @@ -240,6 +241,6 @@ export type ParserOptions = TestDiscoveryOptions; export const IUnitTestSocketServer = Symbol('IUnitTestSocketServer'); export interface IUnitTestSocketServer extends Disposable { on(event: string | symbol, listener: Function): this; - start(): Promise; + start(options?: { port?: number, host?: string }): Promise; stop(): void; } diff --git a/src/client/unittests/nosetest/runner.ts b/src/client/unittests/nosetest/runner.ts index 5afdb0d8e507..e7c384f21af9 100644 --- a/src/client/unittests/nosetest/runner.ts +++ b/src/client/unittests/nosetest/runner.ts @@ -59,12 +59,12 @@ export function runTest(serviceContainer: IServiceContainer, testResultsService: return promiseToGetXmlLogFile.then(() => { if (options.debug === true) { const debugLauncher = serviceContainer.get(ITestDebugLauncher); - return debugLauncher.getPort(options.workspaceFolder) - .then(debugPort => { + return debugLauncher.getLaunchOptions(options.workspaceFolder) + .then(debugPortAndHost => { const testLauncherFile = path.join(__dirname, '..', '..', '..', '..', 'pythonFiles', 'PythonTools', 'testlauncher.py'); - const nosetestlauncherargs = [options.cwd, 'my_secret', debugPort.toString(), 'nose']; + const nosetestlauncherargs = [options.cwd, 'my_secret', debugPortAndHost.port.toString(), 'nose']; const debuggerArgs = [testLauncherFile].concat(nosetestlauncherargs).concat(noseTestArgs.concat(testPaths)); - const launchOptions = { cwd: options.cwd, args: debuggerArgs, token: options.token, outChannel: options.outChannel, port: debugPort }; + const launchOptions = { cwd: options.cwd, args: debuggerArgs, token: options.token, outChannel: options.outChannel, port: debugPortAndHost.port, host: debugPortAndHost.host }; // tslint:disable-next-line:prefer-type-cast no-any return debugLauncher.launchDebugger(launchOptions) as Promise; }); diff --git a/src/client/unittests/pytest/runner.ts b/src/client/unittests/pytest/runner.ts index 408e297d392d..0bfe9ae8209d 100644 --- a/src/client/unittests/pytest/runner.ts +++ b/src/client/unittests/pytest/runner.ts @@ -35,12 +35,12 @@ export function runTest(serviceContainer: IServiceContainer, testResultsService: const testArgs = testPaths.concat(args, [`--junitxml=${xmlLogFile}`]); if (options.debug) { const debugLauncher = serviceContainer.get(ITestDebugLauncher); - return debugLauncher.getPort(options.workspaceFolder) - .then(debugPort => { + return debugLauncher.getLaunchOptions(options.workspaceFolder) + .then(debugPortAndHost => { const testLauncherFile = path.join(__dirname, '..', '..', '..', '..', 'pythonFiles', 'PythonTools', 'testlauncher.py'); - const pytestlauncherargs = [options.cwd, 'my_secret', debugPort.toString(), 'pytest']; + const pytestlauncherargs = [options.cwd, 'my_secret', debugPortAndHost.port.toString(), 'pytest']; const debuggerArgs = [testLauncherFile].concat(pytestlauncherargs).concat(testArgs); - const launchOptions = { cwd: options.cwd, args: debuggerArgs, token: options.token, outChannel: options.outChannel, port: debugPort }; + const launchOptions = { cwd: options.cwd, args: debuggerArgs, token: options.token, outChannel: options.outChannel, port: debugPortAndHost.port, host: debugPortAndHost.host }; // tslint:disable-next-line:prefer-type-cast no-any return debugLauncher.launchDebugger(launchOptions) as Promise; }); diff --git a/src/client/unittests/unittest/runner.ts b/src/client/unittests/unittest/runner.ts index c848c42e0b82..671cdb4c2d53 100644 --- a/src/client/unittests/unittest/runner.ts +++ b/src/client/unittests/unittest/runner.ts @@ -28,7 +28,7 @@ interface ITestData { } // tslint:disable-next-line:max-func-body-length -export function runTest(serviceContainer: IServiceContainer, testManager: BaseTestManager, testResultsService: ITestResultsService, options: TestRunOptions): Promise { +export async function runTest(serviceContainer: IServiceContainer, testManager: BaseTestManager, testResultsService: ITestResultsService, options: TestRunOptions): Promise { options.tests.summary.errors = 0; options.tests.summary.failures = 0; options.tests.summary.passed = 0; @@ -93,10 +93,10 @@ export function runTest(serviceContainer: IServiceContainer, testManager: BaseTe } if (options.debug === true) { const debugLauncher = serviceContainer.get(ITestDebugLauncher); - return debugLauncher.getPort(options.workspaceFolder) - .then(debugPort => { - testArgs.push(...['--secret=my_secret', `--port=${debugPort}`]); - const launchOptions = { cwd: options.cwd, args: [testLauncherFile].concat(testArgs), token: options.token, outChannel: options.outChannel, port: debugPort }; + return debugLauncher.getLaunchOptions(options.workspaceFolder) + .then(debugPortAndHost => { + testArgs.push(...['--secret=my_secret', `--port=${debugPortAndHost.port}`]); + const launchOptions = { cwd: options.cwd, args: [testLauncherFile].concat(testArgs), token: options.token, outChannel: options.outChannel, port: debugPortAndHost.port, host: debugPortAndHost.host }; // tslint:disable-next-line:prefer-type-cast no-any return debugLauncher.launchDebugger(launchOptions); }); @@ -149,7 +149,6 @@ export function runTest(serviceContainer: IServiceContainer, testManager: BaseTe return Promise.reject(reason); }); } - function getStartDirectory(args: string[]): string { let startDirectory = '.'; const indexOfStartDir = args.findIndex(arg => arg.indexOf('-s') === 0 || arg.indexOf('--start-directory') === 0); diff --git a/src/client/unittests/unittest/socketServer.ts b/src/client/unittests/unittest/socketServer.ts index 7357ab1e6eb9..da83a350e61a 100644 --- a/src/client/unittests/unittest/socketServer.ts +++ b/src/client/unittests/unittest/socketServer.ts @@ -1,37 +1,21 @@ 'use strict'; import { EventEmitter } from 'events'; -import * as fs from 'fs'; import { injectable } from 'inversify'; import * as net from 'net'; -import * as os from 'os'; import { createDeferred, Deferred } from '../../common/helpers'; import { IUnitTestSocketServer } from '../common/types'; // tslint:disable-next-line:variable-name const MaxConnections = 100; -function getIPType() { - const networkInterfaces = os.networkInterfaces(); - // tslint:disable-next-line:variable-name - let IPType = ''; - // tslint:disable-next-line:prefer-type-cast no-any - if (networkInterfaces && Array.isArray(networkInterfaces) && (networkInterfaces as any).length > 0) { - // getting the family of first network interface available - IPType = networkInterfaces[Object.keys(networkInterfaces)[0]][0].family; - } - return IPType; -} - @injectable() export class UnitTestSocketServer extends EventEmitter implements IUnitTestSocketServer { private server?: net.Server; private startedDef?: Deferred; - private path: string; private sockets: net.Socket[] = []; private ipcBuffer: string = ''; constructor() { super(); - this.path = (getIPType() === 'IPv6') ? '::1' : '127.0.0.1'; } public get clientsConnected(): boolean { return this.sockets.length > 0; @@ -45,24 +29,24 @@ export class UnitTestSocketServer extends EventEmitter implements IUnitTestSocke this.server = undefined; } } - public start(): Promise { + public start(options: { port?: number, host?: string } = { port: 0, host: 'localhost' }): Promise { this.startedDef = createDeferred(); - fs.unlink(this.path, () => { - this.server = net.createServer(this.connectionListener.bind(this)); - this.server!.maxConnections = MaxConnections; - this.server!.on('error', (err) => { - if (this.startedDef) { - this.startedDef.reject(err); - this.startedDef = undefined; - } - this.emit('error', err); - }); - this.log('starting server as', 'TCP'); - this.server!.listen(0, this.path, (socket: net.Socket) => { - this.startedDef!.resolve(this.server!.address().port); + this.server = net.createServer(this.connectionListener.bind(this)); + this.server!.maxConnections = MaxConnections; + this.server!.on('error', (err) => { + if (this.startedDef) { + this.startedDef.reject(err); this.startedDef = undefined; - this.emit('start', socket); - }); + } + this.emit('error', err); + }); + this.log('starting server as', 'TCP'); + options.port = typeof options.port === 'number' ? options.port! : 0; + options.host = typeof options.host === 'string' && options.host!.trim().length > 0 ? options.host!.trim() : 'localhost'; + this.server!.listen(options, (socket: net.Socket) => { + this.startedDef!.resolve(this.server!.address().port); + this.startedDef = undefined; + this.emit('start', socket); }); return this.startedDef!.promise; } diff --git a/src/test/common/socketCallbackHandler.test.ts b/src/test/common/socketCallbackHandler.test.ts index 217f11822aa6..b9784a356289 100644 --- a/src/test/common/socketCallbackHandler.test.ts +++ b/src/test/common/socketCallbackHandler.test.ts @@ -1,30 +1,21 @@ -// -// Note: This example test is leveraging the Mocha test framework. -// Please refer to their documentation on https://mochajs.org/ for help. -// - -// Place this right on top -import { initialize } from './../initialize'; -// The module 'assert' provides assertion methods from node -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -import { SocketStream } from '../../client/common/net/socket/SocketStream'; -import { SocketServer } from '../../client/common/net/socket/socketServer'; -import { SocketCallbackHandler } from '../../client/common/net/socket/socketCallbackHandler'; -import { createDeferred, Deferred } from '../../client/common/helpers'; -import { IdDispenser } from '../../client/common/idDispenser'; +// tslint:disable:member-ordering no-any max-classes-per-file max-func-body-length +import * as assert from 'assert'; +import * as getFreePort from 'get-port'; import * as net from 'net'; +import { createDeferred, Deferred } from '../../client/common/helpers'; +import { SocketCallbackHandler } from '../../client/common/net/socket/socketCallbackHandler'; +import { SocketServer } from '../../client/common/net/socket/socketServer'; +import { SocketStream } from '../../client/common/net/socket/SocketStream'; -const uint64be = require("uint64be"); - +// tslint:disable-next-line:no-require-imports no-var-requires +const uint64be = require('uint64be'); +// tslint:disable-next-line:no-stateless-class class Commands { - public static ExitCommandBytes: Buffer = new Buffer("exit"); - public static PingBytes: Buffer = new Buffer("ping"); - public static ListKernelsBytes: Buffer = new Buffer("lstk"); + public static ExitCommandBytes: Buffer = new Buffer('exit'); + public static PingBytes: Buffer = new Buffer('ping'); + public static ListKernelsBytes: Buffer = new Buffer('lstk'); } namespace ResponseCommands { @@ -37,35 +28,33 @@ const GUID = 'This is the Guid'; const PID = 1234; class MockSocketCallbackHandler extends SocketCallbackHandler { - private idDispenser: IdDispenser; constructor(socketServer: SocketServer) { super(socketServer); this.registerCommandHandler(ResponseCommands.Pong, this.onPong.bind(this)); this.registerCommandHandler(ResponseCommands.Error, this.onError.bind(this)); - this.idDispenser = new IdDispenser(); } private onError() { const message = this.stream.readStringInTransaction(); - if (message == undefined) { + if (message === undefined) { return; } - this.emit("error", '', '', message); + this.emit('error', '', '', message); } public ping(message: string) { this.SendRawCommand(Commands.PingBytes); const stringBuffer = new Buffer(message); - let buffer = Buffer.concat([Buffer.concat([new Buffer('U'), uint64be.encode(stringBuffer.byteLength)]), stringBuffer]); + const buffer = Buffer.concat([Buffer.concat([new Buffer('U'), uint64be.encode(stringBuffer.byteLength)]), stringBuffer]); this.stream.Write(buffer); } private onPong() { const message = this.stream.readStringInTransaction(); - if (message == undefined) { + if (message === undefined) { return; } - this.emit("pong", message); + this.emit('pong', message); } private pid: number; @@ -74,14 +63,14 @@ class MockSocketCallbackHandler extends SocketCallbackHandler { protected handleHandshake(): boolean { if (!this.guid) { this.guid = this.stream.readStringInTransaction(); - if (this.guid == undefined) { + if (this.guid === undefined) { return false; } } if (!this.pid) { this.pid = this.stream.readInt32InTransaction(); - if (this.pid == undefined) { + if (this.pid === undefined) { return false; } } @@ -95,7 +84,7 @@ class MockSocketCallbackHandler extends SocketCallbackHandler { return true; } - this.emit("handshake"); + this.emit('handshake'); return true; } } @@ -122,7 +111,7 @@ class MockSocketClient { this.SocketStream.BeginTransaction(); const cmdId = new Buffer([this.SocketStream.ReadByte(), this.SocketStream.ReadByte(), this.SocketStream.ReadByte(), this.SocketStream.ReadByte()]).toString(); const message = this.SocketStream.ReadString(); - if (message == undefined) { + if (message === undefined) { this.SocketStream.EndTransaction(); return; } @@ -141,8 +130,7 @@ class MockSocketClient { const messageBuffer = new Buffer(message); const pongBuffer = Buffer.concat([Buffer.concat([new Buffer('U'), uint64be.encode(messageBuffer.byteLength)]), messageBuffer]); this.SocketStream.Write(pongBuffer); - } - catch (ex) { + } catch (ex) { this.SocketStream.Write(new Buffer(ResponseCommands.Error)); const errorMessage = `Fatal error in handling data at socket client. Error: ${ex.message}`; @@ -153,25 +141,34 @@ class MockSocketClient { } } -class MockSocket { - constructor() { - this._data = ''; - } - private _data: string; - private _rawDataWritten: any; - public get dataWritten(): string { - return this._data; - } - public get rawDataWritten(): any { - return this._rawDataWritten; - } - write(data: any) { - this._data = data + ''; - this._rawDataWritten = data; - } -} // Defines a Mocha test suite to group tests of similar kind together suite('SocketCallbackHandler', () => { + test('Succesfully starts without any specific host or port', async () => { + const socketServer = new SocketServer(); + await socketServer.Start(); + }); + test('Succesfully starts with port=0 and no host', async () => { + const socketServer = new SocketServer(); + await socketServer.Start({ port: 0 }); + }); + test('Succesfully starts with port=0 and host=localhost', async () => { + const socketServer = new SocketServer(); + await socketServer.Start({ port: 0, host: 'localhost' }); + }); + test('Succesfully starts with host=127.0.0.1', async () => { + const socketServer = new SocketServer(); + await socketServer.Start({ host: '127.0.0.1' }); + }); + test('Succesfully starts with port=0 and host=127.0.0.1', async () => { + const socketServer = new SocketServer(); + await socketServer.Start({ port: 0, host: '127.0.0.1' }); + }); + test('Succesfully starts with specific port', async () => { + const socketServer = new SocketServer(); + const availablePort = await getFreePort({ host: 'localhost' }); + const port = await socketServer.Start({ port: availablePort, host: 'localhost' }); + assert.equal(port, availablePort, 'Server is not listening on the provided port number'); + }); test('Succesful Handshake', done => { const socketServer = new SocketServer(); let socketClient: MockSocketClient; @@ -182,21 +179,21 @@ suite('SocketCallbackHandler', () => { return socketClient.start(); }).then(() => { const def = createDeferred(); - let timeOut = setTimeout(() => { + let timeOut: NodeJS.Timer | undefined = setTimeout(() => { def.reject('Handshake not completed in allocated time'); }, 5000); callbackHandler.on('handshake', () => { if (timeOut) { clearTimeout(timeOut); - timeOut = null; + timeOut = undefined; } def.resolve(); }); callbackHandler.on('error', (actual: string, expected: string, message: string) => { if (timeOut) { clearTimeout(timeOut); - timeOut = null; + timeOut = undefined; } def.reject({ actual: actual, expected: expected, message: message }); }); @@ -218,26 +215,25 @@ suite('SocketCallbackHandler', () => { return socketClient.start(); }).then(() => { const def = createDeferred(); - let timeOut = setTimeout(() => { + let timeOut: NodeJS.Timer | undefined = setTimeout(() => { def.reject('Handshake not completed in allocated time'); }, 5000); callbackHandler.on('handshake', () => { if (timeOut) { clearTimeout(timeOut); - timeOut = null; + timeOut = undefined; } def.reject('handshake should fail, but it succeeded!'); }); callbackHandler.on('error', (actual: string | number, expected: string, message: string) => { if (timeOut) { clearTimeout(timeOut); - timeOut = null; + timeOut = undefined; } if (actual === 0 && message === 'pids not the same') { def.resolve(); - } - else { + } else { def.reject({ actual: actual, expected: expected, message: message }); } }); @@ -262,7 +258,7 @@ suite('SocketCallbackHandler', () => { }).then(() => { const def = createDeferred(); const PING_MESSAGE = 'This is the Ping Message - Функция проверки ИНН и КПП - 说明'; - let timeOut = setTimeout(() => { + let timeOut: NodeJS.Timer | undefined = setTimeout(() => { def.reject('Handshake not completed in allocated time'); }, 5000); @@ -273,20 +269,19 @@ suite('SocketCallbackHandler', () => { callbackHandler.on('pong', (message: string) => { if (timeOut) { clearTimeout(timeOut); - timeOut = null; + timeOut = undefined; } try { assert.equal(message, PING_MESSAGE); def.resolve(); - } - catch (ex) { + } catch (ex) { def.reject(ex); } }); callbackHandler.on('error', (actual: string, expected: string, message: string) => { if (timeOut) { clearTimeout(timeOut); - timeOut = null; + timeOut = undefined; } def.reject({ actual: actual, expected: expected, message: message }); }); @@ -300,4 +295,86 @@ suite('SocketCallbackHandler', () => { return def.promise; }).then(done).catch(done); }); + test('Succesful Handshake with port=0 and host=localhost', done => { + const socketServer = new SocketServer(); + let socketClient: MockSocketClient; + let callbackHandler: MockSocketCallbackHandler; + socketServer.Start({ port: 0, host: 'localhost' }).then(port => { + callbackHandler = new MockSocketCallbackHandler(socketServer); + socketClient = new MockSocketClient(port); + return socketClient.start(); + }).then(() => { + const def = createDeferred(); + let timeOut: NodeJS.Timer | undefined = setTimeout(() => { + def.reject('Handshake not completed in allocated time'); + }, 5000); + + callbackHandler.on('handshake', () => { + if (timeOut) { + clearTimeout(timeOut); + timeOut = undefined; + } + def.resolve(); + }); + callbackHandler.on('error', (actual: string, expected: string, message: string) => { + if (timeOut) { + clearTimeout(timeOut); + timeOut = undefined; + } + def.reject({ actual: actual, expected: expected, message: message }); + }); + + // Client has connected, now send information to the callback handler via sockets + const guidBuffer = Buffer.concat([new Buffer('A'), uint64be.encode(GUID.length), new Buffer(GUID)]); + socketClient.SocketStream.Write(guidBuffer); + socketClient.SocketStream.WriteInt32(PID); + return def.promise; + }).then(done).catch(done); + }); + test('Succesful Handshake with specific port', done => { + const socketServer = new SocketServer(); + let socketClient: MockSocketClient; + let callbackHandler: MockSocketCallbackHandler; + let availablePort = 0; + new Promise((resolve, reject) => getFreePort({ host: 'localhost' }).then(resolve, reject)) + .then(port => { + availablePort = port; + return socketServer.Start({ port, host: 'localhost' }); + }) + .then(port => { + assert.equal(port, availablePort, 'Server is not listening on the provided port number'); + callbackHandler = new MockSocketCallbackHandler(socketServer); + socketClient = new MockSocketClient(port); + return socketClient.start(); + }) + .then(() => { + const def = createDeferred(); + let timeOut: NodeJS.Timer | undefined = setTimeout(() => { + def.reject('Handshake not completed in allocated time'); + }, 5000); + + callbackHandler.on('handshake', () => { + if (timeOut) { + clearTimeout(timeOut); + timeOut = undefined; + } + def.resolve(); + }); + callbackHandler.on('error', (actual: string, expected: string, message: string) => { + if (timeOut) { + clearTimeout(timeOut); + timeOut = undefined; + } + def.reject({ actual: actual, expected: expected, message: message }); + }); + + // Client has connected, now send information to the callback handler via sockets + const guidBuffer = Buffer.concat([new Buffer('A'), uint64be.encode(GUID.length), new Buffer(GUID)]); + socketClient.SocketStream.Write(guidBuffer); + socketClient.SocketStream.WriteInt32(PID); + return def.promise; + }) + .then(done) + .catch(done); + }); }); diff --git a/src/test/debugger/portAndHost.test.ts b/src/test/debugger/portAndHost.test.ts new file mode 100644 index 000000000000..a6d3ed23daac --- /dev/null +++ b/src/test/debugger/portAndHost.test.ts @@ -0,0 +1,119 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { expect, use } from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as getFreePort from 'get-port'; +import * as net from 'net'; +import * as path from 'path'; +import { ThreadEvent } from 'vscode-debugadapter'; +import { DebugClient } from 'vscode-debugadapter-testsupport'; +import { createDeferred } from '../../client/common/helpers'; +import { LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; +import { closeActiveWindows, initialize, initializeTest } from '../initialize'; + +use(chaiAsPromised); + +const debugFilesPath = path.join(__dirname, '..', '..', '..', 'src', 'test', 'pythonFiles', 'debugging'); + +const DEBUG_ADAPTER = path.join(__dirname, '..', '..', 'client', 'debugger', 'Main.js'); + +// tslint:disable-next-line:max-func-body-length +suite('Standard Debugging', () => { + let debugClient: DebugClient; + suiteSetup(initialize); + + setup(async () => { + await new Promise(resolve => setTimeout(resolve, 1000)); + debugClient = new DebugClient('node', DEBUG_ADAPTER, 'python'); + await debugClient.start(); + }); + teardown(async () => { + // Wait for a second before starting another test (sometimes, sockets take a while to get closed). + await new Promise(resolve => setTimeout(resolve, 1000)); + try { + debugClient.stop(); + // tslint:disable-next-line:no-empty + } catch (ex) { } + }); + + async function testDebuggingWithProvidedPort(port?: number | undefined, host?: string | undefined) { + const args: LaunchRequestArguments = { + program: path.join(debugFilesPath, 'simplePrint.py'), + cwd: debugFilesPath, + stopOnEntry: false, + debugOptions: ['RedirectOutput'], + pythonPath: 'python', + args: [], + envFile: '', + port, + host + }; + const threadIdPromise = createDeferred(); + debugClient.on('thread', (data: ThreadEvent) => { + if (data.body.reason === 'started') { + threadIdPromise.resolve(data.body.threadId); + } + }); + + const initializePromise = debugClient.initializeRequest({ + adapterID: 'python', + linesStartAt1: true, + columnsStartAt1: true, + supportsRunInTerminalRequest: true, + pathFormat: 'path' + }); + + await debugClient.launch(args); + await initializePromise; + + // Wait till we get the thread of the program. + const threadId = await threadIdPromise.promise; + expect(threadId).to.be.greaterThan(0, 'ThreadId not received'); + + // Confirm port is in use (if one was provided). + if (typeof port === 'number' && port > 0) { + // We know the port 'debuggerPort' was free, now that the debugger has started confirm that this port is no longer free. + const portBasedOnDebuggerPort = await getFreePort({ host: 'localhost', port }); + expect(portBasedOnDebuggerPort).is.not.equal(port, 'Port assigned to debugger not used by the debugger'); + } + + // Continue the program. + debugClient.continueRequest({ threadId }); + + await debugClient.waitForEvent('terminated'); + } + + test('Confirm debuggig works if both port and host are not provided', async () => { + await testDebuggingWithProvidedPort(); + }); + + test('Confirm debuggig works if port=0', async () => { + await testDebuggingWithProvidedPort(0, 'localhost'); + }); + + test('Confirm debuggig works if port=0 or host=localhost', async () => { + await testDebuggingWithProvidedPort(0, 'localhost'); + }); + + test('Confirm debuggig works if port=0 or host=127.0.0.1', async () => { + await testDebuggingWithProvidedPort(0, '127.0.0.1'); + }); + + test('Confirm debuggig fails when an invalid host is provided', async () => { + const promise = testDebuggingWithProvidedPort(0, 'xyz123409924ple_ewf'); + expect(promise).to.eventually.be.rejected.and.to.have.property('code', 'ENOTFOUND', 'Debugging failed for some other reason'); + }); + + test('Confirm debuggig fails when provided port is in use', async () => { + // tslint:disable-next-line:no-empty + const server = net.createServer((s) => { }); + const port = await new Promise((resolve, reject) => server.listen({ host: 'localhost', port: 0 }, () => resolve(server.address().port))); + try { + const promise = testDebuggingWithProvidedPort(port); + expect(promise).to.eventually.be.rejected.and.to.have.property('code', 'EADDRINUSE', 'Debugging failed for some other reason'); + } finally { + server.close(); + } + }); +}); diff --git a/src/test/pythonFiles/debugging/simplePrint.py b/src/test/pythonFiles/debugging/simplePrint.py new file mode 100644 index 000000000000..8cde7829c178 --- /dev/null +++ b/src/test/pythonFiles/debugging/simplePrint.py @@ -0,0 +1 @@ +print("hello world") diff --git a/src/test/unittests/mocks.ts b/src/test/unittests/mocks.ts index 53bd496f471e..ae4d5d52b316 100644 --- a/src/test/unittests/mocks.ts +++ b/src/test/unittests/mocks.ts @@ -30,8 +30,8 @@ export class MockDebugLauncher implements ITestDebugLauncher, Disposable { constructor() { this._launched = createDeferred(); } - public async getPort(resource?: Uri): Promise { - return 0; + public async getLaunchOptions(resource?: Uri): Promise<{ port: number, host: string }> { + return { port: 0, host: 'localhost' }; } public async launchDebugger(options: launchOptions): Promise { this._launched.resolve(true); @@ -100,12 +100,12 @@ export class MockUnitTestSocketServer extends EventEmitter implements IUnitTestS public addResults(results: {}[]) { this.results.push(...results); } - public async start(): Promise { + public async start(options: { port: number, host: string } = { port: 0, host: 'localhost' }): Promise { this.results.forEach(result => { this.emit('result', result); }); this.results = []; - return 0; + return typeof options.port === 'number' ? options.port! : 0; } // tslint:disable-next-line:no-empty public stop(): void { }