Merge branch 'master' into bugfix/fix_CVE-2020-16881_bypass

This commit is contained in:
Martin Aeschlimann 2020-10-02 17:05:36 +02:00 committed by GitHub
commit 7c91cee267
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
69 changed files with 241 additions and 432 deletions

View file

@ -1,122 +0,0 @@
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-12
ARG TARGET_DISPLAY=":1"
# VNC options
ARG MAX_VNC_RESOLUTION=1920x1080x16
ARG TARGET_VNC_RESOLUTION=1920x1080
ARG TARGET_VNC_DPI=72
ARG TARGET_VNC_PORT=5901
ARG VNC_PASSWORD="vscode"
# noVNC (VNC web client) options
ARG INSTALL_NOVNC="true"
ARG NOVNC_VERSION=1.1.0
ARG TARGET_NOVNC_PORT=6080
ARG WEBSOCKETIFY_VERSION=0.9.0
# Firefox is useful for testing things like browser launch events, but optional
ARG INSTALL_FIREFOX="false"
# Expected non-root username from base image
ARG USERNAME=node
# Core environment variables for X11, VNC, and fluxbox
ENV DBUS_SESSION_BUS_ADDRESS="autolaunch:" \
MAX_VNC_RESOLUTION="${MAX_VNC_RESOLUTION}" \
VNC_RESOLUTION="${TARGET_VNC_RESOLUTION}" \
VNC_DPI="${TARGET_VNC_DPI}" \
VNC_PORT="${TARGET_VNC_PORT}" \
NOVNC_PORT="${TARGET_NOVNC_PORT}" \
DISPLAY="${TARGET_DISPLAY}" \
LANG="en_US.UTF-8" \
LANGUAGE="en_US.UTF-8" \
VISUAL="nano" \
EDITOR="nano"
# Configure apt and install packages
RUN apt-get update \
&& export DEBIAN_FRONTEND=noninteractive \
#
# Install the Cascadia Code fonts - https://github.com/microsoft/cascadia-code
&& curl -sSL https://github.com/microsoft/cascadia-code/releases/download/v2004.30/CascadiaCode_2004.30.zip -o /tmp/cascadia-fonts.zip \
&& unzip /tmp/cascadia-fonts.zip -d /tmp/cascadia-fonts \
&& mkdir -p /usr/share/fonts/truetype/cascadia \
&& mv /tmp/cascadia-fonts/ttf/* /usr/share/fonts/truetype/cascadia/ \
&& rm -rf /tmp/cascadia-fonts.zip /tmp/cascadia-fonts \
#
# Install X11, fluxbox and VS Code dependencies
&& apt-get -y install --no-install-recommends \
xvfb \
x11vnc \
fluxbox \
dbus-x11 \
x11-utils \
x11-xserver-utils \
xdg-utils \
fbautostart \
xterm \
eterm \
gnome-terminal \
gnome-keyring \
seahorse \
nautilus \
libx11-dev \
libxkbfile-dev \
libsecret-1-dev \
libnotify4 \
libnss3 \
libxss1 \
libasound2 \
libgbm1 \
xfonts-base \
xfonts-terminus \
fonts-noto \
fonts-wqy-microhei \
fonts-droid-fallback \
vim-tiny \
nano \
#
# [Optional] Install noVNC
&& if [ "${INSTALL_NOVNC}" = "true" ]; then \
mkdir -p /usr/local/novnc \
&& curl -sSL https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.zip -o /tmp/novnc-install.zip \
&& unzip /tmp/novnc-install.zip -d /usr/local/novnc \
&& cp /usr/local/novnc/noVNC-${NOVNC_VERSION}/vnc_lite.html /usr/local/novnc/noVNC-${NOVNC_VERSION}/index.html \
&& rm /tmp/novnc-install.zip \
&& curl -sSL https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.zip -o /tmp/websockify-install.zip \
&& unzip /tmp/websockify-install.zip -d /usr/local/novnc \
&& apt-get -y install --no-install-recommends python-numpy \
&& ln -s /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION} /usr/local/novnc/noVNC-${NOVNC_VERSION}/utils/websockify \
&& rm /tmp/websockify-install.zip; \
fi \
#
# [Optional] Install Firefox
&& if [ "${INSTALL_FIREFOX}" = "true" ]; then \
apt-get -y install --no-install-recommends firefox-esr; \
fi \
#
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
COPY bin/init-dev-container.sh /usr/local/share/
COPY bin/set-resolution /usr/local/bin/
COPY fluxbox/* /root/.fluxbox/
COPY fluxbox/* /home/${USERNAME}/.fluxbox/
# Update privs, owners of config files
RUN mkdir -p /var/run/dbus /root/.vnc /home/${USERNAME}/.vnc \
&& touch /root/.Xmodmap /home/${USERNAME}/.Xmodmap \
&& echo "${VNC_PASSWORD}" | tee /root/.vnc/passwd > /home/${USERNAME}/.vnc/passwd \
&& chown -R ${USERNAME}:${USERNAME} /home/${USERNAME}/.Xmodmap /home/${USERNAME}/.fluxbox /home/${USERNAME}/.vnc \
&& chmod +x /usr/local/share/init-dev-container.sh /usr/local/bin/set-resolution
ENTRYPOINT ["/usr/local/share/init-dev-container.sh"]
CMD ["sleep", "infinity"]

View file

@ -1,8 +1,8 @@
# Code - OSS Development Container
This repository includes configuration for a development container for working with Code - OSS in an isolated local container or using [Visual Studio Codespaces](https://aka.ms/vso).
This repository includes configuration for a development container for working with Code - OSS in an isolated local container or using [GitHub Codespaces](https://github.com/features/codespaces).
> **Tip:** The default VNC password is `vscode`. The VNC server runs on port `5901` with a web client at `6080`. For better performance, we recommend using a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/). Applications like the macOS Screen Sharing app will not perform as well. [Chicken](https://sourceforge.net/projects/chicken/) is a good macOS alternative.
> **Tip:** The default VNC password is `vscode`. The VNC server runs on port `5901` with a web client at `6080`. For better performance, we recommend using a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/). Applications like the macOS Screen Sharing app will not perform as well.
## Quick start - local
@ -18,9 +18,9 @@ This repository includes configuration for a development container for working w
> Note that the Remote - Containers extension requires the Visual Studio Code distribution of Code - OSS. See the [FAQ](https://aka.ms/vscode-remote/faq/license) for details.
4. Press <kbd>Ctrl/Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> and select **Remote-Containers: Clone Repository in Container Volume...**.
4. Press <kbd>Ctrl/Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> and select **Remote - Containers: Open Repository in Container...**.
> **Tip:** While you can use your local source tree instead, operations like `yarn install` can be slow on macOS or using the Hyper-V engine on Windows. We recommend the "clone repository in container" approach instead since it uses "named volume" rather than the local filesystem.
> **Tip:** While you can use your local source tree instead, operations like `yarn install` can be slow on macOS or using the Hyper-V engine on Windows. We recommend the "open repository" approach instead since it uses "named volume" rather than the local filesystem.
5. Type `https://github.com/microsoft/vscode` (or a branch or PR URL) in the input box and press <kbd>Enter</kbd>.
@ -30,25 +30,41 @@ Anything you start in VS Code or the integrated terminal will appear here.
Next: **[Try it out!](#try-it)**
## Quick start - Codespaces
## Quick start - GitHub Codespaces
>Note that the Codespaces browser-based editor cannot currently access the desktop environment in this container (due to a [missing feature](https://github.com/MicrosoftDocs/vsonline/issues/117)). We recommend using Visual Studio Code from the desktop to connect instead in the near term.
> **IMPORTANT:** The current user beta for GitHub Codespaces uses a "Basic" sized codespace which is too small to run a full build of VS Code. You'll soon be able to use a "Standard" sized codespace (4-core, 8GB) that will be better suited for this purpose.
1. Install [Visual Studio Code Stable](https://code.visualstudio.com/) or [Insiders](https://code.visualstudio.com/insiders/) and the [Visual Studio Codespaces](https://aka.ms/vscs-ext-vscode) extension.
1. From the [microsoft/vscode GitHub repository](https://github.com/microsoft/vscode), click on the **Code** dropdown, select **Open with Codespaces**, and the **New codespace**
![Image of VS Codespaces extension](https://microsoft.github.io/vscode-remote-release/images/codespaces-extn.png)
> Note that you will not see these options if you are not in the beta yet.
> Note that the Visual Studio Codespaces extension requires the Visual Studio Code distribution of Code - OSS.
2. After the codespace is up and running in your browser, press <kbd>Ctrl/Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> and select **View: Show Remote Explorer**.
2. Sign in by pressing <kbd>Ctrl/Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> and selecting **Codespaces: Sign In**. You may also need to use the **Codespaces: Create Plan** if you do not have a plan. See the [Codespaces docs](https://aka.ms/vso-docs/vscode) for details.
3. You should see port `6080` under **Forwarded Ports**. Select the line and click on the globe icon to open it in a browser tab.
3. Press <kbd>Ctrl/Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd> and select **Codespaces: Create New Codespace**.
> If you do not see port `6080`, press <kbd>Ctrl/Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>, select **Forward a Port** and enter port `6080`.
4. Use default settings (which should include **Standard** 4 core, 8 GB RAM Codespace), select a plan, and then enter the repository URL `https://github.com/microsoft/vscode` (or a branch or PR URL) in the input box when prompted.
4. In the new tab, you should see noVNC. Click **Connect** and enter `vscode` as the password.
5. After the container is running, open a web browser and go to [http://localhost:6080](http://localhost:6080) or use a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) to connect to `localhost:5901` and enter `vscode` as the password.
Anything you start in VS Code or the integrated terminal will appear here.
6. Anything you start in VS Code or the integrated terminal will appear here.
Next: **[Try it out!](#try-it)**
### Using VS Code with GitHub Codespaces
You will likely see better performance when accessing the codespace you created from VS Code since you can use a[VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/). Here's how to do it.
1. [Create a codespace](#quick-start---github-codespaces) if you have not already.
2. Set up [VS Code for use with GitHub Codespaces](https://docs.github.com/github/developing-online-with-codespaces/using-codespaces-in-visual-studio-code)
3. After the VS Code is up and running, press <kbd>Ctrl/Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>, choose **Codespaces: Connect to Codespace**, and select the codespace you created.
4. After you've connected to the codespace, use a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) to connect to `localhost:5901` and enter `vscode` as the password.
5. Anything you start in VS Code or the integrated terminal will appear here.
Next: **[Try it out!](#try-it)**
## Try it!

View file

@ -1,91 +0,0 @@
#!/bin/bash
NONROOT_USER=node
LOG=/tmp/container-init.log
# Execute the command it not already running
startInBackgroundIfNotRunning()
{
log "Starting $1."
echo -e "\n** $(date) **" | sudoIf tee -a /tmp/$1.log > /dev/null
if ! pidof $1 > /dev/null; then
keepRunningInBackground "$@"
while ! pidof $1 > /dev/null; do
sleep 1
done
log "$1 started."
else
echo "$1 is already running." | sudoIf tee -a /tmp/$1.log > /dev/null
log "$1 is already running."
fi
}
# Keep command running in background
keepRunningInBackground()
{
($2 sh -c "while :; do echo [\$(date)] Process started.; $3; echo [\$(date)] Process exited!; sleep 5; done 2>&1" | sudoIf tee -a /tmp/$1.log > /dev/null & echo "$!" | sudoIf tee /tmp/$1.pid > /dev/null)
}
# Use sudo to run as root when required
sudoIf()
{
if [ "$(id -u)" -ne 0 ]; then
sudo "$@"
else
"$@"
fi
}
# Use sudo to run as non-root user if not already running
sudoUserIf()
{
if [ "$(id -u)" -eq 0 ]; then
sudo -u ${NONROOT_USER} "$@"
else
"$@"
fi
}
# Log messages
log()
{
echo -e "[$(date)] $@" | sudoIf tee -a $LOG > /dev/null
}
log "** SCRIPT START **"
# Start dbus.
log 'Running "/etc/init.d/dbus start".'
if [ -f "/var/run/dbus/pid" ] && ! pidof dbus-daemon > /dev/null; then
sudoIf rm -f /var/run/dbus/pid
fi
sudoIf /etc/init.d/dbus start 2>&1 | sudoIf tee -a /tmp/dbus-daemon-system.log > /dev/null
while ! pidof dbus-daemon > /dev/null; do
sleep 1
done
# Set up Xvfb.
startInBackgroundIfNotRunning "Xvfb" sudoIf "Xvfb ${DISPLAY:-:1} +extension RANDR -screen 0 ${MAX_VNC_RESOLUTION:-1920x1080x16}"
# Start fluxbox as a light weight window manager.
startInBackgroundIfNotRunning "fluxbox" sudoUserIf "dbus-launch startfluxbox"
# Start x11vnc
startInBackgroundIfNotRunning "x11vnc" sudoIf "x11vnc -display ${DISPLAY:-:1} -rfbport ${VNC_PORT:-5901} -localhost -no6 -xkb -shared -forever -passwdfile $HOME/.vnc/passwd"
# Set resolution
/usr/local/bin/set-resolution ${VNC_RESOLUTION:-1280x720} ${VNC_DPI:-72}
# Spin up noVNC if installed and not runnning.
if [ -d "/usr/local/novnc" ] && [ "$(ps -ef | grep /usr/local/novnc/noVNC*/utils/launch.sh | grep -v grep)" = "" ]; then
keepRunningInBackground "noVNC" sudoIf "/usr/local/novnc/noVNC*/utils/launch.sh --listen ${NOVNC_PORT:-6080} --vnc localhost:${VNC_PORT:-5901}"
log "noVNC started."
else
log "noVNC is already running or not installed."
fi
# Run whatever was passed in
log "Executing \"$@\"."
"$@"
log "** SCRIPT EXIT **"

