Merge branch 'main' into joh/source-map-fixes

This commit is contained in:
Johannes Rieken
2026-03-03 10:27:43 +01:00
committed by GitHub
17 changed files with 2108 additions and 1918 deletions

View File

@@ -18,6 +18,8 @@
**/extensions/terminal-suggest/src/shell/fishBuiltinsCache.ts
**/extensions/terminal-suggest/third_party/**
**/extensions/typescript-language-features/test-workspace/**
**/extensions/typescript-language-features/extension.webpack.config.js
**/extensions/typescript-language-features/extension-browser.webpack.config.js
**/extensions/typescript-language-features/package-manager/node-maintainer/**
**/extensions/vscode-api-tests/testWorkspace/**
**/extensions/vscode-api-tests/testWorkspace2/**

View File

@@ -309,6 +309,13 @@ async function buildWebExtensions(isWatch: boolean): Promise<void> {
{ ignore: ['**/node_modules'] }
);
// Find all webpack configs, excluding those that will be esbuilt
const esbuildExtensionDirs = new Set(esbuildConfigLocations.map(p => path.dirname(p)));
const webpackConfigLocations = (await nodeUtil.promisify(glob)(
path.join(extensionsPath, '**', 'extension-browser.webpack.config.js'),
{ ignore: ['**/node_modules'] }
)).filter(configPath => !esbuildExtensionDirs.has(path.dirname(configPath)));
const promises: Promise<unknown>[] = [];
// Esbuild for extensions
@@ -323,5 +330,10 @@ async function buildWebExtensions(isWatch: boolean): Promise<void> {
);
}
// Run webpack for remaining extensions
if (webpackConfigLocations.length > 0) {
promises.push(ext.webpackExtensions('packaging web extension', isWatch, webpackConfigLocations.map(configPath => ({ configPath }))));
}
await Promise.all(promises);
}

View File

