diff --git a/package-lock.json b/package-lock.json index 736551168ae6f..990d3fbcb5a4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "typescript", - "version": "2.7.0", + "version": "2.8.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -63,9 +63,9 @@ } }, "@types/chai": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.0.tgz", - "integrity": "sha512-OuYBlXWHYthxIudMXMeQr92f6D97YoT9CUYCRb0BEP4OavC95jNcczjjr4Ob3H5E1IqlWqwj+leUZPSeth27Qw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.2.tgz", + "integrity": "sha512-D8uQwKYUw2KESkorZ27ykzXgvkDJYXVEihGklgfp5I4HUP8D6IxtcdLTMB1emjQiWzV7WZ5ihm1cxIzVwjoleQ==", "dev": true }, "@types/convert-source-map": { @@ -80,7 +80,7 @@ "integrity": "sha512-18mSs54BvzV8+TTQxt0ancig6tsuPZySnhp3cQkWFFDmDMavU4pmWwR+bHHqRBWODYqpzIzVkqKLuk/fP6yypQ==", "dev": true, "requires": { - "@types/glob": "5.0.34" + "@types/glob": "5.0.35" } }, "@types/events": { @@ -90,9 +90,9 @@ "dev": true }, "@types/glob": { - "version": "5.0.34", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.34.tgz", - "integrity": "sha512-sUvpieq+HsWTLdkeOI8Mi8u22Ag3AoGuM3sv+XMP1bKtbaIAHpEA2f52K2mz6vK5PVhTa3bFyRZLZMqTxOo2Cw==", + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", + "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", "dev": true, "requires": { "@types/events": "1.1.0", @@ -189,9 +189,9 @@ } }, "@types/mocha": { - "version": "2.2.46", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.46.tgz", - "integrity": "sha512-fwTTP5QLf4xHMkv7ovcKvmlLWX3GrxCa5DRQDOilVyYGCp+arZTAQJCy7/4GKezzYJjfWMpB/Cy4e8nrc9XioA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.0.0.tgz", + "integrity": "sha512-ZS0vBV7Jn5Z/Q4T3VXauEKMDCV8nWOtJJg90OsDylkYJiQwcWtKuLzohWzrthBkerUF7DLMmJcwOPEP0i/AOXw==", "dev": true }, "@types/node": { @@ -207,13 +207,13 @@ "dev": true, "requires": { "@types/node": "8.5.5", - "@types/q": "1.0.6" + "@types/q": "1.0.7" } }, "@types/q": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.0.6.tgz", - "integrity": "sha512-LSx7jkcXoXWB+kkfwG5zc9Okbgn51BrjLMtKwbmnqfQlCGttTnTxvDVwQanHxkK6CLKb9yEfxQ1ID6pqDpeURw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.0.7.tgz", + "integrity": "sha512-0WS7XU7sXzQ7J1nbnMKKYdjrrFoO3YtZYgUzeV8JFXffPnHfvSJQleR70I8BOAsOm14i4dyaAZ3YzqIl1YhkXQ==", "dev": true }, "@types/run-sequence": { @@ -226,18 +226,6 @@ "@types/node": "8.5.5" } }, - "@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", - "dev": true - }, - "@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, "@types/through2": { "version": "2.0.33", "resolved": "https://registry.npmjs.org/@types/through2/-/through2-2.0.33.tgz", @@ -315,6 +303,15 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-cyan": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", @@ -348,21 +345,21 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.1" - } - }, "ansi-wrap": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "1.0.0" + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -646,16 +643,10 @@ "resolve": "1.1.7" } }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, "browserify": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-15.0.0.tgz", - "integrity": "sha512-dERxjzl4yacUzaB4XVVXDFFHARzDr6tLRhjqpE/NJUv0SkS3QVmZKiYTiKEQZhQ2HygCL02FUzSS5r3sY/SlTg==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.1.1.tgz", + "integrity": "sha512-iSH21jK0+IApV8YHOfmGt1qsGd74oflQ1Ko/28JOkWLFNBngAQfKb6WYIJ9CufH8vycqKX1sYU3y7ZrVhwevAg==", "dev": true, "requires": { "JSONStream": "1.3.2", @@ -665,15 +656,15 @@ "browserify-zlib": "0.2.0", "buffer": "5.0.8", "cached-path-relative": "1.0.1", - "concat-stream": "1.5.2", + "concat-stream": "1.6.2", "console-browserify": "1.1.0", "constants-browserify": "1.0.0", "crypto-browserify": "3.12.0", "defined": "1.0.0", "deps-sort": "2.0.0", - "domain-browser": "1.1.7", + "domain-browser": "1.2.0", "duplexer2": "0.1.4", - "events": "1.1.1", + "events": "2.0.0", "glob": "7.1.2", "has": "1.0.1", "htmlescape": "1.1.1", @@ -681,7 +672,8 @@ "inherits": "2.0.3", "insert-module-globals": "7.0.1", "labeled-stream-splicer": "2.0.0", - "module-deps": "5.0.1", + "mkdirp": "0.5.1", + "module-deps": "6.0.0", "os-browserify": "0.3.0", "parents": "1.0.1", "path-browserify": "0.0.0", @@ -700,11 +692,77 @@ "syntax-error": "1.3.0", "through2": "2.0.3", "timers-browserify": "1.4.2", - "tty-browserify": "0.0.0", + "tty-browserify": "0.0.1", "url": "0.11.0", "util": "0.10.3", "vm-browserify": "0.0.4", "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "events": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-2.0.0.tgz", + "integrity": "sha512-r/M5YkNg9zwI8QbSf7tsDWWJvO3PGwZXyG7GpFAxtMASnHL2eblFd7iHiGPtyGKKFPZ59S63NeX10Ws6WqGDcg==", + "dev": true + }, + "module-deps": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.0.0.tgz", + "integrity": "sha512-BKsMhJJENEM4dTgqq2MDTTHXRHcNUFegoAwlG4HO4VMdUyMcJDKgfgI+MOv6tR5Iv8G3MKZFgsSiyP3ZoosRMw==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.6.2", + "defined": "1.0.0", + "detective": "5.0.2", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.3", + "resolve": "1.6.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "resolve": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz", + "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + } + } + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + } } }, "browserify-aes": { @@ -793,6 +851,18 @@ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -876,14 +946,40 @@ } }, "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "supports-color": "5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } } }, "check-error": { @@ -1368,6 +1464,16 @@ "clone": "1.0.3" } }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", @@ -1473,12 +1579,6 @@ "randombytes": "2.0.5" } }, - "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", - "dev": true - }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -1488,29 +1588,6 @@ "readable-stream": "2.3.3" } }, - "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", - "dev": true, - "requires": { - "end-of-stream": "1.4.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "stream-shift": "1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", - "dev": true, - "requires": { - "once": "1.4.0" - } - } - } - }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", @@ -1654,12 +1731,6 @@ "es5-ext": "0.10.37" } }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -1753,57 +1824,6 @@ } } }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "2.2.3" - }, - "dependencies": { - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -1879,12 +1899,6 @@ } } }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -1940,6 +1954,16 @@ "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", "dev": true }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1955,6 +1979,12 @@ "for-in": "1.0.2" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -1964,6 +1994,24 @@ "map-cache": "0.2.2" } }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "through2": "2.0.3" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2011,42 +2059,6 @@ "path-is-absolute": "1.0.1" } }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -2310,13 +2322,11 @@ } }, "gulp-clone": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/gulp-clone/-/gulp-clone-1.1.1.tgz", - "integrity": "sha512-+9z6YKyup0pxL1nD9Hw5WjC29d280dsGkegagzt4xKAOvroyzZlA8Bs9MYs2WSSFIDqmcftMUVN/oentgBv69A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-clone/-/gulp-clone-2.0.1.tgz", + "integrity": "sha512-SLg/KsHBbinR/pCX3PF5l1YlR28hLp0X+bcpf77PtMJ6zvAQ5kRjtCPV5Wt1wHXsXWZN0eTUZ15R8ZYpi/CdCA==", "dev": true, "requires": { - "chai": "4.1.2", - "mocha": "4.1.0", "plugin-error": "0.1.2", "through2": "2.0.3" } @@ -2423,28 +2433,28 @@ } }, "gulp-sourcemaps": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.3.tgz", - "integrity": "sha1-EbAz91n5CeCl8Vt730esKcxU76Q=", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", "dev": true, "requires": { "@gulp-sourcemaps/identity-map": "1.0.1", "@gulp-sourcemaps/map-sources": "1.0.0", - "acorn": "5.3.0", + "acorn": "5.5.3", "convert-source-map": "1.5.1", "css": "2.2.1", "debug-fabulous": "1.0.0", "detect-newline": "2.1.0", "graceful-fs": "4.1.11", - "source-map": "0.5.7", + "source-map": "0.6.1", "strip-bom-string": "1.0.0", "through2": "2.0.3" }, "dependencies": { "acorn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", "dev": true }, "graceful-fs": { @@ -2452,116 +2462,45 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, "gulp-typescript": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.3.tgz", - "integrity": "sha512-Np2sJXgtDUwIAoMtlJ9uXsVmpu1FWXlKZw164hLuo56uJa7qo5W2KZ0yAYiYH/HUsaz5L0O2toMOcLIokpFCPg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-4.0.1.tgz", + "integrity": "sha512-BGdaBC1R4SJosXEkkEieeZ21qCZHnfSV78k7zzDljqAxvzDeGRTUqF4geckVclKEeiS3EYOBwNlxoHjJtn20vg==", "dev": true, "requires": { - "gulp-util": "3.0.8", - "source-map": "0.5.7", + "ansi-colors": "1.1.0", + "plugin-error": "0.1.2", + "source-map": "0.6.1", "through2": "2.0.3", - "vinyl-fs": "2.4.4" + "vinyl": "2.1.0", + "vinyl-fs": "3.0.2" }, "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "dev": true, "requires": { "extend": "3.0.1", - "glob": "5.0.15", + "glob": "7.1.2", "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", + "is-negated-glob": "1.0.0", + "ordered-read-streams": "1.0.1", + "pumpify": "1.4.0", + "readable-stream": "2.3.3", + "remove-trailing-separator": "1.1.0", + "to-absolute-glob": "2.0.2", "unique-stream": "2.2.1" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } } }, "graceful-fs": { @@ -2570,38 +2509,10 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.1", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - } - }, - "is-extglob": { + "is-valid-glob": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", "dev": true }, "json-stable-stringify": { @@ -2613,59 +2524,29 @@ "jsonify": "0.0.0" } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", "dev": true, "requires": { - "is-stream": "1.1.0", "readable-stream": "2.3.3" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-absolute": "1.0.0", + "is-negated-glob": "1.0.0" } }, "unique-stream": { @@ -2678,40 +2559,29 @@ "through2-filter": "2.0.0" } }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", + "integrity": "sha512-AUSFda1OukBwuLPBTbyuO4IRWgfXmqC4UTW0f8xrCa8Hkv9oyIU+NSqBlgfOLZRoUt7cHdo75hKQghCywpIyIw==", "dev": true, "requires": { - "duplexify": "3.5.1", - "glob-stream": "5.3.5", + "fs-mkdirp-stream": "1.0.0", + "glob-stream": "6.1.0", "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", + "is-valid-glob": "1.0.0", "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", + "lead": "1.0.0", + "object.assign": "4.1.0", + "pumpify": "1.4.0", "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", + "remove-bom-buffer": "3.0.0", + "remove-bom-stream": "1.2.0", + "resolve-options": "1.1.0", "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" + "to-through": "2.0.0", + "value-or-function": "3.0.0", + "vinyl": "2.1.0", + "vinyl-sourcemap": "1.1.0" } } } @@ -2857,6 +2727,12 @@ "sparkles": "1.0.0" } }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3056,21 +2932,6 @@ "kind-of": "6.0.2" } }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -3092,6 +2953,12 @@ "is-extglob": "2.1.1" } }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -3154,18 +3021,6 @@ "isobject": "3.0.1" } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -3181,12 +3036,6 @@ "is-unc-path": "1.0.0" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -3202,12 +3051,6 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, "is-windows": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", @@ -3422,6 +3265,15 @@ "readable-stream": "2.3.3" } }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "1.0.3" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -3538,12 +3390,6 @@ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "dev": true }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", @@ -3694,19 +3540,10 @@ "timers-ext": "0.1.2" } }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - } - }, "merge2": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.0.tgz", - "integrity": "sha1-D4ghUdmIsfPQdYlFQE+nPuWSPT8=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.1.tgz", + "integrity": "sha512-wUqcG5pxrAcaFI1lkqkMnk3Q7nUxV/NWfpAFSeWUwG9TRODnBDCUHa75mi3o3vLWQ5N4CQERWCauSlP0I3ZqUg==", "dev": true }, "micromatch": { @@ -3806,15 +3643,15 @@ } }, "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.0.4.tgz", + "integrity": "sha512-nMOpAPFosU1B4Ix1jdhx5e3q7XO55ic5a8cgYvW27CequcEY+BabS0kUVL1Cw1V5PuVHZWeNRWFLmEPexo79VA==", "dev": true, "requires": { - "browser-stdout": "1.3.0", + "browser-stdout": "1.3.1", "commander": "2.11.0", "debug": "3.1.0", - "diff": "3.3.1", + "diff": "3.5.0", "escape-string-regexp": "1.0.5", "glob": "7.1.2", "growl": "1.10.3", @@ -3823,6 +3660,12 @@ "supports-color": "4.4.0" }, "dependencies": { + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -3832,6 +3675,12 @@ "ms": "2.0.0" } }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3849,42 +3698,6 @@ "integrity": "sha1-zK/w4ckc9Vf+d+B535lUuRt0d1Y=", "dev": true }, - "module-deps": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-5.0.1.tgz", - "integrity": "sha512-sigq/hm/L+Z5IGi1DDl0x2ptkw7S86aFh213QhPLD8v9Opv90IHzKIuWJrRa5bJ77DVKHco2CfIEuThcT/vDJA==", - "dev": true, - "requires": { - "JSONStream": "1.3.2", - "browser-resolve": "1.11.2", - "cached-path-relative": "1.0.1", - "concat-stream": "1.6.0", - "defined": "1.0.0", - "detective": "5.0.2", - "duplexer2": "0.1.4", - "inherits": "2.0.3", - "parents": "1.0.1", - "readable-stream": "2.3.3", - "resolve": "1.1.7", - "stream-combiner2": "1.1.1", - "subarg": "1.0.0", - "through2": "2.0.3", - "xtend": "4.0.1" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" - } - } - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -3992,6 +3805,15 @@ "remove-trailing-separator": "1.1.0" } }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4066,6 +3888,12 @@ } } }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -4075,6 +3903,18 @@ "isobject": "3.0.1" } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", @@ -4097,27 +3937,6 @@ "make-iterator": "1.0.0" } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - }, - "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - } - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -4248,35 +4067,6 @@ "path-root": "0.1.1" } }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -4444,12 +4234,6 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -4481,6 +4265,61 @@ "randombytes": "2.0.5" } }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + } + } + }, + "pumpify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "dev": true, + "requires": { + "duplexify": "3.5.4", + "inherits": "2.0.3", + "pump": "2.0.1" + }, + "dependencies": { + "duplexify": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + } + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -4505,27 +4344,6 @@ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "randombytes": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", @@ -4578,15 +4396,6 @@ "resolve": "1.1.7" } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "0.1.3" - } - }, "regex-not": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", @@ -4596,6 +4405,27 @@ "extend-shallow": "2.0.1" } }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "is-utf8": "0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "3.0.0", + "safe-buffer": "5.1.1", + "through2": "2.0.3" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -4636,6 +4466,15 @@ "global-modules": "1.0.0" } }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "3.0.0" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -4959,9 +4798,9 @@ } }, "source-map-support": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", - "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", + "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", "dev": true, "requires": { "source-map": "0.6.1" @@ -5228,39 +5067,12 @@ "is-utf8": "0.2.1" } }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } - } - }, "strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", "dev": true }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, "subarg": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", @@ -5270,15 +5082,6 @@ "minimist": "1.2.0" } }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - }, "syntax-error": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", @@ -5348,15 +5151,6 @@ "next-tick": "1.0.0" } }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1" - } - }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -5472,6 +5266,15 @@ "repeat-string": "1.6.1" } }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "2.0.3" + } + }, "travis-fold": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/travis-fold/-/travis-fold-0.1.2.tgz", @@ -5479,52 +5282,19 @@ "dev": true }, "ts-node": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-4.1.0.tgz", - "integrity": "sha512-xcZH12oVg9PShKhy3UHyDmuDLV3y7iKwX25aMVPt1SIXSuAfWkFiGPEkg+th8R4YKW/QCxDoW7lJdb15lx6QWg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", + "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==", "dev": true, "requires": { "arrify": "1.0.1", - "chalk": "2.3.0", + "chalk": "2.3.2", "diff": "3.3.1", "make-error": "1.3.2", "minimist": "1.2.0", "mkdirp": "0.5.1", - "source-map-support": "0.5.0", - "tsconfig": "7.0.0", - "v8flags": "3.0.1", + "source-map-support": "0.5.4", "yn": "2.0.0" - }, - "dependencies": { - "v8flags": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.1.tgz", - "integrity": "sha1-3Oj8N5wX2fLJ6e142JzgAFKxt2s=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } - } - }, - "tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "requires": { - "@types/strip-bom": "3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "3.0.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } } }, "tslib": { @@ -5534,37 +5304,44 @@ "dev": true }, "tslint": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", - "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz", + "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=", "dev": true, "requires": { "babel-code-frame": "6.26.0", "builtin-modules": "1.1.1", - "chalk": "2.3.0", - "commander": "2.11.0", + "chalk": "2.3.2", + "commander": "2.15.1", "diff": "3.3.1", "glob": "7.1.2", + "js-yaml": "3.10.0", "minimatch": "3.0.4", - "resolve": "1.5.0", - "semver": "5.4.1", + "resolve": "1.6.0", + "semver": "5.5.0", "tslib": "1.8.1", "tsutils": "2.16.0" }, "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz", + "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==", "dev": true, "requires": { "path-parse": "1.0.5" } }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true } } @@ -5578,12 +5355,6 @@ "tslib": "1.8.1" } }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -5606,9 +5377,9 @@ "dev": true }, "typescript": { - "version": "2.7.0-dev.20180108", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.0-dev.20180108.tgz", - "integrity": "sha512-ZlggGsch8Y2d0LqAlCYGRzm/gdm2bqSpb4rdthY+YvpPsQqFixT0tU8sgjeRibMXW9hbS2Hz6kibS8L2oUKWfQ==", + "version": "2.8.0-dev.20180322", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.0-dev.20180322.tgz", + "integrity": "sha512-dSYa9IAoj3CRAxtKx9+cSCQLetB7OLtHXhvQWeWY6PPIXvbpAC41ulQWX3TUAkMYU9NS/kGIU8TFM9VFpinJTg==", "dev": true }, "uglify-js": { @@ -5861,10 +5632,10 @@ "user-home": "1.1.1" } }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, "vinyl": { @@ -5873,7 +5644,7 @@ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "2.1.1", + "clone": "2.1.2", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", "cloneable-readable": "1.0.0", @@ -5882,9 +5653,9 @@ }, "dependencies": { "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, "clone-stats": { @@ -5969,6 +5740,29 @@ } } }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "1.0.2", + "convert-source-map": "1.5.1", + "graceful-fs": "4.1.11", + "normalize-path": "2.1.1", + "now-and-later": "2.0.0", + "remove-bom-buffer": "3.0.0", + "vinyl": "2.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, "vlq": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", diff --git a/package.json b/package.json index d0ec2d70ce29c..5837f72317f7e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "http://typescriptlang.org/", - "version": "2.8.0", + "version": "2.9.0", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ef2f2827066a3..2b66e92cdc357 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -118,7 +118,7 @@ namespace ts { let languageVersion: ScriptTarget; let parent: Node; let container: Node; - let containerContainer: Node; // Container one level up + let thisParentContainer: Node; // Container one level up let blockScopeContainer: Node; let lastContainer: Node; let seenThisKeyword: boolean; @@ -186,7 +186,7 @@ namespace ts { languageVersion = undefined; parent = undefined; container = undefined; - containerContainer = undefined; + thisParentContainer = undefined; blockScopeContainer = undefined; lastContainer = undefined; seenThisKeyword = false; @@ -297,7 +297,7 @@ namespace ts { case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. - Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); + Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType, "Impossible parameter parent kind", () => `parent is: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[node.parent.kind] : node.parent.kind}, expected JSDocFunctionType`); const functionType = node.parent; const index = functionType.parameters.indexOf(node as ParameterDeclaration); return "arg" + index as __String; @@ -479,11 +479,9 @@ namespace ts { // and block-container. Then after we pop out of processing the children, we restore // these saved values. const saveContainer = container; - const saveContainerContainer = containerContainer; + const saveThisParentContainer = thisParentContainer; const savedBlockScopeContainer = blockScopeContainer; - containerContainer = container; - // Depending on what kind of node this is, we may have to adjust the current container // and block-container. If the current node is a container, then it is automatically // considered the current block-container as well. Also, for containers that we know @@ -502,6 +500,9 @@ namespace ts { // for it. We must clear this so we don't accidentally move any stale data forward from // a previous compilation. if (containerFlags & ContainerFlags.IsContainer) { + if (node.kind !== SyntaxKind.ArrowFunction) { + thisParentContainer = container; + } container = blockScopeContainer = node; if (containerFlags & ContainerFlags.HasLocals) { container.locals = createSymbolTable(); @@ -571,7 +572,7 @@ namespace ts { } container = saveContainer; - containerContainer = saveContainerContainer; + thisParentContainer = saveThisParentContainer; blockScopeContainer = savedBlockScopeContainer; } @@ -2338,14 +2339,16 @@ namespace ts { if (isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken) { const l = thisContainer.parent.left; if (isPropertyAccessEntityNameExpression(l) && isPrototypeAccess(l.expression)) { - constructorSymbol = getJSInitializerSymbolFromName(l.expression.expression, containerContainer); + constructorSymbol = getJSInitializerSymbolFromName(l.expression.expression, thisParentContainer); } } - // Declare a 'member' if the container is an ES5 class or ES6 constructor - constructorSymbol.members = constructorSymbol.members || createSymbolTable(); - // It's acceptable for multiple 'this' assignments of the same identifier to occur - declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); + if (constructorSymbol) { + // Declare a 'member' if the container is an ES5 class or ES6 constructor + constructorSymbol.members = constructorSymbol.members || createSymbolTable(); + // It's acceptable for multiple 'this' assignments of the same identifier to occur + declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); + } break; case SyntaxKind.Constructor: diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ac31392ca2169..34071fed58169 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -4,7 +4,7 @@ namespace ts { // WARNING: The script `configureNightly.ts` uses a regexp to parse out these values. // If changing the text in this section, be sure to test `configureNightly` too. - export const versionMajorMinor = "2.8"; + export const versionMajorMinor = "2.9"; /** The version of the TypeScript compiler release */ export const version = `${versionMajorMinor}.0-dev`; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b22906540aa8b..12177f8545b18 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -7243,7 +7243,7 @@ namespace ts { forEachChild(sourceFile, visit); if (lastNodeEntirelyBeforePosition) { - const lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition); + const lastChildOfLastEntireNodeBeforePosition = getLastDescendant(lastNodeEntirelyBeforePosition); if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) { bestResult = lastChildOfLastEntireNodeBeforePosition; } @@ -7251,9 +7251,9 @@ namespace ts { return bestResult; - function getLastChild(node: Node): Node { + function getLastDescendant(node: Node): Node { while (true) { - const lastChild = getLastChildWorker(node); + const lastChild = getLastChild(node); if (lastChild) { node = lastChild; } @@ -7263,16 +7263,6 @@ namespace ts { } } - function getLastChildWorker(node: Node): Node | undefined { - let last: Node; - forEachChild(node, child => { - if (nodeIsPresent(child)) { - last = child; - } - }); - return last; - } - function visit(child: Node) { if (nodeIsMissing(child)) { // Missing nodes are effectively invisible to us. We never even consider them diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 01c7bc59fdd6c..0b6b676f7f605 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -588,7 +588,8 @@ namespace ts { // Some file or directory in the watching directory is created // Return early if it does not have any of the watching extension or not the custom failed lookup path const dirOfFileOrDirectory = getDirectoryPath(fileOrDirectoryPath); - if (isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory)) { + if (isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) || + isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory)) { // Invalidate any resolution from this directory isChangedFailedLookupLocation = location => { const locationPath = resolutionHost.toPath(location); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6924995216692..236177ea6ff4d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3883,6 +3883,24 @@ namespace ts { return isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : getTextOfNode(moduleSpecifier); } + export function getLastChild(node: Node): Node | undefined { + let lastChild: Node | undefined; + forEachChild(node, + child => { + if (nodeIsPresent(child)) lastChild = child; + }, + children => { + // As an optimization, jump straight to the end of the list. + for (let i = children.length - 1; i >= 0; i--) { + if (nodeIsPresent(children[i])) { + lastChild = children[i]; + break; + } + } + }); + return lastChild; + } + /** Add a value to a set, and return true if it wasn't already present. */ export function addToSeen(seen: Map, key: string | number): boolean { key = String(key); diff --git a/src/harness/parallel/host.ts b/src/harness/parallel/host.ts index 1e7891e4cc3ec..75712bc7d9b30 100644 --- a/src/harness/parallel/host.ts +++ b/src/harness/parallel/host.ts @@ -384,7 +384,7 @@ namespace Harness.Parallel.Host { }; } - describe = ts.noop as any; // Disable unit tests + (global as any).describe = ts.noop as any; // Disable unit tests return; } diff --git a/src/harness/parallel/worker.ts b/src/harness/parallel/worker.ts index e0194815435f5..50c043cf71d74 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -25,10 +25,10 @@ namespace Harness.Parallel.Worker { (global as any).before = undefined; (global as any).after = undefined; (global as any).beforeEach = undefined; - describe = ((name, callback) => { + (global as any).describe = ((name, callback) => { testList.push({ name, callback, kind: "suite" }); }) as Mocha.IContextDefinition; - it = ((name, callback) => { + (global as any).it = ((name, callback) => { if (!testList) { throw new Error("Tests must occur within a describe block"); } @@ -251,7 +251,7 @@ namespace Harness.Parallel.Worker { }); if (!runUnitTests) { // ensure unit tests do not get run - describe = ts.noop as any; + (global as any).describe = ts.noop; } else { initialized = true; diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 48c3ba3127799..7341ecee7ef5f 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -245,7 +245,7 @@ function beginTests() { if (!runUnitTests) { // patch `describe` to skip unit tests - describe = ts.noop as any; + (global as any).describe = ts.noop; } } diff --git a/src/harness/unittests/organizeImports.ts b/src/harness/unittests/organizeImports.ts index de4a4722d67dc..044fee1367cfd 100644 --- a/src/harness/unittests/organizeImports.ts +++ b/src/harness/unittests/organizeImports.ts @@ -197,6 +197,16 @@ export const Other = 1; assert.isEmpty(changes); }); + testOrganizeImports("Renamed_used", + { + path: "/test.ts", + content: ` +import { F1 as EffOne, F2 as EffTwo } from "lib"; +EffOne(); +`, + }, + libFile); + testOrganizeImports("Simple", { path: "/test.ts", diff --git a/src/harness/unittests/printer.ts b/src/harness/unittests/printer.ts index ad60484d96394..0f6a2ea34749e 100644 --- a/src/harness/unittests/printer.ts +++ b/src/harness/unittests/printer.ts @@ -16,41 +16,43 @@ namespace ts { const printsCorrectly = makePrintsCorrectly("printsFileCorrectly"); // Avoid eagerly creating the sourceFile so that `createSourceFile` doesn't run unless one of these tests is run. let sourceFile: SourceFile; - before(() => sourceFile = createSourceFile("source.ts", ` - interface A { - // comment1 - readonly prop?: T; + before(() => { + sourceFile = createSourceFile("source.ts", ` + interface A { + // comment1 + readonly prop?: T; - // comment2 - method(): void; + // comment2 + method(): void; - // comment3 - new (): A; + // comment3 + new (): A; - // comment4 - (): A; - } + // comment4 + (): A; + } - // comment5 - type B = number | string | object; - type C = A & { x: string; }; // comment6 + // comment5 + type B = number | string | object; + type C = A & { x: string; }; // comment6 - // comment7 - enum E1 { - // comment8 - first - } + // comment7 + enum E1 { + // comment8 + first + } - const enum E2 { - second - } + const enum E2 { + second + } - // comment9 - console.log(1 + 2); + // comment9 + console.log(1 + 2); - // comment10 - function functionWithDefaultArgValue(argument: string = "defaultValue"): void { } - `, ScriptTarget.ES2015)); + // comment10 + function functionWithDefaultArgValue(argument: string = "defaultValue"): void { } + `, ScriptTarget.ES2015); + }); printsCorrectly("default", {}, printer => printer.printFile(sourceFile)); printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile)); @@ -65,20 +67,22 @@ namespace ts { describe("printBundle", () => { const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly"); let bundle: Bundle; - before(() => bundle = createBundle([ - createSourceFile("a.ts", ` - /*! [a.ts] */ + before(() => { + bundle = createBundle([ + createSourceFile("a.ts", ` + /*! [a.ts] */ - // comment0 - const a = 1; - `, ScriptTarget.ES2015), - createSourceFile("b.ts", ` - /*! [b.ts] */ + // comment0 + const a = 1; + `, ScriptTarget.ES2015), + createSourceFile("b.ts", ` + /*! [b.ts] */ - // comment1 - const b = 2; - `, ScriptTarget.ES2015) - ])); + // comment1 + const b = 2; + `, ScriptTarget.ES2015) + ]); + }); printsCorrectly("default", {}, printer => printer.printBundle(bundle)); printsCorrectly("removeComments", { removeComments: true }, printer => printer.printBundle(bundle)); }); diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index 47116cd5b0129..e056153518aa9 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -2113,6 +2113,28 @@ declare module "fs" { }; } }); + + it("works when renaming node_modules folder that already contains @types folder", () => { + const currentDirectory = "/user/username/projects/myproject"; + const file: FileOrFolder = { + path: `${currentDirectory}/a.ts`, + content: `import * as q from "qqq";` + }; + const module: FileOrFolder = { + path: `${currentDirectory}/node_modules2/@types/qqq/index.d.ts`, + content: "export {}" + }; + const files = [file, module, libFile]; + const host = createWatchedSystem(files, { currentDirectory }); + const watch = createWatchOfFilesAndCompilerOptions([file.path], host); + checkProgramActualFiles(watch(), [file.path, libFile.path]); + checkOutputErrorsInitial(host, [getDiagnosticModuleNotFoundOfFile(watch(), file, "qqq")]); + + host.renameFolder(`${currentDirectory}/node_modules2`, `${currentDirectory}/node_modules`); + host.runQueuedTimeoutCallbacks(); + checkProgramActualFiles(watch(), [file.path, libFile.path, `${currentDirectory}/node_modules/@types/qqq/index.d.ts`]); + checkOutputErrorsIncremental(host, emptyArray); + }); }); describe("tsc-watch with when module emit is specified as node", () => { diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 8b62c210abb02..c206d219e2a7b 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -455,16 +455,24 @@ interface Array {}` this.addFileOrFolderInFolder(baseFolder, newFolder); // Invoke watches for files in the folder as deleted (from old path) - for (const entry of folder.entries) { - Debug.assert(isFile(entry)); + this.renameFolderEntries(folder, newFolder); + } + + private renameFolderEntries(oldFolder: Folder, newFolder: Folder) { + for (const entry of oldFolder.entries) { this.fs.delete(entry.path); this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Deleted); - entry.fullPath = combinePaths(newFullPath, getBaseFileName(entry.fullPath)); + entry.fullPath = combinePaths(newFolder.fullPath, getBaseFileName(entry.fullPath)); entry.path = this.toPath(entry.fullPath); - newFolder.entries.push(entry); + if (newFolder !== oldFolder) { + newFolder.entries.push(entry); + } this.fs.set(entry.path, entry); this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Created); + if (isFolder(entry)) { + this.renameFolderEntries(entry, entry); + } } } diff --git a/src/server/server.ts b/src/server/server.ts index e43ca0437d95b..9067547892409 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -1,948 +1,948 @@ -/// -/// - -namespace ts.server { - const childProcess: { - fork(modulePath: string, args: string[], options?: { execArgv: string[], env?: MapLike }): NodeChildProcess; - execFileSync(file: string, args: string[], options: { stdio: "ignore", env: MapLike }): string | Buffer; - } = require("child_process"); - - const os: { - homedir?(): string; - tmpdir(): string; - platform(): string; - } = require("os"); - - interface NodeSocket { - write(data: string, encoding: string): boolean; - } - - const net: { - connect(options: { port: number }, onConnect?: () => void): NodeSocket - } = require("net"); - - function getGlobalTypingsCacheLocation() { - switch (process.platform) { - case "win32": { - const basePath = process.env.LOCALAPPDATA || - process.env.APPDATA || - (os.homedir && os.homedir()) || - process.env.USERPROFILE || - (process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) || - os.tmpdir(); - return combinePaths(combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"), versionMajorMinor); - } - case "openbsd": - case "freebsd": - case "darwin": - case "linux": - case "android": { - const cacheLocation = getNonWindowsCacheLocation(process.platform === "darwin"); - return combinePaths(combinePaths(cacheLocation, "typescript"), versionMajorMinor); - } - default: - Debug.fail(`unsupported platform '${process.platform}'`); - return; - } - } - - function getNonWindowsCacheLocation(platformIsDarwin: boolean) { - if (process.env.XDG_CACHE_HOME) { - return process.env.XDG_CACHE_HOME; - } - const usersDir = platformIsDarwin ? "Users" : "home"; - const homePath = (os.homedir && os.homedir()) || - process.env.HOME || - ((process.env.LOGNAME || process.env.USER) && `/${usersDir}/${process.env.LOGNAME || process.env.USER}`) || - os.tmpdir(); - const cacheFolder = platformIsDarwin - ? "Library/Caches" - : ".cache"; - return combinePaths(normalizeSlashes(homePath), cacheFolder); - } - - interface NodeChildProcess { - send(message: any, sendHandle?: any): void; - on(message: "message" | "exit", f: (m: any) => void): void; - kill(): void; - pid: number; - } - - interface ReadLineOptions { - input: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - terminal?: boolean; - historySize?: number; - } - - interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; - } - - const readline: { - createInterface(options: ReadLineOptions): NodeJS.EventEmitter; - } = require("readline"); - - const fs: { - openSync(path: string, options: string): number; - close(fd: number, callback: (err: NodeJS.ErrnoException) => void): void; - writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number; - writeSync(fd: number, data: any, position?: number, enconding?: string): number; - statSync(path: string): Stats; - stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - } = require("fs"); - - - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: false, - }); - - class Logger implements server.Logger { // tslint:disable-line no-unnecessary-qualifier - private fd = -1; - private seq = 0; - private inGroup = false; - private firstInGroup = true; - - constructor(private readonly logFilename: string, - private readonly traceToConsole: boolean, - private readonly level: LogLevel) { - if (this.logFilename) { - try { - this.fd = fs.openSync(this.logFilename, "w"); - } - catch (_) { - // swallow the error and keep logging disabled if file cannot be opened - } - } - } - - static padStringRight(str: string, padding: string) { - return (str + padding).slice(0, padding.length); - } - - close() { - if (this.fd >= 0) { - fs.close(this.fd, noop); - } - } - - getLogFileName() { - return this.logFilename; - } - - perftrc(s: string) { - this.msg(s, Msg.Perf); - } - - info(s: string) { - this.msg(s, Msg.Info); - } - - err(s: string) { - this.msg(s, Msg.Err); - } - - startGroup() { - this.inGroup = true; - this.firstInGroup = true; - } - - endGroup() { - this.inGroup = false; - } - - loggingEnabled() { - return !!this.logFilename || this.traceToConsole; - } - - hasLevel(level: LogLevel) { - return this.loggingEnabled() && this.level >= level; - } - - msg(s: string, type: Msg = Msg.Err) { - if (!this.canWrite) return; - - s = `[${nowString()}] ${s}\n`; - if (!this.inGroup || this.firstInGroup) { - const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " "); - s = prefix + s; - } - this.write(s); - if (!this.inGroup) { - this.seq++; - } - } - - private get canWrite() { - return this.fd >= 0 || this.traceToConsole; - } - - private write(s: string) { - if (this.fd >= 0) { - const buf = new Buffer(s); - // tslint:disable-next-line no-null-keyword - fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); - } - if (this.traceToConsole) { - console.warn(s); - } - } - } - - // E.g. "12:34:56.789" - function nowString() { - const d = new Date(); - return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`; - } - - interface QueuedOperation { - operationId: string; - operation: () => void; - } - - class NodeTypingsInstaller implements ITypingsInstaller { - private installer: NodeChildProcess; - private projectService: ProjectService; - private activeRequestCount = 0; - private requestQueue: QueuedOperation[] = []; - private requestMap = createMap(); // Maps operation ID to newest requestQueue entry with that ID - /** We will lazily request the types registry on the first call to `isKnownTypesPackageName` and store it in `typesRegistryCache`. */ - private requestedRegistry: boolean; - private typesRegistryCache: Map> | undefined; - - // This number is essentially arbitrary. Processing more than one typings request - // at a time makes sense, but having too many in the pipe results in a hang - // (see https://github.com/nodejs/node/issues/7657). - // It would be preferable to base our limit on the amount of space left in the - // buffer, but we have yet to find a way to retrieve that value. - private static readonly maxActiveRequestCount = 10; - private static readonly requestDelayMillis = 100; - private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void }; - - constructor( - private readonly telemetryEnabled: boolean, - private readonly logger: Logger, - private readonly host: ServerHost, - readonly globalTypingsCacheLocation: string, - readonly typingSafeListLocation: string, - readonly typesMapLocation: string, - private readonly npmLocation: string | undefined, - private event: Event) { - } - - isKnownTypesPackageName(name: string): boolean { - // We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package. - const validationResult = JsTyping.validatePackageName(name); - if (validationResult !== JsTyping.PackageNameValidationResult.Ok) { - return false; - } - - if (this.requestedRegistry) { - return !!this.typesRegistryCache && this.typesRegistryCache.has(name); - } - - this.requestedRegistry = true; - this.send({ kind: "typesRegistry" }); - return false; - } - - installPackage(options: InstallPackageOptionsWithProject): Promise { - const rq: InstallPackageRequest = { kind: "installPackage", ...options }; - this.send(rq); - Debug.assert(this.packageInstalledPromise === undefined); - return new Promise((resolve, reject) => { - this.packageInstalledPromise = { resolve, reject }; - }); - } - - attach(projectService: ProjectService) { - this.projectService = projectService; - if (this.logger.hasLevel(LogLevel.requestTime)) { - this.logger.info("Binding..."); - } - - const args: string[] = [Arguments.GlobalCacheLocation, this.globalTypingsCacheLocation]; - if (this.telemetryEnabled) { - args.push(Arguments.EnableTelemetry); - } - if (this.logger.loggingEnabled() && this.logger.getLogFileName()) { - args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName())), `ti-${process.pid}.log`)); - } - if (this.typingSafeListLocation) { - args.push(Arguments.TypingSafeListLocation, this.typingSafeListLocation); - } - if (this.typesMapLocation) { - args.push(Arguments.TypesMapLocation, this.typesMapLocation); - } - if (this.npmLocation) { - args.push(Arguments.NpmLocation, this.npmLocation); - } - - const execArgv: string[] = []; - for (const arg of process.execArgv) { - const match = /^--((?:debug|inspect)(?:-brk)?)(?:=(\d+))?$/.exec(arg); - if (match) { - // if port is specified - use port + 1 - // otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1 - const currentPort = match[2] !== undefined - ? +match[2] - : match[1].charAt(0) === "d" ? 5858 : 9229; - execArgv.push(`--${match[1]}=${currentPort + 1}`); - break; - } - } - - this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv }); - this.installer.on("message", m => this.handleMessage(m)); - - this.event({ pid: this.installer.pid }, "typingsInstallerPid"); - - process.on("exit", () => { - this.installer.kill(); - }); - } - - onProjectClosed(p: Project): void { - this.send({ projectName: p.getProjectName(), kind: "closeProject" }); - } - - private send(rq: TypingInstallerRequestUnion): void { - this.installer.send(rq); - } - - enqueueInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void { - const request = createInstallTypingsRequest(project, typeAcquisition, unresolvedImports); - if (this.logger.hasLevel(LogLevel.verbose)) { - if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Scheduling throttled operation:${stringifyIndented(request)}`); - } - } - - const operationId = project.getProjectName(); - const operation = () => { - if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Sending request:${stringifyIndented(request)}`); - } - this.send(request); - }; - const queuedRequest: QueuedOperation = { operationId, operation }; - - if (this.activeRequestCount < NodeTypingsInstaller.maxActiveRequestCount) { - this.scheduleRequest(queuedRequest); - } - else { - if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Deferring request for: ${operationId}`); - } - this.requestQueue.push(queuedRequest); - this.requestMap.set(operationId, queuedRequest); - } - } - - private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { - if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Received response:${stringifyIndented(response)}`); - } - - switch (response.kind) { - case EventTypesRegistry: - this.typesRegistryCache = createMapFromTemplate(response.typesRegistry); - break; - case ActionPackageInstalled: { - const { success, message } = response; - if (success) { - this.packageInstalledPromise.resolve({ successMessage: message }); - } - else { - this.packageInstalledPromise.reject(message); - } - this.packageInstalledPromise = undefined; - - this.projectService.updateTypingsForProject(response); - - // The behavior is the same as for setTypings, so send the same event. - this.event(response, "setTypings"); - break; - } - case EventInitializationFailed: - { - const body: protocol.TypesInstallerInitializationFailedEventBody = { - message: response.message - }; - const eventName: protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed"; - this.event(body, eventName); - break; - } - case EventBeginInstallTypes: - { - const body: protocol.BeginInstallTypesEventBody = { - eventId: response.eventId, - packages: response.packagesToInstall, - }; - const eventName: protocol.BeginInstallTypesEventName = "beginInstallTypes"; - this.event(body, eventName); - break; - } - case EventEndInstallTypes: - { - if (this.telemetryEnabled) { - const body: protocol.TypingsInstalledTelemetryEventBody = { - telemetryEventName: "typingsInstalled", - payload: { - installedPackages: response.packagesToInstall.join(","), - installSuccess: response.installSuccess, - typingsInstallerVersion: response.typingsInstallerVersion - } - }; - const eventName: protocol.TelemetryEventName = "telemetry"; - this.event(body, eventName); - } - - const body: protocol.EndInstallTypesEventBody = { - eventId: response.eventId, - packages: response.packagesToInstall, - success: response.installSuccess, - }; - const eventName: protocol.EndInstallTypesEventName = "endInstallTypes"; - this.event(body, eventName); - break; - } - case ActionInvalidate: - { - this.projectService.updateTypingsForProject(response); - break; - } - case ActionSet: - { - if (this.activeRequestCount > 0) { - this.activeRequestCount--; - } - else { - Debug.fail("Received too many responses"); - } - - while (this.requestQueue.length > 0) { - const queuedRequest = this.requestQueue.shift(); - if (this.requestMap.get(queuedRequest.operationId) === queuedRequest) { - this.requestMap.delete(queuedRequest.operationId); - this.scheduleRequest(queuedRequest); - break; - } - - if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Skipping defunct request for: ${queuedRequest.operationId}`); - } - } - - this.projectService.updateTypingsForProject(response); - - this.event(response, "setTypings"); - - break; - } - default: - assertTypeIsNever(response); - } - } - - private scheduleRequest(request: QueuedOperation) { - if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Scheduling request for: ${request.operationId}`); - } - this.activeRequestCount++; - this.host.setTimeout(request.operation, NodeTypingsInstaller.requestDelayMillis); - } - } - - class IOSession extends Session { - private eventPort: number; - private eventSocket: NodeSocket | undefined; - private socketEventQueue: { body: any, eventName: string }[] | undefined; - private constructed: boolean | undefined; - - constructor() { - const event: Event | undefined = (body: object, eventName: string) => { - if (this.constructed) { - this.event(body, eventName); - } - else { - // It is unsafe to dereference `this` before initialization completes, - // so we defer until the next tick. - // - // Construction should finish before the next tick fires, so we do not need to do this recursively. - setImmediate(() => this.event(body, eventName)); - } - }; - - const host = sys; - - const typingsInstaller = disableAutomaticTypingAcquisition - ? undefined - : new NodeTypingsInstaller(telemetryEnabled, logger, host, getGlobalTypingsCacheLocation(), typingSafeListLocation, typesMapLocation, npmLocation, event); - - super({ - host, - cancellationToken, - useSingleInferredProject, - useInferredProjectPerProjectRoot, - typingsInstaller: typingsInstaller || nullTypingsInstaller, - byteLength: Buffer.byteLength, - hrtime: process.hrtime, - logger, - canUseEvents: eventPort !== undefined, - suppressDiagnosticEvents, - globalPlugins, - pluginProbeLocations, - allowLocalPluginLoads, - }); - - this.eventPort = eventPort; - if (this.canUseEvents && this.eventPort) { - const s = net.connect({ port: this.eventPort }, () => { - this.eventSocket = s; - if (this.socketEventQueue) { - // flush queue. - for (const event of this.socketEventQueue) { - this.writeToEventSocket(event.body, event.eventName); - } - this.socketEventQueue = undefined; - } - }); - } - - this.constructed = true; - } - - event(body: T, eventName: string): void { - Debug.assert(this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); - - if (this.canUseEvents && this.eventPort) { - if (!this.eventSocket) { - if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`eventPort: event "${eventName}" queued, but socket not yet initialized`); - } - (this.socketEventQueue || (this.socketEventQueue = [])).push({ body, eventName }); - return; - } - else { - Debug.assert(this.socketEventQueue === undefined); - this.writeToEventSocket(body, eventName); - } - } - else { - super.event(body, eventName); - } - } - - private writeToEventSocket(body: object, eventName: string): void { - this.eventSocket.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); - } - - exit() { - this.logger.info("Exiting..."); - this.projectService.closeLog(); - process.exit(0); - } - - listen() { - rl.on("line", (input: string) => { - const message = input.trim(); - this.onMessage(message); - }); - - rl.on("close", () => { - this.exit(); - }); - } - } - - interface LogOptions { - file?: string; - detailLevel?: LogLevel; - traceToConsole?: boolean; - logToFile?: boolean; - } - - function parseLoggingEnvironmentString(logEnvStr: string): LogOptions { - if (!logEnvStr) { - return {}; - } - const logEnv: LogOptions = { logToFile: true }; - const args = logEnvStr.split(" "); - const len = args.length - 1; - for (let i = 0; i < len; i += 2) { - const option = args[i]; - const value = args[i + 1]; - if (option && value) { - switch (option) { - case "-file": - logEnv.file = stripQuotes(value); - break; - case "-level": - const level = getLogLevel(value); - logEnv.detailLevel = level !== undefined ? level : LogLevel.normal; - break; - case "-traceToConsole": - logEnv.traceToConsole = value.toLowerCase() === "true"; - break; - case "-logToFile": - logEnv.logToFile = value.toLowerCase() === "true"; - break; - } - } - } - return logEnv; - } - - function getLogLevel(level: string) { - if (level) { - const l = level.toLowerCase(); - for (const name in LogLevel) { - if (isNaN(+name) && l === name.toLowerCase()) { - return LogLevel[name]; - } - } - } - return undefined; - } - - // TSS_LOG "{ level: "normal | verbose | terse", file?: string}" - function createLogger() { - const cmdLineLogFileName = findArgument("--logFile"); - const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity")); - const envLogOptions = parseLoggingEnvironmentString(process.env.TSS_LOG); - - const logFileName = cmdLineLogFileName - ? stripQuotes(cmdLineLogFileName) - : envLogOptions.logToFile - ? envLogOptions.file || (__dirname + "/.log" + process.pid.toString()) - : undefined; - - const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel; - return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity); - } - // This places log file in the directory containing editorServices.js - // TODO: check that this location is writable - - // average async stat takes about 30 microseconds - // set chunk size to do 30 files in < 1 millisecond - function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) { - const watchedFiles: WatchedFile[] = []; - let nextFileToCheck = 0; - return { getModifiedTime, poll, startWatchTimer, addFile, removeFile }; - - function getModifiedTime(fileName: string): Date { - return fs.statSync(fileName).mtime; - } - - function poll(checkedIndex: number) { - const watchedFile = watchedFiles[checkedIndex]; - if (!watchedFile) { - return; - } - - fs.stat(watchedFile.fileName, (err, stats) => { - if (err) { - if (err.code === "ENOENT") { - if (watchedFile.mtime.getTime() !== 0) { - watchedFile.mtime = missingFileModifiedTime; - watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Deleted); - } - } - else { - watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Changed); - } - } - else { - onWatchedFileStat(watchedFile, stats.mtime); - } - }); - } - - // this implementation uses polling and - // stat due to inconsistencies of fs.watch - // and efficiency of stat on modern filesystems - function startWatchTimer() { - setInterval(() => { - let count = 0; - let nextToCheck = nextFileToCheck; - let firstCheck = -1; - while ((count < chunkSize) && (nextToCheck !== firstCheck)) { - poll(nextToCheck); - if (firstCheck < 0) { - firstCheck = nextToCheck; - } - nextToCheck++; - if (nextToCheck === watchedFiles.length) { - nextToCheck = 0; - } - count++; - } - nextFileToCheck = nextToCheck; - }, interval); - } - - function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { - const file: WatchedFile = { - fileName, - callback, - mtime: sys.fileExists(fileName) - ? getModifiedTime(fileName) - : missingFileModifiedTime // Any subsequent modification will occur after this time - }; - - watchedFiles.push(file); - if (watchedFiles.length === 1) { - startWatchTimer(); - } - return file; - } - - function removeFile(file: WatchedFile) { - unorderedRemoveItem(watchedFiles, file); - } - } - - // REVIEW: for now this implementation uses polling. - // The advantage of polling is that it works reliably - // on all os and with network mounted files. - // For 90 referenced files, the average time to detect - // changes is 2*msInterval (by default 5 seconds). - // The overhead of this is .04 percent (1/2500) with - // average pause of < 1 millisecond (and max - // pause less than 1.5 milliseconds); question is - // do we anticipate reference sets in the 100s and - // do we care about waiting 10-20 seconds to detect - // changes for large reference sets? If so, do we want - // to increase the chunk size or decrease the interval - // time dynamically to match the large reference set? - const pollingWatchedFileSet = createPollingWatchedFileSet(); - - const pending: Buffer[] = []; - let canWrite = true; - - function writeMessage(buf: Buffer) { - if (!canWrite) { - pending.push(buf); - } - else { - canWrite = false; - process.stdout.write(buf, setCanWriteFlagAndWriteMessageIfNecessary); - } - } - - function setCanWriteFlagAndWriteMessageIfNecessary() { - canWrite = true; - if (pending.length) { - writeMessage(pending.shift()); - } - } - - function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string) { - path = normalizeSlashes(path); - if (isUNCPath(path)) { - // UNC path: extract server name - // //server/location - // ^ <- from 0 to this position - const firstSlash = path.indexOf(directorySeparator, 2); - return firstSlash !== -1 ? path.substring(0, firstSlash).toLowerCase() : path; - } - const rootLength = getRootLength(path); - if (rootLength === 0) { - // relative path - assume file is on the current drive - return currentDriveKey; - } - if (path.charCodeAt(1) === CharacterCodes.colon && path.charCodeAt(2) === CharacterCodes.slash) { - // rooted path that starts with c:/... - extract drive letter - return path.charAt(0).toLowerCase(); - } - if (path.charCodeAt(0) === CharacterCodes.slash && path.charCodeAt(1) !== CharacterCodes.slash) { - // rooted path that starts with slash - /somename - use key for current drive - return currentDriveKey; - } - // do not cache any other cases - return undefined; - } - - function isUNCPath(s: string): boolean { - return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash; - } - - const logger = createLogger(); - - const sys = ts.sys; - const nodeVersion = getNodeMajorVersion(); - // use watchGuard process on Windows when node version is 4 or later - const useWatchGuard = process.platform === "win32" && nodeVersion >= 4; - const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys); - const noopWatcher: FileWatcher = { close: noop }; - // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function - // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point - function watchDirectorySwallowingException(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher { - try { - return originalWatchDirectory(path, callback, recursive); - } - catch (e) { - logger.info(`Exception when creating directory watcher: ${e.message}`); - return noopWatcher; - } - } - - if (useWatchGuard) { - const currentDrive = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined); - const statusCache = createMap(); - sys.watchDirectory = (path, callback, recursive) => { - const cacheKey = extractWatchDirectoryCacheKey(path, currentDrive); - let status = cacheKey && statusCache.get(cacheKey); - if (status === undefined) { - if (logger.hasLevel(LogLevel.verbose)) { - logger.info(`${cacheKey} for path ${path} not found in cache...`); - } - try { - const args = [combinePaths(__dirname, "watchGuard.js"), path]; - if (logger.hasLevel(LogLevel.verbose)) { - logger.info(`Starting ${process.execPath} with args:${stringifyIndented(args)}`); - } - childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { ELECTRON_RUN_AS_NODE: "1" } }); - status = true; - if (logger.hasLevel(LogLevel.verbose)) { - logger.info(`WatchGuard for path ${path} returned: OK`); - } - } - catch (e) { - status = false; - if (logger.hasLevel(LogLevel.verbose)) { - logger.info(`WatchGuard for path ${path} returned: ${e.message}`); - } - } - if (cacheKey) { - statusCache.set(cacheKey, status); - } - } - else if (logger.hasLevel(LogLevel.verbose)) { - logger.info(`watchDirectory for ${path} uses cached drive information.`); - } - if (status) { - // this drive is safe to use - call real 'watchDirectory' - return watchDirectorySwallowingException(path, callback, recursive); - } - else { - // this drive is unsafe - return no-op watcher - return noopWatcher; - } - }; - } - else { - sys.watchDirectory = watchDirectorySwallowingException; - } - - // Override sys.write because fs.writeSync is not reliable on Node 4 - sys.write = (s: string) => writeMessage(new Buffer(s, "utf8")); - sys.watchFile = (fileName, callback) => { - const watchedFile = pollingWatchedFileSet.addFile(fileName, callback); - return { - close: () => pollingWatchedFileSet.removeFile(watchedFile) - }; - }; - - sys.setTimeout = setTimeout; - sys.clearTimeout = clearTimeout; - sys.setImmediate = setImmediate; - sys.clearImmediate = clearImmediate; - if (typeof global !== "undefined" && global.gc) { - sys.gc = () => global.gc(); - } - - sys.require = (initialDir: string, moduleName: string): RequireResult => { - try { - return { module: require(resolveJavaScriptModule(moduleName, initialDir, sys)), error: undefined }; - } - catch (error) { - return { module: undefined, error }; - } - }; - - let cancellationToken: ServerCancellationToken; - try { - const factory = require("./cancellationToken"); - cancellationToken = factory(sys.args); - } - catch (e) { - cancellationToken = nullCancellationToken; - } - - let eventPort: number | undefined; - { - const str = findArgument("--eventPort"); - const v = str && parseInt(str); - if (!isNaN(v)) { - eventPort = v; - } - } - - const localeStr = findArgument("--locale"); - if (localeStr) { - validateLocaleAndSetLanguage(localeStr, sys); - } - - setStackTraceLimit(); - - const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation); - const typesMapLocation = findArgument(Arguments.TypesMapLocation) || combinePaths(sys.getExecutingFilePath(), "../typesMap.json"); - const npmLocation = findArgument(Arguments.NpmLocation); - - function parseStringArray(argName: string): ReadonlyArray { - const arg = findArgument(argName); - if (arg === undefined) { - return emptyArray; - } - return arg.split(",").filter(name => name !== ""); - } - - const globalPlugins = parseStringArray("--globalPlugins"); - const pluginProbeLocations = parseStringArray("--pluginProbeLocations"); - const allowLocalPluginLoads = hasArgument("--allowLocalPluginLoads"); - - const useSingleInferredProject = hasArgument("--useSingleInferredProject"); - const useInferredProjectPerProjectRoot = hasArgument("--useInferredProjectPerProjectRoot"); - const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); - const suppressDiagnosticEvents = hasArgument("--suppressDiagnosticEvents"); - const telemetryEnabled = hasArgument(Arguments.EnableTelemetry); - - logger.info(`Starting TS Server`); - logger.info(`Version: ${version}`); - logger.info(`Arguments: ${process.argv.join(" ")}`); - logger.info(`Platform: ${os.platform()} NodeVersion: ${nodeVersion} CaseSensitive: ${sys.useCaseSensitiveFileNames}`); - - const ioSession = new IOSession(); - process.on("uncaughtException", err => { - ioSession.logError(err, "unknown"); - }); - // See https://github.com/Microsoft/TypeScript/issues/11348 - // tslint:disable-next-line no-unnecessary-type-assertion-2 - (process as any).noAsar = true; - // Start listening - ioSession.listen(); -} +/// +/// + +namespace ts.server { + const childProcess: { + fork(modulePath: string, args: string[], options?: { execArgv: string[], env?: MapLike }): NodeChildProcess; + execFileSync(file: string, args: string[], options: { stdio: "ignore", env: MapLike }): string | Buffer; + } = require("child_process"); + + const os: { + homedir?(): string; + tmpdir(): string; + platform(): string; + } = require("os"); + + interface NodeSocket { + write(data: string, encoding: string): boolean; + } + + const net: { + connect(options: { port: number }, onConnect?: () => void): NodeSocket + } = require("net"); + + function getGlobalTypingsCacheLocation() { + switch (process.platform) { + case "win32": { + const basePath = process.env.LOCALAPPDATA || + process.env.APPDATA || + (os.homedir && os.homedir()) || + process.env.USERPROFILE || + (process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) || + os.tmpdir(); + return combinePaths(combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"), versionMajorMinor); + } + case "openbsd": + case "freebsd": + case "darwin": + case "linux": + case "android": { + const cacheLocation = getNonWindowsCacheLocation(process.platform === "darwin"); + return combinePaths(combinePaths(cacheLocation, "typescript"), versionMajorMinor); + } + default: + Debug.fail(`unsupported platform '${process.platform}'`); + return; + } + } + + function getNonWindowsCacheLocation(platformIsDarwin: boolean) { + if (process.env.XDG_CACHE_HOME) { + return process.env.XDG_CACHE_HOME; + } + const usersDir = platformIsDarwin ? "Users" : "home"; + const homePath = (os.homedir && os.homedir()) || + process.env.HOME || + ((process.env.LOGNAME || process.env.USER) && `/${usersDir}/${process.env.LOGNAME || process.env.USER}`) || + os.tmpdir(); + const cacheFolder = platformIsDarwin + ? "Library/Caches" + : ".cache"; + return combinePaths(normalizeSlashes(homePath), cacheFolder); + } + + interface NodeChildProcess { + send(message: any, sendHandle?: any): void; + on(message: "message" | "exit", f: (m: any) => void): void; + kill(): void; + pid: number; + } + + interface ReadLineOptions { + input: NodeJS.ReadableStream; + output?: NodeJS.WritableStream; + terminal?: boolean; + historySize?: number; + } + + interface Stats { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + dev: number; + ino: number; + mode: number; + nlink: number; + uid: number; + gid: number; + rdev: number; + size: number; + blksize: number; + blocks: number; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } + + const readline: { + createInterface(options: ReadLineOptions): NodeJS.EventEmitter; + } = require("readline"); + + const fs: { + openSync(path: string, options: string): number; + close(fd: number, callback: (err: NodeJS.ErrnoException) => void): void; + writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number; + writeSync(fd: number, data: any, position?: number, enconding?: string): number; + statSync(path: string): Stats; + stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + } = require("fs"); + + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false, + }); + + class Logger implements server.Logger { // tslint:disable-line no-unnecessary-qualifier + private fd = -1; + private seq = 0; + private inGroup = false; + private firstInGroup = true; + + constructor(private readonly logFilename: string, + private readonly traceToConsole: boolean, + private readonly level: LogLevel) { + if (this.logFilename) { + try { + this.fd = fs.openSync(this.logFilename, "w"); + } + catch (_) { + // swallow the error and keep logging disabled if file cannot be opened + } + } + } + + static padStringRight(str: string, padding: string) { + return (str + padding).slice(0, padding.length); + } + + close() { + if (this.fd >= 0) { + fs.close(this.fd, noop); + } + } + + getLogFileName() { + return this.logFilename; + } + + perftrc(s: string) { + this.msg(s, Msg.Perf); + } + + info(s: string) { + this.msg(s, Msg.Info); + } + + err(s: string) { + this.msg(s, Msg.Err); + } + + startGroup() { + this.inGroup = true; + this.firstInGroup = true; + } + + endGroup() { + this.inGroup = false; + } + + loggingEnabled() { + return !!this.logFilename || this.traceToConsole; + } + + hasLevel(level: LogLevel) { + return this.loggingEnabled() && this.level >= level; + } + + msg(s: string, type: Msg = Msg.Err) { + if (!this.canWrite) return; + + s = `[${nowString()}] ${s}\n`; + if (!this.inGroup || this.firstInGroup) { + const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " "); + s = prefix + s; + } + this.write(s); + if (!this.inGroup) { + this.seq++; + } + } + + private get canWrite() { + return this.fd >= 0 || this.traceToConsole; + } + + private write(s: string) { + if (this.fd >= 0) { + const buf = new Buffer(s); + // tslint:disable-next-line no-null-keyword + fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); + } + if (this.traceToConsole) { + console.warn(s); + } + } + } + + // E.g. "12:34:56.789" + function nowString() { + const d = new Date(); + return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`; + } + + interface QueuedOperation { + operationId: string; + operation: () => void; + } + + class NodeTypingsInstaller implements ITypingsInstaller { + private installer: NodeChildProcess; + private projectService: ProjectService; + private activeRequestCount = 0; + private requestQueue: QueuedOperation[] = []; + private requestMap = createMap(); // Maps operation ID to newest requestQueue entry with that ID + /** We will lazily request the types registry on the first call to `isKnownTypesPackageName` and store it in `typesRegistryCache`. */ + private requestedRegistry: boolean; + private typesRegistryCache: Map> | undefined; + + // This number is essentially arbitrary. Processing more than one typings request + // at a time makes sense, but having too many in the pipe results in a hang + // (see https://github.com/nodejs/node/issues/7657). + // It would be preferable to base our limit on the amount of space left in the + // buffer, but we have yet to find a way to retrieve that value. + private static readonly maxActiveRequestCount = 10; + private static readonly requestDelayMillis = 100; + private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void }; + + constructor( + private readonly telemetryEnabled: boolean, + private readonly logger: Logger, + private readonly host: ServerHost, + readonly globalTypingsCacheLocation: string, + readonly typingSafeListLocation: string, + readonly typesMapLocation: string, + private readonly npmLocation: string | undefined, + private event: Event) { + } + + isKnownTypesPackageName(name: string): boolean { + // We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package. + const validationResult = JsTyping.validatePackageName(name); + if (validationResult !== JsTyping.PackageNameValidationResult.Ok) { + return false; + } + + if (this.requestedRegistry) { + return !!this.typesRegistryCache && this.typesRegistryCache.has(name); + } + + this.requestedRegistry = true; + this.send({ kind: "typesRegistry" }); + return false; + } + + installPackage(options: InstallPackageOptionsWithProject): Promise { + const rq: InstallPackageRequest = { kind: "installPackage", ...options }; + this.send(rq); + Debug.assert(this.packageInstalledPromise === undefined); + return new Promise((resolve, reject) => { + this.packageInstalledPromise = { resolve, reject }; + }); + } + + attach(projectService: ProjectService) { + this.projectService = projectService; + if (this.logger.hasLevel(LogLevel.requestTime)) { + this.logger.info("Binding..."); + } + + const args: string[] = [Arguments.GlobalCacheLocation, this.globalTypingsCacheLocation]; + if (this.telemetryEnabled) { + args.push(Arguments.EnableTelemetry); + } + if (this.logger.loggingEnabled() && this.logger.getLogFileName()) { + args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName())), `ti-${process.pid}.log`)); + } + if (this.typingSafeListLocation) { + args.push(Arguments.TypingSafeListLocation, this.typingSafeListLocation); + } + if (this.typesMapLocation) { + args.push(Arguments.TypesMapLocation, this.typesMapLocation); + } + if (this.npmLocation) { + args.push(Arguments.NpmLocation, this.npmLocation); + } + + const execArgv: string[] = []; + for (const arg of process.execArgv) { + const match = /^--((?:debug|inspect)(?:-brk)?)(?:=(\d+))?$/.exec(arg); + if (match) { + // if port is specified - use port + 1 + // otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1 + const currentPort = match[2] !== undefined + ? +match[2] + : match[1].charAt(0) === "d" ? 5858 : 9229; + execArgv.push(`--${match[1]}=${currentPort + 1}`); + break; + } + } + + this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv }); + this.installer.on("message", m => this.handleMessage(m)); + + this.event({ pid: this.installer.pid }, "typingsInstallerPid"); + + process.on("exit", () => { + this.installer.kill(); + }); + } + + onProjectClosed(p: Project): void { + this.send({ projectName: p.getProjectName(), kind: "closeProject" }); + } + + private send(rq: TypingInstallerRequestUnion): void { + this.installer.send(rq); + } + + enqueueInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void { + const request = createInstallTypingsRequest(project, typeAcquisition, unresolvedImports); + if (this.logger.hasLevel(LogLevel.verbose)) { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Scheduling throttled operation:${stringifyIndented(request)}`); + } + } + + const operationId = project.getProjectName(); + const operation = () => { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Sending request:${stringifyIndented(request)}`); + } + this.send(request); + }; + const queuedRequest: QueuedOperation = { operationId, operation }; + + if (this.activeRequestCount < NodeTypingsInstaller.maxActiveRequestCount) { + this.scheduleRequest(queuedRequest); + } + else { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Deferring request for: ${operationId}`); + } + this.requestQueue.push(queuedRequest); + this.requestMap.set(operationId, queuedRequest); + } + } + + private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Received response:${stringifyIndented(response)}`); + } + + switch (response.kind) { + case EventTypesRegistry: + this.typesRegistryCache = createMapFromTemplate(response.typesRegistry); + break; + case ActionPackageInstalled: { + const { success, message } = response; + if (success) { + this.packageInstalledPromise.resolve({ successMessage: message }); + } + else { + this.packageInstalledPromise.reject(message); + } + this.packageInstalledPromise = undefined; + + this.projectService.updateTypingsForProject(response); + + // The behavior is the same as for setTypings, so send the same event. + this.event(response, "setTypings"); + break; + } + case EventInitializationFailed: + { + const body: protocol.TypesInstallerInitializationFailedEventBody = { + message: response.message + }; + const eventName: protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed"; + this.event(body, eventName); + break; + } + case EventBeginInstallTypes: + { + const body: protocol.BeginInstallTypesEventBody = { + eventId: response.eventId, + packages: response.packagesToInstall, + }; + const eventName: protocol.BeginInstallTypesEventName = "beginInstallTypes"; + this.event(body, eventName); + break; + } + case EventEndInstallTypes: + { + if (this.telemetryEnabled) { + const body: protocol.TypingsInstalledTelemetryEventBody = { + telemetryEventName: "typingsInstalled", + payload: { + installedPackages: response.packagesToInstall.join(","), + installSuccess: response.installSuccess, + typingsInstallerVersion: response.typingsInstallerVersion + } + }; + const eventName: protocol.TelemetryEventName = "telemetry"; + this.event(body, eventName); + } + + const body: protocol.EndInstallTypesEventBody = { + eventId: response.eventId, + packages: response.packagesToInstall, + success: response.installSuccess, + }; + const eventName: protocol.EndInstallTypesEventName = "endInstallTypes"; + this.event(body, eventName); + break; + } + case ActionInvalidate: + { + this.projectService.updateTypingsForProject(response); + break; + } + case ActionSet: + { + if (this.activeRequestCount > 0) { + this.activeRequestCount--; + } + else { + Debug.fail("Received too many responses"); + } + + while (this.requestQueue.length > 0) { + const queuedRequest = this.requestQueue.shift(); + if (this.requestMap.get(queuedRequest.operationId) === queuedRequest) { + this.requestMap.delete(queuedRequest.operationId); + this.scheduleRequest(queuedRequest); + break; + } + + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Skipping defunct request for: ${queuedRequest.operationId}`); + } + } + + this.projectService.updateTypingsForProject(response); + + this.event(response, "setTypings"); + + break; + } + default: + assertTypeIsNever(response); + } + } + + private scheduleRequest(request: QueuedOperation) { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Scheduling request for: ${request.operationId}`); + } + this.activeRequestCount++; + this.host.setTimeout(request.operation, NodeTypingsInstaller.requestDelayMillis); + } + } + + class IOSession extends Session { + private eventPort: number; + private eventSocket: NodeSocket | undefined; + private socketEventQueue: { body: any, eventName: string }[] | undefined; + private constructed: boolean | undefined; + + constructor() { + const event: Event | undefined = (body: object, eventName: string) => { + if (this.constructed) { + this.event(body, eventName); + } + else { + // It is unsafe to dereference `this` before initialization completes, + // so we defer until the next tick. + // + // Construction should finish before the next tick fires, so we do not need to do this recursively. + setImmediate(() => this.event(body, eventName)); + } + }; + + const host = sys; + + const typingsInstaller = disableAutomaticTypingAcquisition + ? undefined + : new NodeTypingsInstaller(telemetryEnabled, logger, host, getGlobalTypingsCacheLocation(), typingSafeListLocation, typesMapLocation, npmLocation, event); + + super({ + host, + cancellationToken, + useSingleInferredProject, + useInferredProjectPerProjectRoot, + typingsInstaller: typingsInstaller || nullTypingsInstaller, + byteLength: Buffer.byteLength, + hrtime: process.hrtime, + logger, + canUseEvents: true, + suppressDiagnosticEvents, + globalPlugins, + pluginProbeLocations, + allowLocalPluginLoads, + }); + + this.eventPort = eventPort; + if (this.canUseEvents && this.eventPort) { + const s = net.connect({ port: this.eventPort }, () => { + this.eventSocket = s; + if (this.socketEventQueue) { + // flush queue. + for (const event of this.socketEventQueue) { + this.writeToEventSocket(event.body, event.eventName); + } + this.socketEventQueue = undefined; + } + }); + } + + this.constructed = true; + } + + event(body: T, eventName: string): void { + Debug.assert(this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); + + if (this.canUseEvents && this.eventPort) { + if (!this.eventSocket) { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`eventPort: event "${eventName}" queued, but socket not yet initialized`); + } + (this.socketEventQueue || (this.socketEventQueue = [])).push({ body, eventName }); + return; + } + else { + Debug.assert(this.socketEventQueue === undefined); + this.writeToEventSocket(body, eventName); + } + } + else { + super.event(body, eventName); + } + } + + private writeToEventSocket(body: object, eventName: string): void { + this.eventSocket.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); + } + + exit() { + this.logger.info("Exiting..."); + this.projectService.closeLog(); + process.exit(0); + } + + listen() { + rl.on("line", (input: string) => { + const message = input.trim(); + this.onMessage(message); + }); + + rl.on("close", () => { + this.exit(); + }); + } + } + + interface LogOptions { + file?: string; + detailLevel?: LogLevel; + traceToConsole?: boolean; + logToFile?: boolean; + } + + function parseLoggingEnvironmentString(logEnvStr: string): LogOptions { + if (!logEnvStr) { + return {}; + } + const logEnv: LogOptions = { logToFile: true }; + const args = logEnvStr.split(" "); + const len = args.length - 1; + for (let i = 0; i < len; i += 2) { + const option = args[i]; + const value = args[i + 1]; + if (option && value) { + switch (option) { + case "-file": + logEnv.file = stripQuotes(value); + break; + case "-level": + const level = getLogLevel(value); + logEnv.detailLevel = level !== undefined ? level : LogLevel.normal; + break; + case "-traceToConsole": + logEnv.traceToConsole = value.toLowerCase() === "true"; + break; + case "-logToFile": + logEnv.logToFile = value.toLowerCase() === "true"; + break; + } + } + } + return logEnv; + } + + function getLogLevel(level: string) { + if (level) { + const l = level.toLowerCase(); + for (const name in LogLevel) { + if (isNaN(+name) && l === name.toLowerCase()) { + return LogLevel[name]; + } + } + } + return undefined; + } + + // TSS_LOG "{ level: "normal | verbose | terse", file?: string}" + function createLogger() { + const cmdLineLogFileName = findArgument("--logFile"); + const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity")); + const envLogOptions = parseLoggingEnvironmentString(process.env.TSS_LOG); + + const logFileName = cmdLineLogFileName + ? stripQuotes(cmdLineLogFileName) + : envLogOptions.logToFile + ? envLogOptions.file || (__dirname + "/.log" + process.pid.toString()) + : undefined; + + const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel; + return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity); + } + // This places log file in the directory containing editorServices.js + // TODO: check that this location is writable + + // average async stat takes about 30 microseconds + // set chunk size to do 30 files in < 1 millisecond + function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) { + const watchedFiles: WatchedFile[] = []; + let nextFileToCheck = 0; + return { getModifiedTime, poll, startWatchTimer, addFile, removeFile }; + + function getModifiedTime(fileName: string): Date { + return fs.statSync(fileName).mtime; + } + + function poll(checkedIndex: number) { + const watchedFile = watchedFiles[checkedIndex]; + if (!watchedFile) { + return; + } + + fs.stat(watchedFile.fileName, (err, stats) => { + if (err) { + if (err.code === "ENOENT") { + if (watchedFile.mtime.getTime() !== 0) { + watchedFile.mtime = missingFileModifiedTime; + watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Deleted); + } + } + else { + watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Changed); + } + } + else { + onWatchedFileStat(watchedFile, stats.mtime); + } + }); + } + + // this implementation uses polling and + // stat due to inconsistencies of fs.watch + // and efficiency of stat on modern filesystems + function startWatchTimer() { + setInterval(() => { + let count = 0; + let nextToCheck = nextFileToCheck; + let firstCheck = -1; + while ((count < chunkSize) && (nextToCheck !== firstCheck)) { + poll(nextToCheck); + if (firstCheck < 0) { + firstCheck = nextToCheck; + } + nextToCheck++; + if (nextToCheck === watchedFiles.length) { + nextToCheck = 0; + } + count++; + } + nextFileToCheck = nextToCheck; + }, interval); + } + + function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile { + const file: WatchedFile = { + fileName, + callback, + mtime: sys.fileExists(fileName) + ? getModifiedTime(fileName) + : missingFileModifiedTime // Any subsequent modification will occur after this time + }; + + watchedFiles.push(file); + if (watchedFiles.length === 1) { + startWatchTimer(); + } + return file; + } + + function removeFile(file: WatchedFile) { + unorderedRemoveItem(watchedFiles, file); + } + } + + // REVIEW: for now this implementation uses polling. + // The advantage of polling is that it works reliably + // on all os and with network mounted files. + // For 90 referenced files, the average time to detect + // changes is 2*msInterval (by default 5 seconds). + // The overhead of this is .04 percent (1/2500) with + // average pause of < 1 millisecond (and max + // pause less than 1.5 milliseconds); question is + // do we anticipate reference sets in the 100s and + // do we care about waiting 10-20 seconds to detect + // changes for large reference sets? If so, do we want + // to increase the chunk size or decrease the interval + // time dynamically to match the large reference set? + const pollingWatchedFileSet = createPollingWatchedFileSet(); + + const pending: Buffer[] = []; + let canWrite = true; + + function writeMessage(buf: Buffer) { + if (!canWrite) { + pending.push(buf); + } + else { + canWrite = false; + process.stdout.write(buf, setCanWriteFlagAndWriteMessageIfNecessary); + } + } + + function setCanWriteFlagAndWriteMessageIfNecessary() { + canWrite = true; + if (pending.length) { + writeMessage(pending.shift()); + } + } + + function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string) { + path = normalizeSlashes(path); + if (isUNCPath(path)) { + // UNC path: extract server name + // //server/location + // ^ <- from 0 to this position + const firstSlash = path.indexOf(directorySeparator, 2); + return firstSlash !== -1 ? path.substring(0, firstSlash).toLowerCase() : path; + } + const rootLength = getRootLength(path); + if (rootLength === 0) { + // relative path - assume file is on the current drive + return currentDriveKey; + } + if (path.charCodeAt(1) === CharacterCodes.colon && path.charCodeAt(2) === CharacterCodes.slash) { + // rooted path that starts with c:/... - extract drive letter + return path.charAt(0).toLowerCase(); + } + if (path.charCodeAt(0) === CharacterCodes.slash && path.charCodeAt(1) !== CharacterCodes.slash) { + // rooted path that starts with slash - /somename - use key for current drive + return currentDriveKey; + } + // do not cache any other cases + return undefined; + } + + function isUNCPath(s: string): boolean { + return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash; + } + + const logger = createLogger(); + + const sys = ts.sys; + const nodeVersion = getNodeMajorVersion(); + // use watchGuard process on Windows when node version is 4 or later + const useWatchGuard = process.platform === "win32" && nodeVersion >= 4; + const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys); + const noopWatcher: FileWatcher = { close: noop }; + // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function + // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point + function watchDirectorySwallowingException(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher { + try { + return originalWatchDirectory(path, callback, recursive); + } + catch (e) { + logger.info(`Exception when creating directory watcher: ${e.message}`); + return noopWatcher; + } + } + + if (useWatchGuard) { + const currentDrive = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined); + const statusCache = createMap(); + sys.watchDirectory = (path, callback, recursive) => { + const cacheKey = extractWatchDirectoryCacheKey(path, currentDrive); + let status = cacheKey && statusCache.get(cacheKey); + if (status === undefined) { + if (logger.hasLevel(LogLevel.verbose)) { + logger.info(`${cacheKey} for path ${path} not found in cache...`); + } + try { + const args = [combinePaths(__dirname, "watchGuard.js"), path]; + if (logger.hasLevel(LogLevel.verbose)) { + logger.info(`Starting ${process.execPath} with args:${stringifyIndented(args)}`); + } + childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { ELECTRON_RUN_AS_NODE: "1" } }); + status = true; + if (logger.hasLevel(LogLevel.verbose)) { + logger.info(`WatchGuard for path ${path} returned: OK`); + } + } + catch (e) { + status = false; + if (logger.hasLevel(LogLevel.verbose)) { + logger.info(`WatchGuard for path ${path} returned: ${e.message}`); + } + } + if (cacheKey) { + statusCache.set(cacheKey, status); + } + } + else if (logger.hasLevel(LogLevel.verbose)) { + logger.info(`watchDirectory for ${path} uses cached drive information.`); + } + if (status) { + // this drive is safe to use - call real 'watchDirectory' + return watchDirectorySwallowingException(path, callback, recursive); + } + else { + // this drive is unsafe - return no-op watcher + return noopWatcher; + } + }; + } + else { + sys.watchDirectory = watchDirectorySwallowingException; + } + + // Override sys.write because fs.writeSync is not reliable on Node 4 + sys.write = (s: string) => writeMessage(new Buffer(s, "utf8")); + sys.watchFile = (fileName, callback) => { + const watchedFile = pollingWatchedFileSet.addFile(fileName, callback); + return { + close: () => pollingWatchedFileSet.removeFile(watchedFile) + }; + }; + + sys.setTimeout = setTimeout; + sys.clearTimeout = clearTimeout; + sys.setImmediate = setImmediate; + sys.clearImmediate = clearImmediate; + if (typeof global !== "undefined" && global.gc) { + sys.gc = () => global.gc(); + } + + sys.require = (initialDir: string, moduleName: string): RequireResult => { + try { + return { module: require(resolveJavaScriptModule(moduleName, initialDir, sys)), error: undefined }; + } + catch (error) { + return { module: undefined, error }; + } + }; + + let cancellationToken: ServerCancellationToken; + try { + const factory = require("./cancellationToken"); + cancellationToken = factory(sys.args); + } + catch (e) { + cancellationToken = nullCancellationToken; + } + + let eventPort: number | undefined; + { + const str = findArgument("--eventPort"); + const v = str && parseInt(str); + if (!isNaN(v)) { + eventPort = v; + } + } + + const localeStr = findArgument("--locale"); + if (localeStr) { + validateLocaleAndSetLanguage(localeStr, sys); + } + + setStackTraceLimit(); + + const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation); + const typesMapLocation = findArgument(Arguments.TypesMapLocation) || combinePaths(sys.getExecutingFilePath(), "../typesMap.json"); + const npmLocation = findArgument(Arguments.NpmLocation); + + function parseStringArray(argName: string): ReadonlyArray { + const arg = findArgument(argName); + if (arg === undefined) { + return emptyArray; + } + return arg.split(",").filter(name => name !== ""); + } + + const globalPlugins = parseStringArray("--globalPlugins"); + const pluginProbeLocations = parseStringArray("--pluginProbeLocations"); + const allowLocalPluginLoads = hasArgument("--allowLocalPluginLoads"); + + const useSingleInferredProject = hasArgument("--useSingleInferredProject"); + const useInferredProjectPerProjectRoot = hasArgument("--useInferredProjectPerProjectRoot"); + const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); + const suppressDiagnosticEvents = hasArgument("--suppressDiagnosticEvents"); + const telemetryEnabled = hasArgument(Arguments.EnableTelemetry); + + logger.info(`Starting TS Server`); + logger.info(`Version: ${version}`); + logger.info(`Arguments: ${process.argv.join(" ")}`); + logger.info(`Platform: ${os.platform()} NodeVersion: ${nodeVersion} CaseSensitive: ${sys.useCaseSensitiveFileNames}`); + + const ioSession = new IOSession(); + process.on("uncaughtException", err => { + ioSession.logError(err, "unknown"); + }); + // See https://github.com/Microsoft/TypeScript/issues/11348 + // tslint:disable-next-line no-unnecessary-type-assertion-2 + (process as any).noAsar = true; + // Start listening + ioSession.listen(); +} diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index 7de070d1099c7..d63837e7dd4c2 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -13,8 +13,7 @@ namespace ts.codefix { }); function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker): void { - const deletedNodes: Node[] = []; - const deletes: (() => void)[] = []; + const deletedNodes: { node: Node, inList: boolean }[] = []; const ctorSymbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false)); if (!ctorSymbol || !(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) { @@ -49,23 +48,23 @@ namespace ts.codefix { return undefined; } + copyComments(ctorDeclaration, newClassDeclaration, sourceFile); + // Because the preceding node could be touched, we need to insert nodes before delete nodes. changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); - for (const deleteCallback of deletes) { - deleteCallback(); - } - - function deleteNode(node: Node, inList = false) { - if (deletedNodes.some(n => isNodeDescendantOf(node, n))) { - // Parent node has already been deleted; do nothing - return; - } - deletedNodes.push(node); + for (const { node, inList } of deletedNodes) { if (inList) { - deletes.push(() => changes.deleteNodeInList(sourceFile, node)); + changes.deleteNodeInList(sourceFile, node); } else { - deletes.push(() => changes.deleteNode(sourceFile, node)); + changes.deleteNode(sourceFile, node); + } + } + + function deleteNode(node: Node, inList = false) { + // If parent node has already been deleted, do nothing + if (!deletedNodes.some(n => isNodeDescendantOf(node, n.node))) { + deletedNodes.push({ node, inList }); } } diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index f6489fce6d208..b4999e968fbda 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -98,7 +98,7 @@ namespace ts.OrganizeImports { } else { // List of named imports - const newElements = namedBindings.elements.filter(e => isDeclarationUsed(e.propertyName || e.name)); + const newElements = namedBindings.elements.filter(e => isDeclarationUsed(e.name)); if (newElements.length < namedBindings.elements.length) { namedBindings = newElements.length ? updateNamedImports(namedBindings, newElements) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index c3ab35c923b1c..da92e5ab6060e 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -134,11 +134,7 @@ namespace ts.textChanges { readonly options?: ChangeNodeOptions; } - export function getSeparatorCharacter(separator: Token) { - return tokenToString(separator.kind); - } - - export function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStart, position: Position) { + function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStart, position: Position) { if (options.useNonAdjustedStartPosition) { return node.getStart(sourceFile); } @@ -168,7 +164,7 @@ namespace ts.textChanges { return getStartPositionOfLine(getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile); } - export function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: ConfigurableEnd) { + function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: ConfigurableEnd) { if (options.useNonAdjustedEndPosition || isExpression(node)) { return node.getEnd(); } @@ -225,6 +221,7 @@ namespace ts.textChanges { return this; } + /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ public deleteNode(sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = {}) { const startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart); const endPosition = getAdjustedEndPosition(sourceFile, node, options); @@ -638,7 +635,7 @@ namespace ts.textChanges { // order changes by start position const normalized = stableSort(changesInFile, (a, b) => a.range.pos - b.range.pos); // verify that change intervals do not overlap, except possibly at end points. - for (let i = 0; i < normalized.length - 2; i++) { + for (let i = 0; i < normalized.length - 1; i++) { Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", () => `${JSON.stringify(normalized[i].range)} and ${JSON.stringify(normalized[i + 1].range)}`); } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 09887d9dffa4a..2772b8920e79a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1499,17 +1499,4 @@ namespace ts { function getFirstChild(node: Node): Node | undefined { return node.forEachChild(child => child); } - - function getLastChild(node: Node): Node | undefined { - let lastChild: Node | undefined; - node.forEachChild( - child => { lastChild = child; }, - children => { - // As an optimization, jump straight to the end of the list. - if (children.length) { - lastChild = last(children); - } - }); - return lastChild; - } } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b26ca2f3b9804..4045f2212a1c9 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2842,7 +2842,7 @@ declare namespace ts { } } declare namespace ts { - const versionMajorMinor = "2.8"; + const versionMajorMinor = "2.9"; /** The version of the TypeScript compiler release */ const version: string; } diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0699d3fffb70d..3af5746213ecf 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2842,7 +2842,7 @@ declare namespace ts { } } declare namespace ts { - const versionMajorMinor = "2.8"; + const versionMajorMinor = "2.9"; /** The version of the TypeScript compiler release */ const version: string; } diff --git a/tests/baselines/reference/organizeImports/Renamed_used.ts b/tests/baselines/reference/organizeImports/Renamed_used.ts new file mode 100644 index 0000000000000..5e9395e9ef5fb --- /dev/null +++ b/tests/baselines/reference/organizeImports/Renamed_used.ts @@ -0,0 +1,9 @@ +// ==ORIGINAL== + +import { F1 as EffOne, F2 as EffTwo } from "lib"; +EffOne(); + +// ==ORGANIZED== + +import { F1 as EffOne } from "lib"; +EffOne(); diff --git a/tests/baselines/reference/typeFromPropertyAssignment20.symbols b/tests/baselines/reference/typeFromPropertyAssignment20.symbols new file mode 100644 index 0000000000000..c7e035aaab411 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment20.symbols @@ -0,0 +1,35 @@ +=== tests/cases/conformance/salsa/bluebird.js === +!function outer (f) { return f }( +>outer : Symbol(outer, Decl(bluebird.js, 0, 1)) +>f : Symbol(f, Decl(bluebird.js, 0, 17)) +>f : Symbol(f, Decl(bluebird.js, 0, 17)) + + function inner () { +>inner : Symbol(inner, Decl(bluebird.js, 0, 33)) + + function Async() { +>Async : Symbol(Async, Decl(bluebird.js, 1, 23)) + + this._trampolineEnabled = true; +>_trampolineEnabled : Symbol(Async._trampolineEnabled, Decl(bluebird.js, 2, 26), Decl(bluebird.js, 7, 20)) + } + + Async.prototype.disableTrampolineIfNecessary = function dtin(b) { +>Async.prototype : Symbol(Async.disableTrampolineIfNecessary, Decl(bluebird.js, 4, 9)) +>Async : Symbol(Async, Decl(bluebird.js, 1, 23)) +>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --)) +>disableTrampolineIfNecessary : Symbol(Async.disableTrampolineIfNecessary, Decl(bluebird.js, 4, 9)) +>dtin : Symbol(dtin, Decl(bluebird.js, 6, 54)) +>b : Symbol(b, Decl(bluebird.js, 6, 69)) + + if (b) { +>b : Symbol(b, Decl(bluebird.js, 6, 69)) + + this._trampolineEnabled = false; +>this._trampolineEnabled : Symbol(Async._trampolineEnabled, Decl(bluebird.js, 2, 26), Decl(bluebird.js, 7, 20)) +>this : Symbol(Async, Decl(bluebird.js, 1, 23)) +>_trampolineEnabled : Symbol(Async._trampolineEnabled, Decl(bluebird.js, 2, 26), Decl(bluebird.js, 7, 20)) + } + }; + }) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment20.types b/tests/baselines/reference/typeFromPropertyAssignment20.types new file mode 100644 index 0000000000000..85265a97c84e2 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment20.types @@ -0,0 +1,48 @@ +=== tests/cases/conformance/salsa/bluebird.js === +!function outer (f) { return f }( +>!function outer (f) { return f }( function inner () { function Async() { this._trampolineEnabled = true; } Async.prototype.disableTrampolineIfNecessary = function dtin(b) { if (b) { this._trampolineEnabled = false; } }; }) : boolean +>function outer (f) { return f }( function inner () { function Async() { this._trampolineEnabled = true; } Async.prototype.disableTrampolineIfNecessary = function dtin(b) { if (b) { this._trampolineEnabled = false; } }; }) : () => void +>function outer (f) { return f } : (f: () => void) => () => void +>outer : (f: () => void) => () => void +>f : () => void +>f : () => void + + function inner () { +>function inner () { function Async() { this._trampolineEnabled = true; } Async.prototype.disableTrampolineIfNecessary = function dtin(b) { if (b) { this._trampolineEnabled = false; } }; } : () => void +>inner : () => void + + function Async() { +>Async : () => void + + this._trampolineEnabled = true; +>this._trampolineEnabled = true : true +>this._trampolineEnabled : any +>this : any +>_trampolineEnabled : any +>true : true + } + + Async.prototype.disableTrampolineIfNecessary = function dtin(b) { +>Async.prototype.disableTrampolineIfNecessary = function dtin(b) { if (b) { this._trampolineEnabled = false; } } : (b: any) => void +>Async.prototype.disableTrampolineIfNecessary : any +>Async.prototype : any +>Async : () => void +>prototype : any +>disableTrampolineIfNecessary : any +>function dtin(b) { if (b) { this._trampolineEnabled = false; } } : (b: any) => void +>dtin : (b: any) => void +>b : any + + if (b) { +>b : any + + this._trampolineEnabled = false; +>this._trampolineEnabled = false : false +>this._trampolineEnabled : boolean +>this : { _trampolineEnabled: boolean; disableTrampolineIfNecessary: (b: any) => void; } +>_trampolineEnabled : boolean +>false : false + } + }; + }) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment21.errors.txt b/tests/baselines/reference/typeFromPropertyAssignment21.errors.txt new file mode 100644 index 0000000000000..27ac5b8b5061f --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment21.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/salsa/chrome-devtools-DOMExtension.js(2,17): error TS2339: Property 'removeChildren' does not exist on type 'Event'. +tests/cases/conformance/salsa/chrome-devtools-DOMExtension.js(3,10): error TS2339: Property 'textContent' does not exist on type 'Event'. + + +==== tests/cases/conformance/salsa/chrome-devtools-DOMExtension.js (2 errors) ==== + // Extend that DOM! (doesn't work, but shouldn't crash) + Event.prototype.removeChildren = function () { + ~~~~~~~~~~~~~~ +!!! error TS2339: Property 'removeChildren' does not exist on type 'Event'. + this.textContent = 'nope, not going to happen' + ~~~~~~~~~~~ +!!! error TS2339: Property 'textContent' does not exist on type 'Event'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeFromPropertyAssignment21.symbols b/tests/baselines/reference/typeFromPropertyAssignment21.symbols new file mode 100644 index 0000000000000..5ed1c655d4af9 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment21.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/salsa/chrome-devtools-DOMExtension.js === +// Extend that DOM! (doesn't work, but shouldn't crash) +Event.prototype.removeChildren = function () { +>Event.prototype : Symbol(prototype, Decl(lib.dom.d.ts, --, --)) +>Event : Symbol(Event, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>prototype : Symbol(prototype, Decl(lib.dom.d.ts, --, --)) + + this.textContent = 'nope, not going to happen' +>this : Symbol(Event, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +} + diff --git a/tests/baselines/reference/typeFromPropertyAssignment21.types b/tests/baselines/reference/typeFromPropertyAssignment21.types new file mode 100644 index 0000000000000..34aba8d078d26 --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment21.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/salsa/chrome-devtools-DOMExtension.js === +// Extend that DOM! (doesn't work, but shouldn't crash) +Event.prototype.removeChildren = function () { +>Event.prototype.removeChildren = function () { this.textContent = 'nope, not going to happen'} : () => void +>Event.prototype.removeChildren : any +>Event.prototype : Event +>Event : { new (typeArg: string, eventInitDict?: EventInit): Event; prototype: Event; readonly AT_TARGET: number; readonly BUBBLING_PHASE: number; readonly CAPTURING_PHASE: number; readonly NONE: number; } +>prototype : Event +>removeChildren : any +>function () { this.textContent = 'nope, not going to happen'} : () => void + + this.textContent = 'nope, not going to happen' +>this.textContent = 'nope, not going to happen' : "nope, not going to happen" +>this.textContent : any +>this : Event +>textContent : any +>'nope, not going to happen' : "nope, not going to happen" +} + diff --git a/tests/baselines/reference/typeFromPropertyAssignment22.errors.txt b/tests/baselines/reference/typeFromPropertyAssignment22.errors.txt new file mode 100644 index 0000000000000..969824cb33fbf --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment22.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/salsa/npm-install.js(12,1): error TS2322: Type 'string | number' is not assignable to type 'number | undefined'. + Type 'string' is not assignable to type 'number | undefined'. + + +==== tests/cases/conformance/salsa/npm-install.js (1 errors) ==== + function Installer () { + this.args = 0 + } + Installer.prototype.loadArgMetadata = function (next) { + // ArrowFunction isn't treated as a this-container + (args) => { + this.args = 'hi' + this.newProperty = 1 + } + } + var i = new Installer() + i.newProperty = i.args // error, number | string =/> number | undefined + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'string | number' is not assignable to type 'number | undefined'. +!!! error TS2322: Type 'string' is not assignable to type 'number | undefined'. + \ No newline at end of file diff --git a/tests/baselines/reference/typeFromPropertyAssignment22.symbols b/tests/baselines/reference/typeFromPropertyAssignment22.symbols new file mode 100644 index 0000000000000..2591f0f5a73de --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment22.symbols @@ -0,0 +1,41 @@ +=== tests/cases/conformance/salsa/npm-install.js === +function Installer () { +>Installer : Symbol(Installer, Decl(npm-install.js, 0, 0)) + + this.args = 0 +>args : Symbol(Installer.args, Decl(npm-install.js, 0, 23), Decl(npm-install.js, 5, 15)) +} +Installer.prototype.loadArgMetadata = function (next) { +>Installer.prototype : Symbol(Installer.loadArgMetadata, Decl(npm-install.js, 2, 1)) +>Installer : Symbol(Installer, Decl(npm-install.js, 0, 0)) +>prototype : Symbol(Function.prototype, Decl(lib.d.ts, --, --)) +>loadArgMetadata : Symbol(Installer.loadArgMetadata, Decl(npm-install.js, 2, 1)) +>next : Symbol(next, Decl(npm-install.js, 3, 48)) + + // ArrowFunction isn't treated as a this-container + (args) => { +>args : Symbol(args, Decl(npm-install.js, 5, 5)) + + this.args = 'hi' +>this.args : Symbol(Installer.args, Decl(npm-install.js, 0, 23), Decl(npm-install.js, 5, 15)) +>this : Symbol(Installer, Decl(npm-install.js, 0, 0)) +>args : Symbol(Installer.args, Decl(npm-install.js, 0, 23), Decl(npm-install.js, 5, 15)) + + this.newProperty = 1 +>this.newProperty : Symbol(Installer.newProperty, Decl(npm-install.js, 6, 24)) +>this : Symbol(Installer, Decl(npm-install.js, 0, 0)) +>newProperty : Symbol(Installer.newProperty, Decl(npm-install.js, 6, 24)) + } +} +var i = new Installer() +>i : Symbol(i, Decl(npm-install.js, 10, 3)) +>Installer : Symbol(Installer, Decl(npm-install.js, 0, 0)) + +i.newProperty = i.args // error, number | string =/> number | undefined +>i.newProperty : Symbol(Installer.newProperty, Decl(npm-install.js, 6, 24)) +>i : Symbol(i, Decl(npm-install.js, 10, 3)) +>newProperty : Symbol(Installer.newProperty, Decl(npm-install.js, 6, 24)) +>i.args : Symbol(Installer.args, Decl(npm-install.js, 0, 23), Decl(npm-install.js, 5, 15)) +>i : Symbol(i, Decl(npm-install.js, 10, 3)) +>args : Symbol(Installer.args, Decl(npm-install.js, 0, 23), Decl(npm-install.js, 5, 15)) + diff --git a/tests/baselines/reference/typeFromPropertyAssignment22.types b/tests/baselines/reference/typeFromPropertyAssignment22.types new file mode 100644 index 0000000000000..888a9f6efc4ae --- /dev/null +++ b/tests/baselines/reference/typeFromPropertyAssignment22.types @@ -0,0 +1,55 @@ +=== tests/cases/conformance/salsa/npm-install.js === +function Installer () { +>Installer : () => void + + this.args = 0 +>this.args = 0 : 0 +>this.args : any +>this : any +>args : any +>0 : 0 +} +Installer.prototype.loadArgMetadata = function (next) { +>Installer.prototype.loadArgMetadata = function (next) { // ArrowFunction isn't treated as a this-container (args) => { this.args = 'hi' this.newProperty = 1 }} : (next: any) => void +>Installer.prototype.loadArgMetadata : any +>Installer.prototype : any +>Installer : () => void +>prototype : any +>loadArgMetadata : any +>function (next) { // ArrowFunction isn't treated as a this-container (args) => { this.args = 'hi' this.newProperty = 1 }} : (next: any) => void +>next : any + + // ArrowFunction isn't treated as a this-container + (args) => { +>(args) => { this.args = 'hi' this.newProperty = 1 } : (args: any) => void +>args : any + + this.args = 'hi' +>this.args = 'hi' : "hi" +>this.args : string | number +>this : { args: string | number; loadArgMetadata: (next: any) => void; newProperty: number | undefined; } +>args : string | number +>'hi' : "hi" + + this.newProperty = 1 +>this.newProperty = 1 : 1 +>this.newProperty : number | undefined +>this : { args: string | number; loadArgMetadata: (next: any) => void; newProperty: number | undefined; } +>newProperty : number | undefined +>1 : 1 + } +} +var i = new Installer() +>i : { args: string | number; loadArgMetadata: (next: any) => void; newProperty: number | undefined; } +>new Installer() : { args: string | number; loadArgMetadata: (next: any) => void; newProperty: number | undefined; } +>Installer : () => void + +i.newProperty = i.args // error, number | string =/> number | undefined +>i.newProperty = i.args : string | number +>i.newProperty : number | undefined +>i : { args: string | number; loadArgMetadata: (next: any) => void; newProperty: number | undefined; } +>newProperty : number | undefined +>i.args : string | number +>i : { args: string | number; loadArgMetadata: (next: any) => void; newProperty: number | undefined; } +>args : string | number + diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment20.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment20.ts new file mode 100644 index 0000000000000..13214cbf4480e --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment20.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @Filename: bluebird.js + +!function outer (f) { return f }( + function inner () { + function Async() { + this._trampolineEnabled = true; + } + + Async.prototype.disableTrampolineIfNecessary = function dtin(b) { + if (b) { + this._trampolineEnabled = false; + } + }; + }) diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment21.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment21.ts new file mode 100644 index 0000000000000..968a8206c195e --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment21.ts @@ -0,0 +1,10 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @lib: dom, es5 +// @Filename: chrome-devtools-DOMExtension.js + +// Extend that DOM! (doesn't work, but shouldn't crash) +Event.prototype.removeChildren = function () { + this.textContent = 'nope, not going to happen' +} diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment22.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment22.ts new file mode 100644 index 0000000000000..75bc2c62b90c0 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment22.ts @@ -0,0 +1,17 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @strictNullChecks: true +// @Filename: npm-install.js +function Installer () { + this.args = 0 +} +Installer.prototype.loadArgMetadata = function (next) { + // ArrowFunction isn't treated as a this-container + (args) => { + this.args = 'hi' + this.newProperty = 1 + } +} +var i = new Installer() +i.newProperty = i.args // error, number | string =/> number | undefined diff --git a/tests/cases/fourslash/server/convertFunctionToEs6Class-server.ts b/tests/cases/fourslash/server/convertFunctionToEs6Class-server.ts index 498c976e71ecb..24a7acbf8edc5 100644 --- a/tests/cases/fourslash/server/convertFunctionToEs6Class-server.ts +++ b/tests/cases/fourslash/server/convertFunctionToEs6Class-server.ts @@ -14,9 +14,8 @@ verify.codeFix({ description: "Convert function to an ES2015 class", newFileContent: -// NOTE: '// Comment' should be included, but due to incorrect handling of trivia, -// it's omitted right now. -`class fn {\r +`// Comment\r +class fn {\r constructor() {\r this.baz = 10;\r }\r