Merge branch 'master' into aeschli/cssheadless

This commit is contained in:
Martin Aeschlimann 2020-05-27 10:54:07 +02:00
commit 90861d4924
223 changed files with 2381 additions and 1025 deletions

View file

@ -63,13 +63,18 @@
"browser": [
"common"
],
"electron-main": [
"electron-sandbox": [
"common",
"node"
"browser"
],
"electron-browser": [
"common",
"browser",
"node",
"electron-sandbox"
],
"electron-main": [
"common",
"node"
]
}
@ -104,6 +109,14 @@
"**/vs/base/{common,browser}/**"
]
},
{
"target": "**/vs/base/electron-sandbox/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/{common,browser,electron-sandbox}/**"
]
},
{
"target": "**/vs/base/node/**",
"restrictions": [
@ -149,13 +162,22 @@
"*" // node modules
]
},
{
"target": "**/vs/base/parts/*/electron-sandbox/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/{common,browser,electron-sandbox}/**",
"**/vs/base/parts/*/{common,browser,electron-sandbox}/**"
]
},
{
"target": "**/vs/base/parts/*/electron-browser/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/{common,browser,node,electron-browser}/**",
"**/vs/base/parts/*/{common,browser,node,electron-browser}/**",
"**/vs/base/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/base/parts/*/{common,browser,node,electron-sandbox,electron-browser}/**",
"*" // node modules
]
},
@ -210,14 +232,24 @@
"*" // node modules
]
},
{
"target": "**/vs/platform/*/electron-sandbox/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/{common,browser,electron-sandbox}/**",
"**/vs/base/parts/*/{common,browser,electron-sandbox}/**",
"**/vs/platform/*/{common,browser,electron-sandbox}/**"
]
},
{
"target": "**/vs/platform/*/electron-browser/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/{common,browser,node}/**",
"**/vs/base/parts/*/{common,browser,node,electron-browser}/**",
"**/vs/platform/*/{common,browser,node,electron-browser}/**",
"**/vs/base/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/base/parts/*/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/platform/*/{common,browser,node,electron-sandbox,electron-browser}/**",
"*" // node modules
]
},
@ -421,18 +453,34 @@
"**/vs/**/{common,worker}/**"
]
},
{
"target": "**/vs/workbench/electron-sandbox/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/{common,browser,electron-sandbox}/**",
"**/vs/base/parts/*/{common,browser,electron-sandbox}/**",
"**/vs/platform/*/{common,browser,electron-sandbox}/**",
"**/vs/editor/{common,browser,electron-sandbox}/**",
"**/vs/editor/contrib/**", // editor/contrib is equivalent to /browser/ by convention
"**/vs/workbench/{common,browser,electron-sandbox}/**",
"**/vs/workbench/api/{common,browser,electron-sandbox}/**",
"**/vs/workbench/services/*/{common,browser,electron-sandbox}/**"
]
},
{
"target": "**/vs/workbench/electron-browser/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/{common,browser,node,electron-browser}/**",
"**/vs/base/parts/*/{common,browser,node,electron-browser}/**",
"**/vs/platform/*/{common,browser,node,electron-browser}/**",
"**/vs/editor/{common,browser,node,electron-browser}/**",
"**/vs/base/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/base/parts/*/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/platform/*/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/editor/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/editor/contrib/**", // editor/contrib is equivalent to /browser/ by convention
"**/vs/workbench/{common,browser,node,electron-browser,api}/**",
"**/vs/workbench/services/*/{common,browser,node,electron-browser}/**",
"**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/api/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/services/*/{common,browser,node,electron-sandbox,electron-browser}/**",
"*" // node modules
]
},
@ -444,7 +492,7 @@
"**/vs/base/**",
"**/vs/platform/**",
"**/vs/editor/**",
"**/vs/workbench/{common,browser,node,electron-browser}/**",
"**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**",
"vs/workbench/contrib/files/common/editors/fileEditorInput",
"**/vs/workbench/services/**",
"**/vs/workbench/test/**",
@ -508,16 +556,30 @@
"*" // node modules
]
},
{
"target": "**/vs/workbench/services/**/electron-sandbox/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/**/{common,browser,worker,electron-sandbox}/**",
"**/vs/platform/**/{common,browser,electron-sandbox}/**",
"**/vs/editor/**",
"**/vs/workbench/{common,browser,electron-sandbox}/**",
"**/vs/workbench/api/{common,browser,electron-sandbox}/**",
"**/vs/workbench/services/**/{common,browser,electron-sandbox}/**"
]
},
{
"target": "**/vs/workbench/services/**/electron-browser/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/**/{common,browser,worker,node,electron-browser}/**",
"**/vs/platform/**/{common,browser,node,electron-browser}/**",
"**/vs/base/**/{common,browser,worker,node,electron-sandbox,electron-browser}/**",
"**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/editor/**",
"**/vs/workbench/{common,browser,node,electron-browser,api}/**",
"**/vs/workbench/services/**/{common,browser,node,electron-browser}/**",
"**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/api/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/services/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"*" // node modules
]
},
@ -530,7 +592,7 @@
"**/vs/base/**",
"**/vs/platform/**",
"**/vs/editor/**",
"**/vs/workbench/{common,browser,node,electron-browser}/**",
"**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/services/**",
"**/vs/workbench/contrib/**",
"**/vs/workbench/test/**",
@ -624,17 +686,32 @@
"*" // node modules
]
},
{
"target": "**/vs/workbench/contrib/**/electron-sandbox/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/**/{common,browser,worker,electron-sandbox}/**",
"**/vs/platform/**/{common,browser,electron-sandbox}/**",
"**/vs/editor/**",
"**/vs/workbench/{common,browser,electron-sandbox}/**",
"**/vs/workbench/api/{common,browser,electron-sandbox}/**",
"**/vs/workbench/services/**/{common,browser,electron-sandbox}/**",
"**/vs/workbench/contrib/**/{common,browser,electron-sandbox}/**"
]
},
{
"target": "**/vs/workbench/contrib/**/electron-browser/**",
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/**/{common,browser,worker,node,electron-browser}/**",
"**/vs/platform/**/{common,browser,node,electron-browser}/**",
"**/vs/base/**/{common,browser,worker,node,electron-sandbox,electron-browser}/**",
"**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/editor/**",
"**/vs/workbench/{common,browser,node,electron-browser,api}/**",
"**/vs/workbench/services/**/{common,browser,node,electron-browser}/**",
"**/vs/workbench/contrib/**/{common,browser,node,electron-browser}/**",
"**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/api/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/services/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/contrib/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"*" // node modules
]
},
@ -654,10 +731,10 @@
"restrictions": [
"vs/nls",
"vs/css!./**/*",
"**/vs/base/**/{common,browser,node,electron-browser}/**",
"**/vs/base/parts/**/{common,browser,node,electron-browser}/**",
"**/vs/platform/**/{common,browser,node,electron-browser}/**",
"**/vs/code/**/{common,browser,node,electron-browser}/**",
"**/vs/base/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/base/parts/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/code/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"*" // node modules
]
},
@ -685,6 +762,54 @@
"*" // node modules
]
},
{
"target": "**/src/vs/workbench/workbench.common.main.ts",
"restrictions": [
"vs/nls",
"**/vs/base/**/{common,browser}/**",
"**/vs/base/parts/**/{common,browser}/**",
"**/vs/platform/**/{common,browser}/**",
"**/vs/editor/**",
"**/vs/workbench/**/{common,browser}/**"
]
},
{
"target": "**/src/vs/workbench/workbench.web.main.ts",
"restrictions": [
"vs/nls",
"**/vs/base/**/{common,browser}/**",
"**/vs/base/parts/**/{common,browser}/**",
"**/vs/platform/**/{common,browser}/**",
"**/vs/editor/**",
"**/vs/workbench/**/{common,browser}/**",
"**/vs/workbench/workbench.common.main"
]
},
{
"target": "**/src/vs/workbench/workbench.sandbox.main.ts",
"restrictions": [
"vs/nls",
"**/vs/base/**/{common,browser,electron-sandbox}/**",
"**/vs/base/parts/**/{common,browser,electron-sandbox}/**",
"**/vs/platform/**/{common,browser,electron-sandbox}/**",
"**/vs/editor/**",
"**/vs/workbench/**/{common,browser,electron-sandbox}/**",
"**/vs/workbench/workbench.common.main"
]
},
{
"target": "**/src/vs/workbench/workbench.desktop.main.ts",
"restrictions": [
"vs/nls",
"**/vs/base/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/base/parts/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/editor/**",
"**/vs/workbench/**/{common,browser,node,electron-sandbox,electron-browser}/**",
"**/vs/workbench/workbench.common.main",
"**/vs/workbench/workbench.sandbox.main"
]
},
{
"target": "**/extensions/**",
"restrictions": "**/*"

View file

@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v16
ref: v17
path: ./actions
- name: Install Actions
if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'author-verification-requested')

View file

@ -11,7 +11,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v16
ref: v17
path: ./actions
- name: Install Actions
run: npm install --production --prefix ./actions

View file

@ -13,7 +13,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v16
ref: v17
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run Commands

View file

@ -13,7 +13,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v16
ref: v17
path: ./actions
- name: Install Actions
if: contains(github.event.issue.labels.*.name, '*english-please')

View file

@ -17,7 +17,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v16
ref: v17
- name: Install Actions
if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request')
run: npm install --production --prefix ./actions

View file

@ -13,7 +13,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v16
ref: v17
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run Locker

View file

@ -13,7 +13,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v16
ref: v17
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run Needs More Info Closer

View file

@ -11,7 +11,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v16
ref: v17
path: ./actions
- name: Install Actions
run: npm install --production --prefix ./actions

View file

@ -11,7 +11,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v16
ref: v17
path: ./actions
- name: Install Actions
run: npm install --production --prefix ./actions

View file

@ -14,7 +14,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v16
ref: v17
- name: Install Actions
if: contains(github.event.issue.labels.*.name, 'testplan-item') || contains(github.event.issue.labels.*.name, 'invalid-testplan-item')
run: npm install --production --prefix ./actions

View file

@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron"
target "8.3.0"
target "7.2.4"
runtime "electron"

View file

@ -10,11 +10,11 @@ const path = require('path');
let window = null;
app.once('ready', () => {
window = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, webviewTag: true, enableWebSQL: false } });
window = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, webviewTag: true } });
window.setMenuBarVisibility(false);
window.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true }));
// window.webContents.openDevTools();
window.once('closed', () => window = null);
});
app.on('window-all-closed', () => app.quit());
app.on('window-all-closed', () => app.quit());

View file

@ -66,6 +66,7 @@ const vscodeResources = [
'out-build/vs/base/node/languagePacks.js',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}',
'out-build/vs/base/browser/ui/codicons/codicon/**',
'out-build/vs/base/parts/sandbox/electron-browser/preload.js',
'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/contrib/debug/**/*.json',
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
@ -154,6 +155,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
const out = sourceFolderName;
const checksums = computeChecksums(out, [
'vs/base/parts/sandbox/electron-browser/preload.js',
'vs/workbench/workbench.desktop.main.js',
'vs/workbench/workbench.desktop.main.css',
'vs/workbench/services/extensions/node/extensionHostProcess.js',

View file

@ -130,6 +130,14 @@ const RULES = [
'lib.dom.d.ts' // no DOM
]
},
// Electron (sandbox)
{
target: '**/vs/**/electron-sandbox/**',
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Electron (renderer): skip
{
target: '**/vs/**/electron-browser/**',

View file

@ -143,6 +143,15 @@ const RULES = [
]
},
// Electron (sandbox)
{
target: '**/vs/**/electron-sandbox/**',
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Electron (renderer): skip
{
target: '**/vs/**/electron-browser/**',

View file

@ -6,7 +6,7 @@
"git": {
"name": "chromium",
"repositoryUrl": "https://chromium.googlesource.com/chromium/src",
"commitHash": "052d3b44972e6d94ef40054d46c150b7cdd7a5d8"
"commitHash": "e4745133a1d3745f066e068b8033c6a269b59caf"
}
},
"licenseDetail": [
@ -40,7 +40,7 @@
"SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
],
"isOnlyProductionDependency": true,
"version": "80.0.3987.165"
"version": "78.0.3904.130"
},
{
"component": {
@ -48,11 +48,11 @@
"git": {
"name": "nodejs",
"repositoryUrl": "https://github.com/nodejs/node",
"commitHash": "42cce5a9d0fd905bf4ad7a2528c36572dfb8b5ad"
"commitHash": "787378879acfb212ed4ff824bf9f767a24a5cb43a"
}
},
"isOnlyProductionDependency": true,
"version": "12.13.0"
"version": "12.8.1"
},
{
"component": {
@ -60,12 +60,12 @@
"git": {
"name": "electron",
"repositoryUrl": "https://github.com/electron/electron",
"commitHash": "426d45cd8569fb7731f213159336cea019829ec5"
"commitHash": "0552e0d5de46ffa3b481d741f1db5c779e201565"
}
},
"isOnlyProductionDependency": true,
"license": "MIT",
"version": "8.3.0"
"version": "7.2.4"
},
{
"component": {

View file

@ -488,7 +488,7 @@
"t": "source.batchfile constant.character.escape.batchfile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "constant.character: #569CD6"
@ -510,7 +510,7 @@
"t": "source.batchfile constant.character.escape.batchfile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "constant.character: #569CD6"

View file

@ -1555,7 +1555,7 @@
"t": "source.coffee string.regexp.multiline.coffee keyword.control.anchor.regexp",
"r": {
"dark_plus": "keyword.control.anchor.regexp: #DCDCAA",
"light_plus": "keyword.control.anchor.regexp: #FF0000",
"light_plus": "keyword.control.anchor.regexp: #EE0000",
"dark_vs": "keyword.control: #569CD6",
"light_vs": "keyword.control: #0000FF",
"hc_black": "keyword.control: #C586C0"
@ -1605,4 +1605,4 @@
"hc_black": "string.regexp: #D16969"
}
}
]
]

View file

@ -191,7 +191,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -257,7 +257,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -389,7 +389,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.block.struct.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -433,7 +433,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.block.struct.cpp meta.body.struct.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -532,7 +532,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.block.struct.cpp meta.body.struct.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -587,7 +587,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -719,7 +719,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -763,7 +763,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -862,7 +862,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -906,7 +906,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -1027,7 +1027,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -1071,7 +1071,7 @@
"t": "source.cpp meta.preprocessor.macro.cpp constant.character.escape.line-continuation.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "constant.character: #569CD6"
@ -1187,4 +1187,4 @@
"hc_black": "meta.preprocessor: #569CD6"
}
}
]
]

