diff --git a/.prettierrc.js b/.prettierrc.js index 5e79fa06796..09e067316e2 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -26,4 +26,12 @@ module.exports = { 'vueIndentScriptAndStyle': false, 'singleAttributePerLine': true, 'experimentalOperatorPosition': 'start', + 'overrides': [ + { + files: ['build/commands/tsconfig.json'], + options: { + parser: 'jsonc', + }, + }, + ], } diff --git a/build/commands/lib/actionGuard.js b/build/commands/lib/actionGuard.js index fbc3a5ef5cb..d1ede7a81df 100644 --- a/build/commands/lib/actionGuard.js +++ b/build/commands/lib/actionGuard.js @@ -10,8 +10,10 @@ import path from 'node:path' // This function is used to get the call stack of the guarded operation. It is // stored in the guard file. function getGuardCallStack() { + // @ts-ignore const stack = new Error().stack.split('\n').slice(2) for (let i = 0; i < stack.length; i++) { + // @ts-ignore if (!stack[i].includes('at ActionGuard.')) { return 'GUARD_CALLSTACK:\n' + stack.slice(i).join('\n') } diff --git a/build/commands/lib/affectedTests.js b/build/commands/lib/affectedTests.js index 4c39110ffee..d0e2b19e5db 100644 --- a/build/commands/lib/affectedTests.js +++ b/build/commands/lib/affectedTests.js @@ -37,6 +37,7 @@ const asGnTarget = (file) => { async function getModifiedFiles(target = 'HEAD~', base = null) { const args = ['diff', '--name-only', target, base].filter((x) => x) const maxBuffer = 1024 * 1024 * 5 + // @ts-ignore return exec('git', args, { maxBuffer }).then((x) => x.stdout .trim() diff --git a/build/commands/lib/buildChromiumRelease.js b/build/commands/lib/buildChromiumRelease.js index bb5c1b83f1b..8af9d04184e 100644 --- a/build/commands/lib/buildChromiumRelease.js +++ b/build/commands/lib/buildChromiumRelease.js @@ -210,6 +210,7 @@ function buildChromiumRelease(buildOptions = {}) { Log.progressScope('make archive', () => { chromiumConfig.processArtifacts() }) + return 0 } export default buildChromiumRelease diff --git a/build/commands/lib/checkEnvironment.js b/build/commands/lib/checkEnvironment.js index fb92e0c19d0..cd164c88902 100644 --- a/build/commands/lib/checkEnvironment.js +++ b/build/commands/lib/checkEnvironment.js @@ -15,6 +15,10 @@ checkWorkingDirectoryChainOnWindows() function checkNodeVersion() { const nodeVersion = process.versions.node const requiredNodeVersion = process.env.npm_package_engines_node + if (!requiredNodeVersion) { + Log.warn('npm_package_engines_node not set. Skipping node version check.') + return + } const upgradeInstructions = 'You can upgrade Node.js by downloading it from https://nodejs.org/' @@ -24,6 +28,10 @@ function checkNodeVersion() { function checkNpmVersion() { const npmVersion = process.env.npm_config_npm_version const requiredNpmVersion = process.env.npm_package_engines_npm + if (!requiredNpmVersion) { + Log.warn('npm_package_engines_npm not set. Skipping npm version check.') + return + } const upgradeInstructions = 'You can upgrade npm by running "npm install -g npm"' diff --git a/build/commands/lib/chromiumRebaseL10n.js b/build/commands/lib/chromiumRebaseL10n.js index f70ecd90f4b..ed7cfbe4cd1 100644 --- a/build/commands/lib/chromiumRebaseL10n.js +++ b/build/commands/lib/chromiumRebaseL10n.js @@ -93,7 +93,7 @@ const copyBraveStringsToOrigin = () => { } } -const chromiumRebaseL10n = async (options) => { +const chromiumRebaseL10n = async () => { resetChromeStringFiles() const removed = await l10nUtil.rebaseBraveStringFilesOnChromiumL10nFiles() l10nUtil.getBraveAutoGeneratedPaths().forEach((sourceStringPath) => { diff --git a/build/commands/lib/config.js b/build/commands/lib/config.js index 6eacc295faf..88132e20e8e 100644 --- a/build/commands/lib/config.js +++ b/build/commands/lib/config.js @@ -18,6 +18,11 @@ const braveCoreDir = path.join(rootDir, 'src', 'brave') const envConfig = new EnvConfig(braveCoreDir) +/** + * @param {string[]} keyPath + * @param {any} defaultValue + * @returns {any} + */ const getEnvConfig = (keyPath, defaultValue = undefined) => { return envConfig.get(keyPath, defaultValue) } @@ -129,12 +134,14 @@ const Config = function () { this.buildToolsDir = path.join(this.srcDir, 'build') this.resourcesDir = path.join(this.rootDir, 'resources') this.depotToolsDir = envConfig.getPath(['projects', 'depot_tools', 'dir']) + assert(this.depotToolsDir, 'depot_tools dir must be set') this.depotToolsRepo = getEnvConfig([ 'projects', 'depot_tools', 'repository', 'url', ]) + assert(this.depotToolsRepo, 'depot_tools repository url must be set') this.gclientFile = path.join(this.rootDir, '.gclient') this.gclientVerbose = getEnvConfig(['gclient_verbose']) || false this.disableGclientConfigUpdate = getEnvConfig( @@ -366,8 +373,10 @@ Config.prototype.getBraveLogoIconName = function () { Config.prototype.buildArgs = function () { const version = this.braveVersion + // @ts-ignore const versionParts = version.split('+')[0].split('.') + /** @type {Record} */ let args = { 'import("//brave/build/args/brave_defaults.gni")': null, is_asan: this.isAsan(), @@ -1111,10 +1120,12 @@ Object.defineProperty(Config.prototype, 'defaultOptions', { // Brave-specific setup. env.NINJA_CORE_MULTIPLIER = Math.min( 20, + // @ts-ignore parseInt(env.NINJA_CORE_MULTIPLIER) || 20, ).toString() env.NINJA_CORE_LIMIT = Math.min( kRemoteLimit, + // @ts-ignore parseInt(env.NINJA_CORE_LIMIT) || kRemoteLimit, ).toString() @@ -1139,6 +1150,7 @@ Object.defineProperty(Config.prototype, 'defaultOptions', { if (defaultValue === undefined) { return } + // @ts-ignore const valueFromEnv = parseInt(envSisoLimits.get(key)) || defaultValue envSisoLimits.set(key, Math.min(defaultValue, valueFromEnv).toString()) }) diff --git a/build/commands/lib/depotTools.js b/build/commands/lib/depotTools.js index 6ea40b54bd1..10b49520f28 100644 --- a/build/commands/lib/depotTools.js +++ b/build/commands/lib/depotTools.js @@ -71,6 +71,7 @@ function removeDepotTools() { function installDepotTools(options = config.defaultOptions) { options.cwd = config.braveCoreDir + // @ts-ignore const enforcedDepotToolsRef = config.getProjectRef('depot_tools', null) if (enforcedDepotToolsRef && !isDepotToolsRefValid(enforcedDepotToolsRef)) { Log.error( diff --git a/build/commands/lib/envConfig.js b/build/commands/lib/envConfig.js index 7c17d25d30f..2c08614b6de 100644 --- a/build/commands/lib/envConfig.js +++ b/build/commands/lib/envConfig.js @@ -29,7 +29,7 @@ export default class EnvConfig { * @type {Record} */ #packageJson /** Raw variables from .env files. - * @type {Record} */ + * @type {NodeJS.Dict} */ #dotenvConfig /** Stored default values for assertions on the same key requests. * @type {Record} */ @@ -75,7 +75,7 @@ export default class EnvConfig { * @throws {AssertionError} If called with different defaultValue for same key * @throws {Error} If .env value cannot be parsed or has wrong type */ - get(keyPath, defaultValue) { + get(keyPath, defaultValue = undefined) { assert.notEqual(keyPath.length, 0, 'keyPath must not be empty') const keyJoined = keyPath.join('_') @@ -264,10 +264,10 @@ export default class EnvConfig { * Creates a placeholder .env file if none exists. * * @param {string} configDir - Directory containing .env file - * @returns {Record} The parsed .env file + * @returns {NodeJS.Dict} The parsed .env file */ static #loadDotenvConfig(configDir) { - /** @type {Record} */ + /** @type {NodeJS.Dict} */ let dotenvConfig = {} // Parse {configDir}/.env with all included env files. const dotenvConfigPath = path.join(configDir, '.env') @@ -293,7 +293,7 @@ export default class EnvConfig { * Format: include_env=path/to/file.env * * @param {string} envPath - Path to the main .env file to parse - * @returns {Record} The parsed .env file + * @returns {NodeJS.Dict} The parsed .env file */ static #parseEnvFileWithIncludes(envPath) { const seenFiles = new Set() @@ -318,7 +318,7 @@ export default class EnvConfig { lines.forEach((line) => { const includeEnvMatch = line.match(/^include_env=([^#]+)(?:#.*)?$/) - if (includeEnvMatch) { + if (includeEnvMatch && includeEnvMatch[1]) { const includePath = includeEnvMatch[1].trim() const resolvedPath = path.resolve(path.dirname(filePath), includePath) result += readEnvFile(resolvedPath, filePath) diff --git a/build/commands/lib/envConfig.test.js b/build/commands/lib/envConfig.test.js index 476146b2f56..c61814c7536 100644 --- a/build/commands/lib/envConfig.test.js +++ b/build/commands/lib/envConfig.test.js @@ -3,18 +3,18 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. +import assert from 'node:assert' import fs from 'node:fs' import os from 'node:os' import path from 'node:path' import EnvConfig from './envConfig.js' +import Log from './logging.js' // Mock the logging module jest.mock('./logging.js', () => ({ error: jest.fn(), })) -import Log from './logging.js' - describe('EnvConfig', () => { const configDir = '/path/to/config' const packageJsonPath = path.join(configDir, 'package.json') @@ -639,6 +639,7 @@ describe('EnvConfig', () => { const result = envConfig.getPath(['home_path']) const expected = path.join(os.homedir(), '.config/app') expect(result).toBe(expected) + assert(typeof result === 'string') expect(path.isAbsolute(result)).toBe(true) }) @@ -649,6 +650,7 @@ describe('EnvConfig', () => { const result = envConfig.getPath(['HOME', 'PATH']) const expected = path.join(os.homedir(), 'projects/brave') expect(result).toBe(expected) + assert(typeof result === 'string') expect(path.isAbsolute(result)).toBe(true) }) diff --git a/build/commands/lib/fuzzer.js b/build/commands/lib/fuzzer.js index 76685a4a810..2ea443609a7 100644 --- a/build/commands/lib/fuzzer.js +++ b/build/commands/lib/fuzzer.js @@ -32,13 +32,14 @@ const unzip = (zipFile, outdir) => { } jszip.loadAsync(data).then((zip) => { // Sensitive - zip.forEach((relativePath, zipEntry) => { + zip.forEach((_, zipEntry) => { const resolvedPath = path.join(outdir, zipEntry.name) if (!zip.file(zipEntry.name)) { if (!fs.existsSync(resolvedPath)) { fs.mkdirSync(resolvedPath) } } else { + // @ts-ignore zip .file(zipEntry.name) .async('nodebuffer') diff --git a/build/commands/lib/l10nUtil.js b/build/commands/lib/l10nUtil.js index 41764d626dd..60e199b9405 100644 --- a/build/commands/lib/l10nUtil.js +++ b/build/commands/lib/l10nUtil.js @@ -290,7 +290,9 @@ function addGrd(chromiumPath, bravePath, exclude = new Set()) { if (exclude.has(grdp)) { continue } + // @ts-ignore const chromiumGrdpPath = path.resolve(path.join(chromiumDir, grdp)) + // @ts-ignore const braveGrdpPath = path.resolve(path.join(braveDir, grdp)) // grdp files can have their own grdp parts too mapping = { @@ -317,6 +319,7 @@ function getRemovedGRDParts(mapping) { const chromiumGRDPs = getGrdPartsFromGrd(sourcePath) let removed = new Set() for (let i = 0; i < braveGRDPs.length; i++) { + // @ts-ignore if (!chromiumGRDPs.includes(braveGRDPs[i])) { removed.add(braveGRDPs[i]) } @@ -421,9 +424,12 @@ const l10nUtil = { // Crowdin manages files per grd and not per grd or grdp. // This is because only 1 xtb is created per grd per locale even if it has multiple grdp files. getBraveTopLevelPaths: () => { - return l10nUtil - .getAllBravePaths() - .filter((x) => ['grd', 'json'].includes(x.split('.').pop())) + return l10nUtil.getAllBravePaths().filter((x) => + ['grd', 'json'].includes( + // @ts-ignore + x.split('.').pop(), + ), + ) }, // Helper function to pretty print removed GRDP file names. diff --git a/build/commands/lib/start.js b/build/commands/lib/start.js index 472aacfe54a..1b1029bc3c4 100644 --- a/build/commands/lib/start.js +++ b/build/commands/lib/start.js @@ -3,6 +3,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. +import assert from 'node:assert' import path from 'node:path' import fs from 'fs-extra' import config from './config.js' @@ -87,6 +88,7 @@ const start = ( let userDataDir if (options.user_data_dir_name) { if (process.platform === 'darwin') { + assert(process.env.HOME, 'HOME not set') userDataDir = path.join( process.env.HOME, 'Library', @@ -95,12 +97,14 @@ const start = ( options.user_data_dir_name, ) } else if (process.platform === 'win32') { + assert(process.env.LocalAppData, 'LocalAppData not set') userDataDir = path.join( process.env.LocalAppData, 'BraveSoftware', options.user_data_dir_name, ) } else { + assert(process.env.HOME, 'HOME not set') userDataDir = path.join( process.env.HOME, '.config', diff --git a/build/commands/lib/syncUtils.js b/build/commands/lib/syncUtils.js index 035d779c37b..e2c22767fa5 100644 --- a/build/commands/lib/syncUtils.js +++ b/build/commands/lib/syncUtils.js @@ -204,6 +204,7 @@ function syncChromium(program) { config.rootDir, '.brave_latest_successful_sync.json', ) + // @ts-ignore const latestSyncInfo = util.readJSON(latestSyncInfoFilePath, {}) const expectedSyncInfo = { chromiumRef: requiredChromiumRef, @@ -273,7 +274,9 @@ function syncChromium(program) { util.runGclient(args) util.modifyGitExclusions(config.srcDir, { + // @ts-ignore remove: ['brave/', 'brave_origin/'], + // @ts-ignore add: ['/brave/'], }) util.writeJSON(latestSyncInfoFilePath, expectedSyncInfo) diff --git a/build/commands/lib/test.js b/build/commands/lib/test.js index ac530d74818..80242108958 100644 --- a/build/commands/lib/test.js +++ b/build/commands/lib/test.js @@ -223,7 +223,7 @@ const runTests = async ( runOptions.stdio = 'inherit' } - let progStatus = 0 + let progStatus = undefined if (config.isIOS()) { const outputDir = path.join(config.outputDir, `run_${testSuite}_out`) diff --git a/build/commands/lib/updateChromeVersion.js b/build/commands/lib/updateChromeVersion.js index 66dcdcbd266..b3378187a7f 100644 --- a/build/commands/lib/updateChromeVersion.js +++ b/build/commands/lib/updateChromeVersion.js @@ -25,14 +25,17 @@ function updateChromeVersion() { const versionLineRegex = /^(MAJOR|MINOR|BUILD|PATCH)=(\d+)$/ for (let line = 0; line < 4; ++line) { assert( + // @ts-ignore versionLines[line].search(versionLineRegex) === 0, `${versionLines[line]} (${line}) doesn't match ${versionLineRegex}`, ) if (line === 0) { // Keep MAJOR. + // @ts-ignore assert(versionLines[line].startsWith('MAJOR=')) } else { // Set MINOR, BUILD, PATCH to Brave version. + // @ts-ignore versionLines[line] = versionLines[line].replace( versionLineRegex, `$1=${braveVersionParts[line - 1]}`, diff --git a/build/commands/lib/updatePatches.js b/build/commands/lib/updatePatches.js index ce37241c378..d697c05c5c3 100644 --- a/build/commands/lib/updatePatches.js +++ b/build/commands/lib/updatePatches.js @@ -161,7 +161,7 @@ async function updatePatches( patchDirPath, ) // We only remove stale patch files if we're updating everything. - if (onlyFiles.length === 0) { + if (onlyFiles && onlyFiles.length === 0) { await removeStalePatchFiles( patchFilenames, patchDirPath, diff --git a/build/commands/lib/util.js b/build/commands/lib/util.js index 9f19089dc34..9144f1f2c60 100644 --- a/build/commands/lib/util.js +++ b/build/commands/lib/util.js @@ -207,7 +207,7 @@ const util = { let prog = util.run('git', gitArgs, { cwd: repoPath, continueOnFail, ...options}) if (prog.status !== 0) { - return null + return '' } else { return prog.stdout.toString().trim() } @@ -388,6 +388,7 @@ const util = { } const chromiumSrcDir = path.join(config.srcDir, 'brave', 'chromium_src') + // @ts-ignore const sourceFiles = util.walkSync(chromiumSrcDir, applyFileFilter) const additionalGen = getAdditionalGenLocation() @@ -450,6 +451,7 @@ const util = { const cacheFileFilter = (file) => { return file.endsWith('.cache') || file.endsWith('.cache.sha256') } + // @ts-ignore for (const file of util.walkSync(reproxyCacheDir, cacheFileFilter)) { fs.rmSync(file) } @@ -830,7 +832,7 @@ const util = { .split('\n') }, - massRename: (options = {}) => { + massRename: () => { let cmdOptions = config.defaultOptions cmdOptions.cwd = config.braveCoreDir util.run( @@ -858,6 +860,7 @@ const util = { fs.readdirSync(dir).forEach((file) => { if (fs.statSync(path.join(dir, file)).isDirectory()) { filelist = util.walkSync(path.join(dir, file), filter, filelist) + // @ts-ignore } else if (!filter || filter.call(null, file)) { filelist = filelist.concat(path.join(dir, file)) } @@ -896,6 +899,9 @@ const util = { // Returns the actual .git dir in case a worktree is used. const gitDir = util.runGit(repoDir, ['rev-parse', '--git-common-dir'], false) + if (!gitDir) { + return null + } if (!path.isAbsolute(gitDir)) { return path.join(repoDir, gitDir) } diff --git a/build/commands/scripts/commands.js b/build/commands/scripts/commands.js index aab0cd52878..2ff41048b2c 100644 --- a/build/commands/scripts/commands.js +++ b/build/commands/scripts/commands.js @@ -48,6 +48,7 @@ function parseInteger(string) { const parsedArgs = program.parseOptions(process.argv) +// @ts-ignore program.version(process.env.npm_package_version) program.command('versions').action(versions) diff --git a/build/commands/scripts/format.js b/build/commands/scripts/format.js index 8d03dbd7d9d..c54df787b53 100644 --- a/build/commands/scripts/format.js +++ b/build/commands/scripts/format.js @@ -171,7 +171,7 @@ const runPrettierForFile = async (file, dryRun, ignorePath) => { }) if (fileInfo.ignored || !fileInfo.inferredParser) { - return + return '' } const options = await prettier.resolveConfig(file) @@ -184,6 +184,7 @@ const runPrettierForFile = async (file, dryRun, ignorePath) => { if (content !== formatted) { return await handleDifference(file, dryRun, formatted) } + return '' } const runPrettier = async (files, dryRun) => { @@ -210,7 +211,7 @@ const runPrettier = async (files, dryRun) => { const runMojomFormatForFile = async (file, dryRun) => { if (!file.endsWith('.mojom')) { - return + return '' } // Mojom formatting is experimental. Only these files are formatted by now. const mojomFormatAllowList = ['**/brave_wallet/**/*.mojom'] @@ -218,12 +219,12 @@ const runMojomFormatForFile = async (file, dryRun) => { if ( !mojomFormatAllowList.some((pattern) => path.matchesGlob(file, pattern)) ) { - return + return '' } const content = await fs.readFile(file, { encoding: 'utf-8' }) if (!content) { - return + return '' } const mojomFormatArgs = [ @@ -253,6 +254,7 @@ const runMojomFormatForFile = async (file, dryRun) => { if (content !== formatted) { return await handleDifference(file, dryRun, formatted) } + return '' } const runMojomFormat = async (files, dryRun) => { diff --git a/build/commands/scripts/sync.js b/build/commands/scripts/sync.js index cf5866ef053..116523ec5d1 100644 --- a/build/commands/scripts/sync.js +++ b/build/commands/scripts/sync.js @@ -17,6 +17,7 @@ import syncUtil from '../lib/syncUtils.js' import sisoUtils from '../lib/sisoUtils.js' program + // @ts-ignore .version(process.env.npm_package_version) .option('--gclient_verbose', 'verbose output for gclient') .option('--target_os ', 'comma-separated target OS list') diff --git a/build/commands/scripts/updatePatches.js b/build/commands/scripts/updatePatches.js index 43f45a9b292..d26ef8e0f6d 100644 --- a/build/commands/scripts/updatePatches.js +++ b/build/commands/scripts/updatePatches.js @@ -12,6 +12,7 @@ function loadChromiumPathFilter(filePath) { const configLines = fs .readFileSync(filePath, 'utf-8') .split('\n') + // @ts-ignore .map((line) => line.split('#')[0].trim()) // Removing comments. .filter((line) => line.length > 0) diff --git a/build/commands/tsconfig.json b/build/commands/tsconfig.json index c63bf474680..40b3f6c190d 100644 --- a/build/commands/tsconfig.json +++ b/build/commands/tsconfig.json @@ -29,6 +29,14 @@ // `obj[key]` returns `T | undefined` instead of `T`. "noUncheckedIndexedAccess": true, // Require explicit `break` or `return` in switch cases. - "noFallthroughCasesInSwitch": true - } + "noFallthroughCasesInSwitch": true, + // Issue an error if a function does not return a value. + "noImplicitReturns": true, + // Issue an error if a value is used as if it were `null` or `undefined`. + "strictNullChecks": true, + // Issue an error if a local variable is declared and not used. + "noUnusedLocals": true, + // Issue an error if a value is declared and not used. + "noUnusedParameters": true, + }, }