Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
abba93bd8e Bump @eslint/compat from 1.4.1 to 2.1.1
Bumps [@eslint/compat](https://github.com/eslint/rewrite/tree/HEAD/packages/compat) from 1.4.1 to 2.1.1.
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/packages/compat/CHANGELOG.md)
- [Commits](https://github.com/eslint/rewrite/commits/compat-v2.1.1/packages/compat)

---
updated-dependencies:
- dependency-name: "@eslint/compat"
  dependency-version: 2.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-27 19:54:16 +00:00
34 changed files with 146 additions and 687 deletions

View File

@@ -9,10 +9,6 @@ updates:
cooldown:
default-days: 7
labels: []
groups:
codeql-action:
patterns:
- "github/codeql-action/*"
- package-ecosystem: "npm"
directory: "/"

View File

@@ -58,7 +58,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -75,7 +75,7 @@ jobs:
if: needs.changes.outputs.docs == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -104,7 +104,7 @@ jobs:
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.ci == 'true' || needs.changes.outputs.npm == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -135,7 +135,7 @@ jobs:
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -173,7 +173,7 @@ jobs:
with:
submodules: true
- run: quilt push -a
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -217,7 +217,7 @@ jobs:
# Push up an artifact containing the linux-x64 release.
- run: KEEP_MODULES=1 npm run release
- run: tar -czf package.tar.gz release
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: linux-x64-package
path: ./package.tar.gz
@@ -232,7 +232,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -245,13 +245,13 @@ jobs:
./test/node_modules/.bin/playwright install-deps
./test/node_modules/.bin/playwright install
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: linux-x64-package
- run: tar -xzf package.tar.gz
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: always()
with:
name: failed-test-videos
@@ -282,7 +282,7 @@ jobs:
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -295,7 +295,7 @@ jobs:
./test/node_modules/.bin/playwright install-deps
./test/node_modules/.bin/playwright install
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: linux-x64-package
- run: tar -xzf package.tar.gz
@@ -304,7 +304,7 @@ jobs:
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
- run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
if: always()
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: always()
with:
name: failed-test-videos-proxy

View File

@@ -34,7 +34,7 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
@@ -109,14 +109,14 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
- uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4.3.0
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}

View File

@@ -83,7 +83,7 @@ jobs:
# which requires secrets.
allow-unsafe-pr-checkout: true
- run: quilt push -a
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -180,7 +180,7 @@ jobs:
# which requires secrets.
allow-unsafe-pr-checkout: true
- run: quilt push -a
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -253,7 +253,7 @@ jobs:
git apply --whitespace=nowarn "patches/$patch"
done < patches/series
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
cache: npm
@@ -347,7 +347,7 @@ jobs:
esac
npm run package
- uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
- uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
draft: true
discussion_category_name: "📣 Announcements"

View File

@@ -30,7 +30,7 @@ jobs:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version-file: .node-version
@@ -51,7 +51,7 @@ jobs:
fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@8f28faec26515256b6d22074d1d2a8986f4cbd87 # latest
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
with:
scan-type: "fs"
scan-ref: "."
@@ -62,7 +62,7 @@ jobs:
severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
with:
sarif_file: "trivy-repo-results.sarif"
@@ -80,13 +80,13 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
config-file: ./.github/codeql-config.yml
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2

View File

@@ -49,7 +49,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- name: Run Trivy vulnerability scanner in image mode
uses: aquasecurity/trivy-action@8f28faec26515256b6d22074d1d2a8986f4cbd87 # latest
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
with:
image-ref: "docker.io/codercom/code-server:latest"
ignore-unfixed: true
@@ -58,6 +58,6 @@ jobs:
severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
with:
sarif_file: "trivy-image-results.sarif"

View File

@@ -22,35 +22,6 @@ Code v99.99.999
## Unreleased
### Added
- `--disable-file-cache` keeps workspace files out of the browser cache. It
stops the webview service worker from storing them in Cache Storage and
serves them from `/vscode-remote-resource` with `Cache-Control: no-store`.
Extension files stay cached.
## [4.144.0](https://github.com/coder/code-server/releases/tag/v4.144.0) - 2026-10-29
Code v1.144.0
### Changed
- Update to Code 1.144.0
### Fixed
- `--socket-fd` now works: the inherited socket is passed on to the process
that listens, and the address is logged as `fd:<n>`. Previously code-server
failed with `listen EEXIST` or `Server has no address`.
- The cookie domain was not being set against the shared root host of proxy
domains when proxy domains contained template variables like `{{port}}`,
resulting in having to sign in multiple times per domain instead of only once
as originally intended.
- When doing the web socket origin check, if the host does not already contain a
port, fall back to `X-Forwarded-Port`.
- Fix default ports not matching in the web socket origin check (for example
`https://coder.com` will now match `https://coder.com:443`).
## [4.143.1](https://github.com/coder/code-server/releases/tag/v4.143.1) - 2026-10-23
Code v1.143.1

View File

