From d11dc8c2bff16ed9b4151fc9135819e924d62cd0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 24 Feb 2022 08:21:06 +0100 Subject: [PATCH 1/8] lifecycle - prevent multiple overlapping window unloads --- .../electron-main/lifecycleMainService.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts index b6c8d9fdc2425..69310c99ce811 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts @@ -241,6 +241,8 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe private pendingWillShutdownPromise: Promise | undefined = undefined; + private readonly mapWindowIdToPendingUnload = new Map>(); + private readonly phaseWhen = new Map(); constructor( @@ -469,7 +471,24 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe } } - async unload(window: ICodeWindow, reason: UnloadReason): Promise { + unload(window: ICodeWindow, reason: UnloadReason): Promise { + + // Ensure there is only 1 unload running at the same time + const pendingUnloadPromise = this.mapWindowIdToPendingUnload.get(window.id); + if (pendingUnloadPromise) { + return pendingUnloadPromise; + } + + // Start unload and remember in map until finished + const unloadPromise = this.doUnload(window, reason).finally(() => { + this.mapWindowIdToPendingUnload.delete(window.id); + }); + this.mapWindowIdToPendingUnload.set(window.id, unloadPromise); + + return unloadPromise; + } + + private async doUnload(window: ICodeWindow, reason: UnloadReason): Promise { // Always allow to unload a window that is not yet ready if (!window.isReady) { From 155c5e8964a59de6d325366de1dd33315bf353ae Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Feb 2022 07:45:29 +0100 Subject: [PATCH 2/8] :up: playwright --- package.json | 2 +- yarn.lock | 422 +++++++++++++++++++++++++++++---------------------- 2 files changed, 245 insertions(+), 179 deletions(-) diff --git a/package.json b/package.json index f0bfeea345285..4ab83ae87bb0f 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ }, "devDependencies": { "7zip": "0.0.6", - "@playwright/test": "1.18.0", + "@playwright/test": "1.19.2", "@types/applicationinsights": "0.20.0", "@types/cookie": "^0.3.3", "@types/copy-webpack-plugin": "^6.0.3", diff --git a/yarn.lock b/yarn.lock index 3160e0a6dd07c..f748498aec5de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -95,6 +95,13 @@ events "^3.0.0" tslib "^2.2.0" +"@babel/code-frame@7.16.7", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + "@babel/code-frame@^7.0.0": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -102,13 +109,6 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - "@babel/code-frame@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" @@ -121,20 +121,20 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== -"@babel/core@^7.14.8": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.7.tgz#db990f931f6d40cb9b87a0dc7d2adc749f1dcbcf" - integrity sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA== +"@babel/core@7.16.12": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" + integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== dependencies: "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.16.7" + "@babel/generator" "^7.16.8" "@babel/helper-compilation-targets" "^7.16.7" "@babel/helper-module-transforms" "^7.16.7" "@babel/helpers" "^7.16.7" - "@babel/parser" "^7.16.7" + "@babel/parser" "^7.16.12" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/traverse" "^7.16.10" + "@babel/types" "^7.16.8" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -163,7 +163,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.16.7", "@babel/generator@^7.16.8": +"@babel/generator@^7.16.8": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== @@ -172,6 +172,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03" @@ -199,6 +208,19 @@ browserslist "^4.17.5" semver "^6.3.0" +"@babel/helper-create-class-features-plugin@^7.16.10": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9" + integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-create-class-features-plugin@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz#9c5b34b53a01f2097daf10678d65135c1b9f84ba" @@ -397,6 +419,11 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/parser@^7.16.12", "@babel/parser@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== + "@babel/parser@^7.16.7", "@babel/parser@^7.16.8": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.8.tgz#61c243a3875f7d0b0962b0543a33ece6ff2f1f17" @@ -407,7 +434,7 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081" integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ== -"@babel/plugin-proposal-class-properties@^7.14.5": +"@babel/plugin-proposal-class-properties@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== @@ -415,7 +442,7 @@ "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-dynamic-import@^7.14.5": +"@babel/plugin-proposal-dynamic-import@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== @@ -423,7 +450,7 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.14.5": +"@babel/plugin-proposal-export-namespace-from@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== @@ -431,7 +458,7 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": +"@babel/plugin-proposal-logical-assignment-operators@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== @@ -439,7 +466,7 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": +"@babel/plugin-proposal-nullish-coalescing-operator@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== @@ -447,7 +474,7 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.14.5": +"@babel/plugin-proposal-numeric-separator@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== @@ -455,7 +482,7 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-optional-chaining@^7.14.5": +"@babel/plugin-proposal-optional-chaining@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== @@ -464,15 +491,15 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.14.5": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.7.tgz#e418e3aa6f86edd6d327ce84eff188e479f571e0" - integrity sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw== +"@babel/plugin-proposal-private-methods@7.16.11": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" + integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.10" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-proposal-private-property-in-object@^7.14.5": +"@babel/plugin-proposal-private-property-in-object@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== @@ -482,7 +509,7 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-syntax-async-generators@^7.8.4": +"@babel/plugin-syntax-async-generators@7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== @@ -503,7 +530,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-json-strings@^7.8.3": +"@babel/plugin-syntax-json-strings@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== @@ -538,14 +565,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.3": +"@babel/plugin-syntax-object-rest-spread@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": +"@babel/plugin-syntax-optional-catch-binding@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== @@ -573,7 +600,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-modules-commonjs@^7.14.5": +"@babel/plugin-transform-modules-commonjs@7.16.8": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== @@ -583,7 +610,7 @@ "@babel/helper-simple-access" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-react-jsx@^7.14.5": +"@babel/plugin-transform-react-jsx@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz#86a6a220552afd0e4e1f0388a68a372be7add0d4" integrity sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag== @@ -603,7 +630,7 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-typescript" "^7.16.7" -"@babel/preset-typescript@^7.14.5": +"@babel/preset-typescript@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== @@ -630,6 +657,22 @@ "@babel/parser" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/traverse@^7.16.10": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.16.7": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.8.tgz#bab2f2b09a5fe8a8d9cad22cbfe3ba1d126fef9c" @@ -669,6 +712,14 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" +"@babel/types@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + "@babel/types@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" @@ -1013,49 +1064,49 @@ node-addon-api "^3.2.1" node-gyp-build "^4.3.0" -"@playwright/test@1.18.0": - version "1.18.0" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.18.0.tgz#e6ac7b588d927fdd028d72f0db1030dd777a79a7" - integrity sha512-ceu4DqerPlyRsdNfke4IUyWH1WccRuBokngFdPAzc5CRzlGmSTT59NBkJyn8Fg/F01CziaMFgNRrHQIMSd4g5A== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/core" "^7.14.8" - "@babel/plugin-proposal-class-properties" "^7.14.5" - "@babel/plugin-proposal-dynamic-import" "^7.14.5" - "@babel/plugin-proposal-export-namespace-from" "^7.14.5" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-numeric-separator" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-private-methods" "^7.14.5" - "@babel/plugin-proposal-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-transform-modules-commonjs" "^7.14.5" - "@babel/plugin-transform-react-jsx" "^7.14.5" - "@babel/preset-typescript" "^7.14.5" - babel-plugin-module-resolver "^4.1.0" +"@playwright/test@1.19.2": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.19.2.tgz#429d1aa70f5e4cd521cdc8a5d9861ae4fcda3f7c" + integrity sha512-5oCmlYHjtOL662OxSkZBYGnoHWIQui7b4YHWNeSCYwhQjmjVcV5njRc8oBZlU8IwJgG7ZH2yhDk1haU96ygbWw== + dependencies: + "@babel/code-frame" "7.16.7" + "@babel/core" "7.16.12" + "@babel/plugin-proposal-class-properties" "7.16.7" + "@babel/plugin-proposal-dynamic-import" "7.16.7" + "@babel/plugin-proposal-export-namespace-from" "7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "7.16.7" + "@babel/plugin-proposal-numeric-separator" "7.16.7" + "@babel/plugin-proposal-optional-chaining" "7.16.7" + "@babel/plugin-proposal-private-methods" "7.16.11" + "@babel/plugin-proposal-private-property-in-object" "7.16.7" + "@babel/plugin-syntax-async-generators" "7.8.4" + "@babel/plugin-syntax-json-strings" "7.8.3" + "@babel/plugin-syntax-object-rest-spread" "7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "7.8.3" + "@babel/plugin-transform-modules-commonjs" "7.16.8" + "@babel/plugin-transform-react-jsx" "7.16.7" + "@babel/preset-typescript" "7.16.7" + babel-plugin-module-resolver "4.1.0" colors "1.4.0" - commander "^8.2.0" - debug "^4.1.1" - expect "=27.2.5" - jest-matcher-utils "=27.2.5" - jpeg-js "^0.4.2" - json5 "^2.2.0" - mime "^2.4.6" - minimatch "^3.0.3" - ms "^2.1.2" - open "^8.3.0" - pirates "^4.0.1" - pixelmatch "^5.2.1" - playwright-core "=1.18.0" - pngjs "^5.0.0" - rimraf "^3.0.2" - source-map-support "^0.4.18" - stack-utils "^2.0.3" - yazl "^2.5.1" + commander "8.3.0" + debug "4.3.3" + expect "27.2.5" + jest-matcher-utils "27.2.5" + jpeg-js "0.4.3" + json5 "2.2.0" + mime "3.0.0" + minimatch "3.0.4" + ms "2.1.3" + open "8.4.0" + pirates "4.0.4" + pixelmatch "5.2.1" + playwright-core "1.19.2" + pngjs "6.0.0" + rimraf "3.0.2" + source-map-support "0.4.18" + stack-utils "2.0.5" + yazl "2.5.1" "@sindresorhus/is@^0.14.0": version "0.14.0" @@ -2446,7 +2497,7 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-module-resolver@^4.1.0: +babel-plugin-module-resolver@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2" integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA== @@ -3333,6 +3384,11 @@ commander@2.11.x: resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== +commander@8.3.0, commander@^8.2.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + commander@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" @@ -3353,11 +3409,6 @@ commander@^7.0.0, commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^8.2.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - commandpost@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/commandpost/-/commandpost-1.2.1.tgz#2e9c4c7508b9dc704afefaa91cab92ee6054cc68" @@ -3861,6 +3912,13 @@ debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: dependencies: ms "2.1.2" +debug@4.3.3, debug@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -3868,13 +3926,6 @@ debug@^3.1.0: dependencies: ms "^2.1.1" -debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - decamelize@^1.1.1, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -4872,7 +4923,7 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect@=27.2.5: +expect@27.2.5: version "27.2.5" resolved "https://registry.yarnpkg.com/expect/-/expect-27.2.5.tgz#16154aaa60b4d9a5b0adacfea3e4d6178f4b93fd" integrity sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA== @@ -4941,17 +4992,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@^1.0.3: - version "1.7.0" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" - integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== - dependencies: - concat-stream "^1.6.2" - debug "^2.6.9" - mkdirp "^0.5.4" - yauzl "^2.10.0" - -extract-zip@^2.0.1: +extract-zip@2.0.1, extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== @@ -4962,6 +5003,16 @@ extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +extract-zip@^1.0.3: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -6288,6 +6339,14 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + https-proxy-agent@^2.2.3: version "2.2.4" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" @@ -6304,14 +6363,6 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -7017,7 +7068,7 @@ jest-get-type@^27.0.6, jest-get-type@^27.4.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== -jest-matcher-utils@=27.2.5: +jest-matcher-utils@27.2.5: version "27.2.5" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz#4684faaa8eb32bf15e6edaead6834031897e2980" integrity sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg== @@ -7066,7 +7117,7 @@ jest-worker@^27.0.2: merge-stream "^2.0.0" supports-color "^8.0.0" -jpeg-js@^0.4.2: +jpeg-js@0.4.3, jpeg-js@^0.4.2: version "0.4.3" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q== @@ -7167,6 +7218,13 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -7193,13 +7251,6 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" -json5@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -7873,6 +7924,11 @@ mime-types@^2.1.27: dependencies: mime-db "1.48.0" +mime@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mime@^1.3.4: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" @@ -8121,7 +8177,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1, ms@^2.1.2: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -8611,7 +8667,7 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= -open@^8.3.0: +open@8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== @@ -9036,12 +9092,12 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -pirates@^4.0.1: +pirates@4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== -pixelmatch@^5.2.1: +pixelmatch@5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-5.2.1.tgz#9e4e4f4aa59648208a31310306a5bed5522b0d65" integrity sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ== @@ -9069,27 +9125,27 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -playwright-core@=1.18.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.18.0.tgz#b4d2b9068f26357adaa952a13254796fd439f322" - integrity sha512-JTRlCVpfAFcC1nth+XIE07w6M5m6C8PaEoClv7wGWF97cyDMcHIij0xIVEKMKli7IG5N0mqjLDFc/akXSbMZ1g== - dependencies: - commander "^8.2.0" - debug "^4.1.1" - extract-zip "^2.0.1" - https-proxy-agent "^5.0.0" - jpeg-js "^0.4.2" - mime "^2.4.6" - pngjs "^5.0.0" - progress "^2.0.3" - proper-lockfile "^4.1.1" - proxy-from-env "^1.1.0" - rimraf "^3.0.2" - socks-proxy-agent "^6.1.0" - stack-utils "^2.0.3" - ws "^7.4.6" - yauzl "^2.10.0" - yazl "^2.5.1" +playwright-core@1.19.2: + version "1.19.2" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.19.2.tgz#90b9209554f174c649abf495952fcb4335437218" + integrity sha512-OsL3sJZIo1UxKNWSP7zW7sk3FyUGG06YRHxHeBw51eIOxTCQRx5t+hXd0cvXashN2CHnd3hIZTs2aKa/im4hZQ== + dependencies: + commander "8.3.0" + debug "4.3.3" + extract-zip "2.0.1" + https-proxy-agent "5.0.0" + jpeg-js "0.4.3" + mime "3.0.0" + pngjs "6.0.0" + progress "2.0.3" + proper-lockfile "4.1.2" + proxy-from-env "1.1.0" + rimraf "3.0.2" + socks-proxy-agent "6.1.1" + stack-utils "2.0.5" + ws "8.4.2" + yauzl "2.10.0" + yazl "2.5.1" playwright-core@=1.18.1: version "1.18.1" @@ -9149,6 +9205,11 @@ plugin-error@^1.0.0, plugin-error@^1.0.1: arr-union "^3.1.0" extend-shallow "^3.0.2" +pngjs@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821" + integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg== + pngjs@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-4.0.1.tgz#f803869bb2fc1bfe1bf99aa4ec21c108117cfdbe" @@ -9560,22 +9621,22 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +progress@2.0.3, progress@^2.0.0, progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= -progress@^2.0.0, progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - 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= -proper-lockfile@^4.1.1: +proper-lockfile@4.1.2, proper-lockfile@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== @@ -9589,7 +9650,7 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -proxy-from-env@^1.1.0: +proxy-from-env@1.1.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -10121,7 +10182,7 @@ rimraf@2.6.3, rimraf@~2.6.2: dependencies: glob "^7.1.3" -rimraf@^3.0.2: +rimraf@3.0.2, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -10480,6 +10541,15 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +socks-proxy-agent@6.1.1, socks-proxy-agent@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" + integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== + dependencies: + agent-base "^6.0.2" + debug "^4.3.1" + socks "^2.6.1" + socks-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz#7c0f364e7b1cf4a7a437e71253bed72e9004be60" @@ -10489,15 +10559,6 @@ socks-proxy-agent@^5.0.0: debug "4" socks "^2.3.3" -socks-proxy-agent@^6.1.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" - integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== - dependencies: - agent-base "^6.0.2" - debug "^4.3.1" - socks "^2.6.1" - socks@^2.3.3, socks@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" @@ -10530,6 +10591,13 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" +source-map-support@0.4.18: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + source-map-support@^0.3.2: version "0.3.3" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.3.3.tgz#34900977d5ba3f07c7757ee72e73bb1a9b53754f" @@ -10537,13 +10605,6 @@ source-map-support@^0.3.2: dependencies: source-map "0.1.32" -source-map-support@^0.4.18: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - source-map-support@~0.5.12, source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -10694,7 +10755,7 @@ stack-trace@0.0.10: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= -stack-utils@^2.0.3: +stack-utils@2.0.5, stack-utils@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== @@ -12289,6 +12350,11 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +ws@8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" + integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== + ws@^7.2.0: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" @@ -12546,7 +12612,7 @@ yaserver@^0.2.0: resolved "https://registry.yarnpkg.com/yaserver/-/yaserver-0.2.0.tgz#56393027dc13f3c1bb89d20e0bd17269aa927802" integrity sha512-onsELrl7Y42M4P3T9R0N/ZJNJRu4cGwzhDyOWIFRMJvPUIrGKInYGh+DJBefrbr1qoyDu7DSCLl9BL5hSSVfDA== -yauzl@^2.10.0, yauzl@^2.4.2, yauzl@^2.9.2: +yauzl@2.10.0, yauzl@^2.10.0, yauzl@^2.4.2, yauzl@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= @@ -12562,6 +12628,13 @@ yauzl@^2.2.1: buffer-crc32 "~0.2.3" fd-slicer "~1.0.1" +yazl@2.5.1, yazl@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" + integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== + dependencies: + buffer-crc32 "~0.2.3" + yazl@^2.2.1, yazl@^2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" @@ -12569,13 +12642,6 @@ yazl@^2.2.1, yazl@^2.4.3: dependencies: buffer-crc32 "~0.2.3" -yazl@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" - integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== - dependencies: - buffer-crc32 "~0.2.3" - ylru@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" From 99ef89977578a3b799f95fedf697590f7280a4ee Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Feb 2022 08:01:59 +0100 Subject: [PATCH 3/8] workspace editing - move path normalization into service --- .../platform/workspaces/common/workspaces.ts | 4 +- .../browser/actions/workspaceCommands.ts | 6 +-- .../abstractWorkspaceEditingService.ts | 49 +++++++++++-------- .../browser/workspaceEditingService.ts | 6 +-- .../services/workspaces/browser/workspaces.ts | 12 ++--- .../workspaces/browser/workspacesService.ts | 8 +-- .../workspaceEditingService.ts | 10 ++-- 7 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/vs/platform/workspaces/common/workspaces.ts b/src/vs/platform/workspaces/common/workspaces.ts index 7e5a2f3b1fb76..cb31aedbb25b5 100644 --- a/src/vs/platform/workspaces/common/workspaces.ts +++ b/src/vs/platform/workspaces/common/workspaces.ts @@ -27,10 +27,10 @@ export interface IWorkspacesService { readonly _serviceBrand: undefined; // Workspaces Management - enterWorkspace(path: URI): Promise; + enterWorkspace(workspaceUri: URI): Promise; createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise; deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise; - getWorkspaceIdentifier(workspacePath: URI): Promise; + getWorkspaceIdentifier(workspaceUri: URI): Promise; // Workspaces History readonly onDidChangeRecentlyOpened: Event; diff --git a/src/vs/workbench/browser/actions/workspaceCommands.ts b/src/vs/workbench/browser/actions/workspaceCommands.ts index 930acd52a1ad1..6c234a113c068 100644 --- a/src/vs/workbench/browser/actions/workspaceCommands.ts +++ b/src/vs/workbench/browser/actions/workspaceCommands.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { hasWorkspaceFileExtension, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; -import { dirname, removeTrailingPathSeparator } from 'vs/base/common/resources'; +import { dirname } from 'vs/base/common/resources'; import { CancellationToken } from 'vs/base/common/cancellation'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; @@ -69,7 +69,7 @@ CommandsRegistry.registerCommand({ return; } - await workspaceEditingService.addFolders(folders.map(folder => ({ uri: removeTrailingPathSeparator(folder) }))); + await workspaceEditingService.addFolders(folders.map(folder => ({ uri: folder }))); } }); @@ -84,7 +84,7 @@ CommandsRegistry.registerCommand({ return; } - await workspaceEditingService.updateFolders(0, contextService.getWorkspace().folders.length, folders.map(folder => ({ uri: removeTrailingPathSeparator(folder) }))); + await workspaceEditingService.updateFolders(0, contextService.getWorkspace().folders.length, folders.map(folder => ({ uri: folder }))); } }); diff --git a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts index 4da4c1acbb739..bd4868724fb5e 100644 --- a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts @@ -14,7 +14,7 @@ import { ConfigurationScope, IConfigurationRegistry, Extensions as Configuration import { Registry } from 'vs/platform/registry/common/platform'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { distinct, firstOrDefault } from 'vs/base/common/arrays'; -import { basename, isEqual, isEqualAuthority } from 'vs/base/common/resources'; +import { basename, isEqual, isEqualAuthority, removeTrailingPathSeparator } from 'vs/base/common/resources'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IFileService } from 'vs/platform/files/common/files'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -96,23 +96,28 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi return `workspace.${WORKSPACE_EXTENSION}`; } - updateFolders(index: number, deleteCount?: number, foldersToAdd?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): Promise { + async updateFolders(index: number, deleteCount?: number, foldersToAddCandidates?: IWorkspaceFolderCreationData[], donotNotifyError?: boolean): Promise { const folders = this.contextService.getWorkspace().folders; let foldersToDelete: URI[] = []; if (typeof deleteCount === 'number') { - foldersToDelete = folders.slice(index, index + deleteCount).map(f => f.uri); + foldersToDelete = folders.slice(index, index + deleteCount).map(folder => folder.uri); + } + + let foldersToAdd: IWorkspaceFolderCreationData[] = []; + if (Array.isArray(foldersToAddCandidates)) { + foldersToAdd = foldersToAddCandidates.map(folderToAdd => ({ uri: removeTrailingPathSeparator(folderToAdd.uri), name: folderToAdd.name })); // Normalize } const wantsToDelete = foldersToDelete.length > 0; - const wantsToAdd = Array.isArray(foldersToAdd) && foldersToAdd.length > 0; + const wantsToAdd = foldersToAdd.length > 0; if (!wantsToAdd && !wantsToDelete) { - return Promise.resolve(); // return early if there is nothing to do + return; // return early if there is nothing to do } // Add Folders - if (wantsToAdd && !wantsToDelete && Array.isArray(foldersToAdd)) { + if (wantsToAdd && !wantsToDelete) { return this.doAddFolders(foldersToAdd, index, donotNotifyError); } @@ -128,16 +133,16 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi // other folders, we handle this specially and just enter workspace // mode with the folders that are being added. if (this.includesSingleFolderWorkspace(foldersToDelete)) { - return this.createAndEnterWorkspace(foldersToAdd!); + return this.createAndEnterWorkspace(foldersToAdd); } // if we are not in workspace-state, we just add the folders if (this.contextService.getWorkbenchState() !== WorkbenchState.WORKSPACE) { - return this.doAddFolders(foldersToAdd!, index, donotNotifyError); + return this.doAddFolders(foldersToAdd, index, donotNotifyError); } // finally, update folders within the workspace - return this.doUpdateFolders(foldersToAdd!, foldersToDelete, index, donotNotifyError); + return this.doUpdateFolders(foldersToAdd, foldersToDelete, index, donotNotifyError); } } @@ -153,7 +158,11 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi } } - addFolders(foldersToAdd: IWorkspaceFolderCreationData[], donotNotifyError: boolean = false): Promise { + addFolders(foldersToAddCandidates: IWorkspaceFolderCreationData[], donotNotifyError: boolean = false): Promise { + + // Normalize + const foldersToAdd = foldersToAddCandidates.map(folderToAdd => ({ uri: removeTrailingPathSeparator(folderToAdd.uri), name: folderToAdd.name })); + return this.doAddFolders(foldersToAdd, undefined, donotNotifyError); } @@ -240,7 +249,7 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi return this.enterWorkspace(path); } - async saveAndEnterWorkspace(path: URI): Promise { + async saveAndEnterWorkspace(workspaceUri: URI): Promise { const workspaceIdentifier = this.getCurrentWorkspaceIdentifier(); if (!workspaceIdentifier) { return; @@ -248,21 +257,21 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi // Allow to save the workspace of the current window // if we have an identical match on the path - if (isEqual(workspaceIdentifier.configPath, path)) { + if (isEqual(workspaceIdentifier.configPath, workspaceUri)) { return this.saveWorkspace(workspaceIdentifier); } // From this moment on we require a valid target that is not opened already - if (!await this.isValidTargetWorkspacePath(path)) { + if (!await this.isValidTargetWorkspacePath(workspaceUri)) { return; } - await this.saveWorkspaceAs(workspaceIdentifier, path); + await this.saveWorkspaceAs(workspaceIdentifier, workspaceUri); - return this.enterWorkspace(path); + return this.enterWorkspace(workspaceUri); } - async isValidTargetWorkspacePath(path: URI): Promise { + async isValidTargetWorkspacePath(workspaceUri: URI): Promise { return true; // OK } @@ -339,14 +348,14 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi ); } - abstract enterWorkspace(path: URI): Promise; + abstract enterWorkspace(workspaceUri: URI): Promise; - protected async doEnterWorkspace(path: URI): Promise { + protected async doEnterWorkspace(workspaceUri: URI): Promise { if (!!this.environmentService.extensionTestsLocationURI) { throw new Error('Entering a new workspace is not possible in tests.'); } - const workspace = await this.workspacesService.getWorkspaceIdentifier(path); + const workspace = await this.workspacesService.getWorkspaceIdentifier(workspaceUri); // Settings migration (only if we come from a folder workspace) if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { @@ -356,7 +365,7 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi const workspaceImpl = this.contextService as WorkspaceService; await workspaceImpl.initialize(workspace); - return this.workspacesService.enterWorkspace(path); + return this.workspacesService.enterWorkspace(workspaceUri); } private migrateWorkspaceSettings(toWorkspace: IWorkspaceIdentifier): Promise { diff --git a/src/vs/workbench/services/workspaces/browser/workspaceEditingService.ts b/src/vs/workbench/services/workspaces/browser/workspaceEditingService.ts index 8f9a668b9f913..b5230e4d64125 100644 --- a/src/vs/workbench/services/workspaces/browser/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/browser/workspaceEditingService.ts @@ -43,12 +43,12 @@ export class BrowserWorkspaceEditingService extends AbstractWorkspaceEditingServ super(jsonEditingService, contextService, configurationService, notificationService, commandService, fileService, textFileService, workspacesService, environmentService, fileDialogService, dialogService, hostService, uriIdentityService, workspaceTrustManagementService); } - async enterWorkspace(path: URI): Promise { - const result = await this.doEnterWorkspace(path); + async enterWorkspace(workspaceUri: URI): Promise { + const result = await this.doEnterWorkspace(workspaceUri); if (result) { // Open workspace in same window - await this.hostService.openWindow([{ workspaceUri: path }], { forceReuseWindow: true }); + await this.hostService.openWindow([{ workspaceUri }], { forceReuseWindow: true }); } } } diff --git a/src/vs/workbench/services/workspaces/browser/workspaces.ts b/src/vs/workbench/services/workspaces/browser/workspaces.ts index 98278cf23ea2a..d180ef2896cf3 100644 --- a/src/vs/workbench/services/workspaces/browser/workspaces.ts +++ b/src/vs/workbench/services/workspaces/browser/workspaces.ts @@ -11,10 +11,10 @@ import { hash } from 'vs/base/common/hash'; // NOTE: DO NOT CHANGE. IDENTIFIERS HAVE TO REMAIN STABLE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -export function getWorkspaceIdentifier(workspacePath: URI): IWorkspaceIdentifier { +export function getWorkspaceIdentifier(workspaceUri: URI): IWorkspaceIdentifier { return { - id: getWorkspaceId(workspacePath), - configPath: workspacePath + id: getWorkspaceId(workspaceUri), + configPath: workspaceUri }; } @@ -22,10 +22,10 @@ export function getWorkspaceIdentifier(workspacePath: URI): IWorkspaceIdentifier // NOTE: DO NOT CHANGE. IDENTIFIERS HAVE TO REMAIN STABLE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -export function getSingleFolderWorkspaceIdentifier(folderPath: URI): ISingleFolderWorkspaceIdentifier { +export function getSingleFolderWorkspaceIdentifier(folderUri: URI): ISingleFolderWorkspaceIdentifier { return { - id: getWorkspaceId(folderPath), - uri: folderPath + id: getWorkspaceId(folderUri), + uri: folderUri }; } diff --git a/src/vs/workbench/services/workspaces/browser/workspacesService.ts b/src/vs/workbench/services/workspaces/browser/workspacesService.ts index 64c1d2d19c9ac..3723350dcd493 100644 --- a/src/vs/workbench/services/workspaces/browser/workspacesService.ts +++ b/src/vs/workbench/services/workspaces/browser/workspacesService.ts @@ -167,8 +167,8 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS //#region Workspace Management - async enterWorkspace(path: URI): Promise { - return { workspace: await this.getWorkspaceIdentifier(path) }; + async enterWorkspace(workspaceUri: URI): Promise { + return { workspace: await this.getWorkspaceIdentifier(workspaceUri) }; } async createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise { @@ -200,8 +200,8 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS } } - async getWorkspaceIdentifier(workspacePath: URI): Promise { - return getWorkspaceIdentifier(workspacePath); + async getWorkspaceIdentifier(workspaceUri: URI): Promise { + return getWorkspaceIdentifier(workspaceUri); } //#endregion diff --git a/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts b/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts index 36afeafd483e3..e63f50d9d3584 100644 --- a/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts @@ -139,14 +139,14 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi } } - override async isValidTargetWorkspacePath(path: URI): Promise { + override async isValidTargetWorkspacePath(workspaceUri: URI): Promise { const windows = await this.nativeHostService.getWindows(); // Prevent overwriting a workspace that is currently opened in another window - if (windows.some(window => isWorkspaceIdentifier(window.workspace) && this.uriIdentityService.extUri.isEqual(window.workspace.configPath, path))) { + if (windows.some(window => isWorkspaceIdentifier(window.workspace) && this.uriIdentityService.extUri.isEqual(window.workspace.configPath, workspaceUri))) { await this.dialogService.show( Severity.Info, - localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)), + localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(workspaceUri)), undefined, { detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again.") @@ -159,8 +159,8 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi return true; // OK } - async enterWorkspace(path: URI): Promise { - const result = await this.doEnterWorkspace(path); + async enterWorkspace(workspaceUri: URI): Promise { + const result = await this.doEnterWorkspace(workspaceUri); if (result) { // Migrate storage to new workspace From 236c75b5bf6ecc2af3029b86afef56b7b2880eff Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Feb 2022 09:03:24 +0100 Subject: [PATCH 4/8] text editors - cleanup view state handling --- .../browser/parts/editor/textDiffEditor.ts | 28 ++++++++++-------- .../parts/editor/textResourceEditor.ts | 29 +++++++++---------- src/vs/workbench/common/editor.ts | 18 +++++++++++- .../workbench/common/editor/editorOptions.ts | 9 +++--- .../files/browser/editors/textFileEditor.ts | 11 ++----- .../editor/browser/codeEditorService.ts | 2 +- .../test/browser/parts/editor/editor.test.ts | 28 +++++++++++++++++- 7 files changed, 83 insertions(+), 42 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index c3b2c140dc12b..3078d3eb35e8d 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -9,7 +9,7 @@ import { isObject, isArray, assertIsDefined, withUndefinedAsNull, withNullAsUnde import { IDiffEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; -import { TEXT_DIFF_EDITOR_ID, IEditorFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorOpenContext, EditorInputCapabilities, isEditorInput } from 'vs/workbench/common/editor'; +import { TEXT_DIFF_EDITOR_ID, IEditorFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorOpenContext, EditorInputCapabilities, isEditorInput, isTextEditorViewState } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -140,18 +140,18 @@ export class TextDiffEditor extends BaseTextEditor impleme const resolvedDiffEditorModel = resolvedModel as TextDiffEditorModel; diffEditor.setModel(withUndefinedAsNull(resolvedDiffEditorModel.textDiffEditorModel)); - /// Apply options to editor if any + // Restore view state (unless provided by options) + let hasPreviousViewState = false; + if (!isTextEditorViewState(options?.viewState)) { + hasPreviousViewState = this.restoreTextDiffEditorViewState(input, options, context, diffEditor); + } + + // Apply options to editor if any let optionsGotApplied = false; if (options) { optionsGotApplied = applyTextEditorOptions(options, diffEditor, ScrollType.Immediate); } - // Otherwise restore View State unless disabled via settings - let hasPreviousViewState = false; - if (!optionsGotApplied) { - hasPreviousViewState = this.restoreTextDiffEditorViewState(input, context, diffEditor); - } - // Diff navigator this.diffNavigator = new DiffNavigator(diffEditor, { alwaysRevealFirst: !optionsGotApplied && !hasPreviousViewState // only reveal first change if we had no options or viewstate @@ -179,10 +179,14 @@ export class TextDiffEditor extends BaseTextEditor impleme } } - private restoreTextDiffEditorViewState(editor: DiffEditorInput, context: IEditorOpenContext, control: IDiffEditor): boolean { - const viewState = this.loadEditorViewState(editor, context); - if (viewState) { - control.restoreViewState(viewState); + private restoreTextDiffEditorViewState(editor: DiffEditorInput, options: ITextEditorOptions | undefined, context: IEditorOpenContext, control: IDiffEditor): boolean { + const editorViewState = this.loadEditorViewState(editor, context); + if (editorViewState) { + if (options?.selection && editorViewState.modified) { + editorViewState.modified.cursorState = []; // prevent duplicate selections via options + } + + control.restoreViewState(editorViewState); return true; } diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index 9dfdeab236996..f7d4fadab0499 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { ICodeEditor, getCodeEditor, IPasteEvent } from 'vs/editor/browser/editorBrowser'; -import { IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext, isTextEditorViewState } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { AbstractTextResourceEditorInput, TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; @@ -77,15 +77,21 @@ export class AbstractTextResourceEditor extends BaseTextEditor { textEditor.setModel(textFileModel.textEditorModel); // Restore view state (unless provided by options) - if (!options?.viewState) { + if (!isTextEditorViewState(options?.viewState)) { const editorViewState = this.loadEditorViewState(input, context); if (editorViewState) { if (options?.selection) { - // If we have a selection, make sure to not - // restore any selection from the view state - // to ensure the right selection change event - // is fired and we avoid changing selections - // twice. - editorViewState.cursorState = []; + editorViewState.cursorState = []; // prevent duplicate selections via options } textEditor.restoreViewState(editorViewState); diff --git a/src/vs/workbench/services/editor/browser/codeEditorService.ts b/src/vs/workbench/services/editor/browser/codeEditorService.ts index 95b97f44c6cc3..0aaf3980f4f26 100644 --- a/src/vs/workbench/services/editor/browser/codeEditorService.ts +++ b/src/vs/workbench/services/editor/browser/codeEditorService.ts @@ -57,7 +57,7 @@ export class CodeEditorService extends AbstractCodeEditorService { input.resource && // we need a request resource to compare with source === activeTextEditorControl.getModifiedEditor() && // we need the source of this request to be the modified side of the diff editor activeTextEditorControl.getModel() && // we need a target model to compare with - isEqual(input.resource, activeTextEditorControl.getModel()!.modified.uri) // we need the input resources to match with modified side + isEqual(input.resource, activeTextEditorControl.getModel()?.modified.uri) // we need the input resources to match with modified side ) { const targetEditor = activeTextEditorControl.getModifiedEditor(); diff --git a/src/vs/workbench/test/browser/parts/editor/editor.test.ts b/src/vs/workbench/test/browser/parts/editor/editor.test.ts index c0c2e4f1bf429..74e548d78f6c2 100644 --- a/src/vs/workbench/test/browser/parts/editor/editor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editor.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorResourceAccessor, SideBySideEditor, EditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, isResourceEditorInput, isUntitledResourceEditorInput, isResourceDiffEditorInput, isEditorInputWithOptionsAndGroup, EditorInputWithOptions, isEditorInputWithOptions, isEditorInput, EditorInputWithOptionsAndGroup, isResourceSideBySideEditorInput, IResourceSideBySideEditorInput } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, SideBySideEditor, EditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, isResourceEditorInput, isUntitledResourceEditorInput, isResourceDiffEditorInput, isEditorInputWithOptionsAndGroup, EditorInputWithOptions, isEditorInputWithOptions, isEditorInput, EditorInputWithOptionsAndGroup, isResourceSideBySideEditorInput, IResourceSideBySideEditorInput, isTextEditorViewState } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -20,6 +20,8 @@ import { EditorService } from 'vs/workbench/services/editor/browser/editorServic import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { EditorResolution, IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { ICodeEditorViewState, IDiffEditorViewState } from 'vs/editor/common/editorCommon'; +import { Position } from 'vs/editor/common/core/position'; suite('Workbench editor utils', () => { @@ -364,6 +366,30 @@ suite('Workbench editor utils', () => { assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInputWithOptionsAndGroup), true); }); + test('isTextEditorViewState', () => { + assert.strictEqual(isTextEditorViewState(undefined), false); + assert.strictEqual(isTextEditorViewState({}), false); + + const codeEditorViewState: ICodeEditorViewState = { + contributionsState: {}, + cursorState: [], + viewState: { + scrollLeft: 0, + firstPosition: new Position(1, 1), + firstPositionDeltaTop: 1 + } + }; + + assert.strictEqual(isTextEditorViewState(codeEditorViewState), true); + + const diffEditorViewState: IDiffEditorViewState = { + original: codeEditorViewState, + modified: codeEditorViewState + }; + + assert.strictEqual(isTextEditorViewState(diffEditorViewState), true); + }); + test('whenEditorClosed (single editor)', async function () { return testWhenEditorClosed(false, false, toResource.call(this, '/path/index.txt')); }); From 28034e015c9b7483f773208d4e2aaf1bd7af119c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Feb 2022 09:26:32 +0100 Subject: [PATCH 5/8] storage - further tweak lifecycle behaviour --- src/vs/base/parts/storage/common/storage.ts | 2 +- .../storage/electron-main/storageMain.ts | 27 ++++++++++++------- .../electron-main/storageMainService.ts | 22 +++++++-------- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/vs/base/parts/storage/common/storage.ts b/src/vs/base/parts/storage/common/storage.ts index c892f8fbef3fa..a6bfeaefbd985 100644 --- a/src/vs/base/parts/storage/common/storage.ts +++ b/src/vs/base/parts/storage/common/storage.ts @@ -74,7 +74,7 @@ export interface IStorage extends IDisposable { close(): Promise; } -enum StorageState { +export enum StorageState { None, Initialized, Closed diff --git a/src/vs/platform/storage/electron-main/storageMain.ts b/src/vs/platform/storage/electron-main/storageMain.ts index cc650f3b0e15d..b817dd7832730 100644 --- a/src/vs/platform/storage/electron-main/storageMain.ts +++ b/src/vs/platform/storage/electron-main/storageMain.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { join } from 'vs/base/common/path'; import { Promises } from 'vs/base/node/pfs'; -import { InMemoryStorageDatabase, IStorage, Storage, StorageHint } from 'vs/base/parts/storage/common/storage'; +import { InMemoryStorageDatabase, IStorage, Storage, StorageHint, StorageState } from 'vs/base/parts/storage/common/storage'; import { ISQLiteStorageDatabaseLoggingOptions, SQLiteStorageDatabase } from 'vs/base/parts/storage/node/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; @@ -107,6 +107,8 @@ abstract class BaseStorageMain extends Disposable implements IStorageMain { private readonly whenInitPromise = new DeferredPromise(); readonly whenInit = this.whenInitPromise.p; + private state = StorageState.None; + constructor( protected readonly logService: ILogService ) { @@ -116,6 +118,10 @@ abstract class BaseStorageMain extends Disposable implements IStorageMain { init(): Promise { if (!this.initializePromise) { this.initializePromise = (async () => { + if (this.state !== StorageState.None) { + return; // either closed or already initialized + } + try { // Create storage via subclasses @@ -143,6 +149,11 @@ abstract class BaseStorageMain extends Disposable implements IStorageMain { } catch (error) { this.logService.error(`StorageMain#initialize(): Unable to init storage due to ${error}`); } finally { + + // Update state + this.state = StorageState.Initialized; + + // Mark init promise as completed this.whenInitPromise.complete(); } })(); @@ -184,12 +195,15 @@ abstract class BaseStorageMain extends Disposable implements IStorageMain { // Ensure we are not accidentally leaving // a pending initialized storage behind in - // case close() was called before init() - // finishes + // case `close()` was called before `init()` + // finishes. if (this.initializePromise) { await this.initializePromise; } + // Update state + this.state = StorageState.Closed; + // Propagate to storage lib await this._storage.close(); @@ -316,10 +330,3 @@ export class WorkspaceStorageMain extends BaseStorageMain implements IStorageMai } } } - -export class InMemoryStorageMain extends BaseStorageMain { - - protected async doCreate(): Promise { - return new Storage(new InMemoryStorageDatabase()); - } -} diff --git a/src/vs/platform/storage/electron-main/storageMainService.ts b/src/vs/platform/storage/electron-main/storageMainService.ts index c398abc7927fb..53491f6f089a8 100644 --- a/src/vs/platform/storage/electron-main/storageMainService.ts +++ b/src/vs/platform/storage/electron-main/storageMainService.ts @@ -9,10 +9,10 @@ import { IStorage } from 'vs/base/parts/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { ILifecycleMainService, LifecycleMainPhase, ShutdownReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; +import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILogService } from 'vs/platform/log/common/log'; import { AbstractStorageService, IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { GlobalStorageMain, InMemoryStorageMain, IStorageMain, IStorageMainOptions, WorkspaceStorageMain } from 'vs/platform/storage/electron-main/storageMain'; +import { GlobalStorageMain, IStorageMain, IStorageMainOptions, WorkspaceStorageMain } from 'vs/platform/storage/electron-main/storageMain'; import { IAnyWorkspaceIdentifier, IEmptyWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace'; //#region Storage Main Service (intent: make global and workspace storage accessible to windows from main process) @@ -44,7 +44,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic declare readonly _serviceBrand: undefined; - private shutdownReason: ShutdownReason | undefined = undefined; + private willShutdown: boolean = false; constructor( @ILogService private readonly logService: ILogService, @@ -82,8 +82,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic this._register(this.lifecycleMainService.onWillShutdown(e => { this.logService.trace('storageMainService#onWillShutdown()'); - // Remember shutdown reason - this.shutdownReason = e.reason; + this.willShutdown = true; // Global Storage e.join(this.globalStorage.close()); @@ -119,6 +118,10 @@ export class StorageMainService extends Disposable implements IStorageMainServic private readonly mapWorkspaceToStorage = new Map(); workspaceStorage(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IEmptyWorkspaceIdentifier): IStorageMain { + if (this.willShutdown) { + throw new Error('Refusing to create workspace storage for application will shutdown.'); + } + let workspaceStorage = this.mapWorkspaceToStorage.get(workspace.id); if (!workspaceStorage) { this.logService.trace(`StorageMainService: creating workspace storage (${workspace.id})`); @@ -137,14 +140,9 @@ export class StorageMainService extends Disposable implements IStorageMainServic } private createWorkspaceStorage(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IEmptyWorkspaceIdentifier): IStorageMain { - if (this.shutdownReason === ShutdownReason.KILL) { - // Workaround for native crashes that we see when - // SQLite DBs are being created even after shutdown - // https://github.com/microsoft/vscode/issues/143186 - return new InMemoryStorageMain(this.logService); - } + const workspaceStorage = new WorkspaceStorageMain(workspace, this.getStorageOptions(), this.logService, this.environmentService); - return new WorkspaceStorageMain(workspace, this.getStorageOptions(), this.logService, this.environmentService); + return workspaceStorage; } //#endregion From 4a282b459eddff6b086d12a335bee29be0a63db9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Feb 2022 09:57:55 +0100 Subject: [PATCH 6/8] lifecycle - remove unused `onBeforeUnloadWindow` --- .../electron-main/lifecycleMainService.ts | 53 ------------------- .../electron-main/storageMainService.test.ts | 1 - .../services/lifecycle/common/lifecycle.ts | 22 +++++--- 3 files changed, 15 insertions(+), 61 deletions(-) diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts index 69310c99ce811..6b9dd062653da 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts @@ -12,7 +12,6 @@ import { cwd } from 'vs/base/common/process'; import { assertIsDefined } from 'vs/base/common/types'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { handleVetos } from 'vs/platform/lifecycle/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateMainService } from 'vs/platform/state/electron-main/state'; import { ICodeWindow, LoadReason, UnloadReason } from 'vs/platform/window/electron-main/window'; @@ -38,25 +37,6 @@ interface WindowLoadEvent { reason: LoadReason; } -interface WindowUnloadEvent { - - /** - * The window that is unloading. - */ - window: ICodeWindow; - - /** - * More details why the window is unloading. - */ - reason: UnloadReason; - - /** - * A way to join the unloading of the window and optionally - * veto the unload to finish. - */ - veto(value: boolean | Promise): void; -} - export const enum ShutdownReason { /** @@ -124,12 +104,6 @@ export interface ILifecycleMainService { */ readonly onWillLoadWindow: Event; - /** - * An event that fires before a window is about to unload. Listeners can veto this event to prevent - * the window from unloading. - */ - readonly onBeforeUnloadWindow: Event; - /** * An event that fires before a window closes. This event is fired after any veto has been dealt * with so that listeners know for sure that the window will close without veto. @@ -220,9 +194,6 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe private readonly _onBeforeCloseWindow = this._register(new Emitter()); readonly onBeforeCloseWindow = this._onBeforeCloseWindow.event; - private readonly _onBeforeUnloadWindow = this._register(new Emitter()); - readonly onBeforeUnloadWindow = this._onBeforeUnloadWindow.event; - private _quitRequested = false; get quitRequested(): boolean { return this._quitRequested; } @@ -506,16 +477,6 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe return this.handleWindowUnloadVeto(veto); } - // then check for vetos in the main side - veto = await this.onBeforeUnloadWindowInMain(window, windowUnloadReason); - if (veto) { - this.logService.trace(`Lifecycle#unload() - veto in main (window ID ${window.id})`); - - return this.handleWindowUnloadVeto(veto); - } - - this.logService.trace(`Lifecycle#unload() - no veto (window ID ${window.id})`); - // finally if there are no vetos, unload the renderer await this.onWillUnloadWindowInRenderer(window, windowUnloadReason); @@ -562,20 +523,6 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe }); } - private onBeforeUnloadWindowInMain(window: ICodeWindow, reason: UnloadReason): Promise { - const vetos: (boolean | Promise)[] = []; - - this._onBeforeUnloadWindow.fire({ - reason, - window, - veto(value) { - vetos.push(value); - } - }); - - return handleVetos(vetos, err => this.logService.error(err)); - } - private onWillUnloadWindowInRenderer(window: ICodeWindow, reason: UnloadReason): Promise { return new Promise(resolve => { const oneTimeEventToken = this.oneTimeListenerTokenGenerator++; diff --git a/src/vs/platform/storage/test/electron-main/storageMainService.test.ts b/src/vs/platform/storage/test/electron-main/storageMainService.test.ts index fa7fc8d05915b..f3a3106da3a08 100644 --- a/src/vs/platform/storage/test/electron-main/storageMainService.test.ts +++ b/src/vs/platform/storage/test/electron-main/storageMainService.test.ts @@ -57,7 +57,6 @@ suite('StorageMainService', function () { onWillLoadWindow = Event.None; onBeforeCloseWindow = Event.None; - onBeforeUnloadWindow = Event.None; wasRestarted = false; quitRequested = false; diff --git a/src/vs/workbench/services/lifecycle/common/lifecycle.ts b/src/vs/workbench/services/lifecycle/common/lifecycle.ts index 35e6dbd0a93a4..c63c7e1dda873 100644 --- a/src/vs/workbench/services/lifecycle/common/lifecycle.ts +++ b/src/vs/workbench/services/lifecycle/common/lifecycle.ts @@ -97,17 +97,25 @@ export interface WillShutdownEvent { export const enum ShutdownReason { - /** Window is closed */ + /** + * The window is closed. + */ CLOSE = 1, - /** Application is quit */ - QUIT = 2, + /** + * The window closes because the application quits. + */ + QUIT, - /** Window is reloaded */ - RELOAD = 3, + /** + * The window is reloaded. + */ + RELOAD, - /** Other configuration loaded into window */ - LOAD = 4 + /** + * The window is loaded into a different workspace context. + */ + LOAD } export const enum StartupKind { From bb1045cde2b225bc31974d6455dfc027e084bb6d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 25 Feb 2022 10:15:50 +0100 Subject: [PATCH 7/8] lifecycle - dispose main process IPC when being killed --- src/vs/code/electron-main/app.ts | 12 +++++++++++- .../lifecycle/electron-main/lifecycleMainService.ts | 11 +++++++---- .../storage/electron-main/storageMainService.ts | 8 -------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index bc9a5dba8c882..7792c22fd6eea 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -60,7 +60,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { IIssueMainService, IssueMainService } from 'vs/platform/issue/electron-main/issueMainService'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; import { ILaunchMainService, LaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; -import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; +import { ILifecycleMainService, LifecycleMainPhase, ShutdownReason } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILoggerService, ILogService } from 'vs/platform/log/common/log'; import { LoggerChannel, LogLevelChannel } from 'vs/platform/log/common/logIpc'; import { IMenubarMainService, MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService'; @@ -471,6 +471,16 @@ export class CodeApplication extends Disposable { // Main process server (electron IPC based) const mainProcessElectronServer = new ElectronIPCServer(); + this.lifecycleMainService.onWillShutdown(e => { + if (e.reason === ShutdownReason.KILL) { + // When we go down abnormally, make sure to free up + // any IPC we accept from other windows to reduce + // the chance of doing work after we go down. Kill + // is special in that it does not orderly shutdown + // windows. + mainProcessElectronServer.dispose(); + } + }); // Resolve unique machine ID this.logService.trace('Resolving machine identifier...'); diff --git a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts index 6b9dd062653da..ac3b7bfb3b213 100644 --- a/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMainService.ts @@ -599,8 +599,8 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe }; app.once('quit', quitListener); - // app.relaunch() does not quit automatically, so we quit first, - // check for vetoes and then relaunch from the app.on('quit') event + // `app.relaunch()` does not quit automatically, so we quit first, + // check for vetoes and then relaunch from the `app.on('quit')` event const veto = await this.quit(true /* will restart */); if (veto) { app.removeListener('quit', quitListener); @@ -623,10 +623,13 @@ export class LifecycleMainService extends Disposable implements ILifecycleMainSe await Promise.race([ - // still do not block more than 1s + // Still do not block more than 1s timeout(1000), - // destroy any opened window + // Destroy any opened window: we do not unload windows here because + // there is a chance that the unload is veto'd or long running due + // to a participant within the window. this is not wanted when we + // are asked to kill the application. (async () => { for (const window of BrowserWindow.getAllWindows()) { if (window && !window.isDestroyed()) { diff --git a/src/vs/platform/storage/electron-main/storageMainService.ts b/src/vs/platform/storage/electron-main/storageMainService.ts index 53491f6f089a8..36658666615b8 100644 --- a/src/vs/platform/storage/electron-main/storageMainService.ts +++ b/src/vs/platform/storage/electron-main/storageMainService.ts @@ -44,8 +44,6 @@ export class StorageMainService extends Disposable implements IStorageMainServic declare readonly _serviceBrand: undefined; - private willShutdown: boolean = false; - constructor( @ILogService private readonly logService: ILogService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @@ -82,8 +80,6 @@ export class StorageMainService extends Disposable implements IStorageMainServic this._register(this.lifecycleMainService.onWillShutdown(e => { this.logService.trace('storageMainService#onWillShutdown()'); - this.willShutdown = true; - // Global Storage e.join(this.globalStorage.close()); @@ -118,10 +114,6 @@ export class StorageMainService extends Disposable implements IStorageMainServic private readonly mapWorkspaceToStorage = new Map(); workspaceStorage(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IEmptyWorkspaceIdentifier): IStorageMain { - if (this.willShutdown) { - throw new Error('Refusing to create workspace storage for application will shutdown.'); - } - let workspaceStorage = this.mapWorkspaceToStorage.get(workspace.id); if (!workspaceStorage) { this.logService.trace(`StorageMainService: creating workspace storage (${workspace.id})`); From 22520f9461b2843211750a476a6bcf487ffcf51e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sat, 26 Feb 2022 08:23:43 +0100 Subject: [PATCH 8/8] :lipstick: --- src/vs/workbench/services/path/common/pathService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/services/path/common/pathService.ts b/src/vs/workbench/services/path/common/pathService.ts index 5f407090cbe32..b00c949dc3fb3 100644 --- a/src/vs/workbench/services/path/common/pathService.ts +++ b/src/vs/workbench/services/path/common/pathService.ts @@ -105,7 +105,6 @@ export abstract class AbstractPathService implements IPathService { const env = await this.remoteAgentService.getEnvironment(); const userHome = this.maybeUnresolvedUserHome = env?.userHome || localUserHome; - return userHome; })(); }