Enable more ts checks in build/commands. (#34341)

This commit is contained in:
Aleksei Khoroshilov
2026-03-10 14:11:32 +00:00
committed by GitHub
parent 8378c4d212
commit ecb96b1fef
23 changed files with 94 additions and 23 deletions
+8
View File
@@ -26,4 +26,12 @@ module.exports = {
'vueIndentScriptAndStyle': false,
'singleAttributePerLine': true,
'experimentalOperatorPosition': 'start',
'overrides': [
{
files: ['build/commands/tsconfig.json'],
options: {
parser: 'jsonc',
},
},
],
}
+2
View File
@@ -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')
}
+1
View File
@@ -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()
@@ -210,6 +210,7 @@ function buildChromiumRelease(buildOptions = {}) {
Log.progressScope('make archive', () => {
chromiumConfig.processArtifacts()
})
return 0
}
export default buildChromiumRelease
+8
View File
@@ -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"'
+1 -1
View File
@@ -93,7 +93,7 @@ const copyBraveStringsToOrigin = () => {
}
}
const chromiumRebaseL10n = async (options) => {
const chromiumRebaseL10n = async () => {
resetChromeStringFiles()
const removed = await l10nUtil.rebaseBraveStringFilesOnChromiumL10nFiles()
l10nUtil.getBraveAutoGeneratedPaths().forEach((sourceStringPath) => {
+12
View File
@@ -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<string, any>} */
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())
})
+1
View File
@@ -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(
+6 -6
View File
@@ -29,7 +29,7 @@ export default class EnvConfig {
* @type {Record<string, any>} */
#packageJson
/** Raw variables from .env files.
* @type {Record<string, string>} */
* @type {NodeJS.Dict<string>} */
#dotenvConfig
/** Stored default values for assertions on the same key requests.
* @type {Record<string, any>} */
@@ -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<string, string>} The parsed .env file
* @returns {NodeJS.Dict<string>} The parsed .env file
*/
static #loadDotenvConfig(configDir) {
/** @type {Record<string, string>} */
/** @type {NodeJS.Dict<string>} */
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<string, string>} The parsed .env file
* @returns {NodeJS.Dict<string>} 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)
+4 -2
View File
@@ -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)
})
+2 -1
View File
@@ -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')
+9 -3
View File
@@ -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.
+4
View File
@@ -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',
+3
View File
@@ -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)
+1 -1
View File
@@ -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`)
@@ -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]}`,
+1 -1
View File
@@ -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,
+8 -2
View File
@@ -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)
}
+1
View File
@@ -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)
+6 -4
View File
@@ -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) => {
+1
View File
@@ -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 <target_os>', 'comma-separated target OS list')
+1
View File
@@ -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)
+10 -2
View File
@@ -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,
},
}