@@ -101,14 +101,6 @@ function update_csp() {
echo "Calculated hash as $hash"
# Use octothorpe as a delimiter since the hash may contain a slash.
sed -i.bak "s#'sha256-[^']\+'#'sha256-$hash'#" "$file"
# For the web worker extension host iframe, there is a matching sha in the
# web server.
if [[ $file == */webWorkerExtensionHostIframe.html ]] ; then
quilt add ./lib/vscode/src/vs/server/node/webClientServer.ts
sed -i.bak \
"s#webWorkerExtensionHostIframeScriptSHA = 'sha256-[^']\+'#webWorkerExtensionHostIframeScriptSHA = 'sha256-$hash'#" \
./lib/vscode/src/vs/server/node/webClientServer.ts
fi
done
quilt refresh

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.58.0
version: 3.57.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.144.0
appVersion: 4.143.1

View File

@@ -4,13 +4,8 @@ metadata:
name: {{ include "code-server.fullname" . }}
labels:
{{- include "code-server.labels" . | nindent 4 }}
annotations:
{{- with .Values.service.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
loadBalancerClass: {{ .Values.service.loadBalancerClass }}
ports:
- port: {{ .Values.service.port }}
targetPort: http

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.144.0'
tag: '4.143.1'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
@@ -48,8 +48,6 @@ priorityClassName: ""
service:
type: ClusterIP
port: 8080
loadBalancerClass: null
annotations: {}
ingress:
enabled: false

205
package-lock.json generated
View File

@@ -11,7 +11,7 @@
"license": "MIT",
"dependencies": {
"@coder/logger": "^3.0.1",
"argon2": "^0.45.1",
"argon2": "^0.44.0",
"compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6",
@@ -767,13 +767,13 @@
}
},
"node_modules/@types/node": {
"version": "24.19.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.2.tgz",
"integrity": "sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==",
"version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": ">=7.24.0 <7.24.7"
"undici-types": "~7.18.0"
}
},
"node_modules/@types/pem": {
@@ -870,17 +870,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.1.tgz",
"integrity": "sha512-5CokTWXpmbylfFabsbvHC0CAw3XLaGnoa+nFJX5FR592h/LoZsENUE6p/rg5xvkKrFEXz6pYmgI29AgXc2N3BQ==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.69.0.tgz",
"integrity": "sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.72.1",
"@typescript-eslint/type-utils": "8.72.1",
"@typescript-eslint/utils": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1",
"@typescript-eslint/scope-manager": "8.69.0",
"@typescript-eslint/type-utils": "8.69.0",
"@typescript-eslint/utils": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -893,15 +893,15 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.72.1",
"@typescript-eslint/parser": "^8.69.0",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.14",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.14.tgz",
"integrity": "sha512-wCBiZ77u1tuWde6G/nfOtLaCTYcFDU5yCzARzK10y+rLhzYoL7a7yEemcopcc2Mzow7gZOIjnV2ym1NYmdiJOQ==",
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz",
"integrity": "sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -909,16 +909,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.1.tgz",
"integrity": "sha512-ZGwZP4OCfyA0AQTpEAMWz+rtX01DRhQWW5hB0ucKDEIX5U7jdmPSaMx94rQfaPAQzIYz2BimOgKOJtjfpRFQ9g==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.69.0.tgz",
"integrity": "sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.72.1",
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1",
"@typescript-eslint/scope-manager": "8.69.0",
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0",
"debug": "^4.4.3"
},
"engines": {
@@ -934,14 +934,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.1.tgz",
"integrity": "sha512-fAuVMkwdO/huI8nyo/WKnNKf6Gag93S56Rh3Ts5mGcavwSdaN8tRg1gCeIGX8PF+nzp1BjGfO4gHhGzW1J6jTg==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.69.0.tgz",
"integrity": "sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.72.1",
"@typescript-eslint/types": "^8.72.1",
"@typescript-eslint/tsconfig-utils": "^8.69.0",
"@typescript-eslint/types": "^8.69.0",
"debug": "^4.4.3"
},
"engines": {
@@ -956,14 +956,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.1.tgz",
"integrity": "sha512-lC/t6eMCZZQAAKZEYGL6RDVSuFehpdmMT6h+nJIjIa6oylN/PwDgDVtEIbB7O9xFfZYtZAYLoLlDNWKJhtF+uQ==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.69.0.tgz",
"integrity": "sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1"
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -974,9 +974,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.1.tgz",
"integrity": "sha512-e4D5R5vpeAEPBxT2BAzsFQL3sbwyeeeo5+aczgNSRK1V734jE7pTqaGFU+fXapWEQwnZbpFaTn32+Z8DwS6OTg==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.69.0.tgz",
"integrity": "sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -991,15 +991,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.1.tgz",
"integrity": "sha512-iY2wlmyrXJmx4yxUGP3aYCFF3cA/6ShddOKmLU2dx7LnEykbAM8WThlxZEfd1NddqceF6eJmZUayxx9oKIYNlg==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.69.0.tgz",
"integrity": "sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1",
"@typescript-eslint/utils": "8.72.1",
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0",
"@typescript-eslint/utils": "8.69.0",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -1016,9 +1016,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.1.tgz",
"integrity": "sha512-LmE5IhQet1BWOWEXqBrVtBPsMAOQ6Nzk35d+WLh3mk4EUF33sqlfxjio1MdYeSvKSG5skactKKuixBIKXhL4Rw==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.69.0.tgz",
"integrity": "sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1030,16 +1030,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.1.tgz",
"integrity": "sha512-DAlUoUV93hIvrtIQLwCbmZQYVZwOMhiHJrOVUUIWicFZaIYjTRqlY3I/NZevfkLmSqkNHRu2qYDcq9lrn16oOQ==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.69.0.tgz",
"integrity": "sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.72.1",
"@typescript-eslint/tsconfig-utils": "8.72.1",
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1",
"@typescript-eslint/project-service": "8.69.0",
"@typescript-eslint/tsconfig-utils": "8.69.0",
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -1097,16 +1097,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.1.tgz",
"integrity": "sha512-5v5liypurJBFHCBNqh/RjsymAD+VWcE0djuGY/BUqp5fC3Qn+luWDEksjuTtWjPn6i5zQlUtkZCRG/CYG0yCkA==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.69.0.tgz",
"integrity": "sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.72.1",
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1"
"@typescript-eslint/scope-manager": "8.69.0",
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1121,13 +1121,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.1.tgz",
"integrity": "sha512-SB8xqipSzZHUePCCLNeYxqnxq83X61/qzNhjQGbTfjxGZIeOEP7tBgWYX05Tcd6CgE02WdTJnh5b8kMZJ/+bnQ==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.69.0.tgz",
"integrity": "sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/types": "8.69.0",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -1539,15 +1539,15 @@
"license": "MIT"
},
"node_modules/argon2": {
"version": "0.45.1",
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.45.1.tgz",
"integrity": "sha512-skm+/WCjkGqCQxF7FG1LuZXM5yvbFjgbfiCGsud2oLgaDhh6b6dbH0b1EkghbM+xx4Bj8Ape+KKgixoIlWZicQ==",
"version": "0.44.0",
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.44.0.tgz",
"integrity": "sha512-zHPGN3S55sihSQo0dBbK0A5qpi2R31z7HZDZnry3ifOyj8bZZnpZND2gpmhnRGO1V/d555RwBqIK5W4Mrmv3ig==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@phc/format": "^1.0.0",
"cross-env": "^10.1.0",
"node-addon-api": "^8.9.0",
"cross-env": "^10.0.0",
"node-addon-api": "^8.5.0",
"node-gyp-build": "^4.8.4"
},
"engines": {
@@ -1558,7 +1558,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/array-buffer-byte-length": {
@@ -1740,9 +1739,9 @@
"license": "MIT"
},
"node_modules/basic-ftp": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-6.2.3.tgz",
"integrity": "sha512-T7GYtQ2eKJUN5YORG7A8u2WfB9JMN0a4/wl3MI64qq2qTRfa3FXzoNq0DDojZDkDyStcL+TkfKsz4JHEZx5kGQ==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
@@ -3467,9 +3466,9 @@
}
},
"node_modules/globals": {
"version": "17.13.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.13.0.tgz",
"integrity": "sha512-RwMTC61u7hrG3ZJMkZQOK4JLJrKS8QtoTii63EmWvFXHqycY9FObBJQCbsLxSO8kjKhWE5kV1GC+Vb1g3RI0Zg==",
"version": "17.6.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz",
"integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3689,9 +3688,9 @@
}
},
"node_modules/i18next": {
"version": "26.5.11",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.11.tgz",
"integrity": "sha512-Wc0klBPKxqZ2tL2qdAnF8xvvnWgr1IMGSY2ikTiAvaFVbz7xiFARtkoU4RidBDw1SyziGROp0qxu6qnJ7l2Wug==",
"version": "26.3.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz",
"integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==",
"funding": [
{
"type": "individual",
@@ -3708,7 +3707,7 @@
],
"license": "MIT",
"peerDependencies": {
"typescript": "^5 || ^6 || ^7"
"typescript": "^5 || ^6"
},
"peerDependenciesMeta": {
"typescript": {
@@ -4284,9 +4283,9 @@
"license": "ISC"
},
"node_modules/js-yaml": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.5.0.tgz",
"integrity": "sha512-paNr4LFIFPjeeSmwNYdrb8FafLLG/Cr2Af3GjbsHJ5CxIjH4r0c2emlmRdAtpPAieP1gRVzk6buBbVP5gBMGAg==",
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.3.tgz",
"integrity": "sha512-yzzNtgczwgoVHNigCyKTXcQJU4Y8t/ikU4UxXW0BvrLfHTGWZhsNcOT2s/a7vn81/4KqVnNmHjaUEPlvWnNwVw==",
"funding": [
{
"type": "github",
@@ -4299,28 +4298,12 @@
],
"license": "MIT",
"dependencies": {
"argparse": "^3.0.3"
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.mjs"
}
},
"node_modules/js-yaml/node_modules/argparse": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.4.tgz",
"integrity": "sha512-fwWK3Zq22l4XJJjx5mcBHGikIk+hJqO+32dPm0Jur7+rtG5x1scOjSfdT9ZKeWHPpsya/l0HHK4tDImBkTrtvA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "PSF-2.0"
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -4915,9 +4898,9 @@
}
},
"node_modules/node-addon-api": {
"version": "8.9.2",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.2.tgz",
"integrity": "sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==",
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.6.0.tgz",
"integrity": "sha512-gBVjCaqDlRUk0EwoPNKzIr9KkS9041G/q31IBShPs1Xz6UTA+EXdZADbzqAJQrpDRq71CIMnOP5VMut3SL0z5Q==",
"license": "MIT",
"engines": {
"node": "^18 || ^20 || >= 21"
@@ -6403,16 +6386,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.1.tgz",
"integrity": "sha512-3Li9FfPmQp45nxEtFD1ZCrYFI3cYK5kpyNtmm1H7lMagm8u9sy6PTjy3ytwQZs7KNukOyKFHAZ6z6GjYFeaeXw==",
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.69.0.tgz",
"integrity": "sha512-B3MltX0VqjUBNEe3b3sSuiRbfa6XrfHFtBiPamjT5AsW/dfq+y+bc0wyuS9DxAS1LyzCxRp2+rxzpLUvqM2BvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.72.1",
"@typescript-eslint/parser": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1",
"@typescript-eslint/utils": "8.72.1"
"@typescript-eslint/eslint-plugin": "8.69.0",
"@typescript-eslint/parser": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0",
"@typescript-eslint/utils": "8.69.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6446,9 +6429,9 @@
}
},
"node_modules/undici-types": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"dev": true,
"license": "MIT"
},

