chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:38:42 +08:00
commit 2d485ba600
8326 changed files with 2641263 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
#!/bin/bash
set -e # Exit on error
set -x # Print commands as they are executed
# Configuration
APP_NAME="void"
APP_VERSION="1.0.0"
ARCH="x86_64"
export ARCH
# Check if void binary exists in current directory
if [ ! -f "./void" ]; then
echo "Error: void binary not found in current directory"
exit 1
fi
# Check if icon exists
if [ ! -f "./void.png" ]; then
echo "Error: void.png icon not found in current directory"
exit 1
fi
# Create temporary directory
TEMP_DIR="$(mktemp -d)"
echo "Created temporary directory: $TEMP_DIR"
APP_DIR="$TEMP_DIR/$APP_NAME.AppDir"
# Create basic AppDir structure
mkdir -pv "$APP_DIR/usr/bin"
mkdir -pv "$APP_DIR/usr/lib"
mkdir -pv "$APP_DIR/usr/share/applications"
mkdir -pv "$APP_DIR/usr/share/icons/hicolor/256x256/apps"
# Exclude create-appimage.sh and appimagetool-x86_64.AppImage from being copied
echo "Copying files excluding create-appimage.sh and appimagetool-x86_64.AppImage..."
cp -v ./void "$APP_DIR/usr/bin/"
# Copy the icon to required locations
cp -v ./void.png "$APP_DIR/void.png"
cp -v ./void.png "$APP_DIR/usr/share/icons/hicolor/256x256/apps/void.png"
# Copy dependencies with error checking
echo "Copying dependencies..."
for lib in $(ldd ./void | grep "=> /" | awk '{print $3}'); do
if [ -f "$lib" ]; then
cp -v "$lib" "$APP_DIR/usr/lib/" || echo "Failed to copy $lib"
else
echo "Warning: Library $lib not found"
fi
done
# Create desktop file with error checking
echo "Creating desktop file..."
if ! cat > "$APP_DIR/$APP_NAME.desktop" <<EOF
[Desktop Entry]
Name=$APP_NAME
Exec=void
Icon=void
Type=Application
Categories=Utility;
Comment=Void Linux Application
EOF
then
echo "Error creating desktop file"
exit 1
fi
# Make desktop file executable
chmod +x "$APP_DIR/$APP_NAME.desktop"
# Copy the desktop file to the applications directory
cp -v "$APP_DIR/$APP_NAME.desktop" "$APP_DIR/usr/share/applications/"
# Create AppRun with error checking
echo "Creating AppRun..."
if ! cat > "$APP_DIR/AppRun" <<EOF
#!/bin/bash
cd "\$(dirname "\$0")/usr/bin"
export LD_LIBRARY_PATH="\$APPDIR/usr/lib:\$LD_LIBRARY_PATH"
exec ./void "\$@"
EOF
then
echo "Error creating AppRun"
exit 1
fi
# Make AppRun executable
chmod +x "$APP_DIR/AppRun"
# Download appimagetool if not present in the current directory
if [ ! -f "./appimagetool-x86_64.AppImage" ]; then
echo "Downloading appimagetool-x86_64.AppImage..."
wget "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x appimagetool-x86_64.AppImage
else
echo "appimagetool-x86_64.AppImage is already present."
fi
# Create the AppImage
echo "Creating AppImage..."
ARCH=x86_64 ./appimagetool-x86_64.AppImage "$APP_DIR" "${APP_NAME}-${APP_VERSION}-${ARCH}.AppImage"
# Cleanup
echo "Cleaning up..."
rm -rf "$TEMP_DIR"
echo "AppImage creation complete!"
+168
View File
@@ -0,0 +1,168 @@
#!/bin/bash
# Exit on error
set -e
# Check platform
platform=$(uname)
if [[ "$platform" == "Darwin" ]]; then
echo "Running on macOS. Note that the AppImage created will only work on Linux systems."
if ! command -v docker &> /dev/null; then
echo "Docker Desktop for Mac is not installed. Please install it from https://www.docker.com/products/docker-desktop"
exit 1
fi
elif [[ "$platform" == "Linux" ]]; then
echo "Running on Linux. Proceeding with AppImage creation..."
else
echo "This script is intended to run on macOS or Linux. Current platform: $platform"
exit 1
fi
# Enable BuildKit
export DOCKER_BUILDKIT=1
BUILD_IMAGE_NAME="void-appimage-builder"
# Check if Docker is running
if ! docker info >/dev/null 2>&1; then
echo "Docker is not running. Please start Docker first."
exit 1
fi
# Check and install Buildx if needed
if ! docker buildx version >/dev/null 2>&1; then
echo "Installing Docker Buildx..."
mkdir -p ~/.docker/cli-plugins/
curl -SL https://github.com/docker/buildx/releases/download/v0.13.1/buildx-v0.13.1.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
chmod +x ~/.docker/cli-plugins/docker-buildx
fi
# Download appimagetool if not present
if [ ! -f "appimagetool" ]; then
echo "Downloading appimagetool..."
wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x appimagetool
fi
# Delete any existing AppImage to avoid bloating the build
rm -f Void-x86_64.AppImage
# Create build Dockerfile
echo "Creating build Dockerfile..."
cat > Dockerfile.build << 'EOF'
# syntax=docker/dockerfile:1
FROM ubuntu:20.04
# Install required dependencies
RUN apt-get update && apt-get install -y \
libfuse2 \
libglib2.0-0 \
libgtk-3-0 \
libx11-xcb1 \
libxss1 \
libxtst6 \
libnss3 \
libasound2 \
libdrm2 \
libgbm1 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
EOF
# Create .dockerignore file
echo "Creating .dockerignore file..."
cat > .dockerignore << EOF
Dockerfile.build
.dockerignore
.git
.gitignore
.DS_Store
*~
*.swp
*.swo
*.tmp
*.bak
*.log
*.err
node_modules/
venv/
*.egg-info/
*.tox/
dist/
EOF
# Build Docker image without cache
echo "Building Docker image (no cache)..."
docker build --no-cache -t "$BUILD_IMAGE_NAME" -f Dockerfile.build .
# Create AppImage using local appimagetool
echo "Creating AppImage..."
docker run --rm --privileged -v "$(pwd):/app" "$BUILD_IMAGE_NAME" bash -c '
cd /app && \
rm -rf VoidApp.AppDir && \
mkdir -p VoidApp.AppDir/usr/bin VoidApp.AppDir/usr/lib VoidApp.AppDir/usr/share/applications && \
find . -maxdepth 1 ! -name VoidApp.AppDir ! -name "." ! -name ".." -exec cp -r {} VoidApp.AppDir/usr/bin/ \; && \
cp void.png VoidApp.AppDir/ && \
echo "[Desktop Entry]" > VoidApp.AppDir/void.desktop && \
echo "Name=Void" >> VoidApp.AppDir/void.desktop && \
echo "Comment=Open source AI code editor." >> VoidApp.AppDir/void.desktop && \
echo "GenericName=Text Editor" >> VoidApp.AppDir/void.desktop && \
echo "Exec=void %F" >> VoidApp.AppDir/void.desktop && \
echo "Icon=void" >> VoidApp.AppDir/void.desktop && \
echo "Type=Application" >> VoidApp.AppDir/void.desktop && \
echo "StartupNotify=false" >> VoidApp.AppDir/void.desktop && \
echo "StartupWMClass=Void" >> VoidApp.AppDir/void.desktop && \
echo "Categories=TextEditor;Development;IDE;" >> VoidApp.AppDir/void.desktop && \
echo "MimeType=application/x-void-workspace;" >> VoidApp.AppDir/void.desktop && \
echo "Keywords=void;" >> VoidApp.AppDir/void.desktop && \
echo "Actions=new-empty-window;" >> VoidApp.AppDir/void.desktop && \
echo "[Desktop Action new-empty-window]" >> VoidApp.AppDir/void.desktop && \
echo "Name=New Empty Window" >> VoidApp.AppDir/void.desktop && \
echo "Name[de]=Neues leeres Fenster" >> VoidApp.AppDir/void.desktop && \
echo "Name[es]=Nueva ventana vacía" >> VoidApp.AppDir/void.desktop && \
echo "Name[fr]=Nouvelle fenêtre vide" >> VoidApp.AppDir/void.desktop && \
echo "Name[it]=Nuova finestra vuota" >> VoidApp.AppDir/void.desktop && \
echo "Name[ja]=新しい空のウィンドウ" >> VoidApp.AppDir/void.desktop && \
echo "Name[ko]=새 빈 창" >> VoidApp.AppDir/void.desktop && \
echo "Name[ru]=Новое пустое окно" >> VoidApp.AppDir/void.desktop && \
echo "Name[zh_CN]=新建空窗口" >> VoidApp.AppDir/void.desktop && \
echo "Name[zh_TW]=開新空視窗" >> VoidApp.AppDir/void.desktop && \
echo "Exec=void --new-window %F" >> VoidApp.AppDir/void.desktop && \
echo "Icon=void" >> VoidApp.AppDir/void.desktop && \
chmod +x VoidApp.AppDir/void.desktop && \
cp VoidApp.AppDir/void.desktop VoidApp.AppDir/usr/share/applications/ && \
echo "[Desktop Entry]" > VoidApp.AppDir/void-url-handler.desktop && \
echo "Name=Void - URL Handler" > VoidApp.AppDir/void-url-handler.desktop && \
echo "Comment=Open source AI code editor." > VoidApp.AppDir/void-url-handler.desktop && \
echo "GenericName=Text Editor" > VoidApp.AppDir/void-url-handler.desktop && \
echo "Exec=void --open-url %U" > VoidApp.AppDir/void-url-handler.desktop && \
echo "Icon=void" > VoidApp.AppDir/void-url-handler.desktop && \
echo "Type=Application" > VoidApp.AppDir/void-url-handler.desktop && \
echo "NoDisplay=true" > VoidApp.AppDir/void-url-handler.desktop && \
echo "StartupNotify=true" > VoidApp.AppDir/void-url-handler.desktop && \
echo "Categories=Utility;TextEditor;Development;IDE;" > VoidApp.AppDir/void-url-handler.desktop && \
echo "MimeType=x-scheme-handler/void;" > VoidApp.AppDir/void-url-handler.desktop && \
echo "Keywords=void;" > VoidApp.AppDir/void-url-handler.desktop && \
chmod +x VoidApp.AppDir/void-url-handler.desktop && \
cp VoidApp.AppDir/void-url-handler.desktop VoidApp.AppDir/usr/share/applications/ && \
echo "#!/bin/bash" > VoidApp.AppDir/AppRun && \
echo "HERE=\$(dirname \"\$(readlink -f \"\${0}\")\")" >> VoidApp.AppDir/AppRun && \
echo "export PATH=\${HERE}/usr/bin:\${PATH}" >> VoidApp.AppDir/AppRun && \
echo "export LD_LIBRARY_PATH=\${HERE}/usr/lib:\${LD_LIBRARY_PATH}" >> VoidApp.AppDir/AppRun && \
echo "exec \${HERE}/usr/bin/void --no-sandbox \"\$@\"" >> VoidApp.AppDir/AppRun && \
chmod +x VoidApp.AppDir/AppRun && \
chmod -R 755 VoidApp.AppDir && \
# Strip unneeded symbols from the binary to reduce size
strip --strip-unneeded VoidApp.AppDir/usr/bin/void
ls -la VoidApp.AppDir/ && \
ARCH=x86_64 ./appimagetool -n VoidApp.AppDir Void-x86_64.AppImage
'
# Clean up
rm -rf VoidApp.AppDir .dockerignore appimagetool
echo "AppImage creation complete! Your AppImage is: Void-x86_64.AppImage"
+127
View File
@@ -0,0 +1,127 @@
# README
This is a community-made AppImage creation script.
There are some reported bugs with it.
To generate an AppImage yourself, feel free to look at
stable-linux.yml in the separate `void-builder/` repo,
which runs a GitHub Action that builds the AppImage you see on our website.
# Void AppImage Creation Script
This script automates the process of creating an AppImage for the Void Editor using Docker. It works on macOS and Linux platforms.
## Requirements
* **Docker:** The script relies on Docker to build the AppImage inside a container.
* **macOS or Linux:** The script is designed for these platforms. On macOS, it generates a Linux-compatible AppImage.
* **Internet Connection:** Required for downloading necessary tools (like `docker-buildx` and `appimagetool` inside the Docker container).
## Prerequisites
1. **Install Docker:**
* **macOS:** Download and install Docker Desktop from [docker.com](docker.com).
* **Ubuntu:**
```bash
sudo apt install docker.io
```
* **Arch Linux:**
```bash
sudo pacman -S docker
```
* **Fedora:**
```bash
sudo dnf install docker
```
2. **Set Docker User Group:**
Docker requires users to be part of the `docker` group to run Docker commands without `sudo`.
```bash
sudo usermod -aG docker $USER
```
After running this command, log out and log back in for the group changes to take effect.
3. **Enable and Start Docker:**
```bash
sudo systemctl enable docker
sudo systemctl start docker
```
## Ubuntu Dependencies (Installed via Docker)
These dependencies are installed within the Docker container (Ubuntu 20.04 base). You generally don't need to install them manually:
* `libfuse2`
* `libglib2.0-0`
* `libgtk-3-0`
* `libx11-xcb1`
* `libxss1`
* `libxtst6`
* `libnss3`
* `libasound2`
* `libdrm2`
* `libgbm1`
## Usage Instructions
1. **Clone or Download the Script:**
Save the script to your system as `create_appimage.sh`.
2. **Make the Script Executable:**
```bash
chmod +x create_appimage.sh
```
3. **Copy Required Files:**
Copy the following files to the directory where the app binary is being bundled (created during the build process):
* `create_appimage.sh`
* `void.desktop`
* `void.png`
4. **Run the Script:**
```bash
./create_appimage.sh
```
5. **Result:**
After the script completes, it will generate an AppImage named `Void-x86_64.AppImage` (or similar, depending on your architecture) in the current directory.
## Script Overview
* **Platform Check:** Checks for macOS or Linux. Exits if unsupported.
* **Docker Checks:** Ensures Docker is installed and running.
* **Buildx Installation:** Installs `docker buildx` if missing.
* **`appimagetool` Download:** Downloads `appimagetool` inside the Docker container.
* **Dockerfile Creation:** Creates a temporary `Dockerfile.build` for the Ubuntu-based environment.
* **Docker Image Build:** Builds a Docker image and runs the build process.
* **AppImage Creation:**
* Creates the `VoidApp.AppDir` structure.
* Copies binaries, resources, and the `.desktop` entry.
* Copies `void.desktop` and `void.png`.
* Strips unnecessary symbols from the binary.
* Runs `appimagetool` to generate the AppImage.
* **Cleanup:** Removes the temporary `Dockerfile.build`.
## Troubleshooting
* **Docker Not Running:** Ensure Docker is installed and running.
* **Permission Issues:** Try running the script with `sudo` or check Docker permissions.
* **Outdated Dependencies:** Ensure you have the minimum required versions.
## License
This script is provided "as is". It is free to use, modify, and distribute, but comes with no warranty.
+12
View File
@@ -0,0 +1,12 @@
[Desktop Entry]
Name=Void - URL Handler
Comment=Open source AI code editor.
GenericName=Text Editor
Exec=void --open-url %U
Icon=void
Type=Application
NoDisplay=true
StartupNotify=true
Categories=Utility;TextEditor;Development;IDE;
MimeType=x-scheme-handler/void;
Keywords=void;
+27
View File
@@ -0,0 +1,27 @@
[Desktop Entry]
Name=Void
Comment=Open source AI code editor.
GenericName=Text Editor
Exec=void %F
Icon=void
Type=Application
StartupNotify=false
StartupWMClass=Void
Categories=TextEditor;Development;IDE;
MimeType=application/x-void-workspace;
Keywords=void;
Actions=new-empty-window;
[Desktop Action new-empty-window]
Name=New Empty Window
Name[de]=Neues leeres Fenster
Name[es]=Nueva ventana vacía
Name[fr]=Nouvelle fenêtre vide
Name[it]=Nuova finestra vuota
Name[ja]=新しい空のウィンドウ
Name[ko]=새 빈 창
Name[ru]=Новое пустое окно
Name[zh_CN]=新建空窗口
Name[zh_TW]=開新空視窗
Exec=void --new-window %F
Icon=void
Binary file not shown.

