From c8bd33e1ba89aa36afceb081def28b45a154522c Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 2 Aug 2024 10:36:21 +1000 Subject: [PATCH 1/7] Update TypeScript (#15910) --- package-lock.json | 926 +--------------------------------------------- package.json | 3 +- 2 files changed, 8 insertions(+), 921 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a87499bfd4..c261c735b0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -183,7 +183,6 @@ "gulp": "^5.0.0", "gulp-filter": "^7.0.0", "gulp-rename": "^2.0.0", - "gulp-typescript": "^6.0.0-alpha.1", "husky": "^8.0.3", "jsdom": "^22.1.0", "json2csv": "^5.0.7", @@ -223,7 +222,7 @@ "tsconfig-paths-webpack-plugin": "^3.2.0", "tsx": "^3.13.0", "typemoq": "^2.1.0", - "typescript": "^5.4.5", + "typescript": "^5.5.4", "unicode-properties": "^1.3.1", "utf-8-validate": "^5.0.8", "util": "^0.12.4", @@ -4893,30 +4892,6 @@ "node": ">= 8" } }, - "node_modules/append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", - "dev": true, - "dependencies": { - "buffer-equal": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/append-buffer/node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", @@ -6396,15 +6371,6 @@ "node": ">=0.8" } }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -6437,38 +6403,6 @@ "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", "dev": true }, - "node_modules/cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "node_modules/cloneable-readable/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/cloneable-readable/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/cls-hooked": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", @@ -9485,37 +9419,6 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/flush-write-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/flush-write-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/fontkit": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.1.tgz", @@ -9660,19 +9563,6 @@ "node": ">= 8" } }, - "node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/fs-walk": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/fs-walk/-/fs-walk-0.0.1.tgz", @@ -9895,60 +9785,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-stream/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/glob-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -10282,36 +10118,6 @@ "node": ">=4" } }, - "node_modules/gulp-typescript": { - "version": "6.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz", - "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1", - "plugin-error": "^1.0.1", - "source-map": "^0.7.3", - "through2": "^3.0.1", - "vinyl": "^2.2.0", - "vinyl-fs": "^3.0.3" - }, - "engines": { - "node": ">= 8" - }, - "peerDependencies": { - "typescript": "~2.7.1 || >=2.8.0-dev || >=2.9.0-dev || ~3.0.0 || >=3.0.0-dev || >=3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev " - } - }, - "node_modules/gulp-typescript/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, "node_modules/gulp/node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -11593,12 +11399,6 @@ "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true - }, "node_modules/is-valid-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", @@ -12588,51 +12388,6 @@ "node": ">= 10.13.0" } }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", - "dev": true, - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/less": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", @@ -13873,18 +13628,6 @@ "node": ">=0.10.0" } }, - "node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -14420,36 +14163,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/ordered-read-streams/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/ordered-read-streams/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -16410,48 +16123,12 @@ "node": ">=4" } }, - "node_modules/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, - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", - "dev": true, - "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", "dev": true }, - "node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/replace-homedir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", @@ -16543,18 +16220,6 @@ "node": ">=4" } }, - "node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", - "dev": true, - "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/resolve-path": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", @@ -18328,16 +17993,6 @@ "xtend": "~4.0.1" } }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, "node_modules/through2/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -18430,18 +18085,6 @@ "node": ">=8.0" } }, - "node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", - "dev": true, - "dependencies": { - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -19452,9 +19095,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -19568,16 +19211,6 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, "node_modules/universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -19780,15 +19413,6 @@ "node": ">= 0.10" } }, - "node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -19798,23 +19422,6 @@ "node": ">= 0.8" } }, - "node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/vinyl-contents": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", @@ -19862,94 +19469,6 @@ "node": ">=10.13.0" } }, - "node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-fs/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/vinyl-fs/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", - "dev": true, - "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vinyl/node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -24117,23 +23636,6 @@ "picomatch": "^2.0.4" } }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - }, - "dependencies": { - "buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true - } - } - }, "append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", @@ -25268,12 +24770,6 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", - "dev": true - }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -25302,40 +24798,6 @@ "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", "dev": true }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "1.3.0", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "cls-hooked": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", @@ -27666,39 +27128,6 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "1.3.0", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "fontkit": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.1.tgz", @@ -27804,16 +27233,6 @@ "minipass": "^3.0.0" } }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, "fs-walk": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/fs-walk/-/fs-walk-0.0.1.tgz", @@ -27969,56 +27388,6 @@ "is-glob": "^4.0.3" } }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "5.1.2", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "1.3.0", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -28397,32 +27766,6 @@ "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", "dev": true }, - "gulp-typescript": { - "version": "6.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz", - "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1", - "plugin-error": "^1.0.1", - "source-map": "^0.7.3", - "through2": "^3.0.1", - "vinyl": "^2.2.0", - "vinyl-fs": "^3.0.3" - }, - "dependencies": { - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } - } - }, "gulplog": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", @@ -29209,12 +28552,6 @@ "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true - }, "is-valid-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", @@ -29987,47 +29324,6 @@ "integrity": "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==", "dev": true }, - "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "1.3.0", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, "less": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", @@ -30999,15 +30295,6 @@ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, "npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -31416,38 +30703,6 @@ "type-check": "^0.4.0" } }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "1.3.0", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -32775,39 +32030,12 @@ "es6-error": "^4.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.5", - "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": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "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", "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", "dev": true }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, "replace-homedir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", @@ -32874,15 +32102,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, "resolve-path": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", @@ -34289,16 +33508,6 @@ } } }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, "timers-browserify": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", @@ -34351,15 +33560,6 @@ "is-number": "^7.0.0" } }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -35024,9 +34224,9 @@ } }, "typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true }, "uint64be": { @@ -35127,16 +34327,6 @@ } } }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, "universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -35291,40 +34481,12 @@ "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", "dev": true }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", - "dev": true - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "dependencies": { - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true - } - } - }, "vinyl-contents": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", @@ -35362,80 +34524,6 @@ } } }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "1.3.0", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/package.json b/package.json index 74819f1d03f..1fbe99bd722 100644 --- a/package.json +++ b/package.json @@ -2290,7 +2290,6 @@ "gulp": "^5.0.0", "gulp-filter": "^7.0.0", "gulp-rename": "^2.0.0", - "gulp-typescript": "^6.0.0-alpha.1", "husky": "^8.0.3", "jsdom": "^22.1.0", "json2csv": "^5.0.7", @@ -2330,7 +2329,7 @@ "tsconfig-paths-webpack-plugin": "^3.2.0", "tsx": "^3.13.0", "typemoq": "^2.1.0", - "typescript": "^5.4.5", + "typescript": "^5.5.4", "unicode-properties": "^1.3.1", "utf-8-validate": "^5.0.8", "util": "^0.12.4", From 2a9942ecc62c091294553ffb2cc07197b5d49112 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 2 Aug 2024 20:56:12 +1000 Subject: [PATCH 2/7] Bump engine version to 1.93 (#15913) --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c261c735b0f..26ef181de9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -231,7 +231,7 @@ "webpack-cli": "^5.1.4" }, "engines": { - "vscode": "^1.92.0" + "vscode": "^1.93.0" }, "optionalDependencies": { "canvas": "^2.7.0", diff --git a/package.json b/package.json index 1fbe99bd722..b3bae2e79d2 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "theme": "light" }, "engines": { - "vscode": "^1.92.0" + "vscode": "^1.93.0" }, "l10n": "./l10n", "extensionKind": [ From 2eb804d8305f7cd2af6194b28de80b63b3fbf3d8 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 2 Aug 2024 20:57:07 +1000 Subject: [PATCH 3/7] Store all temporary files in global storage (#15912) * Store all temporary files in global storage * Better logging * Fixes * Fixes * Log storage folder --- src/extension.common.ts | 2 + src/extension.node.ts | 2 + .../contributedKerneFinder.node.unit.test.ts | 2 + src/kernels/raw/finder/jupyterPaths.node.ts | 35 ++- .../raw/launcher/kernelProcess.node.ts | 22 +- .../launcher/kernelProcess.node.unit.test.ts | 223 ++++++------------ .../localIPyWidgetScriptManager.node.ts | 3 +- src/platform/common/temp.node.ts | 48 ++++ src/platform/common/temp.ts | 35 +++ src/platform/webviews/webviewPanelProvider.ts | 6 +- src/standalone/devTools/clearCache.ts | 4 +- ...yWidgetScriptManager.vscode.common.test.ts | 9 +- 12 files changed, 205 insertions(+), 186 deletions(-) create mode 100644 src/platform/common/temp.node.ts create mode 100644 src/platform/common/temp.ts diff --git a/src/extension.common.ts b/src/extension.common.ts index bbc6e44694c..7f8b6e5fcdb 100644 --- a/src/extension.common.ts +++ b/src/extension.common.ts @@ -47,6 +47,7 @@ import { StopWatch } from './platform/common/utils/stopWatch'; import { sendTelemetryEvent } from './telemetry'; import { IExtensionActivationManager } from './platform/activation/types'; import { getVSCodeChannel } from './platform/common/application/applicationEnvironment'; +import { getExtensionTempDir } from './platform/common/temp'; export function initializeLoggers( context: IExtensionContext, @@ -82,6 +83,7 @@ export function initializeLoggers( if (options?.platform) { standardOutputChannel.appendLine(`Platform: ${options.platform} (${options.arch}).`); } + standardOutputChannel.appendLine(`Temp Storage folder ${getDisplayPath(getExtensionTempDir(context))}`); if (!workspace.workspaceFolders || workspace.workspaceFolders.length === 0) { standardOutputChannel.appendLine(`No workspace folder opened.`); } else if (workspace.workspaceFolders.length === 1) { diff --git a/src/extension.node.ts b/src/extension.node.ts index 594b908755c..8fa4267fe3b 100644 --- a/src/extension.node.ts +++ b/src/extension.node.ts @@ -68,6 +68,7 @@ import { postActivateLegacy } from './extension.common'; import { activateNotebookTelemetry } from './kernels/telemetry/notebookTelemetry'; +import { deleteOldTempDirs } from './platform/common/temp.node'; durations.codeLoadingTime = stopWatch.elapsedTime; @@ -103,6 +104,7 @@ export async function activate(context: IExtensionContext): Promise(); const context = mock(); + when(context.extension).thenReturn({ packageJSON: { version: '1.0.0' } } as any); when(context.extensionUri).thenReturn(Uri.file(EXTENSION_ROOT_DIR)); + when(context.globalStorageUri).thenReturn(Uri.joinPath(Uri.file(EXTENSION_ROOT_DIR), 'temp')); when(memento.get(anything(), anything())).thenCall((_, defaultValue) => { if (Array.isArray(defaultValue)) { return defaultValue; diff --git a/src/kernels/raw/finder/jupyterPaths.node.ts b/src/kernels/raw/finder/jupyterPaths.node.ts index 453650788ff..477c5e7062b 100644 --- a/src/kernels/raw/finder/jupyterPaths.node.ts +++ b/src/kernels/raw/finder/jupyterPaths.node.ts @@ -1,7 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +import * as crypto from 'crypto'; import { inject, injectable, named } from 'inversify'; +import * as fs from 'fs-extra'; import * as path from '../../../platform/vscode-path/path'; import * as uriPath from '../../../platform/vscode-path/resources'; import { CancellationToken, Memento, Uri } from 'vscode'; @@ -27,6 +29,7 @@ import { getDisplayPath } from '../../../platform/common/platform/fs-paths'; import { StopWatch } from '../../../platform/common/utils/stopWatch'; import { ResourceMap, ResourceSet } from '../../../platform/common/utils/map'; import { getPythonEnvDisplayName, getSysPrefix } from '../../../platform/interpreter/helpers'; +import { getExtensionTempDir } from '../../../platform/common/temp'; const winJupyterPath = path.join('AppData', 'Roaming', 'jupyter', 'kernels'); const linuxJupyterPath = path.join('.local', 'share', 'jupyter', 'kernels'); @@ -70,9 +73,10 @@ export class JupyterPaths { /** * Contains the name of the directory where the Jupyter extension will temporary register Kernels when using non-raw. * (this way we don't register kernels in global path). + * This path needs to be writable, as we store the kernelspecs here when we spawn kernels using Jupyter Server. */ public async getKernelSpecTempRegistrationFolder() { - const dir = uriPath.joinPath(this.context.extensionUri, 'temp', 'jupyter', 'kernels'); + const dir = uriPath.joinPath(getExtensionTempDir(this.context), 'jupyter', 'kernels'); await this.fs.createDirectory(dir); return dir; } @@ -110,8 +114,23 @@ export class JupyterPaths { /** * Returns the value for `JUPYTER_RUNTIME_DIR`, location where Jupyter stores runtime files. * Such as kernel connection files. + * This path needs to be writable, as we store the connection files in here. */ - public async getRuntimeDir(): Promise { + public async getRuntimeDir(): Promise { + const runtimeDir = await this.getRuntimeDirImpl(); + if (runtimeDir) { + return runtimeDir; + } + + // Run time directory doesn't exist or no permissions. + const extensionRuntimeDir = Uri.joinPath(getExtensionTempDir(this.context), 'jupyter', 'runtime'); + await fs.ensureDir(extensionRuntimeDir.fsPath); + logger.trace(`Using extension runtime directory ${extensionRuntimeDir.fsPath}`); + return extensionRuntimeDir; + } + + private runtimeDirIsWritable = false; + private async getRuntimeDirImpl(): Promise { let runtimeDir: Uri | undefined; const userHomeDir = this.platformService.homeDir; if (userHomeDir) { @@ -133,11 +152,19 @@ export class JupyterPaths { } try { - // Make sure the local file exists + // Make sure the directory exists and is writable. await this.fs.createDirectory(runtimeDir); + if (!this.runtimeDirIsWritable) { + // Ensure this folder is writable as well, we've found cases where this folder is not writable. + const tempFileName = `temp-test-write-access-${crypto.randomBytes(20).toString('hex')}.txt`; + const tempFile = uriPath.joinPath(runtimeDir, tempFileName); + // If this fails, then thats find, at least we know the folder is not writable, even if it exists. + await fs.writeFile(tempFile.fsPath, ''); + await fs.unlink(tempFile.fsPath).catch(noop); + } return runtimeDir; } catch (ex) { - logger.error(`Failed to create runtime directory, reverting to temp directory ${runtimeDir}`, ex); + logger.error(`Failed to create/or verify write access to runtime directory ${runtimeDir}`, ex); } } /** diff --git a/src/kernels/raw/launcher/kernelProcess.node.ts b/src/kernels/raw/launcher/kernelProcess.node.ts index 46480e95ede..8fbae4c1d1e 100644 --- a/src/kernels/raw/launcher/kernelProcess.node.ts +++ b/src/kernels/raw/launcher/kernelProcess.node.ts @@ -4,6 +4,7 @@ import { ChildProcess } from 'child_process'; import { kill } from 'process'; import * as fs from 'fs-extra'; +import * as crypto from 'crypto'; import * as os from 'os'; import * as path from '../../../platform/vscode-path/path'; import { CancellationError, CancellationToken, Event, EventEmitter, Uri } from 'vscode'; @@ -456,7 +457,10 @@ export class KernelProcess extends ObservableDisposable implements IKernelProces ); } - this.connectionFile = await this.createConnectionFile(); + const runtimeDir = await this.jupyterPaths.getRuntimeDir(); + const connectionFileName = `kernel-v3${crypto.randomBytes(20).toString('hex')}.json`; + this.connectionFile = Uri.joinPath(runtimeDir, connectionFileName); + // Python kernels are special. Handle the extra arguments. if (this.isPythonKernel) { // Slice out -f and the connection file from the args @@ -495,22 +499,6 @@ export class KernelProcess extends ObservableDisposable implements IKernelProces } } } - private async createConnectionFile() { - const runtimeDir = await this.jupyterPaths.getRuntimeDir(); - const tempFile = await this.fileSystem.createTemporaryLocalFile({ - fileExtension: '.json', - prefix: 'kernel-v2-' - }); - // Note: We have to dispose the temp file and recreate it else the file - // system will hold onto the file with an open handle. THis doesn't work so well when - // a different process tries to open it. - const connectionFile = runtimeDir - ? path.join(runtimeDir.fsPath, path.basename(tempFile.filePath)) - : tempFile.filePath; - // Ensure we dispose this, and don't maintain a handle on this file. - await tempFile.dispose(); // Do not remove this line. - return Uri.file(connectionFile); - } // Add the command line arguments private addPythonConnectionArgs(connectionFile: Uri): string[] { const newConnectionArgs: string[] = []; diff --git a/src/kernels/raw/launcher/kernelProcess.node.unit.test.ts b/src/kernels/raw/launcher/kernelProcess.node.unit.test.ts index cb35bff3288..c3db36260aa 100644 --- a/src/kernels/raw/launcher/kernelProcess.node.unit.test.ts +++ b/src/kernels/raw/launcher/kernelProcess.node.unit.test.ts @@ -7,7 +7,7 @@ import * as os from 'os'; import { assert } from 'chai'; import * as path from '../../../platform/vscode-path/path'; import * as sinon from 'sinon'; -import { anything, instance, mock, when, verify, capture, deepEqual } from 'ts-mockito'; +import { anything, instance, mock, when, verify, capture } from 'ts-mockito'; import { KernelProcess, TcpPortUsage } from './kernelProcess.node'; import { IProcessService, @@ -35,7 +35,6 @@ import { EventEmitter } from 'stream'; import { PythonKernelInterruptDaemon } from '../finder/pythonKernelInterruptDaemon.node'; import { JupyterPaths } from '../finder/jupyterPaths.node'; import { waitForCondition } from '../../../test/common.node'; -import { uriEquals } from '../../../test/datascience/helpers'; import { IS_REMOTE_NATIVE_TEST } from '../../../test/constants'; import { logger } from '../../../platform/logging'; import { IPlatformService } from '../../../platform/common/platform/types'; @@ -44,7 +43,7 @@ import { createObservable } from '../../../platform/common/process/proc.node'; import { ServiceContainer } from '../../../platform/ioc/container'; import { IServiceContainer } from '../../../platform/ioc/types'; -suite('kernel Process', () => { +suite('Kernel Process', () => { ['watiForPortsToBeUsed experiments disabled', 'watiForPortsToBeUsed experiments enabled'].forEach( (experimentMsg) => { suite(experimentMsg, () => { @@ -70,7 +69,6 @@ suite('kernel Process', () => { let outputChannel: IOutputChannel | undefined; let jupyterSettings: IJupyterSettings; let token: CancellationTokenSource; - let tempFileDisposable: IDisposable; let processService: IProcessService; let pythonProcess: IPythonExecutionService; let disposables: IDisposable[] = []; @@ -78,7 +76,7 @@ suite('kernel Process', () => { let daemon: PythonKernelInterruptDaemon; let proc: ChildProcess; let jupyterPaths: JupyterPaths; - const tempFileCreationOptions = { fileExtension: '.json', prefix: 'kernel-v2-' }; + const jupyterRuntimeDir = Uri.file(path.join('hello', 'jupyter', 'runtime')); setup(() => { experiment = mock(); when(experiment.inExperiment(Experiments.DoNotWaitForZmqPortsToBeUsed)).thenReturn( @@ -88,7 +86,6 @@ suite('kernel Process', () => { when(serviceContainer.get(IExperimentService)).thenReturn(instance(experiment)); sinon.stub(ServiceContainer, 'instance').get(() => instance(serviceContainer)); - tempFileDisposable = mock(); token = new CancellationTokenSource(); disposables.push(token); processService = mock(); @@ -145,11 +142,7 @@ suite('kernel Process', () => { when(pythonExecFactory.createActivatedEnvironment(anything())).thenResolve(instance(pythonProcess)); (instance(daemon) as any).then = undefined; sinon.stub(TcpPortUsage, 'waitUntilUsed').callsFake(() => Promise.resolve()); - when(fs.createTemporaryLocalFile(anything())).thenResolve({ - dispose: noop, - filePath: 'connection.json' - }); - when(jupyterPaths.getRuntimeDir()).thenResolve(); + when(jupyterPaths.getRuntimeDir()).thenResolve(jupyterRuntimeDir); const platform = mock(); when(platform.isWindows).thenReturn(false); kernelProcess = new KernelProcess( @@ -179,20 +172,14 @@ suite('kernel Process', () => { name: 'csharp', executable: 'dotnet' }; - const tempFile = 'temporary file.json'; when(connectionMetadata.kind).thenReturn('startUsingLocalKernelSpec'); when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - when(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).thenResolve({ - dispose: instance(tempFileDisposable).dispose, - filePath: tempFile - }); await kernelProcess.launch('', 0, token.token); - verify(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).atLeast(1); - verify(tempFileDisposable.dispose()).once(); - verify(fs.writeFile(uriEquals(tempFile), anything())).atLeast(1); - verify(tempFileDisposable.dispose()).calledBefore(fs.writeFile(uriEquals(tempFile), anything())); + verify(fs.writeFile(anything(), anything())).atLeast(1); + const kernelJson = capture(fs.writeFile).first()[0]; + assert.ok(kernelJson.fsPath.startsWith(jupyterRuntimeDir.fsPath)); }); test('Ensure kernelspec json file is created with the connection info in it', async () => { const kernelSpec: IJupyterKernelSpec = { @@ -201,17 +188,14 @@ suite('kernel Process', () => { name: 'csharp', executable: 'dotnet' }; - const tempFile = 'temporary file.json'; when(connectionMetadata.kind).thenReturn('startUsingLocalKernelSpec'); when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - when(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).thenResolve({ - dispose: instance(tempFileDisposable).dispose, - filePath: tempFile - }); await kernelProcess.launch('', 0, token.token); - verify(fs.writeFile(uriEquals(tempFile), JSON.stringify(connection))).atLeast(1); + verify(fs.writeFile(anything(), anything())).atLeast(1); + const kernelJson = capture(fs.writeFile).first()[0]; + assert.ok(kernelJson.fsPath.startsWith(jupyterRuntimeDir.fsPath)); }); test('Ensure we start the .NET process instead of a Python process (& daemon is not started either)', async () => { const kernelSpec: IJupyterKernelSpec = { @@ -220,23 +204,18 @@ suite('kernel Process', () => { name: 'csharp', executable: 'dotnet' }; - const tempFile = 'temporary file.json'; when(connectionMetadata.kind).thenReturn('startUsingLocalKernelSpec'); when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - when(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).thenResolve({ - dispose: instance(tempFileDisposable).dispose, - filePath: tempFile - }); await kernelProcess.launch('', 0, token.token); verify(pythonExecFactory.createActivatedEnvironment(anything())).never(); verify(pythonProcess.execObservable(anything(), anything())).never(); assert.strictEqual(capture(processService.execObservable).first()[0], 'dotnet'); - assert.deepStrictEqual(capture(processService.execObservable).first()[1], [ - 'csharp', - Uri.file(tempFile).fsPath - ]); + assert.deepStrictEqual(capture(processService.execObservable).first()[1][0], 'csharp'); + assert.ok( + capture(processService.execObservable).first()[1][1].startsWith(jupyterRuntimeDir.fsPath) + ); }); test('Ensure connection file is created in jupyter runtime directory (.net kernel)', async () => { const kernelSpec: IJupyterKernelSpec = { @@ -245,33 +224,23 @@ suite('kernel Process', () => { name: 'csharp', executable: 'dotnet' }; - const tempFile = path.join('tmp', 'temporary file.json'); - const jupyterRuntimeDir = Uri.file(path.join('hello', 'jupyter', 'runtime')); - const expectedConnectionFile = path.join(jupyterRuntimeDir.fsPath, path.basename(tempFile)); - when(jupyterPaths.getRuntimeDir()).thenResolve(jupyterRuntimeDir); when(connectionMetadata.kind).thenReturn('startUsingLocalKernelSpec'); when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - when(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).thenResolve({ - dispose: instance(tempFileDisposable).dispose, - filePath: tempFile - }); - when(fs.exists(anything())).thenCall( - (file: Uri) => file.fsPath === Uri.file(expectedConnectionFile).fsPath - ); await kernelProcess.launch('', 0, token.token); assert.strictEqual(capture(processService.execObservable).first()[0], 'dotnet'); - assert.deepStrictEqual(capture(processService.execObservable).first()[1], [ - 'csharp', - expectedConnectionFile - ]); + assert.deepStrictEqual(capture(processService.execObservable).first()[1][0], 'csharp'); + assert.ok( + capture(processService.execObservable).first()[1][1].startsWith(jupyterRuntimeDir.fsPath) + ); // Verify it gets deleted. await kernelProcess.dispose(); await waitForCondition( () => { - verify(fs.delete(uriEquals(expectedConnectionFile))).once(); + verify(fs.delete(anything())).once(); + assert.ok(capture(fs.delete).first()[0].fsPath.startsWith(jupyterRuntimeDir.fsPath)); return true; }, 5_000, @@ -285,29 +254,23 @@ suite('kernel Process', () => { name: 'csharp', executable: 'dotnet' }; - const tempFile = path.join('tmp', 'temporary file.json'); - when(jupyterPaths.getRuntimeDir()).thenResolve(); when(connectionMetadata.kind).thenReturn('startUsingLocalKernelSpec'); when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - when(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).thenResolve({ - dispose: instance(tempFileDisposable).dispose, - filePath: tempFile - }); - when(fs.exists(anything())).thenCall((file: Uri) => file.fsPath === Uri.file(tempFile).fsPath); await kernelProcess.launch('', 0, token.token); assert.strictEqual(capture(processService.execObservable).first()[0], 'dotnet'); - assert.deepStrictEqual(capture(processService.execObservable).first()[1], [ - 'csharp', - Uri.file(tempFile).fsPath - ]); + assert.deepStrictEqual(capture(processService.execObservable).first()[1][0], 'csharp'); + assert.ok( + capture(processService.execObservable).first()[1][1].startsWith(jupyterRuntimeDir.fsPath) + ); // Verify it gets deleted. await kernelProcess.dispose(); await waitForCondition( () => { - verify(fs.delete(uriEquals(tempFile))).once(); + verify(fs.delete(anything())).once(); + assert.ok(capture(fs.delete).first()[0].fsPath.startsWith(jupyterRuntimeDir.fsPath)); return true; }, 5_000, @@ -327,71 +290,29 @@ suite('kernel Process', () => { name: 'Python3', executable: 'python' }; - const tempFile = path.join('tmp', 'temporary file.json'); - const jupyterRuntimeDir = Uri.file(path.join('hello', 'jupyter', 'runtime')); - const expectedConnectionFile = path.join(jupyterRuntimeDir.fsPath, path.basename(tempFile)); - when(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).thenResolve({ - dispose: noop, - filePath: tempFile - }); - when(fs.exists(anything())).thenCall( - (file: Uri) => file.fsPath === Uri.file(expectedConnectionFile).fsPath - ); - when(jupyterPaths.getRuntimeDir()).thenResolve(jupyterRuntimeDir); when(pythonExecFactory.createActivatedEnvironment(anything())).thenResolve(instance(pythonProcess)); when(connectionMetadata.kind).thenReturn('startUsingPythonInterpreter'); when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - const expectedArgs = [`-m`, `ipykernel`, `--f="${expectedConnectionFile}"`, `--debug`]; await kernelProcess.launch(__dirname, 0, token.token); verify(processService.execObservable(anything(), anything())).never(); - verify(pythonProcess.execObservable(deepEqual(expectedArgs), anything())).once(); - - // Verify it gets deleted. - await kernelProcess.dispose(); - await waitForCondition( - () => { - verify(fs.delete(uriEquals(expectedConnectionFile))).once(); - return true; - }, - 5_000, - 'Connection file not deleted' + verify(pythonProcess.execObservable(anything(), anything())).once(); + const execArgs = capture(pythonProcess.execObservable).first()[0]; + assert.strictEqual(execArgs[0], '-m'); + assert.strictEqual(execArgs[1], 'ipykernel'); + const fileArg = execArgs[2]; + assert.ok( + fileArg.startsWith(`--f=${jupyterRuntimeDir.fsPath}`), + `Expected '${fileArg}' to start with '${`--f=${jupyterRuntimeDir.fsPath}`}'` ); - }); - test('Ensure connection file is created in temp directory (python daemon kernel)', async () => { - const kernelSpec: IJupyterKernelSpec = { - argv: [ - os.platform() === 'win32' ? 'python.exe' : 'python', - '-m', - 'ipykernel', - '-f', - '{connection_file}' - ], - display_name: 'Python', - name: 'Python3', - executable: 'python' - }; - const tempFile = path.join('tmp', 'temporary file.json'); - when(fs.createTemporaryLocalFile(deepEqual(tempFileCreationOptions))).thenResolve({ - dispose: noop, - filePath: tempFile - }); - when(fs.exists(anything())).thenCall((file: Uri) => file.fsPath === Uri.file(tempFile).fsPath); - when(jupyterPaths.getRuntimeDir()).thenResolve(); - when(pythonExecFactory.createActivatedEnvironment(anything())).thenResolve(instance(pythonProcess)); - when(connectionMetadata.kind).thenReturn('startUsingPythonInterpreter'); - when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - const expectedArgs = [`-m`, `ipykernel`, `--f="${Uri.file(tempFile).fsPath}"`, `--debug`]; - await kernelProcess.launch(__dirname, 0, token.token); - - verify(processService.execObservable(anything(), anything())).never(); - verify(pythonProcess.execObservable(deepEqual(expectedArgs), anything())).once(); + assert.strictEqual(execArgs[3], '--debug'); // Verify it gets deleted. await kernelProcess.dispose(); await waitForCondition( () => { - verify(fs.delete(uriEquals(tempFile))).once(); + verify(fs.delete(anything())).once(); + assert.ok(capture(fs.delete).first()[0].fsPath.startsWith(jupyterRuntimeDir.fsPath)); return true; }, 5_000, @@ -414,11 +335,19 @@ suite('kernel Process', () => { when(pythonExecFactory.createActivatedEnvironment(anything())).thenResolve(instance(pythonProcess)); when(connectionMetadata.kind).thenReturn('startUsingPythonInterpreter'); when(connectionMetadata.kernelSpec).thenReturn(kernelSpec); - const expectedArgs = [`-m`, `ipykernel`, `--f=${Uri.file('connection.json').fsPath}`, `--debug`]; await kernelProcess.launch(__dirname, 0, token.token); verify(processService.execObservable(anything(), anything())).never(); - verify(pythonProcess.execObservable(deepEqual(expectedArgs), anything())).once(); + verify(pythonProcess.execObservable(anything(), anything())).once(); + const execArgs = capture(pythonProcess.execObservable).first()[0]; + assert.strictEqual(execArgs[0], '-m'); + assert.strictEqual(execArgs[1], 'ipykernel'); + const fileArg = execArgs[2]; + assert.ok( + fileArg.startsWith(`--f=${jupyterRuntimeDir.fsPath}`), + `Expected '${fileArg}' to start with '${`--f=${jupyterRuntimeDir.fsPath}`}'` + ); + assert.strictEqual(execArgs[3], '--debug'); }); }); } @@ -434,7 +363,7 @@ suite('Kernel Process', () => { let disposables: IDisposable[] = []; let token: CancellationTokenSource; let experiment: IExperimentService; - + const jupyterRuntimeDir = Uri.file(path.join('hello', 'jupyter', 'runtime')); suiteSetup(async function () { // These are slow tests, hence lets run only on linux on CI. if (IS_REMOTE_NATIVE_TEST()) { @@ -459,7 +388,7 @@ suite('Kernel Process', () => { disposables = dispose(disposables); }); - function launchKernel(metadata: LocalKernelSpecConnectionMetadata, connectionFile: string) { + function launchKernel(metadata: LocalKernelSpecConnectionMetadata) { experiment = mock(); when(experiment.inExperiment(Experiments.DoNotWaitForZmqPortsToBeUsed)).thenReturn( experimentMsg.includes('enabled') @@ -490,15 +419,11 @@ suite('Kernel Process', () => { }; const jupyterPaths = mock(); pythonExecFactory = mock(); - when(jupyterPaths.getRuntimeDir()).thenResolve(); + when(jupyterPaths.getRuntimeDir()).thenResolve(jupyterRuntimeDir); when(processExecutionFactory.create(anything())).thenResolve(instanceOfExecutionService); when(processExecutionFactory.create(anything(), anything())).thenResolve( instanceOfExecutionService ); - when(fs.createTemporaryLocalFile(anything())).thenResolve({ - dispose: noop, - filePath: connectionFile - }); when(fs.writeFile(anything(), anything())).thenResolve(); when(kernelEnvVarsService.getEnvironmentVariables(anything(), anything(), anything())).thenResolve( {} @@ -555,16 +480,14 @@ suite('Kernel Process', () => { executable: '' } }); - const kernelProcess = launchKernel(metadata, 'wow/connection_config.json'); + const kernelProcess = launchKernel(metadata); await kernelProcess.launch('', 10_000, token.token); const args = capture(processService.execObservable).first(); assert.strictEqual(args[0], metadata.kernelSpec.argv[0]); assert.deepStrictEqual( - args[1], - metadata.kernelSpec.argv - .slice(1, metadata.kernelSpec.argv.length - 1) - .concat(`--connection-file=${Uri.file('wow/connection_config.json').fsPath}`) + args[1].slice(0, args[1].length - 1), + metadata.kernelSpec.argv.slice(1, metadata.kernelSpec.argv.length - 1) ); await kernelProcess.dispose(); }); @@ -591,16 +514,14 @@ suite('Kernel Process', () => { executable: '' } }); - const kernelProcess = launchKernel(metadata, 'wow/connection config.json'); + const kernelProcess = launchKernel(metadata); await kernelProcess.launch('', 10_000, token.token); const args = capture(processService.execObservable).first(); assert.strictEqual(args[0], metadata.kernelSpec.argv[0]); assert.deepStrictEqual( - args[1], - metadata.kernelSpec.argv - .slice(1, metadata.kernelSpec.argv.length - 1) - .concat(`--connection-file="${Uri.file('wow/connection config.json').fsPath}"`) + args[1].slice(0, args[1].length - 1), + metadata.kernelSpec.argv.slice(1, metadata.kernelSpec.argv.length - 1) ); await kernelProcess.dispose(); }); @@ -628,16 +549,14 @@ suite('Kernel Process', () => { executable: '' } }); - const kernelProcess = launchKernel(metadata, 'wow/connection config.json'); + const kernelProcess = launchKernel(metadata); await kernelProcess.launch('', 10_000, token.token); const args = capture(processService.execObservable).first(); assert.strictEqual(args[0], metadata.kernelSpec.argv[0]); assert.deepStrictEqual( - args[1], - metadata.kernelSpec.argv - .slice(1, metadata.kernelSpec.argv.length - 1) - .concat(Uri.file('wow/connection config.json').fsPath) + args[1].slice(0, args[1].length - 1), + metadata.kernelSpec.argv.slice(1, metadata.kernelSpec.argv.length - 1) ); await kernelProcess.dispose(); }); @@ -662,16 +581,14 @@ suite('Kernel Process', () => { executable: '' } }); - const kernelProcess = launchKernel(metadata, 'connection_config.json'); + const kernelProcess = launchKernel(metadata); await kernelProcess.launch('', 10_000, token.token); const args = capture(processService.execObservable).first(); assert.strictEqual(args[0], metadata.kernelSpec.argv[0]); assert.deepStrictEqual( - args[1], - metadata.kernelSpec.argv - .slice(1, metadata.kernelSpec.argv.length - 1) - .concat(`--connection-file=${Uri.file('connection_config.json').fsPath}`) + args[1].slice(0, args[1].length - 1), + metadata.kernelSpec.argv.slice(1, metadata.kernelSpec.argv.length - 1) ); await kernelProcess.dispose(); }); @@ -696,16 +613,14 @@ suite('Kernel Process', () => { executable: '' } }); - const kernelProcess = launchKernel(metadata, 'D:\\hello\\connection config.json'); + const kernelProcess = launchKernel(metadata); await kernelProcess.launch('', 10_000, token.token); const args = capture(processService.execObservable).first(); assert.strictEqual(args[0], metadata.kernelSpec.argv[0]); assert.deepStrictEqual( - args[1], - metadata.kernelSpec.argv - .slice(1, metadata.kernelSpec.argv.length - 1) - .concat(`--connection-file="${Uri.file('D:\\hello\\connection config.json').fsPath}"`) + args[1].slice(0, args[1].length - 1), + metadata.kernelSpec.argv.slice(1, metadata.kernelSpec.argv.length - 1) ); await kernelProcess.dispose(); }); @@ -731,16 +646,14 @@ suite('Kernel Process', () => { executable: '' } }); - const kernelProcess = launchKernel(metadata, 'D:\\hello\\connection config.json'); + const kernelProcess = launchKernel(metadata); await kernelProcess.launch('', 10_000, token.token); const args = capture(processService.execObservable).first(); assert.strictEqual(args[0], metadata.kernelSpec.argv[0]); assert.deepStrictEqual( - args[1], - metadata.kernelSpec.argv - .slice(1, metadata.kernelSpec.argv.length - 1) - .concat(Uri.file('D:\\hello\\connection config.json').fsPath) + args[1].slice(0, args[1].length - 1), + metadata.kernelSpec.argv.slice(1, metadata.kernelSpec.argv.length - 1) ); await kernelProcess.dispose(); }); diff --git a/src/notebooks/controllers/ipywidgets/scriptSourceProvider/localIPyWidgetScriptManager.node.ts b/src/notebooks/controllers/ipywidgets/scriptSourceProvider/localIPyWidgetScriptManager.node.ts index 55ef5da8b8a..7430742b9ed 100644 --- a/src/notebooks/controllers/ipywidgets/scriptSourceProvider/localIPyWidgetScriptManager.node.ts +++ b/src/notebooks/controllers/ipywidgets/scriptSourceProvider/localIPyWidgetScriptManager.node.ts @@ -13,6 +13,7 @@ import { BaseIPyWidgetScriptManager } from './baseIPyWidgetScriptManager'; import { IIPyWidgetScriptManager, INbExtensionsPathProvider } from '../types'; import { JupyterPaths } from '../../../../kernels/raw/finder/jupyterPaths.node'; import { logger } from '../../../../platform/logging'; +import { getExtensionTempDir } from '../../../../platform/common/temp'; type KernelConnectionId = string; /** @@ -74,7 +75,7 @@ export class LocalIPyWidgetScriptManager extends BaseIPyWidgetScriptManager impl return; } const kernelHash = await getTelemetrySafeHashedString(this.kernel.kernelConnectionMetadata.id); - const baseUrl = Uri.joinPath(this.context.extensionUri, 'temp', 'scripts', kernelHash, 'jupyter'); + const baseUrl = Uri.joinPath(getExtensionTempDir(this.context), 'scripts', kernelHash, 'jupyter'); const targetNbExtensions = Uri.joinPath(baseUrl, 'nbextensions'); const [jupyterDataDirectories] = await Promise.all([ diff --git a/src/platform/common/temp.node.ts b/src/platform/common/temp.node.ts new file mode 100644 index 00000000000..390b8094c93 --- /dev/null +++ b/src/platform/common/temp.node.ts @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as fs from 'fs-extra'; +import { Uri } from 'vscode'; +import type { IExtensionContext } from './types'; +import { noop } from './utils/misc'; +import { getCurrentTempDirName, TEMP_DIR_PREFIX } from './temp'; +import { logger } from '../logging'; + +// WARNING: Do not move this into `temp.ts` as this is specific to node extension. +// using native fs is faster than using vscode.workspace.fs. +// WARNING: Do not move this into `temp.ts` as this is specific to node extension. +// using native fs is faster than using vscode.workspace.fs. +// WARNING: Do not move this into `temp.ts` as this is specific to node extension. +// using native fs is faster than using vscode.workspace.fs. +// WARNING: Do not move this into `temp.ts` as this is specific to node extension. +// using native fs is faster than using vscode.workspace.fs. + +/** + * Delete old temp directories that are no longer required. + * We create temporary directories in global storage directory as thats guaranteed to be read-write. + * We need to delete these directories when they are no longer required. + * + * E.g. when users install a new version of the extension, then old files are no longer required. + * This way the temporary directories are not left behind & cleaned up. + * + * We used to store temp files in os.tmpdir, but that's not guaranteed to be read-write. + * Found cases where that failed. + * We also used to store files in extension sub directory, but that's not guaranteed to be read-write. + * + * No need to move this into `temp.ts` as this is specific to node extension. + * & using native fs is faster than using vscode.workspace.fs. + * @param context + */ +export async function deleteOldTempDirs(context: IExtensionContext) { + const dirs = await fs.readdir(context.globalStorageUri.fsPath).catch(() => []); + const currentTempDir = getCurrentTempDirName(context); + await Promise.all( + dirs + .filter((dir) => dir.startsWith(TEMP_DIR_PREFIX) && dir !== currentTempDir) + .map((dir) => { + const dirToDelete = Uri.joinPath(context.globalStorageUri, dir).fsPath; + logger.info(`Deleting old temp dir ${dirToDelete}`); + return fs.remove(dirToDelete); + }) + ).catch(noop); +} diff --git a/src/platform/common/temp.ts b/src/platform/common/temp.ts new file mode 100644 index 00000000000..405e358c8e8 --- /dev/null +++ b/src/platform/common/temp.ts @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { FileType, Uri, workspace } from 'vscode'; +import type { IExtensionContext } from './types'; +import { isWeb, noop } from './utils/misc'; + +export const TEMP_DIR_PREFIX = 'version'; + +export function getCurrentTempDirName(context: IExtensionContext): string { + return `${TEMP_DIR_PREFIX}-${context.extension.packageJSON.version || 'version'}`; +} + +export function getExtensionTempDir(context: IExtensionContext): Uri { + if (isWeb()) { + return Uri.joinPath(context.globalStorageUri, getCurrentTempDirName(context)); + } else { + // Ensure we use the file scheme when dealing with the desktop version of VS Code. + // eslint-disable-next-line local-rules/dont-use-fspath + return Uri.joinPath(Uri.file(context.globalStorageUri.fsPath), getCurrentTempDirName(context)); + } +} + +export async function deleteTempDirs(context: IExtensionContext) { + try { + const dirs = await workspace.fs.readDirectory(context.globalStorageUri); + await Promise.all( + dirs + .filter(([name, type]) => name.startsWith(TEMP_DIR_PREFIX) && type === FileType.Directory) + .map(([dir]) => workspace.fs.delete(Uri.joinPath(context.globalStorageUri, dir), { recursive: true })) + ).catch(noop); + } catch { + // + } +} diff --git a/src/platform/webviews/webviewPanelProvider.ts b/src/platform/webviews/webviewPanelProvider.ts index a4401a70e0f..2e0a801610f 100644 --- a/src/platform/webviews/webviewPanelProvider.ts +++ b/src/platform/webviews/webviewPanelProvider.ts @@ -6,8 +6,8 @@ import { Uri, ViewColumn, WebviewOptions, WebviewPanel as vscodeWebviewPanel, wi import { IWebviewPanel, IWebviewPanelOptions, IWebviewPanelProvider } from '../common/application/types'; import { IFileSystem } from '../common/platform/types'; import { IDisposableRegistry, IExtensionContext } from '../common/types'; -import * as path from '../vscode-path/path'; import { Webview } from './webview'; +import { getExtensionTempDir } from '../common/temp'; class WebviewPanel extends Webview implements IWebviewPanel { private get panel(): vscodeWebviewPanel | undefined { @@ -120,9 +120,9 @@ export class WebviewPanelProvider implements IWebviewPanelProvider { // eslint-disable-next-line @typescript-eslint/no-explicit-any public async create(options: IWebviewPanelOptions): Promise { - // Allow loading resources from the `/tmp` folder when in webiviews. + // Allow loading resources from the `/` folder when in webiviews. // Used by widgets to place files that are not otherwise accessible. - const additionalRootPaths = [Uri.file(path.join(this.context.extensionPath, 'temp'))]; + const additionalRootPaths = [getExtensionTempDir(this.context)]; if (Array.isArray(options.additionalPaths)) { additionalRootPaths.push(...options.additionalPaths); } diff --git a/src/standalone/devTools/clearCache.ts b/src/standalone/devTools/clearCache.ts index 89d4389d54f..3fce1b3ba7c 100644 --- a/src/standalone/devTools/clearCache.ts +++ b/src/standalone/devTools/clearCache.ts @@ -7,6 +7,7 @@ import { noop } from '../../platform/common/utils/misc'; import { Commands } from '../../platform/common/constants'; import { logger } from '../../platform/logging'; import { RemoteKernelSpecCacheFileName } from '../../kernels/jupyter/constants'; +import { deleteTempDirs } from '../../platform/common/temp'; export function addClearCacheCommand(context: IExtensionContext, isDevMode: boolean) { if (!isDevMode) { @@ -28,7 +29,8 @@ export function addClearCacheCommand(context: IExtensionContext, isDevMode: bool await Promise.all([ workspace.fs.delete(Uri.joinPath(context.globalStorageUri, 'lastExecutedRemoteCell.json')).then(noop, noop), workspace.fs.delete(Uri.joinPath(context.globalStorageUri, 'remoteServersMRUList.json')).then(noop, noop), - workspace.fs.delete(Uri.joinPath(context.globalStorageUri, RemoteKernelSpecCacheFileName)).then(noop, noop) + workspace.fs.delete(Uri.joinPath(context.globalStorageUri, RemoteKernelSpecCacheFileName)).then(noop, noop), + deleteTempDirs(context).then(noop, noop) ]); logger.info('Cache cleared'); }); diff --git a/src/test/datascience/ipywidgets/ipyWidgetScriptManager.vscode.common.test.ts b/src/test/datascience/ipywidgets/ipyWidgetScriptManager.vscode.common.test.ts index 8e21e2c0dec..f588d2848d3 100644 --- a/src/test/datascience/ipywidgets/ipyWidgetScriptManager.vscode.common.test.ts +++ b/src/test/datascience/ipywidgets/ipyWidgetScriptManager.vscode.common.test.ts @@ -31,6 +31,7 @@ import { createActiveInterpreterController } from '../notebook/helpers'; import { IInterpreterService } from '../../../platform/interpreter/contracts'; import { IControllerRegistration } from '../../../notebooks/controllers/types'; import { HttpClient } from '../../../platform/common/net/httpClient'; +import { getExtensionTempDir } from '../../../platform/common/temp'; suite('IPyWidget Script Manager @widgets', function () { this.timeout(120_000); @@ -120,8 +121,7 @@ suite('IPyWidget Script Manager @widgets', function () { assert.fail('We should have started a Python kernel'); } else { const expectedDir = Uri.joinPath( - context.extensionUri, - 'temp', + getExtensionTempDir(context), 'scripts', await getTelemetrySafeHashedString(kernel.kernelConnectionMetadata.id), 'jupyter' @@ -140,8 +140,7 @@ suite('IPyWidget Script Manager @widgets', function () { return this.skip(); } const expectedDir = Uri.joinPath( - context.extensionUri, - 'temp', + getExtensionTempDir(context), 'scripts', await getTelemetrySafeHashedString(kernel.kernelConnectionMetadata.id), 'jupyter' @@ -157,7 +156,7 @@ suite('IPyWidget Script Manager @widgets', function () { // await del([nbExtensionsFolder]); const fsNode = api.serviceContainer.get(IFileSystemNode); // eslint-disable-next-line local-rules/dont-use-fspath - await fsNode.delete(nbExtensionsFolder); + await fsNode.delete(Uri.file(nbExtensionsFolder.fsPath)); assert.isFalse(await fs.exists(nbExtensionsFolder), `Directory '${nbExtensionsFolder}'does not exist`); await kernel.restart(); From 9212a3a51670284e0594c871f53364b0ebfcbc69 Mon Sep 17 00:00:00 2001 From: Aaron Munger Date: Wed, 7 Aug 2024 14:42:57 -0700 Subject: [PATCH 4/7] migrate to new mamba github action (#15927) --- .github/workflows/build-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3c278cdaa88..18121e33368 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -394,13 +394,13 @@ jobs: python-version: ${{matrix.pythonVersion}} - name: Install Conda environment from environment.yml - uses: mamba-org/provision-with-micromamba@3c96c0c27676490c63c18bc81f5c51895ac3e0e6 + uses: mamba-org/setup-micromamba@v1 if: matrix.python == 'conda' with: cache-downloads: true environment-name: functional_test_env environment-file: ./build/conda-test-requirements.yml - extra-specs: | + create-args: | python=${{matrix.pythonVersion}} - name: Set CI Path From 1515b12e823afbfeb9df7e503e9a85999a2fd347 Mon Sep 17 00:00:00 2001 From: Aaron Munger Date: Wed, 7 Aug 2024 15:44:21 -0700 Subject: [PATCH 5/7] Set has cells context key to false on code lens provider dispose (#15926) * move code cells context setter to code lens provider, set context false on dispose * remove from global activation * add newline * remove check * lint --- package.json | 2 +- .../editor-integration/cellFactory.ts | 12 ---------- .../editor-integration/codelensprovider.ts | 24 +++++++++++++++++-- src/standalone/activation/globalActivation.ts | 21 ---------------- src/test/datascience/datascience.unit.test.ts | 8 ------- 5 files changed, 23 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index b3bae2e79d2..bb7166c7bdf 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ { "command": "jupyter.runcurrentcell", "key": "ctrl+enter", - "when": "editorTextFocus && !editorHasSelection && jupyter.hascodecells && !notebookEditorFocused && !jupyter.havenativecells" + "when": "editorTextFocus && !editorHasSelection && jupyter.hascodecells && !notebookEditorFocused" }, { "command": "jupyter.runcurrentcellandaddbelow", diff --git a/src/interactive-window/editor-integration/cellFactory.ts b/src/interactive-window/editor-integration/cellFactory.ts index 0a05df503c2..517cbd8d5cf 100644 --- a/src/interactive-window/editor-integration/cellFactory.ts +++ b/src/interactive-window/editor-integration/cellFactory.ts @@ -75,18 +75,6 @@ export function generateCells( } } -export function hasCells(document: TextDocument, settings?: IJupyterSettings): boolean { - const matcher = new CellMatcher(settings); - for (let index = 0; index < document.lineCount; index += 1) { - const line = document.lineAt(index); - if (matcher.isCell(line.text)) { - return true; - } - } - - return false; -} - export function generateCellRangesFromDocument(document: TextDocument, settings?: IJupyterSettings): ICellRange[] { // Implmentation of getCells here based on Don's Jupyter extension work const matcher = new CellMatcher(settings); diff --git a/src/interactive-window/editor-integration/codelensprovider.ts b/src/interactive-window/editor-integration/codelensprovider.ts index 3b7cb41f5f0..16928468b44 100644 --- a/src/interactive-window/editor-integration/codelensprovider.ts +++ b/src/interactive-window/editor-integration/codelensprovider.ts @@ -19,6 +19,7 @@ import { EditorContexts, InteractiveInputScheme, NotebookCellScheme, + PYTHON_LANGUAGE, Telemetry } from '../../platform/common/constants'; import { IDataScienceCodeLensProvider, ICodeWatcher } from './types'; @@ -56,6 +57,19 @@ export class DataScienceCodeLensProvider implements IDataScienceCodeLensProvider if (this.debugLocationTracker) { disposableRegistry.push(this.debugLocationTracker.updated(this.onDebugLocationUpdated.bind(this))); } + + disposableRegistry.push(vscode.window.onDidChangeActiveTextEditor(() => this.onChangedActiveTextEditor())); + this.onChangedActiveTextEditor(); + } + + private onChangedActiveTextEditor() { + const activeEditor = vscode.window.activeTextEditor; + + if (!activeEditor || activeEditor.document.languageId != PYTHON_LANGUAGE) { + // set the context to false so our command doesn't run for other files + const hasCellsContext = new ContextKey(EditorContexts.HasCodeCells); + hasCellsContext.set(false).catch((ex) => logger.warn('Failed to set jupyter.HasCodeCells context', ex)); + } } public dispose() { @@ -65,6 +79,10 @@ export class DataScienceCodeLensProvider implements IDataScienceCodeLensProvider duration: this.totalExecutionTimeInMs / this.totalGetCodeLensCalls }); } + + const editorContext = new ContextKey(EditorContexts.HasCodeCells); + editorContext.set(false).catch(noop); + dispose(this.activeCodeWatchers); } @@ -112,8 +130,10 @@ export class DataScienceCodeLensProvider implements IDataScienceCodeLensProvider // Update the hasCodeCells context at the same time we are asked for codelens as VS code will // ask whenever a change occurs. Do this regardless of if we have code lens turned on or not as // shift+enter relies on this code context. - const editorContext = new ContextKey(EditorContexts.HasCodeCells); - editorContext.set(codeLenses && codeLenses.length > 0).catch(noop); + const hasCellsContext = new ContextKey(EditorContexts.HasCodeCells); + hasCellsContext + .set(codeLenses && codeLenses.length > 0) + .catch((ex) => logger.debug('Failed to set jupyter.HasCodeCells context', ex)); // Don't provide any code lenses if we have not enabled data science const settings = this.configuration.getSettings(document.uri); diff --git a/src/standalone/activation/globalActivation.ts b/src/standalone/activation/globalActivation.ts index 9214eca591b..a0ac5f0b2f8 100644 --- a/src/standalone/activation/globalActivation.ts +++ b/src/standalone/activation/globalActivation.ts @@ -2,7 +2,6 @@ // Licensed under the MIT License. import { inject, injectable, multiInject, optional } from 'inversify'; -import { PYTHON_LANGUAGE } from '../../platform/common/constants'; import { ContextKey } from '../../platform/common/contextKey'; import { IConfigurationService, @@ -14,8 +13,6 @@ import { noop } from '../../platform/common/utils/misc'; import { EditorContexts } from '../../platform/common/constants'; import { IExtensionSyncActivationService } from '../../platform/activation/types'; import { IRawNotebookSupportedService } from '../../kernels/raw/types'; -import { hasCells } from '../../interactive-window/editor-integration/cellFactory'; -import { window } from 'vscode'; /** * Singleton class that activate a bunch of random things that didn't fit anywhere else. @@ -46,10 +43,6 @@ export class GlobalActivation implements IExtensionSyncActivationService { this.changeHandler = this.configuration.getSettings(undefined).onDidChange(this.onSettingsChanged.bind(this)); this.disposableRegistry.push(this); - // Listen for active editor changes so we can detect have code cells or not - this.disposableRegistry.push(window.onDidChangeActiveTextEditor(() => this.onChangedActiveTextEditor())); - this.onChangedActiveTextEditor(); - // Figure out the ZMQ available context key this.computeZmqAvailable(); @@ -76,18 +69,4 @@ export class GlobalActivation implements IExtensionSyncActivationService { const zmqContext = new ContextKey(EditorContexts.ZmqAvailable); zmqContext.set(this.rawSupported ? this.rawSupported.isSupported : false).then(noop, noop); } - - private onChangedActiveTextEditor() { - // Setup the editor context for the cells - const editorContext = new ContextKey(EditorContexts.HasCodeCells); - const activeEditor = window.activeTextEditor; - - if (activeEditor && activeEditor.document.languageId === PYTHON_LANGUAGE) { - // Inform the editor context that we have cells, fire and forget is ok on the promise here - // as we don't care to wait for this context to be set and we can't do anything if it fails - editorContext.set(hasCells(activeEditor.document, this.configuration.getSettings())).catch(noop); - } else { - editorContext.set(false).catch(noop); - } - } } diff --git a/src/test/datascience/datascience.unit.test.ts b/src/test/datascience/datascience.unit.test.ts index 6d1e4f7a447..2249927cd46 100644 --- a/src/test/datascience/datascience.unit.test.ts +++ b/src/test/datascience/datascience.unit.test.ts @@ -12,7 +12,6 @@ import { GlobalActivation } from '../../standalone/activation/globalActivation'; import { RawNotebookSupportedService } from '../../kernels/raw/session/rawNotebookSupportedService.node'; import { IRawNotebookSupportedService } from '../../kernels/raw/types'; import { pruneCell } from '../../platform/common/utils'; -import { mockedVSCodeNamespaces } from '../vscode-mock'; /* eslint-disable */ suite('Tests', () => { @@ -20,7 +19,6 @@ suite('Tests', () => { let configService: IConfigurationService; let settings: IWatchableJupyterSettings; let onDidChangeSettings: sinon.SinonStub; - let onDidChangeActiveTextEditor: sinon.SinonStub; let rawNotebookSupported: IRawNotebookSupportedService; setup(() => { configService = mock(ConfigurationService); @@ -36,11 +34,8 @@ suite('Tests', () => { ); onDidChangeSettings = sinon.stub(); - onDidChangeActiveTextEditor = sinon.stub(); when(configService.getSettings(anything())).thenReturn(instance(settings)); when(settings.onDidChange).thenReturn(onDidChangeSettings); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - when(mockedVSCodeNamespaces.window.onDidChangeActiveTextEditor).thenReturn(onDidChangeActiveTextEditor); when(rawNotebookSupported.isSupported).thenReturn(true); }); @@ -52,9 +47,6 @@ suite('Tests', () => { test('Should add handler for Settings Changed', async () => { assert.ok(onDidChangeSettings.calledOnce); }); - test('Should add handler for ActiveTextEditorChanged', async () => { - assert.ok(onDidChangeActiveTextEditor.calledOnce); - }); }); suite('Cell pruning', () => { From 109457dfa8c7752974b09fccb2697eb8305f6920 Mon Sep 17 00:00:00 2001 From: Aaron Munger Date: Thu, 8 Aug 2024 14:10:13 -0700 Subject: [PATCH 6/7] add logging to help troubleshoot delegation errors (#15928) * add logging to help troubleshoot delegation errors * change property * lint * telemetry update --- src/gdpr.ts | 2 ++ src/telemetry.ts | 21 ++++++++++++++---- .../dataviewer/dataViewerCommandRegistry.ts | 10 ++++++--- .../dataviewer/dataViewerDelegator.ts | 22 +++++++++++++++++-- .../variablesView/variableView.ts | 2 +- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/gdpr.ts b/src/gdpr.ts index af320ef9444..36c6812749a 100644 --- a/src/gdpr.ts +++ b/src/gdpr.ts @@ -386,6 +386,8 @@ // Failed to show the data viewer via the variable view. /* __GDPR__ "DATASCIENCE.FAILED_SHOW_DATA_EXPLORER" : { + "reason": {"classification":"SystemMetaData","purpose":"FeatureInsight","comment":"","owner":"amunger"}, + "fromVariableView": {"classification":"SystemMetaData","purpose":"FeatureInsight","comment":"","owner":"amunger"}, "${include}": [ "${F1}" diff --git a/src/telemetry.ts b/src/telemetry.ts index 6049484265b..3ac87b3dd76 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -1785,15 +1785,28 @@ export class IEventNamePropertyMapping { /** * Failed to show the data viewer via the variable view. */ - [Telemetry.FailedShowDataViewer]: TelemetryEventInfo = { - owner: 'IanMatthewHuff', + [Telemetry.FailedShowDataViewer]: TelemetryEventInfo<{ + reason: string; + fromVariableView: boolean; + }> = { + owner: 'amunger', feature: ['DataFrameViewer', 'VariableViewer'], - source: 'N/A' + source: 'N/A', + properties: { + reason: { + classification: 'SystemMetaData', + purpose: 'FeatureInsight' + }, + fromVariableView: { + classification: 'SystemMetaData', + purpose: 'FeatureInsight' + } + } }; /** * Sent when the jupyter.refreshDataViewer command is invoked */ - [Telemetry.RefreshDataViewer]: TelemetryEventInfo = { + [Telemetry.RefreshDataViewer]: TelemetryEventInfo = { owner: 'IanMatthewHuff', feature: ['DataFrameViewer'], source: 'User Action' diff --git a/src/webviews/extension-side/dataviewer/dataViewerCommandRegistry.ts b/src/webviews/extension-side/dataviewer/dataViewerCommandRegistry.ts index 3d3384a3434..bfa96b5249f 100644 --- a/src/webviews/extension-side/dataviewer/dataViewerCommandRegistry.ts +++ b/src/webviews/extension-side/dataviewer/dataViewerCommandRegistry.ts @@ -49,9 +49,8 @@ export class DataViewerCommandRegistry implements IExtensionSyncActivationServic private readonly jupyterVariableDataProviderFactory: IJupyterVariableDataProviderFactory | undefined, @inject(IDataViewerFactory) @optional() private readonly dataViewerFactory: IDataViewerFactory | undefined, @inject(IJupyterVariables) - @optional() @named(Identifiers.DEBUGGER_VARIABLES) - private variableProvider: IJupyterVariables | undefined, + private variableProvider: IJupyterVariables, @inject(IDataScienceErrorHandler) private readonly errorHandler: IDataScienceErrorHandler, @inject(IDataViewerDependencyService) @optional() @@ -91,9 +90,14 @@ export class DataViewerCommandRegistry implements IExtensionSyncActivationServic private async delegateDataViewer(request: IJupyterVariable | IShowDataViewerFromVariablePanel) { const variable = 'variable' in request ? await this.getVariableFromRequest(request) : request; if (!variable) { + logger.error('Full variable info could not be retreived'); + sendTelemetryEvent(Telemetry.FailedShowDataViewer, undefined, { + reason: 'no variable info', + fromVariableView: false + }); return; } - return this.dataViewerDelegator.showContributedDataViewer(variable); + return this.dataViewerDelegator.showContributedDataViewer(variable, false); } // get the information needed about the request from the debug variable view diff --git a/src/webviews/extension-side/dataviewer/dataViewerDelegator.ts b/src/webviews/extension-side/dataviewer/dataViewerDelegator.ts index f2ef5ebe626..67efbdd8eab 100644 --- a/src/webviews/extension-side/dataviewer/dataViewerDelegator.ts +++ b/src/webviews/extension-side/dataviewer/dataViewerDelegator.ts @@ -13,7 +13,7 @@ import * as localize from '../../../platform/common/utils/localize'; @injectable() export class DataViewerDelegator { - public async showContributedDataViewer(variable: IJupyterVariable) { + public async showContributedDataViewer(variable: IJupyterVariable, fromVariableView: boolean) { try { // jupyterVariableViewers const variableViewers = this.getMatchingExternalVariableViewers(variable); @@ -34,11 +34,23 @@ export class DataViewerDelegator { }); } else if (variableViewers.length === 1) { const command = variableViewers[0].jupyterVariableViewers.command; + logger.info( + `Showing data viewer with command ${command} for variable ${JSON.stringify({ + ...variable, + value: '...' + })}` + ); return commands.executeCommand(command, variable); } else { const thirdPartyViewers = variableViewers.filter((d) => d.extension.id !== JVSC_EXTENSION_ID); if (thirdPartyViewers.length === 1) { const command = thirdPartyViewers[0].jupyterVariableViewers.command; + logger.info( + `Showing data viewer viewer with command ${command} for variable ${JSON.stringify({ + ...variable, + value: '...' + })}` + ); return commands.executeCommand(command, variable); } // show quick pick @@ -55,6 +67,12 @@ export class DataViewerDelegator { const item = quickPick.selectedItems[0]; if (item) { quickPick.hide(); + logger.info( + `Showing data viewer viewer with command ${item.command} for variable ${JSON.stringify({ + ...variable, + value: '...' + })}` + ); return commands.executeCommand(item.command, variable); } }); @@ -62,7 +80,7 @@ export class DataViewerDelegator { } } catch (e) { logger.error(e); - sendTelemetryEvent(Telemetry.FailedShowDataViewer); + sendTelemetryEvent(Telemetry.FailedShowDataViewer, undefined, { reason: 'exception', fromVariableView }); window.showErrorMessage(localize.DataScience.showDataViewerFail).then(noop, noop); } } diff --git a/src/webviews/extension-side/variablesView/variableView.ts b/src/webviews/extension-side/variablesView/variableView.ts index d970036d4f2..5b140da0787 100644 --- a/src/webviews/extension-side/variablesView/variableView.ts +++ b/src/webviews/extension-side/variablesView/variableView.ts @@ -133,7 +133,7 @@ export class VariableView extends WebviewViewHost imp @swallowExceptions() public async showDataViewer(request: IShowDataViewer) { request.variable.fileName = request.variable.fileName ?? this.notebookWatcher.activeKernel?.notebook.uri; - return this.dataViewerDelegator.showContributedDataViewer(request.variable); + return this.dataViewerDelegator.showContributedDataViewer(request.variable, true); } private postProcessSupportsDataExplorer(response: IJupyterVariablesResponse) { From 2a11eb0be0db775560232006cd86d67dfcee3a11 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Sun, 11 Aug 2024 09:19:57 +1000 Subject: [PATCH 7/7] Allow DW to use proposed API (#15820) --- src/platform/common/constants.ts | 1 + src/standalone/api/kernels/kernel.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/platform/common/constants.ts b/src/platform/common/constants.ts index fac5cb31097..79b04f69ad9 100644 --- a/src/platform/common/constants.ts +++ b/src/platform/common/constants.ts @@ -22,6 +22,7 @@ export const NOTEBOOK_SELECTOR = [ export const CodespaceExtensionId = 'GitHub.codespaces'; export const JVSC_EXTENSION_ID = 'ms-toolsai.jupyter'; +export const DATA_WRANGLER_EXTENSION_ID = 'ms-toolsai.datawrangler'; export const POWER_TOYS_EXTENSION_ID = 'ms-toolsai.vscode-jupyter-powertoys'; export const JUPYTER_HUB_EXTENSION_ID = 'ms-toolsai.jupyter-hub'; export const AppinsightsKey = '0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255'; diff --git a/src/standalone/api/kernels/kernel.ts b/src/standalone/api/kernels/kernel.ts index d6847776bb6..658082babb5 100644 --- a/src/standalone/api/kernels/kernel.ts +++ b/src/standalone/api/kernels/kernel.ts @@ -31,7 +31,12 @@ import { StopWatch } from '../../../platform/common/utils/stopWatch'; import { Deferred, createDeferred, sleep } from '../../../platform/common/utils/async'; import { once } from '../../../platform/common/utils/events'; import { logger } from '../../../platform/logging'; -import { JVSC_EXTENSION_ID, POWER_TOYS_EXTENSION_ID, PYTHON_LANGUAGE } from '../../../platform/common/constants'; +import { + DATA_WRANGLER_EXTENSION_ID, + JVSC_EXTENSION_ID, + POWER_TOYS_EXTENSION_ID, + PYTHON_LANGUAGE +} from '../../../platform/common/constants'; import { ChatMime, generatePythonCodeToInvokeCallback } from '../../../kernels/chat/generator'; import { isDisplayIdTrackedForExtension, @@ -244,7 +249,7 @@ class WrappedKernelPerExtension extends DisposableBase implements Kernel { }, onDidChangeStatus: that.onDidChangeStatus.bind(this), get onDidReceiveDisplayUpdate() { - if (![JVSC_EXTENSION_ID, POWER_TOYS_EXTENSION_ID].includes(extensionId)) { + if (![JVSC_EXTENSION_ID, POWER_TOYS_EXTENSION_ID, DATA_WRANGLER_EXTENSION_ID].includes(extensionId)) { throw new Error(`Proposed API is not supported for extension ${extensionId}`); }