View File

@@ -67,7 +67,7 @@
},
"dependencies": {
"@coder/logger": "^3.0.1",
"argon2": "^0.45.1",
"argon2": "^0.44.0",
"compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6",
@@ -90,9 +90,6 @@
"resolutions": {
"@types/node": "24.x"
},
"overrides": {
"basic-ftp": "^6.2.1"
},
"bin": {
"code-server": "out/node/entry.js"
},

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
@@ -262,7 +262,9 @@ class RemoteAuthoritiesImpl {
@@ -256,7 +256,9 @@ class RemoteAuthoritiesImpl {
return URI.from({
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
authority: `${host}:${port}`,

View File

@@ -2,7 +2,7 @@ Index: code-server/lib/vscode/build/gulpfile.extensions.ts
===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.extensions.ts
+++ code-server/lib/vscode/build/gulpfile.extensions.ts
@@ -283,6 +283,29 @@ export const compileCopilotExtensionBuil
@@ -294,6 +294,29 @@ export const compileCopilotExtensionBuil
task.task(compileCopilotExtensionBuildTask);
/**

View File

@@ -6,8 +6,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-Q3Tfcw0dGu/YD4dGBrRqBeOnmRMAH8HbKxArK4YSXBc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-BmcTt6YZr75RujSQ3gF/UQL77e1RrOx62jNeikpwtxc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
- content="default-src 'none'; script-src 'sha256-7cKy9iQfWRXcgRS74x6I4q5cRDkv8nQz51jecqMmQ5w=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-FYdHnaDkSHwSK3TmWDrs/tT+X4bK+aaoa9yy432BONk=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming -->
<meta name="viewport"
@@ -24,16 +24,3 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWor
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
</head>
<body>
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -114,7 +114,7 @@ const APP_ROOT = dirname(FileAccess.asFi
const STATIC_PATH = `/static`;
const CALLBACK_PATH = `/callback`;
const WEB_EXTENSION_PATH = `/web-extension-resource`;
-const webWorkerExtensionHostIframeScriptSHA = 'sha256-daEgfo2VIXpx2Np71KqCCbkeQwv+68vPrx54XRcbdcs=';
+const webWorkerExtensionHostIframeScriptSHA = 'sha256-gfjiOVjAlxqrivZAfTq2d83mOaz0fnAxbGaFpj5IjD8=';
/**
* Substitutes the `{{...}}` placeholders of a workbench template. Placeholders must only ever

View File

@@ -1,188 +0,0 @@
Add option to keep workspace files out of the browser cache
This patch adds support for a new CLI flag called `--disable-file-cache`. When
set, workspace files are not stored on the client disk through two caches:
- The webview resource loader sends no ETag for a resource outside the
webview's own extension, and the webview service worker only stores responses
that have an ETag, so these resources stay out of Cache Storage.
- `/vscode-remote-resource` responds with `Cache-Control: no-store` for files
outside the extension directories.
Extension resources keep their ETags so webviews still load extension code from
the cache. The default value for this is `false`.
To test, start code-server with `--disable-file-cache`, open a Markdown file
that embeds an image from the workspace, and open the preview. In the browser
dev tools, the `vscode-resource-cache-*` Cache Storage of the webview service
worker should have no entry for the image, and a request to
`/vscode-remote-resource?path=<image>` should respond with
`Cache-Control: no-store`.
Index: code-server/lib/vscode/src/vs/server/node/remoteExtensionHostAgentServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/remoteExtensionHostAgentServer.ts
+++ code-server/lib/vscode/src/vs/server/node/remoteExtensionHostAgentServer.ts
@@ -177,15 +177,14 @@ class RemoteExtensionHostAgentServer ext
const requestOrigin = req.headers['origin'];
const responseHeaders = getRemoteResourceResponseHeaders(requestOrigin, origin => this._webEndpointOriginChecker.matches(origin));
- if (this._environmentService.isBuilt) {
- if (isEqualOrParent(filePath, this._environmentService.builtinExtensionsPath, !platform.isLinux)
- || isEqualOrParent(filePath, this._environmentService.extensionsPath, !platform.isLinux)
- ) {
- responseHeaders['Cache-Control'] = 'public, max-age=31536000';
- }
+ const isExtensionFile = isEqualOrParent(filePath, this._environmentService.builtinExtensionsPath, !platform.isLinux)
+ || isEqualOrParent(filePath, this._environmentService.extensionsPath, !platform.isLinux);
+ if (this._environmentService.isBuilt && isExtensionFile) {
+ responseHeaders['Cache-Control'] = 'public, max-age=31536000';
}
- return serveFile(filePath, CacheControl.ETAG, this._logService, req, res, responseHeaders);
+ const cacheControl = this._environmentService.args['disable-file-cache'] && !isExtensionFile ? CacheControl.NO_CACHING : CacheControl.ETAG;
+ return serveFile(filePath, cacheControl, this._logService, req, res, responseHeaders);
}
// workbench web UI
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -37,6 +37,7 @@ export const serverOptions: OptionDescri
'auth': { type: 'string' },
'disable-file-downloads': { type: 'boolean' },
'disable-file-uploads': { type: 'boolean' },
+ 'disable-file-cache': { type: 'boolean' },
'disable-getting-started-override': { type: 'boolean' },
'locale': { type: 'string' },
'link-protection-trusted-domains': { type: 'string[]' },
@@ -139,6 +140,7 @@ export interface ServerParsedArgs {
'auth'?: string;
'disable-file-downloads'?: boolean;
'disable-file-uploads'?: boolean;
+ 'disable-file-cache'?: boolean;
'disable-getting-started-override'?: boolean,
'locale'?: string
'link-protection-trusted-domains'?: string[],
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -442,6 +442,7 @@ export class WebClientServer {
userDataPath: this._environmentService.userDataPath,
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
+ isEnabledFileCache: !this._environmentService.args['disable-file-cache'],
isEnabledCoderGettingStarted: !this._environmentService.args['disable-getting-started-override'],
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -330,6 +330,11 @@ export interface IWorkbenchConstructionO
readonly isEnabledFileUploads?: boolean
/**
+ * Whether the browser may cache workspace files.
+ */
+ readonly isEnabledFileCache?: boolean
+
+ /**
* Whether to use Coder's custom Getting Started text.
*/
readonly isEnabledCoderGettingStarted?: boolean
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.ts
@@ -15,7 +15,7 @@ import { Lazy } from '../../../../base/c
import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
import { COI, Schemas } from '../../../../base/common/network.js';
import { observableValue } from '../../../../base/common/observable.js';
-import { isEqualAuthority } from '../../../../base/common/resources.js';
+import { isEqualAuthority, isEqualOrParent } from '../../../../base/common/resources.js';
import { listenStream } from '../../../../base/common/stream.js';
import { URI } from '../../../../base/common/uri.js';
import { generateUuid } from '../../../../base/common/uuid.js';
@@ -32,6 +32,7 @@ import { INotificationService } from '..
import { IRemoteAuthorityResolverService } from '../../../../platform/remote/common/remoteAuthorityResolver.js';
import { ITunnelService } from '../../../../platform/tunnel/common/tunnel.js';
import { WebviewPortMappingManager } from '../../../../platform/webview/common/webviewPortMapping.js';
+import { IBrowserWorkbenchEnvironmentService } from '../../../services/environment/browser/environmentService.js';
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
import { IRemoteAgentService } from '../../../services/remote/common/remoteAgentService.js';
import { decodeAuthority, webviewGenericCspSource, webviewRootResourceAuthority } from '../common/webview.js';
@@ -864,6 +865,8 @@ export class WebviewElement extends Disp
const rangeHeader = range
? `bytes ${range.start}-${rangeEnd}/${result.size}`
: undefined;
+ // The service worker only stores responses that have an etag.
+ const etag = this._isFileCacheAllowed(uri) ? result.etag : undefined;
if (WebviewElement._supportsTransferableStreams.value) {
let controller: ReadableStreamDefaultController<Uint8Array<ArrayBuffer>> | undefined;
let closed = false;
@@ -915,7 +918,7 @@ export class WebviewElement extends Disp
status: range ? 206 : 200,
path: uri.path,
mime: result.mimeType,
- etag: result.etag,
+ etag,
mtime: result.mtime,
range: rangeHeader,
stream,
@@ -927,7 +930,7 @@ export class WebviewElement extends Disp
status: range ? 206 : 200,
path: uri.path,
mime: result.mimeType,
- etag: result.etag,
+ etag,
mtime: result.mtime,
range: rangeHeader,
});
@@ -984,6 +987,14 @@ export class WebviewElement extends Disp
});
}
+ private _isFileCacheAllowed(uri: URI): boolean {
+ if ((this._environmentService as IBrowserWorkbenchEnvironmentService).isEnabledFileCache) {
+ return true;
+ }
+ const extensionLocation = this.extension?.location;
+ return !!extensionLocation && isEqualOrParent(uri, extensionLocation);
+ }
+
private async localLocalhost(id: string, origin: string) {
const authority = this._environmentService.remoteAuthority;
const resolveAuthority = authority ? await this._remoteAuthorityResolverService.resolveAuthority(authority) : undefined;
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -49,6 +49,11 @@ export interface IBrowserWorkbenchEnviro
readonly isEnabledFileUploads?: boolean;
/**
+ * Allow the browser to cache workspace files.
+ */
+ readonly isEnabledFileCache?: boolean;
+
+ /**
* Enable Coder's custom getting started text.
*/
readonly isEnabledCoderGettingStarted?: boolean;
@@ -145,6 +150,13 @@ export class BrowserWorkbenchEnvironment
return this.options.isEnabledFileUploads;
}
+ get isEnabledFileCache(): boolean {
+ if (typeof this.options.isEnabledFileCache === "undefined") {
+ throw new Error('isEnabledFileCache was not provided to the browser');
+ }
+ return this.options.isEnabledFileCache;
+ }
+
get isEnabledCoderGettingStarted(): boolean {
if (typeof this.options.isEnabledCoderGettingStarted === "undefined") {
throw new Error('isEnabledCoderGettingStarted was not provided to the browser');

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 { status } from '../../../../base/browser/ui/aria/aria.js';
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
@@ -56,7 +56,7 @@ import { IRecentFolder, IRecentWorkspace
@@ -55,7 +55,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';
@@ -944,6 +944,72 @@ export class GettingStartedPage extends
@@ -930,6 +930,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', {},);
@@ -1000,6 +1066,9 @@ export class GettingStartedPage extends
@@ -980,6 +1046,9 @@ export class GettingStartedPage extends
recentList.setLimit(5);
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
}

View File

@@ -169,7 +169,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
@@ -65,6 +65,7 @@ import { IOpenerService } from '../../pl
@@ -64,6 +64,7 @@ import { IOpenerService } from '../../pl
import { mixin, safeStringify } from '../../base/common/objects.js';
import { IndexedDB } from '../../base/browser/indexedDB.js';
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
@@ -177,7 +177,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
import { IProgressService } from '../../platform/progress/common/progress.js';
import { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js';
import { dirname, joinPath } from '../../base/common/resources.js';
@@ -141,6 +142,9 @@ export class BrowserMain extends Disposa
@@ -140,6 +141,9 @@ export class BrowserMain extends Disposa
// Startup
const instantiationService = workbench.startup();

View File

@@ -77,7 +77,7 @@ Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/ext
import { TargetPlatform } from '../../extensions/common/extensions.js';
import { ExtensionGalleryResourceType, getExtensionGalleryManifestResourceUri, IExtensionGalleryManifest, IExtensionGalleryManifestService } from '../../extensionManagement/common/extensionGalleryManifest.js';
import { ILogService } from '../../log/common/log.js';
@@ -167,9 +166,9 @@ export abstract class AbstractExtensionR
@@ -163,9 +162,9 @@ export abstract class AbstractExtensionR
}
protected _isWebExtensionResourceEndPoint(uri: URI): boolean {

View File

@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
@@ -324,6 +324,10 @@ function extensionDescriptionArrayToMap(
@@ -321,6 +321,10 @@ function extensionDescriptionArrayToMap(
}
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {

View File

@@ -179,7 +179,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
@@ -34,6 +34,7 @@ import { ISignService } from '../../plat
@@ -33,6 +33,7 @@ import { ISignService } from '../../plat
import { SignService } from '../../platform/sign/browser/signService.js';
import { IWorkbenchConstructionOptions, IWorkbench, IWorkspace, ITunnel } from './web.api.js';
import { BrowserStorageService } from '../services/storage/browser/storageService.js';
@@ -187,7 +187,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
import { IStorageService } from '../../platform/storage/common/storage.js';
import { toLocalISOString } from '../../base/common/date.js';
import { isWorkspaceToOpen, isFolderToOpen } from '../../platform/window/common/window.js';
@@ -488,7 +489,7 @@ export class BrowserMain extends Disposa
@@ -482,7 +483,7 @@ export class BrowserMain extends Disposa
serviceCollection.set(IWorkbenchConfigurationService, service);
return service;
}),
@@ -196,7 +196,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
serviceCollection.set(IStorageService, service);
return service;
})
@@ -610,7 +611,21 @@ export class BrowserMain extends Disposa
@@ -604,7 +605,21 @@ export class BrowserMain extends Disposa
}));
}

