diff --git a/.eslintrc.json b/.eslintrc.json index 24b5b101e17..cf4c1418a11 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -268,7 +268,6 @@ "**/vs/base/{common,node,electron-main}/**", "**/vs/base/parts/*/{common,node,electron-main}/**", "**/vs/platform/*/{common,node,electron-main}/**", - "**/vs/code/**", "*" // node modules ] }, @@ -807,7 +806,6 @@ "**/vs/platform/**/{common,node}/**", "**/vs/workbench/**/{common,node}/**", "**/vs/server/**", - "**/vs/code/**/{common,node}/**", "*" // node modules ] }, @@ -1009,6 +1007,7 @@ "end", "expand", "hide", + "invalidate", "open", "override", "receive", diff --git a/.github/commands.json b/.github/commands.json index 7563a3924a1..de0643d56c9 100644 --- a/.github/commands.json +++ b/.github/commands.json @@ -93,7 +93,7 @@ "addLabel": "z-author-verified", "removeLabel": "author-verification-requested", "requireLabel": "author-verification-requested", - "disallowLabel": "awaiting-insiders-release" + "disallowLabel": "unreleased" }, { "type": "comment", diff --git a/.mailmap b/.mailmap index bd9e4941e50..d4542abf73c 100644 --- a/.mailmap +++ b/.mailmap @@ -1,4 +1,5 @@ Eric Amodio Eric Amodio +Eric Amodio Eric Amodio Daniel Imms Daniel Imms Tanha Kabir Tanha Kabir Raymond Zhao diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index f6e7f3592e3..f480308a5c6 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -319,7 +319,7 @@ "watch": "npm run build-preview && gulp watch-extension:markdown-language-features", "vscode:prepublish": "npm run build-ext && npm run build-preview", "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json", - "build-preview": "webpack --mode production", + "build-preview": "npx webpack-cli --mode production", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, diff --git a/extensions/package.json b/extensions/package.json index 69f8501b208..3537c5c7f75 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -4,7 +4,7 @@ "license": "MIT", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "^4.2.0-dev.20210201" + "typescript": "insiders" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/simple-browser/media/index.js b/extensions/simple-browser/media/index.js index ca44111a2ea..d74299e1e71 100644 --- a/extensions/simple-browser/media/index.js +++ b/extensions/simple-browser/media/index.js @@ -1,220 +1,2 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./preview-src/index.ts"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./preview-src/events.ts": -/*!*******************************!*\ - !*** ./preview-src/events.ts ***! - \*******************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.onceDocumentLoaded = void 0; -function onceDocumentLoaded(f) { - if (document.readyState === 'loading' || document.readyState === 'uninitialized') { - document.addEventListener('DOMContentLoaded', f); - } - else { - f(); - } -} -exports.onceDocumentLoaded = onceDocumentLoaded; - - -/***/ }), - -/***/ "./preview-src/index.ts": -/*!******************************!*\ - !*** ./preview-src/index.ts ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -Object.defineProperty(exports, "__esModule", { value: true }); -const events_1 = __webpack_require__(/*! ./events */ "./preview-src/events.ts"); -const vscode = acquireVsCodeApi(); -function getSettings() { - const element = document.getElementById('simple-browser-settings'); - if (element) { - const data = element.getAttribute('data-settings'); - if (data) { - return JSON.parse(data); - } - } - throw new Error(`Could not load settings`); -} -const settings = getSettings(); -const iframe = document.querySelector('iframe'); -const header = document.querySelector('.header'); -const input = header.querySelector('.url-input'); -const forwardButton = header.querySelector('.forward-button'); -const backButton = header.querySelector('.back-button'); -const reloadButton = header.querySelector('.reload-button'); -const openExternalButton = header.querySelector('.open-external-button'); -window.addEventListener('message', e => { - switch (e.data.type) { - case 'focus': - { - iframe.focus(); - break; - } - case 'didChangeFocusLockIndicatorEnabled': - { - toggleFocusLockIndicatorEnabled(e.data.enabled); - break; - } - } -}); -events_1.onceDocumentLoaded(() => { - setInterval(() => { - var _a; - const iframeFocused = ((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.tagName) === 'IFRAME'; - document.body.classList.toggle('iframe-focused', iframeFocused); - }, 50); - iframe.addEventListener('load', () => { - // Noop - }); - input.addEventListener('change', e => { - const url = e.target.value; - navigateTo(url); - }); - forwardButton.addEventListener('click', () => { - history.forward(); - }); - backButton.addEventListener('click', () => { - history.back(); - }); - openExternalButton.addEventListener('click', () => { - vscode.postMessage({ - type: 'openExternal', - url: input.value - }); - }); - reloadButton.addEventListener('click', () => { - // This does not seem to trigger what we want - // history.go(0); - // This incorrectly adds entries to the history but does reload - iframe.src = input.value; - }); - navigateTo(settings.url); - input.value = settings.url; - toggleFocusLockIndicatorEnabled(settings.focusLockIndicatorEnabled); - function navigateTo(rawUrl) { - try { - const url = new URL(rawUrl); - // Try to bust the cache for the iframe - // There does not appear to be any way to reliably do this except modifying the url - url.searchParams.append('vscodeBrowserReqId', Date.now().toString()); - iframe.src = url.toString(); - } - catch (_a) { - iframe.src = rawUrl; - } - } -}); -function toggleFocusLockIndicatorEnabled(enabled) { - document.body.classList.toggle('enable-focus-lock-indicator', enabled); -} - - -/***/ }) - -/******/ }); +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const o=n(1),r=acquireVsCodeApi();const c=function(){const e=document.getElementById("simple-browser-settings");if(e){const t=e.getAttribute("data-settings");if(t)return JSON.parse(t)}throw new Error("Could not load settings")}(),a=document.querySelector("iframe"),u=document.querySelector(".header"),d=u.querySelector(".url-input"),i=u.querySelector(".forward-button"),s=u.querySelector(".back-button"),l=u.querySelector(".reload-button"),f=u.querySelector(".open-external-button");function y(e){document.body.classList.toggle("enable-focus-lock-indicator",e)}window.addEventListener("message",e=>{switch(e.data.type){case"focus":a.focus();break;case"didChangeFocusLockIndicatorEnabled":y(e.data.enabled)}}),o.onceDocumentLoaded(()=>{function e(e){try{const t=new URL(e);t.searchParams.append("vscodeBrowserReqId",Date.now().toString()),a.src=t.toString()}catch(t){a.src=e}}setInterval(()=>{var e;const t="IFRAME"===(null===(e=document.activeElement)||void 0===e?void 0:e.tagName);document.body.classList.toggle("iframe-focused",t)},50),a.addEventListener("load",()=>{}),d.addEventListener("change",t=>{e(t.target.value)}),i.addEventListener("click",()=>{history.forward()}),s.addEventListener("click",()=>{history.back()}),f.addEventListener("click",()=>{r.postMessage({type:"openExternal",url:d.value})}),l.addEventListener("click",()=>{a.src=d.value}),e(c.url),d.value=c.url,y(c.focusLockIndicatorEnabled)})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.onceDocumentLoaded=void 0,t.onceDocumentLoaded=function(e){"loading"===document.readyState||"uninitialized"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}}]); //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/extensions/simple-browser/media/index.js.map b/extensions/simple-browser/media/index.js.map index d4e76529981..df62d30257b 100644 --- a/extensions/simple-browser/media/index.js.map +++ b/extensions/simple-browser/media/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./preview-src/events.ts","webpack:///./preview-src/index.ts"],"names":[],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;AClFa;AACb;AACA;AACA;AACA;AACA,8CAA8C,cAAc;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACfa;AACb;AACA;AACA;AACA;AACA,8CAA8C,cAAc;AAC5D,iBAAiB,mBAAO,CAAC,yCAAU;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,KAAK;AACL;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA","file":"index.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./preview-src/index.ts\");\n","\"use strict\";\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.onceDocumentLoaded = void 0;\nfunction onceDocumentLoaded(f) {\n if (document.readyState === 'loading' || document.readyState === 'uninitialized') {\n document.addEventListener('DOMContentLoaded', f);\n }\n else {\n f();\n }\n}\nexports.onceDocumentLoaded = onceDocumentLoaded;\n","\"use strict\";\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst events_1 = require(\"./events\");\nconst vscode = acquireVsCodeApi();\nfunction getSettings() {\n const element = document.getElementById('simple-browser-settings');\n if (element) {\n const data = element.getAttribute('data-settings');\n if (data) {\n return JSON.parse(data);\n }\n }\n throw new Error(`Could not load settings`);\n}\nconst settings = getSettings();\nconst iframe = document.querySelector('iframe');\nconst header = document.querySelector('.header');\nconst input = header.querySelector('.url-input');\nconst forwardButton = header.querySelector('.forward-button');\nconst backButton = header.querySelector('.back-button');\nconst reloadButton = header.querySelector('.reload-button');\nconst openExternalButton = header.querySelector('.open-external-button');\nwindow.addEventListener('message', e => {\n switch (e.data.type) {\n case 'focus':\n {\n iframe.focus();\n break;\n }\n case 'didChangeFocusLockIndicatorEnabled':\n {\n toggleFocusLockIndicatorEnabled(e.data.enabled);\n break;\n }\n }\n});\nevents_1.onceDocumentLoaded(() => {\n setInterval(() => {\n var _a;\n const iframeFocused = ((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.tagName) === 'IFRAME';\n document.body.classList.toggle('iframe-focused', iframeFocused);\n }, 50);\n iframe.addEventListener('load', () => {\n // Noop\n });\n input.addEventListener('change', e => {\n const url = e.target.value;\n navigateTo(url);\n });\n forwardButton.addEventListener('click', () => {\n history.forward();\n });\n backButton.addEventListener('click', () => {\n history.back();\n });\n openExternalButton.addEventListener('click', () => {\n vscode.postMessage({\n type: 'openExternal',\n url: input.value\n });\n });\n reloadButton.addEventListener('click', () => {\n // This does not seem to trigger what we want\n // history.go(0);\n // This incorrectly adds entries to the history but does reload\n iframe.src = input.value;\n });\n navigateTo(settings.url);\n input.value = settings.url;\n toggleFocusLockIndicatorEnabled(settings.focusLockIndicatorEnabled);\n function navigateTo(rawUrl) {\n try {\n const url = new URL(rawUrl);\n // Try to bust the cache for the iframe\n // There does not appear to be any way to reliably do this except modifying the url\n url.searchParams.append('vscodeBrowserReqId', Date.now().toString());\n iframe.src = url.toString();\n }\n catch (_a) {\n iframe.src = rawUrl;\n }\n }\n});\nfunction toggleFocusLockIndicatorEnabled(enabled) {\n document.body.classList.toggle('enable-focus-lock-indicator', enabled);\n}\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./preview-src/index.ts","webpack:///./preview-src/events.ts"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","events_1","vscode","acquireVsCodeApi","settings","element","document","getElementById","data","getAttribute","JSON","parse","Error","getSettings","iframe","querySelector","header","input","forwardButton","backButton","reloadButton","openExternalButton","toggleFocusLockIndicatorEnabled","enabled","body","classList","toggle","window","addEventListener","e","type","focus","onceDocumentLoaded","navigateTo","rawUrl","url","URL","searchParams","append","Date","now","toString","src","_a","setInterval","iframeFocused","activeElement","tagName","target","history","forward","back","postMessage","focusLockIndicatorEnabled","f","readyState"],"mappings":"aACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QAKfF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,G,+BC7ErDrB,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,IACtD,MAAMe,EAAW,EAAQ,GACnBC,EAASC,mBAWf,MAAMC,EAVN,WACI,MAAMC,EAAUC,SAASC,eAAe,2BACxC,GAAIF,EAAS,CACT,MAAMG,EAAOH,EAAQI,aAAa,iBAClC,GAAID,EACA,OAAOE,KAAKC,MAAMH,GAG1B,MAAM,IAAII,MAAM,2BAEHC,GACXC,EAASR,SAASS,cAAc,UAChCC,EAASV,SAASS,cAAc,WAChCE,EAAQD,EAAOD,cAAc,cAC7BG,EAAgBF,EAAOD,cAAc,mBACrCI,EAAaH,EAAOD,cAAc,gBAClCK,EAAeJ,EAAOD,cAAc,kBACpCM,EAAqBL,EAAOD,cAAc,yBA8DhD,SAASO,EAAgCC,GACrCjB,SAASkB,KAAKC,UAAUC,OAAO,8BAA+BH,GA9DlEI,OAAOC,iBAAiB,UAAWC,IAC/B,OAAQA,EAAErB,KAAKsB,MACX,IAAK,QAEGhB,EAAOiB,QACP,MAER,IAAK,qCAEGT,EAAgCO,EAAErB,KAAKe,YAKvDtB,EAAS+B,mBAAmB,KAkCxB,SAASC,EAAWC,GAChB,IACI,MAAMC,EAAM,IAAIC,IAAIF,GAGpBC,EAAIE,aAAaC,OAAO,qBAAsBC,KAAKC,MAAMC,YACzD3B,EAAO4B,IAAMP,EAAIM,WAErB,MAAOE,GACH7B,EAAO4B,IAAMR,GA1CrBU,YAAY,KACR,IAAID,EACJ,MAAME,EAAoG,YAAjD,QAAjCF,EAAKrC,SAASwC,qBAAkC,IAAPH,OAAgB,EAASA,EAAGI,SAC7FzC,SAASkB,KAAKC,UAAUC,OAAO,iBAAkBmB,IAClD,IACH/B,EAAOc,iBAAiB,OAAQ,QAGhCX,EAAMW,iBAAiB,SAAUC,IAE7BI,EADYJ,EAAEmB,OAAO9D,SAGzBgC,EAAcU,iBAAiB,QAAS,KACpCqB,QAAQC,YAEZ/B,EAAWS,iBAAiB,QAAS,KACjCqB,QAAQE,SAEZ9B,EAAmBO,iBAAiB,QAAS,KACzC1B,EAAOkD,YAAY,CACftB,KAAM,eACNK,IAAKlB,EAAM/B,UAGnBkC,EAAaQ,iBAAiB,QAAS,KAInCd,EAAO4B,IAAMzB,EAAM/B,QAEvB+C,EAAW7B,EAAS+B,KACpBlB,EAAM/B,MAAQkB,EAAS+B,IACvBb,EAAgClB,EAASiD,8B,6BCpE7C1E,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,IACtDnB,EAAQiE,wBAAqB,EAS7BjE,EAAQiE,mBARR,SAA4BsB,GACI,YAAxBhD,SAASiD,YAAoD,kBAAxBjD,SAASiD,WAC9CjD,SAASsB,iBAAiB,mBAAoB0B,GAG9CA","file":"index.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","\"use strict\";\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst events_1 = require(\"./events\");\nconst vscode = acquireVsCodeApi();\nfunction getSettings() {\n const element = document.getElementById('simple-browser-settings');\n if (element) {\n const data = element.getAttribute('data-settings');\n if (data) {\n return JSON.parse(data);\n }\n }\n throw new Error(`Could not load settings`);\n}\nconst settings = getSettings();\nconst iframe = document.querySelector('iframe');\nconst header = document.querySelector('.header');\nconst input = header.querySelector('.url-input');\nconst forwardButton = header.querySelector('.forward-button');\nconst backButton = header.querySelector('.back-button');\nconst reloadButton = header.querySelector('.reload-button');\nconst openExternalButton = header.querySelector('.open-external-button');\nwindow.addEventListener('message', e => {\n switch (e.data.type) {\n case 'focus':\n {\n iframe.focus();\n break;\n }\n case 'didChangeFocusLockIndicatorEnabled':\n {\n toggleFocusLockIndicatorEnabled(e.data.enabled);\n break;\n }\n }\n});\nevents_1.onceDocumentLoaded(() => {\n setInterval(() => {\n var _a;\n const iframeFocused = ((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.tagName) === 'IFRAME';\n document.body.classList.toggle('iframe-focused', iframeFocused);\n }, 50);\n iframe.addEventListener('load', () => {\n // Noop\n });\n input.addEventListener('change', e => {\n const url = e.target.value;\n navigateTo(url);\n });\n forwardButton.addEventListener('click', () => {\n history.forward();\n });\n backButton.addEventListener('click', () => {\n history.back();\n });\n openExternalButton.addEventListener('click', () => {\n vscode.postMessage({\n type: 'openExternal',\n url: input.value\n });\n });\n reloadButton.addEventListener('click', () => {\n // This does not seem to trigger what we want\n // history.go(0);\n // This incorrectly adds entries to the history but does reload\n iframe.src = input.value;\n });\n navigateTo(settings.url);\n input.value = settings.url;\n toggleFocusLockIndicatorEnabled(settings.focusLockIndicatorEnabled);\n function navigateTo(rawUrl) {\n try {\n const url = new URL(rawUrl);\n // Try to bust the cache for the iframe\n // There does not appear to be any way to reliably do this except modifying the url\n url.searchParams.append('vscodeBrowserReqId', Date.now().toString());\n iframe.src = url.toString();\n }\n catch (_a) {\n iframe.src = rawUrl;\n }\n }\n});\nfunction toggleFocusLockIndicatorEnabled(enabled) {\n document.body.classList.toggle('enable-focus-lock-indicator', enabled);\n}\n","\"use strict\";\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.onceDocumentLoaded = void 0;\nfunction onceDocumentLoaded(f) {\n if (document.readyState === 'loading' || document.readyState === 'uninitialized') {\n document.addEventListener('DOMContentLoaded', f);\n }\n else {\n f();\n }\n}\nexports.onceDocumentLoaded = onceDocumentLoaded;\n"],"sourceRoot":""} \ No newline at end of file diff --git a/extensions/simple-browser/package.json b/extensions/simple-browser/package.json index d5c6da0a701..5ba906d12ef 100644 --- a/extensions/simple-browser/package.json +++ b/extensions/simple-browser/package.json @@ -54,8 +54,8 @@ "watch": "npm run build-preview && gulp watch-extension:markdown-language-features", "vscode:prepublish": "npm run build-ext && npm run build-preview", "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json", - "build-preview": "webpack --mode development", - "build-preview-production": "webpack --mode production", + "build-preview": "npx webpack-cli --mode development", + "build-preview-production": "npx webpack-cli --mode production", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose", "postinstall": "node ./build/copy" @@ -66,11 +66,7 @@ }, "devDependencies": { "vscode-codicons": "^0.0.14", - "@types/node": "^12.11.7", - "ts-loader": "^6.2.1", - "typescript": "^3.7.3", - "webpack": "^4.41.2", - "webpack-cli": "^3.3.0" + "@types/node": "^12.11.7" }, "repository": { "type": "git", diff --git a/extensions/simple-browser/yarn.lock b/extensions/simple-browser/yarn.lock index 721ede37a6a..6d51d4dc074 100644 --- a/extensions/simple-browser/yarn.lock +++ b/extensions/simple-browser/yarn.lock @@ -7,214 +7,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.69.tgz#7cb6a3aa0d16664bf2dcd1450ccb8477464fbd79" integrity sha512-2F2VQRSFmzqgUEXw75L51MgnnZqc6bKWVSUPfrDPzp6mzGGibeVwyQcpvZvBr5RnsoMRHmC8EcBQiobSeqeJxg== -"@webassemblyjs/ast@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" - integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== - dependencies: - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - -"@webassemblyjs/floating-point-hex-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" - integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== - -"@webassemblyjs/helper-api-error@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" - integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== - -"@webassemblyjs/helper-buffer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" - integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== - -"@webassemblyjs/helper-code-frame@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" - integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== - dependencies: - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/helper-fsm@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" - integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== - -"@webassemblyjs/helper-module-context@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" - integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== - dependencies: - "@webassemblyjs/ast" "1.9.0" - -"@webassemblyjs/helper-wasm-bytecode@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" - integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== - -"@webassemblyjs/helper-wasm-section@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" - integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - -"@webassemblyjs/ieee754@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" - integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" - integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" - integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== - -"@webassemblyjs/wasm-edit@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" - integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/helper-wasm-section" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-opt" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/wasm-gen@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" - integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wasm-opt@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" - integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - -"@webassemblyjs/wasm-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" - integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wast-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" - integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/floating-point-hex-parser" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-code-frame" "1.9.0" - "@webassemblyjs/helper-fsm" "1.9.0" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/wast-printer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" - integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -acorn@^6.4.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.1.0, ajv@^6.10.2: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - applicationinsights@1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" @@ -224,566 +16,6 @@ applicationinsights@1.0.8: diagnostic-channel-publishers "0.2.1" zone.js "0.7.6" -aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -binary-extensions@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" - integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bluebird@^3.5.5: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: - version "4.11.9" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" - integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== - -bn.js@^5.1.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" - integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -cacache@^12.0.2: - version "12.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" - integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chalk@^2.3.0, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chokidar@^3.4.1: - version "3.4.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" - integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.1.2" - -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== - dependencies: - tslib "^1.9.0" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.5.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -detect-file@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= - diagnostic-channel-publishers@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" @@ -796,1775 +28,11 @@ diagnostic-channel@0.2.0: dependencies: semver "^5.3.0" -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -duplexify@^3.4.2, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -elliptic@^6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" - integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -errno@^0.1.3, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== - dependencies: - prr "~1.0.1" - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -esrecurse@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -events@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" - integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= - dependencies: - homedir-polyfill "^1.0.1" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -figgy-pudding@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" - integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -findup-sync@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" - integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== - dependencies: - detect-file "^1.0.0" - is-glob "^4.0.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -flush-write-stream@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -from2@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - -fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== - dependencies: - is-glob "^4.0.1" - -glob@^7.1.3, glob@^7.1.4: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -infer-owner@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -interpret@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -loader-runner@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== - -loader-utils@^1.0.2, loader-utils@^1.2.3, loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -make-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@^0.5.1, mkdirp@^0.5.3: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -nan@^2.12.1: - version "2.14.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" - integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -neo-async@^2.5.0, neo-async@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -p-limit@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parallel-transform@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== - dependencies: - cyclist "^1.0.1" - inherits "^2.0.3" - readable-stream "^2.1.5" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -pbkdf2@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" - integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - 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" - -readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -readdirp@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" - integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== - dependencies: - picomatch "^2.2.1" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -rimraf@^2.5.4, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= - dependencies: - aproba "^1.1.1" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -safer-buffer@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: +semver@^5.3.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -serialize-javascript@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== - dependencies: - randombytes "^2.1.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@~0.5.12: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== - dependencies: - figgy-pudding "^3.5.1" - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-each@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -tapable@^1.0.0, tapable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -terser-webpack-plugin@^1.4.3: - version "1.4.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" - integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== - dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^4.0.0" - source-map "^0.6.1" - terser "^4.1.2" - webpack-sources "^1.4.0" - worker-farm "^1.7.0" - -terser@^4.1.2: - version "4.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" - integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== - dependencies: - setimmediate "^1.0.4" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -ts-loader@^6.2.1: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" - integrity sha512-HDo5kXZCBml3EUPcc7RlZOV/JGlLHwppTLEHb3SHnr5V7NXD4klMEkrhJe5wgRbaWsSXi+Y1SIBN/K9B6zWGWQ== - dependencies: - chalk "^2.3.0" - enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" - micromatch "^4.0.0" - semver "^6.0.0" - -tslib@^1.9.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -typescript@^3.7.3: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -v8-compile-cache@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - vscode-codicons@^0.0.14: version "0.0.14" resolved "https://registry.yarnpkg.com/vscode-codicons/-/vscode-codicons-0.0.14.tgz#e0d05418e2e195564ff6f6a2199d70415911c18f" @@ -2582,150 +50,6 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== -watchpack-chokidar2@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" - integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== - dependencies: - chokidar "^2.1.8" - -watchpack@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" - integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== - dependencies: - graceful-fs "^4.1.2" - neo-async "^2.5.0" - optionalDependencies: - chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.0" - -webpack-cli@^3.3.0: - version "3.3.12" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" - integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== - dependencies: - chalk "^2.4.2" - cross-spawn "^6.0.5" - enhanced-resolve "^4.1.1" - findup-sync "^3.0.0" - global-modules "^2.0.0" - import-local "^2.0.0" - interpret "^1.4.0" - loader-utils "^1.4.0" - supports-color "^6.1.0" - v8-compile-cache "^2.1.1" - yargs "^13.3.2" - -webpack-sources@^1.4.0, webpack-sources@^1.4.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack@^4.41.2: - version "4.44.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" - integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/wasm-edit" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.4.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" - chrome-trace-event "^1.0.2" - enhanced-resolve "^4.3.0" - eslint-scope "^4.0.3" - json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.3" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.3" - watchpack "^1.7.4" - webpack-sources "^1.4.1" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@^1.2.14, which@^1.2.9, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -worker-farm@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== - dependencies: - errno "~0.1.7" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -xtend@^4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - zone.js@0.7.6: version "0.7.6" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" diff --git a/extensions/testing-editor-contributions/src/extension.ts b/extensions/testing-editor-contributions/src/extension.ts index fc6ab30b1ff..79b0c851532 100644 --- a/extensions/testing-editor-contributions/src/extension.ts +++ b/extensions/testing-editor-contributions/src/extension.ts @@ -3,410 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import * as nls from 'vscode-nls'; - -const localize = nls.loadMessageBundle(); - -interface IDisposable { - dispose(): void; +export function activate() { + // no-op. This extension may be removed in the future } - -const enum Constants { - ConfigSection = 'testing', - EnableCodeLensConfig = 'enableCodeLens', - EnableDiagnosticsConfig = 'enableProblemDiagnostics', -} - -export function activate(context: vscode.ExtensionContext) { - const diagnostics = vscode.languages.createDiagnosticCollection(); - const services = new TestingEditorServices(diagnostics); - context.subscriptions.push( - services, - diagnostics, - vscode.languages.registerCodeLensProvider({ scheme: 'file' }, services), - ); -} - -class TestingConfig implements IDisposable { - private section = vscode.workspace.getConfiguration(Constants.ConfigSection); - private readonly changeEmitter = new vscode.EventEmitter(); - private readonly listener = vscode.workspace.onDidChangeConfiguration(evt => { - if (evt.affectsConfiguration(Constants.ConfigSection)) { - this.section = vscode.workspace.getConfiguration(Constants.ConfigSection); - this.changeEmitter.fire(); - } - }); - - public readonly onChange = this.changeEmitter.event; - - public get codeLens() { - return this.section.get(Constants.EnableCodeLensConfig, true); - } - - public get diagnostics() { - return this.section.get(Constants.EnableDiagnosticsConfig, false); - } - - public get isEnabled() { - return this.codeLens || this.diagnostics; - } - - public dispose() { - this.listener.dispose(); - } -} - -export class TestingEditorServices implements IDisposable, vscode.CodeLensProvider { - private readonly codeLensChangeEmitter = new vscode.EventEmitter(); - private readonly documents = new Map(); - private readonly config = new TestingConfig(); - private disposables: IDisposable[]; - private wasEnabled = this.config.isEnabled; - - /** - * @inheritdoc - */ - public readonly onDidChangeCodeLenses = this.codeLensChangeEmitter.event; - - constructor(private readonly diagnostics: vscode.DiagnosticCollection) { - this.disposables = [ - new vscode.Disposable(() => this.expireAll()), - - this.config, - - vscode.window.onDidChangeVisibleTextEditors((editors) => { - if (!this.config.isEnabled) { - return; - } - - const expiredEditors = new Set(this.documents.keys()); - for (const editor of editors) { - const key = editor.document.uri.toString(); - this.ensure(key, editor.document); - expiredEditors.delete(key); - } - - for (const expired of expiredEditors) { - this.expire(expired); - } - }), - - vscode.workspace.onDidCloseTextDocument((document) => { - this.expire(document.uri.toString()); - }), - - this.config.onChange(() => { - if (!this.wasEnabled || this.config.isEnabled) { - this.attachToAllVisible(); - } else if (this.wasEnabled || !this.config.isEnabled) { - this.expireAll(); - } - - this.wasEnabled = this.config.isEnabled; - this.codeLensChangeEmitter.fire(); - }), - ]; - - if (this.config.isEnabled) { - this.attachToAllVisible(); - } - } - - /** - * @inheritdoc - */ - public provideCodeLenses(document: vscode.TextDocument) { - if (!this.config.codeLens) { - return []; - } - - return this.documents.get(document.uri.toString())?.provideCodeLenses() ?? []; - } - - /** - * Attach to all currently visible editors. - */ - private attachToAllVisible() { - for (const editor of vscode.window.visibleTextEditors) { - this.ensure(editor.document.uri.toString(), editor.document); - } - } - - /** - * Unattaches to all tests. - */ - private expireAll() { - for (const observer of this.documents.values()) { - observer.dispose(); - } - - this.documents.clear(); - } - - /** - * Subscribes to tests for the document URI. - */ - private ensure(key: string, document: vscode.TextDocument) { - const state = this.documents.get(key); - if (!state) { - const observer = new DocumentTestObserver(document, this.diagnostics, this.config); - this.documents.set(key, observer); - observer.onDidChangeCodeLenses(() => this.config.codeLens && this.codeLensChangeEmitter.fire()); - } - } - - /** - * Expires and removes the watcher for the document. - */ - private expire(key: string) { - const observer = this.documents.get(key); - if (!observer) { - return; - } - - observer.dispose(); - this.documents.delete(key); - } - - /** - * @override - */ - public dispose() { - this.disposables.forEach((d) => d.dispose()); - } -} - -class DocumentTestObserver implements IDisposable { - private readonly codeLensChangeEmitter = new vscode.EventEmitter(); - private readonly observer = vscode.test.createDocumentTestObserver(this.document); - private readonly disposables: IDisposable[]; - public readonly onDidChangeCodeLenses = this.codeLensChangeEmitter.event; - private didHaveDiagnostics = this.config.diagnostics; - - constructor( - private readonly document: vscode.TextDocument, - private readonly diagnostics: vscode.DiagnosticCollection, - private readonly config: TestingConfig, - ) { - this.disposables = [ - this.observer, - this.codeLensChangeEmitter, - - config.onChange(() => { - if (this.didHaveDiagnostics && !config.diagnostics) { - this.diagnostics.set(document.uri, []); - } else if (!this.didHaveDiagnostics && config.diagnostics) { - this.updateDiagnostics(); - } - - this.didHaveDiagnostics = config.diagnostics; - }), - - this.observer.onDidChangeTest(() => { - this.updateDiagnostics(); - this.codeLensChangeEmitter.fire(); - }), - ]; - - } - - private updateDiagnostics() { - if (!this.config.diagnostics) { - return; - } - - const uriString = this.document.uri.toString(); - const diagnostics: vscode.Diagnostic[] = []; - for (const test of iterateOverTests(this.observer.tests)) { - for (const message of test.state.messages) { - if (message.location?.uri.toString() === uriString) { - diagnostics.push({ - range: message.location.range, - message: message.message.toString(), - severity: testToDiagnosticSeverity(message.severity), - }); - } - } - } - - this.diagnostics.set(this.document.uri, diagnostics); - } - - public provideCodeLenses(): vscode.CodeLens[] { - const lenses: vscode.CodeLens[] = []; - - for (const test of iterateOverTests(this.observer.tests)) { - const { debuggable = false, runnable = true } = test; - if (!test.location || !(debuggable || runnable)) { - continue; - } - - const summary = summarize(test); - - lenses.push({ - isResolved: true, - range: test.location.range, - command: { - title: `$(${testStateToIcon[summary.computedState]}) ${getLabelFor(test, summary)}`, - command: 'vscode.runTests', - arguments: [[test]], - tooltip: localize('tooltip.debug', 'Debug {0}', test.label), - }, - }); - - if (debuggable) { - lenses.push({ - isResolved: true, - range: test.location.range, - command: { - title: localize('action.debug', 'Debug'), - command: 'vscode.debugTests', - arguments: [[test]], - tooltip: localize('tooltip.debug', 'Debug {0}', test.label), - }, - }); - } - } - - return lenses; - } - - /** - * @override - */ - public dispose() { - this.diagnostics.set(this.document.uri, []); - this.disposables.forEach(d => d.dispose()); - } -} - -function getLabelFor(test: vscode.TestItem, summary: ITestSummary) { - if (summary.duration !== undefined) { - return localize( - 'tooltip.runStateWithDuration', - '{0}/{1} Tests Passed in {2}', - summary.passed, - summary.passed + summary.failed, - formatDuration(summary.duration), - ); - } - - if (summary.passed > 0 || summary.failed > 0) { - return localize('tooltip.runState', '{0}/{1} Tests Passed', summary.passed, summary.failed); - } - - if (test.state.runState === vscode.TestRunState.Passed) { - return test.state.duration !== undefined - ? localize('state.passedWithDuration', 'Passed in {0}', formatDuration(test.state.duration)) - : localize('state.passed', 'Passed'); - } - - if (isFailedState(test.state.runState)) { - return localize('state.failed', 'Failed'); - } - - return localize('action.run', 'Run Tests'); -} - -function formatDuration(duration: number) { - if (duration < 1_000) { - return `${Math.round(duration)}ms`; - } - - if (duration < 100_000) { - return `${(duration / 1000).toPrecision(3)}s`; - } - - return `${(duration / 1000 / 60).toPrecision(3)}m`; -} - -const statePriority: { [K in vscode.TestRunState]: number } = { - [vscode.TestRunState.Running]: 6, - [vscode.TestRunState.Queued]: 5, - [vscode.TestRunState.Errored]: 4, - [vscode.TestRunState.Failed]: 3, - [vscode.TestRunState.Passed]: 2, - [vscode.TestRunState.Skipped]: 1, - [vscode.TestRunState.Unset]: 0, -}; - -const maxPriority = (a: vscode.TestRunState, b: vscode.TestRunState) => - statePriority[a] > statePriority[b] ? a : b; - -const isFailedState = (s: vscode.TestRunState) => - s === vscode.TestRunState.Failed || s === vscode.TestRunState.Errored; - -interface ITestSummary { - passed: number; - failed: number; - duration: number | undefined; - computedState: vscode.TestRunState; -} - -function summarize(test: vscode.TestItem) { - let passed = 0; - let failed = 0; - let duration: number | undefined; - let computedState = test.state.runState; - - const queue = test.children ? [test.children] : []; - while (queue.length) { - for (const test of queue.pop()!) { - computedState = maxPriority(computedState, test.state.runState); - if (test.state.runState === vscode.TestRunState.Passed) { - passed++; - if (test.state.duration !== undefined) { - duration = test.state.duration + (duration ?? 0); - } - } else if (isFailedState(test.state.runState)) { - failed++; - if (test.state.duration !== undefined) { - duration = test.state.duration + (duration ?? 0); - } - } - - if (test.children) { - queue.push(test.children); - } - } - } - - return { passed, failed, duration, computedState }; -} - -function* iterateOverTests(tests: ReadonlyArray) { - const queue = [tests]; - while (queue.length) { - for (const test of queue.pop()!) { - yield test; - if (test.children) { - queue.push(test.children); - } - } - } -} - -const testStateToIcon: { [K in vscode.TestRunState]: string } = { - [vscode.TestRunState.Errored]: 'testing-error-icon', - [vscode.TestRunState.Failed]: 'testing-failed-icon', - [vscode.TestRunState.Passed]: 'testing-passed-icon', - [vscode.TestRunState.Queued]: 'testing-queued-icon', - [vscode.TestRunState.Skipped]: 'testing-skipped-icon', - [vscode.TestRunState.Unset]: 'beaker', - [vscode.TestRunState.Running]: 'loading~spin', -}; - -const testToDiagnosticSeverity = (severity: vscode.TestMessageSeverity | undefined) => { - switch (severity) { - case vscode.TestMessageSeverity.Hint: - return vscode.DiagnosticSeverity.Hint; - case vscode.TestMessageSeverity.Information: - return vscode.DiagnosticSeverity.Information; - case vscode.TestMessageSeverity.Warning: - return vscode.DiagnosticSeverity.Warning; - case vscode.TestMessageSeverity.Error: - default: - return vscode.DiagnosticSeverity.Error; - } -}; diff --git a/extensions/typescript-language-features/src/languageFeatures/languageConfiguration.ts b/extensions/typescript-language-features/src/languageFeatures/languageConfiguration.ts index ccd59d51773..75d32770a68 100644 --- a/extensions/typescript-language-features/src/languageFeatures/languageConfiguration.ts +++ b/extensions/typescript-language-features/src/languageFeatures/languageConfiguration.ts @@ -15,7 +15,9 @@ import * as languageModeIds from '../utils/languageModeIds'; const jsTsLanguageConfiguration: vscode.LanguageConfiguration = { indentationRules: { decreaseIndentPattern: /^((?!.*?\/\*).*\*\/)?\s*[\}\]].*$/, - increaseIndentPattern: /^((?!\/\/).)*(\{[^}"'`]*|\([^)"'`]*|\[[^\]"'`]*)$/ + increaseIndentPattern: /^((?!\/\/).)*(\{[^}"'`]*|\([^)"'`]*|\[[^\]"'`]*)$/, + // e.g. * ...| or */| or *-----*/| + unIndentedLinePattern: /^(\t|[ ])*[ ]\*[^/]*\*\/\s*$|^(\t|[ ])*[ ]\*\/\s*$|^(\t|[ ])*[ ]\*([ ]([^\*]|\*(?!\/))*)?$/ }, wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, onEnterRules: [ diff --git a/extensions/typescript-language-features/src/test/unit/onEnter.test.ts b/extensions/typescript-language-features/src/test/unit/onEnter.test.ts index 0aeb8425b0a..cd0d99c0e41 100644 --- a/extensions/typescript-language-features/src/test/unit/onEnter.test.ts +++ b/extensions/typescript-language-features/src/test/unit/onEnter.test.ts @@ -67,4 +67,47 @@ suite.skip('OnEnter', () => { ` x`)); }); }); + + test('should not indent after a multi-line comment block 1', () => { + return withRandomFileEditor(`/*-----\n * line 1\n * line 2\n *-----*/\n${CURSOR}`, 'js', async (_editor, document) => { + await type(document, '\nx'); + assert.strictEqual( + document.getText(), + joinLines( + `/*-----`, + ` * line 1`, + ` * line 2`, + ` *-----*/`, + ``, + `x`)); + }); + }); + + test('should not indent after a multi-line comment block 2', () => { + return withRandomFileEditor(`/*-----\n * line 1\n * line 2\n */\n${CURSOR}`, 'js', async (_editor, document) => { + await type(document, '\nx'); + assert.strictEqual( + document.getText(), + joinLines( + `/*-----`, + ` * line 1`, + ` * line 2`, + ` */`, + ``, + `x`)); + }); + }); + + test('should indent within a multi-line comment block', () => { + return withRandomFileEditor(`/*-----\n * line 1\n * line 2${CURSOR}`, 'js', async (_editor, document) => { + await type(document, '\nx'); + assert.strictEqual( + document.getText(), + joinLines( + `/*-----`, + ` * line 1`, + ` * line 2`, + ` * x`)); + }); + }); }); diff --git a/extensions/yarn.lock b/extensions/yarn.lock index 3274642a159..c50271692e7 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -19,10 +19,10 @@ fast-plist@0.1.2: resolved "https://registry.yarnpkg.com/fast-plist/-/fast-plist-0.1.2.tgz#a45aff345196006d406ca6cdcd05f69051ef35b8" integrity sha1-pFr/NFGWAG1AbKbNzQX2kFHvNbg= -typescript@^4.2.0-dev.20210201: - version "4.2.0-dev.20210201" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-dev.20210201.tgz#3d8ae7214cd4b23d3ae400f84d1afe5679f3e2f0" - integrity sha512-By8G30ZYs+b/8084cSnjP7ILd8ExUBC4Qi9FY2iRlBApHu/A08ExLlCRnYkHN1PgxcNs4rTaozJsgXHJ6cg92g== +typescript@insiders: + version "4.2.0-insiders.20210210" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.0-insiders.20210210.tgz#f109217dec41af7ef0fece60a91e5c3cce572d25" + integrity sha512-PBBQ/WNJ/HG+cH2nu+sPFbUPqv8FMraVihOfwlBzoa+0iGHa1I8gueJTUyBIOPU24tClLwKoU8dfscpn0rnuWw== vscode-grammar-updater@^1.0.3: version "1.0.3" diff --git a/package.json b/package.json index 80a8470c50e..c256b29dc2b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.54.0", - "distro": "1bc28dd86603be17b5bf6ffa9370864f58e0ef77", + "distro": "f542aeaaf397d5c71e480442fe772dbe362726db", "author": { "name": "Microsoft Corporation" }, @@ -195,7 +195,7 @@ "underscore": "^1.8.2", "vinyl": "^2.0.0", "vinyl-fs": "^3.0.0", - "vscode-debugprotocol": "1.44.0", + "vscode-debugprotocol": "1.45.0-pre.0", "vscode-nls-dev": "^3.3.1", "vscode-telemetry-extractor": "^1.6.0", "webpack": "^4.43.0", @@ -222,4 +222,4 @@ "elliptic": "^6.5.3", "nwmatcher": "^1.4.4" } -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts index 6b1c8dc938a..f82138b8626 100644 --- a/src/vs/base/browser/ui/sash/sash.ts +++ b/src/vs/base/browser/ui/sash/sash.ts @@ -12,6 +12,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { Event, Emitter } from 'vs/base/common/event'; import { getElementsByTagName, EventHelper, createStyleSheet, addDisposableListener, append, $ } from 'vs/base/browser/dom'; import { domEvent } from 'vs/base/browser/event'; +import { Delayer } from 'vs/base/common/async'; let DEBUG = false; // DEBUG = Boolean("true"); // done "weirdly" so that a lint warning prevents you from pushing this @@ -87,6 +88,7 @@ export class Sash extends Disposable { private hidden: boolean; private orientation!: Orientation; private size: number; + private hoverDelayer = this._register(new Delayer(300)); private _state: SashState = SashState.Enabled; get state(): SashState { return this._state; } @@ -136,10 +138,10 @@ export class Sash extends Disposable { if (state !== SashState.Disabled) { this._orthogonalStartDragHandle = append(this.el, $('.orthogonal-drag-handle.start')); this.orthogonalStartDragHandleDisposables.add(toDisposable(() => this._orthogonalStartDragHandle!.remove())); - domEvent(this._orthogonalStartDragHandle, 'mouseenter', false) - (() => sash.el.classList.add('hover'), undefined, this.orthogonalStartDragHandleDisposables); - domEvent(this._orthogonalStartDragHandle, 'mouseleave', false) - (() => sash.el.classList.remove('hover'), undefined, this.orthogonalStartDragHandleDisposables); + domEvent(this._orthogonalStartDragHandle, 'mouseenter') + (() => Sash.onMouseEnter(sash), undefined, this.orthogonalStartDragHandleDisposables); + domEvent(this._orthogonalStartDragHandle, 'mouseleave') + (() => Sash.onMouseLeave(sash), undefined, this.orthogonalStartDragHandleDisposables); } }; @@ -166,10 +168,10 @@ export class Sash extends Disposable { if (state !== SashState.Disabled) { this._orthogonalEndDragHandle = append(this.el, $('.orthogonal-drag-handle.end')); this.orthogonalEndDragHandleDisposables.add(toDisposable(() => this._orthogonalEndDragHandle!.remove())); - domEvent(this._orthogonalEndDragHandle, 'mouseenter', false) - (() => sash.el.classList.add('hover'), undefined, this.orthogonalEndDragHandleDisposables); - domEvent(this._orthogonalEndDragHandle, 'mouseleave', false) - (() => sash.el.classList.remove('hover'), undefined, this.orthogonalEndDragHandleDisposables); + domEvent(this._orthogonalEndDragHandle, 'mouseenter') + (() => Sash.onMouseEnter(sash), undefined, this.orthogonalEndDragHandleDisposables); + domEvent(this._orthogonalEndDragHandle, 'mouseleave') + (() => Sash.onMouseLeave(sash), undefined, this.orthogonalEndDragHandleDisposables); } }; @@ -197,6 +199,8 @@ export class Sash extends Disposable { this._register(domEvent(this.el, 'mousedown')(this.onMouseDown, this)); this._register(domEvent(this.el, 'dblclick')(this.onMouseDoubleClick, this)); + this._register(domEvent(this.el, 'mouseenter')(() => Sash.onMouseEnter(this))); + this._register(domEvent(this.el, 'mouseleave')(() => Sash.onMouseLeave(this))); this._register(Gesture.addTarget(this.el)); this._register(domEvent(this.el, EventType.Start)(this.onTouchStart, this)); @@ -394,6 +398,15 @@ export class Sash extends Disposable { })); } + private static onMouseEnter(sash: Sash): void { + sash.hoverDelayer.trigger(() => sash.el.classList.add('hover')); + } + + private static onMouseLeave(sash: Sash): void { + sash.hoverDelayer.cancel(); + sash.el.classList.remove('hover'); + } + layout(): void { if (this.orientation === Orientation.VERTICAL) { const verticalProvider = (this.layoutProvider); diff --git a/src/vs/base/browser/ui/tree/objectTree.ts b/src/vs/base/browser/ui/tree/objectTree.ts index 633d8ca7e41..21e65570132 100644 --- a/src/vs/base/browser/ui/tree/objectTree.ts +++ b/src/vs/base/browser/ui/tree/objectTree.ts @@ -69,7 +69,7 @@ export class ObjectTree, TFilterData = void> extends this.model.updateElementHeight(element, height); } - resort(element: T, recursive = true): void { + resort(element: T | null, recursive = true): void { this.model.resort(element, recursive); } diff --git a/src/vs/base/common/stream.ts b/src/vs/base/common/stream.ts index 8874a0fa41a..d9e26f56af9 100644 --- a/src/vs/base/common/stream.ts +++ b/src/vs/base/common/stream.ts @@ -16,6 +16,13 @@ export interface ReadableStreamEvents { /** * The 'data' event is emitted whenever the stream is * relinquishing ownership of a chunk of data to a consumer. + * + * NOTE: PLEASE UNDERSTAND THAT ADDING A DATA LISTENER CAN + * TURN THE STREAM INTO FLOWING MODE. IT IS THEREFOR THE + * LAST LISTENER THAT SHOULD BE ADDED AND NOT THE FIRST + * + * Use `listenStream` as a helper method to listen to + * stream events in the right order. */ on(event: 'data', callback: (data: T) => void): void; @@ -268,7 +275,7 @@ class WriteableStreamImpl implements WriteableStream { // end with data or error if provided if (result instanceof Error) { this.error(result); - } else if (result) { + } else if (typeof result !== 'undefined') { this.write(result); } @@ -489,18 +496,74 @@ export function peekReadable(readable: Readable, reducer: IReducer, max } /** - * Helper to fully read a T stream into a T. + * Helper to fully read a T stream into a T or consuming + * a stream fully, awaiting all the events without caring + * about the data. */ -export function consumeStream(stream: ReadableStreamEvents, reducer: IReducer): Promise { +export function consumeStream(stream: ReadableStreamEvents, reducer: IReducer): Promise; +export function consumeStream(stream: ReadableStreamEvents): Promise; +export function consumeStream(stream: ReadableStreamEvents, reducer?: IReducer): Promise { return new Promise((resolve, reject) => { const chunks: T[] = []; - stream.on('data', data => chunks.push(data)); - stream.on('error', error => reject(error)); - stream.on('end', () => resolve(reducer(chunks))); + listenStream(stream, { + onData: chunk => { + if (reducer) { + chunks.push(chunk); + } + }, + onError: error => { + if (reducer) { + reject(error); + } else { + resolve(undefined); + } + }, + onEnd: () => { + if (reducer) { + resolve(reducer(chunks)); + } else { + resolve(undefined); + } + } + }); }); } +export interface IStreamListener { + + /** + * The 'data' event is emitted whenever the stream is + * relinquishing ownership of a chunk of data to a consumer. + */ + onData(data: T): void; + + /** + * Emitted when any error occurs. + */ + onError(err: Error): void; + + /** + * The 'end' event is emitted when there is no more data + * to be consumed from the stream. The 'end' event will + * not be emitted unless the data is completely consumed. + */ + onEnd(): void; +} + +/** + * Helper to listen to all events of a T stream in proper order. + */ +export function listenStream(stream: ReadableStreamEvents, listener: IStreamListener): void { + stream.on('error', error => listener.onError(error)); + stream.on('end', () => listener.onEnd()); + + // Adding the `data` listener will turn the stream + // into flowing mode. As such it is important to + // add this listener last (DO NOT CHANGE!) + stream.on('data', data => listener.onData(data)); +} + /** * Helper to peek up to `maxChunks` into a stream. The return type signals if * the stream has ended or not. If not, caller needs to add a `data` listener @@ -509,9 +572,9 @@ export function consumeStream(stream: ReadableStreamEvents, reducer: IRedu export function peekStream(stream: ReadableStream, maxChunks: number): Promise> { return new Promise((resolve, reject) => { const streamListeners = new DisposableStore(); + const buffer: T[] = []; // Data Listener - const buffer: T[] = []; const dataListener = (chunk: T) => { // Add to buffer @@ -529,23 +592,27 @@ export function peekStream(stream: ReadableStream, maxChunks: number): Pro } }; - streamListeners.add(toDisposable(() => stream.removeListener('data', dataListener))); - stream.on('data', dataListener); - // Error Listener const errorListener = (error: Error) => { return reject(error); }; - streamListeners.add(toDisposable(() => stream.removeListener('error', errorListener))); - stream.on('error', errorListener); - + // End Listener const endListener = () => { return resolve({ stream, buffer, ended: true }); }; + streamListeners.add(toDisposable(() => stream.removeListener('error', errorListener))); + stream.on('error', errorListener); + streamListeners.add(toDisposable(() => stream.removeListener('end', endListener))); stream.on('end', endListener); + + // Important: leave the `data` listener last because + // this can turn the stream into flowing mode and we + // want `error` events to be received as well. + streamListeners.add(toDisposable(() => stream.removeListener('data', dataListener))); + stream.on('data', dataListener); }); } @@ -585,46 +652,11 @@ export function toReadable(t: T): Readable { export function transform(stream: ReadableStreamEvents, transformer: ITransformer, reducer: IReducer): ReadableStream { const target = newWriteableStream(reducer); - stream.on('data', data => target.write(transformer.data(data))); - stream.on('end', () => target.end()); - stream.on('error', error => target.error(transformer.error ? transformer.error(error) : error)); + listenStream(stream, { + onData: data => target.write(transformer.data(data)), + onError: error => target.error(transformer.error ? transformer.error(error) : error), + onEnd: () => target.end() + }); return target; } - -export interface IReadableStreamObservable { - - /** - * A promise to await the `end` or `error` event - * of a stream. - */ - errorOrEnd: () => Promise; -} - -/** - * Helper to observe a stream for certain events through - * a promise based API. - */ -export function observe(stream: ReadableStream): IReadableStreamObservable { - - // A stream is closed when it ended or errord - // We install this listener right from the - // beginning to catch the events early. - const errorOrEnd = Promise.race([ - new Promise(resolve => stream.on('end', () => resolve())), - new Promise(resolve => stream.on('error', () => resolve())) - ]); - - return { - errorOrEnd(): Promise { - - // We need to ensure the stream is flowing so that our - // listeners are getting triggered. It is possible that - // the stream is not flowing because no `data` listener - // was attached yet. - stream.resume(); - - return errorOrEnd; - } - }; -} diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index 535502f3efd..0757b52ab81 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -1023,146 +1023,141 @@ export class StaticRouter implements IClientRouter } } - -//#region createChannelReceiver / createChannelSender - /** - * Use both `createChannelReceiver` and `createChannelSender` - * for automated process <=> process communication over methods - * and events. You do not need to spell out each method on both - * sides, a proxy will take care of this. + * Use ProxyChannels to automatically wrapping and unwrapping + * services to/from IPC channels, instead of manually wrapping + * each service method and event. * - * Rules: - * - if marshalling is enabled, only `URI` and `RegExp` is converted + * Restrictions: + * - If marshalling is enabled, only `URI` and `RegExp` is converted * automatically for you - * - events must follow the naming convention `onUppercase` + * - Events must follow the naming convention `onUpperCase` * - `CancellationToken` is currently not supported - * - if a context is provided, you can use `AddFirstParameterToFunctions` + * - If a context is provided, you can use `AddFirstParameterToFunctions` * utility to signal this in the receiving side type */ +export namespace ProxyChannel { -export interface IBaseChannelOptions { + export interface IProxyOptions { - /** - * Disables automatic marshalling of `URI`. - * If marshalling is disabled, `UriComponents` - * must be used instead. - */ - disableMarshalling?: boolean; -} - -export interface IChannelReceiverOptions extends IBaseChannelOptions { } - -export function createChannelReceiver(service: unknown, options?: IChannelReceiverOptions): IServerChannel { - const handler = service as { [key: string]: unknown }; - const disableMarshalling = options && options.disableMarshalling; - - // Buffer any event that should be supported by - // iterating over all property keys and finding them - const mapEventNameToEvent = new Map>(); - for (const key in handler) { - if (propertyIsEvent(key)) { - mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event, true)); - } + /** + * Disables automatic marshalling of `URI`. + * If marshalling is disabled, `UriComponents` + * must be used instead. + */ + disableMarshalling?: boolean; } - return new class implements IServerChannel { + export interface ICreateServiceChannelOptions extends IProxyOptions { } - listen(_: unknown, event: string): Event { - const eventImpl = mapEventNameToEvent.get(event); - if (eventImpl) { - return eventImpl as Event; + export function fromService(service: unknown, options?: ICreateServiceChannelOptions): IServerChannel { + const handler = service as { [key: string]: unknown }; + const disableMarshalling = options && options.disableMarshalling; + + // Buffer any event that should be supported by + // iterating over all property keys and finding them + const mapEventNameToEvent = new Map>(); + for (const key in handler) { + if (propertyIsEvent(key)) { + mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event, true)); } - - throw new Error(`Event not found: ${event}`); } - call(_: unknown, command: string, args?: any[]): Promise { - const target = handler[command]; - if (typeof target === 'function') { + return new class implements IServerChannel { - // Revive unless marshalling disabled - if (!disableMarshalling && Array.isArray(args)) { - for (let i = 0; i < args.length; i++) { - args[i] = revive(args[i]); - } + listen(_: unknown, event: string): Event { + const eventImpl = mapEventNameToEvent.get(event); + if (eventImpl) { + return eventImpl as Event; } - return target.apply(handler, args); + throw new Error(`Event not found: ${event}`); } - throw new Error(`Method not found: ${command}`); - } - }; -} - -export interface IChannelSenderOptions extends IBaseChannelOptions { - - /** - * If provided, will add the value of `context` - * to each method call to the target. - */ - context?: unknown; - - /** - * If provided, will not proxy any of the properties - * that are part of the Map but rather return that value. - */ - properties?: Map; -} - -export function createChannelSender(channel: IChannel, options?: IChannelSenderOptions): T { - const disableMarshalling = options && options.disableMarshalling; - - return new Proxy({}, { - get(_target: T, propKey: PropertyKey) { - if (typeof propKey === 'string') { - - // Check for predefined values - if (options?.properties?.has(propKey)) { - return options.properties.get(propKey); - } - - // Event - if (propertyIsEvent(propKey)) { - return channel.listen(propKey); - } - - // Function - return async function (...args: any[]) { - - // Add context if any - let methodArgs: any[]; - if (options && !isUndefinedOrNull(options.context)) { - methodArgs = [options.context, ...args]; - } else { - methodArgs = args; - } - - const result = await channel.call(propKey, methodArgs); + call(_: unknown, command: string, args?: any[]): Promise { + const target = handler[command]; + if (typeof target === 'function') { // Revive unless marshalling disabled - if (!disableMarshalling) { - return revive(result); + if (!disableMarshalling && Array.isArray(args)) { + for (let i = 0; i < args.length; i++) { + args[i] = revive(args[i]); + } } - return result; - }; + return target.apply(handler, args); + } + + throw new Error(`Method not found: ${command}`); } + }; + } - throw new Error(`Property not found: ${String(propKey)}`); - } - }) as T; + export interface ICreateProxyServiceOptions extends IProxyOptions { + + /** + * If provided, will add the value of `context` + * to each method call to the target. + */ + context?: unknown; + + /** + * If provided, will not proxy any of the properties + * that are part of the Map but rather return that value. + */ + properties?: Map; + } + + export function toService(channel: IChannel, options?: ICreateProxyServiceOptions): T { + const disableMarshalling = options && options.disableMarshalling; + + return new Proxy({}, { + get(_target: T, propKey: PropertyKey) { + if (typeof propKey === 'string') { + + // Check for predefined values + if (options?.properties?.has(propKey)) { + return options.properties.get(propKey); + } + + // Event + if (propertyIsEvent(propKey)) { + return channel.listen(propKey); + } + + // Function + return async function (...args: any[]) { + + // Add context if any + let methodArgs: any[]; + if (options && !isUndefinedOrNull(options.context)) { + methodArgs = [options.context, ...args]; + } else { + methodArgs = args; + } + + const result = await channel.call(propKey, methodArgs); + + // Revive unless marshalling disabled + if (!disableMarshalling) { + return revive(result); + } + + return result; + }; + } + + throw new Error(`Property not found: ${String(propKey)}`); + } + }) as T; + } + + function propertyIsEvent(name: string): boolean { + // Assume a property is an event if it has a form of "onSomething" + return name[0] === 'o' && name[1] === 'n' && strings.isUpperAsciiLetter(name.charCodeAt(2)); + } } -function propertyIsEvent(name: string): boolean { - // Assume a property is an event if it has a form of "onSomething" - return name[0] === 'o' && name[1] === 'n' && strings.isUpperAsciiLetter(name.charCodeAt(2)); -} - -//#endregion - - const colorTables = [ ['#2977B1', '#FC802D', '#34A13A', '#D3282F', '#9366BA'], ['#8B564C', '#E177C0', '#7F7F7F', '#BBBE3D', '#2EBECD'] diff --git a/src/vs/base/parts/ipc/electron-sandbox/ipc.mp.ts b/src/vs/base/parts/ipc/electron-browser/ipc.mp.ts similarity index 90% rename from src/vs/base/parts/ipc/electron-sandbox/ipc.mp.ts rename to src/vs/base/parts/ipc/electron-browser/ipc.mp.ts index 98e865fe9bf..3f031a057e2 100644 --- a/src/vs/base/parts/ipc/electron-sandbox/ipc.mp.ts +++ b/src/vs/base/parts/ipc/electron-browser/ipc.mp.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { ipcRenderer } from 'electron'; import { Event } from 'vs/base/common/event'; import { ClientConnectionEvent, IPCServer } from 'vs/base/parts/ipc/common/ipc'; import { Protocol as MessagePortProtocol } from 'vs/base/parts/ipc/common/ipc.mp'; @@ -39,6 +39,9 @@ export class Server extends IPCServer { }; // Send one port back to the requestor + // Note: we intentionally use `electron` APIs here because + // transferables like the `MessagePort` cannot be transfered + // over preload scripts when `contextIsolation: true` ipcRenderer.postMessage('vscode:createMessageChannelResult', nonce, [outgoingPort]); return result; diff --git a/src/vs/base/parts/ipc/test/common/ipc.test.ts b/src/vs/base/parts/ipc/test/common/ipc.test.ts index 8ed0f3797f1..6e3dd39a5e1 100644 --- a/src/vs/base/parts/ipc/test/common/ipc.test.ts +++ b/src/vs/base/parts/ipc/test/common/ipc.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { Emitter, Event } from 'vs/base/common/event'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { canceled } from 'vs/base/common/errors'; @@ -332,10 +332,10 @@ suite('Base IPC', function () { const testServer = new TestIPCServer(); server = testServer; - server.registerChannel(TestChannelId, createChannelReceiver(service)); + server.registerChannel(TestChannelId, ProxyChannel.fromService(service)); client = testServer.createConnection('client1'); - ipcService = createChannelSender(client.getChannel(TestChannelId)); + ipcService = ProxyChannel.toService(client.getChannel(TestChannelId)); }); teardown(function () { @@ -398,10 +398,10 @@ suite('Base IPC', function () { const testServer = new TestIPCServer(); server = testServer; - server.registerChannel(TestChannelId, createChannelReceiver(service)); + server.registerChannel(TestChannelId, ProxyChannel.fromService(service)); client = testServer.createConnection('client1'); - ipcService = createChannelSender(client.getChannel(TestChannelId), { context: 'Super Context' }); + ipcService = ProxyChannel.toService(client.getChannel(TestChannelId), { context: 'Super Context' }); }); teardown(function () { diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index 11984805df6..bd12c6d8fb2 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -35,17 +35,6 @@ } }, - /** - * @param {string} channel - * @param {any} message - * @param {MessagePort[]} transfer - */ - postMessage(channel, message, transfer) { - if (validateIPC(channel)) { - ipcRenderer.postMessage(channel, message, transfer); - } - }, - /** * @param {string} channel * @param {any[]} args @@ -88,6 +77,33 @@ } }, + ipcMessagePort: { + + /** + * @param {string} channelRequest + * @param {string} channelResponse + * @param {string} requestNonce + */ + connect(channelRequest, channelResponse, requestNonce) { + if (validateIPC(channelRequest) && validateIPC(channelResponse)) { + const responseListener = (/** @type {import('electron').IpcRendererEvent} */ e, /** @type {string} */ responseNonce) => { + // validate that the nonce from the response is the same + // as when requested. and if so, use `postMessage` to + // send the `MessagePort` safely over, even when context + // isolation is enabled + if (requestNonce === responseNonce) { + ipcRenderer.off(channelResponse, responseListener); + window.postMessage(requestNonce, '*', e.ports); + } + }; + + // request message port from main and await result + ipcRenderer.on(channelResponse, responseListener); + ipcRenderer.send(channelRequest, requestNonce); + } + } + }, + /** * Support for subset of methods of Electron's `webFrame` type. */ diff --git a/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts b/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts index 1adb322d1ba..e03f9e13673 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/electronTypes.ts @@ -15,10 +15,12 @@ export interface IpcRendererEvent extends Event { // Docs: https://electronjs.org/docs/api/structures/ipc-renderer-event - /** - * A list of MessagePorts that were transferred with this message - */ - ports: MessagePort[]; + // Note: API with `Transferable` intentionally commented out because you + // cannot transfer these when `contextIsolation: true`. + // /** + // * A list of MessagePorts that were transferred with this message + // */ + // ports: MessagePort[]; /** * The `IpcRenderer` instance that emitted the event originally */ @@ -93,20 +95,23 @@ export interface IpcRenderer { * If you do not need a response to the message, consider using `ipcRenderer.send`. */ invoke(channel: string, ...args: any[]): Promise; - /** - * Send a message to the main process, optionally transferring ownership of zero or - * more `MessagePort` objects. - * - * The transferred `MessagePort` objects will be available in the main process as - * `MessagePortMain` objects by accessing the `ports` property of the emitted - * event. - * - * For example: - * - * For more information on using `MessagePort` and `MessageChannel`, see the MDN - * documentation. - */ - postMessage(channel: string, message: any, transfer?: MessagePort[]): void; + + // Note: API with `Transferable` intentionally commented out because you + // cannot transfer these when `contextIsolation: true`. + // /** + // * Send a message to the main process, optionally transferring ownership of zero or + // * more `MessagePort` objects. + // * + // * The transferred `MessagePort` objects will be available in the main process as + // * `MessagePortMain` objects by accessing the `ports` property of the emitted + // * event. + // * + // * For example: + // * + // * For more information on using `MessagePort` and `MessageChannel`, see the MDN + // * documentation. + // */ + // postMessage(channel: string, message: any): void; } export interface WebFrame { diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index 4c38fa964a3..05492311ea8 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -94,7 +94,23 @@ export interface ISandboxContext { sandbox: boolean; } +export interface IpcMessagePort { + + /** + * Establish a connection via `MessagePort` to a target. The main process + * will need to transfer the port over to the `channelResponse` after listening + * to `channelRequest` with a payload of `requestNonce` so that the + * source can correlate the response. + * + * The source should install a `window.on('message')` listener, ensuring `e.data` + * matches `requestNonce`, `e.source` matches `window` and then receiving the + * `MessagePort` via `e.ports[0]`. + */ + connect(channelRequest: string, channelResponse: string, requestNonce: string): void; +} + export const ipcRenderer: IpcRenderer = globals.vscode.ipcRenderer; +export const ipcMessagePort: IpcMessagePort = globals.vscode.ipcMessagePort; export const webFrame: WebFrame = globals.vscode.webFrame; export const crashReporter: CrashReporter = globals.vscode.crashReporter; export const process: ISandboxNodeProcess = globals.vscode.process; diff --git a/src/vs/base/test/common/stream.test.ts b/src/vs/base/test/common/stream.test.ts index 0fb36467b2f..7594d7cb8e6 100644 --- a/src/vs/base/test/common/stream.test.ts +++ b/src/vs/base/test/common/stream.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { isReadableStream, newWriteableStream, Readable, consumeReadable, peekReadable, consumeStream, ReadableStream, toStream, toReadable, transform, peekStream, isReadableBufferedStream, observe } from 'vs/base/common/stream'; +import { isReadableStream, newWriteableStream, Readable, consumeReadable, peekReadable, consumeStream, ReadableStream, toStream, toReadable, transform, peekStream, isReadableBufferedStream, listenStream } from 'vs/base/common/stream'; import { timeout } from 'vs/base/common/async'; suite('Stream', () => { @@ -69,6 +69,7 @@ suite('Stream', () => { stream.end('Final Bit'); assert.strictEqual(chunks.length, 4); assert.strictEqual(chunks[3], 'Final Bit'); + assert.strictEqual(end, true); stream.destroy(); @@ -76,6 +77,15 @@ suite('Stream', () => { assert.strictEqual(chunks.length, 4); }); + test('WriteableStream - end with empty string works', async () => { + const reducer = (strings: string[]) => strings.length > 0 ? strings.join() : 'error'; + const stream = newWriteableStream(reducer); + stream.end(''); + + const result = await consumeStream(stream, reducer); + assert.strictEqual(result, ''); + }); + test('WriteableStream - removeListener', () => { const stream = newWriteableStream(strings => strings.join()); @@ -270,6 +280,56 @@ suite('Stream', () => { assert.strictEqual(consumed, '1,2,3,4,5'); }); + test('consumeStream - without reducer', async () => { + const stream = readableToStream(arrayToReadable(['1', '2', '3', '4', '5'])); + const consumed = await consumeStream(stream); + assert.strictEqual(consumed, undefined); + }); + + test('consumeStream - without reducer and error', async () => { + const stream = newWriteableStream(strings => strings.join()); + stream.error(new Error()); + + const consumed = await consumeStream(stream); + assert.strictEqual(consumed, undefined); + }); + + test('listenStream', () => { + const stream = newWriteableStream(strings => strings.join()); + + let error = false; + let end = false; + let data = ''; + + listenStream(stream, { + onData: d => { + data = d; + }, + onError: e => { + error = true; + }, + onEnd: () => { + end = true; + } + }); + + stream.write('Hello'); + + assert.strictEqual(data, 'Hello'); + + stream.write('World'); + assert.strictEqual(data, 'World'); + + assert.strictEqual(error, false); + assert.strictEqual(end, false); + + stream.error(new Error()); + assert.strictEqual(error, true); + + stream.end('Final Bit'); + assert.strictEqual(end, true); + }); + test('peekStream', async () => { for (let i = 0; i < 5; i++) { const stream = readableToStream(arrayToReadable(['1', '2', '3', '4', '5'])); @@ -335,30 +395,6 @@ suite('Stream', () => { assert.strictEqual(consumed, '11,22,33,44,55'); }); - test('observer', async () => { - const source1 = newWriteableStream(strings => strings.join()); - setTimeout(() => source1.error(new Error())); - await observe(source1).errorOrEnd(); - - const source2 = newWriteableStream(strings => strings.join()); - setTimeout(() => source2.end('Hello Test')); - await observe(source2).errorOrEnd(); - - const source3 = newWriteableStream(strings => strings.join()); - setTimeout(() => { - source3.write('Hello Test'); - source3.error(new Error()); - }); - await observe(source3).errorOrEnd(); - - const source4 = newWriteableStream(strings => strings.join()); - setTimeout(() => { - source4.write('Hello Test'); - source4.end(); - }); - await observe(source4).errorOrEnd(); - }); - test('events are delivered even if a listener is removed during delivery', () => { const stream = newWriteableStream(strings => strings.join()); diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index e8639c8ea31..18f4dd64f99 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -7,8 +7,9 @@ import product from 'vs/platform/product/common/product'; import * as fs from 'fs'; import { release } from 'os'; import { gracefulify } from 'graceful-fs'; -import { Server as MessagePortServer } from 'vs/base/parts/ipc/electron-sandbox/ipc.mp'; -import { StaticRouter, createChannelSender, createChannelReceiver } from 'vs/base/parts/ipc/common/ipc'; +import { ipcRenderer } from 'electron'; +import { Server as MessagePortServer } from 'vs/base/parts/ipc/electron-browser/ipc.mp'; +import { StaticRouter, ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; @@ -28,7 +29,6 @@ import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProp import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc'; import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; -import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { ILogService, ILoggerService, MultiplexLogService, ConsoleLogger } from 'vs/platform/log/common/log'; import { LogLevelChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; @@ -40,7 +40,8 @@ import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/co import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner'; import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner'; import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner'; -import { IMainProcessService, MessagePortMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { MessagePortMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog'; import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService'; import { IDiagnosticsService } from 'vs/platform/diagnostics/common/diagnostics'; @@ -184,7 +185,7 @@ class SharedProcessMain extends Disposable { services.set(IRequestService, new SyncDescriptor(RequestService)); // Native Host - const nativeHostService = createChannelSender(mainProcessService.getChannel('nativeHost'), { context: this.configuration.windowId }); + const nativeHostService = ProxyChannel.toService(mainProcessService.getChannel('nativeHost'), { context: this.configuration.windowId }); services.set(INativeHostService, nativeHostService); // Download @@ -270,12 +271,12 @@ class SharedProcessMain extends Disposable { // Localizations const localizationsService = accessor.get(ILocalizationsService); - const localizationsChannel = createChannelReceiver(localizationsService); + const localizationsChannel = ProxyChannel.fromService(localizationsService); this.server.registerChannel('localizations', localizationsChannel); // Diagnostics const diagnosticsService = accessor.get(IDiagnosticsService); - const diagnosticsChannel = createChannelReceiver(diagnosticsService); + const diagnosticsChannel = ProxyChannel.fromService(diagnosticsService); this.server.registerChannel('diagnostics', diagnosticsChannel); // Extension Tips diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 34e9f56ada6..ff58b3f5664 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -10,14 +10,14 @@ import { IProcessEnvironment, isWindows, isMacintosh, isLinux, isLinuxSnap } fro import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; -import { resolveShellEnv } from 'vs/code/node/shellEnv'; +import { resolveShellEnv } from 'vs/platform/environment/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; import { UpdateChannel } from 'vs/platform/update/electron-main/updateIpc'; -import { getDelayedChannel, StaticRouter, createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { getDelayedChannel, StaticRouter, ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc.electron'; import { Server as NodeIPCServer } from 'vs/base/parts/ipc/node/ipc.net'; import { Client as MessagePortClient } from 'vs/base/parts/ipc/electron-main/ipc.mp'; -import { SharedProcess } from 'vs/code/electron-main/sharedProcess'; +import { SharedProcess } from 'vs/platform/sharedProcess/electron-main/sharedProcess'; import { LaunchMainService, ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; @@ -525,7 +525,7 @@ export class CodeApplication extends Disposable { services.set(IWindowsMainService, new SyncDescriptor(WindowsMainService, [machineId, this.userEnv])); services.set(IDialogMainService, new SyncDescriptor(DialogMainService)); services.set(ILaunchMainService, new SyncDescriptor(LaunchMainService)); - services.set(IDiagnosticsService, createChannelSender(getDelayedChannel(sharedProcessReady.then(client => client.getChannel('diagnostics'))))); + services.set(IDiagnosticsService, ProxyChannel.toService(getDelayedChannel(sharedProcessReady.then(client => client.getChannel('diagnostics'))))); services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv])); services.set(IEncryptionMainService, new SyncDescriptor(EncryptionMainService, [machineId])); @@ -606,7 +606,7 @@ export class CodeApplication extends Disposable { // Register more Main IPC services const launchMainService = accessor.get(ILaunchMainService); - const launchChannel = createChannelReceiver(launchMainService, { disableMarshalling: true }); + const launchChannel = ProxyChannel.fromService(launchMainService, { disableMarshalling: true }); this.mainIpcServer.registerChannel('launch', launchChannel); // Register more Electron IPC services @@ -615,44 +615,44 @@ export class CodeApplication extends Disposable { electronIpcServer.registerChannel('update', updateChannel); const issueMainService = accessor.get(IIssueMainService); - const issueChannel = createChannelReceiver(issueMainService); + const issueChannel = ProxyChannel.fromService(issueMainService); electronIpcServer.registerChannel('issue', issueChannel); const encryptionMainService = accessor.get(IEncryptionMainService); - const encryptionChannel = createChannelReceiver(encryptionMainService); + const encryptionChannel = ProxyChannel.fromService(encryptionMainService); electronIpcServer.registerChannel('encryption', encryptionChannel); const keyboardLayoutMainService = accessor.get(IKeyboardLayoutMainService); - const keyboardLayoutChannel = createChannelReceiver(keyboardLayoutMainService); + const keyboardLayoutChannel = ProxyChannel.fromService(keyboardLayoutMainService); electronIpcServer.registerChannel('keyboardLayout', keyboardLayoutChannel); const displayMainService = accessor.get(IDisplayMainService); - const displayChannel = createChannelReceiver(displayMainService); + const displayChannel = ProxyChannel.fromService(displayMainService); electronIpcServer.registerChannel('display', displayChannel); const nativeHostMainService = this.nativeHostMainService = accessor.get(INativeHostMainService); - const nativeHostChannel = createChannelReceiver(this.nativeHostMainService); + const nativeHostChannel = ProxyChannel.fromService(this.nativeHostMainService); electronIpcServer.registerChannel('nativeHost', nativeHostChannel); sharedProcessClient.then(client => client.registerChannel('nativeHost', nativeHostChannel)); const workspacesService = accessor.get(IWorkspacesService); - const workspacesChannel = createChannelReceiver(workspacesService); + const workspacesChannel = ProxyChannel.fromService(workspacesService); electronIpcServer.registerChannel('workspaces', workspacesChannel); const menubarMainService = accessor.get(IMenubarMainService); - const menubarChannel = createChannelReceiver(menubarMainService); + const menubarChannel = ProxyChannel.fromService(menubarMainService); electronIpcServer.registerChannel('menubar', menubarChannel); const urlService = accessor.get(IURLService); - const urlChannel = createChannelReceiver(urlService); + const urlChannel = ProxyChannel.fromService(urlService); electronIpcServer.registerChannel('url', urlChannel); const extensionUrlTrustService = accessor.get(IExtensionUrlTrustService); - const extensionUrlTrustChannel = createChannelReceiver(extensionUrlTrustService); + const extensionUrlTrustChannel = ProxyChannel.fromService(extensionUrlTrustService); electronIpcServer.registerChannel('extensionUrlTrust', extensionUrlTrustChannel); const webviewManagerService = accessor.get(IWebviewManagerService); - const webviewChannel = createChannelReceiver(webviewManagerService); + const webviewChannel = ProxyChannel.fromService(webviewManagerService); electronIpcServer.registerChannel('webview', webviewChannel); const storageMainService = accessor.get(IStorageMainService); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 5194253b49a..f9de03dfc32 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -12,7 +12,7 @@ import product from 'vs/platform/product/common/product'; import { parseMainProcessArgv, addArg } from 'vs/platform/environment/node/argvHelper'; import { createWaitMarkerFile } from 'vs/platform/environment/node/waitMarkerFile'; import { LifecycleMainService, ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { Server as NodeIPCServer, serve as nodeIPCServe, connect as nodeIPCConnect, XDG_RUNTIME_DIR } from 'vs/base/parts/ipc/node/ipc.net'; import { Client as NodeIPCClient } from 'vs/base/parts/ipc/common/ipc.net'; import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; @@ -292,7 +292,7 @@ class CodeMain { }, 10000); } - const launchService = createChannelSender(client.getChannel('launch'), { disableMarshalling: true }); + const launchService = ProxyChannel.toService(client.getChannel('launch'), { disableMarshalling: true }); // Process Info if (args.status) { diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index aab72a48cd6..3680d8b5185 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -38,6 +38,7 @@ import { IUndoRedoService, ResourceEditStackSnapshot } from 'vs/platform/undoRed import { TextChange } from 'vs/editor/common/model/textChange'; import { Constants } from 'vs/base/common/uint'; import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer'; +import { listenStream } from 'vs/base/common/stream'; function createTextBufferBuilder() { return new PieceTreeTextBufferBuilder(); @@ -64,33 +65,33 @@ export function createTextBufferFactoryFromStream(stream: ITextStream | VSBuffer let done = false; - stream.on('data', (chunk: string | VSBuffer) => { - if (validator) { - const error = validator(chunk); - if (error) { + listenStream(stream, { + onData: chunk => { + if (validator) { + const error = validator(chunk); + if (error) { + done = true; + reject(error); + } + } + + if (filter) { + chunk = filter(chunk); + } + + builder.acceptChunk((typeof chunk === 'string') ? chunk : chunk.toString()); + }, + onError: error => { + if (!done) { done = true; reject(error); } - } - - if (filter) { - chunk = filter(chunk); - } - - builder.acceptChunk((typeof chunk === 'string') ? chunk : chunk.toString()); - }); - - stream.on('error', (error) => { - if (!done) { - done = true; - reject(error); - } - }); - - stream.on('end', () => { - if (!done) { - done = true; - resolve(builder.finish()); + }, + onEnd: () => { + if (!done) { + done = true; + resolve(builder.finish()); + } } }); }); diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.css b/src/vs/platform/actions/browser/menuEntryActionViewItem.css index 5ef85311a27..c74cf3ac2e0 100644 --- a/src/vs/platform/actions/browser/menuEntryActionViewItem.css +++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.css @@ -5,7 +5,6 @@ .monaco-action-bar .action-item.menu-entry .action-label { background-image: var(--menu-entry-icon-light); - display: inline-flex; } .vs-dark .monaco-action-bar .action-item.menu-entry .action-label, diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts index cc1f7304ad2..5e107a1a8a6 100644 --- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts +++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts @@ -95,7 +95,7 @@ function fillInActions( const target = isPrimaryGroup(group) ? primaryBucket : secondaryBucket; const submenuActions = action.actions; - if (target.length + submenuActions.length - 1 <= primaryMaxCount && shouldInlineSubmenu(action, group, target.length)) { + if (target.length + submenuActions.length - 2 <= primaryMaxCount && shouldInlineSubmenu(action, group, target.length)) { target.splice(index, 1, ...submenuActions); } } diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/platform/environment/node/shellEnv.ts similarity index 100% rename from src/vs/code/node/shellEnv.ts rename to src/vs/platform/environment/node/shellEnv.ts diff --git a/src/vs/platform/files/common/fileService.ts b/src/vs/platform/files/common/fileService.ts index 9fddb5507f2..ab2a5236895 100644 --- a/src/vs/platform/files/common/fileService.ts +++ b/src/vs/platform/files/common/fileService.ts @@ -14,7 +14,7 @@ import { TernarySearchTree } from 'vs/base/common/map'; import { isNonEmptyArray, coalesce } from 'vs/base/common/arrays'; import { ILogService } from 'vs/platform/log/common/log'; import { VSBuffer, VSBufferReadable, readableToBuffer, bufferToReadable, streamToBuffer, VSBufferReadableStream, VSBufferReadableBufferedStream, bufferedStreamToBuffer, newWriteableBufferStream } from 'vs/base/common/buffer'; -import { isReadableStream, transform, peekReadable, peekStream, isReadableBufferedStream, newWriteableStream, IReadableStreamObservable, observe } from 'vs/base/common/stream'; +import { isReadableStream, transform, peekReadable, peekStream, isReadableBufferedStream, newWriteableStream, listenStream, consumeStream } from 'vs/base/common/stream'; import { Promises, Queue } from 'vs/base/common/async'; import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; import { Schemas } from 'vs/base/common/network'; @@ -454,8 +454,7 @@ export class FileService extends Disposable implements IFileService { throw error; }); - let fileStreamObserver: IReadableStreamObservable | undefined = undefined; - + let fileStream: VSBufferReadableStream | undefined = undefined; try { // if the etag is provided, we await the result of the validation @@ -466,8 +465,6 @@ export class FileService extends Disposable implements IFileService { await statPromise; } - let fileStream: VSBufferReadableStream | undefined = undefined; - // read unbuffered (only if either preferred, or the provider has no buffered read capability) if (!(hasOpenReadWriteCloseCapability(provider) || hasFileReadStreamCapability(provider)) || (hasReadWriteCapability(provider) && options?.preferUnbuffered)) { fileStream = this.readFileUnbuffered(provider, resource, options); @@ -483,9 +480,6 @@ export class FileService extends Disposable implements IFileService { fileStream = this.readFileBuffered(provider, resource, cancellableSource.token, options); } - // observe the stream for the error case below - fileStreamObserver = observe(fileStream); - const fileStat = await statPromise; return { @@ -497,8 +491,8 @@ export class FileService extends Disposable implements IFileService { // Await the stream to finish so that we exit this method // in a consistent state with file handles closed // (https://github.com/microsoft/vscode/issues/114024) - if (fileStreamObserver) { - await fileStreamObserver.errorOrEnd(); + if (fileStream) { + await consumeStream(fileStream); } throw new FileOperationError(localize('err.read', "Unable to read file '{0}' ({1})", this.resourceForError(resource), ensureFileSystemProviderError(error).toString()), toFileOperationResult(error), options); @@ -1065,28 +1059,29 @@ export class FileService extends Disposable implements IFileService { return new Promise(async (resolve, reject) => { - stream.on('data', async chunk => { + listenStream(stream, { + onData: async chunk => { - // pause stream to perform async write operation - stream.pause(); + // pause stream to perform async write operation + stream.pause(); - try { - await this.doWriteBuffer(provider, handle, chunk, chunk.byteLength, posInFile, 0); - } catch (error) { - return reject(error); - } + try { + await this.doWriteBuffer(provider, handle, chunk, chunk.byteLength, posInFile, 0); + } catch (error) { + return reject(error); + } - posInFile += chunk.byteLength; + posInFile += chunk.byteLength; - // resume stream now that we have successfully written - // run this on the next tick to prevent increasing the - // execution stack because resume() may call the event - // handler again before finishing. - setTimeout(() => stream.resume()); + // resume stream now that we have successfully written + // run this on the next tick to prevent increasing the + // execution stack because resume() may call the event + // handler again before finishing. + setTimeout(() => stream.resume()); + }, + onError: error => reject(error), + onEnd: () => resolve() }); - - stream.on('error', error => reject(error)); - stream.on('end', () => resolve()); }); } diff --git a/src/vs/platform/files/node/diskFileSystemProvider.ts b/src/vs/platform/files/node/diskFileSystemProvider.ts index a7216230eb6..cffe2849710 100644 --- a/src/vs/platform/files/node/diskFileSystemProvider.ts +++ b/src/vs/platform/files/node/diskFileSystemProvider.ts @@ -30,7 +30,7 @@ import { VSBuffer } from 'vs/base/common/buffer'; export interface IWatcherOptions { pollingInterval?: number; - usePolling: boolean; + usePolling: boolean | string[]; } export interface IDiskFileSystemProviderOptions { diff --git a/src/vs/platform/files/node/watcher/nsfw/watcherApp.ts b/src/vs/platform/files/node/watcher/nsfw/watcherApp.ts index d7fa2831572..0cc6da3b19f 100644 --- a/src/vs/platform/files/node/watcher/nsfw/watcherApp.ts +++ b/src/vs/platform/files/node/watcher/nsfw/watcherApp.ts @@ -5,8 +5,8 @@ import { Server } from 'vs/base/parts/ipc/node/ipc.cp'; import { NsfwWatcherService } from 'vs/platform/files/node/watcher/nsfw/nsfwWatcherService'; -import { createChannelReceiver } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; const server = new Server('watcher'); const service = new NsfwWatcherService(); -server.registerChannel('watcher', createChannelReceiver(service)); +server.registerChannel('watcher', ProxyChannel.fromService(service)); diff --git a/src/vs/platform/files/node/watcher/nsfw/watcherService.ts b/src/vs/platform/files/node/watcher/nsfw/watcherService.ts index 3b0cd433fce..32dead9e7fd 100644 --- a/src/vs/platform/files/node/watcher/nsfw/watcherService.ts +++ b/src/vs/platform/files/node/watcher/nsfw/watcherService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createChannelSender, getNextTickChannel } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel, getNextTickChannel } from 'vs/base/parts/ipc/common/ipc'; import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; import { IDiskFileChange, ILogMessage } from 'vs/platform/files/node/watcher/watcher'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -61,7 +61,7 @@ export class FileWatcher extends Disposable { })); // Initialize watcher - this.service = createChannelSender(getNextTickChannel(client.getChannel('watcher'))); + this.service = ProxyChannel.toService(getNextTickChannel(client.getChannel('watcher'))); this.service.setVerboseLogging(this.verboseLogging); diff --git a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts index 25276aa2ac4..4e60dec99af 100644 --- a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts @@ -49,7 +49,7 @@ export class ChokidarWatcherService extends Disposable implements IWatcherServic get wacherCount() { return this._watcherCount; } private pollingInterval?: number; - private usePolling?: boolean; + private usePolling?: boolean | string[]; private verboseLogging: boolean | undefined; private spamCheckStartTime: number | undefined; @@ -101,7 +101,11 @@ export class ChokidarWatcherService extends Disposable implements IWatcherServic private watch(basePath: string, requests: IWatcherRequest[]): IWatcher { const pollingInterval = this.pollingInterval || 5000; - const usePolling = this.usePolling; + let usePolling = this.usePolling; // boolean or a list of path patterns + if (Array.isArray(usePolling)) { + // switch to polling if one of the paths matches with a watched path + usePolling = usePolling.some(pattern => requests.some(r => glob.match(pattern, r.path))); + } const watcherOpts: chokidar.WatchOptions = { ignoreInitial: true, diff --git a/src/vs/platform/files/node/watcher/unix/watcher.ts b/src/vs/platform/files/node/watcher/unix/watcher.ts index 83ce68dbe8c..1e4ec9eccaa 100644 --- a/src/vs/platform/files/node/watcher/unix/watcher.ts +++ b/src/vs/platform/files/node/watcher/unix/watcher.ts @@ -13,7 +13,7 @@ export interface IWatcherRequest { export interface IWatcherOptions { pollingInterval?: number; - usePolling?: boolean; + usePolling?: boolean | string[]; // boolean or a set of glob patterns matching folders that need polling verboseLogging?: boolean; } diff --git a/src/vs/platform/files/node/watcher/unix/watcherApp.ts b/src/vs/platform/files/node/watcher/unix/watcherApp.ts index 471e9c9af3e..d7ecdda29b4 100644 --- a/src/vs/platform/files/node/watcher/unix/watcherApp.ts +++ b/src/vs/platform/files/node/watcher/unix/watcherApp.ts @@ -5,8 +5,8 @@ import { Server } from 'vs/base/parts/ipc/node/ipc.cp'; import { ChokidarWatcherService } from 'vs/platform/files/node/watcher/unix/chokidarWatcherService'; -import { createChannelReceiver } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; const server = new Server('watcher'); const service = new ChokidarWatcherService(); -server.registerChannel('watcher', createChannelReceiver(service)); +server.registerChannel('watcher', ProxyChannel.fromService(service)); diff --git a/src/vs/platform/files/node/watcher/unix/watcherService.ts b/src/vs/platform/files/node/watcher/unix/watcherService.ts index 75f1bcf90b4..1ee26f965ee 100644 --- a/src/vs/platform/files/node/watcher/unix/watcherService.ts +++ b/src/vs/platform/files/node/watcher/unix/watcherService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createChannelSender, getNextTickChannel } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel, getNextTickChannel } from 'vs/base/parts/ipc/common/ipc'; import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; import { IDiskFileChange, ILogMessage } from 'vs/platform/files/node/watcher/watcher'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -62,7 +62,7 @@ export class FileWatcher extends Disposable { })); // Initialize watcher - this.service = createChannelSender(getNextTickChannel(client.getChannel('watcher'))); + this.service = ProxyChannel.toService(getNextTickChannel(client.getChannel('watcher'))); this.service.init({ ...this.watcherOptions, verboseLogging: this.verboseLogging }); this._register(this.service.onDidChangeFile(e => !this.isDisposed && this.onDidFilesChange(e))); diff --git a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts index 667e135bca6..b5dfa9db4d8 100644 --- a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts +++ b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts @@ -1584,6 +1584,20 @@ flakySuite('Disk File Service', function () { assert.strictEqual(error!.fileOperationResult, FileOperationResult.FILE_TOO_LARGE); } + (isWindows ? test.skip /* windows: cannot create file symbolic link without elevated context */ : test)('readFile - dangling symbolic link - https://github.com/microsoft/vscode/issues/116049', async () => { + const link = URI.file(join(testDir, 'small.js-link')); + await promises.symlink(join(testDir, 'small.js'), link.fsPath); + + let error: FileOperationError | undefined = undefined; + try { + await service.readFile(link); + } catch (err) { + error = err; + } + + assert.ok(error); + }); + test('createFile', async () => { return assertCreateFile(contents => VSBuffer.fromString(contents)); }); diff --git a/src/vs/platform/ipc/electron-browser/mainProcessService.ts b/src/vs/platform/ipc/electron-browser/mainProcessService.ts new file mode 100644 index 00000000000..9253eddb605 --- /dev/null +++ b/src/vs/platform/ipc/electron-browser/mainProcessService.ts @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IChannel, IServerChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; +import { Server as MessagePortServer } from 'vs/base/parts/ipc/electron-browser/ipc.mp'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; + +/** + * An implementation of `IMainProcessService` that leverages MessagePorts. + */ +export class MessagePortMainProcessService implements IMainProcessService { + + declare readonly _serviceBrand: undefined; + + constructor( + private server: MessagePortServer, + private router: StaticRouter + ) { } + + getChannel(channelName: string): IChannel { + return this.server.getChannel(channelName, this.router); + } + + registerChannel(channelName: string, channel: IServerChannel): void { + this.server.registerChannel(channelName, channel); + } +} diff --git a/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts b/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts index 2f326523ce5..22e6149ee95 100644 --- a/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts +++ b/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts @@ -3,11 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IChannel, IServerChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; +import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; import { Client as IPCElectronClient } from 'vs/base/parts/ipc/electron-sandbox/ipc.electron'; import { Disposable } from 'vs/base/common/lifecycle'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { Server as MessagePortServer } from 'vs/base/parts/ipc/electron-sandbox/ipc.mp'; export const IMainProcessService = createDecorator('mainProcessService'); @@ -45,24 +44,3 @@ export class ElectronIPCMainProcessService extends Disposable implements IMainPr this.mainProcessConnection.registerChannel(channelName, channel); } } - -/** - * An implementation of `IMainProcessService` that leverages MessagePorts. - */ -export class MessagePortMainProcessService implements IMainProcessService { - - declare readonly _serviceBrand: undefined; - - constructor( - private server: MessagePortServer, - private router: StaticRouter - ) { } - - getChannel(channelName: string): IChannel { - return this.server.getChannel(channelName, this.router); - } - - registerChannel(channelName: string, channel: IServerChannel): void { - this.server.registerChannel(channelName, channel); - } -} diff --git a/src/vs/platform/ipc/electron-sandbox/sharedProcessService.ts b/src/vs/platform/ipc/electron-sandbox/sharedProcessService.ts index 60299f96efb..d3f157a5815 100644 --- a/src/vs/platform/ipc/electron-sandbox/sharedProcessService.ts +++ b/src/vs/platform/ipc/electron-sandbox/sharedProcessService.ts @@ -5,8 +5,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Event } from 'vs/base/common/event'; -import { IpcRendererEvent } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes'; -import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { ipcMessagePort } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { Client as MessagePortClient } from 'vs/base/parts/ipc/common/ipc.mp'; import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; @@ -45,13 +44,13 @@ export class SharedProcessService extends Disposable implements ISharedProcessSe // Ask to create message channel inside the window // and send over a UUID to correlate the response const nonce = generateUuid(); - ipcRenderer.send('vscode:createSharedProcessMessageChannel', nonce); + ipcMessagePort.connect('vscode:createSharedProcessMessageChannel', 'vscode:createSharedProcessMessageChannelResult', nonce); // Wait until the main side has returned the `MessagePort` // We need to filter by the `nonce` to ensure we listen // to the right response. - const onMessageChannelResult = Event.fromNodeEventEmitter<{ nonce: string, port: MessagePort }>(ipcRenderer, 'vscode:createSharedProcessMessageChannelResult', (e: IpcRendererEvent, nonce: string) => ({ nonce, port: e.ports[0] })); - const { port } = await Event.toPromise(Event.once(Event.filter(onMessageChannelResult, e => e.nonce === nonce))); + const onMessageChannelResult = Event.fromDOMEventEmitter<{ nonce: string, port: MessagePort, source: unknown }>(window, 'message', (e: MessageEvent) => ({ nonce: e.data, port: e.ports[0], source: e.source })); + const { port } = await Event.toPromise(Event.once(Event.filter(onMessageChannelResult, e => e.nonce === nonce && e.source === window))); this.logService.trace('Renderer->SharedProcess#connect: connection established'); diff --git a/src/vs/platform/native/electron-sandbox/nativeHostService.ts b/src/vs/platform/native/electron-sandbox/nativeHostService.ts index 2175c479423..cc52246b294 100644 --- a/src/vs/platform/native/electron-sandbox/nativeHostService.ts +++ b/src/vs/platform/native/electron-sandbox/nativeHostService.ts @@ -5,7 +5,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; // @ts-ignore: interface is implemented via proxy export class NativeHostService implements INativeHostService { @@ -16,7 +16,7 @@ export class NativeHostService implements INativeHostService { readonly windowId: number, @IMainProcessService mainProcessService: IMainProcessService ) { - return createChannelSender(mainProcessService.getChannel('nativeHost'), { + return ProxyChannel.toService(mainProcessService.getChannel('nativeHost'), { context: windowId, properties: (() => { const properties = new Map(); diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts similarity index 100% rename from src/vs/code/electron-main/sharedProcess.ts rename to src/vs/platform/sharedProcess/electron-main/sharedProcess.ts diff --git a/src/vs/platform/userDataSync/common/userDataSyncLog.ts b/src/vs/platform/userDataSync/common/userDataSyncLog.ts index aa32fef6b04..9eb9b4c7679 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncLog.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncLog.ts @@ -17,7 +17,7 @@ export class UserDataSyncLogService extends AbstractLogger implements IUserDataS @IEnvironmentService environmentService: IEnvironmentService ) { super(); - this.logger = this._register(loggerService.createLogger(environmentService.userDataSyncLogResource)); + this.logger = this._register(loggerService.createLogger(environmentService.userDataSyncLogResource, { name: 'settingssync' })); } trace(message: string, ...args: any[]): void { diff --git a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts index bb0aafe22ee..276b7492e63 100644 --- a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts +++ b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts @@ -9,6 +9,7 @@ import { bufferToStream, VSBufferReadableStream } from 'vs/base/common/buffer'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { FileAccess, Schemas } from 'vs/base/common/network'; +import { listenStream } from 'vs/base/common/stream'; import { URI } from 'vs/base/common/uri'; import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; import { ILogService } from 'vs/platform/log/common/log'; @@ -75,28 +76,27 @@ export class WebviewProtocolProvider extends Disposable { if (!this.listening) { this.listening = true; - // Data - stream.on('data', data => { - try { - if (!this.push(data.buffer)) { - stream.pause(); // pause the stream if we should not push anymore + listenStream(stream, { + onData: data => { + try { + if (!this.push(data.buffer)) { + stream.pause(); // pause the stream if we should not push anymore + } + } catch (error) { + this.emit(error); + } + }, + onError: error => { + this.emit('error', error); + }, + onEnd: () => { + try { + this.push(null); // signal EOS + } catch (error) { + this.emit(error); } - } catch (error) { - this.emit(error); } }); - - // End - stream.on('end', () => { - try { - this.push(null); // signal EOS - } catch (error) { - this.emit(error); - } - }); - - // Error - stream.on('error', error => this.emit('error', error)); } // ensure the stream is flowing @@ -168,7 +168,11 @@ export class WebviewProtocolProvider extends Disposable { rewriteUri = (uri) => { if (metadata.remoteConnectionData) { if (uri.scheme === Schemas.vscodeRemote || (metadata.extensionLocation?.scheme === Schemas.vscodeRemote)) { - return URI.parse(`http://${metadata.remoteConnectionData.host}:${metadata.remoteConnectionData.port}`).with({ + let host = metadata.remoteConnectionData.host; + if (host && host.indexOf(':') !== -1) { // IPv6 address + host = `[${host}]`; + } + return URI.parse(`http://${host}:${metadata.remoteConnectionData.port}`).with({ path: '/vscode-remote-resource', query: `tkn=${metadata.remoteConnectionData.connectionToken}&path=${encodeURIComponent(uri.path)}`, }); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/platform/windows/electron-main/window.ts similarity index 98% rename from src/vs/code/electron-main/window.ts rename to src/vs/platform/windows/electron-main/window.ts index 8ab193bff8e..7fc86f531bd 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/platform/windows/electron-main/window.ts @@ -19,7 +19,7 @@ import product from 'vs/platform/product/common/product'; import { WindowMinimumSize, IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { browserCodeLoadingCacheStrategy, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; -import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; +import { defaultWindowState, ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; @@ -44,14 +44,6 @@ export interface IWindowCreationOptions { isExtensionTestHost?: boolean; } -export const defaultWindowState = function (mode = WindowMode.Normal): IWindowState { - return { - width: 1024, - height: 768, - mode - }; -}; - interface ITouchBarSegment extends SegmentedControlSegment { id: string; } @@ -702,6 +694,15 @@ export class CodeWindow extends Disposable implements ICodeWindow { config.userEnv = { ...currentUserEnv, ...config.userEnv }; // still allow to override certain environment as passed in } + // If named pipe was instantiated for the crashpad_handler process, reuse the same + // pipe for new app instances connecting to the original app instance. + // Ref: https://github.com/microsoft/vscode/issues/115874 + if (process.env['CHROME_CRASHPAD_PIPE_NAME']) { + Object.assign(config.userEnv, { + CHROME_CRASHPAD_PIPE_NAME: process.env['CHROME_CRASHPAD_PIPE_NAME'] + }); + } + // If this is the first time the window is loaded, we associate the paths // directly with the window because we assume the loading will just work if (this._readyState === ReadyState.NONE) { diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index 8bd10465032..c309ff263f4 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -45,6 +45,14 @@ export interface IWindowState { display?: number; } +export const defaultWindowState = function (mode = WindowMode.Normal): IWindowState { + return { + width: 1024, + height: 768, + mode + }; +}; + export const enum WindowMode { Maximized, Normal, diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index eebedf00688..c7625528cf4 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -12,7 +12,7 @@ import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { IStateService } from 'vs/platform/state/node/state'; -import { CodeWindow } from 'vs/code/electron-main/window'; +import { CodeWindow } from 'vs/platform/windows/electron-main/window'; import { BrowserWindow, MessageBoxOptions, WebContents } from 'electron'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; diff --git a/src/vs/platform/windows/electron-main/windowsStateHandler.ts b/src/vs/platform/windows/electron-main/windowsStateHandler.ts index 9b9558fa964..b0e50c85ff4 100644 --- a/src/vs/platform/windows/electron-main/windowsStateHandler.ts +++ b/src/vs/platform/windows/electron-main/windowsStateHandler.ts @@ -8,13 +8,12 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { isMacintosh } from 'vs/base/common/platform'; import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; -import { defaultWindowState } from 'vs/code/electron-main/window'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/node/state'; import { INativeWindowConfiguration, IWindowSettings } from 'vs/platform/windows/common/windows'; -import { ICodeWindow, IWindowsMainService, IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows'; +import { defaultWindowState, ICodeWindow, IWindowsMainService, IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; export interface IWindowState { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 8ef37f497aa..c4ba736b627 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2077,10 +2077,12 @@ declare module 'vscode' { export function registerTestProvider(testProvider: TestProvider): Disposable; /** - * Runs tests with the given options. If no options are given, then - * all tests are run. Returns the resulting test run. + * Runs tests. The "run" contains the list of tests to run as well as a + * method that can be used to update their state. At the point in time + * that "run" is called, all tests given in the run have their state + * automatically set to {@link TestRunState.Queued}. */ - export function runTests(options: TestRunOptions, cancellationToken?: CancellationToken): Thenable; + export function runTests(run: TestRunOptions, cancellationToken?: CancellationToken): Thenable; /** * Returns an observer that retrieves tests in the given workspace folder. @@ -2194,6 +2196,14 @@ declare module 'vscode' { */ readonly discoveredInitialTests?: Thenable; + /** + * An event that fires when a test becomes outdated, as a result of + * file changes, for example. In "watch" mode, tests that are outdated + * will be automatically re-run after a short delay. Firing a test + * with children will mark the entire subtree as outdated. + */ + readonly onDidInvalidateTest?: Event; + /** * Dispose will be called when there are no longer observers interested * in the hierarchy. @@ -2238,11 +2248,11 @@ declare module 'vscode' { * @todo this will eventually need to be able to return a summary report, coverage for example. */ // eslint-disable-next-line vscode-dts-provider-naming - runTests?(options: TestRunOptions, cancellationToken: CancellationToken): ProviderResult; + runTests?(options: TestRun, cancellationToken: CancellationToken): ProviderResult; } /** - * Options given to `TestProvider.runTests` + * Options given to {@link test.runTests} */ export interface TestRunOptions { /** @@ -2257,6 +2267,17 @@ declare module 'vscode' { debug: boolean; } + /** + * Options given to `TestProvider.runTests` + */ + export interface TestRun extends TestRunOptions { + /** + * Updates the state of the test in the run. By default, all tests involved + * in the run will have a "queued" state until they are updated by this method. + */ + setState(test: T, state: TestState): void; + } + /** * A test item is an item shown in the "test explorer" view. It encompasses * both a suite and a test, since they have almost or identical capabilities. @@ -2305,12 +2326,6 @@ declare module 'vscode' { * Optional list of nested tests for this item. */ children?: TestItem[]; - - /** - * Test run state. Will generally be {@link TestRunState.Unset} by - * default. - */ - state: TestState; } /** @@ -2345,11 +2360,11 @@ declare module 'vscode' { * in order to update it. This allows consumers to quickly and easily check * for changes via object identity. */ - export class TestState { + export interface TestState { /** * Current state of the test. */ - readonly runState: TestRunState; + readonly state: TestRunState; /** * Optional duration of the test run, in milliseconds. @@ -2360,14 +2375,7 @@ declare module 'vscode' { * Associated test run message. Can, for example, contain assertion * failure information if the test fails. */ - readonly messages: ReadonlyArray>; - - /** - * @param state Run state to hold in the test state - * @param messages List of associated messages for the test - * @param duration Length of time the test run took, if appropriate. - */ - constructor(runState: TestRunState, messages?: TestMessage[], duration?: number); + readonly messages?: ReadonlyArray>; } /** diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index 4ed2572a8f7..f6286c8656d 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -214,13 +214,6 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu $logout(providerId: string, sessionId: string): Promise { return this.authenticationService.logout(providerId, sessionId); } - - private isAccessAllowed(providerId: string, accountName: string, extensionId: string): boolean { - const allowList = readAllowedExtensions(this.storageService, providerId, accountName); - const extensionData = allowList.find(extension => extension.id === extensionId); - return !!extensionData; - } - private async loginPrompt(providerName: string, extensionName: string): Promise { const { choice } = await this.dialogService.show( Severity.Info, @@ -257,10 +250,15 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu if (existingSessionPreference) { const matchingSession = potentialSessions.find(session => session.id === existingSessionPreference); if (matchingSession) { - const allowed = await this.authenticationService.showGetSessionPrompt(providerId, matchingSession.account.label, extensionId, extensionName); - if (allowed) { - return matchingSession; + const allowed = this.authenticationService.isAccessAllowed(providerId, matchingSession.account.label, extensionId); + if (!allowed) { + const didAcceptPrompt = await this.authenticationService.showGetSessionPrompt(providerId, matchingSession.account.label, extensionId, extensionName); + if (!didAcceptPrompt) { + throw new Error('User did not consent to login.'); + } } + + return matchingSession; } } } @@ -270,14 +268,14 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu async $getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: { createIfNone: boolean, clearSessionPreference: boolean }): Promise { const orderedScopes = scopes.sort().join(' '); - const sessions = (await this.authenticationService.getSessions(providerId)).filter(session => session.scopes.slice().sort().join(' ') === orderedScopes); + const sessions = (await this.authenticationService.getSessions(providerId, true)).filter(session => session.scopes.slice().sort().join(' ') === orderedScopes); const silent = !options.createIfNone; let session: modes.AuthenticationSession | undefined; if (sessions.length) { if (!this.authenticationService.supportsMultipleAccounts(providerId)) { session = sessions[0]; - const allowed = this.isAccessAllowed(providerId, session.account.label, extensionId); + const allowed = this.authenticationService.isAccessAllowed(providerId, session.account.label, extensionId); if (!allowed) { if (!silent) { const didAcceptPrompt = await this.authenticationService.showGetSessionPrompt(providerId, session.account.label, extensionId, extensionName); @@ -302,7 +300,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu throw new Error('User did not consent to login.'); } - session = await this.authenticationService.login(providerId, scopes); + session = await this.authenticationService.login(providerId, scopes, true); await this.setTrustedExtensionAndAccountPreference(providerId, session.account.label, extensionId, extensionName, session.id); } else { await this.authenticationService.requestNewSession(providerId, scopes, extensionId, extensionName); diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index c03943332e4..2b11030f2e0 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -129,13 +129,13 @@ export class MainThreadFileSystemEventService { } } else { if (operation === FileOperation.CREATE) { - message = localize('ask.N.create', "{0} extensions want to make refactoring changes with this file creation", data.extensionNames.length); + message = localize({ key: 'ask.N.create', comment: ['{0} is a number, e.g "3 extensions want..."'] }, "{0} extensions want to make refactoring changes with this file creation", data.extensionNames.length); } else if (operation === FileOperation.COPY) { - message = localize('ask.N.copy', "{0} extensions want to make refactoring changes with this file copy", data.extensionNames.length); + message = localize({ key: 'ask.N.copy', comment: ['{0} is a number, e.g "3 extensions want..."'] }, "{0} extensions want to make refactoring changes with this file copy", data.extensionNames.length); } else if (operation === FileOperation.MOVE) { - message = localize('ask.N.move', "{0} extensions want to make refactoring changes with this file move", data.extensionNames.length); + message = localize({ key: 'ask.N.move', comment: ['{0} is a number, e.g "3 extensions want..."'] }, "{0} extensions want to make refactoring changes with this file move", data.extensionNames.length); } else /* if (operation === FileOperation.DELETE) */ { - message = localize('ask.N.delete', "{0} extensions want to make refactoring changes with this file deletion", data.extensionNames.length); + message = localize({ key: 'ask.N.delete', comment: ['{0} is a number, e.g "3 extensions want..."'] }, "{0} extensions want to make refactoring changes with this file deletion", data.extensionNames.length); } } diff --git a/src/vs/workbench/api/browser/mainThreadTesting.ts b/src/vs/workbench/api/browser/mainThreadTesting.ts index 370f08df900..3b127f10a79 100644 --- a/src/vs/workbench/api/browser/mainThreadTesting.ts +++ b/src/vs/workbench/api/browser/mainThreadTesting.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { CancellationToken } from 'vs/base/common/cancellation'; -import { Disposable, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; -import { getTestSubscriptionKey, RunTestsRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; -import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; +import { getTestSubscriptionKey, ITestState, RunTestsRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestResultService, LiveTestResult } from 'vs/workbench/contrib/testing/common/testResultService'; import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; import { ExtHostContext, ExtHostTestingResource, ExtHostTestingShape, IExtHostContext, MainContext, MainThreadTestingShape } from '../common/extHost.protocol'; @@ -19,12 +19,6 @@ const reviveDiff = (diff: TestsDiff) => { if (item.item.location) { item.item.location.uri = URI.revive(item.item.location.uri); } - - for (const message of item.item.state.messages) { - if (message.location) { - message.location.uri = URI.revive(message.location.uri); - } - } } } }; @@ -37,30 +31,42 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh constructor( extHostContext: IExtHostContext, @ITestService private readonly testService: ITestService, - @ITestResultService resultService: ITestResultService, + @ITestResultService private readonly resultService: ITestResultService, ) { super(); this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostTesting); this._register(this.testService.onShouldSubscribe(args => this.proxy.$subscribeToTests(args.resource, args.uri))); this._register(this.testService.onShouldUnsubscribe(args => this.proxy.$unsubscribeFromTests(args.resource, args.uri))); - const testCompleteListener = this._register(new MutableDisposable()); - this._register(resultService.onNewTestResult(results => { - testCompleteListener.value = results.onComplete(() => this.proxy.$publishTestResults({ tests: results.tests })); - })); + // const testCompleteListener = this._register(new MutableDisposable()); + // todo(@connor4312): reimplement, maybe + // this._register(resultService.onResultsChanged(results => { + // testCompleteListener.value = results.onComplete(() => this.proxy.$publishTestResults({ tests: [] })); + // })); testService.updateRootProviderCount(1); - const lastCompleted = resultService.results.find(r => !r.isComplete); - if (lastCompleted) { - this.proxy.$publishTestResults({ tests: lastCompleted.tests }); - } - for (const { resource, uri } of this.testService.subscriptions) { this.proxy.$subscribeToTests(resource, uri); } } + /** + * @inheritdoc + */ + $updateTestStateInRun(runId: string, testId: string, state: ITestState): void { + const r = this.resultService.getResult(runId); + if (r && r instanceof LiveTestResult) { + for (const message of state.messages) { + if (message.location) { + message.location.uri = URI.revive(message.location.uri); + } + } + + r.updateState(testId, state); + } + } + /** * @inheritdoc */ @@ -105,8 +111,9 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh this.testService.publishDiff(resource, URI.revive(uri), diff); } - public $runTests(req: RunTestsRequest, token: CancellationToken): Promise { - return this.testService.runTests(req, token); + public async $runTests(req: RunTestsRequest, token: CancellationToken): Promise { + const result = await this.testService.runTests(req, token); + return result.id; } public dispose() { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 2372d159941..3b658592ed8 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1297,10 +1297,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I // checkProposedApiEnabled(extension); return extHostTypes.TestMessageSeverity; }, - get TestState() { - // checkProposedApiEnabled(extension); - return extHostTypes.TestState; - }, get WorkspaceTrustState() { // checkProposedApiEnabled(extension); return extHostTypes.WorkspaceTrustState; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 8e417d49e59..d3d2e2a7d8b 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -58,7 +58,7 @@ import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib import { DebugConfigurationProviderTriggerKind, WorkspaceTrustState } from 'vs/workbench/api/common/extHostTypes'; import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; import { IExtensionIdWithVersion } from 'vs/platform/userDataSync/common/extensionsStorageSync'; -import { InternalTestItem, InternalTestResults, RunTestForProviderRequest, RunTestsRequest, RunTestsResult, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { InternalTestItem, InternalTestResults, ITestState, RunTestForProviderRequest, RunTestsRequest, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { WorkspaceTrustStateChangeEvent } from 'vs/platform/workspace/common/workspaceTrust'; @@ -1826,7 +1826,7 @@ export const enum ExtHostTestingResource { } export interface ExtHostTestingShape { - $runTestsForProvider(req: RunTestForProviderRequest, token: CancellationToken): Promise; + $runTestsForProvider(req: RunTestForProviderRequest, token: CancellationToken): Promise; $subscribeToTests(resource: ExtHostTestingResource, uri: UriComponents): void; $unsubscribeFromTests(resource: ExtHostTestingResource, uri: UriComponents): void; $lookupTest(test: TestIdWithProvider): Promise; @@ -1840,7 +1840,8 @@ export interface MainThreadTestingShape { $subscribeToDiffs(resource: ExtHostTestingResource, uri: UriComponents): void; $unsubscribeFromDiffs(resource: ExtHostTestingResource, uri: UriComponents): void; $publishDiff(resource: ExtHostTestingResource, uri: UriComponents, diff: TestsDiff): void; - $runTests(req: RunTestsRequest, token: CancellationToken): Promise; + $updateTestStateInRun(runId: string, testId: string, state: ITestState): void; + $runTests(req: RunTestsRequest, token: CancellationToken): Promise; } // --- proxy identifiers diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts index fb30845668e..bab357e0043 100644 --- a/src/vs/workbench/api/common/extHostTesting.ts +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -16,11 +16,11 @@ import { ExtHostTestingResource, ExtHostTestingShape, MainContext, MainThreadTes import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData'; import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; -import { TestItem } from 'vs/workbench/api/common/extHostTypeConverters'; +import { TestItem, TestState } from 'vs/workbench/api/common/extHostTypeConverters'; import { Disposable } from 'vs/workbench/api/common/extHostTypes'; import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { OwnedTestCollection, SingleUseTestCollection } from 'vs/workbench/contrib/testing/common/ownedTestCollection'; -import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, InternalTestItemWithChildren, InternalTestResults, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { AbstractIncrementalTestCollection, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, InternalTestItemWithChildren, InternalTestResults, RunTestForProviderRequest, TestDiffOpType, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import type * as vscode from 'vscode'; const getTestSubscriptionKey = (resource: ExtHostTestingResource, uri: URI) => `${resource}:${uri.toString()}`; @@ -93,9 +93,7 @@ export class ExtHostTesting implements ExtHostTestingShape { // Find workspace items first, then owned tests, then document tests. // If a test instance exists in both the workspace and document, prefer // the workspace because it's less ephemeral. - .map(test => this.workspaceObservers.getMirroredTestDataByReference(test) - ?? mapFind(this.testSubscriptions.values(), c => c.collection.getTestByReference(test)) - ?? this.textDocumentObservers.getMirroredTestDataByReference(test)) + .map(this.getInternalTestForReference, this) .filter(isDefined) .map(item => ({ providerId: item.providerId, testId: item.id })), debug: req.debug @@ -219,10 +217,10 @@ export class ExtHostTesting implements ExtHostTestingShape { * providers to be run. * @override */ - public async $runTestsForProvider(req: RunTestForProviderRequest, cancellation: CancellationToken): Promise { + public async $runTestsForProvider(req: RunTestForProviderRequest, cancellation: CancellationToken): Promise { const provider = this.providers.get(req.providerId); if (!provider || !provider.runTests) { - return EMPTY_TEST_RESULT; + return; } const tests = req.ids.map(id => this.ownedTests.getTestById(id)?.actual) @@ -230,16 +228,25 @@ export class ExtHostTesting implements ExtHostTestingShape { // Only send the actual TestItem's to the user to run. .map(t => t instanceof TestItemFilteredWrapper ? t.actual : t); if (!tests.length) { - return EMPTY_TEST_RESULT; + return; } try { - await provider.runTests({ tests, debug: req.debug }, cancellation); + await provider.runTests({ + setState: (test, state) => { + const internal = this.getInternalTestForReference(test); + if (internal) { + this.flushCollectionDiffs(); + this.proxy.$updateTestStateInRun(req.runId, internal.id, TestState.from(state)); + } + }, tests, debug: req.debug + }, cancellation); + for (const { collection } of this.testSubscriptions.values()) { collection.flushDiff(); // ensure all states are updated } - return EMPTY_TEST_RESULT; + return; } catch (e) { console.error(e); // so it appears to attached debuggers throw e; @@ -256,6 +263,28 @@ export class ExtHostTesting implements ExtHostTestingShape { return Promise.resolve(item); } + /** + * Flushes diff information for all collections to ensure state in the + * main thread is updated. + */ + private flushCollectionDiffs() { + for (const { collection } of this.testSubscriptions.values()) { + collection.flushDiff(); + } + } + + /** + * Gets the internal test item associated with the reference from the extension. + */ + private getInternalTestForReference(test: vscode.TestItem) { + // Find workspace items first, then owned tests, then document tests. + // If a test instance exists in both the workspace and document, prefer + // the workspace because it's less ephemeral. + return this.workspaceObservers.getMirroredTestDataByReference(test) + ?? mapFind(this.testSubscriptions.values(), c => c.collection.getTestByReference(test)) + ?? this.textDocumentObservers.getMirroredTestDataByReference(test); + } + private createDefaultDocumentTestHierarchy(provider: vscode.TestProvider, document: vscode.TextDocument, folder: vscode.WorkspaceFolder | undefined): vscode.TestHierarchy | undefined { if (!folder) { return; @@ -361,10 +390,6 @@ export class TestItemFilteredWrapper implements vscode.TestItem { return this.actual.runnable; } - public get state() { - return this.actual.state; - } - public get children() { // We only want children that match the filter. return this.getWrappedChildren().filter(child => child.hasNodeMatchingFilter); @@ -645,7 +670,6 @@ class TestItemFromMirror implements vscode.RequiredTestItem { public get id() { return this.#internal.revived.id!; } public get label() { return this.#internal.revived.label; } public get description() { return this.#internal.revived.description; } - public get state() { return this.#internal.revived.state; } public get location() { return this.#internal.revived.location; } public get runnable() { return this.#internal.revived.runnable ?? true; } public get debuggable() { return this.#internal.revived.debuggable ?? false; } @@ -665,7 +689,6 @@ class TestItemFromMirror implements vscode.RequiredTestItem { id: this.id, label: this.label, description: this.description, - state: this.state, location: this.location, runnable: this.runnable, debuggable: this.debuggable, diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index e4b69b8cc48..5f211700488 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1478,22 +1478,22 @@ export namespace NotebookDecorationRenderOptions { export namespace TestState { export function from(item: vscode.TestState): ITestState { return { - runState: item.runState, + state: item.state, duration: item.duration, - messages: item.messages.map(message => ({ + messages: item.messages?.map(message => ({ message: MarkdownString.fromStrict(message.message) || '', severity: message.severity, expectedOutput: message.expectedOutput, actualOutput: message.actualOutput, location: message.location ? location.from(message.location) : undefined, - })), + })) ?? [], }; } export function to(item: ITestState): vscode.TestState { - return new types.TestState( - item.runState, - item.messages.map(message => ({ + return { + state: item.state, + messages: item.messages.map(message => ({ message: typeof message.message === 'string' ? message.message : MarkdownString.to(message.message), severity: message.severity, expectedOutput: message.expectedOutput, @@ -1503,8 +1503,8 @@ export namespace TestState { uri: URI.revive(message.location.uri) }), })), - item.duration, - ); + duration: item.duration, + }; } } @@ -1518,7 +1518,6 @@ export namespace TestItem { debuggable: item.debuggable ?? false, description: item.description, runnable: item.runnable ?? true, - state: TestState.from(item.state), }; } @@ -1533,7 +1532,6 @@ export namespace TestItem { debuggable: item.debuggable, description: item.description, runnable: item.runnable, - state: TestState.to(item.state), }; } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 91bbb75fd61..45c8dfe60de 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2849,6 +2849,33 @@ export enum ColorThemeKind { //#region Notebook +export class NotebookCellMetadata { + + readonly readonly: boolean; + readonly inputCollapsed: boolean; + readonly outputCollapsed: boolean; + + [key: string]: unknown; + + constructor(readonly: boolean, inputCollapsed: boolean, outputCollapsed: boolean) { + this.readonly = readonly; + this.inputCollapsed = inputCollapsed; + this.outputCollapsed = outputCollapsed; + } + + with(change: Partial<{ readonly: boolean, inputCollapsed: boolean, outputCollapsed: boolean, [key: string]: unknown }>): NotebookCellMetadata { + const thisAndChange = { ...this, ...change }; + const res = new NotebookCellMetadata(thisAndChange.readonly, thisAndChange.inputCollapsed, thisAndChange.outputCollapsed); + for (const key in change) { + if (Object.prototype.hasOwnProperty.call(change, key)) { + res[key] = change[key]; + } + } + return res; + } +} + + export class NotebookCellOutputItem { static isNotebookCellOutputItem(obj: unknown): obj is vscode.NotebookCellOutputItem { @@ -3018,31 +3045,6 @@ export enum TestMessageSeverity { Hint = 3 } -@es5ClassCompat -export class TestState { - #runState: TestRunState; - #duration?: number; - #messages: ReadonlyArray>; - - public get runState() { - return this.#runState; - } - - public get duration() { - return this.#duration; - } - - public get messages() { - return this.#messages; - } - - constructor(runState: TestRunState, messages: vscode.TestMessage[] = [], duration?: number) { - this.#runState = runState; - this.#messages = Object.freeze(messages.map(m => Object.freeze(m))); - this.#duration = duration; - } -} - export type RequiredTestItem = vscode.RequiredTestItem; export type TestItem = vscode.TestItem; diff --git a/src/vs/workbench/api/common/menusExtensionPoint.ts b/src/vs/workbench/api/common/menusExtensionPoint.ts index 078eff7442f..6360dadf550 100644 --- a/src/vs/workbench/api/common/menusExtensionPoint.ts +++ b/src/vs/workbench/api/common/menusExtensionPoint.ts @@ -182,6 +182,11 @@ const apiMenus: IAPIMenu[] = [ id: MenuId.TimelineItemContext, description: localize('view.timelineContext', "The Timeline view item context menu") }, + { + key: 'ports/item/context', + id: MenuId.TunnelContext, + description: localize('view.tunnelContext', "The Ports view item context menu") + } ]; namespace schema { diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts index f9ac315fd33..4364969d2bd 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts @@ -104,7 +104,7 @@ export class BreadcrumbsModel { } const breadcrumbsElements = this._currentOutline.value.config.breadcrumbsDataSource.getBreadcrumbElements(); - for (let i = this._cfgSymbolPath.getValue() === 'last' ? breadcrumbsElements.length - 1 : 0; i < breadcrumbsElements.length; i++) { + for (let i = this._cfgSymbolPath.getValue() === 'last' && breadcrumbsElements.length > 0 ? breadcrumbsElements.length - 1 : 0; i < breadcrumbsElements.length; i++) { result.push(new OutlineElement2(breadcrumbsElements[i], this._currentOutline.value)); } diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 030e3bdcc11..003527d67e0 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -469,7 +469,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands. MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All") }, group: '5_close', order: 10 }); MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: nls.localize('closeAllSaved', "Close Saved") }, group: '5_close', order: 20 }); MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.TOGGLE_KEEP_EDITORS_COMMAND_ID, title: nls.localize('toggleKeepEditors', "Keep Editors Open"), toggled: ContextKeyExpr.not('config.workbench.editor.enablePreview') }, group: '7_settings', order: 10 }); -MenuRegistry.appendMenuItem(MenuId.EditorTitle, { submenu: MenuId.EditorTitleRun, title: { value: nls.localize('run', "Run"), original: 'Run', }, icon: Codicon.run, group: 'navigation' }); +MenuRegistry.appendMenuItem(MenuId.EditorTitle, { submenu: MenuId.EditorTitleRun, title: { value: nls.localize('run', "Run"), original: 'Run', }, icon: Codicon.run, group: 'navigation', order: -1 }); interface IEditorToolItem { id: string; title: string; icon?: { dark?: URI; light?: URI; } | ThemeIcon; } diff --git a/src/vs/workbench/browser/parts/views/media/views.css b/src/vs/workbench/browser/parts/views/media/views.css index 48ceb904d51..2d5807d00b5 100644 --- a/src/vs/workbench/browser/parts/views/media/views.css +++ b/src/vs/workbench/browser/parts/views/media/views.css @@ -64,13 +64,7 @@ } .monaco-workbench .pane > .pane-body > .welcome-view .monaco-button { - margin-left: auto; - margin-right: auto; -} - -.monaco-workbench .pane > .pane-body.wide > .welcome-view .monaco-button { - margin-left: inherit; - max-width: 260px; + max-width: 300px; } .monaco-workbench .pane > .pane-body .welcome-view-content { diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts index efcdd8981df..8c4bd5e0a68 100644 --- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts +++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts @@ -9,7 +9,7 @@ import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchCo import { Disposable } from 'vs/base/common/lifecycle'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { IDisplayMainService } from 'vs/platform/display/common/displayMainService'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { clearAllFontInfos } from 'vs/editor/browser/config/configuration'; class DisplayChangeRemeasureFonts extends Disposable implements IWorkbenchContribution { @@ -18,7 +18,7 @@ class DisplayChangeRemeasureFonts extends Disposable implements IWorkbenchContri @IMainProcessService mainProcessService: IMainProcessService ) { super(); - const displayMainService = createChannelSender(mainProcessService.getChannel('display')); + const displayMainService = ProxyChannel.toService(mainProcessService.getChannel('display')); displayMainService.onDidDisplayChanged(() => { clearAllFontInfos(); }); diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index c381002d67f..46cd8f54f9d 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -76,7 +76,6 @@ function revealLastElement(tree: WorkbenchAsyncDataTree) { const sessionsToIgnore = new Set(); const identityProvider = { getId: (element: IReplElement) => element.getId() }; -const diffIdentityProvider = { getId: (element: IReplElement) => element.getId() + element.toString() }; export class Repl extends ViewPane implements IHistoryNavigationWidget { declare readonly _serviceBrand: undefined; @@ -513,7 +512,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { } const lastElementVisible = this.tree.scrollTop + this.tree.renderHeight >= this.tree.scrollHeight; - await this.tree.updateChildren(undefined, true, false, { diffIdentityProvider }); + await this.tree.updateChildren(undefined, true, false, { diffIdentityProvider: identityProvider }); const session = this.tree.getInput(); if (session) { diff --git a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts index dad39a583d7..026c2f48422 100644 --- a/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts +++ b/src/vs/workbench/contrib/debug/common/debugProtocol.d.ts @@ -704,6 +704,7 @@ declare module DebugProtocol { The request configures the debuggers response to thrown exceptions. If an exception is configured to break, a 'stopped' event is fired (with reason 'exception'). Clients should only call this request if the capability 'exceptionBreakpointFilters' returns one or more filters. + If a filter or filter option is invalid (e.g. due to an invalid 'condition'), the request should fail with an 'ErrorResponse' explaining the problem(s). */ export interface SetExceptionBreakpointsRequest extends Request { // command: 'setExceptionBreakpoints'; @@ -1629,10 +1630,14 @@ declare module DebugProtocol { filter: string; /** The name of the filter option. This will be shown in the UI. */ label: string; + /** An optional help text providing additional information about the exception filter. This string is typically shown as a hover and must be translated. */ + description?: string; /** Initial value of the filter option. If not specified a value 'false' is assumed. */ default?: boolean; /** Controls whether a condition can be specified for this filter option. If false or missing, a condition can not be set. */ supportsCondition?: boolean; + /** An optional help text providing information about the condition. This string is shown as the placeholder text for a text box and must be translated. */ + conditionDescription?: string; } /** A structured message object. Used to return errors from requests. */ @@ -1774,6 +1779,8 @@ declare module DebugProtocol { endLine?: number; /** An optional end column of the range covered by the stack frame. */ endColumn?: number; + /** Indicates whether this frame can be restarted with the 'restart' request. Clients should only use this if the debug adapter supports the 'restart' request (capability 'supportsRestartRequest' is true). */ + canRestart?: boolean; /** Optional memory reference for the current instruction pointer in this frame. */ instructionPointerReference?: string; /** The module associated with this frame, if any. */ diff --git a/src/vs/workbench/contrib/debug/common/replModel.ts b/src/vs/workbench/contrib/debug/common/replModel.ts index a4a20e491af..cb0918d67ad 100644 --- a/src/vs/workbench/contrib/debug/common/replModel.ts +++ b/src/vs/workbench/contrib/debug/common/replModel.ts @@ -16,6 +16,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur const MAX_REPL_LENGTH = 10000; let topReplElementCounter = 0; +const getUniqueId = () => `topReplElement:${topReplElementCounter++}`; export class SimpleReplElement implements IReplElement { @@ -234,13 +235,14 @@ export class ReplModel { return; } if (!previousElement.value.endsWith('\n') && !previousElement.value.endsWith('\r\n') && previousElement.count === 1) { - previousElement.value += data; + this.replElements[this.replElements.length - 1] = new SimpleReplElement( + session, getUniqueId(), previousElement.value + data, sev, source); this._onDidChangeElements.fire(); return; } } - const element = new SimpleReplElement(session, `topReplElement:${topReplElementCounter++}`, data, sev, source); + const element = new SimpleReplElement(session, getUniqueId(), data, sev, source); this.addReplElement(element); } else { // TODO@Isidor hack, we should introduce a new type which is an output that can fetch children like an expression @@ -315,7 +317,7 @@ export class ReplModel { } // show object - this.appendToRepl(session, new RawObjectReplElement(`topReplElement:${topReplElementCounter++}`, (a).prototype, a, undefined, nls.localize('snapshotObj', "Only primitive values are shown for this object.")), sev, source); + this.appendToRepl(session, new RawObjectReplElement(getUniqueId(), (a).prototype, a, undefined, nls.localize('snapshotObj', "Only primitive values are shown for this object.")), sev, source); } // string: watch out for % replacement directive diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 5e3d9d5ebba..6868dfacdaf 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -2193,7 +2193,7 @@ export class SystemDisabledWarningAction extends ExtensionAction { } if (this.workspaceTrustService.isWorkspaceTrustEnabled() && this.extension.enablementState === EnablementState.DisabledByTrustRequirement) { this.class = `${SystemDisabledWarningAction.TRUST_CLASS}`; - this.tooltip = localize('extension disabled because of trust requirement', "This extension has been disabled as it requires a trusted workspace"); + this.tooltip = localize('extension disabled because of trust requirement', "This extension has been disabled because the current workspace is not trusted"); return; } } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts b/src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts index f096881c6a4..e7aa4578c3d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsIcons.ts @@ -31,4 +31,5 @@ export const starEmptyIcon = registerIcon('extensions-star-empty', Codicon.starE export const warningIcon = registerIcon('extensions-warning-message', Codicon.warning, localize('warningIcon', 'Icon shown with a warning message in the extensions editor.')); export const infoIcon = registerIcon('extensions-info-message', Codicon.info, localize('infoIcon', 'Icon shown with an info message in the extensions editor.')); -export const trustIcon = registerIcon('extension-trust-message', Codicon.shield, localize('trustIcon', 'Icon shown with a message in the extension editor.')); + +export const trustIcon = registerIcon('extension-workspace-trust', Codicon.shield, localize('trustIcon', 'Icon shown with a workspace trust message in the extension editor.')); diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css b/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css index 737320d942c..f4b5009eefc 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css @@ -34,6 +34,9 @@ } .extension-install-count .codicon, +.extension-action.codicon-extensions-info-message, +.extension-action.codicon-extensions-warning-message, +.extension-action.codicon-extension-workspace-trust, .extension-action.codicon-extensions-manage { color: inherit; } diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index d8289ff2b9a..61b0b7f33f9 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -53,6 +53,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService'; import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +import { listenStream } from 'vs/base/common/stream'; export const NEW_FILE_COMMAND_ID = 'explorer.newFile'; export const NEW_FILE_LABEL = nls.localize('newFile', "New File"); @@ -1034,22 +1035,22 @@ const downloadFileHandler = async (accessor: ServicesAccessor) => { reject(); })); - sourceStream.on('data', data => { - if (!disposed) { - target.write(data.buffer); - reportProgress(contents.name, contents.size, data.byteLength, operation); + listenStream(sourceStream, { + onData: data => { + if (!disposed) { + target.write(data.buffer); + reportProgress(contents.name, contents.size, data.byteLength, operation); + } + }, + onError: error => { + disposables.dispose(); + reject(error); + }, + onEnd: () => { + disposables.dispose(); + resolve(); } }); - - sourceStream.on('error', error => { - disposables.dispose(); - reject(error); - }); - - sourceStream.on('end', () => { - disposables.dispose(); - resolve(); - }); }); } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 9fb71481155..304e86c73c6 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -1624,7 +1624,10 @@ export class ChangeCellLanguageAction extends NotebookCellAction { const modelService = accessor.get(IModelService); const quickInputService = accessor.get(IQuickInputService); - const providerLanguages = [...context.notebookEditor.viewModel.notebookDocument.resolvedLanguages, 'markdown']; + const providerLanguages = [ + ...(context.notebookEditor.activeKernel?.supportedLanguages ?? context.notebookEditor.viewModel.notebookDocument.resolvedLanguages), + 'markdown' + ]; providerLanguages.forEach(languageId => { let description: string; if (context.cell.cellKind === CellKind.Markdown ? (languageId === 'markdown') : (languageId === context.cell.language)) { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts index d3bc0b2ab9b..2858f29bf52 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts @@ -91,8 +91,8 @@ registerAction2(class extends Action2 { ) : undefined; if (selectedKernel) { - editor.activeKernel = selectedKernel!; - return selectedKernel!.resolve(editor.uri!, editor.getId(), tokenSource.token); + editor.activeKernel = selectedKernel; + return selectedKernel.resolve(editor.uri!, editor.getId(), tokenSource.token); } else { picker.show(); } @@ -224,4 +224,3 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { } Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(KernelStatus, LifecyclePhase.Ready); - diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 27a85a990a8..628eecf0cdb 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1470,6 +1470,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const nextIndex = ui ? this.viewModel.getNextVisibleCellIndex(index) : index + 1; let language; if (type === CellKind.Code) { + const supportedLanguages = this._activeKernel?.supportedLanguages ?? this.viewModel.notebookDocument.resolvedLanguages; + const defaultLanguage = supportedLanguages[0] || 'plaintext'; if (cell?.cellKind === CellKind.Code) { language = cell.language; } else if (cell?.cellKind === CellKind.Markdown) { @@ -1477,20 +1479,20 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor if (nearestCodeCellIndex > -1) { language = this.viewModel.viewCells[nearestCodeCellIndex].language; } else { - language = this.viewModel.resolvedLanguages[0] || 'plaintext'; + language = defaultLanguage; } } else { if (cell === undefined && direction === 'above') { // insert cell at the very top - language = this.viewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || this.viewModel.resolvedLanguages[0] || 'plaintext'; + language = this.viewModel.viewCells.find(cell => cell.cellKind === CellKind.Code)?.language || defaultLanguage; } else { - language = this.viewModel.resolvedLanguages[0] || 'plaintext'; + language = defaultLanguage; } } - if (this.viewModel.resolvedLanguages.indexOf(language) < 0) { + if (!supportedLanguages.includes(language)) { // the language no longer exists - language = this.viewModel.resolvedLanguages[0] || 'plaintext'; + language = defaultLanguage; } } else { language = 'markdown'; @@ -1500,8 +1502,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor (direction === 'above' ? index : nextIndex) : index; const focused = this._list.getFocusedElements(); - const newCell = this.viewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); - return newCell as CellViewModel; + return this.viewModel.createCell(insertIndex, initialText, language, type, undefined, [], true, undefined, focused); } async splitNotebookCell(cell: ICellViewModel): Promise { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 228fde919bc..6da32d01e45 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -40,13 +40,9 @@ import { ICustomEditorInfo, ICustomEditorViewTypesHandler, IEditorService } from import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -export class NotebookKernelProviderInfoStore extends Disposable { +export class NotebookKernelProviderInfoStore { private readonly _notebookKernelProviders: INotebookKernelProvider[] = []; - constructor() { - super(); - } - add(provider: INotebookKernelProvider) { this._notebookKernelProviders.push(provider); this._updateProviderExtensionsInfo(); @@ -66,7 +62,7 @@ export class NotebookKernelProviderInfoStore extends Disposable { } getContributedKernelProviders() { - return [...this._notebookKernelProviders.values()]; + return [...this._notebookKernelProviders]; } private _updateProviderExtensionsInfo() { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index feb58e89952..dc191b89763 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -168,10 +168,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD return this._notebook; } - get resolvedLanguages() { - return this._notebook.resolvedLanguages; - } - get uri() { return this._notebook.uri; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index d725acb1061..7df3a0a8b0f 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -189,6 +189,8 @@ export interface INotebookTextModel { metadata: NotebookDocumentMetadata readonly uri: URI; readonly versionId: number; + + /** @deprecated */ languages: string[]; readonly cells: readonly ICell[]; onWillDispose(listener: () => void): IDisposable; @@ -722,6 +724,7 @@ export interface INotebookKernelInfoDto2 { detail?: string; isPreferred?: boolean; preloads?: UriComponents[]; + supportedLanguages?: string[] } export interface INotebookKernelInfo2 extends INotebookKernelInfoDto2 { diff --git a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts index 3654be90a53..f3ba2a45148 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts @@ -462,6 +462,7 @@ class OutputAutomaticPortForwarding extends Disposable { class ProcAutomaticPortForwarding extends Disposable { private candidateListener: IDisposable | undefined; private autoForwarded: Set = new Set(); + private notifiedOnly: Set = new Set(); private notifier: OnAutoForwardedAction; private initialCandidates: Set = new Set(); private portsFeatures: IDisposable | undefined; @@ -543,18 +544,18 @@ class ProcAutomaticPortForwarding extends Disposable { if (this.initialCandidates.has(address)) { return undefined; } + const alreadyForwarded = mapHasAddressLocalhostOrAllInterfaces(this.remoteExplorerService.tunnelModel.forwarded, value.host, value.port); if (mapHasAddressLocalhostOrAllInterfaces(this.remoteExplorerService.tunnelModel.detected, value.host, value.port)) { return undefined; } - if (mapHasAddressLocalhostOrAllInterfaces(this.remoteExplorerService.tunnelModel.forwarded, value.host, value.port)) { - return undefined; - } if (this.portsAttributes.getAttributes(value.port)?.onAutoForward === OnPortForward.Ignore) { return undefined; } const forwarded = await this.remoteExplorerService.forward(value, undefined, undefined, undefined, undefined, undefined, false); - if (forwarded) { + if (!alreadyForwarded && forwarded) { this.autoForwarded.add(address); + } else if (forwarded) { + this.notifiedOnly.add(address); } return forwarded; }))).filter(tunnel => !!tunnel); @@ -571,6 +572,9 @@ class ProcAutomaticPortForwarding extends Disposable { this.remoteExplorerService.close(value); this.autoForwarded.delete(key); removedPorts.push(value.port); + } else if (this.notifiedOnly.has(key)) { + this.notifiedOnly.delete(key); + removedPorts.push(value.port); } else if (this.initialCandidates.has(key)) { this.initialCandidates.delete(key); } diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index 53b3382d388..f2808ab0899 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -812,23 +812,26 @@ namespace LabelTunnelAction { export const LABEL = nls.localize('remote.tunnel.label', "Set Label"); export function handler(): ICommandHandler { - return async (accessor, arg) => { + return async (accessor, arg): Promise<{ port: number, label: string } | undefined> => { const context = (arg !== undefined || arg instanceof TunnelItem) ? arg : accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName); if (context instanceof TunnelItem) { - const remoteExplorerService = accessor.get(IRemoteExplorerService); - remoteExplorerService.setEditable(context, { - onFinish: async (value, success) => { - if (success) { - remoteExplorerService.tunnelModel.name(context.remoteHost, context.remotePort, value); - } - remoteExplorerService.setEditable(context, null); - }, - validationMessage: () => null, - placeholder: nls.localize('remote.tunnelsView.labelPlaceholder', "Port label"), - startingValue: context.name + return new Promise(resolve => { + const remoteExplorerService = accessor.get(IRemoteExplorerService); + remoteExplorerService.setEditable(context, { + onFinish: async (value, success) => { + if (success) { + remoteExplorerService.tunnelModel.name(context.remoteHost, context.remotePort, value); + } + remoteExplorerService.setEditable(context, null); + resolve(success ? { port: context.remotePort, label: value } : undefined); + }, + validationMessage: () => null, + placeholder: nls.localize('remote.tunnelsView.labelPlaceholder', "Port label"), + startingValue: context.name + }); }); } - return; + return undefined; }; } } diff --git a/src/vs/workbench/contrib/sash/browser/sash.contribution.ts b/src/vs/workbench/contrib/sash/browser/sash.contribution.ts index 4f61c8e2381..92460b36e1e 100644 --- a/src/vs/workbench/contrib/sash/browser/sash.contribution.ts +++ b/src/vs/workbench/contrib/sash/browser/sash.contribution.ts @@ -36,7 +36,6 @@ Registry.as(ConfigurationExtensions.Configuration) registerThemingParticipant((theme, collector) => { const sashHoverBorderColor = theme.getColor(sashHoverBorder); collector.addRule(` - .monaco-sash:hover, .monaco-sash.hover, .monaco-sash.active { background: ${sashHoverBorderColor} diff --git a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts index b7655429425..39d95cc7bc2 100644 --- a/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmRepositoriesViewPane.ts @@ -21,7 +21,7 @@ import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { RepositoryRenderer } from 'vs/workbench/contrib/scm/browser/scmRepositoryRenderer'; -import { collectContextMenuActions, getStatusBarActionViewItem } from 'vs/workbench/contrib/scm/browser/util'; +import { collectContextMenuActions, getActionViewItemProvider } from 'vs/workbench/contrib/scm/browser/util'; import { Orientation } from 'vs/base/browser/ui/sash/sash'; class ListDelegate implements IListVirtualDelegate { @@ -62,7 +62,7 @@ export class SCMRepositoriesViewPane extends ViewPane { const listContainer = append(container, $('.scm-view.scm-repositories-view')); const delegate = new ListDelegate(); - const renderer = this.instantiationService.createInstance(RepositoryRenderer, getStatusBarActionViewItem); + const renderer = this.instantiationService.createInstance(RepositoryRenderer, getActionViewItemProvider(this.instantiationService)); const identityProvider = { getId: (r: ISCMRepository) => r.provider.id }; this.list = this.instantiationService.createInstance(WorkbenchList, `SCM Main`, listContainer, delegate, [renderer], { diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index ef611614223..9e49aa3061c 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -23,7 +23,7 @@ import { MenuItemAction, IMenuService, registerAction2, MenuId, IAction2Options, import { IAction, ActionRunner, IActionViewItemProvider } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { IThemeService, registerThemingParticipant, IFileIconTheme } from 'vs/platform/theme/common/themeService'; -import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getStatusBarActionViewItem } from './util'; +import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, getActionViewItemProvider } from './util'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; import { WorkbenchCompressibleObjectTree, IOpenEvent } from 'vs/platform/list/browser/listService'; import { IConfigurationService, ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; @@ -1831,10 +1831,10 @@ export class SCMViewPane extends ViewPane { this._register(actionRunner.onBeforeRun(() => this.tree.domFocus())); const renderers: ICompressibleTreeRenderer[] = [ - this.instantiationService.createInstance(RepositoryRenderer, getStatusBarActionViewItem), + this.instantiationService.createInstance(RepositoryRenderer, getActionViewItemProvider(this.instantiationService)), this.inputRenderer, - this.instantiationService.createInstance(ResourceGroupRenderer, getStatusBarActionViewItem), - this.instantiationService.createInstance(ResourceRenderer, () => this._viewModel, this.listLabels, getStatusBarActionViewItem, actionRunner) + this.instantiationService.createInstance(ResourceGroupRenderer, getActionViewItemProvider(this.instantiationService)), + this.instantiationService.createInstance(ResourceRenderer, () => this._viewModel, this.listLabels, getActionViewItemProvider(this.instantiationService), actionRunner) ]; const filter = new SCMTreeFilter(); diff --git a/src/vs/workbench/contrib/scm/browser/util.ts b/src/vs/workbench/contrib/scm/browser/util.ts index fc27ff6b731..7d916c437d5 100644 --- a/src/vs/workbench/contrib/scm/browser/util.ts +++ b/src/vs/workbench/contrib/scm/browser/util.ts @@ -7,14 +7,15 @@ import { ISCMResource, ISCMRepository, ISCMResourceGroup, ISCMInput } from 'vs/w import { IMenu } from 'vs/platform/actions/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { IDisposable, Disposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { Action, IAction, IActionViewItem } from 'vs/base/common/actions'; -import { createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { Action, IAction, IActionViewItemProvider } from 'vs/base/common/actions'; +import { createActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { equals } from 'vs/base/common/arrays'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { Command } from 'vs/editor/common/modes'; import { reset } from 'vs/base/browser/dom'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; export function isSCMRepository(element: any): element is ISCMRepository { return !!(element as ISCMRepository).provider && !!(element as ISCMRepository).input; @@ -107,10 +108,12 @@ class StatusBarActionViewItem extends ActionViewItem { } } -export function getStatusBarActionViewItem(action: IAction): IActionViewItem | undefined { - if (action instanceof StatusBarAction) { - return new StatusBarActionViewItem(action); - } +export function getActionViewItemProvider(instaService: IInstantiationService): IActionViewItemProvider { + return action => { + if (action instanceof StatusBarAction) { + return new StatusBarActionViewItem(action); + } - return undefined; + return createActionViewItem(instaService, action); + }; } diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index ec8c2afce05..aa467b2a8b6 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -17,7 +17,7 @@ import { Action2, ICommandAction, MenuId, MenuRegistry, registerAction2, SyncAct import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationScope, Extensions as ConfigurationExtensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyEqualsExpr, ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IFileService } from 'vs/platform/files/common/files'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -637,8 +637,6 @@ const viewDescriptor: IViewDescriptor = { mnemonicTitle: nls.localize({ key: 'miViewSearch', comment: ['&& denotes a mnemonic'] }, "&&Search"), keybindings: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F, - // View: Show Search is used for the keybindings in the View menu and the sidebar #115556, but it should only be enabled when search.mode == view, or else it will steal priority over opening a search editor #115511 - when: ContextKeyAndExpr.create([Constants.SearchViewVisibleKey.toNegated(), ContextKeyEqualsExpr.create(`config.${SEARCH_MODE_CONFIG}`, 'view')]), }, order: 1 } @@ -712,7 +710,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ ] }, id: Constants.FindInFilesActionId, - weight: KeybindingWeight.WorkbenchContrib, + // Give more weightage to this keybinding than of `View: Show Search` keybinding. See #116188, #115556, #115511 + weight: KeybindingWeight.WorkbenchContrib + 1, when: null, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_F, handler: FindInFilesCommand diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 4da73bd5b88..40f36f73b52 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -678,12 +678,18 @@ export class SearchView extends ViewPane { private clearMessage(): HTMLElement { this.searchWithoutFolderMessageElement = undefined; + const wasHidden = this.messagesElement.style.display === 'none'; dom.clearNode(this.messagesElement); dom.show(this.messagesElement); dispose(this.messageDisposables); this.messageDisposables = []; - return dom.append(this.messagesElement, $('.message')); + const newMessage = dom.append(this.messagesElement, $('.message')); + if (wasHidden) { + this.reLayout(); + } + + return newMessage; } private createSearchResultsView(container: HTMLElement): void { @@ -1085,6 +1091,7 @@ export class SearchView extends ViewPane { this.tree.ariaLabel = nls.localize('emptySearch', "Empty Search"); aria.status(nls.localize('ariaSearchResultsClearStatus', "The search results have been cleared")); + this.reLayout(); } clearFilePatternFields(): void { diff --git a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index 92dcbb35ba1..0af9ae95069 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -237,12 +237,12 @@ export function escapeNonWindowsPath(path: string): string { if (newPath.indexOf('\\') !== 0) { newPath = newPath.replace(/\\/g, '\\\\'); } - if (!newPath && (newPath.indexOf('"') !== -1)) { - newPath = '\'' + newPath + '\''; - } else if (newPath.indexOf(' ') !== -1) { + if (newPath.indexOf(' ') !== -1) { newPath = newPath.replace(/ /g, '\\ '); } - return newPath; + const bannedChars = /[\`\$\|\&\>\~\#\!\^\*\;\<\"\']/g; + newPath = newPath.replace(bannedChars, ''); + return `'${newPath}'`; } export type TerminalShellSetting = ( diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts index e1858ddb9ee..0129e797ade 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts @@ -10,13 +10,28 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { Position } from 'vs/editor/common/core/position'; import { IWorkspaceFolder, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; import { HierarchicalElement, HierarchicalFolder } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; import { locationsEqual, TestLocationStore } from 'vs/workbench/contrib/testing/browser/explorerProjections/locationStore'; import { NodeChangeList, NodeRenderDirective, NodeRenderFn, peersHaveChildren } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; +import { IComputedStateAccessor, refreshComputedState } from 'vs/workbench/contrib/testing/common/getComputedState'; import { InternalTestItem, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/common/workspaceTestCollectionService'; +const computedStateAccessor: IComputedStateAccessor = { + getOwnState: i => i.state, + getCurrentComputedState: i => i.state, + setComputedState: (i, s) => i.state = s, + getChildren: i => i.children.values(), + *getParents(i) { + for (let parent = i.parentItem; parent; parent = parent.parentItem) { + yield parent; + } + }, +}; + /** * Projection that lists tests in their traditional tree view. */ @@ -40,11 +55,42 @@ export class HierarchicalByLocationProjection extends Disposable implements ITes */ public readonly onUpdate = this.updateEmitter.event; - constructor(listener: TestSubscriptionListener) { + constructor(listener: TestSubscriptionListener, @ITestResultService private readonly results: ITestResultService) { super(); this._register(listener.onDiff(([folder, diff]) => this.applyDiff(folder, diff))); this._register(listener.onFolderChange(this.applyFolderChange, this)); + // when test results are cleared, recalculate all state + this._register(results.onResultsChanged((evt) => { + if (!('removed' in evt)) { + return; + } + + for (const inTree of [...this.items.values()].sort((a, b) => b.depth - a.depth)) { + const lookup = this.results.getStateByExtId(inTree.test.item.extId)?.[1]; + inTree.ownState = lookup?.state.state ?? TestRunState.Unset; + const computed = lookup?.computedState ?? TestRunState.Unset; + if (computed !== inTree.state) { + inTree.state = computed; + this.addUpdated(inTree); + } + } + + this.updateEmitter.fire(); + })); + + // when test states change, reflect in the tree + this._register(results.onTestChanged(([, { item, state, computedState }]) => { + for (const i of this.items.values()) { + if (i.test.item.extId === item.extId) { + i.ownState = state.state; + refreshComputedState(computedStateAccessor, i, this.addUpdated, computedState); + this.updateEmitter.fire(); + return; + } + } + })); + for (const [folder, collection] of listener.workspaceFolderCollections) { for (const node of collection.all) { this.storeItem(this.createItem(node, folder.folder)); @@ -96,7 +142,7 @@ export class HierarchicalByLocationProjection extends Disposable implements ITes const locationChanged = !locationsEqual(existing.location, item.item.location); if (locationChanged) { this.locations.remove(existing); } - existing.update(item, this.addUpdated); + existing.update(item); if (locationChanged) { this.locations.add(existing); } this.addUpdated(existing); break; @@ -172,5 +218,11 @@ export class HierarchicalByLocationProjection extends Disposable implements ITes item.parentItem.children.add(item); this.items.set(item.test.id, item); this.locations.add(item); + + const prevState = this.results.getStateByExtId(item.test.item.extId)?.[1]; + if (prevState) { + item.ownState = prevState.state.state; + refreshComputedState(computedStateAccessor, item, this.addUpdated, prevState.computedState); + } } } diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts index b263ca46c16..8775e2454d0 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts @@ -10,6 +10,7 @@ import { HierarchicalByLocationProjection as HierarchicalByLocationProjection } import { HierarchicalElement, HierarchicalFolder } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; import { NodeRenderDirective } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; import { InternalTestItem } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/common/workspaceTestCollectionService'; /** @@ -64,9 +65,9 @@ export class HierarchicalByNameElement extends HierarchicalElement { /** * @override */ - public update(actual: InternalTestItem, addUpdated: (n: ITestTreeElement) => void) { + public update(actual: InternalTestItem) { const wasRunnable = this.test.item.runnable; - super.update(actual, addUpdated); + super.update(actual); if (this.test.item.runnable !== wasRunnable) { this.updateLeafTestState(); @@ -117,8 +118,8 @@ export class HierarchicalByNameElement extends HierarchicalElement { * test root rather than the heirarchal parent. */ export class HierarchicalByNameProjection extends HierarchicalByLocationProjection { - constructor(listener: TestSubscriptionListener) { - super(listener); + constructor(listener: TestSubscriptionListener, @ITestResultService results: ITestResultService) { + super(listener, results); const originalRenderNode = this.renderNode.bind(this); this.renderNode = (node, recurse) => { diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts index 07bd0d0c1a7..fb1dc153526 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes.ts @@ -7,7 +7,6 @@ import { Iterable } from 'vs/base/common/iterator'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; import { ITestTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; -import { maxPriority, statePriority } from 'vs/workbench/contrib/testing/common/testingStates'; import { InternalTestItem, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; /** @@ -15,7 +14,6 @@ import { InternalTestItem, TestIdWithProvider } from 'vs/workbench/contrib/testi */ export class HierarchicalElement implements ITestTreeElement { public readonly children = new Set(); - public computedState: TestRunState | undefined; public readonly depth: number = this.parentItem.depth + 1; public get treeId() { @@ -26,10 +24,6 @@ export class HierarchicalElement implements ITestTreeElement { return this.test.item.label; } - public get state() { - return this.test.item.state.runState; - } - public get location() { return this.test.item.location; } @@ -46,16 +40,15 @@ export class HierarchicalElement implements ITestTreeElement { : Iterable.empty(); } + public state = TestRunState.Unset; + public ownState = TestRunState.Unset; + constructor(public readonly test: InternalTestItem, public readonly parentItem: HierarchicalFolder | HierarchicalElement) { this.test = { ...test, item: { ...test.item } }; // clone since we Object.assign updatese } - public update(actual: InternalTestItem, addUpdated: (n: ITestTreeElement) => void) { - const stateChange = actual.item.state.runState !== this.state; + public update(actual: InternalTestItem) { Object.assign(this.test, actual); - if (stateChange) { - refreshComputedState(this, addUpdated); - } } } @@ -80,67 +73,12 @@ export class HierarchicalFolder implements ITestTreeElement { return Iterable.concatNested(Iterable.map(this.children, c => c.debuggable)); } + public state = TestRunState.Unset; + public ownState = TestRunState.Unset; + constructor(private readonly folder: IWorkspaceFolder) { } public get label() { return this.folder.name; } } - -/** - * Gets the computed state for the node. - */ -export const getComputedState = (node: ITestTreeElement) => { - if (node.computedState === undefined) { - node.computedState = node.state ?? TestRunState.Unset; - for (const child of node.children) { - node.computedState = maxPriority(node.computedState, getComputedState(child)); - } - } - - return node.computedState; -}; - -/** - * Refreshes the computed state for the node and its parents. Any changes - * elements cause `addUpdated` to be called. - */ -export const refreshComputedState = (node: ITestTreeElement, addUpdated: (n: ITestTreeElement) => void) => { - if (node.computedState === undefined) { - return; - } - - const oldPriority = statePriority[node.computedState]; - node.computedState = undefined; - const newState = getComputedState(node); - const newPriority = statePriority[getComputedState(node)]; - if (newPriority === oldPriority) { - return; - } - - addUpdated(node); - if (newPriority > oldPriority) { - // Update all parents to ensure they're at least this priority. - for (let parent = node.parentItem; parent; parent = parent.parentItem) { - const prev = parent.computedState; - if (prev !== undefined && statePriority[prev] >= newPriority) { - break; - } - - parent.computedState = newState; - addUpdated(parent); - } - } else if (newPriority < oldPriority) { - // Re-render all parents of this node whose computed priority might have come from this node - for (let parent = node.parentItem; parent; parent = parent.parentItem) { - const prev = parent.computedState; - if (prev === undefined || statePriority[prev] > oldPriority) { - break; - } - - parent.computedState = undefined; - parent.computedState = getComputedState(parent); - addUpdated(parent); - } - } -}; diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts index 78459dfe316..4a9e0770d5e 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts @@ -40,13 +40,6 @@ export interface ITestTreeProjection extends IDisposable { export interface ITestTreeElement { - /** - * Computed element state. Will be set automatically if not initially provided. - * The projection is responsible for clearing (or updating) this if it - * becomes invalid. - */ - computedState: TestRunState | undefined; - readonly children: Set; /** @@ -85,9 +78,11 @@ export interface ITestTreeElement { readonly debuggable: Iterable; /** - * State of of the tree item. Mostly used for deriving the computed state. + * Element state to display. */ - readonly state?: TestRunState; + state: TestRunState; + + readonly ownState: TestRunState; readonly label: string; readonly parentItem: ITestTreeElement | null; } diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts deleted file mode 100644 index ea6f7c7919a..00000000000 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation.ts +++ /dev/null @@ -1,321 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; -import { Emitter } from 'vs/base/common/event'; -import { FuzzyScore } from 'vs/base/common/filters'; -import { Iterable } from 'vs/base/common/iterator'; -import { DisposableStore } from 'vs/base/common/lifecycle'; -import { URI } from 'vs/base/common/uri'; -import { Position } from 'vs/editor/common/core/position'; -import { Location as ModeLocation } from 'vs/editor/common/modes'; -import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; -import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; -import { locationsEqual, TestLocationStore } from 'vs/workbench/contrib/testing/browser/explorerProjections/locationStore'; -import { NodeChangeList, NodeRenderDirective, NodeRenderFn, peersHaveChildren } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; -import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; -import { AbstractIncrementalTestCollection, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; -import { isRunningState, statesInOrder } from 'vs/workbench/contrib/testing/common/testingStates'; -import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/common/workspaceTestCollectionService'; - -interface IStatusTestItem extends IncrementalTestCollectionItem { - treeElements: Map; - previousState: TestRunState; - depth: number; - parentItem?: IStatusTestItem; - location?: ModeLocation; -} - -type TreeElement = StateElement | TestStateElement; - -class TestStateElement implements ITestTreeElement { - public computedState = this.state; - - public get treeId() { - return `sltest:${this.test.id}`; - } - - public get label() { - return this.test.item.label; - } - - public get location() { - return this.test.item.location; - } - - public get runnable(): Iterable { - // if this item is runnable and all its children are in the same state, - // we can run all of them in one go. This will eventually be true - // for leaf nodes, whose treeElements contain only their own state. - if (this.test.item.runnable && this.test.treeElements.size === 1) { - return [{ testId: this.test.id, providerId: this.test.providerId }]; - } - - return Iterable.concatNested(Iterable.map(this.children, c => c.runnable)); - } - - public get debuggable(): Iterable { - // same logic as runnable above - if (this.test.item.debuggable && this.test.treeElements.size === 1) { - return [{ testId: this.test.id, providerId: this.test.providerId }]; - } - - return Iterable.concatNested(Iterable.map(this.children, c => c.debuggable)); - } - - public readonly depth = this.test.depth; - public readonly children = new Set(); - - constructor( - public readonly state: TestRunState, - public readonly test: IStatusTestItem, - public readonly parentItem: TestStateElement | StateElement, - ) { - parentItem.children.add(this); - } - - public remove() { - this.parentItem.children.delete(this); - } -} - -/** - * Shows tests in a hierarchical way, but grouped by status. This is more - * complex than it may look at first glance, because nodes can appear in - * multiple places if they have children with different statuses. - */ -export class StateByLocationProjection extends AbstractIncrementalTestCollection implements ITestTreeProjection { - private readonly updateEmitter = new Emitter(); - private readonly changes = new NodeChangeList(); - private readonly locations = new TestLocationStore(); - private readonly disposable = new DisposableStore(); - - /** - * @inheritdoc - */ - public readonly onUpdate = this.updateEmitter.event; - - /** - * Root elements for states in the tree. - */ - protected readonly stateRoots = new Map>(); - - constructor(listener: TestSubscriptionListener) { - super(); - - this.disposable.add(listener.onDiff(([, diff]) => this.apply(diff))); - - const firstDiff: TestsDiff = []; - for (const [, collection] of listener.workspaceFolderCollections) { - firstDiff.push(...collection.getReviverDiff()); - } - - this.apply(firstDiff); - } - - /** - * Frees listeners associated with the projection. - */ - public dispose() { - this.disposable.dispose(); - } - - /** - * @inheritdoc - */ - public getTestAtPosition(uri: URI, position: Position) { - const item = this.locations.getTestAtPosition(uri, position); - if (!item) { - return undefined; - } - - for (const state of statesInOrder) { - const element = item.treeElements.get(state); - if (element) { - return element; - } - } - - return undefined; - } - - /** - * @inheritdoc - */ - public applyTo(tree: ObjectTree) { - this.changes.applyTo(tree, this.renderNode, () => this.stateRoots.values()); - } - - private readonly renderNode: NodeRenderFn = (node, recurse) => { - if (node.depth === 1 /* test provider */) { - if (node.children.size === 0) { - return NodeRenderDirective.Omit; - } else if (!peersHaveChildren(node, () => this.stateRoots.values())) { - return NodeRenderDirective.Concat; - } - } - - return { - element: node, - children: recurse(node.children), - }; - }; - - /** - * @override - */ - protected createChangeCollector(): IncrementalChangeCollector { - return { - add: node => { - this.resolveNodesRecursive(node); - this.locations.add(node); - }, - remove: (node, isNested) => { - this.locations.remove(node); - - if (!isNested) { - for (const state of node.treeElements.keys()) { - this.pruneStateElements(node, state, true); - } - } - }, - update: node => { - const isRunning = isRunningState(node.item.state.runState); - if (node.item.state.runState !== node.previousState) { - if (isRunning && node.treeElements.has(node.previousState)) { - node.treeElements.get(node.previousState)!.computedState = TestRunState.Running; - } else { - this.pruneStateElements(node, node.previousState); - this.resolveNodesRecursive(node); - } - } else if (!isRunning) { - const previous = node.treeElements.get(node.item.state.runState); - if (previous) { - previous.computedState = node.item.state.runState; - } - } - - const locationChanged = !locationsEqual(node.location, node.item.location); - if (locationChanged) { - this.locations.remove(node); - node.location = node.item.location; - this.locations.add(node); - } - - const treeNode = node.treeElements.get(node.previousState)!; - this.changes.updated(treeNode); - }, - complete: () => { - this.updateEmitter.fire(); - } - }; - } - - /** - * Ensures tree nodes for the item state are present in the tree. - */ - protected resolveNodesRecursive(item: IStatusTestItem) { - const state = item.item.state.runState; - item.previousState = item.item.state.runState; - - // Create a list of items until the current item who don't have a tree node for the status yet - let chain: IStatusTestItem[] = []; - for (let i: IStatusTestItem | undefined = item; i && !i.treeElements.has(state); i = i.parentItem) { - chain.push(i); - } - - for (let i = chain.length - 1; i >= 0; i--) { - const item2 = chain[i]; - // the loop would have stopped pushing parents when either it reaches - // the root, or it reaches a parent who already has a node for this state. - const parent = item2.parentItem?.treeElements.get(state) ?? this.getOrCreateStateElement(state); - const node = this.createElement(state, item2, parent); - - item2.treeElements.set(state, node); - parent.children.add(node); - - if (i === chain.length - 1) { - this.changes.added(node); - } - } - } - - protected createElement(state: TestRunState, item: IStatusTestItem, parent: TreeElement) { - return new TestStateElement(state, item, parent); - } - - - /** - * Recursively (from the leaf to the root) removes tree elements if there's - * no children who have the given state left. - * - * Returns true if it resulted in a node being removed. - */ - protected pruneStateElements(item: IStatusTestItem | undefined, state: TestRunState, force = false) { - if (!item) { - const stateRoot = this.stateRoots.get(state); - if (stateRoot?.children.size === 0) { - this.changes.removed(stateRoot); - this.stateRoots.delete(state); - return true; - } - - return false; - } - - const node = item.treeElements.get(state); - if (!node) { - return false; - } - - // Check to make sure we aren't in the state, and there's no child with the - // state. For the unset state, only show the node if it's a leaf or it - // has children in the unset state. - if (!force) { - if (item.item.state.runState === state && !(state === TestRunState.Unset && item.children.size > 0)) { - return false; - } - - for (const childId of item.children) { - if (this.items.get(childId)?.treeElements.has(state)) { - return false; - } - } - } - - // If so, proceed to deletion and recurse upwards. - item.treeElements.delete(state); - node.remove(); - - if (!this.pruneStateElements(item.parentItem, state)) { - this.changes.removed(node); - } - - return true; - } - - protected getOrCreateStateElement(state: TestRunState) { - let s = this.stateRoots.get(state); - if (!s) { - s = new StateElement(state); - this.changes.added(s); - this.stateRoots.set(state, s); - } - - return s; - } - - protected createItem(item: InternalTestItem, parentItem?: IStatusTestItem): IStatusTestItem { - return { - ...item, - depth: parentItem ? parentItem.depth + 1 : 1, - parentItem: parentItem, - previousState: item.item.state.runState, - location: item.item.location, - children: new Set(), - treeElements: new Map(), - }; - } -} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts deleted file mode 100644 index cd7ad2a077b..00000000000 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateByName.ts +++ /dev/null @@ -1,289 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; -import { Emitter } from 'vs/base/common/event'; -import { FuzzyScore } from 'vs/base/common/filters'; -import { Iterable } from 'vs/base/common/iterator'; -import { DisposableStore } from 'vs/base/common/lifecycle'; -import { URI } from 'vs/base/common/uri'; -import { Position } from 'vs/editor/common/core/position'; -import { Location as ModeLocation } from 'vs/editor/common/modes'; -import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; -import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; -import { ListElementType } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName'; -import { locationsEqual, TestLocationStore } from 'vs/workbench/contrib/testing/browser/explorerProjections/locationStore'; -import { NodeChangeList, NodeRenderFn } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; -import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; -import { AbstractIncrementalTestCollection, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; -import { isRunningState } from 'vs/workbench/contrib/testing/common/testingStates'; -import { TestSubscriptionListener } from 'vs/workbench/contrib/testing/common/workspaceTestCollectionService'; - -class ListTestStateElement implements ITestTreeElement { - public computedState = this.test.item.state.runState; - - public get treeId() { - return `sntest:${this.test.id}`; - } - - public get label() { - return this.test.item.label; - } - - public get location() { - return this.test.item.location; - } - - public get runnable(): Iterable { - return this.test.item.runnable - ? [{ testId: this.test.id, providerId: this.test.providerId }] - : Iterable.empty(); - } - - public get debuggable(): Iterable { - return this.test.item.debuggable - ? [{ testId: this.test.id, providerId: this.test.providerId }] - : Iterable.empty(); - } - - public get description() { - let description: string | undefined; - for (let parent = this.test.parentItem; parent && parent.depth > 0; parent = parent.parentItem) { - description = description ? `${parent.item.label} › ${description}` : parent.item.label; - } - - return description; - } - - public readonly depth = 1; - public readonly children = new Set(); - - constructor( - public readonly test: IStatusListTestItem, - public readonly parentItem: StateElement, - ) { - parentItem.children.add(this); - } - - public remove() { - this.parentItem.children.delete(this); - } -} - -interface IStatusListTestItem extends IncrementalTestCollectionItem { - node?: ListTestStateElement; - type: ListElementType; - previousState: TestRunState; - depth: number; - parentItem?: IStatusListTestItem; - location?: ModeLocation; -} - -type TreeElement = StateElement | ListTestStateElement; - -/** - * Projection that shows tests in a flat list (grouped by status). - */ -export class StateByNameProjection extends AbstractIncrementalTestCollection implements ITestTreeProjection { - private readonly updateEmitter = new Emitter(); - private readonly changes = new NodeChangeList(); - private readonly locations = new TestLocationStore(); - private readonly disposable = new DisposableStore(); - - /** - * @inheritdoc - */ - public readonly onUpdate = this.updateEmitter.event; - - /** - * Root elements for states in the tree. - */ - protected readonly stateRoots = new Map>(); - - constructor(listener: TestSubscriptionListener) { - super(); - - this.disposable.add(listener.onDiff(([, diff]) => this.apply(diff))); - - const firstDiff: TestsDiff = []; - for (const [, collection] of listener.workspaceFolderCollections) { - firstDiff.push(...collection.getReviverDiff()); - } - - this.apply(firstDiff); - } - - /** - * Frees listeners associated with the projection. - */ - public dispose() { - this.disposable.dispose(); - } - - /** - * @inheritdoc - */ - public getTestAtPosition(uri: URI, position: Position) { - return this.locations.getTestAtPosition(uri, position)?.node; - } - - /** - * @inheritdoc - */ - public applyTo(tree: ObjectTree) { - this.changes.applyTo(tree, this.renderNode, () => this.stateRoots.values()); - } - - private readonly renderNode: NodeRenderFn = (node, recurse) => { - return { - element: node, - children: node instanceof StateElement ? recurse(node.children) : undefined, - }; - }; - - /** - * @override - */ - protected createChangeCollector(): IncrementalChangeCollector { - return { - add: node => { - this.resolveNodesRecursive(node); - this.locations.add(node); - }, - remove: (node, isNested) => { - if (node.node) { - this.locations.remove(node); - } - - // for the top node being deleted, we need to update parents. For - // others we only need to remove them from the locations cache. - if (isNested) { - this.removeNodeSingle(node); - } else { - this.removeNode(node); - } - }, - update: node => { - if (node.item.state.runState !== node.previousState && node.node) { - if (isRunningState(node.item.state.runState)) { - node.node.computedState = node.item.state.runState; - } else { - this.removeNode(node); - } - } - - node.previousState = node.item.state.runState; - this.resolveNodesRecursive(node); - - const locationChanged = !locationsEqual(node.location, node.item.location); - if (locationChanged) { - this.locations.remove(node); - node.location = node.item.location; - this.locations.add(node); - } - - if (node.node) { - this.changes.updated(node.node); - } - }, - complete: () => { - this.updateEmitter.fire(); - } - }; - } - - /** - * Ensures tree nodes for the item state are present in the tree. - */ - protected resolveNodesRecursive(item: IStatusListTestItem) { - const newType = Iterable.some(item.children, c => this.items.get(c)?.type !== ListElementType.BranchWithoutLeaf) - ? ListElementType.BranchWithLeaf - : item.item.runnable - ? ListElementType.TestLeaf - : ListElementType.BranchWithoutLeaf; - - if (newType === item.type) { - return; - } - - const isVisible = newType === ListElementType.TestLeaf; - const wasVisible = item.type === ListElementType.TestLeaf; - item.type = newType; - - if (!isVisible && wasVisible && item.node) { - this.removeNodeSingle(item); - } else if (isVisible && !wasVisible) { - const state = item.item.state.runState; - item.node = item.node || new ListTestStateElement(item, this.getOrCreateStateElement(state)); - this.changes.added(item.node); - } - - if (item.parentItem) { - this.resolveNodesRecursive(item.parentItem); - } - } - - /** - * Recursively (from the leaf to the root) removes tree elements if there's - * no children who have the given state left. - * - * Returns true if it resulted in a node being removed. - */ - private removeNode(item: IStatusListTestItem) { - if (!item.node) { - return; - } - - this.removeNodeSingle(item); - - if (item.parentItem) { - this.resolveNodesRecursive(item.parentItem); - } - } - - private removeNodeSingle(item: IStatusListTestItem) { - if (!item.node) { - return; - } - - item.node.remove(); - this.changes.removed(item.node); - - const parent = item.node.parentItem; - item.node = undefined; - item.type = ListElementType.Unset; - - if (parent.children.size === 0) { - this.changes.removed(parent); - this.stateRoots.delete(parent.state); - } - } - - private getOrCreateStateElement(state: TestRunState) { - let s = this.stateRoots.get(state); - if (!s) { - s = new StateElement(state); - this.changes.added(s); - this.stateRoots.set(state, s); - } - - return s; - } - - /** - * @override - */ - protected createItem(item: InternalTestItem, parentItem?: IStatusListTestItem): IStatusListTestItem { - return { - ...item, - type: ListElementType.Unset, - depth: parentItem ? parentItem.depth + 1 : 0, - parentItem: parentItem, - previousState: item.item.state.runState, - location: item.item.location, - children: new Set(), - }; - } -} diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateNodes.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/stateNodes.ts deleted file mode 100644 index 5b3fed98aca..00000000000 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/stateNodes.ts +++ /dev/null @@ -1,35 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Iterable } from 'vs/base/common/iterator'; -import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; -import { ITestTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; -import { testStateNames } from 'vs/workbench/contrib/testing/common/constants'; - -/** - * Base state node element, used in both name and location grouping. - */ -export class StateElement implements ITestTreeElement { - public computedState = this.state; - - public get treeId() { - return `sestate:${this.state}`; - } - - public readonly depth = 0; - public readonly label = testStateNames[this.state]; - public readonly parentItem = null; - public readonly children = new Set(); - - public get runnable() { - return Iterable.concatNested(Iterable.map(this.children, c => c.runnable)); - } - - public get debuggable() { - return Iterable.concatNested(Iterable.map(this.children, c => c.debuggable)); - } - - constructor(public readonly state: TestRunState) { } -} diff --git a/src/vs/workbench/contrib/testing/browser/icons.ts b/src/vs/workbench/contrib/testing/browser/icons.ts index 62df586f8d3..e2b46acd521 100644 --- a/src/vs/workbench/contrib/testing/browser/icons.ts +++ b/src/vs/workbench/contrib/testing/browser/icons.ts @@ -20,10 +20,10 @@ export const testingShowAsList = registerIcon('testing-show-as-list-icon', Codic export const testingShowAsTree = registerIcon('testing-show-as-list-icon', Codicon.listFlat, localize('testingShowAsTree', 'Icon shown when the test explorer is disabled as a list.')); export const testingStatesToIcons = new Map([ - [TestRunState.Errored, registerIcon('testing-error-icon', Codicon.warning, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))], - [TestRunState.Failed, registerIcon('testing-failed-icon', Codicon.close, localize('testingFailedIcon', 'Icon shown for tests that failed.'))], + [TestRunState.Errored, registerIcon('testing-error-icon', Codicon.issues, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))], + [TestRunState.Failed, registerIcon('testing-failed-icon', Codicon.error, localize('testingFailedIcon', 'Icon shown for tests that failed.'))], [TestRunState.Passed, registerIcon('testing-passed-icon', Codicon.pass, localize('testingPassedIcon', 'Icon shown for tests that passed.'))], - [TestRunState.Queued, registerIcon('testing-queued-icon', Codicon.watch, localize('testingQueuedIcon', 'Icon shown for tests that are queued.'))], + [TestRunState.Queued, registerIcon('testing-queued-icon', Codicon.history, localize('testingQueuedIcon', 'Icon shown for tests that are queued.'))], [TestRunState.Running, ThemeIcon.modify(Codicon.loading, 'spin')], [TestRunState.Skipped, registerIcon('testing-skipped-icon', Codicon.debugStepOver, localize('testingSkippedIcon', 'Icon shown for tests that are skipped.'))], [TestRunState.Unset, registerIcon('testing-unset-icon', Codicon.circleOutline, localize('testingUnsetIcon', 'Icon shown for tests that are in an unset state.'))], diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts index db03e28f7c9..6125b257fa7 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -21,9 +21,10 @@ import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane'; import { FocusedViewContext } from 'vs/workbench/common/views'; import * as icons from 'vs/workbench/contrib/testing/browser/icons'; import { TestingExplorerView, TestingExplorerViewModel } from 'vs/workbench/contrib/testing/browser/testingExplorerView'; -import { TestExplorerViewGrouping, TestExplorerViewMode, Testing } from 'vs/workbench/contrib/testing/common/constants'; -import { EMPTY_TEST_RESULT, InternalTestItem, RunTestsResult, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; +import { TestExplorerViewSorting, TestExplorerViewMode, Testing } from 'vs/workbench/contrib/testing/common/constants'; +import { InternalTestItem, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; +import { ITestResult, ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { ITestService, waitForAllRoots } from 'vs/workbench/contrib/testing/common/testService'; import { IWorkspaceTestCollectionService } from 'vs/workbench/contrib/testing/common/workspaceTestCollectionService'; @@ -101,10 +102,10 @@ abstract class RunOrDebugAction extends ViewAction { /** * @override */ - public runInView(accessor: ServicesAccessor, view: TestingExplorerView): Promise { + public runInView(accessor: ServicesAccessor, view: TestingExplorerView): Promise { const tests = this.getActionableTests(accessor.get(IWorkspaceTestCollectionService), view.viewModel); if (!tests.length) { - return Promise.resolve(EMPTY_TEST_RESULT); + return Promise.resolve(undefined); } return accessor.get(ITestService).runTests({ tests, debug: this.debug }); @@ -327,18 +328,18 @@ export class TestingViewAsTreeAction extends ViewAction { } -export class TestingGroupByLocationAction extends ViewAction { +export class TestingSortByNameAction extends ViewAction { constructor() { super({ - id: 'testing.groupByLocation', + id: 'testing.sortByName', viewId: Testing.ExplorerViewId, - title: localize('testing.groupByLocation', "Sort by Name"), + title: localize('testing.sortByName', "Sort by Name"), f1: false, - toggled: TestingContextKeys.viewGrouping.isEqualTo(TestExplorerViewGrouping.ByLocation), + toggled: TestingContextKeys.viewSorting.isEqualTo(TestExplorerViewSorting.ByName), menu: { id: MenuId.ViewTitle, order: 10, - group: 'groupBy', + group: 'sortBy', when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId) } }); @@ -348,22 +349,22 @@ export class TestingGroupByLocationAction extends ViewAction { +export class TestingSortByLocationAction extends ViewAction { constructor() { super({ - id: 'testing.groupByStatus', + id: 'testing.sortByLocation', viewId: Testing.ExplorerViewId, - title: localize('testing.groupByStatus', "Sort by Status"), + title: localize('testing.sortByLocation', "Sort by Location"), f1: false, - toggled: TestingContextKeys.viewGrouping.isEqualTo(TestExplorerViewGrouping.ByStatus), + toggled: TestingContextKeys.viewSorting.isEqualTo(TestExplorerViewSorting.ByLocation), menu: { id: MenuId.ViewTitle, order: 10, - group: 'groupBy', + group: 'sortBy', when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId) } }); @@ -373,7 +374,7 @@ export class TestingGroupByStatusAction extends ViewAction * @override */ public runInView(_accessor: ServicesAccessor, view: TestingExplorerView) { - view.viewModel.viewGrouping = TestExplorerViewGrouping.ByStatus; + view.viewModel.viewSorting = TestExplorerViewSorting.ByLocation; } } @@ -427,6 +428,24 @@ export class RefreshTestsAction extends Action2 { } } +export class ClearTestResultsAction extends Action2 { + constructor() { + super({ + id: 'testing.clearTestResults', + title: localize('testing.clearResults', "Clear All Results"), + category, + f1: true + }); + } + + /** + * @override + */ + public run(accessor: ServicesAccessor) { + accessor.get(ITestResultService).clear(); + } +} + export class EditFocusedTest extends ViewAction { constructor() { super({ diff --git a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts index 8d8bf3dafad..ce6a99f15c0 100644 --- a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts +++ b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts @@ -83,13 +83,14 @@ registerAction2(Action.TestingViewAsTreeAction); registerAction2(Action.CancelTestRunAction); registerAction2(Action.RunSelectedAction); registerAction2(Action.DebugSelectedAction); -registerAction2(Action.TestingGroupByLocationAction); -registerAction2(Action.TestingGroupByStatusAction); +registerAction2(Action.TestingSortByNameAction); +registerAction2(Action.TestingSortByLocationAction); registerAction2(Action.RefreshTestsAction); registerAction2(Action.CollapseAllAction); registerAction2(Action.RunAllAction); registerAction2(Action.DebugAllAction); registerAction2(Action.EditFocusedTest); +registerAction2(Action.ClearTestResultsAction); registerAction2(CloseTestPeek); Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(TestingContentProvider, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/testing/browser/testingDecorations.ts b/src/vs/workbench/contrib/testing/browser/testingDecorations.ts index e0d3fba41ee..01d809934ca 100644 --- a/src/vs/workbench/contrib/testing/browser/testingDecorations.ts +++ b/src/vs/workbench/contrib/testing/browser/testingDecorations.ts @@ -28,8 +28,8 @@ import { testingRunAllIcon, testingRunIcon, testingStatesToIcons } from 'vs/work import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browser/testingOutputPeek'; import { testMessageSeverityColors } from 'vs/workbench/contrib/testing/browser/theme'; import { IncrementalTestCollectionItem, ITestMessage } from 'vs/workbench/contrib/testing/common/testCollection'; -import { maxPriority } from 'vs/workbench/contrib/testing/common/testingStates'; import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri'; +import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { IMainThreadTestCollection, ITestService } from 'vs/workbench/contrib/testing/common/testService'; export class TestingDecorations extends Disposable implements IEditorContribution { @@ -39,6 +39,7 @@ export class TestingDecorations extends Disposable implements IEditorContributio constructor( private readonly editor: ICodeEditor, @ITestService private readonly testService: ITestService, + @ITestResultService private readonly results: ITestResultService, @IInstantiationService private readonly instantiationService: IInstantiationService, ) { super(); @@ -62,6 +63,15 @@ export class TestingDecorations extends Disposable implements IEditorContributio } this.collection.value = this.testService.subscribeToDiffs(ExtHostTestingResource.TextDocument, uri, () => this.setDecorations(uri)); + this._register(this.results.onTestChanged(([, changed]) => { + if (changed.item.location?.uri.toString() === uri.toString()) { + this.setDecorations(uri); + } + })); + this._register(this.results.onResultsChanged(() => { + this.setDecorations(uri); + })); + this.setDecorations(uri); } @@ -74,19 +84,25 @@ export class TestingDecorations extends Disposable implements IEditorContributio this.editor.changeDecorations(accessor => { const newDecorations: ITestDecoration[] = []; for (const test of ref.object.all) { + const stateLookup = this.results.getStateByExtId(test.item.extId); if (hasValidLocation(uri, test.item)) { newDecorations.push(this.instantiationService.createInstance( - RunTestDecoration, test, ref.object, test.item.location, this.editor)); + RunTestDecoration, test, ref.object, test.item.location, this.editor, stateLookup?.[1].computedState)); } - for (let i = 0; i < test.item.state.messages.length; i++) { - const m = test.item.state.messages[i]; + if (!stateLookup) { + continue; + } + + const [result, stateItem] = stateLookup; + for (let i = 0; i < stateItem.state.messages.length; i++) { + const m = stateItem.state.messages[i]; if (hasValidLocation(uri, m)) { const uri = buildTestUri({ - type: TestUriType.LiveMessage, + type: TestUriType.ResultActualOutput, messageIndex: i, - providerId: test.providerId, - testId: test.id, + resultId: result.id, + testId: stateItem.item.extId, }); newDecorations.push(this.instantiationService.createInstance(TestMessageDecoration, m, uri, m.location, this.editor)); @@ -138,7 +154,7 @@ const firstLineRange = (originalRange: IRange) => ({ endColumn: 1, }); -class RunTestDecoration implements ITestDecoration { +class RunTestDecoration extends Disposable implements ITestDecoration { /** * @inheritdoc */ @@ -156,25 +172,16 @@ class RunTestDecoration implements ITestDecoration { private readonly collection: IMainThreadTestCollection, private readonly location: ModeLocation, private readonly editor: ICodeEditor, + computedState: TestRunState | undefined, @ITestService private readonly testService: ITestService, @IContextMenuService private readonly contextMenuService: IContextMenuService, @ICommandService private readonly commandService: ICommandService, ) { + super(); this.line = location.range.startLineNumber; - const queue = [test.children]; - let state = this.test.item.state.runState; - while (queue.length) { - for (const child of queue.pop()!) { - const node = collection.getNodeById(child); - if (node) { - state = maxPriority(node.item.state.runState, state); - } - } - } - - const icon = state !== TestRunState.Unset - ? testingStatesToIcons.get(state)! + const icon = computedState !== undefined && computedState !== TestRunState.Unset + ? testingStatesToIcons.get(computedState)! : test.children.size > 0 ? testingRunAllIcon : testingRunIcon; this.editorDecoration = { diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index f433739f569..81c3e26bf0b 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -5,12 +5,12 @@ import * as dom from 'vs/base/browser/dom'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; +import * as aria from 'vs/base/browser/ui/aria/aria'; import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { DefaultKeyboardNavigationDelegate, IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; import { ITreeEvent, ITreeFilter, ITreeNode, ITreeRenderer, ITreeSorter, TreeFilterResult, TreeVisibility } from 'vs/base/browser/ui/tree/tree'; -import * as aria from 'vs/base/browser/ui/aria/aria'; import { Action, IAction, IActionViewItem } from 'vs/base/common/actions'; import { DeferredPromise } from 'vs/base/common/async'; import { Color, RGBA } from 'vs/base/common/color'; @@ -47,14 +47,10 @@ import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/comm import { ITestTreeElement, ITestTreeProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections'; import { HierarchicalByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation'; import { HierarchicalByNameProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName'; -import { getComputedState } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; -import { StateByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation'; -import { StateByNameProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateByName'; -import { StateElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateNodes'; import { testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons'; import { ITestExplorerFilterState, TestExplorerFilterState, TestingExplorerFilter } from 'vs/workbench/contrib/testing/browser/testingExplorerFilter'; import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browser/testingOutputPeek'; -import { TestExplorerViewGrouping, TestExplorerViewMode, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants'; +import { TestExplorerViewMode, TestExplorerViewSorting, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { cmpPriority, isFailedState } from 'vs/workbench/contrib/testing/common/testingStates'; import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri'; @@ -188,7 +184,7 @@ export class TestingExplorerViewModel extends Disposable { public projection!: ITestTreeProjection; private readonly _viewMode = TestingContextKeys.viewMode.bindTo(this.contextKeyService); - private readonly _viewGrouping = TestingContextKeys.viewGrouping.bindTo(this.contextKeyService); + private readonly _viewSorting = TestingContextKeys.viewSorting.bindTo(this.contextKeyService); /** * Fires when the selected tests change. @@ -210,18 +206,18 @@ export class TestingExplorerViewModel extends Disposable { } - public get viewGrouping() { - return this._viewGrouping.get() ?? TestExplorerViewGrouping.ByLocation; + public get viewSorting() { + return this._viewSorting.get() ?? TestExplorerViewSorting.ByLocation; } - public set viewGrouping(newGrouping: TestExplorerViewGrouping) { - if (newGrouping === this._viewGrouping.get()) { + public set viewSorting(newSorting: TestExplorerViewSorting) { + if (newSorting === this._viewSorting.get()) { return; } - this._viewGrouping.set(newGrouping); - this.updatePreferredProjection(); - this.storageService.store('testing.viewGrouping', newGrouping, StorageScope.WORKSPACE, StorageTarget.USER); + this._viewSorting.set(newSorting); + this.tree.resort(null); + this.storageService.store('testing.viewSorting', newSorting, StorageScope.WORKSPACE, StorageTarget.USER); } constructor( @@ -229,16 +225,17 @@ export class TestingExplorerViewModel extends Disposable { onDidChangeVisibility: Event, private listener: TestSubscriptionListener | undefined, @ITestExplorerFilterState filterState: TestExplorerFilterState, - @IInstantiationService instantiationService: IInstantiationService, + @IInstantiationService private readonly instantiationService: IInstantiationService, @IEditorService private readonly editorService: IEditorService, @ICodeEditorService codeEditorService: ICodeEditorService, @IStorageService private readonly storageService: IStorageService, @IContextKeyService private readonly contextKeyService: IContextKeyService, + @ITestResultService private readonly testResults: ITestResultService, ) { super(); this._viewMode.set(this.storageService.get('testing.viewMode', StorageScope.WORKSPACE, TestExplorerViewMode.Tree) as TestExplorerViewMode); - this._viewGrouping.set(this.storageService.get('testing.viewGrouping', StorageScope.WORKSPACE, TestExplorerViewGrouping.ByLocation) as TestExplorerViewGrouping); + this._viewSorting.set(this.storageService.get('testing.viewSorting', StorageScope.WORKSPACE, TestExplorerViewSorting.ByLocation) as TestExplorerViewSorting); const labels = this._register(instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: onDidChangeVisibility })); @@ -261,7 +258,7 @@ export class TestingExplorerViewModel extends Disposable { simpleKeyboardNavigation: true, identityProvider: instantiationService.createInstance(IdentityProvider), hideTwistiesOfChildlessElements: true, - sorter: instantiationService.createInstance(TreeSorter), + sorter: instantiationService.createInstance(TreeSorter, this), keyboardNavigationLabelProvider: instantiationService.createInstance(TreeKeyboardNavigationLabelProvider), accessibilityProvider: instantiationService.createInstance(ListAccessibilityProvider), filter: this.filter, @@ -293,6 +290,10 @@ export class TestingExplorerViewModel extends Disposable { tracker.deactivate(); } })); + + this._register(testResults.onResultsChanged(() => { + this.tree.resort(null); + })); } /** @@ -380,16 +381,18 @@ export class TestingExplorerViewModel extends Disposable { * Tries to peek the first test error, if the item is in a failed state. */ private async tryPeekError(item: ITestTreeElement) { - if (!item.test || !isFailedState(item.test.item.state.runState)) { + const lookup = item.test && this.testResults.getStateByExtId(item.test.item.extId); + if (!lookup || !isFailedState(lookup[1].state.state)) { return false; } - const index = item.test.item.state.messages.findIndex(m => !!m.location); + const [result, test] = lookup; + const index = test.state.messages.findIndex(m => !!m.location); if (index === -1) { return; } - const message = item.test.item.state.messages[index]; + const message = test.state.messages[index]; const pane = await this.editorService.openEditor({ resource: message.location!.uri, options: { selection: message.location!.range, preserveFocus: true } @@ -401,10 +404,10 @@ export class TestingExplorerViewModel extends Disposable { } TestingOutputPeekController.get(control).show(buildTestUri({ - type: TestUriType.LiveMessage, + type: TestUriType.ResultMessage, messageIndex: index, - providerId: item.test.providerId, - testId: item.test.id, + resultId: result.id, + testId: item.test!.item.extId, })); return true; @@ -417,18 +420,10 @@ export class TestingExplorerViewModel extends Disposable { return; } - if (this._viewGrouping.get() === TestExplorerViewGrouping.ByLocation) { - if (this._viewMode.get() === TestExplorerViewMode.List) { - this.projection = new HierarchicalByNameProjection(this.listener); - } else { - this.projection = new HierarchicalByLocationProjection(this.listener); - } + if (this._viewMode.get() === TestExplorerViewMode.List) { + this.projection = this.instantiationService.createInstance(HierarchicalByNameProjection, this.listener); } else { - if (this._viewMode.get() === TestExplorerViewMode.List) { - this.projection = new StateByNameProjection(this.listener); - } else { - this.projection = new StateByLocationProjection(this.listener); - } + this.projection = this.instantiationService.createInstance(HierarchicalByLocationProjection, this.listener); } this.projection.onUpdate(this.deferUpdate, this); @@ -569,9 +564,19 @@ class TestsFilter implements ITreeFilter { } class TreeSorter implements ITreeSorter { + constructor(private readonly viewModel: TestingExplorerViewModel) { } + public compare(a: ITestTreeElement, b: ITestTreeElement): number { - if (a instanceof StateElement && b instanceof StateElement) { - return cmpPriority(a.computedState, b.computedState); + let delta = cmpPriority(a.state, b.state); + if (delta !== 0) { + return delta; + } + + if (this.viewModel.viewSorting === TestExplorerViewSorting.ByLocation && a.location && b.location && a.location.uri.toString() === b.location.uri.toString()) { + delta = a.location.range.startLineNumber - b.location.range.startLineNumber; + if (delta !== 0) { + return delta; + } } return a.label.localeCompare(b.label); @@ -587,7 +592,7 @@ class ListAccessibilityProvider implements IListAccessibilityProvider class TestRunProgress { private current?: { update: IProgress; deferred: DeferredPromise }; private badge = new MutableDisposable(); - private readonly resultLister = this.resultService.onNewTestResult(result => { + private readonly resultLister = this.resultService.onResultsChanged(result => { + if (!('started' in result)) { + return; + } + this.updateProgress(); this.updateBadge(); - result.onChange(this.throttledProgressUpdate, this); - result.onComplete(() => { + result.started.onChange(this.throttledProgressUpdate, this); + result.started.onComplete(() => { this.throttledProgressUpdate(); this.updateBadge(); }); diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts index 9c2dc7a003c..081c8893ad9 100644 --- a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts +++ b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts @@ -27,15 +27,15 @@ import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeServic import { EditorModel } from 'vs/workbench/common/editor'; import { testingPeekBorder } from 'vs/workbench/contrib/testing/browser/theme'; import { Testing } from 'vs/workbench/contrib/testing/common/constants'; -import { InternalTestItem, ITestMessage } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestItem, ITestMessage, ITestState } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { buildTestUri, parseTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri'; import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; -import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; interface ITestDto { + test: ITestItem, messageIndex: number; - test: InternalTestItem; + state: ITestState; expectedUri: URI; actualUri: URI; messageUri: URI; @@ -66,7 +66,6 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo private readonly editor: ICodeEditor, @IInstantiationService private readonly instantiationService: IInstantiationService, @ITestResultService private readonly testResults: ITestResultService, - @ITestService private readonly testService: ITestService, @IContextKeyService contextKeyService: IContextKeyService, ) { super(); @@ -83,7 +82,7 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo return; } - const message = dto.test.item.state.messages[dto.messageIndex]; + const message = dto.state.messages[dto.messageIndex]; if (!message?.location) { return; } @@ -120,28 +119,14 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo return undefined; } - if ('resultId' in parts) { - const test = this.testResults.lookup(parts.resultId)?.tests.find(t => t.id === parts.testId); - return test && { - test, - messageIndex: parts.messageIndex, - expectedUri: buildTestUri({ ...parts, type: TestUriType.ResultExpectedOutput }), - actualUri: buildTestUri({ ...parts, type: TestUriType.ResultActualOutput }), - messageUri: buildTestUri({ ...parts, type: TestUriType.ResultMessage }), - }; - } - - const test = await this.testService.lookupTest({ providerId: parts.providerId, testId: parts.testId }); - if (!test) { - return; - } - - return { - test, + const test = this.testResults.getResult(parts.resultId)?.getStateByExtId(parts.testId); + return test && { + test: test.item, + state: test.state, messageIndex: parts.messageIndex, - expectedUri: buildTestUri({ ...parts, type: TestUriType.LiveActualOutput }), - actualUri: buildTestUri({ ...parts, type: TestUriType.LiveExpectedOutput }), - messageUri: buildTestUri({ ...parts, type: TestUriType.LiveMessage }), + expectedUri: buildTestUri({ ...parts, type: TestUriType.ResultExpectedOutput }), + actualUri: buildTestUri({ ...parts, type: TestUriType.ResultActualOutput }), + messageUri: buildTestUri({ ...parts, type: TestUriType.ResultMessage }), }; } } @@ -236,14 +221,14 @@ class TestingDiffOutputPeek extends TestingOutputPeek { /** * @override */ - public async setModel({ test, messageIndex, expectedUri, actualUri }: ITestDto) { - const message = test.item.state.messages[messageIndex]; + public async setModel({ test, state, messageIndex, expectedUri, actualUri }: ITestDto) { + const message = state.messages[messageIndex]; if (!message?.location) { return; } this.show(message.location.range, hintDiffPeekHeight(message)); - this.setTitle(message.message.toString(), test.item.label); + this.setTitle(message.message.toString(), test.label); const [original, modified] = await Promise.all([ this.modelService.createModelReference(expectedUri), @@ -285,14 +270,14 @@ class TestingMessageOutputPeek extends TestingOutputPeek { /** * @override */ - public async setModel({ test, messageIndex, messageUri }: ITestDto) { - const message = test.item.state.messages[messageIndex]; + public async setModel({ state, test, messageIndex, messageUri }: ITestDto) { + const message = state.messages[messageIndex]; if (!message?.location) { return; } this.show(message.location.range, hintPeekStrHeight(message.message.toString())); - this.setTitle(message.message.toString(), test.item.label); + this.setTitle(message.message.toString(), test.label); const modelRef = this.model.value = await this.modelService.createModelReference(messageUri); if (this.preview.value) { diff --git a/src/vs/workbench/contrib/testing/common/constants.ts b/src/vs/workbench/contrib/testing/common/constants.ts index d828393d01c..817cef54b7e 100644 --- a/src/vs/workbench/contrib/testing/common/constants.ts +++ b/src/vs/workbench/contrib/testing/common/constants.ts @@ -20,9 +20,9 @@ export const enum TestExplorerViewMode { Tree = 'true' } -export const enum TestExplorerViewGrouping { +export const enum TestExplorerViewSorting { ByLocation = 'location', - ByStatus = 'status', + ByName = 'name', } export const testStateNames: { [K in TestRunState]: string } = { diff --git a/src/vs/workbench/contrib/testing/common/getComputedState.ts b/src/vs/workbench/contrib/testing/common/getComputedState.ts new file mode 100644 index 00000000000..e8bb0d16a2c --- /dev/null +++ b/src/vs/workbench/contrib/testing/common/getComputedState.ts @@ -0,0 +1,84 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; +import { maxPriority, statePriority } from 'vs/workbench/contrib/testing/common/testingStates'; + +/** + * Accessor for nodes in get and refresh computed state. + */ +export interface IComputedStateAccessor { + getOwnState(item: T): TestRunState | undefined; + getCurrentComputedState(item: T): TestRunState; + setComputedState(item: T, state: TestRunState): void; + getChildren(item: T): IterableIterator; + getParents(item: T): IterableIterator; +} + +/** + * Gets the computed state for the node. + * @param force whether to refresh the computed state for this node, even + * if it was previously set. + */ + +export const getComputedState = (accessor: IComputedStateAccessor, node: T, force = false) => { + let computed = accessor.getCurrentComputedState(node); + if (computed === undefined || force) { + computed = accessor.getOwnState(node) ?? TestRunState.Unset; + for (const child of accessor.getChildren(node)) { + computed = maxPriority(computed, getComputedState(accessor, child)); + } + + accessor.setComputedState(node, computed); + } + + return computed; +}; +/** + * Refreshes the computed state for the node and its parents. Any changes + * elements cause `addUpdated` to be called. + */ + +export const refreshComputedState = ( + accessor: IComputedStateAccessor, + node: T, + addUpdated: (node: T) => void, + explicitNewComputedState?: TestRunState, +) => { + const oldState = accessor.getCurrentComputedState(node); + const oldPriority = statePriority[oldState]; + const newState = explicitNewComputedState ?? getComputedState(accessor, node, true); + const newPriority = statePriority[newState]; + if (newPriority === oldPriority) { + return; + } + + accessor.setComputedState(node, newState); + addUpdated(node); + + if (newPriority > oldPriority) { + // Update all parents to ensure they're at least this priority. + for (const parent of accessor.getParents(node)) { + const prev = accessor.getCurrentComputedState(parent); + if (prev !== undefined && statePriority[prev] >= newPriority) { + break; + } + + accessor.setComputedState(parent, newState); + addUpdated(parent); + } + } else if (newPriority < oldPriority) { + // Re-render all parents of this node whose computed priority might have come from this node + for (const parent of accessor.getParents(node)) { + const prev = accessor.getCurrentComputedState(parent); + if (prev === undefined || statePriority[prev] > oldPriority) { + break; + } + + accessor.setComputedState(parent, getComputedState(accessor, parent, true)); + addUpdated(parent); + } + } +}; diff --git a/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts b/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts index 41f4c891fc0..c997e237d7a 100644 --- a/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts +++ b/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts @@ -204,7 +204,6 @@ const keyMap: { [K in keyof Omit]: null } = { id: null, label: null, location: null, - state: null, debuggable: null, description: null, runnable: null diff --git a/src/vs/workbench/contrib/testing/common/testCollection.ts b/src/vs/workbench/contrib/testing/common/testCollection.ts index 566146dc027..8ceb490a2dc 100644 --- a/src/vs/workbench/contrib/testing/common/testCollection.ts +++ b/src/vs/workbench/contrib/testing/common/testCollection.ts @@ -26,24 +26,12 @@ export interface RunTestsRequest { * Request from the main thread to run tests for a single provider. */ export interface RunTestForProviderRequest { + runId: string; providerId: string; ids: string[]; debug: boolean; } -/** - * Response to a {@link RunTestsRequest} - */ -export interface RunTestsResult { - // todo -} - -export const EMPTY_TEST_RESULT: RunTestsResult = {}; - -export const collectTestResults = (results: ReadonlyArray) => { - return results[0] || {}; // todo -}; - export interface ITestMessage { message: string | IMarkdownString; severity: TestMessageSeverity | undefined; @@ -53,7 +41,7 @@ export interface ITestMessage { } export interface ITestState { - runState: TestRunState; + state: TestRunState; duration: number | undefined; messages: ITestMessage[]; } @@ -70,7 +58,6 @@ export interface ITestItem { description: string | undefined; runnable: boolean; debuggable: boolean; - state: ITestState; } /** @@ -84,7 +71,7 @@ export interface InternalTestItem { } export interface InternalTestItemWithChildren extends InternalTestItem { - children: InternalTestItemWithChildren[]; + children: this[]; } export interface InternalTestResults { diff --git a/src/vs/workbench/contrib/testing/common/testResultService.ts b/src/vs/workbench/contrib/testing/common/testResultService.ts index 992081d3a77..702630e8390 100644 --- a/src/vs/workbench/contrib/testing/common/testResultService.ts +++ b/src/vs/workbench/contrib/testing/common/testResultService.ts @@ -4,17 +4,52 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from 'vs/base/common/event'; +import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { TestRunState } from 'vs/workbench/api/common/extHostTypes'; -import { IncrementalTestCollectionItem, InternalTestItemWithChildren, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; +import { IComputedStateAccessor, refreshComputedState } from 'vs/workbench/contrib/testing/common/getComputedState'; +import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue'; +import { IncrementalTestCollectionItem, ITestState, TestIdWithProvider } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; -import { isRunningState, statesInOrder } from 'vs/workbench/contrib/testing/common/testingStates'; +import { statesInOrder } from 'vs/workbench/contrib/testing/common/testingStates'; import { IMainThreadTestCollection } from 'vs/workbench/contrib/testing/common/testService'; +/** + * Count of the number of tests in each run state. + */ export type TestStateCount = { [K in TestRunState]: number }; +export interface ITestResult { + /** + * Count of the number of tests in each run state. + */ + readonly counts: Readonly; + + /** + * Unique ID of this set of test results. + */ + readonly id: string; + + /** + * Gets whether the test run has finished. + */ + readonly isComplete: boolean; + + /** + * Gets the state of the test by its extension-assigned ID. + */ + getStateByExtId(testExtId: string): TestResultItem | undefined; + + /** + * Serializes the test result. Used to save and restore results + * in the workspace. + */ + toJSON(): ISerializedResults; +} + const makeEmptyCounts = () => { const o: Partial = {}; for (const state of statesInOrder) { @@ -24,7 +59,7 @@ const makeEmptyCounts = () => { return o as TestStateCount; }; -export const sumCounts = (counts: TestStateCount[]) => { +export const sumCounts = (counts: Iterable) => { const total = makeEmptyCounts(); for (const count of counts) { for (const state of statesInOrder) { @@ -35,28 +70,97 @@ export const sumCounts = (counts: TestStateCount[]) => { return total; }; -const makeNode = ( +const queuedState: ITestState = { + duration: undefined, + messages: [], + state: TestRunState.Queued +}; + +const unsetState: ITestState = { + duration: undefined, + messages: [], + state: TestRunState.Unset +}; + +const itemToNode = ( + item: IncrementalTestCollectionItem, + byExtId: Map, + byInternalId: Map, +): TestResultItem => { + const n: TestResultItem = { + ...item, + // shallow-clone the test to take a 'snapshot' of it at the point in time where tests run + item: { ...item.item }, + state: unsetState, + computedState: TestRunState.Unset, + }; + + byExtId.set(n.item.extId, n); + byInternalId.set(n.id, n); + + return n; +}; + +const makeParents = ( + collection: IMainThreadTestCollection, + child: IncrementalTestCollectionItem, + byExtId: Map, + byInternalId: Map, +) => { + const parent = child.parent && collection.getNodeById(child.parent); + if (!parent) { + return; + } + + let parentResultItem = byInternalId.get(parent.id); + if (parentResultItem) { + parentResultItem.children.add(child.id); + return; // no need to recurse, all parents already in result + } + + parentResultItem = itemToNode(parent, byExtId, byInternalId); + parentResultItem.children = new Set([child.id]); + makeParents(collection, parent, byExtId, byInternalId); +}; + +const makeNodeAndChildren = ( collection: IMainThreadTestCollection, test: IncrementalTestCollectionItem, + byExtId: Map, + byInternalId: Map, ): TestResultItem => { - const mapped: TestResultItem = { ...test, children: [] }; + const existing = byInternalId.get(test.id); + if (existing) { + return existing; + } + + const mapped = itemToNode(test, byExtId, byInternalId); for (const childId of test.children) { const child = collection.getNodeById(childId); if (child) { - mapped.children.push(makeNode(collection, child)); + makeNodeAndChildren(collection, child, byExtId, byInternalId); } } return mapped; }; -export interface TestResultItem extends InternalTestItemWithChildren { } +interface ISerializedResults { + id: string; + counts: TestStateCount; + items: Iterable<[extId: string, item: TestResultItem]>; +} + +interface TestResultItem extends IncrementalTestCollectionItem { + state: ITestState; + computedState: TestRunState; +} /** * Results of a test. These are created when the test initially started running * and marked as "complete" when the run finishes. */ -export class TestResult { +export class LiveTestResult implements ITestResult { /** * Creates a new TestResult, pulling tests from the associated list * of collections. @@ -65,27 +169,29 @@ export class TestResult { collections: ReadonlyArray, tests: ReadonlyArray, ) { - const mapped: TestResultItem[] = []; + const testByExtId = new Map(); + const testByInternalId = new Map(); for (const test of tests) { for (const collection of collections) { const node = collection.getNodeById(test.testId); - if (node) { - mapped.push(makeNode(collection, node)); - break; + if (!node) { + continue; } + + makeNodeAndChildren(collection, node, testByExtId, testByInternalId); + makeParents(collection, node, testByExtId, testByInternalId); } } - return new TestResult(mapped); + return new LiveTestResult(collections, testByExtId, testByInternalId); } - private completeEmitter = new Emitter(); - private changeEmitter = new Emitter(); + private readonly completeEmitter = new Emitter(); + private readonly changeEmitter = new Emitter(); private _complete = false; - private _cachedCounts?: { [K in TestRunState]: number }; - public onChange = this.changeEmitter.event; - public onComplete = this.completeEmitter.event; + public readonly onChange = this.changeEmitter.event; + public readonly onComplete = this.completeEmitter.event; /** * Unique ID for referring to this set of test results. @@ -93,34 +199,122 @@ export class TestResult { public readonly id = generateUuid(); /** - * Gets whether the test run has finished. + * @inheritdoc */ public get isComplete() { return this._complete; } /** - * Gets a count of tests in each state. + * @inheritdoc */ - public get counts() { - if (this._cachedCounts) { - return this._cachedCounts; - } + public readonly counts: { [K in TestRunState]: number } = makeEmptyCounts(); - const counts = makeEmptyCounts(); - this.forEachTest(({ item }) => { - counts[item.state.runState]++; - }); - - if (this._complete) { - this._cachedCounts = counts; - } - - return counts; + /** + * Gets all tests involved in the run by ID. + */ + public get tests() { + return this.testByInternalId.values(); } - constructor(public readonly tests: TestResultItem[]) { } + private readonly computedStateAccessor: IComputedStateAccessor = { + getOwnState: i => i.state.state, + getCurrentComputedState: i => i.computedState, + setComputedState: (i, s) => i.computedState = s, + getChildren: i => { + const { testByInternalId } = this; + return (function* () { + for (const childId of i.children) { + const child = testByInternalId.get(childId); + if (child) { + yield child; + } + } + })(); + }, + getParents: i => { + const { testByInternalId } = this; + return (function* () { + for (let parentId = i.parent; parentId;) { + const parent = testByInternalId.get(parentId); + if (!parent) { + break; + } + yield parent; + parentId = parent.parent; + } + })(); + }, + }; + + constructor( + private readonly collections: ReadonlyArray, + private readonly testByExtId: Map, + private readonly testByInternalId: Map, + ) { + this.counts[TestRunState.Unset] = testByInternalId.size; + } + + /** + * @inheritdoc + */ + public getStateByExtId(extTestId: string) { + return this.testByExtId.get(extTestId); + } + + /** + * Updates all tests in the collection to the given state. + */ + public setAllToState(state: ITestState, when: (_t: TestResultItem) => boolean) { + for (const test of this.testByInternalId.values()) { + if (when(test)) { + this.counts[state.state]--; + test.state = state; + this.counts[state.state]++; + refreshComputedState(this.computedStateAccessor, test, t => this.changeEmitter.fire(t)); + } + } + } + + /** + * Updates the state of the test by its internal ID. + */ + public updateState(testId: string, state: ITestState) { + let entry = this.testByInternalId.get(testId); + if (!entry) { + entry = this.addTestToRun(testId); + } + if (!entry) { + return; + } + + if (state.state === entry.state.state) { + entry.state = state; + this.changeEmitter.fire(entry); + } else { + this.counts[entry.state.state]--; + entry.state = state; + this.counts[entry.state.state]++; + refreshComputedState(this.computedStateAccessor, entry, t => this.changeEmitter.fire(t)); + } + } + + /** + * Adds a test, by its ID, to the test run. This can end up being called + * if tests were started while discovery was still happening, so initially + * we didn't serialize/capture the test. + */ + private addTestToRun(testId: string) { + for (const collection of this.collections) { + let test = collection.getNodeById(testId); + if (test) { + return makeNodeAndChildren(collection, test, this.testByExtId, this.testByInternalId); + } + } + + return undefined; + } /** * Notifies the service that all tests are complete. @@ -130,109 +324,209 @@ export class TestResult { throw new Error('cannot complete a test result multiple times'); } - // shallow clone test items to 'disconnect' them from the underlying - // connection and stop state changes. Also, marked any still-running - // tests as skipped. - this.forEachTest(test => { - test.item = { ...test.item }; - if (isRunningState(test.item.state.runState)) { - test.item.state = { ...test.item.state, runState: TestRunState.Skipped }; - } - }); - + // un-queue any tests that weren't explicitly updated + this.setAllToState(unsetState, t => t.state.state === TestRunState.Queued); this._complete = true; this.completeEmitter.fire(); } /** - * Fires the 'change' event, should be called by the runner. + * @inheritdoc */ - public notifyChanged() { - this.changeEmitter.fire(); - } - - private forEachTest(fn: (test: TestResultItem) => void) { - const queue = [this.tests]; - while (queue.length) { - for (const test of queue.pop()!) { - fn(test); - queue.push(test.children); - } - } + public toJSON(): ISerializedResults { + return { id: this.id, counts: this.counts, items: [...this.testByExtId.entries()] }; } } +/** + * Test results hydrated from a previously-serialized test run. + */ +class HydratedTestResult implements ITestResult { + /** + * @inheritdoc + */ + public readonly counts = this.serialized.counts; + + /** + * @inheritdoc + */ + public readonly id = this.serialized.id; + + /** + * @inheritdoc + */ + public readonly isComplete = true; + + private readonly map = new Map(); + + constructor(private readonly serialized: ISerializedResults) { + for (const [key, value] of serialized.items) { + this.map.set(key, value); + + for (const message of value.state.messages) { + if (message.location) { + message.location.uri = URI.revive(message.location.uri); + } + } + } + } + + /** + * @inheritdoc + */ + public getStateByExtId(extTestId: string) { + return this.map.get(extTestId); + } + + /** + * @inheritdoc + */ + public toJSON(): ISerializedResults { + return this.serialized; + } +} + +export type ResultChangeEvent = + | { completed: LiveTestResult } + | { started: LiveTestResult } + | { removed: ITestResult[] }; + export interface ITestResultService { readonly _serviceBrand: undefined; + /** + * Fired after any results are added, removed, or completed. + */ + readonly onResultsChanged: Event; /** - * List of test results. Currently running tests are always at the top. + * Fired when a test changed it state, or its computed state is updated. */ - readonly results: TestResult[]; + readonly onTestChanged: Event<[results: ITestResult, item: TestResultItem]>; /** - * Fired after a new event is added to the 'active' array. + * List of known test results. */ - readonly onNewTestResult: Event; + readonly results: ReadonlyArray; + + /** + * Discards all completed test results. + */ + clear(): void; /** * Adds a new test result to the collection. */ - push(result: TestResult): TestResult; + push(result: LiveTestResult): LiveTestResult; /** * Looks up a set of test results by ID. */ - lookup(resultId: string): TestResult | undefined; + getResult(resultId: string): ITestResult | undefined; + + /** + * Looks up a test's most recent state, by its extension-assigned ID. + */ + getStateByExtId(extId: string): [results: ITestResult, item: TestResultItem] | undefined; } export const ITestResultService = createDecorator('testResultService'); -const RETAIN_LAST_RESULTS = 16; +const RETAIN_LAST_RESULTS = 64; export class TestResultService implements ITestResultService { declare _serviceBrand: undefined; - private newResultEmitter = new Emitter(); + private changeResultEmitter = new Emitter(); + private testChangeEmitter = new Emitter<[results: ITestResult, item: TestResultItem]>(); /** * @inheritdoc */ - public results: TestResult[] = []; + public results: ITestResult[] = []; /** * @inheritdoc */ - public readonly onNewTestResult = this.newResultEmitter.event; + public readonly onResultsChanged = this.changeResultEmitter.event; + + /** + * @inheritdoc + */ + public readonly onTestChanged = this.testChangeEmitter.event; private readonly isRunning: IContextKey; + private readonly serializedResults: StoredValue; - constructor(@IContextKeyService contextKeyService: IContextKeyService) { + constructor(@IContextKeyService contextKeyService: IContextKeyService, @IStorageService storage: IStorageService) { this.isRunning = TestingContextKeys.isRunning.bindTo(contextKeyService); + this.serializedResults = new StoredValue({ + key: 'testResults', + scope: StorageScope.WORKSPACE, + target: StorageTarget.MACHINE + }, storage); + + for (const value of this.serializedResults.get([])) { + this.results.push(new HydratedTestResult(value)); + } } /** * @inheritdoc */ - public push(result: TestResult): TestResult { + public getStateByExtId(extId: string): [results: ITestResult, item: TestResultItem] | undefined { + for (const result of this.results) { + const lookup = result.getStateByExtId(extId); + if (lookup && lookup.computedState !== TestRunState.Unset) { + return [result, lookup]; + } + } + + return undefined; + } + + /** + * @inheritdoc + */ + public push(result: LiveTestResult): LiveTestResult { this.results.unshift(result); if (this.results.length > RETAIN_LAST_RESULTS) { this.results.pop(); } - result.onComplete(this.onComplete, this); + result.onComplete(() => this.onComplete(result)); + result.onChange(t => this.testChangeEmitter.fire([result, t]), this.testChangeEmitter); this.isRunning.set(true); - this.newResultEmitter.fire(result); + this.changeResultEmitter.fire({ started: result }); + result.setAllToState(queuedState, () => true); return result; } /** * @inheritdoc */ - public lookup(id: string) { + public getResult(id: string) { return this.results.find(r => r.id === id); } - private onComplete() { + /** + * @inheritdoc + */ + public clear() { + const keep: ITestResult[] = []; + const removed: ITestResult[] = []; + for (const result of this.results) { + if (result.isComplete) { + removed.push(result); + } else { + keep.push(result); + } + } + + this.results = keep; + this.serializedResults.store(this.results.map(r => r.toJSON())); + this.changeResultEmitter.fire({ removed }); + } + + private onComplete(result: LiveTestResult) { // move the complete test run down behind any still-running ones for (let i = 0; i < this.results.length - 2; i++) { if (this.results[i].isComplete && !this.results[i + 1].isComplete) { @@ -241,5 +535,7 @@ export class TestResultService implements ITestResultService { } this.isRunning.set(!this.results[0]?.isComplete); + this.serializedResults.store(this.results.map(r => r.toJSON())); + this.changeResultEmitter.fire({ completed: result }); } } diff --git a/src/vs/workbench/contrib/testing/common/testService.ts b/src/vs/workbench/contrib/testing/common/testService.ts index d9fbf494aad..61639ba1874 100644 --- a/src/vs/workbench/contrib/testing/common/testService.ts +++ b/src/vs/workbench/contrib/testing/common/testService.ts @@ -9,13 +9,14 @@ import { IDisposable, IReference } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; -import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsRequest, RunTestsResult, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsRequest, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestResult } from 'vs/workbench/contrib/testing/common/testResultService'; export const ITestService = createDecorator('testService'); export interface MainTestController { lookupTest(test: TestIdWithProvider): Promise; - runTests(request: RunTestForProviderRequest, token: CancellationToken): Promise; + runTests(request: RunTestForProviderRequest, token: CancellationToken): Promise; } export type TestDiffListener = (diff: TestsDiff) => void; @@ -84,7 +85,7 @@ export interface ITestService { registerTestController(id: string, controller: MainTestController): void; unregisterTestController(id: string): void; - runTests(req: RunTestsRequest, token?: CancellationToken): Promise; + runTests(req: RunTestsRequest, token?: CancellationToken): Promise; cancelTestRun(req: RunTestsRequest): void; publishDiff(resource: ExtHostTestingResource, uri: URI, diff: TestsDiff): void; subscribeToDiffs(resource: ExtHostTestingResource, uri: URI, acceptDiff?: TestDiffListener): IReference; diff --git a/src/vs/workbench/contrib/testing/common/testServiceImpl.ts b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts index 7ff73345c35..8a18a20daa5 100644 --- a/src/vs/workbench/contrib/testing/common/testServiceImpl.ts +++ b/src/vs/workbench/contrib/testing/common/testServiceImpl.ts @@ -8,15 +8,14 @@ import { disposableTimeout } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, IReference } from 'vs/base/common/lifecycle'; -import { isDefined } from 'vs/base/common/types'; import { URI, UriComponents } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ExtHostTestingResource } from 'vs/workbench/api/common/extHost.protocol'; -import { AbstractIncrementalTestCollection, collectTestResults, EMPTY_TEST_RESULT, getTestSubscriptionKey, IncrementalTestCollectionItem, InternalTestItem, RunTestsRequest, RunTestsResult, TestDiffOpType, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { AbstractIncrementalTestCollection, getTestSubscriptionKey, IncrementalTestCollectionItem, InternalTestItem, RunTestsRequest, TestDiffOpType, TestIdWithProvider, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; -import { ITestResultService, TestResult } from 'vs/workbench/contrib/testing/common/testResultService'; +import { ITestResult, ITestResultService, LiveTestResult } from 'vs/workbench/contrib/testing/common/testResultService'; import { IMainThreadTestCollection, ITestService, MainTestController, TestDiffListener } from 'vs/workbench/contrib/testing/common/testService'; type TestLocationIdent = { resource: ExtHostTestingResource, uri: URI }; @@ -40,14 +39,9 @@ export class TestService extends Disposable implements ITestService { private readonly busyStateChangeEmitter = new Emitter(); private readonly changeProvidersEmitter = new Emitter<{ delta: number }>(); private readonly providerCount: IContextKey; - private readonly runStartedEmitter = new Emitter(); - private readonly runCompletedEmitter = new Emitter<{ req: RunTestsRequest, result: RunTestsResult }>(); private readonly runningTests = new Map(); private rootProviderCount = 0; - public readonly onTestRunStarted = this.runStartedEmitter.event; - public readonly onTestRunCompleted = this.runCompletedEmitter.event; - constructor(@IContextKeyService contextKeyService: IContextKeyService, @INotificationService private readonly notificationService: INotificationService, @ITestResultService private readonly testResults: ITestResultService) { super(); this.providerCount = TestingContextKeys.providerCount.bindTo(contextKeyService); @@ -126,35 +120,32 @@ export class TestService extends Disposable implements ITestService { /** * @inheritdoc */ - public async runTests(req: RunTestsRequest, token = CancellationToken.None): Promise { - let result: TestResult | undefined; + public async runTests(req: RunTestsRequest, token = CancellationToken.None): Promise { const subscriptions = [...this.testSubscriptions.values()] .filter(v => req.tests.some(t => v.collection.getNodeById(t.testId))) - .map(s => this.subscribeToDiffs(s.ident.resource, s.ident.uri, () => result?.notifyChanged())); - result = this.testResults.push(TestResult.from(subscriptions.map(s => s.object), req.tests)); + .map(s => this.subscribeToDiffs(s.ident.resource, s.ident.uri)); + const result = this.testResults.push(LiveTestResult.from(subscriptions.map(s => s.object), req.tests)); try { const tests = groupBy(req.tests, (a, b) => a.providerId === b.providerId ? 0 : 1); const cancelSource = new CancellationTokenSource(token); + this.runningTests.set(req, cancelSource); + const requests = tests.map(group => { const providerId = group[0].providerId; const controller = this.testControllers.get(providerId); - return controller?.runTests({ providerId, debug: req.debug, ids: group.map(t => t.testId) }, cancelSource.token).catch(err => { + return controller?.runTests( + { runId: result.id, providerId, debug: req.debug, ids: group.map(t => t.testId) }, + cancelSource.token, + ).catch(err => { this.notificationService.error(localize('testError', 'An error occurred attempting to run tests: {0}', err.message)); - return EMPTY_TEST_RESULT; }); - }).filter(isDefined); - - if (requests.length === 0) { - return EMPTY_TEST_RESULT; - } - - this.runningTests.set(req, cancelSource); - const result = collectTestResults(await Promise.all(requests)); - this.runningTests.delete(req); + }); + await Promise.all(requests); return result; } finally { + this.runningTests.delete(req); subscriptions.forEach(s => s.dispose()); result.markComplete(); } diff --git a/src/vs/workbench/contrib/testing/common/testStubs.ts b/src/vs/workbench/contrib/testing/common/testStubs.ts index 33a9b5295ad..e1d61278a1f 100644 --- a/src/vs/workbench/contrib/testing/common/testStubs.ts +++ b/src/vs/workbench/contrib/testing/common/testStubs.ts @@ -3,12 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TestItem, TestRunState, TestState } from 'vs/workbench/api/common/extHostTypes'; +import { TestItem, TestRunState } from 'vs/workbench/api/common/extHostTypes'; export const stubTest = (label: string): TestItem => ({ label, location: undefined, - state: new TestState(TestRunState.Unset), debuggable: true, runnable: true, description: '' diff --git a/src/vs/workbench/contrib/testing/common/testingContentProvider.ts b/src/vs/workbench/contrib/testing/common/testingContentProvider.ts index e03a0659ef5..c63a507d15f 100644 --- a/src/vs/workbench/contrib/testing/common/testingContentProvider.ts +++ b/src/vs/workbench/contrib/testing/common/testingContentProvider.ts @@ -10,7 +10,6 @@ import { ITextModelContentProvider, ITextModelService } from 'vs/editor/common/s import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { parseTestUri, TestUriType, TEST_DATA_SCHEME } from 'vs/workbench/contrib/testing/common/testingUri'; import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; -import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; /** * A content provider that returns various outputs for tests. This is used @@ -20,8 +19,7 @@ export class TestingContentProvider implements IWorkbenchContribution, ITextMode constructor( @ITextModelService textModelResolverService: ITextModelService, @IModelService private readonly modelService: IModelService, - @ITestService private readonly testService: ITestService, - @ITestService private readonly resultService: ITestResultService, + @ITestResultService private readonly resultService: ITestResultService, ) { textModelResolverService.registerTextModelContentProvider(TEST_DATA_SCHEME, this); } @@ -40,9 +38,7 @@ export class TestingContentProvider implements IWorkbenchContribution, ITextMode return null; } - const test = 'providerId' in parsed - ? await this.testService.lookupTest({ providerId: parsed.providerId, testId: parsed.testId }) - : this.resultService.lookup(parsed.resultId)?.tests.find(t => t.id === parsed.testId); + const test = this.resultService.getResult(parsed.resultId)?.getStateByExtId(parsed.testId); if (!test) { return null; @@ -51,16 +47,13 @@ export class TestingContentProvider implements IWorkbenchContribution, ITextMode let text: string | undefined; switch (parsed.type) { case TestUriType.ResultActualOutput: - case TestUriType.LiveActualOutput: - text = test.item.state.messages[parsed.messageIndex]?.actualOutput; + text = test.state.messages[parsed.messageIndex]?.actualOutput; break; case TestUriType.ResultExpectedOutput: - case TestUriType.LiveExpectedOutput: - text = test.item.state.messages[parsed.messageIndex]?.expectedOutput; + text = test.state.messages[parsed.messageIndex]?.expectedOutput; break; case TestUriType.ResultMessage: - case TestUriType.LiveMessage: - text = test.item.state.messages[parsed.messageIndex]?.message.toString(); + text = test.state.messages[parsed.messageIndex]?.message.toString(); break; } diff --git a/src/vs/workbench/contrib/testing/common/testingContextKeys.ts b/src/vs/workbench/contrib/testing/common/testingContextKeys.ts index 64c192351d7..a7cbbb57a0e 100644 --- a/src/vs/workbench/contrib/testing/common/testingContextKeys.ts +++ b/src/vs/workbench/contrib/testing/common/testingContextKeys.ts @@ -5,12 +5,12 @@ import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ViewContainerLocation } from 'vs/workbench/common/views'; -import { TestExplorerViewMode, TestExplorerViewGrouping } from 'vs/workbench/contrib/testing/common/constants'; +import { TestExplorerViewMode, TestExplorerViewSorting } from 'vs/workbench/contrib/testing/common/constants'; export namespace TestingContextKeys { export const providerCount = new RawContextKey('testing.providerCount', 0); export const viewMode = new RawContextKey('testing.explorerViewMode', TestExplorerViewMode.List); - export const viewGrouping = new RawContextKey('testing.explorerViewGrouping', TestExplorerViewGrouping.ByLocation); + export const viewSorting = new RawContextKey('testing.explorerViewSorting', TestExplorerViewSorting.ByLocation); export const isRunning = new RawContextKey('testing.isRunning', false); export const isInPeek = new RawContextKey('testing.isInPeek', true); export const isPeekVisible = new RawContextKey('testing.isPeekVisible', false); diff --git a/src/vs/workbench/contrib/testing/common/testingStates.ts b/src/vs/workbench/contrib/testing/common/testingStates.ts index 59aa0b93b17..f7eef7b5e45 100644 --- a/src/vs/workbench/contrib/testing/common/testingStates.ts +++ b/src/vs/workbench/contrib/testing/common/testingStates.ts @@ -14,12 +14,12 @@ export type TreeStateNode = { statusNode: true; state: TestRunState; priority: n */ export const statePriority: { [K in TestRunState]: number } = { [TestRunState.Running]: 6, - [TestRunState.Queued]: 5, - [TestRunState.Errored]: 4, - [TestRunState.Failed]: 3, - [TestRunState.Passed]: 2, - [TestRunState.Skipped]: 1, - [TestRunState.Unset]: 0, + [TestRunState.Errored]: 5, + [TestRunState.Failed]: 4, + [TestRunState.Passed]: 3, + [TestRunState.Queued]: 2, + [TestRunState.Unset]: 1, + [TestRunState.Skipped]: 0, }; export const isFailedState = (s: TestRunState) => s === TestRunState.Errored || s === TestRunState.Failed; diff --git a/src/vs/workbench/contrib/testing/common/testingUri.ts b/src/vs/workbench/contrib/testing/common/testingUri.ts index e66995a46cf..5f99df72ba0 100644 --- a/src/vs/workbench/contrib/testing/common/testingUri.ts +++ b/src/vs/workbench/contrib/testing/common/testingUri.ts @@ -8,29 +8,11 @@ import { URI } from 'vs/base/common/uri'; export const TEST_DATA_SCHEME = 'vscode-test-data'; export const enum TestUriType { - LiveMessage, - LiveActualOutput, - LiveExpectedOutput, ResultMessage, ResultActualOutput, ResultExpectedOutput, } -interface ILiveTestUri { - providerId: string; - testId: string; -} - -interface ILiveTestMessageReference extends ILiveTestUri { - type: TestUriType.LiveMessage; - messageIndex: number; -} - -interface ILiveTestOutputReference extends ILiveTestUri { - type: TestUriType.LiveActualOutput | TestUriType.LiveExpectedOutput; - messageIndex: number; -} - interface IResultTestUri { resultId: string; testId: string; @@ -48,13 +30,10 @@ interface IResultTestOutputReference extends IResultTestUri { export type ParsedTestUri = | IResultTestMessageReference - | IResultTestOutputReference - | ILiveTestMessageReference - | ILiveTestOutputReference; + | IResultTestOutputReference; const enum TestUriParts { Results = 'results', - Live = 'live', Messages = 'message', Text = 'text', @@ -78,15 +57,6 @@ export const parseTestUri = (uri: URI): ParsedTestUri | undefined => { case TestUriParts.ExpectedOutput: return { resultId: locationId, testId, messageIndex: index, type: TestUriType.ResultExpectedOutput }; } - } else if (type === TestUriParts.Live) { - switch (part) { - case TestUriParts.Text: - return { providerId: locationId, testId, messageIndex: index, type: TestUriType.LiveMessage }; - case TestUriParts.ActualOutput: - return { providerId: locationId, testId, messageIndex: index, type: TestUriType.LiveActualOutput }; - case TestUriParts.ExpectedOutput: - return { providerId: locationId, testId, messageIndex: index, type: TestUriType.LiveExpectedOutput }; - } } } @@ -96,7 +66,7 @@ export const parseTestUri = (uri: URI): ParsedTestUri | undefined => { export const buildTestUri = (parsed: ParsedTestUri): URI => { const uriParts = { scheme: TEST_DATA_SCHEME, - authority: 'resultId' in parsed ? TestUriParts.Results : TestUriParts.Live + authority: TestUriParts.Results }; const msgRef = (locationId: string, index: number, ...remaining: string[]) => URI.from({ @@ -111,12 +81,6 @@ export const buildTestUri = (parsed: ParsedTestUri): URI => { return msgRef(parsed.resultId, parsed.messageIndex, TestUriParts.ExpectedOutput); case TestUriType.ResultMessage: return msgRef(parsed.resultId, parsed.messageIndex, TestUriParts.Text); - case TestUriType.LiveActualOutput: - return msgRef(parsed.providerId, parsed.messageIndex, TestUriParts.ActualOutput); - case TestUriType.LiveExpectedOutput: - return msgRef(parsed.providerId, parsed.messageIndex, TestUriParts.ExpectedOutput); - case TestUriType.LiveMessage: - return msgRef(parsed.providerId, parsed.messageIndex, TestUriParts.Text); default: throw new Error('Invalid test uri'); } diff --git a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts index 3975417f6c3..343ac3cdecf 100644 --- a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts +++ b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts @@ -13,7 +13,11 @@ suite('Workbench - Testing Explorer Hierarchal by Location Projection', () => { const folder1 = makeTestWorkspaceFolder('f1'); const folder2 = makeTestWorkspaceFolder('f2'); setup(() => { - harness = new TestTreeTestHarness(l => new HierarchicalByLocationProjection(l)); + harness = new TestTreeTestHarness(l => new HierarchicalByLocationProjection(l, { + onResultsChanged: () => undefined, + onTestChanged: () => undefined, + getStateByExtId: () => ({ state: { state: 0 }, computedState: 0 }), + } as any)); }); teardown(() => { diff --git a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts index b699c910290..c08d3eaf637 100644 --- a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts +++ b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts @@ -13,7 +13,11 @@ suite('Workbench - Testing Explorer Hierarchal by Name Projection', () => { const folder1 = makeTestWorkspaceFolder('f1'); const folder2 = makeTestWorkspaceFolder('f2'); setup(() => { - harness = new TestTreeTestHarness(l => new HierarchicalByNameProjection(l)); + harness = new TestTreeTestHarness(l => new HierarchicalByNameProjection(l, { + onResultsChanged: () => undefined, + onTestChanged: () => undefined, + getStateByExtId: () => ({ state: { state: 0 }, computedState: 0 }), + } as any)); }); teardown(() => { diff --git a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/stateByLocation.test.ts b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/stateByLocation.test.ts deleted file mode 100644 index 8472bd48c4d..00000000000 --- a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/stateByLocation.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { StateByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateByLocation'; -import { ReExportedTestRunState as TestRunState, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; -import { TestTreeTestHarness } from 'vs/workbench/contrib/testing/test/browser/testObjectTree'; - -suite('Workbench - Testing Explorer State by Location Projection', () => { - let harness: TestTreeTestHarness; - setup(() => { - harness = new TestTreeTestHarness(l => new StateByLocationProjection(l)); - }); - - teardown(() => { - harness.dispose(); - }); - - test('renders initial tree', () => { - harness.c.addRoot(testStubs.nested(), 'a'); - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'aa' }, { e: 'ab' }] }, { e: 'b' }] } - ]); - }); - - test('expands if second root is added', () => { - harness.c.addRoot(testStubs.nested(), 'a'); - harness.flush(); - harness.c.addRoot({ - ...testStubs.test('root2'), - children: [testStubs.test('c')] - }, 'b'); - assert.deepStrictEqual(harness.flush(), [ - { - e: 'Unset', children: [ - { e: 'root', children: [{ e: 'a', children: [{ e: 'aa' }, { e: 'ab' }] }, { e: 'b' }] }, - { e: 'root2', children: [{ e: 'c' }] }, - ] - } - ]); - }); - - test('recompacts if second root children are removed', () => { - harness.c.addRoot(testStubs.nested(), 'a'); - harness.flush(); - const root2 = { - ...testStubs.test('root2'), - children: [testStubs.test('c')] - }; - - harness.c.addRoot(root2, 'b'); - harness.flush(); - - root2.children.pop(); - harness.c.onItemChange(root2, 'b'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'aa' }, { e: 'ab' }] }, { e: 'b' }] } - ]); - }); - - test('updates nodes if they change', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - tests.children[0].label = 'changed'; - harness.c.onItemChange(tests.children[0], 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'changed', children: [{ e: 'aa' }, { e: 'ab' }] }, { e: 'b' }] } - ]); - }); - - test('updates nodes if they add children', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - tests.children[0].children?.push(testStubs.test('ac')); - harness.c.onItemChange(tests.children[0], 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'aa' }, { e: 'ab' }, { e: 'ac' }] }, { e: 'b' }] } - ]); - }); - - test('updates nodes if they remove children', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - tests.children[0].children?.pop(); - harness.c.onItemChange(tests.children[0], 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'aa' }] }, { e: 'b' }] } - ]); - }); - - test('moves nodes when states change', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - const subchild = tests.children[0].children![0]; - subchild.state = { runState: TestRunState.Passed, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Passed', children: [{ e: 'a', children: [{ e: 'aa' }] }] }, - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'ab' }] }, { e: 'b' }] }, - ]); - - subchild.state = { runState: TestRunState.Failed, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Failed', children: [{ e: 'a', children: [{ e: 'aa' }] }] }, - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'ab' }] }, { e: 'b' }] }, - ]); - - subchild.state = { runState: TestRunState.Unset, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'aa' }, { e: 'ab' }] }, { e: 'b' }] }, - ]); - }); - - test('does not move when state is running', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - const subchild = tests.children[0].children![0]; - subchild.state = { runState: TestRunState.Running, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'aa' }, { e: 'ab' }] }, { e: 'b' }] }, - ]); - - subchild.state = { runState: TestRunState.Failed, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Failed', children: [{ e: 'a', children: [{ e: 'aa' }] }] }, - { e: 'Unset', children: [{ e: 'a', children: [{ e: 'ab' }] }, { e: 'b' }] }, - ]); - }); -}); diff --git a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/stateByName.test.ts b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/stateByName.test.ts deleted file mode 100644 index 2670617d2a3..00000000000 --- a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/stateByName.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { StateByNameProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/stateByName'; -import { ReExportedTestRunState as TestRunState, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; -import { TestTreeTestHarness } from 'vs/workbench/contrib/testing/test/browser/testObjectTree'; - -suite('Workbench - Testing Explorer State by Name Projection', () => { - let harness: TestTreeTestHarness; - setup(() => { - harness = new TestTreeTestHarness(l => new StateByNameProjection(l)); - }); - - teardown(() => { - harness.dispose(); - }); - - test('renders initial tree', () => { - harness.c.addRoot(testStubs.nested(), 'a'); - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'aa' }, { e: 'ab' }, { e: 'b' }] } - ]); - }); - - test('swaps when node becomes leaf', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - tests.children[0].children = []; - harness.c.onItemChange(tests.children[0], 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'a' }, { e: 'b' }] } - ]); - }); - - test('swaps when node is no longer leaf', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - tests.children[1].children = [testStubs.test('ba')]; - harness.c.onItemChange(tests.children[1], 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'aa' }, { e: 'ab' }, { e: 'ba' }] } - ]); - }); - - test('swaps when node is no longer runnable', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - tests.children[1].children = [testStubs.test('ba')]; - harness.c.onItemChange(tests.children[0], 'a'); - harness.flush(); - - tests.children[1].children[0].runnable = false; - harness.c.onItemChange(tests.children[1].children[0], 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'aa' }, { e: 'ab' }, { e: 'b' }] } - ]); - }); - - test('moves nodes when states change', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - const subchild = tests.children[0].children![0]; - subchild.state = { runState: TestRunState.Passed, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Passed', children: [{ e: 'aa' }] }, - { e: 'Unset', children: [{ e: 'ab' }, { e: 'b' }] }, - ]); - - subchild.state = { runState: TestRunState.Failed, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Failed', children: [{ e: 'aa' }] }, - { e: 'Unset', children: [{ e: 'ab' }, { e: 'b' }] }, - ]); - - subchild.state = { runState: TestRunState.Unset, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'aa' }, { e: 'ab' }, { e: 'b' }] } - ]); - }); - - test('does not move when state is running', () => { - const tests = testStubs.nested(); - harness.c.addRoot(tests, 'a'); - harness.flush(); - - const subchild = tests.children[0].children![0]; - subchild.state = { runState: TestRunState.Running, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Unset', children: [{ e: 'aa' }, { e: 'ab' }, { e: 'b' }] } - ]); - - subchild.state = { runState: TestRunState.Failed, messages: [] }; - harness.c.onItemChange(subchild, 'a'); - - assert.deepStrictEqual(harness.flush(), [ - { e: 'Failed', children: [{ e: 'aa' }] }, - { e: 'Unset', children: [{ e: 'ab' }, { e: 'b' }] }, - ]); - }); -}); diff --git a/src/vs/workbench/contrib/testing/test/common/testingUri.test.ts b/src/vs/workbench/contrib/testing/test/common/testingUri.test.ts index d28b37b0063..41d534e5d69 100644 --- a/src/vs/workbench/contrib/testing/test/common/testingUri.test.ts +++ b/src/vs/workbench/contrib/testing/test/common/testingUri.test.ts @@ -9,9 +9,6 @@ import { buildTestUri, ParsedTestUri, parseTestUri, TestUriType } from 'vs/workb suite('Workbench - Testing URIs', () => { test('round trip', () => { const uris: ParsedTestUri[] = [ - { type: TestUriType.LiveActualOutput, messageIndex: 42, providerId: 'p', testId: 't' }, - { type: TestUriType.LiveExpectedOutput, messageIndex: 42, providerId: 'p', testId: 't' }, - { type: TestUriType.LiveMessage, messageIndex: 42, providerId: 'p', testId: 't' }, { type: TestUriType.ResultActualOutput, messageIndex: 42, resultId: 'r', testId: 't' }, { type: TestUriType.ResultExpectedOutput, messageIndex: 42, resultId: 'r', testId: 't' }, { type: TestUriType.ResultMessage, messageIndex: 42, resultId: 'r', testId: 't' }, diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewIgnoreMenuShortcutsManager.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewIgnoreMenuShortcutsManager.ts index 5b5e4dd75ac..e44124e7a22 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewIgnoreMenuShortcutsManager.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewIgnoreMenuShortcutsManager.ts @@ -7,7 +7,7 @@ import { WebviewTag } from 'electron'; import { addDisposableListener } from 'vs/base/browser/dom'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { isMacintosh } from 'vs/base/common/platform'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService'; @@ -26,7 +26,7 @@ export class WebviewIgnoreMenuShortcutsManager { ) { this._isUsingNativeTitleBars = configurationService.getValue('window.titleBarStyle') === 'native'; - this.webviewMainService = createChannelSender(mainProcessService.getChannel('webview')); + this.webviewMainService = ProxyChannel.toService(mainProcessService.getChannel('webview')); } public add(webview: WebviewTag): IDisposable { diff --git a/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts b/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts index cae03c79bdb..1f46cf1bddb 100644 --- a/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts +++ b/src/vs/workbench/contrib/webview/electron-sandbox/resourceLoading.ts @@ -9,7 +9,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import * as modes from 'vs/editor/common/modes'; import { IFileService } from 'vs/platform/files/common/files'; @@ -71,7 +71,7 @@ export class WebviewResourceRequestManager extends Disposable { this._logService.debug(`WebviewResourceRequestManager(${this.id}): init`); - this._webviewManagerService = createChannelSender(mainProcessService.getChannel('webview')); + this._webviewManagerService = ProxyChannel.toService(mainProcessService.getChannel('webview')); this._localResourceRoots = initialContentOptions.localResourceRoots || []; this._portMappings = initialContentOptions.portMapping || []; diff --git a/src/vs/workbench/contrib/webview/electron-sandbox/windowIgnoreMenuShortcutsManager.ts b/src/vs/workbench/contrib/webview/electron-sandbox/windowIgnoreMenuShortcutsManager.ts index 00da271c3e8..7a4d3d20f51 100644 --- a/src/vs/workbench/contrib/webview/electron-sandbox/windowIgnoreMenuShortcutsManager.ts +++ b/src/vs/workbench/contrib/webview/electron-sandbox/windowIgnoreMenuShortcutsManager.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { isMacintosh } from 'vs/base/common/platform'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; @@ -23,7 +23,7 @@ export class WindowIgnoreMenuShortcutsManager { ) { this._isUsingNativeTitleBars = configurationService.getValue('window.titleBarStyle') === 'native'; - this.webviewMainService = createChannelSender(mainProcessService.getChannel('webview')); + this.webviewMainService = ProxyChannel.toService(mainProcessService.getChannel('webview')); } public didFocus(): void { diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index 2ca2490cc62..b91263aa5c6 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -22,7 +22,7 @@ import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/exte import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { flatten } from 'vs/base/common/arrays'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { ActivationKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { Severity } from 'vs/platform/notification/common/notification'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; @@ -108,6 +108,7 @@ export interface IAuthenticationService { getProviderIds(): string[]; registerAuthenticationProvider(id: string, provider: MainThreadAuthenticationProvider): void; unregisterAuthenticationProvider(id: string): void; + isAccessAllowed(providerId: string, accountName: string, extensionId: string): boolean; showGetSessionPrompt(providerId: string, accountName: string, extensionId: string, extensionName: string): Promise; selectSession(providerId: string, extensionId: string, extensionName: string, possibleSessions: AuthenticationSession[]): Promise; requestSessionAccess(providerId: string, extensionId: string, extensionName: string, possibleSessions: AuthenticationSession[]): void; @@ -123,10 +124,10 @@ export interface IAuthenticationService { declaredProviders: AuthenticationProviderInformation[]; readonly onDidChangeDeclaredProviders: Event; - getSessions(providerId: string): Promise>; + getSessions(providerId: string, activateImmediate?: boolean): Promise>; getLabel(providerId: string): string; supportsMultipleAccounts(providerId: string): boolean; - login(providerId: string, scopes: string[]): Promise; + login(providerId: string, scopes: string[], activateImmediate?: boolean): Promise; logout(providerId: string, sessionId: string): Promise; manageTrustedExtensionsForAccount(providerId: string, accountName: string): Promise; @@ -426,7 +427,7 @@ export class AuthenticationService extends Disposable implements IAuthentication } } - async showGetSessionPrompt(providerId: string, accountName: string, extensionId: string, extensionName: string): Promise { + isAccessAllowed(providerId: string, accountName: string, extensionId: string): boolean { const allowList = readAllowedExtensions(this.storageService, providerId, accountName); const extensionData = allowList.find(extension => extension.id === extensionId); if (extensionData) { @@ -442,6 +443,10 @@ export class AuthenticationService extends Disposable implements IAuthentication return true; } + return false; + } + + async showGetSessionPrompt(providerId: string, accountName: string, extensionId: string, extensionName: string): Promise { const providerName = this.getLabel(providerId); const { choice } = await this.dialogService.show( Severity.Info, @@ -454,6 +459,7 @@ export class AuthenticationService extends Disposable implements IAuthentication const allow = choice === 0; if (allow) { + const allowList = readAllowedExtensions(this.storageService, providerId, accountName); allowList.push({ id: extensionId, name: extensionName }); this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL, StorageTarget.USER); } @@ -666,17 +672,7 @@ export class AuthenticationService extends Disposable implements IAuthentication }); } - this._accountBadgeDisposable.clear(); - - let numberOfRequests = 0; - this._signInRequestItems.forEach(providerRequests => { - Object.keys(providerRequests).forEach(request => { - numberOfRequests += providerRequests[request].requestingExtensionIds.length; - }); - }); - - const badge = new NumberBadge(numberOfRequests, () => nls.localize('sign in', "Sign in requested")); - this._accountBadgeDisposable.value = this.activityService.showAccountsActivity({ badge }); + this.updateBadgeCount(); } } getLabel(id: string): string { @@ -697,8 +693,8 @@ export class AuthenticationService extends Disposable implements IAuthentication } } - private async tryActivateProvider(providerId: string): Promise { - await this.extensionService.activateByEvent(getAuthenticationProviderActivationEvent(providerId)); + private async tryActivateProvider(providerId: string, activateImmediate: boolean): Promise { + await this.extensionService.activateByEvent(getAuthenticationProviderActivationEvent(providerId), activateImmediate ? ActivationKind.Immediate : ActivationKind.Normal); let provider = this._authenticationProviders.get(providerId); if (provider) { return provider; @@ -728,18 +724,18 @@ export class AuthenticationService extends Disposable implements IAuthentication return Promise.race([didRegister, didTimeout]); } - async getSessions(id: string): Promise> { + async getSessions(id: string, activateImmediate: boolean = false): Promise> { try { - const authProvider = this._authenticationProviders.get(id) || await this.tryActivateProvider(id); + const authProvider = this._authenticationProviders.get(id) || await this.tryActivateProvider(id, activateImmediate); return await authProvider.getSessions(); } catch (_) { throw new Error(`No authentication provider '${id}' is currently registered.`); } } - async login(id: string, scopes: string[]): Promise { + async login(id: string, scopes: string[], activateImmediate: boolean = false): Promise { try { - const authProvider = this._authenticationProviders.get(id) || await this.tryActivateProvider(id); + const authProvider = this._authenticationProviders.get(id) || await this.tryActivateProvider(id, activateImmediate); return await authProvider.login(scopes); } catch (_) { throw new Error(`No authentication provider '${id}' is currently registered.`); diff --git a/src/vs/workbench/services/diagnostics/electron-sandbox/diagnosticsService.ts b/src/vs/workbench/services/diagnostics/electron-sandbox/diagnosticsService.ts index 82d879f79df..75eae982425 100644 --- a/src/vs/workbench/services/diagnostics/electron-sandbox/diagnosticsService.ts +++ b/src/vs/workbench/services/diagnostics/electron-sandbox/diagnosticsService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/sharedProcessService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IDiagnosticsService } from 'vs/platform/diagnostics/common/diagnostics'; @@ -16,7 +16,7 @@ export class DiagnosticsService implements IDiagnosticsService { constructor( @ISharedProcessService sharedProcessService: ISharedProcessService ) { - return createChannelSender(sharedProcessService.getChannel('diagnostics')); + return ProxyChannel.toService(sharedProcessService.getChannel('diagnostics')); } } diff --git a/src/vs/workbench/services/encryption/electron-sandbox/encryptionService.ts b/src/vs/workbench/services/encryption/electron-sandbox/encryptionService.ts index 336eee9e9a1..198bf51ee01 100644 --- a/src/vs/workbench/services/encryption/electron-sandbox/encryptionService.ts +++ b/src/vs/workbench/services/encryption/electron-sandbox/encryptionService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IEncryptionService } from 'vs/workbench/services/encryption/common/encryptionService'; @@ -13,7 +13,7 @@ export class EncryptionService { declare readonly _serviceBrand: undefined; constructor(@IMainProcessService mainProcessService: IMainProcessService) { - return createChannelSender(mainProcessService.getChannel('encryption')); + return ProxyChannel.toService(mainProcessService.getChannel('encryption')); } } diff --git a/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts index 3cabb495102..00610fa6eb5 100644 --- a/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts +++ b/src/vs/workbench/services/extensionManagement/electron-sandbox/extensionUrlTrustService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; @@ -13,7 +13,7 @@ class ExtensionUrlTrustService { declare readonly _serviceBrand: undefined; constructor(@IMainProcessService mainProcessService: IMainProcessService) { - return createChannelSender(mainProcessService.getChannel('extensionUrlTrust')); + return ProxyChannel.toService(mainProcessService.getChannel('extensionUrlTrust')); } } diff --git a/src/vs/workbench/services/issue/electron-sandbox/issueService.ts b/src/vs/workbench/services/issue/electron-sandbox/issueService.ts index ce1f795ccbc..de309efcbd1 100644 --- a/src/vs/workbench/services/issue/electron-sandbox/issueService.ts +++ b/src/vs/workbench/services/issue/electron-sandbox/issueService.ts @@ -5,7 +5,7 @@ import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; // @ts-ignore: interface is implemented via proxy @@ -14,7 +14,7 @@ export class IssueService implements IIssueService { declare readonly _serviceBrand: undefined; constructor(@IMainProcessService mainProcessService: IMainProcessService) { - return createChannelSender(mainProcessService.getChannel('issue')); + return ProxyChannel.toService(mainProcessService.getChannel('issue')); } } diff --git a/src/vs/workbench/services/keybinding/electron-sandbox/nativeKeyboardLayout.ts b/src/vs/workbench/services/keybinding/electron-sandbox/nativeKeyboardLayout.ts index 318e3910633..a20f74953ca 100644 --- a/src/vs/workbench/services/keybinding/electron-sandbox/nativeKeyboardLayout.ts +++ b/src/vs/workbench/services/keybinding/electron-sandbox/nativeKeyboardLayout.ts @@ -15,7 +15,7 @@ import { DispatchConfig } from 'vs/platform/keyboardLayout/common/dispatchConfig import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { IKeyboardLayoutMainService } from 'vs/platform/keyboardLayout/common/keyboardLayoutMainService'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; export class KeyboardLayoutService extends Disposable implements IKeyboardLayoutService { @@ -34,7 +34,7 @@ export class KeyboardLayoutService extends Disposable implements IKeyboardLayout @IMainProcessService mainProcessService: IMainProcessService ) { super(); - this._keyboardLayoutMainService = createChannelSender(mainProcessService.getChannel('keyboardLayout')); + this._keyboardLayoutMainService = ProxyChannel.toService(mainProcessService.getChannel('keyboardLayout')); this._initPromise = null; this._keyboardMapping = null; this._keyboardLayoutInfo = null; diff --git a/src/vs/workbench/services/localizations/electron-sandbox/localizationsService.ts b/src/vs/workbench/services/localizations/electron-sandbox/localizationsService.ts index 60d652092cc..7b980dd9b70 100644 --- a/src/vs/workbench/services/localizations/electron-sandbox/localizationsService.ts +++ b/src/vs/workbench/services/localizations/electron-sandbox/localizationsService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/sharedProcessService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -16,7 +16,7 @@ export class LocalizationsService implements ILocalizationsService { constructor( @ISharedProcessService sharedProcessService: ISharedProcessService, ) { - return createChannelSender(sharedProcessService.getChannel('localizations')); + return ProxyChannel.toService(sharedProcessService.getChannel('localizations')); } } diff --git a/src/vs/workbench/services/menubar/electron-sandbox/menubarService.ts b/src/vs/workbench/services/menubar/electron-sandbox/menubarService.ts index c1356a21011..55d28ef7062 100644 --- a/src/vs/workbench/services/menubar/electron-sandbox/menubarService.ts +++ b/src/vs/workbench/services/menubar/electron-sandbox/menubarService.ts @@ -5,7 +5,7 @@ import { IMenubarService } from 'vs/platform/menubar/electron-sandbox/menubar'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; // @ts-ignore: interface is implemented via proxy @@ -14,7 +14,7 @@ export class MenubarService implements IMenubarService { declare readonly _serviceBrand: undefined; constructor(@IMainProcessService mainProcessService: IMainProcessService) { - return createChannelSender(mainProcessService.getChannel('menubar')); + return ProxyChannel.toService(mainProcessService.getChannel('menubar')); } } diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 68d6939a1b0..24cac4ab5c0 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -371,7 +371,9 @@ export class TunnelModel extends Disposable { return tunnel; } } else { - existingTunnel.name = name; + if (name) { + existingTunnel.name = name; + } this._onForwardPort.fire(); return mapHasAddressLocalhostOrAllInterfaces(this.remoteTunnels, remote.host, remote.port); } diff --git a/src/vs/workbench/services/textfile/common/encoding.ts b/src/vs/workbench/services/textfile/common/encoding.ts index c4f80a86739..fa303894781 100644 --- a/src/vs/workbench/services/textfile/common/encoding.ts +++ b/src/vs/workbench/services/textfile/common/encoding.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Readable, ReadableStream, newWriteableStream } from 'vs/base/common/stream'; +import { Readable, ReadableStream, newWriteableStream, listenStream } from 'vs/base/common/stream'; import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; export const UTF8 = 'utf8'; @@ -133,50 +133,47 @@ export function toDecodeStream(source: VSBufferReadableStream, options: IDecodeS } }; - // Stream error: forward to target - source.on('error', error => target.error(error)); + listenStream(source, { + onData: async chunk => { - // Stream data - source.on('data', async chunk => { - - // if the decoder is ready, we just write directly - if (decoder) { - target.write(decoder.write(chunk.buffer)); - } - - // otherwise we need to buffer the data until the stream is ready - else { - bufferedChunks.push(chunk); - bytesBuffered += chunk.byteLength; - - // buffered enough data for encoding detection, create stream - if (bytesBuffered >= minBytesRequiredForDetection) { - - // pause stream here until the decoder is ready - source.pause(); - - await createDecoder(); - - // resume stream now that decoder is ready but - // outside of this stack to reduce recursion - setTimeout(() => source.resume()); + // if the decoder is ready, we just write directly + if (decoder) { + target.write(decoder.write(chunk.buffer)); } + + // otherwise we need to buffer the data until the stream is ready + else { + bufferedChunks.push(chunk); + bytesBuffered += chunk.byteLength; + + // buffered enough data for encoding detection, create stream + if (bytesBuffered >= minBytesRequiredForDetection) { + + // pause stream here until the decoder is ready + source.pause(); + + await createDecoder(); + + // resume stream now that decoder is ready but + // outside of this stack to reduce recursion + setTimeout(() => source.resume()); + } + } + }, + onError: error => target.error(error), // simply forward to target + onEnd: async () => { + + // we were still waiting for data to do the encoding + // detection. thus, wrap up starting the stream even + // without all the data to get things going + if (!decoder) { + await createDecoder(); + } + + // end the target with the remainders of the decoder + target.end(decoder?.end()); } }); - - // Stream end - source.on('end', async () => { - - // we were still waiting for data to do the encoding - // detection. thus, wrap up starting the stream even - // without all the data to get things going - if (!decoder) { - await createDecoder(); - } - - // end the target with the remainders of the decoder - target.end(decoder?.end()); - }); }); } diff --git a/src/vs/workbench/services/url/electron-sandbox/urlService.ts b/src/vs/workbench/services/url/electron-sandbox/urlService.ts index 90f842f7d47..6e6b0e1a030 100644 --- a/src/vs/workbench/services/url/electron-sandbox/urlService.ts +++ b/src/vs/workbench/services/url/electron-sandbox/urlService.ts @@ -10,7 +10,7 @@ import { URLHandlerChannel } from 'vs/platform/url/common/urlIpc'; import { IOpenerService, IOpener, matchesScheme } from 'vs/platform/opener/common/opener'; import { IProductService } from 'vs/platform/product/common/productService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { NativeURLService } from 'vs/platform/url/common/urlService'; @@ -31,7 +31,7 @@ export class RelayURLService extends NativeURLService implements IURLHandler, IO ) { super(); - this.urlService = createChannelSender(mainProcessService.getChannel('url')); + this.urlService = ProxyChannel.toService(mainProcessService.getChannel('url')); mainProcessService.registerChannel('urlHandler', new URLHandlerChannel(this)); openerService.registerOpener(this); diff --git a/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts b/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts index f3dd9b34f70..7ae6139c8f8 100644 --- a/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts +++ b/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts @@ -6,7 +6,7 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; // @ts-ignore: interface is implemented via proxy @@ -18,7 +18,7 @@ export class NativeWorkspacesService implements IWorkspacesService { @IMainProcessService mainProcessService: IMainProcessService, @INativeHostService nativeHostService: INativeHostService ) { - return createChannelSender(mainProcessService.getChannel('workspaces'), { context: nativeHostService.windowId }); + return ProxyChannel.toService(mainProcessService.getChannel('workspaces'), { context: nativeHostService.windowId }); } } diff --git a/src/vs/workbench/test/browser/api/extHostTesting.test.ts b/src/vs/workbench/test/browser/api/extHostTesting.test.ts index 1be5d1bc114..a60900d2ea8 100644 --- a/src/vs/workbench/test/browser/api/extHostTesting.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTesting.test.ts @@ -326,7 +326,6 @@ suite('ExtHost Testing', () => { assert.strictEqual(testItem.label, wrapper.label); assert.strictEqual(testItem.location, wrapper.location); assert.strictEqual(testItem.runnable, wrapper.runnable); - assert.strictEqual(testItem.state, wrapper.state); }); test('gets no children if nothing matches Uri filter', () => { diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index ab712e8834c..30c54d04952 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -69,7 +69,7 @@ import { Part } from 'vs/workbench/browser/part'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPanel } from 'vs/workbench/common/panel'; import { IBadge } from 'vs/workbench/services/activity/common/activity'; -import { VSBuffer, VSBufferReadable } from 'vs/base/common/buffer'; +import { bufferToStream, VSBuffer, VSBufferReadable } from 'vs/base/common/buffer'; import { Schemas } from 'vs/base/common/network'; import { IProductService } from 'vs/platform/product/common/productService'; import product from 'vs/platform/product/common/product'; @@ -839,20 +839,7 @@ export class TestFileService implements IFileService { return Promise.resolve({ resource, - value: { - on: (event: string, callback: Function): void => { - if (event === 'data') { - callback(this.content); - } - if (event === 'end') { - callback(); - } - }, - removeListener: () => { }, - resume: () => { }, - pause: () => { }, - destroy: () => { } - }, + value: bufferToStream(VSBuffer.fromString(this.content)), etag: 'index.txt', encoding: 'utf8', mtime: Date.now(), diff --git a/test/smoke/src/areas/search/search.test.ts b/test/smoke/src/areas/search/search.test.ts index 0fac0ca37a2..15257e6bfdb 100644 --- a/test/smoke/src/areas/search/search.test.ts +++ b/test/smoke/src/areas/search/search.test.ts @@ -46,6 +46,7 @@ export function setup() { const app = this.app as Application; await app.workbench.search.searchFor('body'); + await app.workbench.search.expandReplace(); await app.workbench.search.setReplaceText('ydob'); await app.workbench.search.replaceFileMatch('app.js'); await app.workbench.search.waitForResultText('12 results in 4 files'); diff --git a/yarn.lock b/yarn.lock index 8559099a526..b8177d34186 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10074,10 +10074,10 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -vscode-debugprotocol@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.44.0.tgz#79d11844f908cc5104afc303b3780ad2e5fd486a" - integrity sha512-qf+eBnrDyR2MpP08y1JfzJnFZGHdkk86+SRGRp0XepDGNA6n/Nann5XhtAzdGX/yaZokjTAINK313S2yYhHoPQ== +vscode-debugprotocol@1.45.0-pre.0: + version "1.45.0-pre.0" + resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.45.0-pre.0.tgz#7ea4c6e84d966e96a8398241e46bdf98e0dacfde" + integrity sha512-q0ivFfnjFQyL4Qyxp1K8gSdTpfcvlCxmys5adLydBef1XvDKZNONAKalCZZCyaG/vtOlbV1ma6hS5eALNaLd8w== vscode-nls-dev@^3.3.1: version "3.3.1"