View file

@ -2314,7 +2314,7 @@
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp constant.character.escape.cpp",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -2430,4 +2430,4 @@
"hc_black": "default: #FFFFFF"
}
}
]
]

View file

@ -26,6 +26,7 @@
".webmanifest",
".js.map",
".css.map",
".ts.map",
".har",
".jslintrc",
".jsonld"

View file

@ -389,7 +389,7 @@
"t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json constant.character.escape.json",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -1165,4 +1165,4 @@
"hc_black": "default: #FFFFFF"
}
}
]
]

View file

@ -136,7 +136,7 @@
"t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "constant.character: #569CD6"
@ -279,7 +279,7 @@
"t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "constant.character: #569CD6"
@ -323,7 +323,7 @@
"t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "comment: #6A9955",
"light_vs": "comment: #008000",
"hc_black": "constant.character: #569CD6"
@ -378,7 +378,7 @@
"t": "source.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "comment: #6A9955",
"light_vs": "comment: #008000",
"hc_black": "constant.character: #569CD6"
@ -554,7 +554,7 @@
"t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "constant.character: #569CD6"
@ -884,7 +884,7 @@
"t": "source.makefile meta.scope.recipe.makefile constant.character.escape.continuation.makefile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "constant.character: #569CD6"
@ -3029,7 +3029,7 @@
"t": "source.makefile constant.character.escape.continuation.makefile",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "constant.character: #569CD6"

View file

@ -1302,7 +1302,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -1324,7 +1324,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -1346,7 +1346,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -1775,7 +1775,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"

View file

@ -389,7 +389,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -411,7 +411,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -433,7 +433,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -455,7 +455,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -477,7 +477,7 @@
"t": "source.perl string.regexp.find.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -675,7 +675,7 @@
"t": "source.perl string.quoted.double.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -950,7 +950,7 @@
"t": "source.perl string.quoted.double.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -1445,7 +1445,7 @@
"t": "source.perl string.quoted.double.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -2281,7 +2281,7 @@
"t": "source.perl string.quoted.double.perl constant.character.escape.perl",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"

View file

@ -279,7 +279,7 @@
"t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -378,7 +378,7 @@
"t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"

View file

@ -565,7 +565,7 @@
"t": "source.python string.quoted.single.python constant.character.escape.python",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"

View file

@ -2501,7 +2501,7 @@
"t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -2523,7 +2523,7 @@
"t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -2545,7 +2545,7 @@
"t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"
@ -2578,7 +2578,7 @@
"t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby meta.group.regexp.ruby constant.character.escape.ruby",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string.regexp: #D16969",
"light_vs": "string.regexp: #811F3F",
"hc_black": "constant.character: #569CD6"

View file

@ -20761,7 +20761,7 @@
"t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -20882,7 +20882,7 @@
"t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -20959,7 +20959,7 @@
"t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.double.scss constant.character.escape.scss",
"r": {
"dark_plus": "constant.character.escape: #D7BA7D",
"light_plus": "constant.character.escape: #FF0000",
"light_plus": "constant.character.escape: #EE0000",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "constant.character: #569CD6"
@ -21020,4 +21020,4 @@
"hc_black": "comment: #7CA668"
}
}
]
]

View file

@ -169,7 +169,7 @@
"keyword.control.anchor.regexp"
],
"settings": {
"foreground": "#ff0000"
"foreground": "#EE0000"
}
},
{
@ -181,7 +181,7 @@
{
"scope": "constant.character.escape",
"settings": {
"foreground": "#ff0000"
"foreground": "#EE0000"
}
},
{

View file

@ -42,7 +42,23 @@
"pickerGroup.foreground": "#b0b0b0",
"terminal.ansiWhite": "#ffffff",
"inputOption.activeBorder": "#3655b5",
"focusBorder": "#3655b5"
"focusBorder": "#3655b5",
"terminal.ansiBlack": "#1e1e1e",
"terminal.ansiRed": "#C4265E", // the bright color with ~75% transparent on the background
"terminal.ansiGreen": "#86B42B",
"terminal.ansiYellow": "#B3B42B",
"terminal.ansiBlue": "#6A7EC8",
"terminal.ansiMagenta": "#8C6BC8",
"terminal.ansiCyan": "#56ADBC",
"terminal.ansiWhite": "#e3e3dd",
"terminal.ansiBrightBlack": "#666666",
"terminal.ansiBrightRed": "#f92672",
"terminal.ansiBrightGreen": "#A6E22E",
"terminal.ansiBrightYellow": "#e2e22e", // hue shifted #A6E22E
"terminal.ansiBrightBlue": "#819aff", // hue shifted #AE81FF
"terminal.ansiBrightMagenta": "#AE81FF",
"terminal.ansiBrightCyan": "#66D9EF",
"terminal.ansiBrightWhite": "#f8f8f2"
},
"tokenColors": [
{

View file

@ -6,7 +6,7 @@
"git": {
"name": "seti-ui",
"repositoryUrl": "https://github.com/jesseweed/seti-ui",
"commitHash": "8f22764c37feb7f706465f5186132111a2401b6b"
"commitHash": "f3b2775662b0075aab56e5f0c03269f21f3f0f30"
}
},
"version": "0.1.0"

View file

@ -1030,12 +1030,6 @@
"fontCharacter": "\\E074",
"fontColor": "#cc3e44"
},
"_rmd_light": {
"fontColor": "#498ba7"
},
"_rmd": {
"fontColor": "#519aba"
},
"_rollup_light": {
"fontCharacter": "\\E075",
"fontColor": "#b8383d"
@ -1483,7 +1477,7 @@
"test.tsx": "_react_2",
"re": "_reasonml",
"r": "_R",
"rmd": "_rmd",
"rmd": "_R",
"erb": "_html_erb",
"erb.html": "_html_erb",
"html.erb": "_html_erb",
@ -1678,7 +1672,7 @@
"sql": "_db",
"swift": "_swift",
"typescript": "_typescript",
"typescriptreact": "_react",
"typescriptreact": "_typescript",
"xml": "_xml",
"yaml": "_yml",
"argdown": "_argdown",
@ -1811,7 +1805,7 @@
"test.tsx": "_react_2_light",
"re": "_reasonml_light",
"r": "_R_light",
"rmd": "_rmd_light",
"rmd": "_R_light",
"erb": "_html_erb_light",
"erb.html": "_html_erb_light",
"html.erb": "_html_erb_light",
@ -1949,7 +1943,7 @@
"sql": "_db_light",
"swift": "_swift_light",
"typescript": "_typescript_light",
"typescriptreact": "_react_light",
"typescriptreact": "_typescript_light",
"xml": "_xml_light",
"yaml": "_yml_light",
"argdown": "_argdown_light",
@ -2030,5 +2024,5 @@
"npm-debug.log": "_npm_ignored_light"
}
},
"version": "https://github.com/jesseweed/seti-ui/commit/8f22764c37feb7f706465f5186132111a2401b6b"
"version": "https://github.com/jesseweed/seti-ui/commit/f3b2775662b0075aab56e5f0c03269f21f3f0f30"
}

View file