View File

@@ -27,4 +27,3 @@ app-name.diff
remote-storage.diff
remote-secret-storage.diff
csp-hashes.diff
disable-file-cache.diff

View File

@@ -111,14 +111,9 @@ export const createApp = async (args: DefaultedArgs): Promise<App> => {
*
* The address might be a URL or it might be a pipe or socket path.
*/
export const ensureAddress = (server: http.Server, protocol: string, socketFd?: number): URL | string => {
export const ensureAddress = (server: http.Server, protocol: string): URL | string => {
const addr = server.address()
// Node reports no address for a Unix socket adopted by fd.
if (!addr && typeof socketFd === "number") {
return `fd:${socketFd}`
}
if (!addr) {
throw new Error("Server has no address")
}

View File

@@ -51,7 +51,6 @@ export interface UserProvidedCodeArgs {
"disable-update-check"?: boolean
"disable-file-downloads"?: boolean
"disable-file-uploads"?: boolean
"disable-file-cache"?: boolean
"disable-workspace-trust"?: boolean
"disable-getting-started-override"?: boolean
"disable-proxy"?: boolean
@@ -194,10 +193,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
type: "boolean",
description: "Disable file uploads.",
},
"disable-file-cache": {
type: "boolean",
description: "Keep workspace files out of the browser cache.",
},
"disable-workspace-trust": {
type: "boolean",
description: "Disable Workspace Trust feature. This switch only affects the current session.",

View File

@@ -235,16 +235,7 @@ export const getCookieDomain = (host: string, proxyDomains: string[]): string |
return undefined
}
proxyDomains.forEach((proxyDomain) => {
// Proxy domains are patterns like `{{port}}.domain.tld` or
// `prefix-{{port}}-suffix.domain.tld` so use the part after the label that
// contains the port.
const portIndex = proxyDomain.indexOf("{{port}}")
const domain = portIndex === -1 ? proxyDomain : proxyDomain.substring(proxyDomain.indexOf(".", portIndex) + 1)
// Skip patterns we cannot turn into a domain, like `{{port}}.{{host}}`.
if (!domain || domain.includes("{{")) {
return
}
proxyDomains.forEach((domain) => {
if (host.endsWith(domain) && domain.length < host.length) {
host = domain
}

View File

@@ -141,7 +141,7 @@ export const runCodeServer = async (
const app = await createApp(args)
const protocol = args.cert ? "https" : "http"
const serverAddress = ensureAddress(app.server, protocol, args["socket-fd"])
const serverAddress = ensureAddress(app.server, protocol)
const { disposeRoutes, heart } = await register(app, args)
logger.info(`Using config file ${args.config}`)

View File

@@ -8,9 +8,6 @@ import { paths } from "./util"
const timeoutInterval = 10000 // 10s, matches VS Code's timeouts.
// Fd 3 in the child is the IPC channel, so the inherited socket goes to fd 4.
const CHILD_SOCKET_FD = 4
/**
* Listen to a single message from a process. Reject if the process errors,
* exits, or times out.
@@ -337,14 +334,13 @@ export class ParentProcess extends Process {
}
private spawn(): cp.ChildProcess {
const socketFd = this.args?.["socket-fd"]
return cp.fork(path.join(__dirname, "entry"), {
env: {
...process.env,
CODE_SERVER_PARENT_PID: process.pid.toString(),
NODE_EXEC_PATH: process.execPath,
},
stdio: typeof socketFd === "number" ? ["pipe", "pipe", "pipe", "ipc", socketFd] : ["pipe", "pipe", "pipe", "ipc"],
stdio: ["pipe", "pipe", "pipe", "ipc"],
})
}
@@ -363,8 +359,7 @@ export class ParentProcess extends Process {
this.logger,
)
this.logger.debug("got message", field("message", message))
const args = typeof this.args["socket-fd"] === "number" ? { ...this.args, "socket-fd": CHILD_SOCKET_FD } : this.args
this.send(child, { type: "handshake", args })
this.send(child, { type: "handshake", args: this.args })
}
/**

View File

@@ -1,132 +0,0 @@
import { promises as fs } from "fs"
import * as path from "path"
import { Page } from "playwright"
import { clean, getMaybeProxiedCodeServer } from "../utils/helpers"
import { describe, test, expect } from "./baseFixture"
import { CodeServerPage } from "./models/CodeServer"
// A 1x1 PNG.
const png = Buffer.from(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==",
"base64",
)
/**
* Open a Markdown preview that embeds a PNG from the workspace and wait for
* the image to render.
*/
async function previewMarkdownWithImage(codeServerPage: CodeServerPage, imageName: string): Promise<Page> {
const dir = await codeServerPage.workspaceDir
await fs.writeFile(path.join(dir, imageName), png)
const markdown = path.join(dir, `${imageName}.md`)
await fs.writeFile(markdown, `# Preview\n\n![workspace image](${imageName})\n`)
await codeServerPage.openFile(markdown)
await codeServerPage.executeCommandViaMenus("Markdown: Open Preview to the Side")
await codeServerPage.waitForTab(`Preview ${markdown}`)
const image = codeServerPage.page
.frameLocator("iframe.webview.ready")
.frameLocator("#active-frame")
.locator(`img[alt="workspace image"]`)
await expect.poll(() => image.evaluate((img: HTMLImageElement) => img.naturalWidth)).toBeGreaterThan(0)
return codeServerPage.page
}
/**
* URLs in the webview service worker's Cache Storage.
*/
async function cachedWebviewUrls(page: Page): Promise<string[]> {
const frame = await (await page.locator("iframe.webview.ready").elementHandle())?.contentFrame()
if (!frame) {
throw new Error("webview frame not found")
}
return frame.evaluate(async () => {
const urls: string[] = []
for (const name of await caches.keys()) {
if (name.startsWith("vscode-resource-cache-")) {
for (const request of await (await caches.open(name)).keys()) {
urls.push(request.url)
}
}
}
return urls
})
}
async function fetchRemoteResource(codeServerPage: CodeServerPage, file: string) {
const address = await getMaybeProxiedCodeServer(codeServerPage)
const url = new URL(`vscode-remote-resource?path=${encodeURIComponent(file)}`, address)
return codeServerPage.page.request.get(url.toString())
}
/**
* Write a workspace file and a file in the user extensions directory.
*/
async function writeResourceFiles(codeServerPage: CodeServerPage, name: string) {
const dir = await codeServerPage.workspaceDir
const workspaceFile = path.join(dir, `${name}-workspace.txt`)
const extensionDir = path.join(dir, "extensions", `${name}-extension`)
const extensionFile = path.join(extensionDir, "resource.txt")
await fs.writeFile(workspaceFile, "workspace")
await fs.mkdir(extensionDir, { recursive: true })
await fs.writeFile(extensionFile, "extension")
return { workspaceFile, extensionFile }
}
describe("File cache (enabled)", ["--disable-workspace-trust"], {}, async () => {
const testName = "file-cache-enabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should cache workspace files in the webview Cache Storage", async ({ codeServerPage }) => {
const page = await previewMarkdownWithImage(codeServerPage, "cache-enabled.png")
await expect
.poll(async () => (await cachedWebviewUrls(page)).filter((url) => url.includes("cache-enabled.png")))
.toHaveLength(1)
})
test("should serve /vscode-remote-resource with an ETag and without no-store", async ({ codeServerPage }) => {
const { workspaceFile, extensionFile } = await writeResourceFiles(codeServerPage, "enabled")
for (const file of [workspaceFile, extensionFile]) {
const response = await fetchRemoteResource(codeServerPage, file)
expect(response.status()).toBe(200)
expect(response.headers()["etag"]).toBeTruthy()
expect(response.headers()["cache-control"] ?? "").not.toContain("no-store")
}
})
})
describe("File cache (disabled)", ["--disable-workspace-trust", "--disable-file-cache"], {}, async () => {
const testName = "file-cache-disabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should keep workspace files out of the webview Cache Storage but cache extension files", async ({
codeServerPage,
}) => {
const page = await previewMarkdownWithImage(codeServerPage, "cache-disabled.png")
// Cached extension files show that the flag, not a cache failure, keeps the image out.
await expect
.poll(async () => (await cachedWebviewUrls(page)).filter((url) => url.includes("markdown-language-features")))
.not.toHaveLength(0)
expect((await cachedWebviewUrls(page)).filter((url) => url.includes("cache-disabled.png"))).toHaveLength(0)
})
test("should serve /vscode-remote-resource with no-store for workspace files and an ETag for extension files", async ({
codeServerPage,
}) => {
const { workspaceFile, extensionFile } = await writeResourceFiles(codeServerPage, "disabled")
const workspaceResponse = await fetchRemoteResource(codeServerPage, workspaceFile)
expect(workspaceResponse.status()).toBe(200)
expect(workspaceResponse.headers()["cache-control"]).toBe("no-store")
expect(workspaceResponse.headers()["etag"]).toBeUndefined()
const extensionResponse = await fetchRemoteResource(codeServerPage, extensionFile)
expect(extensionResponse.status()).toBe(200)
expect(extensionResponse.headers()["etag"]).toBeTruthy()
expect(extensionResponse.headers()["cache-control"] ?? "").not.toContain("no-store")
})
})

View File

@@ -1,80 +0,0 @@
import { ChildProcess, spawn } from "child_process"
import { promises as fs } from "fs"
import * as http from "http"
import * as net from "net"
import * as path from "path"
import { clean, tmpdir } from "../utils/helpers"
describe("--socket-fd", () => {
const testName = "socketFd"
const codeServerPath = process.env.CODE_SERVER_PATH || path.resolve("../../release-standalone/bin/code-server")
let tempDir: string
let socketDir: string | undefined
let child: ChildProcess | undefined
beforeEach(async () => {
await clean(testName)
tempDir = await tmpdir(testName)
})
afterEach(async () => {
if (child?.pid && child.exitCode === null) {
// Kill the process group so that the wrapper's inner process also stops.
process.kill(-child.pid, "SIGKILL")
}
if (socketDir) {
await fs.rm(socketDir, { force: true, recursive: true })
socketDir = undefined
}
})
// Give the listener to code-server as fd 3, as systemd socket activation does.
const getHealthzThroughFd = async (server: net.Server, target: http.RequestOptions): Promise<number> => {
const fd: number = (server as any)._handle.fd
let output = ""
child = spawn(
codeServerPath,
[
"--socket-fd=3",
"--auth=none",
`--user-data-dir=${path.join(tempDir, "data")}`,
`--config=${path.join(tempDir, "config.yaml")}`,
],
{ detached: true, stdio: ["ignore", "pipe", "pipe", fd] },
)
child.stdout?.on("data", (chunk) => (output += chunk))
child.stderr?.on("data", (chunk) => (output += chunk))
await new Promise((resolve) => server.close(resolve))
const exited = new Promise<never>((_, reject) => {
child?.once("exit", (code) => reject(new Error(`code-server exited with code ${code}:\n${output}`)))
})
const status = new Promise<number>((resolve, reject) => {
http
.get({ ...target, path: "/healthz" }, (res) => {
res.resume()
resolve(res.statusCode ?? 0)
})
.once("error", (error) => reject(new Error(`${error.message}:\n${output}`)))
})
return Promise.race([status, exited])
}
it("should serve requests on a Unix socket passed as a file descriptor", async () => {
// macOS limits socket paths to 104 bytes, and os.tmpdir() can be too long.
socketDir = await fs.mkdtemp("/tmp/cs-fd-")
const server = net.createServer()
await new Promise<void>((resolve) => server.listen(path.join(socketDir!, "listen.sock"), resolve))
// server.close() unlinks the socket path, so connect through a hard link.
const socketPath = path.join(socketDir, "connect.sock")
await fs.link(path.join(socketDir, "listen.sock"), socketPath)
expect(await getHealthzThroughFd(server, { socketPath })).toBe(200)
}, 60000)
it("should serve requests on a TCP socket passed as a file descriptor", async () => {
const server = net.createServer()
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve))
const { port } = server.address() as net.AddressInfo
expect(await getHealthzThroughFd(server, { host: "127.0.0.1", port })).toBe(200)
}, 60000)
})

View File

@@ -152,9 +152,6 @@ describe("ensureAddress", () => {
it("should throw and error if no address", () => {
expect(() => ensureAddress(mockServer, "http")).toThrow("Server has no address")
})
it("should describe a --socket-fd listener by its fd when node reports no address", () => {
expect(ensureAddress(mockServer, "http", 4)).toBe("fd:4")
})
it("should return the address if it's a string", async () => {
mockServer.address = () => "/path/to/unix.sock"
const address = ensureAddress(mockServer, "http")

View File

@@ -109,8 +109,6 @@ describe("parser", () => {
"--disable-file-downloads",
"--disable-file-cache",
"--disable-getting-started-override",
"--disable-proxy",
@@ -139,7 +137,6 @@ describe("parser", () => {
cert: {
value: path.resolve("path/to/cert"),
},
"disable-file-cache": true,
"disable-file-downloads": true,
"disable-getting-started-override": true,
"disable-proxy": true,

View File

@@ -230,35 +230,6 @@ describe("http", () => {
})
})
describe("getCookieDomain", () => {
it("should use the proxy domain for the cookie", () => {
const proxyDomains = ["{{port}}.example.com", "code-{{port}}.test.com"]
expect(http.getCookieDomain("example.com", proxyDomains)).toBe("example.com")
expect(http.getCookieDomain("8080.example.com", proxyDomains)).toBe("example.com")
expect(http.getCookieDomain("8080.example.com:443", proxyDomains)).toBe("example.com")
expect(http.getCookieDomain("code-8080.test.com", proxyDomains)).toBe("test.com")
})
it("should use the highest level proxy domain", () => {
const proxyDomains = ["{{port}}.test.example.com", "{{port}}.example.com"]
expect(http.getCookieDomain("test.example.com", proxyDomains)).toBe("example.com")
expect(http.getCookieDomain("8080.test.example.com", proxyDomains)).toBe("example.com")
})
it("should use the host when no proxy domain matches", () => {
expect(http.getCookieDomain("code.other.com", ["{{port}}.example.com"])).toBe("code.other.com")
expect(http.getCookieDomain("8080.example.com", ["{{port}}.{{host}}"])).toBe("8080.example.com")
expect(http.getCookieDomain("8080.example.com", [])).toBe("8080.example.com")
})
it("should not set a domain for localhost or IP addresses", () => {
const proxyDomains = ["{{port}}.example.com"]
expect(http.getCookieDomain("localhost:8080", proxyDomains)).toBe(undefined)
expect(http.getCookieDomain("127.0.0.1:8080", proxyDomains)).toBe(undefined)
expect(http.getCookieDomain("8080.dev.localhost", proxyDomains)).toBe(undefined)
})
})
describe("constructRedirectPath", () => {
it("should preserve slashes in queryString so they are human-readable", () => {
const mockReq = getMockReq({