View file

@ -1,25 +0,0 @@
#!/bin/bash
RESOLUTION=${1:-${VNC_RESOLUTION:-1920x1080}}
DPI=${2:-${VNC_DPI:-72}}
if [ -z "$1" ]; then
echo -e "**Current Settings **\n"
xrandr
echo -n -e "\nEnter new resolution (WIDTHxHEIGHT, blank for ${RESOLUTION}, Ctrl+C to abort).\n> "
read NEW_RES
if [ "${NEW_RES}" != "" ]; then
RESOLUTION=${NEW_RES}
fi
if [ -z "$2" ]; then
echo -n -e "\nEnter new DPI (blank for ${DPI}, Ctrl+C to abort).\n> "
read NEW_DPI
if [ "${NEW_DPI}" != "" ]; then
DPI=${NEW_DPI}
fi
fi
fi
xrandr --fb ${RESOLUTION} --dpi ${DPI} > /dev/null 2>&1
echo -e "\n**New Settings **\n"
xrandr
echo

View file

@ -1,42 +1,26 @@
{
"name": "Code - OSS",
"build": {
"dockerfile": "Dockerfile",
"args": {
"MAX_VNC_RESOLUTION": "1920x1080x16",
"TARGET_VNC_RESOLUTION": "1280x768",
"TARGET_VNC_PORT": "5901",
"TARGET_NOVNC_PORT": "6080",
"VNC_PASSWORD": "vscode",
"INSTALL_FIREFOX": "true"
}
},
// Image contents: https://github.com/microsoft/vscode-dev-containers/blob/master/repository-containers/images/github.com/microsoft/vscode/.devcontainer/base.Dockerfile
"image": "mcr.microsoft.com/vscode/devcontainers/repos/microsoft/vscode:dev",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/node/workspace/vscode,type=bind,consistency=cached",
"workspaceFolder": "/home/node/workspace/vscode",
"overrideCommand": false,
"runArgs": [
"--init",
// seccomp=unconfined is required for Chrome sandboxing
"--security-opt", "seccomp=unconfined"
],
"runArgs": [ "--init", "--security-opt", "seccomp=unconfined"],
"settings": {
// zsh is also available
"terminal.integrated.shell.linux": "/bin/bash",
"resmon.show.battery": false,
"resmon.show.cpufreq": false,
"remote.extensionKind": {
"ms-vscode.js-debug-nightly": "workspace",
"msjsdiag.debugger-for-chrome": "workspace"
},
"debug.chrome.useV3": true
"resmon.show.cpufreq": false
},
// noVNC, VNC ports
"forwardPorts": [6080, 5901],
// noVNC, VNC ports, debug
"forwardPorts": [6080, 5901, 9222],
"extensions": [
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"msjsdiag.debugger-for-chrome",
"mutantdino.resourcemonitor",
"GitHub.vscode-pull-request-github"
],

View file

@ -1,9 +0,0 @@
[app] (name=code-oss-dev)
[Position] (CENTER) {0 0}
[Maximized] {yes}
[Dimensions] {100% 100%}
[end]
[transient] (role=GtkFileChooserDialog)
[Position] (CENTER) {0 0}
[Dimensions] {70% 70%}
[end]

View file

@ -1,9 +0,0 @@
session.menuFile: ~/.fluxbox/menu
session.keyFile: ~/.fluxbox/keys
session.styleFile: /usr/share/fluxbox/styles//Squared_for_Debian
session.configVersion: 13
session.screen0.workspaces: 1
session.screen0.workspacewarping: false
session.screen0.toolbar.widthPercent: 100
session.screen0.strftimeFormat: %d %b, %a %02k:%M:%S
session.screen0.toolbar.tools: prevworkspace, workspacename, nextworkspace, clock, prevwindow, nextwindow, iconbar, systemtray

View file

@ -1,16 +0,0 @@
[begin] ( Code - OSS Development Container )
[exec] (File Manager) { nautilus ~ } <>
[exec] (Terminal) {/usr/bin/gnome-terminal --working-directory=~ } <>
[exec] (Start Code - OSS) { x-terminal-emulator -T "Code - OSS Build" -e bash /workspaces/vscode*/scripts/code.sh } <>
[submenu] (System >) {}
[exec] (Set Resolution) { x-terminal-emulator -T "Set Resolution" -e bash /usr/local/bin/set-resolution } <>
[exec] (Passwords and Keys) { seahorse } <>
[exec] (Top) { x-terminal-emulator -T "Top" -e /usr/bin/top } <>
[exec] (Editres) {editres} <>
[exec] (Xfontsel) {xfontsel} <>
[exec] (Xkill) {xkill} <>
[exec] (Xrefresh) {xrefresh} <>
[end]
[config] (Configuration >)
[workspaces] (Workspaces >)
[end]

View file

@ -20,8 +20,8 @@
"context-keys": {"assign": []},
"css-less-scss": {"assign": ["aeschli"]},
"custom-editors": {"assign": ["mjbvz"]},
"debug": {"assign": ["isidorn"]},
"debug-console": {"assign": ["isidorn"]},
"debug": {"assign": ["connor4312 "]},
"debug-console": {"assign": ["connor4312 "]},
"dialogs": {"assign": ["sbatten"]},
"diff-editor": {"assign": []},
"dropdown": {"assign": []},

View file

@ -133,6 +133,13 @@
"action": "updateLabels",
"addLabel": "~needs more info"
},
{
"type": "comment",
"name": "jsDebugLogs",
"action": "updateLabels",
"addLabel": "needs more info",
"comment": "Please collect trace logs using the following instructions:\n\n> If you're able to, add `\"trace\": true` to your `launch.json` and reproduce the issue. The location of the log file on your disk will be written to the Debug Console. Share that with us.\n>\n> ⚠️ This log file will not contain source code, but will contain file paths. You can drop it into https://microsoft.github.io/vscode-pwa-analyzer/index.html to see what it contains. If you'd rather not share the log publicly, you can email it to connor@xbox.com"
},
{
"type": "comment",
"name": "closedWith",

View file

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

View file

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

View file

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

View file

@ -13,7 +13,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v35
ref: v36
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: v35
ref: v36
path: ./actions
- name: Install Actions
run: npm install --production --prefix ./actions

View file

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

View file

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

View file

@ -14,7 +14,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v35
ref: v36
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Install Storage Module

View file

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

View file

@ -14,7 +14,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v35
ref: v36
- 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: v35
ref: v36
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: v35
ref: v36
path: ./actions
- name: Install Actions
run: npm install --production --prefix ./actions

View file

@ -13,7 +13,7 @@ jobs:
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v35
ref: v36
path: ./actions
- name: Checkout Repo
if: github.event_name != 'issues'

View file

@ -14,7 +14,7 @@ jobs:
with:
repository: 'microsoft/vscode-github-triage-actions'
path: ./actions
ref: v35
ref: v36
- 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

@ -167,7 +167,12 @@ interface ISchemaAssociation {
* A match succeeds when there is at least one pattern matching and last matching pattern does not start with '!'.
*/
fileMatch: string[];
/*
* The schema for the given URI.
* If no schema is provided, the schema will be fetched with the schema request service (if available).
*/
schema?: JSONSchema;
}
```

View file

@ -1,7 +1,7 @@
{
"name": "vscode-json-languageserver",
"description": "JSON language server",
"version": "1.2.3",
"version": "1.3.0",
"author": "Microsoft Corporation",
"license": "MIT",
"engines": {

View file

@ -68,6 +68,7 @@ export interface ITokenResponse {
refresh_token: string;
scope: string;
token_type: string;
id_token?: string;
}
function parseQuery(uri: vscode.Uri) {
@ -449,7 +450,19 @@ export class AzureActiveDirectoryService {
}
private getTokenFromResponse(json: ITokenResponse, scope: string, existingId?: string): IToken {
const claims = this.getTokenClaims(json.access_token);
let claims = undefined;
try {
claims = this.getTokenClaims(json.access_token);
} catch (e) {
if (json.id_token) {
Logger.info('Failed to fetch token claims from access_token. Attempting to parse id_token instead');
claims = this.getTokenClaims(json.id_token);
} else {
throw e;
}
}
return {
expiresIn: json.expires_in,
expiresAt: json.expires_in ? Date.now() + json.expires_in * 1000 : undefined,

View file

@ -2,4 +2,4 @@
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
This extension provides Syntax Highlighting, Symbol Infomation, Result Highlighting, and Go to Definition capabilities for the Search Results Editor.
This extension provides Syntax Highlighting, Symbol Information, Result Highlighting, and Go to Definition capabilities for the Search Results Editor.

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.50.0",
"distro": "8b294911aabcfe39d612f32d1d2aa3cd6e9732b3",
"distro": "66a02247b2916cb7cf8a3b70677e1d798c6527f2",
"author": {
"name": "Microsoft Corporation"
},
@ -193,4 +193,4 @@
"windows-mutex": "0.3.0",
"windows-process-tree": "0.2.4"
}
}
}

View file

@ -91,7 +91,7 @@
},
{
"name": "ms-vscode.js-debug",
"version": "1.50.1",
"version": "1.50.2",
"repo": "https://github.com/microsoft/vscode-js-debug",
"metadata": {
"id": "25629058-ddac-4e17-abba-74678e126c5d",
@ -106,7 +106,7 @@
},
{
"name": "ms-vscode.vscode-js-profile-table",
"version": "0.0.10",
"version": "0.0.11",
"repo": "https://github.com/microsoft/vscode-js-debug",
"metadata": {
"id": "7e52b41b-71ad-457b-ab7e-0620f1fc4feb",

View file

@ -1229,7 +1229,6 @@ export function asCSSUrl(uri: URI): string {
return `url('${FileAccess.asBrowserUri(uri).toString(true).replace(/'/g, '%27')}')`;
}
export function triggerDownload(dataOrUri: Uint8Array | URI, name: string): void {
// If the data is provided as Buffer, we create a

View file

@ -133,7 +133,7 @@
}
/** Spans in markdown hovers need a margin-bottom to avoid looking cramped: https://github.com/microsoft/vscode/issues/101496 **/
.monaco-hover .markdown-hover .hover-contents span {
.monaco-hover .markdown-hover .hover-contents:not(.code-hover-contents) span {
margin-bottom: 4px;
display: inline-block;
}

View file

@ -97,7 +97,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
private selectionDetailsPane!: HTMLElement;
private _skipLayout: boolean = false;
private _sticky: boolean = true; // for dev purposes only
private _sticky: boolean = false; // for dev purposes only
constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) {

View file

@ -150,7 +150,7 @@ export class UriIterator implements IKeyIterator<URI> {
this._states.push(UriIteratorState.Authority);
}
if (this._value.path) {
//todo@jrieken the case-sensitive logic is copied form `resources.ts#hasToIgnoreCase`
//todo@jrieken #107886 the case-sensitive logic is copied form `resources.ts#hasToIgnoreCase`
// which cannot be used because it depends on this
const caseSensitive = key.scheme === Schemas.file && isLinux;
this._pathIterator = new PathIterator(false, caseSensitive);

View file

@ -135,6 +135,8 @@ class FileAccessImpl {
/**
* Returns a URI to use in contexts where the browser is responsible
* for loading (e.g. fetch()) or when used within the DOM.
*
* **Note:** use `dom.ts#asCSSUrl` whenever the URL is to be used in CSS context.
*/
asBrowserUri(uri: URI): URI;
asBrowserUri(moduleId: string, moduleIdToUrl: { toUrl(moduleId: string): string }): URI;

View file

@ -35,7 +35,6 @@ import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifec
import { IStorageMainService } from 'vs/platform/storage/node/storageMainService';
import { IFileService } from 'vs/platform/files/common/files';
import { FileAccess, Schemas } from 'vs/base/common/network';
import { ColorScheme } from 'vs/platform/theme/common/theme';
export interface IWindowCreationOptions {
state: IWindowState;
@ -784,7 +783,10 @@ export class CodeWindow extends Disposable implements ICodeWindow {
windowConfiguration.fullscreen = this.isFullScreen;
// Set Accessibility Config
windowConfiguration.colorScheme = (nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors) ? ColorScheme.HIGH_CONTRAST : nativeTheme.shouldUseDarkColors ? ColorScheme.DARK : ColorScheme.LIGHT;
windowConfiguration.colorScheme = {
dark: nativeTheme.shouldUseDarkColors,
highContrast: nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors
};
windowConfiguration.autoDetectHighContrast = windowConfig?.autoDetectHighContrast ?? true;
windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled;

View file

@ -328,7 +328,7 @@ export abstract class AbstractContextKeyService implements IContextKeyService {
public abstract getContextValuesContainer(contextId: number): Context;
public abstract createChildContext(parentContextId?: number): number;
public abstract disposeContext(contextId: number): void;
public abstract updateParent(parentContextKeyService: IContextKeyService): void;
public abstract updateParent(parentContextKeyService?: IContextKeyService): void;
}
export class ContextKeyService extends AbstractContextKeyService implements IContextKeyService {
@ -423,6 +423,7 @@ class ScopedContextKeyService extends AbstractContextKeyService {
public dispose(): void {
this._isDisposed = true;
this._parent.disposeContext(this._myContextId);
this._parentChangeListener?.dispose();
if (this._domNode) {
this._domNode.removeAttribute(KEYBINDING_CONTEXT_ATTR);
this._domNode = undefined;
@ -454,7 +455,11 @@ class ScopedContextKeyService extends AbstractContextKeyService {
this._parent.disposeContext(contextId);
}
public updateParent(parentContextKeyService: AbstractContextKeyService): void {
public updateParent(parentContextKeyService?: AbstractContextKeyService): void {
if (!parentContextKeyService) {
this._parentChangeListener?.dispose();
return;
}
const thisContainer = this._parent.getContextValuesContainer(this._myContextId);
const oldAllValues = thisContainer.collectAllValues();
this._parent = parentContextKeyService;

View file

@ -1139,7 +1139,7 @@ export interface IContextKeyService {
createScoped(target?: IContextKeyServiceTarget): IContextKeyService;
getContext(target: IContextKeyServiceTarget | null): IContext;
updateParent(parentContextKeyService: IContextKeyService): void;
updateParent(parentContextKeyService?: IContextKeyService): void;
}
export const SET_CONTEXT_COMMAND_ID = 'setContext';

View file

@ -5,10 +5,9 @@
import { Event } from 'vs/base/common/event';
import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, MouseInputEvent } from 'vs/base/parts/sandbox/common/electronTypes';
import { IOpenedWindow, IWindowOpenable, IOpenEmptyWindowOptions, IOpenWindowOptions } from 'vs/platform/windows/common/windows';
import { IOpenedWindow, IWindowOpenable, IOpenEmptyWindowOptions, IOpenWindowOptions, IColorScheme } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { ColorScheme } from 'vs/platform/theme/common/theme';
import { URI } from 'vs/base/common/uri';
export interface ICPUProperties {
@ -48,7 +47,7 @@ export interface ICommonNativeHostService {
readonly onOSResume: Event<unknown>;
readonly onColorSchemeChange: Event<ColorScheme>;
readonly onColorSchemeChange: Event<IColorScheme>;
// Window
getWindows(): Promise<IOpenedWindow[]>;

View file

@ -8,7 +8,7 @@ import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-m
import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, Menu, BrowserWindow, app, clipboard, powerMonitor, nativeTheme } from 'electron';
import { OpenContext } from 'vs/platform/windows/node/window';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions, IColorScheme } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { isMacintosh, isWindows, isRootUser, isLinux } from 'vs/base/common/platform';
import { ICommonNativeHostService, IOSProperties, IOSStatistics } from 'vs/platform/native/common/native';
@ -22,7 +22,6 @@ import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { MouseInputEvent } from 'vs/base/parts/sandbox/common/electronTypes';
import { arch, totalmem, release, platform, type, loadavg, freemem, cpus } from 'os';
import { ColorScheme } from 'vs/platform/theme/common/theme';
import { virtualMachineHint } from 'vs/base/node/id';
import { ILogService } from 'vs/platform/log/common/log';
import { dirname, join } from 'vs/base/common/path';
@ -52,16 +51,10 @@ export class NativeHostMainService implements INativeHostMainService {
// Color Scheme changes
nativeTheme.on('updated', () => {
let colorScheme: ColorScheme;
if (nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors) {
colorScheme = ColorScheme.HIGH_CONTRAST;
} else if (nativeTheme.shouldUseDarkColors) {
colorScheme = ColorScheme.DARK;
} else {
colorScheme = ColorScheme.LIGHT;
}
this._onColorSchemeChange.fire(colorScheme);
this._onColorSchemeChange.fire({
highContrast: nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors,
dark: nativeTheme.shouldUseDarkColors
});
});
}
@ -87,7 +80,7 @@ export class NativeHostMainService implements INativeHostMainService {
readonly onOSResume = Event.fromNodeEventEmitter(powerMonitor, 'resume');
private readonly _onColorSchemeChange = new Emitter<ColorScheme>();
private readonly _onColorSchemeChange = new Emitter<IColorScheme>();
readonly onColorSchemeChange = this._onColorSchemeChange.event;
//#endregion

View file

@ -107,10 +107,17 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel {
this._socketsDispose.delete(localSocket.localAddress);
remoteSocket.end();
});
localSocket.on('close', () => remoteSocket.end());
localSocket.on('error', () => {
this._socketsDispose.delete(localSocket.localAddress);
remoteSocket.destroy();
});
remoteSocket.on('end', () => localSocket.end());
remoteSocket.on('close', () => localSocket.end());
remoteSocket.on('error', () => {
localSocket.destroy();
});
localSocket.pipe(remoteSocket);
remoteSocket.pipe(localSocket);

View file

@ -11,7 +11,6 @@ import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platf
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { LogLevel } from 'vs/platform/log/common/log';
import { ExportData } from 'vs/base/common/performance';
import { ColorScheme } from 'vs/platform/theme/common/theme';
export const WindowMinimumSize = {
WIDTH: 400,
@ -213,12 +212,17 @@ export interface INativeRunKeybindingInWindowRequest {
userSettingsLabel: string;
}
export interface IColorScheme {
dark: boolean;
highContrast: boolean;
}
export interface IWindowConfiguration {
sessionId: string;
remoteAuthority?: string;
colorScheme: ColorScheme;
colorScheme: IColorScheme;
autoDetectHighContrast?: boolean;
filesToOpenOrCreate?: IPath[];

4
src/vs/vscode.d.ts vendored
View file

@ -6933,7 +6933,7 @@ declare module 'vscode' {
/**
* Fired when the webview content posts a message.
*
* Webview content can post strings or json serilizable objects back to a VS Code extension. They cannot
* Webview content can post strings or json serializable objects back to a VS Code extension. They cannot
* post `Blob`, `File`, `ImageData` and other DOM specific objects since the extension that receives the
* message does not run in a browser environment.
*/
@ -6945,7 +6945,7 @@ declare module 'vscode' {
* Messages are only delivered if the webview is live (either visible or in the
* background with `retainContextWhenHidden`).
*
* @param message Body of the message. This must be a string or other json serilizable object.
* @param message Body of the message. This must be a string or other json serializable object.
*/
postMessage(message: any): Thenable<boolean>;

View file

@ -8,7 +8,7 @@ import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGro
import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, Deprecated_EditorPinnedContext, Deprecated_EditorDirtyContext, EditorResourceAccessor } from 'vs/workbench/common/editor';
import { Event, Emitter, Relay } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom';
import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor, asCSSUrl } from 'vs/base/browser/dom';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
@ -1780,7 +1780,7 @@ registerThemingParticipant((theme, collector, environment) => {
const letterpress = `./media/letterpress${theme.type === 'dark' ? '-dark' : theme.type === 'hc' ? '-hc' : ''}.svg`;
collector.addRule(`
.monaco-workbench .part.editor > .content .editor-group-container.empty .editor-group-letterpress {
background-image: url('${FileAccess.asBrowserUri(letterpress, require).fsPath}')
background-image: ${asCSSUrl(FileAccess.asBrowserUri(letterpress, require))}
}
`);

View file

@ -34,6 +34,7 @@
text-overflow: ellipsis;
overflow: hidden;
font-size: 11px;
min-width: 3ch;
-webkit-margin-before: 0;
-webkit-margin-after: 0;
}
@ -47,6 +48,7 @@
text-overflow: ellipsis;
text-transform: none;
white-space: nowrap;
flex-shrink: 100000;
}
.monaco-pane-view .pane > .pane-header .description .codicon {

View file

@ -209,7 +209,7 @@ export abstract class AbstractTextResourceEditorInput extends EditorInput implem
// Save / Save As
let target: URI | undefined;
if (saveAs) {
target = await this.textFileService.saveAs(this.resource, undefined, options);
target = await this.textFileService.saveAs(this.resource, undefined, { ...options, suggestedTarget: this.preferredResource });
} else {
target = await this.textFileService.save(this.resource, options);
}

View file

@ -196,7 +196,7 @@ export class StartDebugActionViewItem implements IActionViewItem {
}
this.providers.forEach(p => {
if (p.provider && p.provider.type === manager.selectedConfiguration.config?.type) {
if (p.provider && p.provider.type === manager.selectedConfiguration.type) {
this.selected = this.options.length;
}
@ -204,7 +204,7 @@ export class StartDebugActionViewItem implements IActionViewItem {
label: `${p.label}...`, handler: async () => {
const picked = await p.pick();
if (picked) {
await manager.selectConfiguration(picked.launch, picked.config.name, picked.config);
await manager.selectConfiguration(picked.launch, picked.config.name, picked.config, p.provider?.type);
return true;
}
return false;
@ -234,6 +234,7 @@ export class StartDebugActionViewItem implements IActionViewItem {
export class FocusSessionActionViewItem extends SelectActionViewItem {
constructor(
action: IAction,
session: IDebugSession | undefined,
@IDebugService protected readonly debugService: IDebugService,
@IThemeService themeService: IThemeService,
@IContextViewService contextViewService: IContextViewService,
@ -262,15 +263,17 @@ export class FocusSessionActionViewItem extends SelectActionViewItem {
});
this._register(this.debugService.onDidEndSession(() => this.update()));
this.update();
this.update(session);
}
protected getActionContext(_: string, index: number): any {
return this.getSessions()[index];
}
private update() {
const session = this.getSelectedSession();
private update(session?: IDebugSession) {
if (!session) {
session = this.getSelectedSession();
}
const sessions = this.getSessions();
const names = sessions.map(s => {
const label = s.getLabel();

View file

@ -58,6 +58,7 @@ export class ConfigurationManager implements IConfigurationManager {
private selectedName: string | undefined;
private selectedLaunch: ILaunch | undefined;
private selectedConfig: IConfig | undefined;
private selectedType: string | undefined;
private toDispose: IDisposable[];
private readonly _onDidSelectConfigurationName = new Emitter<void>();
private configProviders: IDebugConfigurationProvider[];
@ -493,11 +494,12 @@ export class ConfigurationManager implements IConfigurationManager {
return this.launches.find(l => l.workspace && l.workspace.uri.toString() === workspaceUri.toString());
}
get selectedConfiguration(): { launch: ILaunch | undefined, name: string | undefined, config: IConfig | undefined } {
get selectedConfiguration(): { launch: ILaunch | undefined, name: string | undefined, config: IConfig | undefined, type: string | undefined } {
return {
launch: this.selectedLaunch,
name: this.selectedName,
config: this.selectedConfig
config: this.selectedConfig,
type: this.selectedType
};
}
@ -555,7 +557,8 @@ export class ConfigurationManager implements IConfigurationManager {
}
this.selectedConfig = config;
this.storageService.store(DEBUG_SELECTED_TYPE, this.selectedConfig?.type, StorageScope.WORKSPACE);
this.selectedType = type || this.selectedConfig?.type;
this.storageService.store(DEBUG_SELECTED_TYPE, this.selectedType, StorageScope.WORKSPACE);
const configForType = this.selectedConfig || (this.selectedLaunch && this.selectedName ? this.selectedLaunch.getConfiguration(this.selectedName) : undefined);
if (configForType) {
this.debugConfigurationTypeContext.set(configForType.type);

View file

@ -285,8 +285,6 @@ export class DebugHoverWidget implements IContentWidget {
this.complexValueTitle.textContent = expression.value;
this.complexValueTitle.title = expression.value;
this.layoutTreeAndContainer(true);
this.editor.layoutContentWidget(this);
this.scrollbar.scanDomNode();
this.tree.scrollTop = 0;
this.tree.scrollLeft = 0;
this.complexValueContainer.hidden = false;
@ -302,6 +300,8 @@ export class DebugHoverWidget implements IContentWidget {
const treeHeight = Math.min(this.editor.getLayoutInfo().height * 0.7, this.tree.contentHeight + scrollBarHeight);
this.treeContainer.style.height = `${treeHeight}px`;
this.tree.layout(treeHeight, initialLayout ? 400 : undefined);
this.editor.layoutContentWidget(this);
this.scrollbar.scanDomNode();
}
hide(): void {

View file

@ -75,7 +75,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
orientation: ActionsOrientation.HORIZONTAL,
actionViewItemProvider: (action: IAction) => {
if (action.id === FocusSessionAction.ID) {
return this.instantiationService.createInstance(FocusSessionActionViewItem, action);
return this.instantiationService.createInstance(FocusSessionActionViewItem, action, undefined);
} else if (action instanceof MenuItemAction) {
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
} else if (action instanceof SubmenuItemAction) {

View file

@ -171,7 +171,7 @@ export class DebugViewPaneContainer extends ViewPaneContainer {
return this.startDebugActionViewItem;
}
if (action.id === FocusSessionAction.ID) {
return new FocusSessionActionViewItem(action, this.debugService, this.themeService, this.contextViewService, this.configurationService);
return new FocusSessionActionViewItem(action, undefined, this.debugService, this.themeService, this.contextViewService, this.configurationService);
}
if (action instanceof MenuItemAction) {
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);

View file

@ -459,7 +459,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
getActionViewItem(action: IAction): IActionViewItem | undefined {
if (action.id === SelectReplAction.ID) {
return this.instantiationService.createInstance(SelectReplActionViewItem, this.selectReplAction);
return this.instantiationService.createInstance(SelectReplActionViewItem, this.selectReplAction, this.tree.getInput());
} else if (action.id === FILTER_ACTION_ID) {
this.filterActionViewItem = this.instantiationService.createInstance(ReplFilterActionViewItem, action, localize('workbench.debug.filter.placeholder', "Filter (e.g. text, !exclude)"), this.filterState);
return this.filterActionViewItem;

View file

@ -671,9 +671,11 @@ export interface IConfigurationManager {
launch: ILaunch | undefined;
config: IConfig | undefined;
name: string | undefined;
// Type is used when matching dynamic configurations to their corresponding provider
type: string | undefined;
};
selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig): Promise<void>;
selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig, type?: string): Promise<void>;
getLaunches(): ReadonlyArray<ILaunch>;

View file

@ -327,6 +327,7 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec
try {
this.recommendationSources.push(source);
const recommendationsNotification = new RecommendationsNotification(severity, message, choices, this.notificationService);
Event.once(Event.filter(recommendationsNotification.onDidChangeVisibility, e => !e))(() => this.showNextNotification());
if (this.visibleNotification) {
const index = this.pendingNotificaitons.length;
token.onCancellationRequested(() => this.pendingNotificaitons.splice(index, 1), disposables);
@ -337,7 +338,6 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec
} else {
this.visibleNotification = { recommendationsNotification, source, from: Date.now() };
recommendationsNotification.show();
Event.once(Event.filter(recommendationsNotification.onDidChangeVisibility, e => !e))(() => this.showNextNotification());
}
await raceCancellation(Event.toPromise(recommendationsNotification.onDidClose), token);
return !recommendationsNotification.isCancelled();
@ -355,6 +355,7 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec
.then(() => {
this.unsetVisibileNotification();
if (nextNotificaiton) {
this.visibleNotification = { recommendationsNotification: nextNotificaiton.recommendationsNotification, source: nextNotificaiton.source, from: Date.now() };
nextNotificaiton.recommendationsNotification.show();
}
});

View file

@ -228,8 +228,10 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
const backgroundColor = theme.getColor(listActiveSelectionBackground) || WORKBENCH_BACKGROUND(theme);
const authorForeground = listActiveSelectionForegroundColor.transparent(.9).makeOpaque(backgroundColor);
collector.addRule(`.extensions-list .monaco-list:focus .monaco-list-row:not(.disabled).focused.selected .author { color: ${authorForeground}; }`);
collector.addRule(`.extensions-list .monaco-list:focus .monaco-list-row:not(.disabled).selected .author { color: ${authorForeground}; }`);
const disabledExtensionForeground = listActiveSelectionForegroundColor.transparent(.5).makeOpaque(backgroundColor);
collector.addRule(`.extensions-list .monaco-list:focus .monaco-list-row.disabled.focused.selected { color: ${disabledExtensionForeground}; }`);
collector.addRule(`.extensions-list .monaco-list:focus .monaco-list-row.disabled.selected { color: ${disabledExtensionForeground}; }`);
}
const listInactiveSelectionForegroundColor = theme.getColor(listInactiveSelectionForeground);

View file

@ -836,8 +836,8 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
this.view.setScrollTop(positionOffset - this.view.renderHeight / 2);
// after rendering, it might be pushed down due to markdown cell dynamic height
const elementTop = this.view.elementTop(viewIndex);
this.view.setScrollTop(elementTop - this.view.renderHeight / 2);
const newPositionOffset = this.view.elementTop(viewIndex) + element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
this.view.setScrollTop(newPositionOffset - this.view.renderHeight / 2);
// reveal editor
if (!element.editorAttached) {

View file

@ -1027,7 +1027,9 @@ class TreeMenus extends Disposable implements IDisposable {
createAndFillInContextMenuActions(menu, { shouldForwardArgs: true }, result, this.contextMenuService, g => /^inline/.test(g));
menu.dispose();
// When called without a parameter, updateParent will dispose the parent change listener.
// We cannot call dispose on the contextKeyService because it will break submenus.
contextKeyService.updateParent();
return result;
}
}

View file

@ -58,7 +58,10 @@ export class FileDialogService extends AbstractFileDialogService implements IFil
private shouldUseSimplified(schema: string): { useSimplified: boolean, isSetting: boolean } {
const setting = (this.configurationService.getValue('files.simpleDialog.enable') === true);
const newWindowSetting = (this.configurationService.getValue('window.openFilesInNewWindow') === 'on');
return { useSimplified: (schema !== Schemas.file) || setting, isSetting: newWindowSetting };
return {
useSimplified: ((schema !== Schemas.file) && (schema !== Schemas.userData)) || setting,
isSetting: newWindowSetting
};
}
async pickFileFolderAndOpen(options: IPickAndOpenOptions): Promise<any> {

View file

@ -489,7 +489,7 @@ export class EditorService extends Disposable implements EditorServiceImpl {
//#endregion
//#region preventOpenEditor()
//#region editor overrides
private readonly openEditorHandlers: IOpenEditorOverrideHandler[] = [];

View file

@ -8,14 +8,13 @@ import { joinPath } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { IExtensionHostDebugParams } from 'vs/platform/environment/common/environment';
import { IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IColorScheme, IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IWorkbenchConstructionOptions as IWorkbenchOptions } from 'vs/workbench/workbench.web.api';
import { IProductService } from 'vs/platform/product/common/productService';
import { memoize } from 'vs/base/common/decorators';
import { onUnexpectedError } from 'vs/base/common/errors';
import { parseLineAndColumnAware } from 'vs/base/common/extpath';
import { ColorScheme } from 'vs/platform/theme/common/theme';
class BrowserWorkbenchConfiguration implements IWindowConfiguration {
@ -71,8 +70,8 @@ class BrowserWorkbenchConfiguration implements IWindowConfiguration {
return undefined;
}
get colorScheme() {
return ColorScheme.LIGHT;
get colorScheme(): IColorScheme {
return { dark: false, highContrast: false };
}
}

View file

@ -615,8 +615,13 @@ export class HistoryService extends Disposable implements IHistoryService {
private static readonly MAX_RECENTLY_CLOSED_EDITORS = 20;
private recentlyClosedEditors: IRecentlyClosedEditor[] = [];
private ignoreEditorCloseEvent = false;
private onEditorClosed(event: IEditorCloseEvent): void {
if (this.ignoreEditorCloseEvent) {
return; // blocked
}
const { editor, replaced } = event;
if (replaced) {
return; // ignore if editor was replaced
@ -695,7 +700,17 @@ export class HistoryService extends Disposable implements IHistoryService {
const restoredEditor = this.editorInputFactory.getEditorInputFactory(lastClosedEditor.serialized.typeId)?.deserialize(this.instantiationService, lastClosedEditor.serialized.value);
let editorPane: IEditorPane | undefined = undefined;
if (restoredEditor && !this.editorGroupService.activeGroup.isOpened(restoredEditor)) {
editorPane = await this.editorService.openEditor(restoredEditor, options);
// Fix for https://github.com/microsoft/vscode/issues/107850
// If opening an editor fails, it is possible that we get
// another editor-close event as a result. But we really do
// want to ignore that in our list of recently closed editors
// to prevent endless loops.
this.ignoreEditorCloseEvent = true;
try {
editorPane = await this.editorService.openEditor(restoredEditor, options);
} finally {
this.ignoreEditorCloseEvent = false;
}
}
// If no editor was opened, try with the next one
@ -705,6 +720,8 @@ export class HistoryService extends Disposable implements IHistoryService {
// but make sure to remove this one from the list to prevent
// endless loops.
remove(this.recentlyClosedEditors, lastClosedEditor);
// Try with next one
this.reopenLastClosedEditor();
}
}

View file

@ -5,7 +5,7 @@
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { ITextFileService, ITextFileStreamContent, ITextFileContent, IResourceEncodings, IReadTextFileOptions, IWriteTextFileOptions, toBufferOrReadable, TextFileOperationError, TextFileOperationResult, ITextFileSaveOptions, ITextFileEditorModelManager, IResourceEncoding, stringToSnapshot } from 'vs/workbench/services/textfile/common/textfiles';
import { ITextFileService, ITextFileStreamContent, ITextFileContent, IResourceEncodings, IReadTextFileOptions, IWriteTextFileOptions, toBufferOrReadable, TextFileOperationError, TextFileOperationResult, ITextFileSaveOptions, ITextFileEditorModelManager, IResourceEncoding, stringToSnapshot, ITextFileSaveAsOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { IRevertOptions, IEncodingSupport } from 'vs/workbench/common/editor';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IFileService, FileOperationError, FileOperationResult, IFileStatWithMetadata, ICreateFileOptions, IFileStreamContent } from 'vs/platform/files/common/files';
@ -219,11 +219,11 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return undefined;
}
async saveAs(source: URI, target?: URI, options?: ITextFileSaveOptions): Promise<URI | undefined> {
async saveAs(source: URI, target?: URI, options?: ITextFileSaveAsOptions): Promise<URI | undefined> {
// Get to target resource
if (!target) {
target = await this.fileDialogService.pickFileToSave(await this.suggestSavePath(source), options?.availableFileSystems);
target = await this.fileDialogService.pickFileToSave(await this.suggestSavePath(options?.suggestedTarget ?? source), options?.availableFileSystems);
}
if (!target) {

View file

@ -65,7 +65,7 @@ export interface ITextFileService extends IDisposable {
* @param options optional save options
* @return Path of the saved resource or undefined if canceled.
*/
saveAs(resource: URI, targetResource?: URI, options?: ITextFileSaveOptions): Promise<URI | undefined>;
saveAs(resource: URI, targetResource?: URI, options?: ITextFileSaveAsOptions): Promise<URI | undefined>;
/**
* Reverts the provided resource.
@ -386,6 +386,14 @@ export interface ITextFileSaveOptions extends ISaveOptions {
ignoreErrorHandler?: boolean;
}
export interface ITextFileSaveAsOptions extends ITextFileSaveOptions {
/**
* Optional URI to use as suggested file path to save as.
*/
suggestedTarget?: URI;
}
export interface ITextFileLoadOptions {
/**

View file

@ -8,7 +8,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { Disposable } from 'vs/base/common/lifecycle';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService';
import { ColorScheme } from 'vs/platform/theme/common/theme';
export class BrowserHostColorSchemeService extends Disposable implements IHostColorSchemeService {
@ -38,15 +37,20 @@ export class BrowserHostColorSchemeService extends Disposable implements IHostCo
return this._onDidSchemeChangeEvent.event;
}
get colorScheme(): ColorScheme {
if (window.matchMedia(`(forced-colors: active)`).matches) {
return ColorScheme.HIGH_CONTRAST;
} else if (window.matchMedia(`(prefers-color-scheme: light)`).matches) {
return ColorScheme.LIGHT;
get dark(): boolean {
if (window.matchMedia(`(prefers-color-scheme: light)`).matches) {
return false;
} else if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) {
return ColorScheme.DARK;
return true;
}
return this.environmentService.configuration.colorScheme;
return this.environmentService.configuration.colorScheme.dark;
}
get highContrast(): boolean {
if (window.matchMedia(`(forced-colors: active)`).matches) {
return true;
}
return this.environmentService.configuration.colorScheme.highContrast;
}
}

View file

@ -363,15 +363,11 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
}
private getPreferredColorScheme(): ColorScheme | undefined {
const detectHCThemeSetting = this.configurationService.getValue<boolean>(ThemeSettings.DETECT_HC);
if (this.hostColorService.colorScheme === ColorScheme.HIGH_CONTRAST && detectHCThemeSetting) {
if (this.configurationService.getValue<boolean>(ThemeSettings.DETECT_HC) && this.hostColorService.highContrast) {
return ColorScheme.HIGH_CONTRAST;
}
if (this.configurationService.getValue<boolean>(ThemeSettings.DETECT_COLOR_SCHEME)) {
const osScheme = this.hostColorService.colorScheme;
if (osScheme !== ColorScheme.HIGH_CONTRAST) {
return osScheme;
}
return this.hostColorService.dark ? ColorScheme.DARK : ColorScheme.LIGHT;
}
return undefined;
}
@ -382,7 +378,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
if (themeSettingId) {
const theme = await this.colorThemeRegistry.findThemeBySettingsId(themeSettingId, undefined);
if (theme) {
return this.setColorTheme(theme.id, ConfigurationTarget.USER);
const configurationTarget = this.settings.findAutoConfigurationTarget(settingId);
return this.setColorTheme(theme.id, configurationTarget);
}
}
return null;

View file

@ -5,7 +5,6 @@
import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ColorScheme } from 'vs/platform/theme/common/theme';
export const IHostColorSchemeService = createDecorator<IHostColorSchemeService>('hostColorSchemeService');
@ -13,7 +12,8 @@ export interface IHostColorSchemeService {
readonly _serviceBrand: undefined;
readonly colorScheme: ColorScheme;
readonly dark: boolean;
readonly highContrast: boolean;
readonly onDidChangeColorScheme: Event<void>;
}

View file

@ -298,6 +298,18 @@ export class ThemeConfiguration {
return theme;
}
public findAutoConfigurationTarget(key: string) {
let settings = this.configurationService.inspect(key);
if (!types.isUndefined(settings.workspaceFolderValue)) {
return ConfigurationTarget.WORKSPACE_FOLDER;
} else if (!types.isUndefined(settings.workspaceValue)) {
return ConfigurationTarget.WORKSPACE;
} else if (!types.isUndefined(settings.userRemote)) {
return ConfigurationTarget.USER_REMOTE;
}
return ConfigurationTarget.USER;
}
private async writeConfiguration(key: string, value: any, settingsTarget: ConfigurationTarget | 'auto' | undefined): Promise<void> {
if (settingsTarget === undefined) {
return;
@ -305,15 +317,7 @@ export class ThemeConfiguration {
let settings = this.configurationService.inspect(key);
if (settingsTarget === 'auto') {
if (!types.isUndefined(settings.workspaceFolderValue)) {
settingsTarget = ConfigurationTarget.WORKSPACE_FOLDER;
} else if (!types.isUndefined(settings.workspaceValue)) {
settingsTarget = ConfigurationTarget.WORKSPACE;
} else if (!types.isUndefined(settings.userRemote)) {
settingsTarget = ConfigurationTarget.USER_REMOTE;
} else {
settingsTarget = ConfigurationTarget.USER;
}
settingsTarget = this.findAutoConfigurationTarget(key);
}
if (settingsTarget === ConfigurationTarget.USER) {

View file

@ -8,7 +8,6 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { Disposable } from 'vs/base/common/lifecycle';
import { ColorScheme } from 'vs/platform/theme/common/theme';
import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService';
export class NativeHostColorSchemeService extends Disposable implements IHostColorSchemeService {
@ -27,9 +26,9 @@ export class NativeHostColorSchemeService extends Disposable implements IHostCol
private registerListeners(): void {
// Color Scheme
this._register(this.nativeHostService.onColorSchemeChange(scheme => {
this._colorScheme = scheme;
this._register(this.nativeHostService.onColorSchemeChange(({ highContrast, dark }) => {
this.dark = dark;
this.highContrast = highContrast;
this._onDidChangeColorScheme.fire();
}));
}
@ -37,8 +36,8 @@ export class NativeHostColorSchemeService extends Disposable implements IHostCol
private readonly _onDidChangeColorScheme = this._register(new Emitter<void>());
readonly onDidChangeColorScheme = this._onDidChangeColorScheme.event;
private _colorScheme: ColorScheme = this.environmentService.configuration.colorScheme;
get colorScheme() { return this._colorScheme; }
public dark: boolean = this.environmentService.configuration.colorScheme.dark;
public highContrast: boolean = this.environmentService.configuration.colorScheme.highContrast;
}

View file

@ -40,7 +40,6 @@ import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/ur
import { MouseInputEvent } from 'vs/base/parts/sandbox/common/electronTypes';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IOSProperties, IOSStatistics } from 'vs/platform/native/common/native';
import { ColorScheme } from 'vs/platform/theme/common/theme';
import { homedir } from 'os';
export const TestWorkbenchConfiguration: INativeWorkbenchConfiguration = {
@ -54,7 +53,7 @@ export const TestWorkbenchConfiguration: INativeWorkbenchConfiguration = {
userEnv: {},
execPath: process.execPath,
perfEntries: [],
colorScheme: ColorScheme.DARK,
colorScheme: { dark: true, highContrast: false },
...parseArgs(process.argv, OPTIONS)
};