diff --git a/build/gulpfile.cli.mjs b/build/gulpfile.cli.ts similarity index 85% rename from build/gulpfile.cli.mjs rename to build/gulpfile.cli.ts index efad44e17a5..8336765e0b0 100644 --- a/build/gulpfile.cli.mjs +++ b/build/gulpfile.cli.ts @@ -12,12 +12,11 @@ import * as cp from 'child_process'; import { tmpdir } from 'os'; import { existsSync, mkdirSync, rmSync } from 'fs'; import * as task from './lib/task.ts'; -import * as watcher from './lib/watch/index.ts'; +import watcher from './lib/watch/index.ts'; import * as utilModule from './lib/util.ts'; import * as reporterModule from './lib/reporter.ts'; import untar from 'gulp-untar'; import gunzip from 'gulp-gunzip'; -import { fileURLToPath } from 'url'; const { debounce } = utilModule; const { createReporter } = reporterModule; @@ -43,8 +42,7 @@ const platformOpensslDirName = const platformOpensslDir = path.join(rootAbs, 'openssl', 'package', 'out', platformOpensslDirName); const hasLocalRust = (() => { - /** @type boolean | undefined */ - let result = undefined; + let result: boolean | undefined = undefined; return () => { if (result !== undefined) { return result; @@ -61,15 +59,14 @@ const hasLocalRust = (() => { }; })(); -const compileFromSources = (callback) => { +const compileFromSources = (callback: (err?: string) => void) => { const proc = cp.spawn('cargo', ['--color', 'always', 'build'], { cwd: root, stdio: ['ignore', 'pipe', 'pipe'], env: existsSync(platformOpensslDir) ? { OPENSSL_DIR: platformOpensslDir, ...process.env } : process.env }); - /** @type Buffer[] */ - const stdoutErr = []; + const stdoutErr: Buffer[] = []; proc.stdout.on('data', d => stdoutErr.push(d)); proc.stderr.on('data', d => stdoutErr.push(d)); proc.on('error', callback); @@ -82,7 +79,7 @@ const compileFromSources = (callback) => { }); }; -const acquireBuiltOpenSSL = (callback) => { +const acquireBuiltOpenSSL = (callback: (err?: unknown) => void) => { const dir = path.join(tmpdir(), 'vscode-openssl-download'); mkdirSync(dir, { recursive: true }); @@ -103,29 +100,28 @@ const acquireBuiltOpenSSL = (callback) => { }); }; -const compileWithOpenSSLCheck = (/** @type import('./lib/reporter').IReporter */ reporter) => es.map((_, callback) => { +const compileWithOpenSSLCheck = (reporter: import('./lib/reporter.ts').IReporter) => es.map((_, callback) => { compileFromSources(err => { if (!err) { - // no-op + callback(); } else if (err.toString().includes('Could not find directory of OpenSSL installation') && !existsSync(platformOpensslDir)) { fancyLog(ansiColors.yellow(`[cli]`), 'OpenSSL libraries not found, acquiring prebuilt bits...'); acquireBuiltOpenSSL(err => { if (err) { - callback(err); + callback(err as Error); } else { compileFromSources(err => { if (err) { reporter(err.toString()); } - callback(null, ''); + callback(); }); } }); } else { reporter(err.toString()); + callback(); } - - callback(null, ''); }); }); @@ -147,8 +143,14 @@ const compileCliTask = task.define('compile-cli', () => { const watchCliTask = task.define('watch-cli', () => { warnIfRustNotInstalled(); + const compile = () => { + const reporter = createReporter('cli'); + return gulp.src(`${root}/Cargo.toml`) + .pipe(compileWithOpenSSLCheck(reporter)) + .pipe(reporter.end(true)); + }; return watcher(`${src}/**`, { read: false }) - .pipe(debounce(compileCliTask)); + .pipe(debounce(compile)); }); gulp.task(compileCliTask); diff --git a/build/gulpfile.compile.mjs b/build/gulpfile.compile.ts similarity index 92% rename from build/gulpfile.compile.mjs rename to build/gulpfile.compile.ts index e79a61b0f43..fcfdf2dca57 100644 --- a/build/gulpfile.compile.mjs +++ b/build/gulpfile.compile.ts @@ -2,17 +2,14 @@ * 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 gulp from 'gulp'; import * as util from './lib/util.ts'; import * as date from './lib/date.ts'; import * as task from './lib/task.ts'; import * as compilation from './lib/compilation.ts'; -/** - * @param {boolean} disableMangle - */ -function makeCompileBuildTask(disableMangle) { +function makeCompileBuildTask(disableMangle: boolean) { return task.series( util.rimraf('out-build'), date.writeISODate('out-build'), diff --git a/build/gulpfile.editor.mjs b/build/gulpfile.editor.ts similarity index 94% rename from build/gulpfile.editor.mjs rename to build/gulpfile.editor.ts index b5ff549fc36..394a2cf2b6d 100644 --- a/build/gulpfile.editor.mjs +++ b/build/gulpfile.editor.ts @@ -2,7 +2,7 @@ * 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 gulp from 'gulp'; import path from 'path'; import * as util from './lib/util.ts'; @@ -84,10 +84,7 @@ const compileEditorESMTask = task.define('compile-editor-esm', () => { ); }); -/** - * @param {string} contents - */ -function toExternalDTS(contents) { +function toExternalDTS(contents: string) { const lines = contents.split(/\r\n|\r|\n/); let killNextCloseCurlyBrace = false; for (let i = 0; i < lines.length; i++) { @@ -230,10 +227,7 @@ gulp.task('monacodts', task.define('monacodts', () => { //#region monaco type checking -/** - * @param {boolean} watch - */ -function createTscCompileTask(watch) { +function createTscCompileTask(watch: boolean) { return () => { return new Promise((resolve, reject) => { const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit']; @@ -244,11 +238,10 @@ function createTscCompileTask(watch) { cwd: path.join(import.meta.dirname, '..'), // stdio: [null, 'pipe', 'inherit'] }); - const errors = []; + const errors: string[] = []; const reporter = createReporter('monaco'); - /** @type {NodeJS.ReadWriteStream | undefined} */ - let report; + let report: NodeJS.ReadWriteStream | undefined; const magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings child.stdout.on('data', data => { @@ -287,13 +280,7 @@ export const monacoTypecheckTask = task.define('monaco-typecheck', createTscComp //#endregion -/** - * Sets a field on an object only if it's not already set, otherwise throws an error - * @param {any} obj - The object to modify - * @param {string} field - The field name to set - * @param {any} value - The value to set - */ -function setUnsetField(obj, field, value) { +function setUnsetField(obj: Record, field: string, value: unknown) { if (obj[field] !== undefined) { throw new Error(`Field "${field}" is already set (but was expected to not be).`); } diff --git a/build/gulpfile.extensions.mjs b/build/gulpfile.extensions.ts similarity index 96% rename from build/gulpfile.extensions.mjs rename to build/gulpfile.extensions.ts index a31584f187a..ad3e5c386c5 100644 --- a/build/gulpfile.extensions.mjs +++ b/build/gulpfile.extensions.ts @@ -22,7 +22,6 @@ import plumber from 'gulp-plumber'; import * as ext from './lib/extensions.ts'; import * as tsb from './lib/tsb/index.ts'; import sourcemaps from 'gulp-sourcemaps'; -import { fileURLToPath } from 'url'; const { getVersion } = getVersionModule; const { createReporter } = reporterModule; @@ -79,13 +78,13 @@ const compilations = [ '.vscode/extensions/vscode-selfhost-import-aid/tsconfig.json', ]; -const getBaseUrl = out => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`; +const getBaseUrl = (out: string) => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`; const tasks = compilations.map(function (tsconfigFile) { const absolutePath = path.join(root, tsconfigFile); const relativeDirname = path.dirname(tsconfigFile.replace(/^(.*\/)?extensions\//i, '')); - const overrideOptions = {}; + const overrideOptions: { sourceMap?: boolean; inlineSources?: boolean; base?: string } = {}; overrideOptions.sourceMap = true; const name = relativeDirname.replace(/\//g, '-'); @@ -98,7 +97,7 @@ const tasks = compilations.map(function (tsconfigFile) { const out = path.join(srcRoot, 'out'); const baseUrl = getBaseUrl(out); - function createPipeline(build, emitError, transpileOnly) { + function createPipeline(build: boolean, emitError?: boolean, transpileOnly?: boolean) { const reporter = createReporter('extensions'); overrideOptions.inlineSources = Boolean(build); @@ -122,14 +121,14 @@ const tasks = compilations.map(function (tsconfigFile) { .pipe(compilation()) .pipe(build ? util.stripSourceMappingURL() : es.through()) .pipe(sourcemaps.write('.', { - sourceMappingURL: !build ? null : f => `${baseUrl}/${f.relative}.map`, + sourceMappingURL: !build ? undefined : f => `${baseUrl}/${f.relative}.map`, addComment: !!build, includeContent: !!build, // note: trailing slash is important, else the source URLs in V8's file coverage are incorrect sourceRoot: '../src/', })) .pipe(tsFilter.restore) - .pipe(reporter.end(emitError)); + .pipe(reporter.end(!!emitError)); return es.duplex(input, output); }; @@ -266,10 +265,7 @@ gulp.task(compileWebExtensionsTask); export const watchWebExtensionsTask = task.define('watch-web', () => buildWebExtensions(true)); gulp.task(watchWebExtensionsTask); -/** - * @param {boolean} isWatch - */ -async function buildWebExtensions(isWatch) { +async function buildWebExtensions(isWatch: boolean) { const extensionsPath = path.join(root, 'extensions'); const webpackConfigLocations = await nodeUtil.promisify(glob)( path.join(extensionsPath, '**', 'extension-browser.webpack.config.js'), diff --git a/build/gulpfile.hygiene.mjs b/build/gulpfile.hygiene.ts similarity index 91% rename from build/gulpfile.hygiene.mjs rename to build/gulpfile.hygiene.ts index a435869d685..24595643c86 100644 --- a/build/gulpfile.hygiene.mjs +++ b/build/gulpfile.hygiene.ts @@ -11,13 +11,10 @@ import { hygiene } from './hygiene.ts'; const dirName = path.dirname(new URL(import.meta.url).pathname); -/** - * @param {string} actualPath - */ -function checkPackageJSON(actualPath) { +function checkPackageJSON(this: NodeJS.ReadWriteStream, actualPath: string) { const actual = JSON.parse(fs.readFileSync(path.join(dirName, '..', actualPath), 'utf8')); const rootPackageJSON = JSON.parse(fs.readFileSync(path.join(dirName, '..', 'package.json'), 'utf8')); - const checkIncluded = (set1, set2) => { + const checkIncluded = (set1: Record, set2: Record) => { for (const depName in set1) { const depVersion = set1[depName]; const rootDepVersion = set2[depName]; diff --git a/build/gulpfile.reh.mjs b/build/gulpfile.reh.ts similarity index 86% rename from build/gulpfile.reh.mjs rename to build/gulpfile.reh.ts index aa5e6a9682e..e74c9fbd870 100644 --- a/build/gulpfile.reh.mjs +++ b/build/gulpfile.reh.ts @@ -7,16 +7,16 @@ import gulp from 'gulp'; import * as path from 'path'; import es from 'event-stream'; import * as util from './lib/util.ts'; -import * as getVersionModule from './lib/getVersion.ts'; +import { getVersion } from './lib/getVersion.ts'; import * as task from './lib/task.ts'; import * as optimize from './lib/optimize.ts'; -import * as inlineMetaModule from './lib/inlineMeta.ts'; +import { inlineMeta } from './lib/inlineMeta.ts'; import product from '../product.json' with { type: 'json' }; import rename from 'gulp-rename'; import replace from 'gulp-replace'; import filter from 'gulp-filter'; -import * as dependenciesModule from './lib/dependencies.ts'; -import * as dateModule from './lib/date.ts'; +import { getProductionDependencies } from './lib/dependencies.ts'; +import { readISODate } from './lib/date.ts'; import vfs from 'vinyl-fs'; import packageJson from '../package.json' with { type: 'json' }; import flatmap from 'gulp-flatmap'; @@ -25,21 +25,15 @@ import untar from 'gulp-untar'; import File from 'vinyl'; import * as fs from 'fs'; import glob from 'glob'; -import { compileBuildWithManglingTask } from './gulpfile.compile.mjs'; -import { cleanExtensionsBuildTask, compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileExtensionMediaBuildTask } from './gulpfile.extensions.mjs'; -import { vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } from './gulpfile.vscode.web.mjs'; +import { compileBuildWithManglingTask } from './gulpfile.compile.ts'; +import { cleanExtensionsBuildTask, compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileExtensionMediaBuildTask } from './gulpfile.extensions.ts'; +import { vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } from './gulpfile.vscode.web.ts'; import * as cp from 'child_process'; import log from 'fancy-log'; import buildfile from './buildfile.ts'; -import { fileURLToPath } from 'url'; -import * as fetchModule from './lib/fetch.ts'; +import { fetchUrls, fetchGithub } from './lib/fetch.ts'; import jsonEditor from 'gulp-json-editor'; -const { inlineMeta } = inlineMetaModule; -const { getVersion } = getVersionModule; -const { getProductionDependencies } = dependenciesModule; -const { readISODate } = dateModule; -const { fetchUrls, fetchGithub } = fetchModule; const REPO_ROOT = path.dirname(import.meta.dirname); const commit = getVersion(REPO_ROOT); @@ -146,12 +140,12 @@ const bootstrapEntryPoints = [ function getNodeVersion() { const npmrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.npmrc'), 'utf8'); - const nodeVersion = /^target="(.*)"$/m.exec(npmrc)[1]; - const internalNodeVersion = /^ms_build_id="(.*)"$/m.exec(npmrc)[1]; + const nodeVersion = /^target="(.*)"$/m.exec(npmrc)![1]; + const internalNodeVersion = /^ms_build_id="(.*)"$/m.exec(npmrc)![1]; return { nodeVersion, internalNodeVersion }; } -function getNodeChecksum(expectedName) { +function getNodeChecksum(expectedName: string): string | undefined { const nodeJsChecksums = fs.readFileSync(path.join(REPO_ROOT, 'build', 'checksums', 'nodejs.txt'), 'utf8'); for (const line of nodeJsChecksums.split('\n')) { const [checksum, name] = line.split(/\s+/); @@ -162,11 +156,12 @@ function getNodeChecksum(expectedName) { return undefined; } -function extractAlpinefromDocker(nodeVersion, platform, arch) { +function extractAlpinefromDocker(nodeVersion: string, platform: string, arch: string) { const imageName = arch === 'arm64' ? 'arm64v8/node' : 'node'; log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from docker image ${imageName}`); const contents = cp.execSync(`docker run --rm ${imageName}:${nodeVersion}-alpine /bin/sh -c 'cat \`which node\`'`, { maxBuffer: 100 * 1024 * 1024, encoding: 'buffer' }); - return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } })]); + // eslint-disable-next-line local/code-no-dangerous-type-assertions + return es.readArray([new File({ path: 'node', contents, stat: { mode: parseInt('755', 8) } as fs.Stats })]); } const { nodeVersion, internalNodeVersion } = getNodeVersion(); @@ -178,7 +173,7 @@ BUILD_TARGETS.forEach(({ platform, arch }) => { if (!fs.existsSync(nodePath)) { util.rimraf(nodePath); - return nodejs(platform, arch) + return nodejs(platform, arch)! .pipe(vfs.dest(nodePath)); } @@ -189,10 +184,10 @@ BUILD_TARGETS.forEach(({ platform, arch }) => { const defaultNodeTask = gulp.task(`node-${process.platform}-${process.arch}`); if (defaultNodeTask) { - gulp.task(task.define('node', defaultNodeTask)); + gulp.task(task.define('node', () => defaultNodeTask)); } -function nodejs(platform, arch) { +function nodejs(platform: string, arch: string): NodeJS.ReadWriteStream | undefined { if (arch === 'armhf') { arch = 'armv7l'; @@ -204,7 +199,7 @@ function nodejs(platform, arch) { log(`Downloading node.js ${nodeVersion} ${platform} ${arch} from ${product.nodejsRepository}...`); const glibcPrefix = process.env['VSCODE_NODE_GLIBC'] ?? ''; - let expectedName; + let expectedName: string | undefined; switch (platform) { case 'win32': expectedName = product.nodejsRepository !== 'https://nodejs.org' ? @@ -221,7 +216,7 @@ function nodejs(platform, arch) { expectedName = `node-v${nodeVersion}-linux-${arch}-musl.tar.gz`; break; } - const checksumSha256 = getNodeChecksum(expectedName); + const checksumSha256 = expectedName ? getNodeChecksum(expectedName) : undefined; if (checksumSha256) { log(`Using SHA256 checksum for checking integrity: ${checksumSha256}`); @@ -232,13 +227,13 @@ function nodejs(platform, arch) { switch (platform) { case 'win32': return (product.nodejsRepository !== 'https://nodejs.org' ? - fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) : + fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName!, checksumSha256 }) : fetchUrls(`/dist/v${nodeVersion}/win-${arch}/node.exe`, { base: 'https://nodejs.org', checksumSha256 })) .pipe(rename('node.exe')); case 'darwin': case 'linux': return (product.nodejsRepository !== 'https://nodejs.org' ? - fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) : + fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName!, checksumSha256 }) : fetchUrls(`/dist/v${nodeVersion}/node-v${nodeVersion}-${platform}-${arch}.tar.gz`, { base: 'https://nodejs.org', checksumSha256 }) ).pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar()))) .pipe(filter('**/node')) @@ -246,7 +241,7 @@ function nodejs(platform, arch) { .pipe(rename('node')); case 'alpine': return product.nodejsRepository !== 'https://nodejs.org' ? - fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName, checksumSha256 }) + fetchGithub(product.nodejsRepository, { version: `${nodeVersion}-${internalNodeVersion}`, name: expectedName!, checksumSha256 }) .pipe(flatmap(stream => stream.pipe(gunzip()).pipe(untar()))) .pipe(filter('**/node')) .pipe(util.setExecutableBit('**')) @@ -255,17 +250,17 @@ function nodejs(platform, arch) { } } -function packageTask(type, platform, arch, sourceFolderName, destinationFolderName) { +function packageTask(type: string, platform: string, arch: string, sourceFolderName: string, destinationFolderName: string) { const destination = path.join(BUILD_ROOT, destinationFolderName); return () => { const src = gulp.src(sourceFolderName + '/**', { base: '.' }) - .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })) + .pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + sourceFolderName), 'out'); })) .pipe(util.setExecutableBit(['**/*.sh'])) .pipe(filter(['**', '!**/*.{js,css}.map'])); const workspaceExtensionPoints = ['debuggers', 'jsonValidation']; - const isUIExtension = (manifest) => { + const isUIExtension = (manifest: { extensionKind?: string; main?: string; contributes?: Record }) => { switch (manifest.extensionKind) { case 'ui': return true; case 'workspace': return false; @@ -294,9 +289,9 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa }).map((extensionPath) => path.basename(path.dirname(extensionPath))) .filter(name => name !== 'vscode-api-tests' && name !== 'vscode-test-resolver'); // Do not ship the test extensions const marketplaceExtensions = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'product.json'), 'utf8')).builtInExtensions - .filter(entry => !entry.platforms || new Set(entry.platforms).has(platform)) - .filter(entry => !entry.clientOnly) - .map(entry => entry.name); + .filter((entry: { platforms?: string[]; clientOnly?: boolean }) => !entry.platforms || new Set(entry.platforms).has(platform)) + .filter((entry: { clientOnly?: boolean }) => !entry.clientOnly) + .map((entry: { name: string }) => entry.name); const extensionPaths = [...localWorkspaceExtensions, ...marketplaceExtensions] .map(name => `.build/extensions/${name}/**`); @@ -306,7 +301,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa .pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true })); let version = packageJson.version; - const quality = product.quality; + const quality = (product as typeof product & { quality?: string }).quality; if (quality && quality !== 'stable') { version += '-' + quality; @@ -314,7 +309,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa const name = product.nameShort; - let packageJsonContents; + let packageJsonContents: string = ''; const packageJsonStream = gulp.src(['remote/package.json'], { base: 'remote' }) .pipe(jsonEditor({ name, version, dependencies: undefined, optionalDependencies: undefined, type: 'module' })) .pipe(es.through(function (file) { @@ -322,7 +317,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa this.emit('data', file); })); - let productJsonContents; + let productJsonContents: string = ''; const productJsonStream = gulp.src(['product.json'], { base: '.' }) .pipe(jsonEditor({ commit, date: readISODate('out-build'), version })) .pipe(es.through(function (file) { @@ -348,7 +343,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa const nodePath = `.build/node/v${nodeVersion}/${platform}-${arch}`; const node = gulp.src(`${nodePath}/**`, { base: nodePath, dot: true }); - let web = []; + let web: NodeJS.ReadWriteStream[] = []; if (type === 'reh-web') { web = [ 'resources/server/favicon.ico', @@ -376,12 +371,12 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa result = es.merge(result, gulp.src('resources/server/bin/remote-cli/code.cmd', { base: '.' }) .pipe(replace('@@VERSION@@', version)) - .pipe(replace('@@COMMIT@@', commit)) + .pipe(replace('@@COMMIT@@', commit || '')) .pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(rename(`bin/remote-cli/${product.applicationName}.cmd`)), gulp.src('resources/server/bin/helpers/browser.cmd', { base: '.' }) .pipe(replace('@@VERSION@@', version)) - .pipe(replace('@@COMMIT@@', commit)) + .pipe(replace('@@COMMIT@@', commit || '')) .pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(rename(`bin/helpers/browser.cmd`)), gulp.src('resources/server/bin/code-server.cmd', { base: '.' }) @@ -391,13 +386,13 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa result = es.merge(result, gulp.src(`resources/server/bin/remote-cli/${platform === 'darwin' ? 'code-darwin.sh' : 'code-linux.sh'}`, { base: '.' }) .pipe(replace('@@VERSION@@', version)) - .pipe(replace('@@COMMIT@@', commit)) + .pipe(replace('@@COMMIT@@', commit || '')) .pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(rename(`bin/remote-cli/${product.applicationName}`)) .pipe(util.setExecutableBit()), gulp.src(`resources/server/bin/helpers/${platform === 'darwin' ? 'browser-darwin.sh' : 'browser-linux.sh'}`, { base: '.' }) .pipe(replace('@@VERSION@@', version)) - .pipe(replace('@@COMMIT@@', commit)) + .pipe(replace('@@COMMIT@@', commit || '')) .pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(rename(`bin/helpers/browser.sh`)) .pipe(util.setExecutableBit()), @@ -425,11 +420,8 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa }; } -/** - * @param {object} product The parsed product.json file contents - */ -function tweakProductForServerWeb(product) { - const result = { ...product }; +function tweakProductForServerWeb(product: typeof import('../product.json')) { + const result: typeof product & { webEndpointUrlTemplate?: string } = { ...product }; delete result.webEndpointUrlTemplate; return result; } @@ -461,7 +453,7 @@ function tweakProductForServerWeb(product) { gulp.task(minifyTask); BUILD_TARGETS.forEach(buildTarget => { - const dashed = (str) => (str ? `-${str}` : ``); + const dashed = (str: string) => (str ? `-${str}` : ``); const platform = buildTarget.platform; const arch = buildTarget.arch; @@ -471,7 +463,13 @@ function tweakProductForServerWeb(product) { const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series( compileNativeExtensionsBuildTask, - gulp.task(`node-${platform}-${arch}`), + () => { + const nodeTask = gulp.task(`node-${platform}-${arch}`) as task.CallbackTask; + if (nodeTask) { + return nodeTask(); + } + return Promise.resolve(); + }, util.rimraf(path.join(BUILD_ROOT, destinationFolderName)), packageTask(type, platform, arch, sourceFolderName, destinationFolderName) )); diff --git a/build/gulpfile.scan.mjs b/build/gulpfile.scan.ts similarity index 80% rename from build/gulpfile.scan.mjs rename to build/gulpfile.scan.ts index 0f6b9d13b72..6aece7029c7 100644 --- a/build/gulpfile.scan.mjs +++ b/build/gulpfile.scan.ts @@ -12,9 +12,9 @@ import * as electronConfigModule from './lib/electron.ts'; import filter from 'gulp-filter'; import * as deps from './lib/dependencies.ts'; import { existsSync, readdirSync } from 'fs'; -import { fileURLToPath } from 'url'; const { config } = electronConfigModule; +const electronDest = (electron as unknown as { dest: (destination: string, options: unknown) => NodeJS.ReadWriteStream }).dest; const root = path.dirname(import.meta.dirname); @@ -35,32 +35,32 @@ const excludedCheckList = [ ]; BUILD_TARGETS.forEach(buildTarget => { - const dashed = (/** @type {string | null} */ str) => (str ? `-${str}` : ``); + const dashed = (str: string | null) => (str ? `-${str}` : ``); const platform = buildTarget.platform; const arch = buildTarget.arch; const destinationExe = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'bin'); const destinationPdb = path.join(path.dirname(root), 'scanbin', `VSCode${dashed(platform)}${dashed(arch)}`, 'pdb'); - const tasks = []; + const tasks: task.Task[] = []; // removal tasks tasks.push(util.rimraf(destinationExe), util.rimraf(destinationPdb)); // electron - tasks.push(() => electron.dest(destinationExe, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch })); + tasks.push(() => electronDest(destinationExe, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch })); // pdbs for windows if (platform === 'win32') { tasks.push( - () => electron.dest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, pdbs: true }), + () => electronDest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, pdbs: true }), () => confirmPdbsExist(destinationExe, destinationPdb) ); } if (platform === 'linux') { tasks.push( - () => electron.dest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, symbols: true }) + () => electronDest(destinationPdb, { ...config, platform, arch: arch === 'armhf' ? 'arm' : arch, symbols: true }) ); } @@ -81,7 +81,7 @@ function getProductionDependencySources() { return productionDependencies.map(d => path.relative(root, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`]).flat(); } -function nodeModules(destinationExe, destinationPdb, platform) { +function nodeModules(destinationExe: string, destinationPdb: string, platform: string): task.CallbackTask { const exe = () => { return gulp.src(getProductionDependencySources(), { base: '.', dot: true }) @@ -101,7 +101,7 @@ function nodeModules(destinationExe, destinationPdb, platform) { .pipe(gulp.dest(destinationPdb)); }; - return gulp.parallel(exe, pdb); + return gulp.parallel(exe, pdb) as task.CallbackTask; } if (platform === 'linux') { @@ -111,13 +111,13 @@ function nodeModules(destinationExe, destinationPdb, platform) { .pipe(gulp.dest(destinationPdb)); }; - return gulp.parallel(exe, pdb); + return gulp.parallel(exe, pdb) as task.CallbackTask; } return exe; } -function confirmPdbsExist(destinationExe, destinationPdb) { +function confirmPdbsExist(destinationExe: string, destinationPdb: string) { readdirSync(destinationExe).forEach(file => { if (excludedCheckList.includes(file)) { return; diff --git a/build/gulpfile.ts b/build/gulpfile.ts index f8d65580ce7..e83b9a08d28 100644 --- a/build/gulpfile.ts +++ b/build/gulpfile.ts @@ -6,8 +6,8 @@ import { EventEmitter } from 'events'; import glob from 'glob'; import gulp from 'gulp'; import { createRequire } from 'node:module'; -import { monacoTypecheckTask /* , monacoTypecheckWatchTask */ } from './gulpfile.editor.mjs'; -import { compileExtensionMediaTask, compileExtensionsTask, watchExtensionsTask } from './gulpfile.extensions.mjs'; +import { monacoTypecheckTask /* , monacoTypecheckWatchTask */ } from './gulpfile.editor.ts'; +import { compileExtensionMediaTask, compileExtensionsTask, watchExtensionsTask } from './gulpfile.extensions.ts'; import * as compilation from './lib/compilation.ts'; import * as task from './lib/task.ts'; import * as util from './lib/util.ts'; @@ -52,7 +52,7 @@ process.on('unhandledRejection', (reason, p) => { }); // Load all the gulpfiles only if running tasks other than the editor tasks -glob.sync('gulpfile.*.{mjs,js}', { cwd: import.meta.dirname }) +glob.sync('gulpfile.*.ts', { cwd: import.meta.dirname }) .forEach(f => { return require(`./${f}`); }); diff --git a/build/gulpfile.vscode.linux.mjs b/build/gulpfile.vscode.linux.ts similarity index 89% rename from build/gulpfile.vscode.linux.mjs rename to build/gulpfile.vscode.linux.ts index 5f341526389..c5d216319ce 100644 --- a/build/gulpfile.vscode.linux.mjs +++ b/build/gulpfile.vscode.linux.ts @@ -8,35 +8,33 @@ import replace from 'gulp-replace'; import rename from 'gulp-rename'; import es from 'event-stream'; import vfs from 'vinyl-fs'; -import * as utilModule from './lib/util.ts'; -import * as getVersionModule from './lib/getVersion.ts'; +import { rimraf } from './lib/util.ts'; +import { getVersion } from './lib/getVersion.ts'; import * as task from './lib/task.ts'; import packageJson from '../package.json' with { type: 'json' }; import product from '../product.json' with { type: 'json' }; import { getDependencies } from './linux/dependencies-generator.ts'; -import * as depLists from './linux/debian/dep-lists.ts'; +import { recommendedDeps as debianRecommendedDependencies } from './linux/debian/dep-lists.ts'; import * as path from 'path'; import * as cp from 'child_process'; import { promisify } from 'util'; -import { fileURLToPath } from 'url'; -const { rimraf } = utilModule; -const { getVersion } = getVersionModule; -const { recommendedDeps: debianRecommendedDependencies } = depLists; const exec = promisify(cp.exec); const root = path.dirname(import.meta.dirname); const commit = getVersion(root); const linuxPackageRevision = Math.floor(new Date().getTime() / 1000); -/** - * @param {string} arch - */ -function getDebPackageArch(arch) { - return { x64: 'amd64', armhf: 'armhf', arm64: 'arm64' }[arch]; +function getDebPackageArch(arch: string): string { + switch (arch) { + case 'x64': return 'amd64'; + case 'armhf': return 'armhf'; + case 'arm64': return 'arm64'; + default: throw new Error(`Unknown arch: ${arch}`); + } } -function prepareDebPackage(arch) { +function prepareDebPackage(arch: string) { const binaryDir = '../VSCode-linux-' + arch; const debArch = getDebPackageArch(arch); const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch; @@ -94,7 +92,7 @@ function prepareDebPackage(arch) { .pipe(replace('@@ARCHITECTURE@@', debArch)) .pipe(replace('@@DEPENDS@@', dependencies.join(', '))) .pipe(replace('@@RECOMMENDS@@', debianRecommendedDependencies.join(', '))) - .pipe(replace('@@INSTALLEDSIZE@@', Math.ceil(size / 1024))) + .pipe(replace('@@INSTALLEDSIZE@@', Math.ceil(size / 1024).toString())) .pipe(rename('DEBIAN/control')) .pipe(es.through(function (f) { that.emit('data', f); }, function () { that.emit('end'); })); })); @@ -122,10 +120,7 @@ function prepareDebPackage(arch) { }; } -/** - * @param {string} arch - */ -function buildDebPackage(arch) { +function buildDebPackage(arch: string) { const debArch = getDebPackageArch(arch); const cwd = `.build/linux/deb/${debArch}`; @@ -136,24 +131,20 @@ function buildDebPackage(arch) { }; } -/** - * @param {string} rpmArch - */ -function getRpmBuildPath(rpmArch) { +function getRpmBuildPath(rpmArch: string): string { return '.build/linux/rpm/' + rpmArch + '/rpmbuild'; } -/** - * @param {string} arch - */ -function getRpmPackageArch(arch) { - return { x64: 'x86_64', armhf: 'armv7hl', arm64: 'aarch64' }[arch]; +function getRpmPackageArch(arch: string): string { + switch (arch) { + case 'x64': return 'x86_64'; + case 'armhf': return 'armv7hl'; + case 'arm64': return 'aarch64'; + default: throw new Error(`Unknown arch: ${arch}`); + } } -/** - * @param {string} arch - */ -function prepareRpmPackage(arch) { +function prepareRpmPackage(arch: string) { const binaryDir = '../VSCode-linux-' + arch; const rpmArch = getRpmPackageArch(arch); const stripBinary = process.env['STRIP'] ?? '/usr/bin/strip'; @@ -205,11 +196,11 @@ function prepareRpmPackage(arch) { .pipe(replace('@@NAME_LONG@@', product.nameLong)) .pipe(replace('@@ICON@@', product.linuxIconName)) .pipe(replace('@@VERSION@@', packageJson.version)) - .pipe(replace('@@RELEASE@@', linuxPackageRevision)) + .pipe(replace('@@RELEASE@@', linuxPackageRevision.toString())) .pipe(replace('@@ARCHITECTURE@@', rpmArch)) .pipe(replace('@@LICENSE@@', product.licenseName)) - .pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@')) - .pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@')) + .pipe(replace('@@QUALITY@@', (product as typeof product & { quality?: string }).quality || '@@QUALITY@@')) + .pipe(replace('@@UPDATEURL@@', (product as typeof product & { updateUrl?: string }).updateUrl || '@@UPDATEURL@@')) .pipe(replace('@@DEPENDENCIES@@', dependencies.join(', '))) .pipe(replace('@@STRIP@@', stripBinary)) .pipe(rename('SPECS/' + product.applicationName + '.spec')); @@ -223,10 +214,7 @@ function prepareRpmPackage(arch) { }; } -/** - * @param {string} arch - */ -function buildRpmPackage(arch) { +function buildRpmPackage(arch: string) { const rpmArch = getRpmPackageArch(arch); const rpmBuildPath = getRpmBuildPath(rpmArch); const rpmOut = `${rpmBuildPath}/RPMS/${rpmArch}`; @@ -239,17 +227,11 @@ function buildRpmPackage(arch) { }; } -/** - * @param {string} arch - */ -function getSnapBuildPath(arch) { +function getSnapBuildPath(arch: string): string { return `.build/linux/snap/${arch}/${product.applicationName}-${arch}`; } -/** - * @param {string} arch - */ -function prepareSnapPackage(arch) { +function prepareSnapPackage(arch: string) { const binaryDir = '../VSCode-linux-' + arch; const destination = getSnapBuildPath(arch); @@ -279,7 +261,7 @@ function prepareSnapPackage(arch) { const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' }) .pipe(replace('@@NAME@@', product.applicationName)) - .pipe(replace('@@VERSION@@', commit.substr(0, 8))) + .pipe(replace('@@VERSION@@', commit!.substr(0, 8))) // Possible run-on values https://snapcraft.io/docs/architectures .pipe(replace('@@ARCHITECTURE@@', arch === 'x64' ? 'amd64' : arch)) .pipe(rename('snap/snapcraft.yaml')); @@ -293,10 +275,7 @@ function prepareSnapPackage(arch) { }; } -/** - * @param {string} arch - */ -function buildSnapPackage(arch) { +function buildSnapPackage(arch: string) { const cwd = getSnapBuildPath(arch); return () => exec('snapcraft', { cwd }); } diff --git a/build/gulpfile.vscode.mjs b/build/gulpfile.vscode.ts similarity index 90% rename from build/gulpfile.vscode.mjs rename to build/gulpfile.vscode.ts index d1d4fc5dc83..c721c1732b4 100644 --- a/build/gulpfile.vscode.mjs +++ b/build/gulpfile.vscode.ts @@ -14,33 +14,27 @@ import filter from 'gulp-filter'; import electron from '@vscode/gulp-electron'; import jsonEditor from 'gulp-json-editor'; import * as util from './lib/util.ts'; -import * as getVersionModule from './lib/getVersion.ts'; -import * as dateModule from './lib/date.ts'; +import { getVersion } from './lib/getVersion.ts'; +import { readISODate } from './lib/date.ts'; import * as task from './lib/task.ts'; import buildfile from './buildfile.ts'; import * as optimize from './lib/optimize.ts'; -import * as inlineMetaModule from './lib/inlineMeta.ts'; +import { inlineMeta } from './lib/inlineMeta.ts'; import packageJson from '../package.json' with { type: 'json' }; import product from '../product.json' with { type: 'json' }; import * as crypto from 'crypto'; import * as i18n from './lib/i18n.ts'; -import * as dependenciesModule from './lib/dependencies.ts'; -import * as electronModule from './lib/electron.ts'; -import * as asarModule from './lib/asar.ts'; +import { getProductionDependencies } from './lib/dependencies.ts'; +import { config } from './lib/electron.ts'; +import { createAsar } from './lib/asar.ts'; import minimist from 'minimist'; -import { compileBuildWithoutManglingTask, compileBuildWithManglingTask } from './gulpfile.compile.mjs'; -import { compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileAllExtensionsBuildTask, compileExtensionMediaBuildTask, cleanExtensionsBuildTask } from './gulpfile.extensions.mjs'; +import { compileBuildWithoutManglingTask, compileBuildWithManglingTask } from './gulpfile.compile.ts'; +import { compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileAllExtensionsBuildTask, compileExtensionMediaBuildTask, cleanExtensionsBuildTask } from './gulpfile.extensions.ts'; import { promisify } from 'util'; import globCallback from 'glob'; import rceditCallback from 'rcedit'; -import { fileURLToPath } from 'url'; -const { getVersion } = getVersionModule; -const { readISODate } = dateModule; -const { inlineMeta } = inlineMetaModule; -const { getProductionDependencies } = dependenciesModule; -const { config } = electronModule; -const { createAsar } = asarModule; + const glob = promisify(globCallback); const rcedit = promisify(rceditCallback); const root = path.dirname(import.meta.dirname); @@ -164,34 +158,30 @@ const minifyVSCodeTask = task.define('minify-vscode', task.series( gulp.task(minifyVSCodeTask); const coreCI = task.define('core-ci', task.series( - gulp.task('compile-build-with-mangling'), + gulp.task('compile-build-with-mangling') as task.Task, task.parallel( - gulp.task('minify-vscode'), - gulp.task('minify-vscode-reh'), - gulp.task('minify-vscode-reh-web'), + gulp.task('minify-vscode') as task.Task, + gulp.task('minify-vscode-reh') as task.Task, + gulp.task('minify-vscode-reh-web') as task.Task, ) )); gulp.task(coreCI); const coreCIPR = task.define('core-ci-pr', task.series( - gulp.task('compile-build-without-mangling'), + gulp.task('compile-build-without-mangling') as task.Task, task.parallel( - gulp.task('minify-vscode'), - gulp.task('minify-vscode-reh'), - gulp.task('minify-vscode-reh-web'), + gulp.task('minify-vscode') as task.Task, + gulp.task('minify-vscode-reh') as task.Task, + gulp.task('minify-vscode-reh-web') as task.Task, ) )); gulp.task(coreCIPR); /** * Compute checksums for some files. - * - * @param {string} out The out folder to read the file from. - * @param {string[]} filenames The paths to compute a checksum for. - * @return {Object} A map of paths to checksums. */ -function computeChecksums(out, filenames) { - const result = {}; +function computeChecksums(out: string, filenames: string[]): Record { + const result: Record = {}; filenames.forEach(function (filename) { const fullPath = path.join(process.cwd(), out, filename); result[filename] = computeChecksum(fullPath); @@ -200,12 +190,9 @@ function computeChecksums(out, filenames) { } /** - * Compute checksum for a file. - * - * @param {string} filename The absolute path to a filename. - * @return {string} The checksum for `filename`. + * Compute checksums for a file. */ -function computeChecksum(filename) { +function computeChecksum(filename: string): string { const contents = fs.readFileSync(filename); const hash = crypto @@ -217,9 +204,7 @@ function computeChecksum(filename) { return hash; } -function packageTask(platform, arch, sourceFolderName, destinationFolderName, opts) { - opts = opts || {}; - +function packageTask(platform: string, arch: string, sourceFolderName: string, destinationFolderName: string, _opts?: { stats?: boolean }) { const destination = path.join(path.dirname(root), destinationFolderName); platform = platform || process.platform; @@ -236,15 +221,15 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op ]); const src = gulp.src(out + '/**', { base: '.' }) - .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + out), 'out'); })) + .pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + out), 'out'); })) .pipe(util.setExecutableBit(['**/*.sh'])); const platformSpecificBuiltInExtensionsExclusions = product.builtInExtensions.filter(ext => { - if (!ext.platforms) { + if (!(ext as { platforms?: string[] }).platforms) { return false; } - const set = new Set(ext.platforms); + const set = new Set((ext as { platforms?: string[] }).platforms); return !set.has(platform); }).map(ext => `!.build/extensions/${ext.name}/**`); @@ -254,20 +239,20 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op .pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true })); let version = packageJson.version; - const quality = product.quality; + const quality = (product as { quality?: string }).quality; if (quality && quality !== 'stable') { version += '-' + quality; } const name = product.nameShort; - const packageJsonUpdates = { name, version }; + const packageJsonUpdates: Record = { name, version }; if (platform === 'linux') { packageJsonUpdates.desktopName = `${product.applicationName}.desktop`; } - let packageJsonContents; + let packageJsonContents: string; const packageJsonStream = gulp.src(['package.json'], { base: '.' }) .pipe(jsonEditor(packageJsonUpdates)) .pipe(es.through(function (file) { @@ -275,7 +260,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op this.emit('data', file); })); - let productJsonContents; + let productJsonContents: string; const productJsonStream = gulp.src(['product.json'], { base: '.' }) .pipe(jsonEditor({ commit, date: readISODate('out-build'), checksums, version })) .pipe(es.through(function (file) { @@ -373,7 +358,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op all = es.merge(all, shortcut, policyDest); } - let result = all + let result: NodeJS.ReadWriteStream = all .pipe(util.skipDirectories()) .pipe(util.fixWin32DirectoryPermissions()) .pipe(filter(['**', '!**/.github/**'], { dot: true })) // https://github.com/microsoft/vscode/issues/116523 @@ -401,10 +386,10 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op .pipe(replace('@@NAME@@', product.nameShort)) .pipe(replace('@@PRODNAME@@', product.nameLong)) .pipe(replace('@@VERSION@@', version)) - .pipe(replace('@@COMMIT@@', commit)) + .pipe(replace('@@COMMIT@@', commit ?? '')) .pipe(replace('@@APPNAME@@', product.applicationName)) .pipe(replace('@@SERVERDATAFOLDER@@', product.serverDataFolderName || '.vscode-remote')) - .pipe(replace('@@QUALITY@@', quality)) + .pipe(replace('@@QUALITY@@', quality ?? '')) .pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; }))); result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' }) @@ -425,7 +410,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op .pipe(replace('@@ApplicationIdShort@@', product.win32RegValueName)) .pipe(replace('@@ApplicationExe@@', product.nameShort + '.exe')) .pipe(replace('@@FileExplorerContextMenuID@@', quality === 'stable' ? 'OpenWithCode' : 'OpenWithCodeInsiders')) - .pipe(replace('@@FileExplorerContextMenuCLSID@@', product.win32ContextMenu[arch].clsid)) + .pipe(replace('@@FileExplorerContextMenuCLSID@@', (product as { win32ContextMenu?: Record }).win32ContextMenu![arch].clsid)) .pipe(replace('@@FileExplorerContextMenuDLL@@', `${quality === 'stable' ? 'code' : 'code_insider'}_explorer_command_${arch}.dll`)) .pipe(rename(f => f.dirname = `appx/manifest`))); } @@ -448,7 +433,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op return task; } -function patchWin32DependenciesTask(destinationFolderName) { +function patchWin32DependenciesTask(destinationFolderName: string) { const cwd = path.join(path.dirname(root), destinationFolderName); return async () => { @@ -489,7 +474,7 @@ const BUILD_TARGETS = [ { platform: 'linux', arch: 'arm64' }, ]; BUILD_TARGETS.forEach(buildTarget => { - const dashed = (str) => (str ? `-${str}` : ``); + const dashed = (str: string) => (str ? `-${str}` : ``); const platform = buildTarget.platform; const arch = buildTarget.arch; const opts = buildTarget.opts; @@ -532,7 +517,7 @@ BUILD_TARGETS.forEach(buildTarget => { // #region nls -const innoSetupConfig = { +const innoSetupConfig: Record = { 'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } }, 'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } }, 'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } }, diff --git a/build/gulpfile.vscode.web.mjs b/build/gulpfile.vscode.web.ts similarity index 88% rename from build/gulpfile.vscode.web.mjs rename to build/gulpfile.vscode.web.ts index 2dac0dd9a47..5371673fa6a 100644 --- a/build/gulpfile.vscode.web.mjs +++ b/build/gulpfile.vscode.web.ts @@ -7,33 +7,28 @@ import gulp from 'gulp'; import * as path from 'path'; import es from 'event-stream'; import * as util from './lib/util.ts'; -import * as getVersionModule from './lib/getVersion.ts'; +import { getVersion } from './lib/getVersion.ts'; import * as task from './lib/task.ts'; import * as optimize from './lib/optimize.ts'; -import * as dateModule from './lib/date.ts'; +import { readISODate } from './lib/date.ts'; import product from '../product.json' with { type: 'json' }; import rename from 'gulp-rename'; import filter from 'gulp-filter'; -import * as dependenciesModule from './lib/dependencies.ts'; +import { getProductionDependencies } from './lib/dependencies.ts'; import vfs from 'vinyl-fs'; import packageJson from '../package.json' with { type: 'json' }; -import { compileBuildWithManglingTask } from './gulpfile.compile.mjs'; +import { compileBuildWithManglingTask } from './gulpfile.compile.ts'; import * as extensions from './lib/extensions.ts'; import VinylFile from 'vinyl'; import jsonEditor from 'gulp-json-editor'; import buildfile from './buildfile.ts'; -import { fileURLToPath } from 'url'; - -const { getVersion } = getVersionModule; -const { readISODate } = dateModule; -const { getProductionDependencies } = dependenciesModule; const REPO_ROOT = path.dirname(import.meta.dirname); const BUILD_ROOT = path.dirname(REPO_ROOT); const WEB_FOLDER = path.join(REPO_ROOT, 'remote', 'web'); const commit = getVersion(REPO_ROOT); -const quality = product.quality; +const quality = (product as { quality?: string }).quality; const version = (quality && quality !== 'stable') ? `${packageJson.version}-${quality}` : packageJson.version; export const vscodeWebResourceIncludes = [ @@ -90,16 +85,8 @@ const vscodeWebEntryPoints = [ buildfile.entrypoint('vs/workbench/workbench.web.main.internal') // TODO@esm remove line when we stop supporting web-amd-esm-bridge ].flat(); -/** - * @param extensionsRoot {string} The location where extension will be read from - * @param {object} product The parsed product.json file contents - */ -export const createVSCodeWebFileContentMapper = (extensionsRoot, product) => { - /** - * @param {string} path - * @returns {((content: string) => string) | undefined} - */ - return path => { +export const createVSCodeWebFileContentMapper = (extensionsRoot: string, product: typeof import('../product.json')) => { + return (path: string): ((content: string) => string) | undefined => { if (path.endsWith('vs/platform/product/common/product.js')) { return content => { const productConfiguration = JSON.stringify({ @@ -143,16 +130,12 @@ const minifyVSCodeWebTask = task.define('minify-vscode-web', task.series( )); gulp.task(minifyVSCodeWebTask); -/** - * @param {string} sourceFolderName - * @param {string} destinationFolderName - */ -function packageTask(sourceFolderName, destinationFolderName) { +function packageTask(sourceFolderName: string, destinationFolderName: string) { const destination = path.join(BUILD_ROOT, destinationFolderName); return () => { const src = gulp.src(sourceFolderName + '/**', { base: '.' }) - .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })); + .pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + sourceFolderName), 'out'); })); const extensions = gulp.src('.build/web/extensions/**', { base: '.build/web', dot: true }); @@ -218,7 +201,7 @@ const compileWebExtensionsBuildTask = task.define('compile-web-extensions-build' )); gulp.task(compileWebExtensionsBuildTask); -const dashed = (/** @type {string} */ str) => (str ? `-${str}` : ``); +const dashed = (str: string) => (str ? `-${str}` : ``); ['', 'min'].forEach(minified => { const sourceFolderName = `out-vscode-web${dashed(minified)}`; diff --git a/build/gulpfile.vscode.win32.mjs b/build/gulpfile.vscode.win32.ts similarity index 86% rename from build/gulpfile.vscode.win32.mjs rename to build/gulpfile.vscode.win32.ts index 66e324d1832..a53108eb389 100644 --- a/build/gulpfile.vscode.win32.mjs +++ b/build/gulpfile.vscode.win32.ts @@ -17,15 +17,13 @@ import { createRequire } from 'module'; const require = createRequire(import.meta.url); const repoPath = path.dirname(import.meta.dirname); -const buildPath = (/** @type {string} */ arch) => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`); -const setupDir = (/** @type {string} */ arch, /** @type {string} */ target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`); +const buildPath = (arch: string) => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`); +const setupDir = (arch: string, target: string) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`); const issPath = path.join(import.meta.dirname, 'win32', 'code.iss'); const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup'))), 'bin', 'ISCC.exe'); const signWin32Path = path.join(repoPath, 'build', 'azure-pipelines', 'common', 'sign-win32.ts'); -function packageInnoSetup(iss, options, cb) { - options = options || {}; - +function packageInnoSetup(iss: string, options: { definitions?: Record }, cb: (err?: Error | null) => void) { const definitions = options.definitions || {}; if (process.argv.some(arg => arg === '--debug-inno')) { @@ -58,16 +56,12 @@ function packageInnoSetup(iss, options, cb) { }); } -/** - * @param {string} arch - * @param {string} target - */ -function buildWin32Setup(arch, target) { +function buildWin32Setup(arch: string, target: string) { if (target !== 'system' && target !== 'user') { throw new Error('Invalid setup target'); } - return cb => { + return (cb?: (err?: any) => void) => { const x64AppId = target === 'system' ? product.win32x64AppId : product.win32x64UserAppId; const arm64AppId = target === 'system' ? product.win32arm64AppId : product.win32arm64UserAppId; @@ -81,8 +75,8 @@ function buildWin32Setup(arch, target) { productJson['target'] = target; fs.writeFileSync(productJsonPath, JSON.stringify(productJson, undefined, '\t')); - const quality = product.quality || 'dev'; - const definitions = { + const quality = (product as { quality?: string }).quality || 'dev'; + const definitions: Record = { NameLong: product.nameLong, NameShort: product.nameShort, DirName: product.win32DirName, @@ -117,15 +111,11 @@ function buildWin32Setup(arch, target) { definitions['AppxPackageName'] = `${product.win32AppUserModelId}`; } - packageInnoSetup(issPath, { definitions }, cb); + packageInnoSetup(issPath, { definitions }, cb as (err?: Error | null) => void); }; } -/** - * @param {string} arch - * @param {string} target - */ -function defineWin32SetupTasks(arch, target) { +function defineWin32SetupTasks(arch: string, target: string) { const cleanTask = util.rimraf(setupDir(arch, target)); gulp.task(task.define(`vscode-win32-${arch}-${target}-setup`, task.series(cleanTask, buildWin32Setup(arch, target)))); } @@ -135,20 +125,14 @@ defineWin32SetupTasks('arm64', 'system'); defineWin32SetupTasks('x64', 'user'); defineWin32SetupTasks('arm64', 'user'); -/** - * @param {string} arch - */ -function copyInnoUpdater(arch) { +function copyInnoUpdater(arch: string) { return () => { return gulp.src('build/win32/{inno_updater.exe,vcruntime140.dll}', { base: 'build/win32' }) .pipe(vfs.dest(path.join(buildPath(arch), 'tools'))); }; } -/** - * @param {string} executablePath - */ -function updateIcon(executablePath) { +function updateIcon(executablePath: string): task.CallbackTask { return cb => { const icon = path.join(repoPath, 'resources', 'win32', 'code.ico'); rcedit(executablePath, { icon }, cb); diff --git a/build/hygiene.ts b/build/hygiene.ts index 72864a2edc0..8778907f13f 100644 --- a/build/hygiene.ts +++ b/build/hygiene.ts @@ -30,7 +30,7 @@ interface VinylFileWithLines extends VinylFile { /** * Main hygiene function that runs checks on files */ -export function hygiene(some: NodeJS.ReadWriteStream | string[], runEslint = true): NodeJS.ReadWriteStream { +export function hygiene(some: NodeJS.ReadWriteStream | string[] | undefined, runEslint = true): NodeJS.ReadWriteStream { console.log('Starting hygiene...'); let errorCount = 0; diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index 2e6756eba3f..58b8e07fdb3 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -209,7 +209,7 @@ function bundleESMTask(opts: IBundleESMTaskOpts): NodeJS.ReadWriteStream { })); } -export interface IBundleESMTaskOpts { +export interface IBundleTaskOpts { /** * Destination folder for the bundled files. */ @@ -220,7 +220,7 @@ export interface IBundleESMTaskOpts { esm: IBundleESMTaskOpts; } -export function bundleTask(opts: IBundleESMTaskOpts): () => NodeJS.ReadWriteStream { +export function bundleTask(opts: IBundleTaskOpts): () => NodeJS.ReadWriteStream { return function () { return bundleESMTask(opts.esm).pipe(gulp.dest(opts.out)); }; diff --git a/build/lib/typings/gulp-gunzip.d.ts b/build/lib/typings/gulp-gunzip.d.ts new file mode 100644 index 00000000000..a68a350d5e7 --- /dev/null +++ b/build/lib/typings/gulp-gunzip.d.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'gulp-gunzip' { + import type { Transform } from 'stream'; + + /** + * Gunzip plugin for gulp + */ + function gunzip(): Transform; + + export = gunzip; +} diff --git a/build/lib/typings/gulp-untar.d.ts b/build/lib/typings/gulp-untar.d.ts new file mode 100644 index 00000000000..7b43fd52a01 --- /dev/null +++ b/build/lib/typings/gulp-untar.d.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'gulp-untar' { + import type { Transform } from 'stream'; + + /** + * Extract TAR files + */ + function untar(): Transform; + + export = untar; +} diff --git a/build/lib/typings/rcedit.d.ts b/build/lib/typings/rcedit.d.ts new file mode 100644 index 00000000000..50a6ba7fb8f --- /dev/null +++ b/build/lib/typings/rcedit.d.ts @@ -0,0 +1,5 @@ + +declare module 'rcedit' { + + export default function rcedit(exePath, options, cb): Promise; +}