@@ -20,8 +20,10 @@ import fancyLog from 'fancy-log';
import ansiColors from 'ansi-colors';
import buffer from 'gulp-buffer';
import * as jsoncParser from 'jsonc-parser';
import webpack from 'webpack';
import { getProductionDependencies } from './dependencies.ts';
import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts';
import { getVersion } from './getVersion.ts';
import { fetchUrls, fetchGithub } from './fetch.ts';
import { createTsgoStream, spawnTsgo } from './tsgo.ts';
import vzip from 'gulp-vinyl-zip';
@@ -30,8 +32,8 @@ import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const root = path.dirname(path.dirname(import.meta.dirname));
// const commit = getVersion(root);
// const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
const commit = getVersion(root);
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
function minifyExtensionResources(input: Stream): Stream {
const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true });
@@ -63,24 +65,32 @@ function updateExtensionPackageJSON(input: Stream, update: (data: any) => any):
.pipe(packageJsonFilter.restore);
}
function fromLocal(extensionPath: string, forWeb: boolean, _disableMangle: boolean): Stream {
function fromLocal(extensionPath: string, forWeb: boolean, disableMangle: boolean): Stream {
const esbuildConfigFileName = forWeb
? 'esbuild.browser.mts'
: 'esbuild.mts';
const webpackConfigFileName = forWeb
? `extension-browser.webpack.config.js`
: `extension.webpack.config.js`;
const hasEsbuild = fs.existsSync(path.join(extensionPath, esbuildConfigFileName));
const hasWebpack = fs.existsSync(path.join(extensionPath, webpackConfigFileName));
let input: Stream;
let isBundled = false;
if (hasEsbuild) {
// Esbuild only does bundling so we still want to run a separate type check step
// Unlike webpack, esbuild only does bundling so we still want to run a separate type check step
input = es.merge(
fromLocalEsbuild(extensionPath, esbuildConfigFileName),
...getBuildRootsForExtension(extensionPath).map(root => typeCheckExtensionStream(root, forWeb)),
);
isBundled = true;
} else if (hasWebpack) {
input = fromLocalWebpack(extensionPath, webpackConfigFileName, disableMangle);
isBundled = true;
} else {
input = fromLocalNormal(extensionPath);
}
@@ -112,6 +122,132 @@ export function typeCheckExtensionStream(extensionPath: string, forWeb: boolean)
return createTsgoStream(tsconfigPath, { taskName: 'typechecking extension (tsgo)', noEmit: true });
}
function fromLocalWebpack(extensionPath: string, webpackConfigFileName: string, disableMangle: boolean): Stream {
const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce');
const webpack = require('webpack');
const webpackGulp = require('webpack-stream');
const result = es.through();
const packagedDependencies: string[] = [];
const stripOutSourceMaps: string[] = [];
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
if (packageJsonConfig.dependencies) {
const webpackConfig = require(path.join(extensionPath, webpackConfigFileName));
const webpackRootConfig = webpackConfig.default;
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
packagedDependencies.push(key);
}
}
if (webpackConfig.StripOutSourceMaps) {
for (const filePath of webpackConfig.StripOutSourceMaps) {
stripOutSourceMaps.push(filePath);
}
}
}
// TODO: add prune support based on packagedDependencies to vsce.PackageManager.Npm similar
// to vsce.PackageManager.Yarn.
// A static analysis showed there are no webpack externals that are dependencies of the current
// local extensions so we can use the vsce.PackageManager.None config to ignore dependencies list
// as a temporary workaround.
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.None, packagedDependencies }).then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath)
}));
// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream.
const webpackConfigLocations = (glob.sync(
path.join(extensionPath, '**', webpackConfigFileName),
{ ignore: ['**/node_modules'] }
) as string[]);
const webpackStreams = webpackConfigLocations.flatMap(webpackConfigPath => {
const webpackDone = (err: Error | undefined, stats: any) => {
fancyLog(`Bundled extension: ${ansiColors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
if (err) {
result.emit('error', err);
}
const { compilation } = stats;
if (compilation.errors.length > 0) {
result.emit('error', compilation.errors.join('\n'));
}
if (compilation.warnings.length > 0) {
result.emit('error', compilation.warnings.join('\n'));
}
};
const exportedConfig = require(webpackConfigPath).default;
return (Array.isArray(exportedConfig) ? exportedConfig : [exportedConfig]).map(config => {
const webpackConfig = {
...config,
...{ mode: 'production' }
};
if (disableMangle) {
if (Array.isArray(config.module.rules)) {
for (const rule of config.module.rules) {
if (Array.isArray(rule.use)) {
for (const use of rule.use) {
if (String(use.loader).endsWith('mangle-loader.js')) {
use.options.disabled = true;
}
}
}
}
}
}
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
return webpackGulp(webpackConfig, webpack, webpackDone)
.pipe(es.through(function (data) {
data.stat = data.stat || {};
data.base = extensionPath;
this.emit('data', data);
}))
.pipe(es.through(function (data: File) {
// source map handling:
// * rewrite sourceMappingURL
// * save to disk so that upload-task picks this up
if (path.extname(data.basename) === '.js') {
if (stripOutSourceMaps.indexOf(data.relative) >= 0) { // remove source map
const contents = (data.contents as Buffer).toString('utf8');
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
} else {
const contents = (data.contents as Buffer).toString('utf8');
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
}), 'utf8');
}
}
this.emit('data', data);
}));
});
});
es.merge(...webpackStreams, es.readArray(files))
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
// this.emit('data', data);
// }))
.pipe(result);
}).catch(err => {
console.error(extensionPath);
console.error(packagedDependencies);
result.emit('error', err);
});
return result.pipe(createStatsStream(path.basename(extensionPath)));
}
function fromLocalNormal(extensionPath: string): Stream {
const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce');
@@ -513,6 +649,70 @@ export function translatePackageJSON(packageJSON: string, packageNLSPath: string
const extensionsPath = path.join(root, 'extensions');
export async function webpackExtensions(taskName: string, isWatch: boolean, webpackConfigLocations: { configPath: string; outputRoot?: string }[]) {
const webpack = require('webpack') as typeof import('webpack');
const webpackConfigs: webpack.Configuration[] = [];
for (const { configPath, outputRoot } of webpackConfigLocations) {
const configOrFnOrArray = require(configPath).default;
function addConfig(configOrFnOrArray: webpack.Configuration | ((env: unknown, args: unknown) => webpack.Configuration) | webpack.Configuration[]) {
for (const configOrFn of Array.isArray(configOrFnOrArray) ? configOrFnOrArray : [configOrFnOrArray]) {
const config = typeof configOrFn === 'function' ? configOrFn({}, {}) : configOrFn;
if (outputRoot) {
config.output!.path = path.join(outputRoot, path.relative(path.dirname(configPath), config.output!.path!));
}
webpackConfigs.push(config);
}
}
addConfig(configOrFnOrArray);
}
function reporter(fullStats: any) {
if (Array.isArray(fullStats.children)) {
for (const stats of fullStats.children) {
const outputPath = stats.outputPath;
if (outputPath) {
const relativePath = path.relative(extensionsPath, outputPath).replace(/\\/g, '/');
const match = relativePath.match(/[^\/]+(\/server|\/client)?/);
fancyLog(`Finished ${ansiColors.green(taskName)} ${ansiColors.cyan(match![0])} with ${stats.errors.length} errors.`);
}
if (Array.isArray(stats.errors)) {
stats.errors.forEach((error: any) => {
fancyLog.error(error);
});
}
if (Array.isArray(stats.warnings)) {
stats.warnings.forEach((warning: any) => {
fancyLog.warn(warning);
});
}
}
}
}
return new Promise<void>((resolve, reject) => {
if (isWatch) {
webpack(webpackConfigs).watch({}, (err, stats) => {
if (err) {
reject();
} else {
reporter(stats?.toJson());
}
});
} else {
webpack(webpackConfigs).run((err, stats) => {
if (err) {
fancyLog.error(err);
reject();
} else {
reporter(stats?.toJson());
resolve();
}
});
}
});
}
export async function esbuildExtensions(taskName: string, isWatch: boolean, scripts: { script: string; outputRoot?: string }[]): Promise<void> {
function reporter(stdError: string, script: string) {
const matches = (stdError || '').match(/\> (.+): error: (.+)?/g);

View File

@@ -0,0 +1,132 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// a webpack loader that bundles all library definitions (d.ts) for the embedded JavaScript engine.
const path = require('path');
const fs = require('fs');
const TYPESCRIPT_LIB_SOURCE = path.join(__dirname, '../../../node_modules/typescript/lib');
const JQUERY_DTS = path.join(__dirname, '../lib/jquery.d.ts');
module.exports = function () {
function getFileName(name) {
return (name === '' ? 'lib.d.ts' : `lib.${name}.d.ts`);
}
function readLibFile(name) {
var srcPath = path.join(TYPESCRIPT_LIB_SOURCE, getFileName(name));
return fs.readFileSync(srcPath).toString();
}
var queue = [];
var in_queue = {};
var enqueue = function (name) {
if (in_queue[name]) {
return;
}
in_queue[name] = true;
queue.push(name);
};
enqueue('es2020.full');
var result = [];
while (queue.length > 0) {
var name = queue.shift();
var contents = readLibFile(name);
var lines = contents.split(/\r\n|\r|\n/);
var outputLines = [];
for (let i = 0; i < lines.length; i++) {
let m = lines[i].match(/\/\/\/\s*<reference\s*lib="([^"]+)"/);
if (m) {
enqueue(m[1]);
}
outputLines.push(lines[i]);
}
result.push({
name: getFileName(name),
output: `"${escapeText(outputLines.join('\n'))}"`
});
}
const jquerySource = fs.readFileSync(JQUERY_DTS).toString();
var lines = jquerySource.split(/\r\n|\r|\n/);
result.push({
name: 'jquery',
output: `"${escapeText(lines.join('\n'))}"`
});
let strResult = `\nconst libs : { [name:string]: string; } = {\n`
for (let i = result.length - 1; i >= 0; i--) {
strResult += `"${result[i].name}": ${result[i].output},\n`;
}
strResult += `\n};`
strResult += `export function loadLibrary(name: string) : string {\n return libs[name] || ''; \n}`;
return strResult;
}
/**
* Escape text such that it can be used in a javascript string enclosed by double quotes (")
*/
function escapeText(text) {
// See http://www.javascriptkit.com/jsref/escapesequence.shtml
var _backspace = '\b'.charCodeAt(0);
var _formFeed = '\f'.charCodeAt(0);
var _newLine = '\n'.charCodeAt(0);
var _nullChar = 0;
var _carriageReturn = '\r'.charCodeAt(0);
var _tab = '\t'.charCodeAt(0);
var _verticalTab = '\v'.charCodeAt(0);
var _backslash = '\\'.charCodeAt(0);
var _doubleQuote = '"'.charCodeAt(0);
var startPos = 0, chrCode, replaceWith = null, resultPieces = [];
for (var i = 0, len = text.length; i < len; i++) {
chrCode = text.charCodeAt(i);
switch (chrCode) {
case _backspace:
replaceWith = '\\b';
break;
case _formFeed:
replaceWith = '\\f';
break;
case _newLine:
replaceWith = '\\n';
break;
case _nullChar:
replaceWith = '\\0';
break;
case _carriageReturn:
replaceWith = '\\r';
break;
case _tab:
replaceWith = '\\t';
break;
case _verticalTab:
replaceWith = '\\v';
break;
case _backslash:
replaceWith = '\\\\';
break;
case _doubleQuote:
replaceWith = '\\"';
break;
}
if (replaceWith !== null) {
resultPieces.push(text.substring(startPos, i));
resultPieces.push(replaceWith);
startPos = i + 1;
replaceWith = null;
}
}
resultPieces.push(text.substring(startPos, len));
return resultPieces.join('');
}

View File

@@ -6,4 +6,5 @@ test/
tsconfig.json
.gitignore
package-lock.json
extension.webpack.config.js
vscode-json-languageserver-*.tgz

View File

@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
const fs = require('fs');
const webpack = require('webpack');
const fancyLog = require('fancy-log');
const ansiColors = require('ansi-colors');
const { Mangler } = require('../build/lib/mangle/index.js');
/**
* Map of project paths to mangled file contents
*
* @type {Map<string, Promise<Map<string, { out: string; sourceMap?: string }>>>}
*/
const mangleMap = new Map();
/**
* @param {string} projectPath
*/
function getMangledFileContents(projectPath) {
let entry = mangleMap.get(projectPath);
if (!entry) {
const log = (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data);
log(`Mangling ${projectPath}`);
const ts2tsMangler = new Mangler(projectPath, log, { mangleExports: true, manglePrivateFields: true });
entry = ts2tsMangler.computeNewFileContents();
mangleMap.set(projectPath, entry);
}
return entry;
}
/**
* @type {webpack.LoaderDefinitionFunction}
*/
module.exports = async function (source, sourceMap, meta) {
if (this.mode !== 'production') {
// Only enable mangling in production builds
return source;
}
if (true) {
// disable mangling for now, SEE https://github.com/microsoft/vscode/issues/204692
return source;
}
const options = this.getOptions();
if (options.disabled) {
// Dynamically disabled
return source;
}
if (source !== fs.readFileSync(this.resourcePath).toString()) {
// File content has changed by previous webpack steps.
// Skip mangling.
return source;
}
const callback = this.async();
const fileContentsMap = await getMangledFileContents(options.configFile);
const newContents = fileContentsMap.get(this.resourcePath);
callback(null, newContents?.out ?? source, sourceMap, meta);
};

View File

@@ -7,3 +7,4 @@ out/**
cgmanifest.json
package-lock.json
preview-src/**
webpack.config.js

View File

@@ -1,6 +1,8 @@
src/**
extension.webpack.config.js
esbuild.*
cgmanifest.json
package-lock.json
webpack.config.js
tsconfig*.json
.gitignore

View File

@@ -0,0 +1,209 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
import path from 'node:path';
import fs from 'node:fs';
import merge from 'merge-options';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import webpack from 'webpack';
import { createRequire } from 'node:module';
/** @typedef {import('webpack').Configuration} WebpackConfig **/
const require = createRequire(import.meta.url);
const tsLoaderOptions = {
compilerOptions: {
'sourceMap': true,
},
onlyCompileBundledFiles: true,
};
function withNodeDefaults(/**@type WebpackConfig & { context: string }*/extConfig) {
const defaultConfig = {
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
target: 'node', // extensions run in a node context
node: {
__dirname: false // leave the __dirname-behaviour intact
},
resolve: {
conditionNames: ['import', 'require', 'node-addons', 'node'],
mainFields: ['module', 'main'],
extensions: ['.ts', '.js'], // support ts-files and js-files
extensionAlias: {
// this is needed to resolve dynamic imports that now require the .js extension
'.js': ['.js', '.ts'],
}
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
// configure TypeScript loader:
// * enable sources maps for end-to-end source maps
loader: 'ts-loader',
options: tsLoaderOptions
},
// disable mangling for now, SEE https://github.com/microsoft/vscode/issues/204692
// {
// loader: path.resolve(import.meta.dirname, 'mangle-loader.js'),
// options: {
// configFile: path.join(extConfig.context, 'tsconfig.json')
// },
// },
]
}]
},
externals: {
'electron': 'commonjs electron', // ignored to avoid bundling from node_modules
'vscode': 'commonjs vscode', // ignored because it doesn't exist,
'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics', // ignored because we don't ship native module
'@azure/functions-core': 'commonjs azure/functions-core', // optional dependency of appinsights that we don't use
'@opentelemetry/tracing': 'commonjs @opentelemetry/tracing', // ignored because we don't ship this module
'@opentelemetry/instrumentation': 'commonjs @opentelemetry/instrumentation', // ignored because we don't ship this module
'@azure/opentelemetry-instrumentation-azure-sdk': 'commonjs @azure/opentelemetry-instrumentation-azure-sdk', // ignored because we don't ship this module
},
output: {
// all output goes into `dist`.
// packaging depends on that and this must always be like it
filename: '[name].js',
path: path.join(extConfig.context, 'dist'),
libraryTarget: 'commonjs',
},
// yes, really source maps
devtool: 'source-map',
plugins: nodePlugins(extConfig.context),
};
return merge(defaultConfig, extConfig);
}
/**
*
* @param {string} context
*/
function nodePlugins(context) {
// Need to find the top-most `package.json` file
const folderName = path.relative(import.meta.dirname, context).split(/[\\\/]/)[0];
const pkgPath = path.join(import.meta.dirname, folderName, 'package.json');
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
const id = `${pkg.publisher}.${pkg.name}`;
return [
new CopyWebpackPlugin({
patterns: [
{ from: 'src', to: '.', globOptions: { ignore: ['**/test/**', '**/*.ts'] }, noErrorOnMissing: true }
]
})
];
}
/**
* @typedef {{
* configFile?: string
* }} AdditionalBrowserConfig
*/
function withBrowserDefaults(/**@type WebpackConfig & { context: string }*/extConfig, /** @type AdditionalBrowserConfig */ additionalOptions = {}) {
/** @type WebpackConfig */
const defaultConfig = {
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
target: 'webworker', // extensions run in a webworker context
resolve: {
mainFields: ['browser', 'module', 'main'],
extensions: ['.ts', '.js'], // support ts-files and js-files
fallback: {
'path': require.resolve('path-browserify'),
'os': require.resolve('os-browserify'),
'util': require.resolve('util')
},
extensionAlias: {
// this is needed to resolve dynamic imports that now require the .js extension
'.js': ['.js', '.ts'],
},
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
// configure TypeScript loader:
// * enable sources maps for end-to-end source maps
loader: 'ts-loader',
options: {
...tsLoaderOptions,
// ...(additionalOptions ? {} : { configFile: additionalOptions.configFile }),
}
},
// disable mangling for now, SEE https://github.com/microsoft/vscode/issues/204692
// {
// loader: path.resolve(import.meta.dirname, 'mangle-loader.js'),
// options: {
// configFile: path.join(extConfig.context, additionalOptions?.configFile ?? 'tsconfig.json')
// },
// },
]
}, {
test: /\.wasm$/,
type: 'asset/inline'
}]
},
externals: {
'vscode': 'commonjs vscode', // ignored because it doesn't exist,
'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics', // ignored because we don't ship native module
'@azure/functions-core': 'commonjs azure/functions-core', // optional dependency of appinsights that we don't use
'@opentelemetry/tracing': 'commonjs @opentelemetry/tracing', // ignored because we don't ship this module
'@opentelemetry/instrumentation': 'commonjs @opentelemetry/instrumentation', // ignored because we don't ship this module
'@azure/opentelemetry-instrumentation-azure-sdk': 'commonjs @azure/opentelemetry-instrumentation-azure-sdk', // ignored because we don't ship this module
},
performance: {
hints: false
},
output: {
// all output goes into `dist`.
// packaging depends on that and this must always be like it
filename: '[name].js',
path: path.join(extConfig.context, 'dist', 'browser'),
libraryTarget: 'commonjs',
},
// yes, really source maps
devtool: 'source-map',
plugins: browserPlugins(extConfig.context)
};
return merge(defaultConfig, extConfig);
}
/**
*
* @param {string} context
*/
function browserPlugins(context) {
// Need to find the top-most `package.json` file
// const folderName = path.relative(__dirname, context).split(/[\\\/]/)[0];
// const pkgPath = path.join(__dirname, folderName, 'package.json');
// const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
// const id = `${pkg.publisher}.${pkg.name}`;
return [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'src', to: '.', globOptions: { ignore: ['**/test/**', '**/*.ts'] }, noErrorOnMissing: true }
]
}),
new webpack.DefinePlugin({
'process.platform': JSON.stringify('web'),
'process.env': JSON.stringify({}),
'process.env.BROWSER_ENV': JSON.stringify('true')
})
];
}
export default withNodeDefaults;
export { withNodeDefaults as node, withBrowserDefaults as browser, nodePlugins, browserPlugins };

1445
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -145,6 +145,7 @@
"@types/sinon-test": "^2.4.2",
"@types/trusted-types": "^2.0.7",
"@types/vscode-notebook-renderer": "^1.72.0",
"@types/webpack": "^5.28.5",
"@types/wicg-file-system-access": "^2023.10.7",
"@types/windows-foreground-love": "^0.3.0",
"@types/winreg": "^1.2.30",
@@ -167,6 +168,8 @@
"asar": "^3.0.3",
"chromium-pickle-js": "^0.2.0",
"cookie": "^0.7.2",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.9.1",
"debounce": "^1.0.0",
"deemon": "^1.13.6",
"electron": "39.6.0",
@@ -176,6 +179,7 @@
"eslint-plugin-jsdoc": "^50.3.1",
"event-stream": "3.3.4",
"fancy-log": "^1.3.3",
"file-loader": "^6.2.0",
"glob": "^5.0.13",
"gulp": "^4.0.0",
"gulp-azure-storage": "^0.12.1",
@@ -216,12 +220,17 @@
"sinon-test": "^3.1.3",
"source-map": "0.6.1",
"source-map-support": "^0.3.2",
"style-loader": "^3.3.2",
"tar": "^7.5.9",
"ts-loader": "^9.5.1",
"tsec": "0.2.7",
"tslib": "^2.6.3",
"typescript": "^6.0.0-dev.20260130",
"typescript-eslint": "^8.45.0",
"util": "^0.12.4",
"webpack": "^5.105.0",
"webpack-cli": "^5.1.4",
"webpack-stream": "^7.0.0",
"xml2js": "^0.5.0",
"yaserver": "^0.4.0"
},

View File

@@ -12,8 +12,9 @@ import { INotificationService } from '../../../platform/notification/common/noti
import { IStorageService } from '../../../platform/storage/common/storage.js';
import { IThemeService } from '../../../platform/theme/common/themeService.js';
import { ActiveAuxiliaryContext, AuxiliaryBarFocusContext } from '../../../workbench/common/contextkeys.js';
import { ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_TOP_ACTIVE_BORDER, ACTIVITY_BAR_TOP_DRAG_AND_DROP_BORDER, ACTIVITY_BAR_TOP_FOREGROUND, ACTIVITY_BAR_TOP_INACTIVE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_DRAG_AND_DROP_BORDER, PANEL_INACTIVE_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_BORDER, SIDE_BAR_TITLE_BORDER, SIDE_BAR_FOREGROUND } from '../../../workbench/common/theme.js';
import { ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_TOP_ACTIVE_BORDER, ACTIVITY_BAR_TOP_DRAG_AND_DROP_BORDER, ACTIVITY_BAR_TOP_FOREGROUND, ACTIVITY_BAR_TOP_INACTIVE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_DRAG_AND_DROP_BORDER, PANEL_INACTIVE_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_TITLE_BORDER, SIDE_BAR_FOREGROUND } from '../../../workbench/common/theme.js';
import { contrastBorder } from '../../../platform/theme/common/colorRegistry.js';
import { sessionsSidebarBorder } from '../../common/theme.js';
import { IViewDescriptorService, ViewContainerLocation } from '../../../workbench/common/views.js';
import { IExtensionService } from '../../../workbench/services/extensions/common/extensions.js';
import { IWorkbenchLayoutService, Parts } from '../../../workbench/services/layout/browser/layoutService.js';
@@ -105,7 +106,7 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
{
hasTitle: true,
trailingSeparator: false,
borderWidth: () => (this.getColor(SIDE_BAR_BORDER) || this.getColor(contrastBorder)) ? 1 : 0,
borderWidth: () => (this.getColor(sessionsSidebarBorder) || this.getColor(contrastBorder)) ? 1 : 0,
},
AuxiliaryBarPart.activeViewSettingsKey,
ActiveAuxiliaryContext.bindTo(contextKeyService),
@@ -141,7 +142,7 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
// Store background and border as CSS variables for the card styling on .part
container.style.setProperty('--part-background', this.getColor(SIDE_BAR_BACKGROUND) || '');
container.style.setProperty('--part-border-color', this.getColor(SIDE_BAR_BORDER) || this.getColor(contrastBorder) || 'transparent');
container.style.setProperty('--part-border-color', this.getColor(sessionsSidebarBorder) || this.getColor(contrastBorder) || 'transparent');
container.style.backgroundColor = 'transparent';
container.style.color = this.getColor(SIDE_BAR_FOREGROUND) || '';

View File

@@ -14,8 +14,9 @@ import { IContextMenuService } from '../../../platform/contextview/browser/conte
import { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
import { IThemeService } from '../../../platform/theme/common/themeService.js';
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BORDER, PANEL_TITLE_BADGE_BACKGROUND, PANEL_TITLE_BADGE_FOREGROUND } from '../../../workbench/common/theme.js';
import { PANEL_BACKGROUND, PANEL_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BORDER, PANEL_TITLE_BADGE_BACKGROUND, PANEL_TITLE_BADGE_FOREGROUND } from '../../../workbench/common/theme.js';
import { contrastBorder } from '../../../platform/theme/common/colorRegistry.js';
import { sessionsSidebarBorder } from '../../common/theme.js';
import { INotificationService } from '../../../platform/notification/common/notification.js';
import { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';
import { assertReturnsDefined } from '../../../base/common/types.js';
@@ -129,7 +130,7 @@ export class PanelPart extends AbstractPaneCompositePart {
// Store background and border as CSS variables for the card styling on .part
container.style.setProperty('--part-background', this.getColor(PANEL_BACKGROUND) || '');
container.style.setProperty('--part-border-color', this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || 'transparent');
container.style.setProperty('--part-border-color', this.getColor(sessionsSidebarBorder) || this.getColor(contrastBorder) || 'transparent');
container.style.backgroundColor = 'transparent';
// Clear inline borders - the card appearance uses CSS border-radius instead

View File

@@ -13,6 +13,7 @@ Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerDefaultCon
'chat.customizationsMenu.userStoragePath': '~/.copilot',
'chat.viewSessions.enabled': false,
'chat.implicitContext.suggestedContext': false,
'chat.implicitContext.enabled': { 'panel': 'never' },
'breadcrumbs.enabled': false,

View File

@@ -33,6 +33,7 @@ import {
} from './tools/languageModelToolsService.js';
import { agentSlashCommandToMarkdown, agentToMarkdown } from './widget/chatContentParts/chatMarkdownDecorationsRenderer.js';
import { Target } from '../common/promptSyntax/service/promptsService.js';
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
export class ChatSlashCommandsContribution extends Disposable {
@@ -49,6 +50,7 @@ export class ChatSlashCommandsContribution extends Disposable {
@IDialogService dialogService: IDialogService,
@INotificationService notificationService: INotificationService,
@IStorageService storageService: IStorageService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
) {
super();
this._store.add(slashCommandService.registerSlashCommand({
@@ -102,16 +104,18 @@ export class ChatSlashCommandsContribution extends Disposable {
}, async () => {
await commandService.executeCommand(ManagePluginsAction.ID);
}));
this._store.add(slashCommandService.registerSlashCommand({
command: 'debug',
detail: nls.localize('debug', "Show Chat Debug View"),
sortText: 'z3_debug',
executeImmediately: true,
silent: true,
locations: [ChatAgentLocation.Chat],
}, async () => {
await commandService.executeCommand('github.copilot.debug.showChatLogView');
}));
if (!this.environmentService.isSessionsWindow) {
this._store.add(slashCommandService.registerSlashCommand({
command: 'debug',
detail: nls.localize('debug', "Show Chat Debug View"),
sortText: 'z3_debug',
executeImmediately: true,
silent: true,
locations: [ChatAgentLocation.Chat],
}, async () => {
await commandService.executeCommand('github.copilot.debug.showChatLogView');
}));
}
this._store.add(slashCommandService.registerSlashCommand({
command: 'agents',
detail: nls.localize('agents', "Configure custom agents"),

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
"private": true,
"scripts": {
"compile": "node ../../node_modules/typescript/bin/tsc",
"bundle-webpack": "webpack --config ./webpack.config.js --bail",
"bundle-webpack": "node ../../node_modules/webpack/bin/webpack --config ./webpack.config.js --bail",
"esm-check": "node esm-check/esm-check.js",
"test": "node runner.js"
},
@@ -14,11 +14,6 @@
"@types/chai": "^4.2.14",
"axe-playwright": "^2.1.0",
"chai": "^4.2.0",
"css-loader": "^6.9.1",
"file-loader": "^6.2.0",
"style-loader": "^3.3.2",
"warnings-to-errors-webpack-plugin": "^2.3.0",
"webpack": "^5.105.0",
"webpack-cli": "^5.1.4"
"warnings-to-errors-webpack-plugin": "^2.3.0"
}
}