@ -110,9 +110,10 @@ export class TypeScriptServerSpawner {
private getForkOptions(kind: ServerKind, configuration: TypeScriptServiceConfiguration) {
const debugPort = TypeScriptServerSpawner.getDebugPort(kind);
const inspectFlag = process.env['TSS_DEBUG_BRK'] ? '--inspect-brk' : '--inspect';
const tsServerForkOptions: electron.ForkOptions = {
execArgv: [
...(debugPort ? [`--inspect=${debugPort}`] : []),
...(debugPort ? [`${inspectFlag}=${debugPort}`] : []),
...(configuration.maxTsServerMemory ? [`--max-old-space-size=${configuration.maxTsServerMemory}`] : [])
]
};
@ -200,7 +201,7 @@ export class TypeScriptServerSpawner {
// We typically only want to debug the main semantic server
return undefined;
}
const value = process.env['TSS_DEBUG'];
const value = process.env['TSS_DEBUG_BRK'] || process.env['TSS_DEBUG'];
if (value) {
const port = parseInt(value);
if (!isNaN(port)) {

View file

@ -29,31 +29,34 @@ suite('vscode API - languages', () => {
const doc = await vscode.workspace.openTextDocument(file);
const langIdNow = doc.languageId;
let clock = 0;
const disposables: vscode.Disposable[] = [];
let close = new Promise(resolve => {
vscode.workspace.onDidCloseTextDocument(e => {
disposables.push(vscode.workspace.onDidCloseTextDocument(e => {
if (e === doc) {
assert.equal(doc.languageId, langIdNow);
assert.equal(clock, 0);
clock += 1;
resolve();
}
});
}));
});
let open = new Promise(resolve => {
vscode.workspace.onDidOpenTextDocument(e => {
disposables.push(vscode.workspace.onDidOpenTextDocument(e => {
if (e === doc) { // same instance!
assert.equal(doc.languageId, 'json');
assert.equal(clock, 1);
clock += 1;
resolve();
}
});
}));
});
let change = vscode.languages.setTextDocumentLanguage(doc, 'json');
await Promise.all([change, close, open]);
assert.equal(clock, 2);
assert.equal(doc.languageId, 'json');
disposables.forEach(disposable => disposable.dispose());
disposables.length = 0;
});
test('setTextDocumentLanguage -> error when language does not exist', async function () {

View file

@ -318,10 +318,14 @@ suite('notebook workflow', () => {
// ---- move up and down ---- //
await vscode.commands.executeCommand('notebook.cell.moveDown');
assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(vscode.notebook.activeNotebookEditor!.selection!), 1,
`first move down, active cell ${vscode.notebook.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.notebook.activeNotebookEditor!.selection!.source}`);
await vscode.commands.executeCommand('notebook.cell.moveDown');
activeCell = vscode.notebook.activeNotebookEditor!.selection;
assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2);
assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2,
`second move down, active cell ${vscode.notebook.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.notebook.activeNotebookEditor!.selection!.source}`);
assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[0].source, 'test');
assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[1].source, '');
assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[2].source, 'test');

View file

@ -100,7 +100,7 @@
"css-loader": "^3.2.0",
"debounce": "^1.0.0",
"deemon": "^1.4.0",
"electron": "8.3.0",
"electron": "7.2.4",
"eslint": "6.8.0",
"eslint-plugin-jsdoc": "^19.1.0",
"event-stream": "3.3.4",

View file

@ -111,7 +111,10 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
}
href = _href(href, false);
if (options.baseUrl) {
href = resolvePath(options.baseUrl, href).toString();
const hasScheme = /^\w[\w\d+.-]*:/.test(href);
if (!hasScheme) {
href = resolvePath(options.baseUrl, href).toString();
}
}
title = removeMarkdownEscapes(title);
href = removeMarkdownEscapes(href);

View file

@ -41,6 +41,7 @@ export interface IMenuOptions {
enableMnemonics?: boolean;
anchorAlignment?: AnchorAlignment;
expandDirection?: Direction;
useEventAsContext?: boolean;
}
export interface IMenuStyles {
@ -316,7 +317,7 @@ export class Menu extends ActionBar {
return menuActionViewItem;
} else {
const menuItemOptions: IMenuItemOptions = { enableMnemonics: options.enableMnemonics };
const menuItemOptions: IMenuItemOptions = { enableMnemonics: options.enableMnemonics, useEventAsContext: options.useEventAsContext };
if (options.getKeyBinding) {
const keybinding = options.getKeyBinding(action);
if (keybinding) {

View file

@ -945,7 +945,8 @@ export class MenuBar extends Disposable {
actionRunner: this.actionRunner,
enableMnemonics: this.options.alwaysOnMnemonics || (this.mnemonicsInUse && this.options.enableMnemonics),
ariaLabel: withNullAsUndefined(customMenu.buttonElement.getAttribute('aria-label')),
expandDirection: this.options.compactMode !== undefined ? this.options.compactMode : Direction.Right
expandDirection: this.options.compactMode !== undefined ? this.options.compactMode : Direction.Right,
useEventAsContext: true
};
let menuWidget = this._register(new Menu(menuHolder, customMenu.actions, menuOptions));

View file

@ -727,7 +727,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
mouseSupport: false,
accessibilityProvider: {
getAriaLabel: (element) => element.text,
getWidgetAriaLabel: () => localize('selectBox', "Select Box"),
getWidgetAriaLabel: () => localize({ key: 'selectBox', comment: ['Behave like native select dropdown element.'] }, "Select Box"),
getRole: () => 'option',
getWidgetRole: () => 'listbox'
}

View file

@ -328,8 +328,8 @@ export namespace Event {
}
export interface NodeEventEmitter {
on(event: string | symbol, listener: Function): this;
removeListener(event: string | symbol, listener: Function): this;
on(event: string | symbol, listener: Function): unknown;
removeListener(event: string | symbol, listener: Function): unknown;
}
export function fromNodeEventEmitter<T>(emitter: NodeEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event<T> {

View file

@ -9,10 +9,9 @@ import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_
export function registerContextMenuListener(): void {
ipcMain.on(CONTEXT_MENU_CHANNEL, (event: IpcMainEvent, contextMenuId: number, items: ISerializableContextMenuItem[], onClickChannel: string, options?: IPopupOptions) => {
const menu = createMenu(event, onClickChannel, items);
const window = BrowserWindow.fromWebContents(event.sender);
menu.popup({
window: window ? window : undefined,
window: BrowserWindow.fromWebContents(event.sender),
x: options ? options.x : undefined,
y: options ? options.y : undefined,
positioningItem: options ? options.positioningItem : undefined,

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ipcRenderer, Event } from 'electron';
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { IContextMenuItem, ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions, IContextMenuEvent } from 'vs/base/parts/contextmenu/common/contextmenu';
let contextMenuIdPool = 0;
@ -13,7 +13,7 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void
const contextMenuId = contextMenuIdPool++;
const onClickChannel = `vscode:onContextMenu${contextMenuId}`;
const onClickChannelHandler = (_event: Event, itemId: number, context: IContextMenuEvent) => {
const onClickChannelHandler = (event: unknown, itemId: number, context: IContextMenuEvent) => {
const item = processedItems[itemId];
if (item.click) {
item.click(context);
@ -21,7 +21,7 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void
};
ipcRenderer.once(onClickChannel, onClickChannelHandler);
ipcRenderer.once(CONTEXT_MENU_CLOSE_CHANNEL, (_event: Event, closedContextMenuId: number) => {
ipcRenderer.once(CONTEXT_MENU_CLOSE_CHANNEL, (event: unknown, closedContextMenuId: number) => {
if (closedContextMenuId !== contextMenuId) {
return;
}

View file

@ -8,7 +8,7 @@ import { Event } from 'vs/base/common/event';
import { VSBuffer } from 'vs/base/common/buffer';
export interface Sender {
send(channel: string, msg: Buffer | null): void;
send(channel: string, msg: unknown): void;
}
export class Protocol implements IMessagePassingProtocol {
@ -17,13 +17,13 @@ export class Protocol implements IMessagePassingProtocol {
send(message: VSBuffer): void {
try {
this.sender.send('ipc:message', (<Buffer>message.buffer));
this.sender.send('vscode:message', message.buffer);
} catch (e) {
// systems are going down
}
}
dispose(): void {
this.sender.send('ipc:disconnect', null);
this.sender.send('vscode:disconnect', null);
}
}
}

View file

@ -10,7 +10,9 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance
import * as errors from 'vs/base/common/errors';
import { VSBuffer } from 'vs/base/common/buffer';
import { getRandomElement } from 'vs/base/common/arrays';
import { isFunction } from 'vs/base/common/types';
import { isFunction, isUndefinedOrNull } from 'vs/base/common/types';
import { revive } from 'vs/base/common/marshalling';
import { isUpperAsciiLetter } from 'vs/base/common/strings';
/**
* An `IChannel` is an abstraction over a collection of commands.
@ -919,3 +921,142 @@ export class StaticRouter<TContext = string> implements IClientRouter<TContext>
return await this.route(hub);
}
}
//#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.
*
* Rules:
* - if marshalling is enabled, only `URI` and `RegExp` is converted
* automatically for you
* - events must follow the naming convention `onUppercase`
* - `CancellationToken` is currently not supported
* - if a context is provided, you can use `AddFirstParameterToFunctions`
* utility to signal this in the receiving side type
*/
export interface IBaseChannelOptions {
/**
* 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<string, Event<unknown>>();
for (const key in handler) {
if (propertyIsEvent(key)) {
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true));
}
}
return new class implements IServerChannel {
listen<T>(_: unknown, event: string): Event<T> {
const eventImpl = mapEventNameToEvent.get(event);
if (eventImpl) {
return eventImpl as Event<T>;
}
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, args?: any[]): Promise<any> {
const target = handler[command];
if (typeof target === 'function') {
// Revive unless marshalling disabled
if (!disableMarshalling && Array.isArray(args)) {
for (let i = 0; i < args.length; i++) {
args[i] = revive(args[i]);
}
}
return target.apply(handler, args);
}
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<string, unknown>;
}
export function createChannelSender<T>(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);
// 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' && isUpperAsciiLetter(name.charCodeAt(2));
}
//#endregion

View file

@ -5,7 +5,7 @@
import { Event, Emitter } from 'vs/base/common/event';
import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/common/ipc';
import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron';
import { Protocol } from 'vs/base/parts/ipc/common/ipc.electron';
import { ipcMain, WebContents } from 'electron';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { VSBuffer } from 'vs/base/common/buffer';
@ -26,7 +26,7 @@ export class Server extends IPCServer {
private static readonly Clients = new Map<number, IDisposable>();
private static getOnDidClientConnect(): Event<ClientConnectionEvent> {
const onHello = Event.fromNodeEventEmitter<WebContents>(ipcMain, 'ipc:hello', ({ sender }) => sender);
const onHello = Event.fromNodeEventEmitter<WebContents>(ipcMain, 'vscode:hello', ({ sender }) => sender);
return Event.map(onHello, webContents => {
const id = webContents.id;
@ -39,8 +39,8 @@ export class Server extends IPCServer {
const onDidClientReconnect = new Emitter<void>();
Server.Clients.set(id, toDisposable(() => onDidClientReconnect.fire()));
const onMessage = createScopedOnMessageEvent(id, 'ipc:message') as Event<VSBuffer>;
const onDidClientDisconnect = Event.any(Event.signal(createScopedOnMessageEvent(id, 'ipc:disconnect')), onDidClientReconnect.event);
const onMessage = createScopedOnMessageEvent(id, 'vscode:message') as Event<VSBuffer>;
const onDidClientDisconnect = Event.any(Event.signal(createScopedOnMessageEvent(id, 'vscode:disconnect')), onDidClientReconnect.event);
const protocol = new Protocol(webContents, onMessage);
return { protocol, onDidClientDisconnect };

View file

@ -5,18 +5,18 @@
import { Event } from 'vs/base/common/event';
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron';
import { ipcRenderer } from 'electron';
import { Protocol } from 'vs/base/parts/ipc/common/ipc.electron';
import { IDisposable } from 'vs/base/common/lifecycle';
import { VSBuffer } from 'vs/base/common/buffer';
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
export class Client extends IPCClient implements IDisposable {
private protocol: Protocol;
private static createProtocol(): Protocol {
const onMessage = Event.fromNodeEventEmitter<VSBuffer>(ipcRenderer, 'ipc:message', (_, message: Buffer) => VSBuffer.wrap(message));
ipcRenderer.send('ipc:hello');
const onMessage = Event.fromNodeEventEmitter<VSBuffer>(ipcRenderer, 'vscode:message', (_, message) => VSBuffer.wrap(message));
ipcRenderer.send('vscode:hello');
return new Protocol(ipcRenderer, onMessage);
}
@ -29,4 +29,4 @@ export class Client extends IPCClient implements IDisposable {
dispose(): void {
this.protocol.dispose();
}
}
}

View file

@ -1,133 +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 { Event } from 'vs/base/common/event';
import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc';
import { revive } from 'vs/base/common/marshalling';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { isUpperAsciiLetter } from 'vs/base/common/strings';
/**
* 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.
*
* Rules:
* - if marshalling is enabled, only `URI` and `RegExp` is converted
* automatically for you
* - events must follow the naming convention `onUppercase`
* - `CancellationToken` is currently not supported
* - if a context is provided, you can use `AddFirstParameterToFunctions`
* utility to signal this in the receiving side type
*/
export interface IBaseChannelOptions {
/**
* 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<string, Event<unknown>>();
for (const key in handler) {
if (propertyIsEvent(key)) {
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true));
}
}
return new class implements IServerChannel {
listen<T>(_: unknown, event: string): Event<T> {
const eventImpl = mapEventNameToEvent.get(event);
if (eventImpl) {
return eventImpl as Event<T>;
}
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, args?: any[]): Promise<any> {
const target = handler[command];
if (typeof target === 'function') {
// Revive unless marshalling disabled
if (!disableMarshalling && Array.isArray(args)) {
for (let i = 0; i < args.length; i++) {
args[i] = revive(args[i]);
}
}
return target.apply(handler, args);
}
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;
}
export function createChannelSender<T>(channel: IChannel, options?: IChannelSenderOptions): T {
const disableMarshalling = options && options.disableMarshalling;
return new Proxy({}, {
get(_target: T, propKey: PropertyKey) {
if (typeof propKey === 'string') {
// 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' && isUpperAsciiLetter(name.charCodeAt(2));
}

View file

@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/node/ipc';
import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, createChannelReceiver, createChannelSender } 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';
@ -103,7 +102,7 @@ interface ITestService {
error(message: string): Promise<void>;
neverComplete(): Promise<void>;
neverCompleteCT(cancellationToken: CancellationToken): Promise<void>;
buffersLength(buffers: Buffer[]): Promise<number>;
buffersLength(buffers: VSBuffer[]): Promise<number>;
marshall(uri: URI): Promise<URI>;
context(): Promise<unknown>;
@ -135,8 +134,8 @@ class TestService implements ITestService {
return new Promise((_, e) => cancellationToken.onCancellationRequested(() => e(canceled())));
}
buffersLength(buffers: Buffer[]): Promise<number> {
return Promise.resolve(buffers.reduce((r, b) => r + b.length, 0));
buffersLength(buffers: VSBuffer[]): Promise<number> {
return Promise.resolve(buffers.reduce((r, b) => r + b.buffer.length, 0));
}
ping(msg: string): void {
@ -199,7 +198,7 @@ class TestChannelClient implements ITestService {
return this.channel.call('neverCompleteCT', undefined, cancellationToken);
}
buffersLength(buffers: Buffer[]): Promise<number> {
buffersLength(buffers: VSBuffer[]): Promise<number> {
return this.channel.call('buffersLength', buffers);
}
@ -317,7 +316,7 @@ suite('Base IPC', function () {
});
test('buffers in arrays', async function () {
const r = await ipcService.buffersLength([Buffer.allocUnsafe(2), Buffer.allocUnsafe(3)]);
const r = await ipcService.buffersLength([VSBuffer.alloc(2), VSBuffer.alloc(3)]);
return assert.equal(r, 5);
});
});
@ -383,7 +382,7 @@ suite('Base IPC', function () {
});
test('buffers in arrays', async function () {
const r = await ipcService.buffersLength([Buffer.allocUnsafe(2), Buffer.allocUnsafe(3)]);
const r = await ipcService.buffersLength([VSBuffer.alloc(2), VSBuffer.alloc(3)]);
return assert.equal(r, 5);
});
});

View file

@ -0,0 +1,249 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// #######################################################################
// ### ###
// ### electron.d.ts types we need in a common layer for reuse ###
// ### (copied from Electron 7.x) ###
// ### ###
// #######################################################################
export interface MessageBoxOptions {
/**
* Can be `"none"`, `"info"`, `"error"`, `"question"` or `"warning"`. On Windows,
* `"question"` displays the same icon as `"info"`, unless you set an icon using
* the `"icon"` option. On macOS, both `"warning"` and `"error"` display the same
* warning icon.
*/
type?: string;
/**
* Array of texts for buttons. On Windows, an empty array will result in one button
* labeled "OK".
*/
buttons?: string[];
/**
* Index of the button in the buttons array which will be selected by default when
* the message box opens.
*/
defaultId?: number;
/**
* Title of the message box, some platforms will not show it.
*/
title?: string;
/**
* Content of the message box.
*/
message: string;
/**
* Extra information of the message.
*/
detail?: string;
/**
* If provided, the message box will include a checkbox with the given label.
*/
checkboxLabel?: string;
/**
* Initial checked state of the checkbox. `false` by default.
*/
checkboxChecked?: boolean;
// icon?: NativeImage;
/**
* The index of the button to be used to cancel the dialog, via the `Esc` key. By
* default this is assigned to the first button with "cancel" or "no" as the label.
* If no such labeled buttons exist and this option is not set, `0` will be used as
* the return value.
*/
cancelId?: number;
/**
* On Windows Electron will try to figure out which one of the `buttons` are common
* buttons (like "Cancel" or "Yes"), and show the others as command links in the
* dialog. This can make the dialog appear in the style of modern Windows apps. If
* you don't like this behavior, you can set `noLink` to `true`.
*/
noLink?: boolean;
/**
* Normalize the keyboard access keys across platforms. Default is `false`.
* Enabling this assumes `&` is used in the button labels for the placement of the
* keyboard shortcut access key and labels will be converted so they work correctly
* on each platform, `&` characters are removed on macOS, converted to `_` on
* Linux, and left untouched on Windows. For example, a button label of `Vie&w`
* will be converted to `Vie_w` on Linux and `View` on macOS and can be selected
* via `Alt-W` on Windows and Linux.
*/
normalizeAccessKeys?: boolean;
}
export interface MessageBoxReturnValue {
/**
* The index of the clicked button.
*/
response: number;
/**
* The checked state of the checkbox if `checkboxLabel` was set. Otherwise `false`.
*/
checkboxChecked: boolean;
}
export interface OpenDevToolsOptions {
/**
* Opens the devtools with specified dock state, can be `right`, `bottom`,
* `undocked`, `detach`. Defaults to last used dock state. In `undocked` mode it's
* possible to dock back. In `detach` mode it's not.
*/
mode: ('right' | 'bottom' | 'undocked' | 'detach');
/**
* Whether to bring the opened devtools window to the foreground. The default is
* `true`.
*/
activate?: boolean;
}
export interface SaveDialogOptions {
title?: string;
/**
* Absolute directory path, absolute file path, or file name to use by default.
*/
defaultPath?: string;
/**
* Custom label for the confirmation button, when left empty the default label will
* be used.
*/
buttonLabel?: string;
filters?: FileFilter[];
/**
* Message to display above text fields.
*
* @platform darwin
*/
message?: string;
/**
* Custom label for the text displayed in front of the filename text field.
*
* @platform darwin
*/
nameFieldLabel?: string;
/**
* Show the tags input box, defaults to `true`.
*
* @platform darwin
*/
showsTagField?: boolean;
/**
* Create a security scoped bookmark when packaged for the Mac App Store. If this
* option is enabled and the file doesn't already exist a blank file will be
* created at the chosen path.
*
* @platform darwin,mas
*/
securityScopedBookmarks?: boolean;
}
export interface OpenDialogOptions {
title?: string;
defaultPath?: string;
/**
* Custom label for the confirmation button, when left empty the default label will
* be used.
*/
buttonLabel?: string;
filters?: FileFilter[];
/**
* Contains which features the dialog should use. The following values are
* supported:
*/
properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory'>;
/**
* Message to display above input boxes.
*
* @platform darwin
*/
message?: string;
/**
* Create security scoped bookmarks when packaged for the Mac App Store.
*
* @platform darwin,mas
*/
securityScopedBookmarks?: boolean;
}
export interface OpenDialogReturnValue {
/**
* whether or not the dialog was canceled.
*/
canceled: boolean;
/**
* An array of file paths chosen by the user. If the dialog is cancelled this will
* be an empty array.
*/
filePaths: string[];
/**
* An array matching the `filePaths` array of base64 encoded strings which contains
* security scoped bookmark data. `securityScopedBookmarks` must be enabled for
* this to be populated. (For return values, see table here.)
*
* @platform darwin,mas
*/
bookmarks?: string[];
}
export interface SaveDialogReturnValue {
/**
* whether or not the dialog was canceled.
*/
canceled: boolean;
/**
* If the dialog is canceled, this will be `undefined`.
*/
filePath?: string;
/**
* Base64 encoded string which contains the security scoped bookmark data for the
* saved file. `securityScopedBookmarks` must be enabled for this to be present.
* (For return values, see table here.)
*
* @platform darwin,mas
*/
bookmark?: string;
}
export interface CrashReporterStartOptions {
companyName: string;
/**
* URL that crash reports will be sent to as POST.
*/
submitURL: string;
/**
* Defaults to `app.name`.
*/
productName?: string;
/**
* Whether crash reports should be sent to the server. Default is `true`.
*/
uploadToServer?: boolean;
/**
* Default is `false`.
*/
ignoreSystemCrashHandler?: boolean;
/**
* An object you can define that will be sent along with the report. Only string
* properties are sent correctly. Nested objects are not supported. When using
* Windows, the property names and values must be fewer than 64 characters.
*/
extra?: Record<string, string>;
/**
* Directory to store the crash reports temporarily (only used when the crash
* reporter is started via `process.crashReporter.start`).
*/
crashesDirectory?: string;
}
export interface FileFilter {
// Docs: http://electronjs.org/docs/api/structures/file-filter
extensions: string[];
name: string;
}

View file

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
(function () {
'use strict';
const { ipcRenderer, webFrame, crashReporter } = require('electron');
// @ts-ignore
window.vscode = {
/**
* A minimal set of methods exposed from ipcRenderer
* to support communication to electron-main
*
* @type {typeof import('../electron-sandbox/globals').ipcRenderer}
*/
ipcRenderer: {
/**
* @param {string} channel
* @param {any[]} args
*/
send(channel, ...args) {
validateIPC(channel);
ipcRenderer.send(channel, ...args);
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
*/
on(channel, listener) {
validateIPC(channel);
ipcRenderer.on(channel, listener);
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
*/
once(channel, listener) {
validateIPC(channel);
ipcRenderer.once(channel, listener);
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
*/
removeListener(channel, listener) {
validateIPC(channel);
ipcRenderer.removeListener(channel, listener);
}
},
/**
* Support for methods of webFrame type.
*
* @type {typeof import('../electron-sandbox/globals').webFrame}
*/
webFrame: {
getZoomFactor() {
return webFrame.getZoomFactor();
},
getZoomLevel() {
return webFrame.getZoomLevel();
},
/**
* @param {number} level
*/
setZoomLevel(level) {
webFrame.setZoomLevel(level);
}
},
/**
* Support for methods of crashReporter type.
*
* @type {typeof import('../electron-sandbox/globals').crashReporter}
*/
crashReporter: {
/**
* @param {Electron.CrashReporterStartOptions} options
*/
start(options) {
crashReporter.start(options);
}
}
};
//#region Utilities
/**
* @param {string} channel
*/
function validateIPC(channel) {
if (!channel || !channel.startsWith('vscode:')) {
throw new Error(`Unsupported event IPC channel '${channel}'`);
}
}
//#endregion
}());

View file

@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CrashReporterStartOptions } from 'vs/base/parts/sandbox/common/electronTypes';
export const ipcRenderer = (window as any).vscode.ipcRenderer as {
/**
* Listens to `channel`, when a new message arrives `listener` would be called with
* `listener(event, args...)`.
*/
on(channel: string, listener: (event: unknown, ...args: any[]) => void): void;
/**
* Adds a one time `listener` function for the event. This `listener` is invoked
* only the next time a message is sent to `channel`, after which it is removed.
*/
once(channel: string, listener: (event: unknown, ...args: any[]) => void): void;
/**
* Removes the specified `listener` from the listener array for the specified
* `channel`.
*/
removeListener(channel: string, listener: (event: unknown, ...args: any[]) => void): void;
/**
* Send an asynchronous message to the main process via `channel`, along with
* arguments. Arguments will be serialized with the Structured Clone Algorithm,
* just like `postMessage`, so prototype chains will not be included. Sending
* Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.
*
* > **NOTE**: Sending non-standard JavaScript types such as DOM objects or special
* Electron objects is deprecated, and will begin throwing an exception starting
* with Electron 9.
*
* The main process handles it by listening for `channel` with the `ipcMain`
* module.
*/
send(channel: string, ...args: any[]): void;
};
export const webFrame = (window as any).vscode.webFrame as {
/**
* The current zoom factor.
*/
getZoomFactor(): number;
/**
* The current zoom level.
*/
getZoomLevel(): number;
/**
* Changes the zoom level to the specified level. The original size is 0 and each
* increment above or below represents zooming 20% larger or smaller to default
* limits of 300% and 50% of original size, respectively.
*/
setZoomLevel(level: number): void;
};
export const crashReporter = (window as any).vscode.crashReporter as {
/**
* You are required to call this method before using any other `crashReporter` APIs
* and in each process (main/renderer) from which you want to collect crash
* reports. You can pass different options to `crashReporter.start` when calling
* from different processes.
*
* **Note** Child processes created via the `child_process` module will not have
* access to the Electron modules. Therefore, to collect crash reports from them,
* use `process.crashReporter.start` instead. Pass the same options as above along
* with an additional one called `crashesDirectory` that should point to a
* directory to store the crash reports temporarily. You can test this out by
* calling `process.crash()` to crash the child process.
*
* **Note:** If you need send additional/updated `extra` parameters after your
* first call `start` you can call `addExtraParameter` on macOS or call `start`
* again with the new/updated `extra` parameters on Linux and Windows.
*
* **Note:** On macOS and windows, Electron uses a new `crashpad` client for crash
* collection and reporting. If you want to enable crash reporting, initializing
* `crashpad` from the main process using `crashReporter.start` is required
* regardless of which process you want to collect crashes from. Once initialized
* this way, the crashpad handler collects crashes from all processes. You still
* have to call `crashReporter.start` from the renderer or child process, otherwise
* crashes from them will get reported without `companyName`, `productName` or any
* of the `extra` information.
*/
start(options: CrashReporterStartOptions): void;
};

View file

@ -3,13 +3,13 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import * as assert from 'assert';
import { ipcRenderer, crashReporter, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals';
export interface INativeOpenDialogOptions {
forceNewWindow?: boolean;
defaultPath?: string;
telemetryEventName?: string;
telemetryExtraData?: ITelemetryData;
}
suite('Sandbox', () => {
test('globals', () => {
assert.ok(ipcRenderer);
assert.ok(crashReporter);
assert.ok(webFrame);
});
});

View file

@ -3,10 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { clipboard, ipcRenderer, shell, webFrame } from 'electron';
import 'vs/css!./media/issueReporter';
import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { ipcRenderer, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import * as os from 'os';
import * as browser from 'vs/base/browser/browser';
import { $ } from 'vs/base/browser/dom';
import { $, windowOpenNoOpener } from 'vs/base/browser/dom';
import { Button } from 'vs/base/browser/ui/button/button';
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel';
@ -15,21 +17,19 @@ import { debounce } from 'vs/base/common/decorators';
import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import { escape } from 'vs/base/common/strings';
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { createChannelSender } from 'vs/base/parts/ipc/node/ipc';
import { getDelayedChannel, createChannelSender } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
import { IssueReporterData as IssueReporterModelData, IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel';
import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage';
import 'vs/css!./media/issueReporter';
import { localize } from 'vs/nls';
import { isRemoteDiagnosticError, SystemInfo } from 'vs/platform/diagnostics/common/diagnostics';
import { EnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { ISettingsSearchIssueReporterData, IssueReporterData, IssueReporterExtensionData, IssueReporterFeatures, IssueReporterStyles, IssueType } from 'vs/platform/issue/node/issue';
import { ISettingsSearchIssueReporterData, IssueReporterData, IssueReporterExtensionData, IssueReporterFeatures, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue';
import { getLogLevel, ILogService } from 'vs/platform/log/common/log';
import { FollowerLogService, LoggerChannelClient } from 'vs/platform/log/common/logIpc';
import { SpdLogService } from 'vs/platform/log/node/spdlogService';
@ -64,6 +64,7 @@ export function startup(configuration: IssueReporterConfiguration) {
export class IssueReporter extends Disposable {
private environmentService!: INativeEnvironmentService;
private electronService!: IElectronService;
private telemetryService!: ITelemetryService;
private logService!: ILogService;
private readonly issueReporterModel: IssueReporterModel;
@ -324,6 +325,9 @@ export class IssueReporter extends Disposable {
const mainProcessService = new MainProcessService(configuration.windowId);
serviceCollection.set(IMainProcessService, mainProcessService);
this.electronService = new ElectronService(configuration.windowId, mainProcessService) as IElectronService;
serviceCollection.set(IElectronService, this.electronService);
this.environmentService = new EnvironmentService(configuration, configuration.execPath);
const logService = new SpdLogService(`issuereporter${configuration.windowId}`, this.environmentService.logsPath, getLogLevel(this.environmentService));
@ -462,7 +466,7 @@ export class IssueReporter extends Disposable {
this.addEventListener('extensionBugsLink', 'click', (e: Event) => {
const url = (<HTMLElement>e.target).innerText;
shell.openExternal(url);
windowOpenNoOpener(url);
});
this.addEventListener('disableExtensions', 'keydown', (e: Event) => {
@ -941,9 +945,9 @@ export class IssueReporter extends Disposable {
private async writeToClipboard(baseUrl: string, issueBody: string): Promise<string> {
return new Promise((resolve, reject) => {
ipcRenderer.once('vscode:issueReporterClipboardResponse', (_: unknown, shouldWrite: boolean) => {
ipcRenderer.once('vscode:issueReporterClipboardResponse', async (event: unknown, shouldWrite: boolean) => {
if (shouldWrite) {
clipboard.writeText(issueBody);
await this.electronService.writeClipboardText(issueBody);
resolve(baseUrl + `&body=${encodeURIComponent(localize('pasteData', "We have written the needed data into your clipboard because it was too large to send. Please paste."))}`);
} else {
reject();
@ -1194,7 +1198,7 @@ export class IssueReporter extends Disposable {
event.stopPropagation();
// Exclude right click
if (event.which < 3) {
shell.openExternal((<HTMLAnchorElement>event.target).href);
windowOpenNoOpener((<HTMLAnchorElement>event.target).href);
this.telemetryService.publicLog2('issueReporterViewSimilarIssue');
}
}

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { assign } from 'vs/base/common/objects';
import { IssueType, ISettingSearchResult, IssueReporterExtensionData } from 'vs/platform/issue/node/issue';
import { IssueType, ISettingSearchResult, IssueReporterExtensionData } from 'vs/platform/issue/common/issue';
import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
export interface IssueReporterData {

View file

@ -6,7 +6,7 @@
import * as assert from 'assert';
import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel';
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
import { IssueType } from 'vs/platform/issue/node/issue';
import { IssueType } from 'vs/platform/issue/common/issue';
suite('IssueReporter', () => {

View file

@ -4,16 +4,17 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/processExplorer';
import { webFrame, ipcRenderer, clipboard } from 'electron';
import { clipboard } from 'electron';
import { webFrame, ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { repeat } from 'vs/base/common/strings';
import { totalmem } from 'os';
import product from 'vs/platform/product/common/product';
import { localize } from 'vs/nls';
import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/node/issue';
import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import * as browser from 'vs/base/browser/browser';
import * as platform from 'vs/base/common/platform';
import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu';
import { popup } from 'vs/base/parts/contextmenu/electron-browser/contextmenu';
import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu';
import { ProcessItem } from 'vs/base/common/processes';
import { addDisposableListener } from 'vs/base/browser/dom';
import { DisposableStore } from 'vs/base/common/lifecycle';
@ -369,7 +370,7 @@ function requestProcessList(totalWaitTime: number): void {
// Wait at least a second between requests.
if (waited > 1000) {
ipcRenderer.send('windowsInfoRequest');
ipcRenderer.send('vscode:windowsInfoRequest');
ipcRenderer.send('vscode:listProcesses');
} else {
requestProcessList(waited);
@ -393,18 +394,18 @@ export function startup(data: ProcessExplorerData): void {
createCloseListener();
// Map window process pids to titles, annotate process names with this when rendering to distinguish between them
ipcRenderer.on('vscode:windowsInfoResponse', (_event: unknown, windows: any[]) => {
ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => {
mapPidToWindowTitle = new Map<number, string>();
windows.forEach(window => mapPidToWindowTitle.set(window.pid, window.title));
});
ipcRenderer.on('vscode:listProcessesResponse', (_event: Event, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => {
ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => {
updateProcessInfo(processRoots);
requestProcessList(0);
});
lastRequestTime = Date.now();
ipcRenderer.send('windowsInfoRequest');
ipcRenderer.send('vscode:windowsInfoRequest');
ipcRenderer.send('vscode:listProcesses');
document.onkeydown = (e: KeyboardEvent) => {

View file

@ -27,7 +27,7 @@ import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProper
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
import { ipcRenderer } from 'electron';
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { ILogService, LogLevel, ILoggerService } from 'vs/platform/log/common/log';
import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
@ -35,26 +35,25 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza
import { combinedDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { DownloadService } from 'vs/platform/download/common/downloadService';
import { IDownloadService } from 'vs/platform/download/common/download';
import { IChannel, IServerChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
import { createChannelSender, createChannelReceiver } from 'vs/base/parts/ipc/node/ipc';
import { IChannel, IServerChannel, StaticRouter, createChannelSender, createChannelReceiver } from 'vs/base/parts/ipc/common/ipc';
import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner';
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 } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { SpdLogService } from 'vs/platform/log/node/spdlogService';
import { DiagnosticsService, IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService';
import { DiagnosticsChannel } from 'vs/platform/diagnostics/node/diagnosticsIpc';
import { FileService } from 'vs/platform/files/common/fileService';
import { IFileService } from 'vs/platform/files/common/files';
import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { Schemas } from 'vs/base/common/network';
import { IProductService } from 'vs/platform/product/common/productService';
import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncChannel, StorageKeysSyncRegistryChannelClient, UserDataSyncMachinesServiceChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { LoggerService } from 'vs/platform/log/node/loggerService';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
@ -66,7 +65,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { UserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSyncEnablementService';
import { IAuthenticationTokenService, AuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
import { AuthenticationTokenServiceChannel } from 'vs/platform/authentication/common/authenticationIpc';
import { AuthenticationTokenServiceChannel } from 'vs/platform/authentication/electron-browser/authenticationIpc';
import { UserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSyncBackupStoreService';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { ExtensionTipsService } from 'vs/platform/extensionManagement/node/extensionTipsService';
@ -90,7 +89,11 @@ interface ISharedProcessInitData {
const eventPrefix = 'monacoworkbench';
class MainProcessService implements IMainProcessService {
constructor(private server: Server, private mainRouter: StaticRouter) { }
constructor(
private server: Server,
private mainRouter: StaticRouter
) { }
_serviceBrand: undefined;
@ -110,7 +113,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
const onExit = () => disposables.dispose();
process.once('exit', onExit);
ipcRenderer.once('electron-main->shared-process: exit', onExit);
ipcRenderer.once('vscode:electron-main->shared-process=exit', onExit);
disposables.add(server);
@ -298,17 +301,17 @@ async function handshake(configuration: ISharedProcessConfiguration): Promise<vo
// receive payload from electron-main to start things
const data = await new Promise<ISharedProcessInitData>(c => {
ipcRenderer.once('electron-main->shared-process: payload', (_: any, r: ISharedProcessInitData) => c(r));
ipcRenderer.once('vscode:electron-main->shared-process=payload', (event: unknown, r: ISharedProcessInitData) => c(r));
// tell electron-main we are ready to receive payload
ipcRenderer.send('shared-process->electron-main: ready-for-payload');
ipcRenderer.send('vscode:shared-process->electron-main=ready-for-payload');
});
// await IPC connection and signal this back to electron-main
const server = await setupIPC(data.sharedIPCHandle);
ipcRenderer.send('shared-process->electron-main: ipc-ready');
ipcRenderer.send('vscode:shared-process->electron-main=ipc-ready');
// await initialization and signal this back to electron-main
await main(server, data, configuration);
ipcRenderer.send('shared-process->electron-main: init-done');
ipcRenderer.send('vscode:shared-process->electron-main=init-done');
}

View file

@ -8,7 +8,6 @@ import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/plat
import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService';
import { IWindowOpenable } from 'vs/platform/windows/common/windows';
import { OpenContext } from 'vs/platform/windows/node/window';
import { ActiveWindowManager } from 'vs/code/node/activeWindowTracker';
import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { getShellEnvironment } from 'vs/code/node/shellEnv';
import { IUpdateService } from 'vs/platform/update/common/update';
@ -32,12 +31,12 @@ import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { getDelayedChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipc';
import { getDelayedChannel, StaticRouter, createChannelReceiver } from 'vs/base/parts/ipc/common/ipc';
import product from 'vs/platform/product/common/product';
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
import { Disposable } from 'vs/base/common/lifecycle';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { ActiveWindowManager } from 'vs/platform/windows/electron-main/windowTracker';
import { URI } from 'vs/base/common/uri';
import { hasWorkspaceFileExtension, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { WorkspacesService } from 'vs/platform/workspaces/electron-main/workspacesService';
@ -45,14 +44,12 @@ import { getMachineId } from 'vs/base/node/id';
import { Win32UpdateService } from 'vs/platform/update/electron-main/updateService.win32';
import { LinuxUpdateService } from 'vs/platform/update/electron-main/updateService.linux';
import { DarwinUpdateService } from 'vs/platform/update/electron-main/updateService.darwin';
import { IIssueService } from 'vs/platform/issue/node/issue';
import { IssueMainService } from 'vs/platform/issue/electron-main/issueMainService';
import { IssueMainService, IIssueMainService } from 'vs/platform/issue/electron-main/issueMainService';
import { LoggerChannel } from 'vs/platform/log/common/logIpc';
import { setUnexpectedErrorHandler, onUnexpectedError } from 'vs/base/common/errors';
import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener';
import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver';
import { IMenubarService } from 'vs/platform/menubar/node/menubar';
import { MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService';
import { IMenubarMainService, MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu';
import { homedir } from 'os';
@ -65,7 +62,7 @@ import { GlobalStorageDatabaseChannel } from 'vs/platform/storage/node/storageIp
import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
import { IBackupMainService } from 'vs/platform/backup/electron-main/backup';
import { WorkspacesHistoryMainService, IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
import { URLService } from 'vs/platform/url/node/urlService';
import { NativeURLService } from 'vs/platform/url/common/urlService';
import { WorkspacesMainService, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { statSync } from 'fs';
import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsIpc';
@ -472,10 +469,10 @@ export class CodeApplication extends Disposable {
const diagnosticsChannel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('diagnostics')));
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService, [diagnosticsChannel]));
services.set(IIssueService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv]));
services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv]));
services.set(IElectronMainService, new SyncDescriptor(ElectronMainService));
services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService));
services.set(IMenubarService, new SyncDescriptor(MenubarMainService));
services.set(IMenubarMainService, new SyncDescriptor(MenubarMainService));
const storageMainService = new StorageMainService(this.logService, this.environmentService);
services.set(IStorageMainService, storageMainService);
@ -485,7 +482,7 @@ export class CodeApplication extends Disposable {
services.set(IBackupMainService, backupMainService);
services.set(IWorkspacesHistoryMainService, new SyncDescriptor(WorkspacesHistoryMainService));
services.set(IURLService, new SyncDescriptor(URLService));
services.set(IURLService, new SyncDescriptor(NativeURLService));
services.set(IWorkspacesMainService, new SyncDescriptor(WorkspacesMainService));
// Telemetry
@ -556,8 +553,8 @@ export class CodeApplication extends Disposable {
const updateChannel = new UpdateChannel(updateService);
electronIpcServer.registerChannel('update', updateChannel);
const issueService = accessor.get(IIssueService);
const issueChannel = createChannelReceiver(issueService);
const issueMainService = accessor.get(IIssueMainService);
const issueChannel = createChannelReceiver(issueMainService);
electronIpcServer.registerChannel('issue', issueChannel);
const electronMainService = accessor.get(IElectronMainService);
@ -573,8 +570,8 @@ export class CodeApplication extends Disposable {
const workspacesChannel = createChannelReceiver(workspacesService);
electronIpcServer.registerChannel('workspaces', workspacesChannel);
const menubarService = accessor.get(IMenubarService);
const menubarChannel = createChannelReceiver(menubarService);
const menubarMainService = accessor.get(IMenubarMainService);
const menubarChannel = createChannelReceiver(menubarMainService);
electronIpcServer.registerChannel('menubar', menubarChannel);
const urlService = accessor.get(IURLService);

View file

@ -59,8 +59,7 @@ export class ProxyAuthHandler extends Disposable {
title: 'VS Code',
webPreferences: {
nodeIntegration: true,
webviewTag: true,
enableWebSQL: false
webviewTag: true
}
};

View file

@ -13,7 +13,7 @@ import { mkdirp } from 'vs/base/node/pfs';
import { validatePaths } from 'vs/code/node/paths';
import { LifecycleMainService, ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { createChannelSender } from 'vs/base/parts/ipc/node/ipc';
import { createChannelSender } from 'vs/base/parts/ipc/common/ipc';
import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';

View file

@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import { memoize } from 'vs/base/common/decorators';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { BrowserWindow, ipcMain, WebContents, Event as ElectronEvent } from 'electron';
@ -32,7 +33,7 @@ export class SharedProcess implements ISharedProcess {
@IThemeMainService private readonly themeMainService: IThemeMainService
) {
// overall ready promise when shared process signals initialization is done
this._whenReady = new Promise<void>(c => ipcMain.once('shared-process->electron-main: init-done', () => c(undefined)));
this._whenReady = new Promise<void>(c => ipcMain.once('vscode:shared-process->electron-main=init-done', () => c(undefined)));
}
@memoize
@ -41,10 +42,10 @@ export class SharedProcess implements ISharedProcess {
show: false,
backgroundColor: this.themeMainService.getBackgroundColor(),
webPreferences: {
preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath,
images: false,
nodeIntegration: true,
webgl: false,
enableWebSQL: false,
disableBlinkFeatures: 'Auxclick' // do NOT change, allows us to identify this window as shared-process in the process explorer
}
});
@ -105,18 +106,18 @@ export class SharedProcess implements ISharedProcess {
return new Promise<void>(c => {
// send payload once shared process is ready to receive it
disposables.add(Event.once(Event.fromNodeEventEmitter(ipcMain, 'shared-process->electron-main: ready-for-payload', ({ sender }: { sender: WebContents }) => sender))(sender => {
sender.send('electron-main->shared-process: payload', {
disposables.add(Event.once(Event.fromNodeEventEmitter(ipcMain, 'vscode:shared-process->electron-main=ready-for-payload', ({ sender }: { sender: WebContents }) => sender))(sender => {
sender.send('vscode:electron-main->shared-process=payload', {
sharedIPCHandle: this.environmentService.sharedIPCHandle,
args: this.environmentService.args,
logLevel: this.logService.getLevel()
});
// signal exit to shared process when we get disposed
disposables.add(toDisposable(() => sender.send('electron-main->shared-process: exit')));
disposables.add(toDisposable(() => sender.send('vscode:electron-main->shared-process=exit')));
// complete IPC-ready promise when shared process signals this to us
ipcMain.once('shared-process->electron-main: ipc-ready', () => c(undefined));
ipcMain.once('vscode:shared-process->electron-main=ipc-ready', () => c(undefined));
}));
});
}

View file

@ -163,10 +163,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
show: !isFullscreenOrMaximized,
title: product.nameLong,
webPreferences: {
preload: URI.parse(this.doGetPreloadUrl()).fsPath,
nodeIntegration: true,
nodeIntegrationInWorker: RUN_TEXTMATE_IN_WORKER,
webviewTag: true,
enableWebSQL: false
webviewTag: true
}
};
@ -777,6 +777,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
}
private doGetPreloadUrl(): string {
return require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js');
}
serializeWindowState(): IWindowState {
if (!this._win) {
return defaultWindowState();

View file

@ -12,6 +12,7 @@ import { IUndoRedoService, IResourceUndoRedoElement, UndoRedoElementType, IWorks
import { URI } from 'vs/base/common/uri';
import { TextChange, compressConsecutiveTextChanges } from 'vs/editor/common/model/textChange';
import * as buffer from 'vs/base/common/buffer';
import { IDisposable } from 'vs/base/common/lifecycle';
function uriGetComparisonKey(resource: URI): string {
return resource.toString();
@ -138,6 +139,10 @@ class SingleModelEditStackData {
}
}
export interface IUndoRedoDelegate {
prepareUndoRedo(element: MultiModelEditStackElement): Promise<IDisposable> | IDisposable | void;
}
export class SingleModelEditStackElement implements IResourceUndoRedoElement {
public model: ITextModel | URI;
@ -224,6 +229,8 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement {
private readonly _editStackElementsArr: SingleModelEditStackElement[];
private readonly _editStackElementsMap: Map<string, SingleModelEditStackElement>;
private _delegate: IUndoRedoDelegate | null;
public get resources(): readonly URI[] {
return this._editStackElementsArr.map(editStackElement => editStackElement.resource);
}
@ -240,6 +247,27 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement {
const key = uriGetComparisonKey(editStackElement.resource);
this._editStackElementsMap.set(key, editStackElement);
}
this._delegate = null;
}
public setDelegate(delegate: IUndoRedoDelegate): void {
this._delegate = delegate;
}
public prepareUndoRedo(): Promise<IDisposable> | IDisposable | void {
if (this._delegate) {
return this._delegate.prepareUndoRedo(this);
}
}
public getMissingModels(): URI[] {
const result: URI[] = [];
for (const editStackElement of this._editStackElementsArr) {
if (URI.isUri(editStackElement.model)) {
result.push(editStackElement.model);
}
}
return result;
}
public setModel(model: ITextModel | URI): void {

View file

@ -113,12 +113,12 @@ interface IRawConfig {
const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? DefaultEndOfLine.LF : DefaultEndOfLine.CRLF;
interface EditStackPastFutureElements {
export interface EditStackPastFutureElements {
past: EditStackElement[];
future: EditStackElement[];
}
function isEditStackPastFutureElements(undoElements: IPastFutureElements): undoElements is EditStackPastFutureElements {
export function isEditStackPastFutureElements(undoElements: IPastFutureElements): undoElements is EditStackPastFutureElements {
return (isEditStackElements(undoElements.past) && isEditStackElements(undoElements.future));
}

View file

@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
import { isEditStackPastFutureElements } from 'vs/editor/common/services/modelServiceImpl';
import { IUndoRedoDelegate, MultiModelEditStackElement } from 'vs/editor/common/model/editStack';
export class ModelUndoRedoParticipant extends Disposable implements IUndoRedoDelegate {
constructor(
@IModelService private readonly _modelService: IModelService,
@ITextModelService private readonly _textModelService: ITextModelService,
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
) {
super();
this._register(this._modelService.onModelRemoved((model) => {
// a model will get disposed, so let's check if the undo redo stack is maintained
const elements = this._undoRedoService.getElements(model.uri);
if (elements.past.length === 0 && elements.future.length === 0) {
return;
}
if (!isEditStackPastFutureElements(elements)) {
return;
}
for (const element of elements.past) {
if (element.type === UndoRedoElementType.Workspace) {
element.setDelegate(this);
}
}
for (const element of elements.future) {
if (element.type === UndoRedoElementType.Workspace) {
element.setDelegate(this);
}
}
}));
}
public prepareUndoRedo(element: MultiModelEditStackElement): IDisposable | Promise<IDisposable> {
// Load all the needed text models
const missingModels = element.getMissingModels();
if (missingModels.length === 0) {
// All models are available!
return Disposable.None;
}
const disposablesPromises = missingModels.map(async (uri) => {
try {
const reference = await this._textModelService.createModelReference(uri);
return <IDisposable>reference;
} catch (err) {
// This model could not be loaded, maybe it was deleted in the meantime?
return Disposable.None;
}
});
return Promise.all(disposablesPromises).then(disposables => {
return {
dispose: () => dispose(disposables)
};
});
}
}

View file

@ -359,7 +359,7 @@ export class CommonFindController extends Disposable implements IEditorContribut
&& this._editor.hasModel()
&& !this._editor.getModel().isTooLargeForSyncing()
) {
return this._clipboardService.readFindText();
return this._clipboardService.readFindTextSync();
}
return '';
}
@ -370,7 +370,7 @@ export class CommonFindController extends Disposable implements IEditorContribut
&& this._editor.hasModel()
&& !this._editor.getModel().isTooLargeForSyncing()
) {
this._clipboardService.writeFindText(text);
this._clipboardService.writeFindTextSync(text);
}
}
}

View file

@ -28,7 +28,6 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IdleValue, raceCancellation } from 'vs/base/common/async';
import { withNullAsUndefined } from 'vs/base/common/types';
import { ILogService } from 'vs/platform/log/common/log';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
@ -38,6 +37,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/tex
class RenameSkeleton {
private readonly _providers: RenameProvider[];
private _providerRenameIdx: number = 0;
constructor(
private readonly model: ITextModel,
@ -51,30 +51,45 @@ class RenameSkeleton {
}
async resolveRenameLocation(token: CancellationToken): Promise<RenameLocation & Rejection | undefined> {
const firstProvider = this._providers[0];
if (!firstProvider) {
return undefined;
}
let res: RenameLocation & Rejection | undefined;
if (firstProvider.resolveRenameLocation) {
res = withNullAsUndefined(await firstProvider.resolveRenameLocation(this.model, this.position, token));
}
const rejects: string[] = [];
if (!res) {
const word = this.model.getWordAtPosition(this.position);
if (word) {
return {
range: new Range(this.position.lineNumber, word.startColumn, this.position.lineNumber, word.endColumn),
text: word.word
};
for (this._providerRenameIdx = 0; this._providerRenameIdx < this._providers.length; this._providerRenameIdx++) {
const provider = this._providers[this._providerRenameIdx];
if (!provider.resolveRenameLocation) {
break;
}
let res = await provider.resolveRenameLocation(this.model, this.position, token);
if (!res) {
continue;
}
if (res.rejectReason) {
rejects.push(res.rejectReason);
continue;
}
return res;
}
return res;
const word = this.model.getWordAtPosition(this.position);
if (!word) {
return {
range: Range.fromPositions(this.position),
text: '',
rejectReason: rejects.length > 0 ? rejects.join('\n') : undefined
};
}
return {
range: new Range(this.position.lineNumber, word.startColumn, this.position.lineNumber, word.endColumn),
text: word.word,
rejectReason: rejects.length > 0 ? rejects.join('\n') : undefined
};
}
async provideRenameEdits(newName: string, i: number, rejects: string[], token: CancellationToken): Promise<WorkspaceEdit & Rejection> {
async provideRenameEdits(newName: string, token: CancellationToken): Promise<WorkspaceEdit & Rejection> {
return this._provideRenameEdits(newName, this._providerRenameIdx, [], token);
}
private async _provideRenameEdits(newName: string, i: number, rejects: string[], token: CancellationToken): Promise<WorkspaceEdit & Rejection> {
const provider = this._providers[i];
if (!provider) {
return {
@ -85,16 +100,21 @@ class RenameSkeleton {
const result = await provider.provideRenameEdits(this.model, this.position, newName, token);
if (!result) {
return this.provideRenameEdits(newName, i + 1, rejects.concat(nls.localize('no result', "No result.")), token);
return this._provideRenameEdits(newName, i + 1, rejects.concat(nls.localize('no result', "No result.")), token);
} else if (result.rejectReason) {
return this.provideRenameEdits(newName, i + 1, rejects.concat(result.rejectReason), token);
return this._provideRenameEdits(newName, i + 1, rejects.concat(result.rejectReason), token);
}
return result;
}
}
export async function rename(model: ITextModel, position: Position, newName: string): Promise<WorkspaceEdit & Rejection> {
return new RenameSkeleton(model, position).provideRenameEdits(newName, 0, [], CancellationToken.None);
const skeleton = new RenameSkeleton(model, position);
const loc = await skeleton.resolveRenameLocation(CancellationToken.None);
if (loc?.rejectReason) {
return { edits: [], rejectReason: loc.rejectReason };
}
return skeleton.provideRenameEdits(newName, CancellationToken.None);
}
// --- register actions and commands
@ -194,7 +214,7 @@ class RenameController implements IEditorContribution {
this.editor.focus();
const renameOperation = raceCancellation(skeleton.provideRenameEdits(inputFieldResult.newName, 0, [], this._cts.token), this._cts.token).then(async renameResult => {
const renameOperation = raceCancellation(skeleton.provideRenameEdits(inputFieldResult.newName, this._cts.token), this._cts.token).then(async renameResult => {
if (!renameResult || !this.editor.hasModel()) {
return;

View file

@ -82,7 +82,7 @@ export class RenameInputField implements IContentWidget {
const updateLabel = () => {
const [accept, preview] = this._acceptKeybindings;
this._keybindingService.lookupKeybinding(accept);
this._label!.innerText = localize('label', "{0} to Rename, {1} to Preview", this._keybindingService.lookupKeybinding(accept)?.getLabel(), this._keybindingService.lookupKeybinding(preview)?.getLabel());
this._label!.innerText = localize({ key: 'label', comment: ['placeholders are keybindings, e.g "F2 to Rename, Shift+F2 to Preview"'] }, "{0} to Rename, {1} to Preview", this._keybindingService.lookupKeybinding(accept)?.getLabel(), this._keybindingService.lookupKeybinding(preview)?.getLabel());
};
updateLabel();
this._disposables.add(this._keybindingService.onDidUpdateKeybindings(updateLabel));

View file

@ -108,12 +108,11 @@ function withTypedEditor<T>(widget: IEditor, codeEditorCallback: (editor: ICodeE
export class SimpleEditorModelResolverService implements ITextModelService {
public _serviceBrand: undefined;
private readonly modelService: IModelService | undefined;
private editor?: IEditor;
constructor(modelService: IModelService | undefined) {
this.modelService = modelService;
}
constructor(
@IModelService private readonly modelService: IModelService
) { }
public setEditor(editor: IEditor): void {
this.editor = editor;
@ -146,7 +145,7 @@ export class SimpleEditorModelResolverService implements ITextModelService {
}
private findModel(editor: ICodeEditor, resource: URI): ITextModel | null {
let model = this.modelService ? this.modelService.getModel(resource) : editor.getModel();
let model = this.modelService.getModel(resource);
if (model && model.uri.toString() !== resource.toString()) {
return null;
}

View file

@ -7,7 +7,6 @@ import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';
import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
export class AuthenticationTokenServiceChannel implements IServerChannel {
constructor(private readonly service: IAuthenticationTokenService) { }

View file

@ -11,11 +11,15 @@ export class BrowserClipboardService implements IClipboardService {
_serviceBrand: undefined;
private _internalResourcesClipboard: URI[] | undefined;
private readonly mapTextToType = new Map<string, string>(); // unsupported in web (only in-memory)
async writeText(text: string, type?: string): Promise<void> {
// With type: only in-memory is supported
if (type) {
return; // TODO@sbatten support for writing a specific type into clipboard is unsupported
this.mapTextToType.set(type, text);
return;
}
// Guard access to navigator.clipboard with try/catch
@ -52,8 +56,10 @@ export class BrowserClipboardService implements IClipboardService {
}
async readText(type?: string): Promise<string> {
// With type: only in-memory is supported
if (type) {
return ''; // TODO@sbatten support for reading a specific type from clipboard is unsupported
return this.mapTextToType.get(type) || '';
}
// Guard access to navigator.clipboard with try/catch
@ -68,26 +74,42 @@ export class BrowserClipboardService implements IClipboardService {
}
}
private findText = ''; // unsupported in web (only in-memory)
async readFindText(): Promise<string> {
return this.findText;
}
async writeFindText(text: string): Promise<void> {
this.findText = text;
}
private resources: URI[] = []; // unsupported in web (only in-memory)
async writeResources(resources: URI[]): Promise<void> {
this.resources = resources;
}
async readResources(): Promise<URI[]> {
return this.resources;
}
async hasResources(): Promise<boolean> {
return this.resources.length > 0;
}
/** @deprecated */
readTextSync(): string | undefined {
return undefined;
}
readFindText(): string {
// @ts-expect-error
return undefined;
/** @deprecated */
readFindTextSync(): string {
return this.findText;
}
writeFindText(text: string): void { }
writeResources(resources: URI[]): void {
this._internalResourcesClipboard = resources;
}
readResources(): URI[] {
return this._internalResourcesClipboard || [];
}
hasResources(): boolean {
return this._internalResourcesClipboard !== undefined && this._internalResourcesClipboard.length > 0;
/** @deprecated */
writeFindTextSync(text: string): void {
this.findText = text;
}
}

View file

@ -22,30 +22,38 @@ export interface IClipboardService {
*/
readText(type?: string): Promise<string>;
readTextSync(): string | undefined;
/**
* Reads text from the system find pasteboard.
*/
readFindText(): string;
readFindText(): Promise<string>;
/**
* Writes text to the system find pasteboard.
*/
writeFindText(text: string): void;
writeFindText(text: string): Promise<void>;
/**
* Writes resources to the system clipboard.
*/
writeResources(resources: URI[]): void;
writeResources(resources: URI[]): Promise<void>;
/**
* Reads resources from the system clipboard.
*/
readResources(): URI[];
readResources(): Promise<URI[]>;
/**
* Find out if resources are copied to the clipboard.
*/
hasResources(): boolean;
hasResources(): Promise<boolean>;
/** @deprecated */
readTextSync(): string | undefined;
/** @deprecated */
readFindTextSync(): string;
/** @deprecated */
writeFindTextSync(text: string): void;
}

View file

@ -272,3 +272,12 @@ export function getFileNamesMessage(fileNamesOrResources: readonly (string | URI
message.push('');
return message.join('\n');
}
export interface INativeOpenDialogOptions {
forceNewWindow?: boolean;
defaultPath?: string;
telemetryEventName?: string;
telemetryExtraData?: ITelemetryData;
}

View file

@ -11,7 +11,7 @@ import { isMacintosh } from 'vs/base/common/platform';
import { dirname } from 'vs/base/common/path';
import { normalizeNFC } from 'vs/base/common/normalization';
import { exists } from 'vs/base/node/pfs';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { withNullAsUndefined } from 'vs/base/common/types';
import { localize } from 'vs/nls';
import { WORKSPACE_FILTER } from 'vs/platform/workspaces/common/workspaces';

View file

@ -6,11 +6,11 @@
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/node/driver';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import * as electron from 'electron';
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { remote } from 'electron';
import { timeout } from 'vs/base/common/async';
import { BaseWindowDriver } from 'vs/platform/driver/browser/baseDriver';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
class WindowDriver extends BaseWindowDriver {
@ -32,7 +32,7 @@ class WindowDriver extends BaseWindowDriver {
private async _click(selector: string, clickCount: number, offset?: { x: number, y: number }): Promise<void> {
const { x, y } = await this._getElementXY(selector, offset);
const webContents: electron.WebContents = (electron as any).remote.getCurrentWebContents();
const webContents = remote.getCurrentWebContents();
webContents.sendInputEvent({ type: 'mouseDown', x, y, button: 'left', clickCount } as any);
await timeout(10);

View file

@ -4,19 +4,18 @@
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'electron';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'vs/base/parts/sandbox/common/electronTypes';
import { IOpenedWindow, IWindowOpenable, IOpenEmptyWindowOptions, INativeOpenWindowOptions } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { INativeOpenWindowOptions, IOpenedWindow } from 'vs/platform/windows/node/window';
export const IElectronService = createDecorator<IElectronService>('electronService');
export interface IElectronService {
export interface ICommonElectronService {
_serviceBrand: undefined;
// Properties
readonly windowId: number;
// Events
readonly onWindowOpen: Event<number>;
@ -61,6 +60,16 @@ export interface IElectronService {
setDocumentEdited(edited: boolean): Promise<void>;
openExternal(url: string): Promise<boolean>;
updateTouchBar(items: ISerializableCommandAction[][]): Promise<void>;
moveItemToTrash(fullPath: string, deleteOnFail?: boolean): Promise<boolean>;
// clipboard
readClipboardText(type?: 'selection' | 'clipboard'): Promise<string>;
writeClipboardText(text: string, type?: 'selection' | 'clipboard'): Promise<void>;
readClipboardFindText(): Promise<string>;
writeClipboardFindText(text: string): Promise<void>;
writeClipboardBuffer(format: string, buffer: Uint8Array, type?: 'selection' | 'clipboard'): Promise<void>;
readClipboardBuffer(format: string): Promise<Uint8Array>;
hasClipboard(format: string, type?: 'selection' | 'clipboard'): Promise<boolean>;
// macOS Touchbar
newWindowTab(): Promise<void>;

View file

@ -5,13 +5,13 @@
import { Event } from 'vs/base/common/event';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron';
import { INativeOpenWindowOptions, IOpenedWindow, OpenContext } from 'vs/platform/windows/node/window';
import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app, clipboard } from 'electron';
import { OpenContext } from 'vs/platform/windows/node/window';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
import { IOpenedWindow, INativeOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { isMacintosh } from 'vs/base/common/platform';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { ICommonElectronService } from 'vs/platform/electron/common/electron';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { AddFirstParameterToFunctions } from 'vs/base/common/types';
@ -23,9 +23,9 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import { ILogService } from 'vs/platform/log/common/log';
import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
export interface IElectronMainService extends AddFirstParameterToFunctions<IElectronService, Promise<unknown> /* only methods, not events */, number | undefined /* window ID */> { }
export interface IElectronMainService extends AddFirstParameterToFunctions<ICommonElectronService, Promise<unknown> /* only methods, not events */, number | undefined /* window ID */> { }
export const IElectronMainService = createDecorator<IElectronService>('electronMainService');
export const IElectronMainService = createDecorator<IElectronMainService>('electronMainService');
export class ElectronMainService implements IElectronMainService {
@ -41,6 +41,12 @@ export class ElectronMainService implements IElectronMainService {
) {
}
//#region Properties
get windowId(): never { throw new Error('Not implemented in electron-main'); }
//#endregion
//#region Events
readonly onWindowOpen: Event<number> = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-created', (_, window: BrowserWindow) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId));
@ -293,6 +299,43 @@ export class ElectronMainService implements IElectronMainService {
}
}
async moveItemToTrash(windowId: number | undefined, fullPath: string): Promise<boolean> {
return shell.moveItemToTrash(fullPath);
}
//#endregion
//#region clipboard
async readClipboardText(windowId: number | undefined, type?: 'selection' | 'clipboard'): Promise<string> {
return clipboard.readText(type);
}
async writeClipboardText(windowId: number | undefined, text: string, type?: 'selection' | 'clipboard'): Promise<void> {
return clipboard.writeText(text, type);
}
async readClipboardFindText(windowId: number | undefined,): Promise<string> {
return clipboard.readFindText();
}
async writeClipboardFindText(windowId: number | undefined, text: string): Promise<void> {
return clipboard.writeFindText(text);
}
async writeClipboardBuffer(windowId: number | undefined, format: string, buffer: Uint8Array, type?: 'selection' | 'clipboard'): Promise<void> {
return clipboard.writeBuffer(format, buffer as Buffer, type);
}
async readClipboardBuffer(windowId: number | undefined, format: string): Promise<Uint8Array> {
return clipboard.readBuffer(format);
}
async hasClipboard(windowId: number | undefined, format: string, type?: 'selection' | 'clipboard'): Promise<boolean> {
return clipboard.has(format, type);
}
//#endregion
//#region macOS Touchbar

View file

@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICommonElectronService } from 'vs/platform/electron/common/electron';
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
import { createChannelSender } from 'vs/base/parts/ipc/common/ipc';
export const IElectronService = createDecorator<IElectronService>('electronService');
export interface IElectronService extends ICommonElectronService { }
export class ElectronService {
_serviceBrand: undefined;
constructor(
readonly windowId: number,
@IMainProcessService mainProcessService: IMainProcessService
) {
return createChannelSender<IElectronService>(mainProcessService.getChannel('electron'), {
context: windowId,
properties: (() => {
const properties = new Map<string, unknown>();
properties.set('windowId', windowId);
return properties;
})()
});
}
}

View file

@ -6,7 +6,7 @@
import * as assert from 'assert';
import { firstIndex } from 'vs/base/common/arrays';
import { localize } from 'vs/nls';
import { MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/node/files';
import { MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files';
import { parseArgs, ErrorReporter, OPTIONS, ParsedArgs } from 'vs/platform/environment/node/argv';
function parseAndValidate(cmdLineArgs: string[], reportWarnings: boolean): ParsedArgs {

View file

@ -362,10 +362,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
}
const { id, uuid } = extension ? extension.identifier : <IExtensionIdentifier>arg1;
let query = new Query()
.withFlags(Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated)
.withFlags(Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties)
.withPage(1, 1)
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code')
.withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished));
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code');
if (uuid) {
query = query.withFilter(FilterType.ExtensionId, uuid);
@ -426,8 +425,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
let query = new Query()
.withFlags(Flags.IncludeLatestVersionOnly, Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties)
.withPage(1, pageSize)
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code')
.withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished));
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code');
if (text) {
// Use category filter instead of "category:themes"
@ -484,6 +482,11 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
}
private queryGallery(query: Query, token: CancellationToken): Promise<{ galleryExtensions: IRawGalleryExtension[], total: number; }> {
// Always exclude non validated and unpublished extensions
query = query
.withFlags(query.flags, Flags.ExcludeNonValidated)
.withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished));
if (!this.isEnabled()) {
return Promise.reject(new Error('No extension gallery service configured.'));
}
@ -602,10 +605,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise<IGalleryExtensionVersion[]> {
let query = new Query()
.withFlags(Flags.IncludeVersions, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated)
.withFlags(Flags.IncludeVersions, Flags.IncludeFiles, Flags.IncludeVersionProperties)
.withPage(1, 1)
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code')
.withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished));
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code');
if (extension.identifier.uuid) {
query = query.withFilter(FilterType.ExtensionId, extension.identifier.uuid);

View file

@ -824,7 +824,6 @@ export function etag(stat: { mtime: number | undefined, size: number | undefined
return stat.mtime.toString(29) + stat.size.toString(31);
}
export function whenProviderRegistered(file: URI, fileService: IFileService): Promise<void> {
if (fileService.canHandleResource(URI.from({ scheme: file.scheme }))) {
return Promise.resolve();
@ -838,3 +837,9 @@ export function whenProviderRegistered(file: URI, fileService: IFileService): Pr
});
});
}
/**
* Desktop only: limits for memory sizes
*/
export const MIN_MAX_MEMORY_SIZE_MB = 2048;
export const FALLBACK_MAX_MEMORY_SIZE_MB = 4096;

View file

@ -3,15 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { shell } from 'electron';
import { DiskFileSystemProvider as NodeDiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { DiskFileSystemProvider as NodeDiskFileSystemProvider, IDiskFileSystemProviderOptions } from 'vs/platform/files/node/diskFileSystemProvider';
import { FileDeleteOptions, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
import { isWindows } from 'vs/base/common/platform';
import { localize } from 'vs/nls';
import { basename } from 'vs/base/common/path';
import { ILogService } from 'vs/platform/log/common/log';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
export class DiskFileSystemProvider extends NodeDiskFileSystemProvider {
constructor(
logService: ILogService,
private electronService: IElectronService,
options?: IDiskFileSystemProviderOptions
) {
super(logService, options);
}
get capabilities(): FileSystemProviderCapabilities {
if (!this._capabilities) {
this._capabilities = super.capabilities | FileSystemProviderCapabilities.Trash;
@ -25,9 +34,9 @@ export class DiskFileSystemProvider extends NodeDiskFileSystemProvider {
return super.doDelete(filePath, opts);
}
const result = shell.moveItemToTrash(filePath);
const result = await this.electronService.moveItemToTrash(filePath);
if (!result) {
throw new Error(isWindows ? localize('binFailed', "Failed to move '{0}' to the recycle bin", basename(filePath)) : localize('trashFailed', "Failed to move '{0}' to the trash", basename(filePath)));
}
}
}
}

View file

@ -7,7 +7,7 @@ import * as assert from 'assert';
import { tmpdir } from 'os';
import { FileService } from 'vs/platform/files/common/fileService';
import { Schemas } from 'vs/base/common/network';
import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
import { generateUuid } from 'vs/base/common/uuid';
import { join, basename, dirname, posix } from 'vs/base/common/path';

View file

@ -3,10 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Client } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { Client } from 'vs/base/parts/ipc/electron-sandbox/ipc.electron-sandbox';
import { Disposable } from 'vs/base/common/lifecycle';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const IMainProcessService = createDecorator<IMainProcessService>('mainProcessService');

View file

@ -3,10 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const IIssueService = createDecorator<IIssueService>('issueService');
// Since data sent through the service is serialized to JSON, functions will be lost, so Color objects
// should not be sent as their 'toString' method will be stripped. Instead convert to strings before sending.
export interface WindowStyles {
@ -91,7 +87,7 @@ export interface ProcessExplorerData extends WindowData {
styles: ProcessExplorerStyles;
}
export interface IIssueService {
export interface ICommonIssueService {
_serviceBrand: undefined;
openReporter(data: IssueReporterData): Promise<void>;
openProcessExplorer(data: ProcessExplorerData): Promise<void>;

View file

@ -6,7 +6,7 @@
import { localize } from 'vs/nls';
import * as objects from 'vs/base/common/objects';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/node/issue';
import { ICommonIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import { BrowserWindow, ipcMain, screen, IpcMainEvent, Display, shell } from 'electron';
import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService';
import { PerformanceInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
@ -18,10 +18,16 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IWindowState } from 'vs/platform/windows/electron-main/windows';
import { listProcesses } from 'vs/base/node/ps';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
import { URI } from 'vs/base/common/uri';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
const DEFAULT_BACKGROUND_COLOR = '#1E1E1E';
export class IssueMainService implements IIssueService {
export const IIssueMainService = createDecorator<IIssueMainService>('issueMainService');
export interface IIssueMainService extends ICommonIssueService { }
export class IssueMainService implements ICommonIssueService {
_serviceBrand: undefined;
_issueWindow: BrowserWindow | null = null;
_issueParentWindow: BrowserWindow | null = null;
@ -163,12 +169,11 @@ export class IssueMainService implements IIssueService {
}
});
ipcMain.on('windowsInfoRequest', (event: IpcMainEvent) => {
ipcMain.on('vscode:windowsInfoRequest', (event: IpcMainEvent) => {
this.launchMainService.getMainProcessInfo().then(info => {
event.sender.send('vscode:windowsInfoResponse', info.windows);
});
});
}
openReporter(data: IssueReporterData): Promise<void> {
@ -189,8 +194,8 @@ export class IssueMainService implements IIssueService {
title: localize('issueReporter', "Issue Reporter"),
backgroundColor: data.styles.backgroundColor || DEFAULT_BACKGROUND_COLOR,
webPreferences: {
nodeIntegration: true,
enableWebSQL: false
preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath,
nodeIntegration: true
}
});
@ -225,7 +230,7 @@ export class IssueMainService implements IIssueService {
if (!this._processExplorerWindow) {
this._processExplorerParentWindow = BrowserWindow.getFocusedWindow();
if (this._processExplorerParentWindow) {
const position = this.getWindowPosition(this._processExplorerParentWindow, 800, 300);
const position = this.getWindowPosition(this._processExplorerParentWindow, 800, 500);
this._processExplorerWindow = new BrowserWindow({
skipTaskbar: true,
resizable: true,
@ -239,8 +244,8 @@ export class IssueMainService implements IIssueService {
backgroundColor: data.styles.backgroundColor,
title: localize('processExplorer', "Process Explorer"),
webPreferences: {
nodeIntegration: true,
enableWebSQL: false
preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath,
nodeIntegration: true
}
});

View file

@ -0,0 +1,11 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICommonIssueService } from 'vs/platform/issue/common/issue';
export const IIssueService = createDecorator<IIssueService>('issueService');
export interface IIssueService extends ICommonIssueService { }

View file

@ -3,14 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
export const IMenubarService = createDecorator<IMenubarService>('menubarService');
export interface IMenubarService {
_serviceBrand: undefined;
export interface ICommonMenubarService {
updateMenubar(windowId: number, menuData: IMenubarData): Promise<void>;
}

View file

@ -18,7 +18,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { mnemonicMenuLabel as baseMnemonicLabel } from 'vs/base/common/labels';
import { IWindowsMainService, IWindowsCountChangedEvent } from 'vs/platform/windows/electron-main/windows';
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
import { IMenubarData, IMenubarKeybinding, MenubarMenuItem, isMenubarMenuItemSeparator, isMenubarMenuItemSubmenu, isMenubarMenuItemAction, IMenubarMenu, isMenubarMenuItemUriAction } from 'vs/platform/menubar/node/menubar';
import { IMenubarData, IMenubarKeybinding, MenubarMenuItem, isMenubarMenuItemSeparator, isMenubarMenuItemSubmenu, isMenubarMenuItemAction, IMenubarMenu, isMenubarMenuItemUriAction } from 'vs/platform/menubar/common/menubar';
import { URI } from 'vs/base/common/uri';
import { IStateService } from 'vs/platform/state/node/state';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';

View file

@ -3,13 +3,19 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IMenubarService, IMenubarData } from 'vs/platform/menubar/node/menubar';
import { ICommonMenubarService, IMenubarData } from 'vs/platform/menubar/common/menubar';
import { Menubar } from 'vs/platform/menubar/electron-main/menubar';
import { ILogService } from 'vs/platform/log/common/log';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
export class MenubarMainService implements IMenubarService {
export const IMenubarMainService = createDecorator<IMenubarMainService>('menubarMainService');
export interface IMenubarMainService extends ICommonMenubarService {
_serviceBrand: undefined;
}
export class MenubarMainService implements IMenubarMainService {
_serviceBrand: undefined;

View file

@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICommonMenubarService } from 'vs/platform/menubar/common/menubar';
export const IMenubarService = createDecorator<IMenubarService>('menubarService');
export interface IMenubarService extends ICommonMenubarService {
_serviceBrand: undefined;
}

View file

@ -5,6 +5,7 @@
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
export const IUndoRedoService = createDecorator<IUndoRedoService>('undoRedoService');
@ -28,6 +29,13 @@ export interface IWorkspaceUndoRedoElement {
undo(): Promise<void> | void;
redo(): Promise<void> | void;
split(): IResourceUndoRedoElement[];
/**
* If implemented, will be invoked before calling `undo()` or `redo()`.
* This is a good place to prepare everything such that the calls to `undo()` or `redo()` are synchronous.
* If a disposable is returned, it will be invoked to clean things up.
*/
prepareUndoRedo?(): Promise<IDisposable> | IDisposable | void;
}
export type IUndoRedoElement = IResourceUndoRedoElement | IWorkspaceUndoRedoElement;

View file

@ -12,6 +12,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import Severity from 'vs/base/common/severity';
import { Schemas } from 'vs/base/common/network';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
function uriGetComparisonKey(resource: URI): string {
return resource.toString();
@ -76,7 +77,7 @@ class RemovedResources {
let messages: string[] = [];
if (externalRemoval.length > 0) {
messages.push(nls.localize('externalRemoval', "The following files have been closed: {0}.", externalRemoval.join(', ')));
messages.push(nls.localize('externalRemoval', "The following files have been closed and modified on disk: {0}.", externalRemoval.join(', ')));
}
if (noParallelUniverses.length > 0) {
messages.push(nls.localize('noParallelUniverses', "The following files have been modified in an incompatible way: {0}.", noParallelUniverses.join(', ')));
@ -154,11 +155,13 @@ class ResourceEditStack {
public resource: URI;
public past: StackElement[];
public future: StackElement[];
public locked: boolean;
constructor(resource: URI) {
this.resource = resource;
this.past = [];
this.future = [];
this.locked = false;
}
}
@ -363,55 +366,135 @@ export class UndoRedoService implements IUndoRedoService {
this._notificationService.error(err);
}
private _safeInvoke(element: StackElement, invoke: () => Promise<void> | void): Promise<void> | void {
private _acquireLocks(affectedEditStacks: ResourceEditStack[]): () => void {
// first, check if all locks can be acquired
for (const editStack of affectedEditStacks) {
if (editStack.locked) {
throw new Error('Cannot acquire edit stack lock');
}
}
// can acquire all locks
for (const editStack of affectedEditStacks) {
editStack.locked = true;
}
return () => {
// release all locks
for (const editStack of affectedEditStacks) {
editStack.locked = false;
}
};
}
private _safeInvokeWithLocks(element: StackElement, invoke: () => Promise<void> | void, affectedEditStacks: ResourceEditStack[], cleanup: IDisposable = Disposable.None): Promise<void> | void {
const releaseLocks = this._acquireLocks(affectedEditStacks);
let result: Promise<void> | void;
try {
result = invoke();
} catch (err) {
releaseLocks();
cleanup.dispose();
return this._onError(err, element);
}
if (result) {
return result.then(undefined, (err) => this._onError(err, element));
// result is Promise<void>
return result.then(
() => {
releaseLocks();
cleanup.dispose();
},
(err) => {
releaseLocks();
cleanup.dispose();
return this._onError(err, element);
}
);
} else {
// result is void
releaseLocks();
cleanup.dispose();
}
}
private _workspaceUndo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
private async _invokePrepare(element: WorkspaceStackElement): Promise<IDisposable> {
if (typeof element.actual.prepareUndoRedo === 'undefined') {
return Disposable.None;
}
const result = element.actual.prepareUndoRedo();
if (typeof result === 'undefined') {
return Disposable.None;
}
return result;
}
private _getAffectedEditStacks(element: WorkspaceStackElement): ResourceEditStack[] {
const affectedEditStacks: ResourceEditStack[] = [];
for (const strResource of element.strResources) {
affectedEditStacks.push(this._editStacks.get(strResource)!);
}
return affectedEditStacks;
}
private _checkWorkspaceUndo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[], checkInvalidatedResources: boolean): WorkspaceVerificationError | null {
if (element.removedResources) {
this._splitPastWorkspaceElement(element, element.removedResources);
const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
this._notificationService.info(message);
return this.undo(resource);
return new WorkspaceVerificationError(this.undo(resource));
}
if (element.invalidatedResources) {
if (checkInvalidatedResources && element.invalidatedResources) {
this._splitPastWorkspaceElement(element, element.invalidatedResources);
const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.invalidatedResources.createMessage());
this._notificationService.info(message);
return this.undo(resource);
return new WorkspaceVerificationError(this.undo(resource));
}
// this must be the last past element in all the impacted resources!
let affectedEditStacks: ResourceEditStack[] = [];
for (const strResource of element.strResources) {
affectedEditStacks.push(this._editStacks.get(strResource)!);
}
let cannotUndoDueToResources: URI[] = [];
const cannotUndoDueToResources: URI[] = [];
for (const editStack of affectedEditStacks) {
if (editStack.past.length === 0 || editStack.past[editStack.past.length - 1] !== element) {
cannotUndoDueToResources.push(editStack.resource);
}
}
if (cannotUndoDueToResources.length > 0) {
this._splitPastWorkspaceElement(element, null);
const paths = cannotUndoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
const message = nls.localize('cannotWorkspaceUndoDueToChanges', "Could not undo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
this._notificationService.info(message);
return this.undo(resource);
return new WorkspaceVerificationError(this.undo(resource));
}
return this._dialogService.show(
const cannotLockDueToResources: URI[] = [];
for (const editStack of affectedEditStacks) {
if (editStack.locked) {
cannotLockDueToResources.push(editStack.resource);
}
}
if (cannotLockDueToResources.length > 0) {
this._splitPastWorkspaceElement(element, null);
const paths = cannotLockDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
const message = nls.localize('cannotWorkspaceUndoDueToInProgressUndoRedo', "Could not undo '{0}' across all files because there is already an undo or redo operation running on {1}", element.label, paths.join(', '));
this._notificationService.info(message);
return new WorkspaceVerificationError(this.undo(resource));
}
return null;
}
private _workspaceUndo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
const affectedEditStacks = this._getAffectedEditStacks(element);
const verificationError = this._checkWorkspaceUndo(resource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/false);
if (verificationError) {
return verificationError.returnValue;
}
return this._confirmAndExecuteWorkspaceUndo(resource, element, affectedEditStacks);
}
private async _confirmAndExecuteWorkspaceUndo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[]): Promise<void> {
const result = await this._dialogService.show(
Severity.Info,
nls.localize('confirmWorkspace', "Would you like to undo '{0}' across all files?", element.label),
[
@ -422,21 +505,47 @@ export class UndoRedoService implements IUndoRedoService {
{
cancelId: 2
}
).then((result) => {
if (result.choice === 2) {
// cancel
return;
} else if (result.choice === 0) {
for (const editStack of affectedEditStacks) {
editStack.past.pop();
editStack.future.push(element);
}
return this._safeInvoke(element, () => element.actual.undo());
} else {
this._splitPastWorkspaceElement(element, null);
return this.undo(resource);
}
});
);
if (result.choice === 2) {
// choice: cancel
return;
}
if (result.choice === 1) {
// choice: undo this file
this._splitPastWorkspaceElement(element, null);
return this.undo(resource);
}
// choice: undo in all files
// At this point, it is possible that the element has been made invalid in the meantime (due to the confirmation await)
const verificationError1 = this._checkWorkspaceUndo(resource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/false);
if (verificationError1) {
return verificationError1.returnValue;
}
// prepare
let cleanup: IDisposable;
try {
cleanup = await this._invokePrepare(element);
} catch (err) {
return this._onError(err, element);
}
// At this point, it is possible that the element has been made invalid in the meantime (due to the prepare await)
const verificationError2 = this._checkWorkspaceUndo(resource, element, affectedEditStacks, /*now also check that there are no more invalidated resources*/true);
if (verificationError2) {
cleanup.dispose();
return verificationError2.returnValue;
}
for (const editStack of affectedEditStacks) {
editStack.past.pop();
editStack.future.push(element);
}
return this._safeInvokeWithLocks(element, () => element.actual.undo(), affectedEditStacks, cleanup);
}
private _resourceUndo(editStack: ResourceEditStack, element: ResourceStackElement): Promise<void> | void {
@ -446,9 +555,14 @@ export class UndoRedoService implements IUndoRedoService {
editStack.future = [];
return;
}
if (editStack.locked) {
const message = nls.localize('cannotResourceUndoDueToInProgressUndoRedo', "Could not undo '{0}' because there is already an undo or redo operation running.", element.label);
this._notificationService.info(message);
return;
}
editStack.past.pop();
editStack.future.push(element);
return this._safeInvoke(element, () => element.actual.undo());
return this._safeInvokeWithLocks(element, () => element.actual.undo(), [editStack]);
}
public undo(resource: URI): Promise<void> | void {
@ -479,46 +593,82 @@ export class UndoRedoService implements IUndoRedoService {
return false;
}
private _workspaceRedo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
private _checkWorkspaceRedo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[], checkInvalidatedResources: boolean): WorkspaceVerificationError | null {
if (element.removedResources) {
this._splitFutureWorkspaceElement(element, element.removedResources);
const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.removedResources.createMessage());
this._notificationService.info(message);
return this.redo(resource);
return new WorkspaceVerificationError(this.redo(resource));
}
if (element.invalidatedResources) {
if (checkInvalidatedResources && element.invalidatedResources) {
this._splitFutureWorkspaceElement(element, element.invalidatedResources);
const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.invalidatedResources.createMessage());
this._notificationService.info(message);
return this.redo(resource);
return new WorkspaceVerificationError(this.redo(resource));
}
// this must be the last future element in all the impacted resources!
let affectedEditStacks: ResourceEditStack[] = [];
for (const strResource of element.strResources) {
affectedEditStacks.push(this._editStacks.get(strResource)!);
}
let cannotRedoDueToResources: URI[] = [];
const cannotRedoDueToResources: URI[] = [];
for (const editStack of affectedEditStacks) {
if (editStack.future.length === 0 || editStack.future[editStack.future.length - 1] !== element) {
cannotRedoDueToResources.push(editStack.resource);
}
}
if (cannotRedoDueToResources.length > 0) {
this._splitFutureWorkspaceElement(element, null);
const paths = cannotRedoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
const message = nls.localize('cannotWorkspaceRedoDueToChanges', "Could not redo '{0}' across all files because changes were made to {1}", element.label, paths.join(', '));
this._notificationService.info(message);
return this.redo(resource);
return new WorkspaceVerificationError(this.redo(resource));
}
const cannotLockDueToResources: URI[] = [];
for (const editStack of affectedEditStacks) {
if (editStack.locked) {
cannotLockDueToResources.push(editStack.resource);
}
}
if (cannotLockDueToResources.length > 0) {
this._splitFutureWorkspaceElement(element, null);
const paths = cannotLockDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path);
const message = nls.localize('cannotWorkspaceRedoDueToInProgressUndoRedo', "Could not redo '{0}' across all files because there is already an undo or redo operation running on {1}", element.label, paths.join(', '));
this._notificationService.info(message);
return new WorkspaceVerificationError(this.redo(resource));
}
return null;
}
private _workspaceRedo(resource: URI, element: WorkspaceStackElement): Promise<void> | void {
const affectedEditStacks = this._getAffectedEditStacks(element);
const verificationError = this._checkWorkspaceRedo(resource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/false);
if (verificationError) {
return verificationError.returnValue;
}
return this._executeWorkspaceRedo(resource, element, affectedEditStacks);
}
private async _executeWorkspaceRedo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[]): Promise<void> {
// prepare
let cleanup: IDisposable;
try {
cleanup = await this._invokePrepare(element);
} catch (err) {
return this._onError(err, element);
}
// At this point, it is possible that the element has been made invalid in the meantime (due to the prepare await)
const verificationError = this._checkWorkspaceRedo(resource, element, affectedEditStacks, /*now also check that there are no more invalidated resources*/true);
if (verificationError) {
cleanup.dispose();
return verificationError.returnValue;
}
for (const editStack of affectedEditStacks) {
editStack.future.pop();
editStack.past.push(element);
}
return this._safeInvoke(element, () => element.actual.redo());
return this._safeInvokeWithLocks(element, () => element.actual.redo(), affectedEditStacks, cleanup);
}
private _resourceRedo(editStack: ResourceEditStack, element: ResourceStackElement): Promise<void> | void {
@ -528,9 +678,14 @@ export class UndoRedoService implements IUndoRedoService {
editStack.future = [];
return;
}
if (editStack.locked) {
const message = nls.localize('cannotResourceRedoDueToInProgressUndoRedo', "Could not redo '{0}' because there is already an undo or redo operation running.", element.label);
this._notificationService.info(message);
return;
}
editStack.future.pop();
editStack.past.push(element);
return this._safeInvoke(element, () => element.actual.redo());
return this._safeInvokeWithLocks(element, () => element.actual.redo(), [editStack]);
}
public redo(resource: URI): Promise<void> | void {
@ -553,4 +708,8 @@ export class UndoRedoService implements IUndoRedoService {
}
}
class WorkspaceVerificationError {
constructor(public readonly returnValue: Promise<void> | void) { }
}
registerSingleton(IUndoRedoService, UndoRedoService);

View file

@ -8,6 +8,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { values } from 'vs/base/common/map';
import { first } from 'vs/base/common/async';
import { toDisposable, IDisposable, Disposable } from 'vs/base/common/lifecycle';
import product from 'vs/platform/product/common/product';
export abstract class AbstractURLService extends Disposable implements IURLService {
@ -27,3 +28,16 @@ export abstract class AbstractURLService extends Disposable implements IURLServi
return toDisposable(() => this.handlers.delete(handler));
}
}
export class NativeURLService extends AbstractURLService {
create(options?: Partial<UriComponents>): URI {
let { authority, path, query, fragment } = options ? options : { authority: undefined, path: undefined, query: undefined, fragment: undefined };
if (authority && path && path.indexOf('/') !== 0) {
path = `/${path}`; // URI validation requires a path if there is an authority
}
return URI.from({ scheme: product.urlProtocol, authority, path, query, fragment });
}
}

View file

@ -1,21 +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 { URI, UriComponents } from 'vs/base/common/uri';
import product from 'vs/platform/product/common/product';
import { AbstractURLService } from 'vs/platform/url/common/urlService';
export class URLService extends AbstractURLService {
create(options?: Partial<UriComponents>): URI {
let { authority, path, query, fragment } = options ? options : { authority: undefined, path: undefined, query: undefined, fragment: undefined };
if (authority && path && path.indexOf('/') !== 0) {
path = `/${path}`; // URI validation requires a path if there is an authority
}
return URI.from({ scheme: product.urlProtocol, authority, path, query, fragment });
}
}

View file

@ -5,7 +5,7 @@
import { IUserDataSyncService, IUserDataSyncLogService, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
import { Event } from 'vs/base/common/event';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
import { UserDataAutoSyncService as BaseUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataAutoSyncService';
import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';

Some files were not shown because too many files have changed in this diff Show more