After

Width:  |  Height:  |  Size: 795 KiB

+37
View File
@@ -0,0 +1,37 @@
@echo off
setlocal
title VSCode Dev
pushd %~dp0..
:: Get electron, compile, built-in extensions
if "%VSCODE_SKIP_PRELAUNCH%"=="" node build/lib/preLaunch.js
for /f "tokens=2 delims=:," %%a in ('findstr /R /C:"\"nameShort\":.*" product.json') do set NAMESHORT=%%~a
set NAMESHORT=%NAMESHORT: "=%
set NAMESHORT=%NAMESHORT:"=%.exe
set CODE=".build\electron\%NAMESHORT%"
:: Manage built-in extensions
if "%~1"=="--builtin" goto builtin
:: Configuration
set ELECTRON_RUN_AS_NODE=1
set NODE_ENV=development
set VSCODE_DEV=1
set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1
:: Launch Code
%CODE% --inspect=5874 out\cli.js %~dp0.. %*
goto end
:builtin
%CODE% build/builtin
:end
popd
endlocal
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
fi
function code() {
cd $ROOT
if [[ "$OSTYPE" == "darwin"* ]]; then
NAME=`node -p "require('./product.json').nameLong"`
CODE="./.build/electron/$NAME.app/Contents/MacOS/Electron"
else
NAME=`node -p "require('./product.json').applicationName"`
CODE=".build/electron/$NAME"
fi
# Get electron, compile, built-in extensions
if [[ -z "${VSCODE_SKIP_PRELAUNCH}" ]]; then
node build/lib/preLaunch.js
fi
# Manage built-in extensions
if [[ "$1" == "--builtin" ]]; then
exec "$CODE" build/builtin
return
fi
ELECTRON_RUN_AS_NODE=1 \
NODE_ENV=development \
VSCODE_DEV=1 \
ELECTRON_ENABLE_LOGGING=1 \
ELECTRON_ENABLE_STACK_DUMPING=1 \
"$CODE" --inspect=5874 "$ROOT/out/cli.js" . "$@"
}
code "$@"
+91
View File
@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
const path = require('path');
const perf = require('@vscode/vscode-perf');
const VSCODE_FOLDER = path.join(__dirname, '..');
async function main() {
const args = process.argv;
/** @type {string | undefined} */
let build = undefined;
if (args.indexOf('--help') === -1 && args.indexOf('-h') === -1) {
// get build arg from args
let buildArgIndex = args.indexOf('--build');
buildArgIndex = buildArgIndex === -1 ? args.indexOf('-b') : buildArgIndex;
if (buildArgIndex === -1) {
let runtimeArgIndex = args.indexOf('--runtime');
runtimeArgIndex = runtimeArgIndex === -1 ? args.indexOf('-r') : runtimeArgIndex;
if (runtimeArgIndex !== -1 && args[runtimeArgIndex + 1] !== 'desktop') {
console.error('Please provide the --build argument. It is an executable file for desktop or a URL for web');
process.exit(1);
}
build = getLocalCLIPath();
} else {
build = args[buildArgIndex + 1];
if (build !== 'insider' && build !== 'stable' && build !== 'exploration') {
build = getExePath(args[buildArgIndex + 1]);
}
args.splice(buildArgIndex + 1, 1);
}
args.push('--folder');
args.push(VSCODE_FOLDER);
args.push('--file');
args.push(path.join(VSCODE_FOLDER, 'package.json'));
}
if (build) {
args.push('--build');
args.push(build);
}
await perf.run();
process.exit(0);
}
/**
* @param {string} buildPath
* @returns {string}
*/
function getExePath(buildPath) {
buildPath = path.normalize(path.resolve(buildPath));
if (buildPath === path.normalize(getLocalCLIPath())) {
return buildPath;
}
let relativeExePath;
switch (process.platform) {
case 'darwin':
relativeExePath = path.join('Contents', 'MacOS', 'Electron');
break;
case 'linux': {
const product = require(path.join(buildPath, 'resources', 'app', 'product.json'));
relativeExePath = product.applicationName;
break;
}
case 'win32': {
const product = require(path.join(buildPath, 'resources', 'app', 'product.json'));
relativeExePath = `${product.nameShort}.exe`;
break;
}
default:
throw new Error('Unsupported platform.');
}
return buildPath.endsWith(relativeExePath) ? buildPath : path.join(buildPath, relativeExePath);
}
/**
* @returns {string}
*/
function getLocalCLIPath() {
return process.platform === 'win32' ? path.join(VSCODE_FOLDER, 'scripts', 'code.bat') : path.join(VSCODE_FOLDER, 'scripts', 'code.sh');
}
main();
+31
View File
@@ -0,0 +1,31 @@
@echo off
setlocal
title VSCode Server
set ROOT_DIR=%~dp0..
pushd %ROOT_DIR%
:: Configuration
set NODE_ENV=development
set VSCODE_DEV=1
:: Get electron, compile, built-in extensions
if "%VSCODE_SKIP_PRELAUNCH%"=="" node build/lib/preLaunch.js
:: Node executable
FOR /F "tokens=*" %%g IN ('node build/lib/node.js') do (SET NODE=%%g)
if not exist "%NODE%" (
:: Download nodejs executable for remote
call npm run gulp node
)
popd
:: Launch Server
call "%NODE%" %ROOT_DIR%\scripts\code-server.js %*
endlocal
+71
View File
@@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
const cp = require('child_process');
const path = require('path');
const open = require('open');
const minimist = require('minimist');
async function main() {
const args = minimist(process.argv.slice(2), {
boolean: [
'help',
'launch'
]
});
if (args.help) {
console.log(
'./scripts/code-server.sh|bat [options]\n' +
' --launch Opens a browser'
);
startServer(['--help']);
return;
}
process.env['VSCODE_SERVER_PORT'] = '9888';
const serverArgs = process.argv.slice(2).filter(v => v !== '--launch');
const addr = await startServer(serverArgs);
if (args['launch']) {
open(addr);
}
}
function startServer(programArgs) {
return new Promise((s, e) => {
const env = { ...process.env };
const entryPoint = path.join(__dirname, '..', 'out', 'server-main.js');
console.log(`Starting server: ${entryPoint} ${programArgs.join(' ')}`);
const proc = cp.spawn(process.execPath, [entryPoint, ...programArgs], { env, stdio: [process.stdin, null, process.stderr] });
proc.stdout.on('data', e => {
const data = e.toString();
process.stdout.write(data);
const m = data.match(/Web UI available at (.*)/);
if (m) {
s(m[1]);
}
});
proc.on('exit', (code) => process.exit(code));
process.on('exit', () => proc.kill());
process.on('SIGINT', () => {
proc.kill();
process.exit(128 + 2); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events
});
process.on('SIGTERM', () => {
proc.kill();
process.exit(128 + 15); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events
});
});
}
main();
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
fi
function code() {
pushd $ROOT
# Get electron, compile, built-in extensions
if [[ -z "${VSCODE_SKIP_PRELAUNCH}" ]]; then
node build/lib/preLaunch.js
fi
NODE=$(node build/lib/node.js)
if [ ! -e $NODE ];then
# Load remote node
npm run gulp node
fi
popd
NODE_ENV=development \
VSCODE_DEV=1 \
$NODE $ROOT/scripts/code-server.js "$@"
}
code "$@"
+24
View File
@@ -0,0 +1,24 @@
@echo off
setlocal
title VSCode Web Serverless
pushd %~dp0\..
:: Sync built-in extensions
call npm run download-builtin-extensions
:: Node executable
FOR /F "tokens=*" %%g IN ('node build/lib/node.js') do (SET NODE=%%g)
if not exist "%NODE%" (
:: Download nodejs executable for remote
call npm run gulp node
)
:: Launch Server
call "%NODE%" scripts\code-web.js %*
popd
endlocal
+167
View File
@@ -0,0 +1,167 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
const testWebLocation = require.resolve('@vscode/test-web');
const fs = require('fs');
const path = require('path');
const cp = require('child_process');
const minimist = require('minimist');
const fancyLog = require('fancy-log');
const ansiColors = require('ansi-colors');
const open = require('open');
const https = require('https');
const APP_ROOT = path.join(__dirname, '..');
const WEB_DEV_EXTENSIONS_ROOT = path.join(APP_ROOT, '.build', 'builtInWebDevExtensions');
const WEB_PLAYGROUND_VERSION = '0.0.13';
async function main() {
const args = minimist(process.argv.slice(2), {
boolean: [
'help',
'playground'
],
string: [
'host',
'port',
'extensionPath',
'browser',
'browserType'
],
});
if (args.help) {
console.log(
'./scripts/code-web.sh|bat[, folderMountPath[, options]]\n' +
' Start with an empty workspace and no folder opened in explorer\n' +
' folderMountPath Open local folder (eg: use `.` to open current directory)\n' +
' --playground Include the vscode-web-playground extension\n'
);
startServer(['--help']);
return;
}
const serverArgs = [];
const HOST = args['host'] ?? 'localhost';
const PORT = args['port'] ?? '8080';
if (args['host'] === undefined) {
serverArgs.push('--host', HOST);
}
if (args['port'] === undefined) {
serverArgs.push('--port', PORT);
}
// only use `./scripts/code-web.sh --playground` to add vscode-web-playground extension by default.
if (args['playground'] === true) {
serverArgs.push('--extensionPath', WEB_DEV_EXTENSIONS_ROOT);
serverArgs.push('--folder-uri', 'memfs:///sample-folder');
await ensureWebDevExtensions(args['verbose']);
}
let openSystemBrowser = false;
if (!args['browser'] && !args['browserType']) {
serverArgs.push('--browserType', 'none');
openSystemBrowser = true;
}
serverArgs.push('--sourcesPath', APP_ROOT);
serverArgs.push(...process.argv.slice(2).filter(v => !v.startsWith('--playground') && v !== '--no-playground'));
startServer(serverArgs);
if (openSystemBrowser) {
open(`http://${HOST}:${PORT}/`);
}
}
function startServer(runnerArguments) {
const env = { ...process.env };
console.log(`Starting @vscode/test-web: ${testWebLocation} ${runnerArguments.join(' ')}`);
const proc = cp.spawn(process.execPath, [testWebLocation, ...runnerArguments], { env, stdio: 'inherit' });
proc.on('exit', (code) => process.exit(code));
process.on('exit', () => proc.kill());
process.on('SIGINT', () => {
proc.kill();
process.exit(128 + 2); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events
});
process.on('SIGTERM', () => {
proc.kill();
process.exit(128 + 15); // https://nodejs.org/docs/v14.16.0/api/process.html#process_signal_events
});
}
async function directoryExists(path) {
try {
return (await fs.promises.stat(path)).isDirectory();
} catch {
return false;
}
}
/** @return {Promise<void>} */
async function downloadPlaygroundFile(fileName, httpsLocation, destinationRoot) {
const destination = path.join(destinationRoot, fileName);
await fs.promises.mkdir(path.dirname(destination), { recursive: true });
const fileStream = fs.createWriteStream(destination);
return (new Promise((resolve, reject) => {
const request = https.get(path.posix.join(httpsLocation, fileName), response => {
response.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close();
resolve();
});
});
request.on('error', reject);
}));
}
async function ensureWebDevExtensions(verbose) {
// Playground (https://github.com/microsoft/vscode-web-playground)
const webDevPlaygroundRoot = path.join(WEB_DEV_EXTENSIONS_ROOT, 'vscode-web-playground');
const webDevPlaygroundExists = await directoryExists(webDevPlaygroundRoot);
let downloadPlayground = false;
if (webDevPlaygroundExists) {
try {
const webDevPlaygroundPackageJson = JSON.parse(((await fs.promises.readFile(path.join(webDevPlaygroundRoot, 'package.json'))).toString()));
if (webDevPlaygroundPackageJson.version !== WEB_PLAYGROUND_VERSION) {
downloadPlayground = true;
}
} catch (error) {
downloadPlayground = true;
}
} else {
downloadPlayground = true;
}
if (downloadPlayground) {
if (verbose) {
fancyLog(`${ansiColors.magenta('Web Development extensions')}: Downloading vscode-web-playground to ${webDevPlaygroundRoot}`);
}
const playgroundRepo = `https://raw.githubusercontent.com/microsoft/vscode-web-playground/main/`;
await Promise.all(['package.json', 'dist/extension.js', 'dist/extension.js.map'].map(
fileName => downloadPlaygroundFile(fileName, playgroundRepo, webDevPlaygroundRoot)
));
} else {
if (verbose) {
fancyLog(`${ansiColors.magenta('Web Development extensions')}: Using existing vscode-web-playground in ${webDevPlaygroundRoot}`);
}
}
}
main();
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
fi
function code() {
cd $ROOT
# Sync built-in extensions
npm run download-builtin-extensions
NODE=$(node build/lib/node.js)
if [ ! -e $NODE ];then
# Load remote node
npm run gulp node
fi
NODE=$(node build/lib/node.js)
$NODE ./scripts/code-web.js "$@"
}
code "$@"
+45
View File
@@ -0,0 +1,45 @@
@echo off
setlocal
title VSCode Dev
pushd %~dp0\..
:: Get electron, compile, built-in extensions
if "%VSCODE_SKIP_PRELAUNCH%"=="" node build/lib/preLaunch.js
for /f "tokens=2 delims=:," %%a in ('findstr /R /C:"\"nameShort\":.*" product.json') do set NAMESHORT=%%~a
set NAMESHORT=%NAMESHORT: "=%
set NAMESHORT=%NAMESHORT:"=%.exe
set CODE=".build\electron\%NAMESHORT%"
:: Manage built-in extensions
if "%~1"=="--builtin" goto builtin
:: Configuration
set NODE_ENV=development
set VSCODE_DEV=1
set VSCODE_CLI=1
set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1
set DISABLE_TEST_EXTENSION="--disable-extension=vscode.vscode-api-tests"
for %%A in (%*) do (
if "%%~A"=="--extensionTestsPath" (
set DISABLE_TEST_EXTENSION=""
)
)
:: Launch Code
%CODE% . %DISABLE_TEST_EXTENSION% %*
goto end
:builtin
%CODE% build/builtin
:end
popd
endlocal
+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname "$(dirname "$(realpath "$0")")")
else
ROOT=$(dirname "$(dirname "$(readlink -f $0)")")
# If the script is running in Docker using the WSL2 engine, powershell.exe won't exist
if grep -qi Microsoft /proc/version && type powershell.exe > /dev/null 2>&1; then
IN_WSL=true
fi
fi
function code() {
cd "$ROOT"
if [[ "$OSTYPE" == "darwin"* ]]; then
NAME=`node -p "require('./product.json').nameLong"`
CODE="./.build/electron/$NAME.app/Contents/MacOS/Electron"
else
NAME=`node -p "require('./product.json').applicationName"`
CODE=".build/electron/$NAME"
fi
# Get electron, compile, built-in extensions
if [[ -z "${VSCODE_SKIP_PRELAUNCH}" ]]; then
node build/lib/preLaunch.js
fi
# Manage built-in extensions
if [[ "$1" == "--builtin" ]]; then
exec "$CODE" build/builtin
return
fi
# Configuration
export NODE_ENV=development
export VSCODE_DEV=1
export VSCODE_CLI=1
export ELECTRON_ENABLE_STACK_DUMPING=1
export ELECTRON_ENABLE_LOGGING=1
DISABLE_TEST_EXTENSION="--disable-extension=vscode.vscode-api-tests"
if [[ "$@" == *"--extensionTestsPath"* ]]; then
DISABLE_TEST_EXTENSION=""
fi
# Launch Code
exec "$CODE" . $DISABLE_TEST_EXTENSION "$@"
}
function code-wsl()
{
HOST_IP=$(echo "" | powershell.exe -noprofile -Command "& {(Get-NetIPAddress | Where-Object {\$_.InterfaceAlias -like '*WSL*' -and \$_.AddressFamily -eq 'IPv4'}).IPAddress | Write-Host -NoNewline}")
export DISPLAY="$HOST_IP:0"
# in a wsl shell
ELECTRON="$ROOT/.build/electron/Code - OSS.exe"
if [ -f "$ELECTRON" ]; then
local CWD=$(pwd)
cd $ROOT
export WSLENV=ELECTRON_RUN_AS_NODE/w:VSCODE_DEV/w:$WSLENV
local WSL_EXT_ID="ms-vscode-remote.remote-wsl"
local WSL_EXT_WLOC=$(echo "" | VSCODE_DEV=1 ELECTRON_RUN_AS_NODE=1 "$ROOT/.build/electron/Code - OSS.exe" "out/cli.js" --locate-extension $WSL_EXT_ID)
cd $CWD
if [ -n "$WSL_EXT_WLOC" ]; then
# replace \r\n with \n in WSL_EXT_WLOC
local WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode-dev.sh
$WSL_CODE "$ROOT" "$@"
exit $?
else
echo "Remote WSL not installed, trying to run VSCode in WSL."
fi
fi
}
if [ "$IN_WSL" == "true" ] && [ -z "$DISPLAY" ]; then
code-wsl "$@"
elif [ -f /mnt/wslg/versions.txt ]; then
code --disable-gpu "$@"
elif [ -f /.dockerenv ]; then
# Workaround for https://bugs.chromium.org/p/chromium/issues/detail?id=1263267
# Chromium does not release shared memory when streaming scripts
# which might exhaust the available resources in the container environment
# leading to failed script loading.
code --disable-dev-shm-usage "$@"
else
code "$@"
fi
exit $?
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
if [ $# -eq 0 ]; then
echo "Pass in a version like ./scripts/generate-vscode-dts.sh 1.30."
echo "Failed to generate index.d.ts."
exit 1
fi
header="// Type definitions for Visual Studio Code ${1}
// Project: https://github.com/microsoft/vscode
// Definitions by: Visual Studio Code Team, Microsoft <https://github.com/microsoft>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
* See https://github.com/microsoft/vscode/blob/main/LICENSE.txt for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Type Definition for Visual Studio Code ${1} Extension API
* See https://code.visualstudio.com/api for more information
*/"
if [ -f ./src/vscode-dts/vscode.d.ts ]; then
echo "$header" > index.d.ts
sed "1,4d" ./src/vscode-dts/vscode.d.ts >> index.d.ts
echo "Generated index.d.ts for version ${1}."
else
echo "Can't find ./src/vscode-dts/vscode.d.ts. Run this script at vscode root."
fi
+18
View File
@@ -0,0 +1,18 @@
@echo off
setlocal
set ELECTRON_RUN_AS_NODE=1
pushd %~dp0\..
for /f "tokens=2 delims=:," %%a in ('findstr /R /C:"\"nameShort\":.*" product.json') do set NAMESHORT=%%~a
set NAMESHORT=%NAMESHORT: "=%
set NAMESHORT=%NAMESHORT:"=%.exe
set CODE=".build\electron\%NAMESHORT%"
%CODE% %*
popd
endlocal
exit /b %errorlevel%
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
fi
pushd $ROOT
if [[ "$OSTYPE" == "darwin"* ]]; then
NAME=`node -p "require('./product.json').nameLong"`
CODE="$ROOT/.build/electron/$NAME.app/Contents/MacOS/Electron"
else
NAME=`node -p "require('./product.json').applicationName"`
CODE="$ROOT/.build/electron/$NAME"
fi
# Get electron
npm run electron
popd
export VSCODE_DEV=1
if [[ "$OSTYPE" == "darwin"* ]]; then
ulimit -n 4096 ; ELECTRON_RUN_AS_NODE=1 \
"$CODE" \
"$@"
else
ELECTRON_RUN_AS_NODE=1 \
"$CODE" \
"$@"
fi
+3
View File
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
+896
View File
@@ -0,0 +1,896 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fsPromise from 'fs/promises';
import path from 'path';
import * as http from 'http';
import * as parcelWatcher from '@parcel/watcher';
/**
* Launches the server for the monaco editor playground
*/
function main() {
const server = new HttpServer({ host: 'localhost', port: 5001, cors: true });
server.use('/', redirectToMonacoEditorPlayground());
const rootDir = path.join(__dirname, '..');
const fileServer = new FileServer(rootDir);
server.use(fileServer.handleRequest);
const moduleIdMapper = new SimpleModuleIdPathMapper(path.join(rootDir, 'out'));
const editorMainBundle = new CachedBundle('vs/editor/editor.main', moduleIdMapper);
fileServer.overrideFileContent(editorMainBundle.entryModulePath, () => editorMainBundle.bundle());
const loaderPath = path.join(rootDir, 'out/vs/loader.js');
fileServer.overrideFileContent(loaderPath, async () =>
Buffer.from(new TextEncoder().encode(makeLoaderJsHotReloadable(await fsPromise.readFile(loaderPath, 'utf8'), new URL('/file-changes', server.url))))
);
const watcher = DirWatcher.watchRecursively(moduleIdMapper.rootDir);
watcher.onDidChange((path, newContent) => {
editorMainBundle.setModuleContent(path, newContent);
editorMainBundle.bundle();
console.log(`${new Date().toLocaleTimeString()}, file change: ${path}`);
});
server.use('/file-changes', handleGetFileChangesRequest(watcher, fileServer, moduleIdMapper));
console.log(`Server listening on ${server.url}`);
}
setTimeout(main, 0);
// #region Http/File Server
type RequestHandler = (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
type ChainableRequestHandler = (req: http.IncomingMessage, res: http.ServerResponse, next: RequestHandler) => Promise<void>;
class HttpServer {
private readonly server: http.Server;
public readonly url: URL;
private handler: ChainableRequestHandler[] = [];
constructor(options: { host: string; port: number; cors: boolean }) {
this.server = http.createServer(async (req, res) => {
if (options.cors) {
res.setHeader('Access-Control-Allow-Origin', '*');
}
let i = 0;
const next = async (req: http.IncomingMessage, res: http.ServerResponse) => {
if (i >= this.handler.length) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
return;
}
const handler = this.handler[i];
i++;
await handler(req, res, next);
};
await next(req, res);
});
this.server.listen(options.port, options.host);
this.url = new URL(`http://${options.host}:${options.port}`);
}
use(handler: ChainableRequestHandler);
use(path: string, handler: ChainableRequestHandler);
use(...args: [path: string, handler: ChainableRequestHandler] | [handler: ChainableRequestHandler]) {
const handler = args.length === 1 ? args[0] : (req, res, next) => {
const path = args[0];
const requestedUrl = new URL(req.url, this.url);
if (requestedUrl.pathname === path) {
return args[1](req, res, next);
} else {
return next(req, res);
}
};
this.handler.push(handler);
}
}
function redirectToMonacoEditorPlayground(): ChainableRequestHandler {
return async (req, res) => {
const url = new URL('https://microsoft.github.io/monaco-editor/playground.html');
url.searchParams.append('source', `http://${req.headers.host}/out/vs`);
res.writeHead(302, { Location: url.toString() });
res.end();
};
}
class FileServer {
private readonly overrides = new Map<string, () => Promise<Buffer>>();
constructor(public readonly publicDir: string) { }
public readonly handleRequest: ChainableRequestHandler = async (req, res, next) => {
const requestedUrl = new URL(req.url!, `http://${req.headers.host}`);
const pathName = requestedUrl.pathname;
const filePath = path.join(this.publicDir, pathName);
if (!filePath.startsWith(this.publicDir)) {
res.writeHead(403, { 'Content-Type': 'text/plain' });
res.end('403 Forbidden');
return;
}
try {
const override = this.overrides.get(filePath);
let content: Buffer;
if (override) {
content = await override();
} else {
content = await fsPromise.readFile(filePath);
}
const contentType = getContentType(filePath);
res.writeHead(200, { 'Content-Type': contentType });
res.end(content);
} catch (err) {
if (err.code === 'ENOENT') {
next(req, res);
} else {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('500 Internal Server Error');
}
}
};
public filePathToUrlPath(filePath: string): string | undefined {
const relative = path.relative(this.publicDir, filePath);
const isSubPath = !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
if (!isSubPath) {
return undefined;
}
const relativePath = relative.replace(/\\/g, '/');
return `/${relativePath}`;
}
public overrideFileContent(filePath: string, content: () => Promise<Buffer>): void {
this.overrides.set(filePath, content);
}
}
function getContentType(filePath: string): string {
const extname = path.extname(filePath);
switch (extname) {
case '.js':
return 'text/javascript';
case '.css':
return 'text/css';
case '.json':
return 'application/json';
case '.png':
return 'image/png';
case '.jpg':
return 'image/jpg';
case '.svg':
return 'image/svg+xml';
case '.html':
return 'text/html';
case '.wasm':
return 'application/wasm';
default:
return 'text/plain';
}
}
// #endregion
// #region File Watching
interface IDisposable {
dispose(): void;
}
class DirWatcher {
public static watchRecursively(dir: string): DirWatcher {
const listeners: ((path: string, newContent: string) => void)[] = [];
const fileContents = new Map<string, string>();
const event = (handler: (path: string, newContent: string) => void) => {
listeners.push(handler);
return {
dispose: () => {
const idx = listeners.indexOf(handler);
if (idx >= 0) {
listeners.splice(idx, 1);
}
}
};
};
parcelWatcher.subscribe(dir, async (err, events) => {
for (const e of events) {
if (e.type === 'update') {
const newContent = await fsPromise.readFile(e.path, 'utf8');
if (fileContents.get(e.path) !== newContent) {
fileContents.set(e.path, newContent);
listeners.forEach(l => l(e.path, newContent));
}
}
}
});
return new DirWatcher(event);
}
constructor(public readonly onDidChange: (handler: (path: string, newContent: string) => void) => IDisposable) {
}
}
function handleGetFileChangesRequest(watcher: DirWatcher, fileServer: FileServer, moduleIdMapper: SimpleModuleIdPathMapper): ChainableRequestHandler {
return async (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
const d = watcher.onDidChange((fsPath, newContent) => {
const path = fileServer.filePathToUrlPath(fsPath);
if (path) {
res.write(JSON.stringify({ changedPath: path, moduleId: moduleIdMapper.getModuleId(fsPath), newContent }) + '\n');
}
});
res.on('close', () => d.dispose());
};
}
function makeLoaderJsHotReloadable(loaderJsCode: string, fileChangesUrl: URL): string {
loaderJsCode = loaderJsCode.replace(
/constructor\(env, scriptLoader, defineFunc, requireFunc, loaderAvailableTimestamp = 0\) {/,
'$&globalThis.___globalModuleManager = this; globalThis.vscode = { process: { env: { VSCODE_DEV: true } } }'
);
const ___globalModuleManager: any = undefined;
// This code will be appended to loader.js
function $watchChanges(fileChangesUrl: string) {
interface HotReloadConfig { }
let reloadFn;
if (globalThis.$sendMessageToParent) {
reloadFn = () => globalThis.$sendMessageToParent({ kind: 'reload' });
} else if (typeof window !== 'undefined') {
reloadFn = () => window.location.reload();
} else {
reloadFn = () => { };
}
console.log('Connecting to server to watch for changes...');
(fetch as any)(fileChangesUrl)
.then(async request => {
const reader = request.body.getReader();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) { break; }
buffer += new TextDecoder().decode(value);
const lines = buffer.split('\n');
buffer = lines.pop()!;
const changes: { relativePath: string; config: HotReloadConfig | undefined; path: string; newContent: string }[] = [];
for (const line of lines) {
const data = JSON.parse(line);
const relativePath = data.changedPath.replace(/\\/g, '/').split('/out/')[1];
changes.push({ config: {}, path: data.changedPath, relativePath, newContent: data.newContent });
}
const result = handleChanges(changes, 'playground-server');
if (result.reloadFailedJsFiles.length > 0) {
reloadFn();
}
}
}).catch(err => {
console.error(err);
setTimeout(() => $watchChanges(fileChangesUrl), 1000);
});
function handleChanges(changes: {
relativePath: string;
config: HotReloadConfig | undefined;
path: string;
newContent: string;
}[], debugSessionName: string) {
// This function is stringified and injected into the debuggee.
const hotReloadData: { count: number; originalWindowTitle: any; timeout: any; shouldReload: boolean } = globalThis.$hotReloadData || (globalThis.$hotReloadData = { count: 0, messageHideTimeout: undefined, shouldReload: false });
const reloadFailedJsFiles: { relativePath: string; path: string }[] = [];
for (const change of changes) {
handleChange(change.relativePath, change.path, change.newContent, change.config);
}
return { reloadFailedJsFiles };
function handleChange(relativePath: string, path: string, newSrc: string, config: any) {
if (relativePath.endsWith('.css')) {
handleCssChange(relativePath);
} else if (relativePath.endsWith('.js')) {
handleJsChange(relativePath, path, newSrc, config);
}
}
function handleCssChange(relativePath: string) {
if (typeof document === 'undefined') {
return;
}
const styleSheet = (([...document.querySelectorAll(`link[rel='stylesheet']`)] as HTMLLinkElement[]))
.find(l => new URL(l.href, document.location.href).pathname.endsWith(relativePath));
if (styleSheet) {
setMessage(`reload ${formatPath(relativePath)} - ${new Date().toLocaleTimeString()}`);
console.log(debugSessionName, 'css reloaded', relativePath);
styleSheet.href = styleSheet.href.replace(/\?.*/, '') + '?' + Date.now();
} else {
setMessage(`could not reload ${formatPath(relativePath)} - ${new Date().toLocaleTimeString()}`);
console.log(debugSessionName, 'ignoring css change, as stylesheet is not loaded', relativePath);
}
}
function handleJsChange(relativePath: string, path: string, newSrc: string, config: any) {
const moduleIdStr = trimEnd(relativePath, '.js');
const requireFn: any = globalThis.require;
const moduleManager = (requireFn as any).moduleManager;
if (!moduleManager) {
console.log(debugSessionName, 'ignoring js change, as moduleManager is not available', relativePath);
return;
}
const moduleId = moduleManager._moduleIdProvider.getModuleId(moduleIdStr);
const oldModule = moduleManager._modules2[moduleId];
if (!oldModule) {
console.log(debugSessionName, 'ignoring js change, as module is not loaded', relativePath);
return;
}
// Check if we can reload
const g = globalThis as any;
// A frozen copy of the previous exports
const oldExports = Object.freeze({ ...oldModule.exports });
const reloadFn = g.$hotReload_applyNewExports?.({ oldExports, newSrc, config });
if (!reloadFn) {
console.log(debugSessionName, 'ignoring js change, as module does not support hot-reload', relativePath);
hotReloadData.shouldReload = true;
reloadFailedJsFiles.push({ relativePath, path });
setMessage(`hot reload not supported for ${formatPath(relativePath)} - ${new Date().toLocaleTimeString()}`);
return;
}
// Eval maintains source maps
function newScript(/* this parameter is used by newSrc */ define) {
// eslint-disable-next-line no-eval
eval(newSrc); // CodeQL [SM01632] This code is only executed during development. It is required for the hot-reload functionality.
}
newScript(/* define */ function (deps, callback) {
// Evaluating the new code was successful.
// Redefine the module
delete moduleManager._modules2[moduleId];
moduleManager.defineModule(moduleIdStr, deps, callback);
const newModule = moduleManager._modules2[moduleId];
// Patch the exports of the old module, so that modules using the old module get the new exports
Object.assign(oldModule.exports, newModule.exports);
// We override the exports so that future reloads still patch the initial exports.
newModule.exports = oldModule.exports;
const successful = reloadFn(newModule.exports);
if (!successful) {
hotReloadData.shouldReload = true;
setMessage(`hot reload failed ${formatPath(relativePath)} - ${new Date().toLocaleTimeString()}`);
console.log(debugSessionName, 'hot reload was not successful', relativePath);
return;
}
console.log(debugSessionName, 'hot reloaded', moduleIdStr);
setMessage(`successfully reloaded ${formatPath(relativePath)} - ${new Date().toLocaleTimeString()}`);
});
}
function setMessage(message: string) {
const domElem = (document.querySelector('.titlebar-center .window-title')) as HTMLDivElement | undefined;
if (!domElem) { return; }
if (!hotReloadData.timeout) {
hotReloadData.originalWindowTitle = domElem.innerText;
} else {
clearTimeout(hotReloadData.timeout);
}
if (hotReloadData.shouldReload) {
message += ' (manual reload required)';
}
domElem.innerText = message;
hotReloadData.timeout = setTimeout(() => {
hotReloadData.timeout = undefined;
// If wanted, we can restore the previous title message
// domElem.replaceChildren(hotReloadData.originalWindowTitle);
}, 5000);
}
function formatPath(path: string): string {
const parts = path.split('/');
parts.reverse();
let result = parts[0];
parts.shift();
for (const p of parts) {
if (result.length + p.length > 40) {
break;
}
result = p + '/' + result;
if (result.length > 20) {
break;
}
}
return result;
}
function trimEnd(str, suffix) {
if (str.endsWith(suffix)) {
return str.substring(0, str.length - suffix.length);
}
return str;
}
}
}
const additionalJsCode = `
(${(function () {
globalThis.$hotReload_deprecateExports = new Set<(oldExports: any, newExports: any) => void>();
}).toString()})();
${$watchChanges.toString()}
$watchChanges(${JSON.stringify(fileChangesUrl)});
`;
return `${loaderJsCode}\n${additionalJsCode}`;
}
// #endregion
// #region Bundling
class CachedBundle {
public readonly entryModulePath = this.mapper.resolveRequestToPath(this.moduleId)!;
constructor(
private readonly moduleId: string,
private readonly mapper: SimpleModuleIdPathMapper,
) {
}
private loader: ModuleLoader | undefined = undefined;
private bundlePromise: Promise<Buffer> | undefined = undefined;
public async bundle(): Promise<Buffer> {
if (!this.bundlePromise) {
this.bundlePromise = (async () => {
if (!this.loader) {
this.loader = new ModuleLoader(this.mapper);
await this.loader.addModuleAndDependencies(this.entryModulePath);
}
const editorEntryPoint = await this.loader.getModule(this.entryModulePath);
const content = bundleWithDependencies(editorEntryPoint!);
return content;
})();
}
return this.bundlePromise;
}
public async setModuleContent(path: string, newContent: string): Promise<void> {
if (!this.loader) {
return;
}
const module = await this.loader!.getModule(path);
if (module) {
if (!this.loader.updateContent(module, newContent)) {
this.loader = undefined;
}
}
this.bundlePromise = undefined;
}
}
function bundleWithDependencies(module: IModule): Buffer {
const visited = new Set<IModule>();
const builder = new SourceMapBuilder();
function visit(module: IModule) {
if (visited.has(module)) {
return;
}
visited.add(module);
for (const dep of module.dependencies) {
visit(dep);
}
builder.addSource(module.source);
}
visit(module);
const sourceMap = builder.toSourceMap();
sourceMap.sourceRoot = module.source.sourceMap.sourceRoot;
const sourceMapBase64Str = Buffer.from(JSON.stringify(sourceMap)).toString('base64');
builder.addLine(`//# sourceMappingURL=data:application/json;base64,${sourceMapBase64Str}`);
return builder.toContent();
}
class ModuleLoader {
private readonly modules = new Map<string, Promise<IModule | undefined>>();
constructor(private readonly mapper: SimpleModuleIdPathMapper) { }
public getModule(path: string): Promise<IModule | undefined> {
return Promise.resolve(this.modules.get(path));
}
public updateContent(module: IModule, newContent: string): boolean {
const parsedModule = parseModule(newContent, module.path, this.mapper);
if (!parsedModule) {
return false;
}
if (!arrayEquals(parsedModule.dependencyRequests, module.dependencyRequests)) {
return false;
}
module.dependencyRequests = parsedModule.dependencyRequests;
module.source = parsedModule.source;
return true;
}
async addModuleAndDependencies(path: string): Promise<IModule | undefined> {
if (this.modules.has(path)) {
return this.modules.get(path)!;
}
const promise = (async () => {
const content = await fsPromise.readFile(path, { encoding: 'utf-8' });
const parsedModule = parseModule(content, path, this.mapper);
if (!parsedModule) {
return undefined;
}
const dependencies = (await Promise.all(parsedModule.dependencyRequests.map(async r => {
if (r === 'require' || r === 'exports' || r === 'module') {
return null;
}
const depPath = this.mapper.resolveRequestToPath(r, path);
if (!depPath) {
return null;
}
return await this.addModuleAndDependencies(depPath);
}))).filter((d): d is IModule => !!d);
const module: IModule = {
id: this.mapper.getModuleId(path)!,
dependencyRequests: parsedModule.dependencyRequests,
dependencies,
path,
source: parsedModule.source,
};
return module;
})();
this.modules.set(path, promise);
return promise;
}
}
function arrayEquals<T>(a: T[], b: T[]): boolean {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
const encoder = new TextEncoder();
function parseModule(content: string, path: string, mapper: SimpleModuleIdPathMapper): { source: Source; dependencyRequests: string[] } | undefined {
const m = content.match(/define\((\[.*?\])/);
if (!m) {
return undefined;
}
const dependencyRequests = JSON.parse(m[1].replace(/'/g, '"')) as string[];
const sourceMapHeader = '//# sourceMappingURL=data:application/json;base64,';
const idx = content.indexOf(sourceMapHeader);
let sourceMap: any = null;
if (idx !== -1) {
const sourceMapJsonStr = Buffer.from(content.substring(idx + sourceMapHeader.length), 'base64').toString('utf-8');
sourceMap = JSON.parse(sourceMapJsonStr);
content = content.substring(0, idx);
}
content = content.replace('define([', `define("${mapper.getModuleId(path)}", [`);
const contentBuffer = Buffer.from(encoder.encode(content));
const source = new Source(contentBuffer, sourceMap);
return { dependencyRequests, source };
}
class SimpleModuleIdPathMapper {
constructor(public readonly rootDir: string) { }
public getModuleId(path: string): string | null {
if (!path.startsWith(this.rootDir) || !path.endsWith('.js')) {
return null;
}
const moduleId = path.substring(this.rootDir.length + 1);
return moduleId.replace(/\\/g, '/').substring(0, moduleId.length - 3);
}
public resolveRequestToPath(request: string, requestingModulePath?: string): string | null {
if (request.indexOf('css!') !== -1) {
return null;
}
if (request.startsWith('.')) {
return path.join(path.dirname(requestingModulePath!), request + '.js');
} else {
return path.join(this.rootDir, request + '.js');
}
}
}
interface IModule {
id: string;
dependencyRequests: string[];
dependencies: IModule[];
path: string;
source: Source;
}
// #endregion
// #region SourceMapBuilder
// From https://stackoverflow.com/questions/29905373/how-to-create-sourcemaps-for-concatenated-files with modifications
class Source {
// Ends with \n
public readonly content: Buffer;
public readonly sourceMap: SourceMap;
public readonly sourceLines: number;
public readonly sourceMapMappings: Buffer;
constructor(content: Buffer, sourceMap: SourceMap | undefined) {
if (!sourceMap) {
sourceMap = SourceMapBuilder.emptySourceMap;
}
let sourceLines = countNL(content);
if (content.length > 0 && content[content.length - 1] !== 10) {
sourceLines++;
content = Buffer.concat([content, Buffer.from([10])]);
}
this.content = content;
this.sourceMap = sourceMap;
this.sourceLines = sourceLines;
this.sourceMapMappings = typeof this.sourceMap.mappings === 'string'
? Buffer.from(encoder.encode(sourceMap.mappings as string))
: this.sourceMap.mappings;
}
}
class SourceMapBuilder {
public static emptySourceMap: SourceMap = { version: 3, sources: [], mappings: Buffer.alloc(0) };
private readonly outputBuffer = new DynamicBuffer();
private readonly sources: string[] = [];
private readonly mappings = new DynamicBuffer();
private lastSourceIndex = 0;
private lastSourceLine = 0;
private lastSourceCol = 0;
addLine(text: string) {
this.outputBuffer.addString(text);
this.outputBuffer.addByte(10);
this.mappings.addByte(59); // ;
}
addSource(source: Source) {
const sourceMap = source.sourceMap;
this.outputBuffer.addBuffer(source.content);
const sourceRemap: number[] = [];
for (const v of sourceMap.sources) {
let pos = this.sources.indexOf(v);
if (pos < 0) {
pos = this.sources.length;
this.sources.push(v);
}
sourceRemap.push(pos);
}
let lastOutputCol = 0;
const inputMappings = source.sourceMapMappings;
let outputLine = 0;
let ip = 0;
let inOutputCol = 0;
let inSourceIndex = 0;
let inSourceLine = 0;
let inSourceCol = 0;
let shift = 0;
let value = 0;
let valpos = 0;
const commit = () => {
if (valpos === 0) { return; }
this.mappings.addVLQ(inOutputCol - lastOutputCol);
lastOutputCol = inOutputCol;
if (valpos === 1) {
valpos = 0;
return;
}
const outSourceIndex = sourceRemap[inSourceIndex];
this.mappings.addVLQ(outSourceIndex - this.lastSourceIndex);
this.lastSourceIndex = outSourceIndex;
this.mappings.addVLQ(inSourceLine - this.lastSourceLine);
this.lastSourceLine = inSourceLine;
this.mappings.addVLQ(inSourceCol - this.lastSourceCol);
this.lastSourceCol = inSourceCol;
valpos = 0;
};
while (ip < inputMappings.length) {
let b = inputMappings[ip++];
if (b === 59) { // ;
commit();
this.mappings.addByte(59);
inOutputCol = 0;
lastOutputCol = 0;
outputLine++;
} else if (b === 44) { // ,
commit();
this.mappings.addByte(44);
} else {
b = charToInteger[b];
if (b === 255) { throw new Error('Invalid sourceMap'); }
value += (b & 31) << shift;
if (b & 32) {
shift += 5;
} else {
const shouldNegate = value & 1;
value >>= 1;
if (shouldNegate) { value = -value; }
switch (valpos) {
case 0: inOutputCol += value; break;
case 1: inSourceIndex += value; break;
case 2: inSourceLine += value; break;
case 3: inSourceCol += value; break;
}
valpos++;
value = shift = 0;
}
}
}
commit();
while (outputLine < source.sourceLines) {
this.mappings.addByte(59);
outputLine++;
}
}
toContent(): Buffer {
return this.outputBuffer.toBuffer();
}
toSourceMap(sourceRoot?: string): SourceMap {
return { version: 3, sourceRoot, sources: this.sources, mappings: this.mappings.toBuffer().toString() };
}
}
export interface SourceMap {
version: number; // always 3
file?: string;
sourceRoot?: string;
sources: string[];
sourcesContent?: string[];
names?: string[];
mappings: string | Buffer;
}
const charToInteger = Buffer.alloc(256);
const integerToChar = Buffer.alloc(64);
charToInteger.fill(255);
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split('').forEach((char, i) => {
charToInteger[char.charCodeAt(0)] = i;
integerToChar[i] = char.charCodeAt(0);
});
class DynamicBuffer {
private buffer: Buffer;
private size: number;
constructor() {
this.buffer = Buffer.alloc(512);
this.size = 0;
}
ensureCapacity(capacity: number) {
if (this.buffer.length >= capacity) {
return;
}
const oldBuffer = this.buffer;
this.buffer = Buffer.alloc(Math.max(oldBuffer.length * 2, capacity));
oldBuffer.copy(this.buffer);
}
addByte(b: number) {
this.ensureCapacity(this.size + 1);
this.buffer[this.size++] = b;
}
addVLQ(num: number) {
let clamped: number;
if (num < 0) {
num = (-num << 1) | 1;
} else {
num <<= 1;
}
do {
clamped = num & 31;
num >>= 5;
if (num > 0) {
clamped |= 32;
}
this.addByte(integerToChar[clamped]);
} while (num > 0);
}
addString(s: string) {
const l = Buffer.byteLength(s);
this.ensureCapacity(this.size + l);
this.buffer.write(s, this.size);
this.size += l;
}
addBuffer(b: Buffer) {
this.ensureCapacity(this.size + b.length);
b.copy(this.buffer, this.size);
this.size += b.length;
}
toBuffer(): Buffer {
return this.buffer.slice(0, this.size);
}
}
function countNL(b: Buffer): number {
let res = 0;
for (let i = 0; i < b.length; i++) {
if (b[i] === 10) { res++; }
}
return res;
}
// #endregion
+17
View File
@@ -0,0 +1,17 @@
@echo off
setlocal
echo Runs tests against the current documentation in https://github.com/microsoft/vscode-docs/tree/vnext
pushd %~dp0\..
:: Endgame tests
call .\scripts\test.bat --runGlob **\*.releaseTest.js %*
if %errorlevel% neq 0 exit /b %errorlevel%
rmdir /s /q %VSCODEUSERDATADIR%
popd
endlocal
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
VSCODEUSERDATADIR=`mktemp -d -t 'myuserdatadir'`
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
fi
cd $ROOT
echo "Runs tests against the current documentation in https://github.com/microsoft/vscode-docs/tree/vnext"
# Tests
./scripts/test.sh --runGlob **/*.releaseTest.js "$@"
rm -r $VSCODEUSERDATADIR
+124
View File
@@ -0,0 +1,124 @@
@echo off
setlocal
pushd %~dp0\..
set VSCODEUSERDATADIR=%TEMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,2%
set VSCODECRASHDIR=%~dp0\..\.build\crashes
set VSCODELOGSDIR=%~dp0\..\.build\logs\integration-tests
:: Figure out which Electron to use for running tests
if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
chcp 65001
set INTEGRATION_TEST_ELECTRON_PATH=.\scripts\code.bat
set VSCODE_BUILD_BUILTIN_EXTENSIONS_SILENCE_PLEASE=1
echo Running integration tests out of sources.
) else (
set VSCODE_CLI=1
set ELECTRON_ENABLE_LOGGING=1
echo Running integration tests with '%INTEGRATION_TEST_ELECTRON_PATH%' as build.
)
echo Storing crash reports into '%VSCODECRASHDIR%'.
echo Storing log files into '%VSCODELOGSDIR%'.
:: Unit tests
echo.
echo ### node.js integration tests
call .\scripts\test.bat --runGlob **\*.integrationTest.js %*
if %errorlevel% neq 0 exit /b %errorlevel%
:: Tests in the extension host
set API_TESTS_EXTRA_ARGS=--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=%VSCODECRASHDIR% --logsPath=%VSCODELOGSDIR% --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
echo.
echo ### API tests (folder)
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests %API_TESTS_EXTRA_ARGS%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### API tests (workspace)
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests %API_TESTS_EXTRA_ARGS%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Colorize tests
call npm run test-extension -- -l vscode-colorize-tests
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Terminal Suggest tests
call npm run test-extension -- -l terminal-suggest --enable-proposed-api=vscode.vscode-api-tests
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### TypeScript tests
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\typescript-language-features\test-workspace --extensionDevelopmentPath=%~dp0\..\extensions\typescript-language-features --extensionTestsPath=%~dp0\..\extensions\typescript-language-features\out\test\unit %API_TESTS_EXTRA_ARGS%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Markdown tests
call npm run test-extension -- -l markdown-language-features
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Emmet tests
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\emmet\test-workspace --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test %API_TESTS_EXTRA_ARGS%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Git tests
for /f "delims=" %%i in ('node -p "require('fs').realpathSync.native(require('os').tmpdir())"') do set TEMPDIR=%%i
set GITWORKSPACE=%TEMPDIR%\git-%RANDOM%
mkdir %GITWORKSPACE%
call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPath=%~dp0\..\extensions\git --extensionTestsPath=%~dp0\..\extensions\git\out\test %API_TESTS_EXTRA_ARGS%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Ipynb tests
call npm run test-extension -- -l ipynb
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Notebook Output tests
call npm run test-extension -- -l notebook-renderers
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Configuration editing tests
set CFWORKSPACE=%TEMPDIR%\cf-%RANDOM%
mkdir %CFWORKSPACE%
call npm run test-extension -- -l configuration-editing
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### GitHub Authentication tests
call npm run test-extension -- -l github-authentication
if %errorlevel% neq 0 exit /b %errorlevel%
:: Tests standalone (CommonJS)
echo.
echo ### CSS tests
call %~dp0\node-electron.bat %~dp0\..\extensions\css-language-features/server/test/index.js
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### HTML tests
call %~dp0\node-electron.bat %~dp0\..\extensions\html-language-features/server/test/index.js
if %errorlevel% neq 0 exit /b %errorlevel%
:: Cleanup
rmdir /s /q %VSCODEUSERDATADIR%
popd
endlocal
+142
View File
@@ -0,0 +1,142 @@
#!/usr/bin/env bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
# --disable-dev-shm-usage: when run on docker containers where size of /dev/shm
# partition < 64MB which causes OOM failure for chromium compositor that uses the partition for shared memory
LINUX_EXTRA_ARGS="--disable-dev-shm-usage"
fi
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
VSCODECRASHDIR=$ROOT/.build/crashes
VSCODELOGSDIR=$ROOT/.build/logs/integration-tests
cd $ROOT
# Figure out which Electron to use for running tests
if [ -z "$INTEGRATION_TEST_ELECTRON_PATH" ]
then
INTEGRATION_TEST_ELECTRON_PATH="./scripts/code.sh"
echo "Running integration tests out of sources."
else
export VSCODE_CLI=1
export ELECTRON_ENABLE_LOGGING=1
echo "Running integration tests with '$INTEGRATION_TEST_ELECTRON_PATH' as build."
fi
echo "Storing crash reports into '$VSCODECRASHDIR'."
echo "Storing log files into '$VSCODELOGSDIR'."
# Unit tests
echo
echo "### node.js integration tests"
echo
./scripts/test.sh --runGlob **/*.integrationTest.js "$@"
# Tests in the extension host
API_TESTS_EXTRA_ARGS="--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=$VSCODECRASHDIR --logsPath=$VSCODELOGSDIR --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-extensions --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
if [ -z "$INTEGRATION_TEST_APP_NAME" ]; then
kill_app() { true; }
else
kill_app() { killall $INTEGRATION_TEST_APP_NAME || true; }
fi
echo
echo "### API tests (folder)"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests $API_TESTS_EXTRA_ARGS
kill_app
echo
echo "### API tests (workspace)"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests $API_TESTS_EXTRA_ARGS
kill_app
echo
echo "### Colorize tests"
echo
npm run test-extension -- -l vscode-colorize-tests
kill_app
echo
echo "### Terminal Suggest tests"
echo
npm run test-extension -- -l terminal-suggest --enable-proposed-api=vscode.vscode-api-tests
kill_app
echo
echo "### TypeScript tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS $ROOT/extensions/typescript-language-features/test-workspace --extensionDevelopmentPath=$ROOT/extensions/typescript-language-features --extensionTestsPath=$ROOT/extensions/typescript-language-features/out/test/unit $API_TESTS_EXTRA_ARGS
kill_app
echo
echo "### Markdown tests"
echo
npm run test-extension -- -l markdown-language-features
kill_app
echo
echo "### Emmet tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS $ROOT/extensions/emmet/test-workspace --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test $API_TESTS_EXTRA_ARGS
kill_app
echo
echo "### Git tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS $(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test $API_TESTS_EXTRA_ARGS
kill_app
echo
echo "### Ipynb tests"
echo
npm run test-extension -- -l ipynb
kill_app
echo
echo "### Notebook Output tests"
echo
npm run test-extension -- -l notebook-renderers
kill_app
echo
echo "### Configuration editing tests"
echo
npm run test-extension -- -l configuration-editing
kill_app
echo
echo "### GitHub Authentication tests"
echo
npm run test-extension -- -l github-authentication
kill_app
# Tests standalone (CommonJS)
echo
echo "### CSS tests"
echo
cd $ROOT/extensions/css-language-features/server && $ROOT/scripts/node-electron.sh test/index.js
echo
echo "### HTML tests"
echo
cd $ROOT/extensions/html-language-features/server && $ROOT/scripts/node-electron.sh test/index.js
# Cleanup
rm -rf $VSCODEUSERDATADIR
+117
View File
@@ -0,0 +1,117 @@
@echo off
setlocal
pushd %~dp0\..
IF "%~1" == "" (
set AUTHORITY=vscode-remote://test+test/
:: backward to forward slashed
set EXT_PATH=%CD:\=/%/extensions
:: Download nodejs executable for remote
call npm run gulp node
) else (
set AUTHORITY=%1
set EXT_PATH=%2
set VSCODEUSERDATADIR=%3
)
IF "%VSCODEUSERDATADIR%" == "" (
set VSCODEUSERDATADIR=%TMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,5%
)
set REMOTE_EXT_PATH=%AUTHORITY%%EXT_PATH%
set VSCODECRASHDIR=%~dp0\..\.build\crashes
set VSCODELOGSDIR=%~dp0\..\.build\logs\integration-tests-remote
set TESTRESOLVER_DATA_FOLDER=%TMP%\testresolverdatafolder-%RANDOM%-%TIME:~6,5%
set TESTRESOLVER_LOGS_FOLDER=%VSCODELOGSDIR%\server
if "%VSCODE_REMOTE_SERVER_PATH%"=="" (
echo Using remote server out of sources for integration tests
) else (
set TESTRESOLVER_INSTALL_BUILTIN_EXTENSION=ms-vscode.vscode-smoketest-check
echo Using '%VSCODE_REMOTE_SERVER_PATH%' as server path
)
:: Figure out which Electron to use for running tests
if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
chcp 65001
set INTEGRATION_TEST_ELECTRON_PATH=.\scripts\code.bat
set API_TESTS_EXTRA_ARGS_BUILT=
echo Running integration tests out of sources.
) else (
set VSCODE_CLI=1
set ELECTRON_ENABLE_LOGGING=1
:: Extra arguments only when running against a built version
set API_TESTS_EXTRA_ARGS_BUILT=--extensions-dir=%EXT_PATH% --enable-proposed-api=vscode.vscode-test-resolver --enable-proposed-api=vscode.vscode-api-tests
echo Using %INTEGRATION_TEST_ELECTRON_PATH% as Electron path
)
echo Storing crash reports into '%VSCODECRASHDIR%'
echo Storing log files into '%VSCODELOGSDIR%'
:: Tests in the extension host
set API_TESTS_EXTRA_ARGS=--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=%VSCODECRASHDIR% --logsPath=%VSCODELOGSDIR% --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-inspect --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
echo.
echo ### API tests (folder)
call "%INTEGRATION_TEST_ELECTRON_PATH%" --folder-uri=%REMOTE_EXT_PATH%/vscode-api-tests/testWorkspace --extensionDevelopmentPath=%REMOTE_EXT_PATH%/vscode-api-tests --extensionTestsPath=%REMOTE_EXT_PATH%/vscode-api-tests/out/singlefolder-tests %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### API tests (workspace)
call "%INTEGRATION_TEST_ELECTRON_PATH%" --file-uri=%REMOTE_EXT_PATH%/vscode-api-tests/testworkspace.code-workspace --extensionDevelopmentPath=%REMOTE_EXT_PATH%/vscode-api-tests --extensionTestsPath=%REMOTE_EXT_PATH%/vscode-api-tests/out/workspace-tests %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### TypeScript tests
call "%INTEGRATION_TEST_ELECTRON_PATH%" --folder-uri=%REMOTE_EXT_PATH%/typescript-language-features/test-workspace --extensionDevelopmentPath=%REMOTE_EXT_PATH%/typescript-language-features --extensionTestsPath=%REMOTE_EXT_PATH%/typescript-language-features\out\test\unit %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Markdown tests
call "%INTEGRATION_TEST_ELECTRON_PATH%" --folder-uri=%REMOTE_EXT_PATH%/markdown-language-features/test-workspace --extensionDevelopmentPath=%REMOTE_EXT_PATH%/markdown-language-features --extensionTestsPath=%REMOTE_EXT_PATH%/markdown-language-features/out/test %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Emmet tests
call "%INTEGRATION_TEST_ELECTRON_PATH%" --folder-uri=%REMOTE_EXT_PATH%/emmet/test-workspace --extensionDevelopmentPath=%REMOTE_EXT_PATH%/emmet --extensionTestsPath=%REMOTE_EXT_PATH%/emmet/out/test %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Git tests
for /f "delims=" %%i in ('node -p "require('fs').realpathSync.native(require('os').tmpdir())"') do set TEMPDIR=%%i
set GITWORKSPACE=%TEMPDIR%\git-%RANDOM%
mkdir %GITWORKSPACE%
call "%INTEGRATION_TEST_ELECTRON_PATH%" --folder-uri=%AUTHORITY%%GITWORKSPACE% --extensionDevelopmentPath=%REMOTE_EXT_PATH%/git --extensionTestsPath=%REMOTE_EXT_PATH%/git/out/test %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Ipynb tests
set IPYNBWORKSPACE=%TEMPDIR%\ipynb-%RANDOM%
mkdir %IPYNBWORKSPACE%
call "%INTEGRATION_TEST_ELECTRON_PATH%" --folder-uri=%AUTHORITY%%IPYNBWORKSPACE% --extensionDevelopmentPath=%REMOTE_EXT_PATH%/ipynb --extensionTestsPath=%REMOTE_EXT_PATH%/ipynb/out/test %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Configuration editing tests
set CFWORKSPACE=%TEMPDIR%\cf-%RANDOM%
mkdir %CFWORKSPACE%
call "%INTEGRATION_TEST_ELECTRON_PATH%" --folder-uri=%AUTHORITY%/%CFWORKSPACE% --extensionDevelopmentPath=%REMOTE_EXT_PATH%/configuration-editing --extensionTestsPath=%REMOTE_EXT_PATH%/configuration-editing/out/test %API_TESTS_EXTRA_ARGS% %API_TESTS_EXTRA_ARGS_BUILT%
if %errorlevel% neq 0 exit /b %errorlevel%
:: Cleanup
IF "%3" == "" (
rmdir /s /q %VSCODEUSERDATADIR%
)
rmdir /s /q %TESTRESOLVER_DATA_FOLDER%
popd
endlocal
+133
View File
@@ -0,0 +1,133 @@
#!/usr/bin/env bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
# --disable-dev-shm-usage: when run on docker containers where size of /dev/shm
# partition < 64MB which causes OOM failure for chromium compositor that uses the partition for shared memory
LINUX_EXTRA_ARGS="--disable-dev-shm-usage"
fi
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
VSCODECRASHDIR=$ROOT/.build/crashes
VSCODELOGSDIR=$ROOT/.build/logs/integration-tests-remote
TESTRESOLVER_DATA_FOLDER=`mktemp -d 2>/dev/null`
cd $ROOT
if [[ "$1" == "" ]]; then
AUTHORITY=vscode-remote://test+test
EXT_PATH=$ROOT/extensions
# Load remote node
npm run gulp node
else
AUTHORITY=$1
EXT_PATH=$2
VSCODEUSERDATADIR=${3:-$VSCODEUSERDATADIR}
fi
export REMOTE_VSCODE=$AUTHORITY$EXT_PATH
# Figure out which Electron to use for running tests
if [ -z "$INTEGRATION_TEST_ELECTRON_PATH" ]
then
INTEGRATION_TEST_ELECTRON_PATH="./scripts/code.sh"
# No extra arguments when running out of sources
EXTRA_INTEGRATION_TEST_ARGUMENTS=""
echo "Running remote integration tests out of sources."
else
export VSCODE_CLI=1
export ELECTRON_ENABLE_LOGGING=1
# Running from a build, we need to enable the vscode-test-resolver extension
EXTRA_INTEGRATION_TEST_ARGUMENTS="--extensions-dir=$EXT_PATH --enable-proposed-api=vscode.vscode-test-resolver --enable-proposed-api=vscode.vscode-api-tests"
echo "Running remote integration tests with $INTEGRATION_TEST_ELECTRON_PATH as build."
fi
export TESTRESOLVER_DATA_FOLDER=$TESTRESOLVER_DATA_FOLDER
export TESTRESOLVER_LOGS_FOLDER=$VSCODELOGSDIR/server
# Figure out which remote server to use for running tests
if [ -z "$VSCODE_REMOTE_SERVER_PATH" ]
then
echo "Using remote server out of sources for integration tests"
else
echo "Using $VSCODE_REMOTE_SERVER_PATH as server path for integration tests"
export TESTRESOLVER_INSTALL_BUILTIN_EXTENSION='ms-vscode.vscode-smoketest-check'
fi
if [ -z "$INTEGRATION_TEST_APP_NAME" ]; then
kill_app() { true; }
else
kill_app() { killall $INTEGRATION_TEST_APP_NAME || true; }
fi
API_TESTS_EXTRA_ARGS="--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=$VSCODECRASHDIR --logsPath=$VSCODELOGSDIR --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
echo "Storing crash reports into '$VSCODECRASHDIR'."
echo "Storing log files into '$VSCODELOGSDIR'."
# Tests in the extension host
echo
echo "### API tests (folder)"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --folder-uri=$REMOTE_VSCODE/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$REMOTE_VSCODE/vscode-api-tests --extensionTestsPath=$REMOTE_VSCODE/vscode-api-tests/out/singlefolder-tests $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
echo
echo "### API tests (workspace)"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --file-uri=$REMOTE_VSCODE/vscode-api-tests/testworkspace.code-workspace --extensionDevelopmentPath=$REMOTE_VSCODE/vscode-api-tests --extensionTestsPath=$REMOTE_VSCODE/vscode-api-tests/out/workspace-tests $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
echo
echo "### TypeScript tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --folder-uri=$REMOTE_VSCODE/typescript-language-features/test-workspace --extensionDevelopmentPath=$REMOTE_VSCODE/typescript-language-features --extensionTestsPath=$REMOTE_VSCODE/typescript-language-features/out/test/unit $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
echo
echo "### Markdown tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --folder-uri=$REMOTE_VSCODE/markdown-language-features/test-workspace --extensionDevelopmentPath=$REMOTE_VSCODE/markdown-language-features --extensionTestsPath=$REMOTE_VSCODE/markdown-language-features/out/test $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
echo
echo "### Emmet tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --folder-uri=$REMOTE_VSCODE/emmet/test-workspace --extensionDevelopmentPath=$REMOTE_VSCODE/emmet --extensionTestsPath=$REMOTE_VSCODE/emmet/out/test $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
echo
echo "### Git tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --folder-uri=$AUTHORITY$(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$REMOTE_VSCODE/git --extensionTestsPath=$REMOTE_VSCODE/git/out/test $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
echo
echo "### Ipynb tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --folder-uri=$AUTHORITY$(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$REMOTE_VSCODE/ipynb --extensionTestsPath=$REMOTE_VSCODE/ipynb/out/test $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
echo
echo "### Configuration editing tests"
echo
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS --folder-uri=$AUTHORITY$(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$REMOTE_VSCODE/configuration-editing --extensionTestsPath=$REMOTE_VSCODE/configuration-editing/out/test $API_TESTS_EXTRA_ARGS $EXTRA_INTEGRATION_TEST_ARGUMENTS
kill_app
# Cleanup
if [[ "$3" == "" ]]; then
rm -rf $VSCODEUSERDATADIR
fi
rm -rf $TESTRESOLVER_DATA_FOLDER
+87
View File
@@ -0,0 +1,87 @@
@echo off
setlocal
pushd %~dp0\..
IF "%~1" == "" (
set AUTHORITY=vscode-remote://test+test/
:: backward to forward slashed
set EXT_PATH=%CD:\=/%/extensions
:: Download nodejs executable for remote
call npm run gulp node
) else (
set AUTHORITY=%1
set EXT_PATH=%2
)
set REMOTE_VSCODE=%AUTHORITY%%EXT_PATH%
if "%VSCODE_REMOTE_SERVER_PATH%"=="" (
chcp 65001
echo Using remote server out of sources for integration web tests
) else (
echo Using '%VSCODE_REMOTE_SERVER_PATH%' as server path for web integration tests
)
if not exist ".\test\integration\browser\out\index.js" (
pushd test\integration\browser
call npm run compile
popd
call npm run playwright-install
)
:: Tests in the extension host
echo.
echo ### API tests (folder)
call node .\test\integration\browser\out\index.js --workspacePath=.\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=.\extensions\vscode-api-tests --extensionTestsPath=.\extensions\vscode-api-tests\out\singlefolder-tests %*
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### API tests (workspace)
call node .\test\integration\browser\out\index.js --workspacePath=.\extensions\vscode-api-tests\testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=.\extensions\vscode-api-tests --extensionTestsPath=.\extensions\vscode-api-tests\out\workspace-tests %*
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### TypeScript tests
call node .\test\integration\browser\out\index.js --workspacePath=.\extensions\typescript-language-features\test-workspace --extensionDevelopmentPath=.\extensions\typescript-language-features --extensionTestsPath=.\extensions\typescript-language-features\out\test\unit %*
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Markdown tests
call node .\test\integration\browser\out\index.js --workspacePath=.\extensions\markdown-language-features\test-workspace --extensionDevelopmentPath=.\extensions\markdown-language-features --extensionTestsPath=.\extensions\markdown-language-features\out\test %*
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Emmet tests
call node .\test\integration\browser\out\index.js --workspacePath=.\extensions\emmet\test-workspace --extensionDevelopmentPath=.\extensions\emmet --extensionTestsPath=.\extensions\emmet\out\test %*
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Git tests
for /f "delims=" %%i in ('node -p "require('fs').realpathSync.native(require('os').tmpdir())"') do set TEMPDIR=%%i
set GITWORKSPACE=%TEMPDIR%\git-%RANDOM%
mkdir %GITWORKSPACE%
call node .\test\integration\browser\out\index.js --workspacePath=%GITWORKSPACE% --extensionDevelopmentPath=.\extensions\git --extensionTestsPath=.\extensions\git\out\test %*
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Ipynb tests
set IPYNBWORKSPACE=%TEMPDIR%\ipynb-%RANDOM%
mkdir %IPYNBWORKSPACE%
call node .\test\integration\browser\out\index.js --workspacePath=%IPYNBWORKSPACE% --extensionDevelopmentPath=.\extensions\ipynb --extensionTestsPath=.\extensions\ipynb\out\test %*
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo ### Configuration editing tests
set CFWORKSPACE=%TEMPDIR%\git-%RANDOM%
mkdir %CFWORKSPACE%
call node .\test\integration\browser\out\index.js --workspacePath=%CFWORKSPACE% --extensionDevelopmentPath=.\extensions\configuration-editing --extensionTestsPath=.\extensions\configuration-editing\out\test %*
if %errorlevel% neq 0 exit /b %errorlevel%
popd
endlocal
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
fi
cd $ROOT
if [ -z "$VSCODE_REMOTE_SERVER_PATH" ]
then
echo "Using remote server out of sources for integration web tests"
else
echo "Using $VSCODE_REMOTE_SERVER_PATH as server path for web integration tests"
fi
if [ ! -e 'test/integration/browser/out/index.js' ];then
(cd test/integration/browser && npm run compile)
npm run playwright-install
fi
# Tests in the extension host
echo
echo "### API tests (folder)"
echo
node test/integration/browser/out/index.js --workspacePath $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests "$@"
echo
echo "### API tests (workspace)"
echo
node test/integration/browser/out/index.js --workspacePath $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests "$@"
echo
echo "### TypeScript tests"
echo
node test/integration/browser/out/index.js --workspacePath $ROOT/extensions/typescript-language-features/test-workspace --extensionDevelopmentPath=$ROOT/extensions/typescript-language-features --extensionTestsPath=$ROOT/extensions/typescript-language-features/out/test/unit "$@"
echo
echo "### Markdown tests"
echo
node test/integration/browser/out/index.js --workspacePath $ROOT/extensions/markdown-language-features/test-workspace --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test "$@"
echo
echo "### Emmet tests"
echo
node test/integration/browser/out/index.js --workspacePath $ROOT/extensions/emmet/test-workspace --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test "$@"
echo
echo "### Git tests"
echo
node test/integration/browser/out/index.js --workspacePath $(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test "$@"
echo
echo "### Ipynb tests"
echo
node test/integration/browser/out/index.js --workspacePath $(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$ROOT/extensions/ipynb --extensionTestsPath=$ROOT/extensions/ipynb/out/test "$@"
echo
echo "### Configuration editing tests"
echo
node test/integration/browser/out/index.js --workspacePath $(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$ROOT/extensions/configuration-editing --extensionTestsPath=$ROOT/extensions/configuration-editing/out/test "$@"
+31
View File
@@ -0,0 +1,31 @@
@echo off
setlocal
set ELECTRON_RUN_AS_NODE=
pushd %~dp0\..
:: Get Code.exe location
for /f "tokens=2 delims=:," %%a in ('findstr /R /C:"\"nameShort\":.*" product.json') do set NAMESHORT=%%~a
set NAMESHORT=%NAMESHORT: "=%
set NAMESHORT=%NAMESHORT:"=%.exe
set CODE=".build\electron\%NAMESHORT%"
:: Download Electron if needed
call node build\lib\electron.js
if %errorlevel% neq 0 node .\node_modules\gulp\bin\gulp.js electron
:: Run tests
set ELECTRON_ENABLE_LOGGING=1
%CODE% .\test\unit\electron\index.js --crash-reporter-directory=%~dp0\..\.build\crashes %*
popd
endlocal
:: app.exit(0) is exiting with code 255 in Electron 1.7.4.
:: See https://github.com/microsoft/vscode/issues/28582
echo errorlevel: %errorlevel%
if %errorlevel% == 255 set errorlevel=0
exit /b %errorlevel%
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
# --disable-dev-shm-usage: when run on docker containers where size of /dev/shm
# partition < 64MB which causes OOM failure for chromium compositor that uses the partition for shared memory
LINUX_EXTRA_ARGS="--disable-dev-shm-usage"
fi
cd $ROOT
if [[ "$OSTYPE" == "darwin"* ]]; then
NAME=`node -p "require('./product.json').nameLong"`
CODE="./.build/electron/$NAME.app/Contents/MacOS/Electron"
else
NAME=`node -p "require('./product.json').applicationName"`
CODE=".build/electron/$NAME"
fi
VSCODECRASHDIR=$ROOT/.build/crashes
# Node modules
test -d node_modules || npm i
# Get electron
npm run electron
# Unit Tests
if [[ "$OSTYPE" == "darwin"* ]]; then
cd $ROOT ; ulimit -n 4096 ; \
ELECTRON_ENABLE_LOGGING=1 \
"$CODE" \
test/unit/electron/index.js --crash-reporter-directory=$VSCODECRASHDIR "$@"
else
cd $ROOT ; \
ELECTRON_ENABLE_LOGGING=1 \
"$CODE" \
test/unit/electron/index.js --crash-reporter-directory=$VSCODECRASHDIR $LINUX_EXTRA_ARGS "$@"
fi
+34
View File
@@ -0,0 +1,34 @@
<#
.SYNOPSIS
Symlinks ./node_modules/xterm to provided $XtermFolder.
#>
Param(
[Parameter(Mandatory=$True)]
$XtermFolder
)
$TargetFolder = "./node_modules/@xterm/xterm"
if (Test-Path $TargetFolder -PathType Container)
{
Write-Host -ForegroundColor Green ":: Deleting $TargetFolder`n"
Remove-Item -Path $TargetFolder
}
if (Test-Path $XtermFolder -PathType Container)
{
Write-Host -ForegroundColor Green "`n:: Creating symlink $TargetFolder -> $XtermFolder`n"
New-Item -Path $TargetFolder -ItemType SymbolicLink -Value $XtermFolder
Write-Host -ForegroundColor Green "`n:: Packaging xterm.js`n"
Set-Location $TargetFolder
yarn package -- --mode development
Set-Location -
Write-Host -ForegroundColor Green "`n:: Finished! To watch changes, open the VS Code terminal in the xterm.js repo and run:`n`n yarn package -- --mode development --watch"
}
else
{
Write-Error -ForegroundColor Red "`n:: $XtermFolder is not a valid folder"
}
+101
View File
@@ -0,0 +1,101 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const cp = require('child_process');
const path = require('path');
const moduleNames = [
'@xterm/xterm',
'@xterm/addon-clipboard',
'@xterm/addon-image',
'@xterm/addon-ligatures',
'@xterm/addon-progress',
'@xterm/addon-search',
'@xterm/addon-serialize',
'@xterm/addon-unicode11',
'@xterm/addon-webgl',
];
const backendOnlyModuleNames = [
'@xterm/headless'
];
const vscodeDir = process.argv.length >= 3 ? process.argv[2] : process.cwd();
if (path.basename(vscodeDir) !== 'vscode') {
console.error('The cwd is not named "vscode"');
return;
}
function getLatestModuleVersion(moduleName) {
return new Promise((resolve, reject) => {
cp.exec(`npm view ${moduleName} versions --json`, { cwd: vscodeDir }, (err, stdout, stderr) => {
if (err) {
reject(err);
}
let versions = JSON.parse(stdout);
// Fix format if there is only a single version published
if (typeof versions === 'string') {
versions = [versions];
}
resolve(versions[versions.length - 1]);
});
});
}
async function update() {
console.log('Fetching latest versions');
const allModules = moduleNames.concat(backendOnlyModuleNames);
const versionPromises = [];
for (const m of allModules) {
versionPromises.push(getLatestModuleVersion(m));
}
const latestVersionsArray = await Promise.all(versionPromises);
const latestVersions = {};
for (const [i, v] of latestVersionsArray.entries()) {
latestVersions[allModules[i]] = v;
}
console.log('Detected versions:');
for (const m of moduleNames.concat(backendOnlyModuleNames)) {
console.log(` ${m}@${latestVersions[m]}`);
}
const pkg = require(path.join(vscodeDir, 'package.json'));
const modulesWithVersion = [];
for (const m of moduleNames) {
const moduleWithVersion = `${m}@${latestVersions[m]}`;
if (pkg.dependencies[m] === latestVersions[m]) {
console.log(`Skipping ${moduleWithVersion}, already up to date`);
continue;
}
modulesWithVersion.push(moduleWithVersion);
}
if (modulesWithVersion.length > 0) {
for (const cwd of [vscodeDir, path.join(vscodeDir, 'remote'), path.join(vscodeDir, 'remote/web')]) {
console.log(`${path.join(cwd, 'package.json')}: Updating\n ${modulesWithVersion.join('\n ')}`);
cp.execSync(`npm install ${modulesWithVersion.join(' ')}`, { cwd });
}
}
const backendOnlyModulesWithVersion = [];
for (const m of backendOnlyModuleNames) {
const moduleWithVersion = `${m}@${latestVersions[m]}`;
if (pkg.dependencies[m] === latestVersions[m]) {
console.log(`Skipping ${moduleWithVersion}, already up to date`);
continue;
}
backendOnlyModulesWithVersion.push(moduleWithVersion);
}
if (backendOnlyModulesWithVersion.length > 0) {
for (const cwd of [vscodeDir, path.join(vscodeDir, 'remote')]) {
console.log(`${path.join(cwd, 'package.json')}: Updating\n ${backendOnlyModulesWithVersion.join('\n ')}`);
cp.execSync(`npm install ${backendOnlyModulesWithVersion.join(' ')}`, { cwd });
}
}
}
update();
+2
View File
@@ -0,0 +1,2 @@
$scriptPath = Join-Path $PSScriptRoot "xterm-update.js"
node $scriptPath (Get-Location)