Compare commits

..

No commits in common. "main" and "v4.104.2" have entirely different histories.

33 changed files with 390 additions and 398 deletions

View file

@ -86,18 +86,6 @@ body:
validations:
required: true
- type: dropdown
attributes:
label: Does this bug reproduce in VS Code web?
description: If the bug reproduces in VS Code web, submit the issue upstream instead (https://github.com/microsoft/vscode). You can run VS Code web with `code serve-web`.
options:
- Yes, this is also broken in VS Code web
- No, this works as expected in VS Code web
- This cannot be tested in VS Code web
- I did not test VS Code web
validations:
required: true
- type: dropdown
attributes:
label: Does this bug reproduce in GitHub Codespaces?

View file

@ -32,7 +32,7 @@ jobs:
helm: ${{ steps.filter.outputs.helm }}
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Check changed files
uses: dorny/paths-filter@v3
id: filter
@ -64,8 +64,8 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -82,8 +82,8 @@ jobs:
needs: changes
if: needs.changes.outputs.docs == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -100,7 +100,7 @@ jobs:
needs: changes
if: needs.changes.outputs.helm == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
@ -114,8 +114,8 @@ jobs:
needs: changes
if: needs.changes.outputs.code == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -132,11 +132,11 @@ jobs:
if: needs.changes.outputs.ci == 'true'
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Check workflow files
run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
./actionlint -color -shellcheck= -ignore "softprops/action-gh-release"
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.1
./actionlint -color -shellcheck= -ignore "set-output"
shell: bash
test-unit:
@ -146,8 +146,8 @@ jobs:
needs: changes
if: needs.changes.outputs.code == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -164,12 +164,12 @@ jobs:
build:
name: Build code-server
runs-on: ubuntu-22.04
timeout-minutes: 70
timeout-minutes: 60
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
DISABLE_V8_COMPILE_CACHE: 1
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
submodules: true
- run: sudo apt update && sudo apt install -y libkrb5-dev
@ -178,7 +178,7 @@ jobs:
packages: quilt
version: 1.0
- run: quilt push -a
- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -231,9 +231,9 @@ jobs:
needs: [changes, build]
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -241,7 +241,7 @@ jobs:
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- uses: actions/download-artifact@v5
- uses: actions/download-artifact@v4
with:
name: npm-package
- run: tar -xzf package.tar.gz
@ -265,9 +265,9 @@ jobs:
needs: [changes, build]
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: actions/setup-node@v6
- uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -275,7 +275,7 @@ jobs:
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- uses: actions/download-artifact@v5
- uses: actions/download-artifact@v4
with:
name: npm-package
- run: tar -xzf package.tar.gz

View file

@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install code-server
run: ./install.sh
@ -44,7 +44,7 @@ jobs:
container: "alpine:3.17"
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install curl
run: apk add curl
@ -67,7 +67,7 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install code-server
run: ./install.sh

View file

@ -25,10 +25,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code-server
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
@ -53,6 +53,38 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_ENVIRONMENT: "production"
homebrew:
needs: npm
runs-on: ubuntu-latest
steps:
# Ensure things are up to date
# Suggested by homebrew maintainers
# https://github.com/Homebrew/discussions/discussions/1532#discussioncomment-782633
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Checkout code-server
uses: actions/checkout@v4
- name: Configure git
run: |
git config --global user.name cdrci
git config --global user.email opensource@coder.com
# Strip out the v (v4.9.1 -> 4.9.1).
- name: Get and set VERSION
run: |
TAG="${{ github.event.inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Bump code-server homebrew version
env:
VERSION: ${{ env.VERSION }}
HOMEBREW_GITHUB_API_TOKEN: ${{secrets.HOMEBREW_GITHUB_API_TOKEN}}
run: ./ci/steps/brew-bump.sh
aur:
runs-on: ubuntu-latest
timeout-minutes: 10
@ -62,13 +94,13 @@ jobs:
steps:
# We need to checkout code-server so we can get the version
- name: Checkout code-server
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
path: "./code-server"
- name: Checkout code-server-aur repo
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
repository: "cdrci/code-server-aur"
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
@ -116,7 +148,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code-server
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

View file

@ -60,10 +60,10 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -94,7 +94,7 @@ jobs:
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Download npm package
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: npm-release-package
@ -126,7 +126,7 @@ jobs:
package-macos-amd64:
name: x86-64 macOS build
runs-on: macos-15-intel
runs-on: macos-13
timeout-minutes: 15
needs: npm-version
env:
@ -134,10 +134,10 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -160,7 +160,7 @@ jobs:
- run: brew install python-setuptools
- name: Download npm package
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: npm-release-package
@ -195,10 +195,10 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
@ -221,7 +221,7 @@ jobs:
- run: brew install python-setuptools
- name: Download npm package
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: npm-release-package
@ -253,7 +253,7 @@ jobs:
needs: npm-version
steps:
- name: Download npm package
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: npm-release-package

View file

@ -41,7 +41,7 @@ jobs:
container: "alpine:3.17"
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install test utilities
run: apk add bats checkbashisms
@ -58,7 +58,7 @@ jobs:
timeout-minutes: 5
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install lint utilities
run: sudo apt install shellcheck

View file

@ -25,12 +25,12 @@ jobs:
timeout-minutes: 15
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
@ -46,12 +46,12 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4
with:
scan-type: "fs"
scan-ref: "."
@ -76,7 +76,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View file

@ -48,10 +48,10 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner in image mode
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4
with:
image-ref: "docker.io/codercom/code-server:latest"
ignore-unfixed: true

View file

@ -1 +1 @@
22.20.0
22.18.0

View file

@ -22,22 +22,6 @@ Code v99.99.999
## Unreleased
## [4.104.2](https://github.com/coder/code-server/releases/tag/v4.104.2) - 2025-09-26
Code v1.104.2
### Changed
- Update to Code 1.104.2.
## [4.104.1](https://github.com/coder/code-server/releases/tag/v4.104.1) - 2025-09-19
Code v1.104.1
### Changed
- Update to Code 1.104.1.
## [4.104.0](https://github.com/coder/code-server/releases/tag/v4.104.0) - 2025-09-15
Code v1.104.0

View file

@ -15,9 +15,9 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.31.2
version: 3.31.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.104.2
appVersion: 4.104.0

View file

@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.104.2'
tag: '4.104.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a

View file

@ -31,7 +31,6 @@
- [What's the difference between code-server and Theia?](#whats-the-difference-between-code-server-and-theia)
- [What's the difference between code-server and OpenVSCode-Server?](#whats-the-difference-between-code-server-and-openvscode-server)
- [What's the difference between code-server and GitHub Codespaces?](#whats-the-difference-between-code-server-and-github-codespaces)
- [What's the difference between code-server and VS Code web?](#whats-the-difference-between-code-server-and-vs-code-web)
- [Does code-server have any security login validation?](#does-code-server-have-any-security-login-validation)
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
- [How do I change the port?](#how-do-i-change-the-port)
@ -323,8 +322,12 @@ As long as there is an active browser connection, code-server touches
`~/.local/share/code-server/heartbeat` once a minute.
If you want to shutdown code-server if there hasn't been an active connection
after a predetermined amount of time, you can use the --idle-timeout-seconds flag
or set an `CODE_SERVER_IDLE_TIMEOUT_SECONDS` environment variable.
after a predetermined amount of time, you can do so by checking continuously for
the last modified time on the heartbeat file. If it is older than X minutes (or
whatever amount of time you'd like), you can kill code-server.
Eventually, [#1636](https://github.com/coder/code-server/issues/1636) will make
this process better.
## How do I change the password?
@ -440,8 +443,6 @@ Specific changes include:
- The ability to use your own marketplace and collect your own telemetry
- Built-in proxy for accessing ports on the remote machine integrated into
VS Code's ports panel
- Settings are stored on disk like desktop VS Code, instead of in browser
storage (note that state is still stored in browser storage).
- Wrapper process that spawns VS Code on-demand and has a separate CLI
- Notification when updates are available
- [Some other things](https://github.com/coder/code-server/tree/main/patches)
@ -450,12 +451,6 @@ Some of these changes appear very unlikely to ever be adopted by Microsoft.
Some may make their way upstream, further closing the gap, but at the moment it
looks like there will always be some subtle differences.
## What's the difference between code-server and VS Code web?
VS Code web (which can be ran using `code serve-web`) has the same differences
as the Codespaces section above. VS Code web can be a better choice if you need
access to the official Microsoft marketplace.
## Does code-server have any security login validation?
code-server supports setting a single password and limits logins to two per

View file

@ -14,8 +14,8 @@ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
7. Install and use Node.js 22:
```shell
nvm install 22
nvm use 22
nvm install 18
nvm use 18
```
8. Install code-server globally on device with: `npm install --global code-server`

@ -1 +1 @@
Subproject commit bf9252a2fb45be6893dd8870c0bf37e2e1766d61
Subproject commit e3a5acfb517a443235981655413d566533107e92

320
package-lock.json generated
View file

@ -128,9 +128,9 @@
}
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
"integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -190,9 +190,9 @@
}
},
"node_modules/@eslint/config-helpers": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
"integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz",
"integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@ -200,9 +200,9 @@
}
},
"node_modules/@eslint/core": {
"version": "0.15.2",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
"integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
"integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@ -250,9 +250,9 @@
}
},
"node_modules/@eslint/js": {
"version": "9.36.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz",
"integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==",
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz",
"integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==",
"dev": true,
"license": "MIT",
"engines": {
@ -273,13 +273,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
"integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz",
"integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.15.2",
"@eslint/core": "^0.15.1",
"levn": "^0.4.1"
},
"engines": {
@ -610,14 +610,15 @@
"license": "MIT"
},
"node_modules/@types/express": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz",
"integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz",
"integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^5.0.0",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
@ -1639,18 +1640,18 @@
}
},
"node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.1.0.tgz",
"integrity": "sha512-/hPxh61E+ll0Ujp24Ilm64cykicul1ypfwjVttduAiEdtnJFvLePSrIPk+HMImtNv5270wOGCb1Tns2rybMkoQ==",
"license": "MIT",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.0",
"http-errors": "^2.0.0",
"iconv-lite": "^0.6.3",
"iconv-lite": "^0.5.2",
"on-finished": "^2.4.1",
"qs": "^6.14.0",
"qs": "6.14.0",
"raw-body": "^3.0.0",
"type-is": "^2.0.0"
},
@ -2149,6 +2150,16 @@
"node": ">= 0.8"
}
},
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
@ -2479,20 +2490,20 @@
}
},
"node_modules/eslint": {
"version": "9.36.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz",
"integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz",
"integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.21.0",
"@eslint/config-helpers": "^0.3.1",
"@eslint/core": "^0.15.2",
"@eslint/config-helpers": "^0.3.0",
"@eslint/core": "^0.15.0",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.36.0",
"@eslint/plugin-kit": "^0.3.5",
"@eslint/js": "9.32.0",
"@eslint/plugin-kit": "^0.3.4",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
@ -2892,45 +2903,55 @@
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"node_modules/express": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz",
"integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==",
"license": "MIT",
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.0",
"body-parser": "^2.0.1",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
"content-type": "~1.0.4",
"cookie": "0.7.1",
"cookie-signature": "^1.2.1",
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"finalhandler": "^2.1.0",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"debug": "4.3.6",
"depd": "2.0.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "^2.0.0",
"fresh": "2.0.0",
"http-errors": "2.0.0",
"merge-descriptors": "^2.0.0",
"methods": "~1.1.2",
"mime-types": "^3.0.0",
"on-finished": "^2.4.1",
"once": "^1.4.0",
"parseurl": "^1.3.3",
"proxy-addr": "^2.0.7",
"qs": "^6.14.0",
"range-parser": "^1.2.1",
"router": "^2.2.0",
"on-finished": "2.4.1",
"once": "1.4.0",
"parseurl": "~1.3.3",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"range-parser": "~1.2.1",
"router": "^2.0.0",
"safe-buffer": "5.2.1",
"send": "^1.1.0",
"serve-static": "^2.2.0",
"statuses": "^2.0.1",
"type-is": "^2.0.1",
"vary": "^1.1.2"
"serve-static": "^2.1.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "^2.0.0",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/cookie": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express/node_modules/cookie-signature": {
@ -2942,6 +2963,44 @@
"node": ">=6.6.0"
}
},
"node_modules/express/node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"license": "MIT",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/express/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"license": "MIT"
},
"node_modules/express/node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@ -3357,9 +3416,9 @@
}
},
"node_modules/globals": {
"version": "16.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
"integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
"version": "16.1.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
"dev": true,
"license": "MIT",
"engines": {
@ -3610,12 +3669,12 @@
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz",
"integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
@ -4421,6 +4480,15 @@
"node": ">= 8"
}
},
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/micromark": {
"version": "2.11.4",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz",
@ -4562,21 +4630,20 @@
}
},
"node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"version": "1.53.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz",
"integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz",
"integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
"mime-db": "^1.53.0"
},
"engines": {
"node": ">= 0.6"
@ -5053,13 +5120,12 @@
"dev": true
},
"node_modules/path-to-regexp": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
"integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
"integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
"engines": {
"node": ">=16"
}
},
"node_modules/pem": {
@ -5268,34 +5334,30 @@
}
},
"node_modules/raw-body": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz",
"integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.7.0",
"iconv-lite": "0.6.3",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.10"
"node": ">= 0.8"
}
},
"node_modules/raw-body/node_modules/iconv-lite": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
"integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==",
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/readable-stream": {
@ -5473,13 +5535,11 @@
}
},
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.1.0.tgz",
"integrity": "sha512-/m/NSLxeYEgWNtyC+WtNHCF7jbGxOibVWKnn+1Psff4dJGOfoXP+MuC/f2CwSmyiHdOIzYnYFp4W6GxWfekaLA==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.0",
"depd": "^2.0.0",
"is-promise": "^4.0.0",
"parseurl": "^1.3.3",
"path-to-regexp": "^8.0.0"
@ -5593,18 +5653,19 @@
}
},
"node_modules/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.1.0.tgz",
"integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.5",
"destroy": "^1.2.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"fresh": "^0.5.2",
"http-errors": "^2.0.0",
"mime-types": "^3.0.1",
"mime-types": "^2.1.35",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
@ -5614,16 +5675,46 @@
"node": ">= 18"
}
},
"node_modules/send/node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/send/node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/send/node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-static": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.1.0.tgz",
"integrity": "sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==",
"license": "MIT",
"dependencies": {
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"parseurl": "^1.3.3",
"send": "^1.2.0"
"send": "^1.0.0"
},
"engines": {
"node": ">= 18"
@ -6216,9 +6307,9 @@
}
},
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz",
"integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==",
"license": "MIT",
"dependencies": {
"content-type": "^1.0.5",
@ -6530,6 +6621,15 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",

View file

@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
+++ code-server/lib/vscode/src/vs/base/common/network.ts
@@ -237,7 +237,9 @@ class RemoteAuthoritiesImpl {
@@ -232,7 +232,9 @@ class RemoteAuthoritiesImpl {
return URI.from({
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
authority: `${host}:${port}`,
@ -99,14 +99,14 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactor
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
+++ code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
@@ -282,6 +282,7 @@ export class BrowserSocketFactory implem
@@ -281,6 +281,7 @@ export class BrowserSocketFactory implem
connect({ host, port }: WebSocketRemoteConnection, path: string, query: string, debugLabel: string): Promise<ISocket> {
return new Promise<ISocket>((resolve, reject) => {
const webSocketSchema = (/^https:/.test(mainWindow.location.href) ? 'wss' : 'ws');
+ path = (mainWindow.location.pathname + "/" + path).replace(/\/\/+/g, "/")
const socket = this._webSocketFactory.create(`${webSocketSchema}://${(/:/.test(host) && !/\[/.test(host)) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
const disposables = new DisposableStore();
disposables.add(socket.onError(reject));
const errorListener = socket.onError(reject);
socket.onOpen(() => {
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
@ -253,7 +253,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
@@ -339,7 +339,8 @@ class LocalStorageURLCallbackProvider ex
@@ -338,7 +338,8 @@ class LocalStorageURLCallbackProvider ex
this.startListening();
}
@ -263,7 +263,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
}
private startListening(): void {
@@ -584,17 +585,6 @@ class WorkspaceProvider implements IWork
@@ -583,17 +584,6 @@ class WorkspaceProvider implements IWork
}
}
@ -281,7 +281,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
(function () {
// Find config by checking for DOM
@@ -604,8 +594,8 @@ function readCookie(name: string): strin
@@ -602,8 +592,8 @@ function readCookie(name: string): strin
if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element');
}

View file

@ -17,7 +17,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTe
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
@@ -107,10 +107,14 @@ class RemoteTerminalBackend extends Base
@@ -106,10 +106,14 @@ class RemoteTerminalBackend extends Base
}
const reqId = e.reqId;
const commandId = e.commandId;

View file

@ -65,7 +65,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTe
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
@@ -98,7 +98,7 @@ class RemoteTerminalBackend extends Base
@@ -97,7 +97,7 @@ class RemoteTerminalBackend extends Base
}
});
@ -78,7 +78,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
@@ -137,6 +137,7 @@ export interface NativeParsedArgs {
@@ -135,6 +135,7 @@ export interface NativeParsedArgs {
'disable-chromium-sandbox'?: boolean;
sandbox?: boolean;
'enable-coi'?: boolean;
@ -90,7 +90,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/node/argv.ts
+++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
@@ -105,6 +105,7 @@ export const OPTIONS: OptionDescriptions
@@ -104,6 +104,7 @@ export const OPTIONS: OptionDescriptions
'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") },
'profile': { type: 'string', 'cat': 'o', args: 'profileName', description: localize('profileName', "Opens the provided folder or workspace with the given profile and associates the profile with the workspace. If the profile does not exist, a new empty one is created.") },
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },

View file

@ -125,12 +125,13 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -6,10 +6,10 @@
import { Disposable } from '../../base/common/lifecycle.js';
@@ -7,11 +7,11 @@ import { Event } from '../../base/common
import { Disposable, DisposableStore, MutableDisposable } from '../../base/common/lifecycle.js';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext, IsSimulationContext } from '../../platform/contextkey/common/contextkeys.js';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext } from '../common/contextkeys.js';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow, isEditableElement } from '../../base/browser/dom.js';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
-import { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';
@ -138,7 +139,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from '../../platform/workspace/common/workspace.js';
import { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.js';
import { getRemoteName } from '../../platform/remote/common/remoteHosts.js';
@@ -69,7 +69,7 @@ export class WorkbenchContextKeysHandler
@@ -72,7 +72,7 @@ export class WorkbenchContextKeysHandler
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ -147,7 +148,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@IProductService private readonly productService: IProductService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IEditorService private readonly editorService: IEditorService,
@@ -199,6 +199,10 @@ export class WorkbenchContextKeysHandler
@@ -208,6 +208,10 @@ export class WorkbenchContextKeysHandler
this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService);
this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized());
@ -239,8 +240,8 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
@IPathService protected readonly pathService: IPathService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@@ -311,20 +311,22 @@ export class SimpleFileDialog extends Di
this.filePickBox.placeholder = nls.localize('remoteFileDialog.placeholder', "Folder path");
@@ -310,20 +310,22 @@ export class SimpleFileDialog extends Di
this.filePickBox.ignoreFocusOut = true;
this.filePickBox.ok = true;
this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic;
- if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
@ -288,7 +289,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
import { WorkbenchCompressibleAsyncDataTree } from '../../../../../platform/list/browser/listService.js';
import { ISearchService, QueryType, getExcludes, ISearchConfiguration, ISearchComplete, IFileQuery } from '../../../../services/search/common/search.js';
import { CancellationToken } from '../../../../../base/common/cancellation.js';
@@ -1594,7 +1595,8 @@ export class FileDragAndDrop implements
@@ -1601,7 +1602,8 @@ export class FileDragAndDrop implements
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@ -298,7 +299,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
) {
const updateDropEnablement = (e: IConfigurationChangeEvent | undefined) => {
if (!e || e.affectsConfiguration('explorer.enableDragAndDrop')) {
@@ -1819,15 +1821,17 @@ export class FileDragAndDrop implements
@@ -1826,15 +1828,17 @@ export class FileDragAndDrop implements
// External file DND (Import/Upload file)
if (data instanceof NativeDragAndDropData) {

View file

@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
import { renderFormattedText } from '../../../../base/browser/formattedTextRenderer.js';
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
import { Button } from '../../../../base/browser/ui/button/button.js';
@@ -53,7 +53,7 @@ import { IRecentFolder, IRecentWorkspace
@@ -54,7 +54,7 @@ import { IRecentFolder, IRecentWorkspace
import { OpenRecentAction } from '../../../browser/actions/windowActions.js';
import { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from '../../../browser/actions/workspaceActions.js';
import { EditorPane } from '../../../browser/parts/editor/editorPane.js';
@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js';
import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
import './gettingStartedColors.js';
@@ -902,6 +902,72 @@ export class GettingStartedPage extends
@@ -872,6 +872,72 @@ export class GettingStartedPage extends
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
);
@ -101,7 +101,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
const leftColumn = $('.categories-column.categories-column-left', {},);
const rightColumn = $('.categories-column.categories-column-right', {},);
@@ -937,6 +1003,9 @@ export class GettingStartedPage extends
@@ -907,6 +973,9 @@ export class GettingStartedPage extends
recentList.setLimit(5);
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
}
@ -213,16 +213,16 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -6,7 +6,7 @@
import { Disposable } from '../../base/common/lifecycle.js';
@@ -7,7 +7,7 @@ import { Event } from '../../base/common
import { Disposable, DisposableStore, MutableDisposable } from '../../base/common/lifecycle.js';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext, IsSimulationContext } from '../../platform/contextkey/common/contextkeys.js';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from '../common/contextkeys.js';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow, isEditableElement } from '../../base/browser/dom.js';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js';
@@ -202,6 +202,7 @@ export class WorkbenchContextKeysHandler
@@ -211,6 +211,7 @@ export class WorkbenchContextKeysHandler
// code-server
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)

View file

@ -265,7 +265,7 @@ Index: code-server/lib/vscode/src/server-main.ts
+++ code-server/lib/vscode/src/server-main.ts
@@ -22,6 +22,9 @@ import { IServerAPI } from './vs/server/
perf.mark('code/server/start');
(globalThis as { vscodeServerStartTime?: number }).vscodeServerStartTime = performance.now();
(globalThis as any).vscodeServerStartTime = performance.now();
+// This is not indented to make the diff less noisy. We need to move this out
+// of the top-level so it will not run immediately and we can control the start.
@ -279,7 +279,7 @@ Index: code-server/lib/vscode/src/server-main.ts
}
+}
function sanitizeStringArg(val: unknown): string | undefined {
function sanitizeStringArg(val: any): string | undefined {
if (Array.isArray(val)) { // if an argument is passed multiple times, minimist creates an array
@@ -283,3 +287,22 @@ function prompt(question: string): Promi
});

View file

@ -32,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -298,6 +298,11 @@ export interface IWorkbenchConstructionO
*/
readonly configurationDefaults?: Record<string, unknown>;
readonly configurationDefaults?: Record<string, any>;
+ /**
+ * Path to the user data directory.
@ -79,7 +79,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co
});
}));
@@ -556,6 +558,12 @@ export class WorkspaceService extends Di
@@ -555,6 +557,12 @@ export class WorkspaceService extends Di
previousFolders = this.workspace.folders;
this.workspace.update(workspace);
} else {

View file

@ -83,7 +83,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalE
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
@@ -292,7 +292,7 @@ export async function createTerminalEnvi
@@ -291,7 +291,7 @@ export async function createTerminalEnvi
// Sanitize the environment, removing any undesirable VS Code and Electron environment
// variables
@ -104,7 +104,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
import { create } from '../../../workbench/workbench.web.main.internal.js';
@@ -606,6 +607,39 @@ class WorkspaceProvider implements IWork
@@ -604,6 +605,39 @@ class WorkspaceProvider implements IWork
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),

View file

@ -96,7 +96,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
import minimist from 'minimist';
import * as nativeWatchdog from 'native-watchdog';
import * as net from 'net';
@@ -451,7 +452,28 @@ async function startExtensionHostProcess
@@ -449,7 +450,28 @@ async function startExtensionHostProcess
);
// rewrite onTerminate-function to be a proper shutdown

View file

@ -94,7 +94,6 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
"welcome-text"?: string
"abs-proxy-base-path"?: string
i18n?: string
"idle-timeout-seconds"?: number
/* Positional arguments. */
_?: string[]
}
@ -304,10 +303,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
path: true,
description: "Path to JSON file with custom translations. Merges with default strings and supports all i18n keys.",
},
"idle-timeout-seconds": {
type: "number",
description: "Timeout in seconds to wait before shutting down when idle.",
},
}
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
@ -401,10 +396,6 @@ export const parse = (
throw new Error("--github-auth can only be set in the config file or passed in via $GITHUB_TOKEN")
}
if (key === "idle-timeout-seconds" && Number(value) <= 60) {
throw new Error("--idle-timeout-seconds must be greater than 60 seconds.")
}
const option = options[key]
if (option.type === "boolean") {
;(args[key] as boolean) = true
@ -620,16 +611,6 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args["github-auth"] = process.env.GITHUB_TOKEN
}
if (process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS) {
if (isNaN(Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS))) {
logger.info("CODE_SERVER_IDLE_TIMEOUT_SECONDS must be a number")
}
if (Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS) <= 60) {
throw new Error("--idle-timeout-seconds must be greater than 60 seconds.")
}
args["idle-timeout-seconds"] = Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS)
}
// Ensure they're not readable by child processes.
delete process.env.PASSWORD
delete process.env.HASHED_PASSWORD

View file

@ -1,6 +1,5 @@
import { logger } from "@coder/logger"
import { promises as fs } from "fs"
import { Emitter } from "../common/emitter"
/**
* Provides a heartbeat using a local file to indicate activity.
@ -9,9 +8,6 @@ export class Heart {
private heartbeatTimer?: NodeJS.Timeout
private heartbeatInterval = 60000
public lastHeartbeat = 0
private readonly _onChange = new Emitter<"alive" | "expired" | "unknown">()
readonly onChange = this._onChange.event
private state: "alive" | "expired" | "unknown" = "expired"
public constructor(
private readonly heartbeatPath: string,
@ -21,13 +17,6 @@ export class Heart {
this.alive = this.alive.bind(this)
}
private setState(state: typeof this.state) {
if (this.state !== state) {
this.state = state
this._onChange.emit(this.state)
}
}
public alive(): boolean {
const now = Date.now()
return now - this.lastHeartbeat < this.heartbeatInterval
@ -39,7 +28,6 @@ export class Heart {
*/
public async beat(): Promise<void> {
if (this.alive()) {
this.setState("alive")
return
}
@ -48,22 +36,7 @@ export class Heart {
if (typeof this.heartbeatTimer !== "undefined") {
clearTimeout(this.heartbeatTimer)
}
this.heartbeatTimer = setTimeout(async () => {
try {
if (await this.isActive()) {
this.beat()
} else {
this.setState("expired")
}
} catch (error: unknown) {
logger.warn((error as Error).message)
this.setState("unknown")
}
}, this.heartbeatInterval)
this.setState("alive")
this.heartbeatTimer = setTimeout(() => heartbeatTimer(this.isActive, this.beat), this.heartbeatInterval)
try {
return await fs.writeFile(this.heartbeatPath, "")
} catch (error: any) {
@ -80,3 +53,20 @@ export class Heart {
}
}
}
/**
* Helper function for the heartbeatTimer.
*
* If heartbeat is active, call beat. Otherwise do nothing.
*
* Extracted to make it easier to test.
*/
export async function heartbeatTimer(isActive: Heart["isActive"], beat: Heart["beat"]) {
try {
if (await isActive()) {
beat()
}
} catch (error: unknown) {
logger.warn((error as Error).message)
}
}

View file

@ -11,7 +11,6 @@ import { loadCustomStrings } from "./i18n"
import { register } from "./routes"
import { VSCodeModule } from "./routes/vscode"
import { isDirectory, open } from "./util"
import { wrapper } from "./wrapper"
/**
* Return true if the user passed an extension-related VS Code flag.
@ -142,7 +141,7 @@ export const runCodeServer = async (
const app = await createApp(args)
const protocol = args.cert ? "https" : "http"
const serverAddress = ensureAddress(app.server, protocol)
const { disposeRoutes, heart } = await register(app, args)
const disposeRoutes = await register(app, args)
logger.info(`Using config file ${args.config}`)
logger.info(`${protocol.toUpperCase()} server listening on ${serverAddress.toString()}`)
@ -167,27 +166,6 @@ export const runCodeServer = async (
logger.info(" - Not serving HTTPS")
}
if (args["idle-timeout-seconds"]) {
logger.info(` - Idle timeout set to ${args["idle-timeout-seconds"]} seconds`)
let idleShutdownTimer: NodeJS.Timeout | undefined
const startIdleShutdownTimer = () => {
idleShutdownTimer = setTimeout(() => {
logger.warn(`Idle timeout of ${args["idle-timeout-seconds"]} seconds exceeded`)
wrapper.exit(0)
}, args["idle-timeout-seconds"]! * 1000)
}
startIdleShutdownTimer()
heart.onChange((state) => {
clearTimeout(idleShutdownTimer)
if (state === "expired") {
startIdleShutdownTimer()
}
})
}
if (args["disable-proxy"]) {
logger.info(" - Proxy disabled")
} else if (args["proxy-domain"].length > 0) {

View file

@ -28,10 +28,7 @@ import * as vscode from "./vscode"
/**
* Register all routes and middleware.
*/
export const register = async (
app: App,
args: DefaultedArgs,
): Promise<{ disposeRoutes: Disposable["dispose"]; heart: Heart }> => {
export const register = async (app: App, args: DefaultedArgs): Promise<Disposable["dispose"]> => {
const heart = new Heart(path.join(paths.data, "heartbeat"), async () => {
return new Promise((resolve, reject) => {
// getConnections appears to not call the callback when there are no more
@ -176,11 +173,8 @@ export const register = async (
app.router.use(errorHandler)
app.wsRouter.use(wsErrorHandler)
return {
disposeRoutes: () => {
heart.dispose()
vscode.dispose()
},
heart,
return () => {
heart.dispose()
vscode.dispose()
}
}

26
test/package-lock.json generated
View file

@ -7,7 +7,7 @@
"license": "MIT",
"devDependencies": {
"@jest-mock/express": "^1.4.5",
"@playwright/test": "^1.56.1",
"@playwright/test": "^1.46.0",
"@types/jest": "^27.0.2",
"@types/jsdom": "^16.2.13",
"@types/node-fetch": "^2.5.8",
@ -18,7 +18,7 @@
"jest-fetch-mock": "^3.0.3",
"jsdom": "^16.4.0",
"node-fetch": "^2.6.7",
"playwright": "^1.56.1",
"playwright": "^1.46.0",
"ts-jest": "^27.0.7",
"wtfnode": "^0.9.1"
}
@ -1012,13 +1012,13 @@
}
},
"node_modules/@playwright/test": {
"version": "1.56.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz",
"integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
"version": "1.47.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz",
"integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.56.1"
"playwright": "1.47.2"
},
"bin": {
"playwright": "cli.js"
@ -4305,13 +4305,13 @@
}
},
"node_modules/playwright": {
"version": "1.56.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz",
"integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==",
"version": "1.47.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz",
"integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.56.1"
"playwright-core": "1.47.2"
},
"bin": {
"playwright": "cli.js"
@ -4324,9 +4324,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.56.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
"integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
"version": "1.47.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz",
"integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View file

@ -3,7 +3,7 @@
"#": "We must put jest in a sub-directory otherwise VS Code somehow picks up the types and generates conflicts with mocha.",
"devDependencies": {
"@jest-mock/express": "^1.4.5",
"@playwright/test": "^1.56.1",
"@playwright/test": "^1.46.0",
"@types/jest": "^27.0.2",
"@types/jsdom": "^16.2.13",
"@types/node-fetch": "^2.5.8",
@ -14,7 +14,7 @@
"jest-fetch-mock": "^3.0.3",
"jsdom": "^16.4.0",
"node-fetch": "^2.6.7",
"playwright": "^1.56.1",
"playwright": "^1.46.0",
"ts-jest": "^27.0.7",
"wtfnode": "^0.9.1"
},

View file

@ -1,6 +1,6 @@
import { logger } from "@coder/logger"
import { readFile, writeFile, stat, utimes } from "fs/promises"
import { Heart } from "../../../src/node/heart"
import { Heart, heartbeatTimer } from "../../../src/node/heart"
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
const mockIsActive = (resolveTo: boolean) => jest.fn().mockResolvedValue(resolveTo)
@ -82,81 +82,31 @@ describe("Heart", () => {
})
describe("heartbeatTimer", () => {
const testName = "heartbeatTimer"
let testDir = ""
beforeAll(async () => {
await clean(testName)
testDir = await tmpdir(testName)
beforeAll(() => {
mockLogger()
})
afterAll(() => {
jest.restoreAllMocks()
})
beforeEach(() => {
jest.useFakeTimers()
})
afterEach(() => {
jest.resetAllMocks()
jest.clearAllTimers()
jest.useRealTimers()
})
it("should call isActive when timeout expires", async () => {
it("should call beat when isActive resolves to true", async () => {
const isActive = true
const mockIsActive = jest.fn().mockResolvedValue(isActive)
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
await heart.beat()
jest.advanceTimersByTime(60 * 1000)
const mockBeatFn = jest.fn()
await heartbeatTimer(mockIsActive, mockBeatFn)
expect(mockIsActive).toHaveBeenCalled()
expect(mockBeatFn).toHaveBeenCalled()
})
it("should log a warning when isActive rejects", async () => {
const errorMsg = "oh no"
const error = new Error(errorMsg)
const mockIsActive = jest.fn().mockRejectedValue(error)
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
await heart.beat()
jest.advanceTimersByTime(60 * 1000)
const mockBeatFn = jest.fn()
await heartbeatTimer(mockIsActive, mockBeatFn)
expect(mockIsActive).toHaveBeenCalled()
expect(mockBeatFn).not.toHaveBeenCalled()
expect(logger.warn).toHaveBeenCalledWith(errorMsg)
})
})
describe("stateChange", () => {
const testName = "stateChange"
let testDir = ""
let heart: Heart
beforeAll(async () => {
await clean(testName)
testDir = await tmpdir(testName)
mockLogger()
})
afterAll(() => {
jest.restoreAllMocks()
})
afterEach(() => {
jest.resetAllMocks()
if (heart) {
heart.dispose()
}
})
it("should change to alive after a beat", async () => {
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
const mockOnChange = jest.fn()
heart.onChange(mockOnChange)
await heart.beat()
expect(mockOnChange.mock.calls[0][0]).toBe("alive")
})
it.only("should change to expired when not active", async () => {
jest.useFakeTimers()
heart = new Heart(`${testDir}/shutdown.txt`, () => new Promise((resolve) => resolve(false)))
const mockOnChange = jest.fn()
heart.onChange(mockOnChange)
await heart.beat()
await jest.advanceTimersByTime(60 * 1000)
expect(mockOnChange.mock.calls[1][0]).toBe("expired")
jest.clearAllTimers()
jest.useRealTimers()
})
})

View file

@ -16,7 +16,6 @@ jest.mock("@coder/logger", () => ({
debug: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
named: jest.fn(),
level: 0,
},
field: jest.fn(),
@ -95,7 +94,7 @@ describe("main", () => {
// Mock routes module
jest.doMock("../../../src/node/routes", () => ({
register: jest.fn().mockResolvedValue({ disposeRoutes: jest.fn() }),
register: jest.fn().mockResolvedValue(jest.fn()),
}))
// Mock loadCustomStrings to succeed
@ -132,7 +131,7 @@ describe("main", () => {
// Mock routes module
jest.doMock("../../../src/node/routes", () => ({
register: jest.fn().mockResolvedValue({ disposeRoutes: jest.fn() }),
register: jest.fn().mockResolvedValue(jest.fn()),
}))
// Import runCodeServer after mocking