Skip to content

Commit 199f69c

Browse files
BridgeARclaudedd-octo-sts[bot]
authored
chore: update eslint unicorn plugin to v65 (#8838)
* chore: update eslint unicorn plugin to v65 * fixup! * perf(core): replace split-then-index with an allocation-free getSegment Reading `str.split(sep)[i]` allocates the full segment array, and the unicorn rule's `split(sep, i + 1)[i]` rewrite is worse for a string separator: passing a limit drops V8 off its constant-limit fast path, paying a per-call ToUint32 plus the array allocation. `getSegment` scans with `indexOf` and slices out the one segment the caller wants. Node 24.15 / V8 13.6, 5M ops x 7 trials, drop best+worst: " " [1] helper 24.6ns split 30.6ns (-20%) split+limit 86.6ns "-" [0] helper 25.4ns split 35.9ns (-29%) split+limit 74.3ns "." [0] helper 16.0ns split 36.4ns (-56%) split+limit 67.2ns * test: cover uncovered diff lines from the unicorn v65 rewrite The unicorn autofix touched branches no existing spec exercised: 1. ws: a connection carrying x-forwarded-proto now asserts the server span's http.url resolves to wss, reaching getRequestProtocol's proxy arm (and the getSegment call inside it). 2. oracledb: a callback-form pool.getConnection pins the callback path, which only the promise form covered before. The ai-sdk `messages.findLast(...)` arm is left for the PR author: covering it needs a VCR cassette recorded against a real OPENAI_API_KEY, since the test agent matches cassettes by request body and runs CI in 404-on-miss mode. Test-only, no production code changes. * test(ai): cover the messages.findLast() arm in setTextGenerationTags and setObjectGenerationTags The two methods use promptInfo.messages.findLast() when the caller passes a messages array without a top-level prompt string. Existing tests all use the prompt: '' form, which short-circuits to promptInfo.prompt and leaves lines 234 and 250 uncovered. Both new tests use an inline mock fetch (same pattern as the prompt-cache capture tests), bypassing the VCR proxy so no cassette recording is needed: - generateText with messages: array and three turns verifies that the last user message is extracted as inputValue. - generateObject with output: 'no-schema' and the same messages array verifies the same path in setObjectGenerationTags. Both tests skip ai < 5.0.0 where the mock-fetch provider wiring differs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(fastify): keep the addHook wrapper allocation-free on the fast path The wrapper declared `wrappedHook (...args)`, which materialises a fresh args array on every fastify hook invocation, including the common case where none of the wrap-fed channels has a subscriber. Forward the `arguments` object untouched on the fast path and copy or index it only in the slow path, so the default request path allocates nothing. * chore(deps): update eslint to v10, unicorn to v68, switch to eslint-plugin-import-x The eslint 9->10 and unicorn 65->68 bumps turn on a large set of new recommended rules. The newly-firing ones are deactivated in the config with per-rule counts, grouped by intent (autofixable follow-up, needs-audit, never-activate), so this bump stays free of production source churn; enabling them is left to follow-ups. Some deactivated rules may surface real bugs (unicorn/no-duplicate-logical-operands, no-duplicate-if-branches, no-loop-iterable-mutation, and the core no-unassigned-vars); their config comments flag them for a focused audit. Changes the bump requires directly: 1. Port the repo's custom eslint rules to the v10 context API; context.getSourceCode() was removed in favour of context.sourceCode. 2. eslint 10 drops Node.js 18, so .nvmrc moves to 22. 3. Rename getRunInChildContextSubtype and drop an unnecessary String.raw to satisfy the two rules kept on (consistent-compound-words, prefer-string-raw). 4. Remove stale unicorn/no-array-for-each disable directives; the rule was renamed to no-for-each, which is deactivated here. * chore: deduplicate yarn.lock * Apply suggestion from @BridgeAR * test(llmobs): use installed OpenAI fixture version The message extraction tests referenced a helper that does not exist, so lint failed before the versioned provider fixture could load. * ci(lint): update validation code for unicorn v68 The validation code landed after the branch's previous base, so Unicorn 68's new checks only surfaced once the branch was rebased. * chore(lint): use Array.at for latest Cypress screenshot handler * test(cypress): cover latest manual screenshot handler * ci(licenses): include deduplicated vendor dependencies npm list represents hoisted transitive packages without a resolved URL. Skipping those entries makes the local license gate report valid attributions as extraneous when the root dependency graph no longer supplies the same package. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: dd-octo-sts[bot] <200755185+dd-octo-sts[bot]@users.noreply.github.com>
1 parent fbd459a commit 199f69c

71 files changed

Lines changed: 802 additions & 1104 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ci/test-optimization-validation/command-output-policy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ function assertOutputParentsUnchanged (state) {
108108
}
109109
}
110110

111-
const lastExisting = state.parentIdentities[state.parentIdentities.length - 1].path
111+
const lastExisting = state.parentIdentities.at(-1).path
112112
const relative = path.relative(lastExisting, path.dirname(state.outputPath))
113113
let current = lastExisting
114114
for (const segment of relative ? relative.split(path.sep) : []) {

ci/test-optimization-validation/command-runner.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ function formatApprovalArgument (value) {
645645
const argument = String(value)
646646
if (/^[A-Za-z0-9_@%+=:,./\\-]+$/.test(argument)) return argument
647647
if (process.platform === 'win32') return JSON.stringify(argument)
648-
return `'${argument.replaceAll('\'', String.raw`'"'"'`)}'`
648+
return `'${argument.replaceAll('\'', '\'"\'"\'')}'`
649649
}
650650

651651
function serializeDisplayCommand (command) {

ci/test-optimization-validation/command-suitability.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ function isProducedBySetup (framework, localPath) {
101101
return false
102102
}
103103

104+
/**
105+
* @param {{ usesShell?: boolean, argv?: string[] }} command
106+
* @param {string} repositoryRoot
107+
*/
104108
function getRepositoryYarnError (command, repositoryRoot) {
105109
if (command.usesShell || path.basename(command.argv?.[0] || '') !== 'yarn') return
106110

@@ -112,7 +116,7 @@ function getRepositoryYarnError (command, repositoryRoot) {
112116
.sort()
113117
} catch {}
114118
if (releases?.length > 0) {
115-
const release = path.posix.join('.yarn', 'releases', releases[releases.length - 1])
119+
const release = path.posix.join('.yarn', 'releases', releases.at(-1))
116120
return `uses bare "yarn", but this repository pins ${release}. Use the structured command ` +
117121
`argv [process.execPath, "${release}", ...] so validation does not depend on an ambient Yarn shim.`
118122
}

ci/test-optimization-validation/plan-writer.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ function formatExecutionPlan ({
136136
'preloads are shown as package names; the validator resolves them from the installed `dd-trace` package.',
137137
''
138138
)
139-
for (const framework of manifest.frameworks.filter(entry => entry.status === 'runnable')) {
139+
for (const framework of manifest.frameworks) {
140+
if (framework.status !== 'runnable') continue
141+
140142
appendFrameworkExecutions(
141143
lines,
142144
framework,
@@ -273,7 +275,9 @@ function formatApprovalSummary ({
273275
}
274276

275277
lines.push('', '## Commands', '')
276-
for (const framework of manifest.frameworks.filter(entry => entry.status === 'runnable')) {
278+
for (const framework of manifest.frameworks) {
279+
if (framework.status !== 'runnable') continue
280+
277281
appendApprovalSummaryFramework(lines, framework, requestedScenario, repositoryRoot)
278282
}
279283

@@ -490,7 +494,9 @@ function getApprovalSummaryPath (out) {
490494
* @returns {void}
491495
*/
492496
function assertPlannedExecutablesAvailable (manifest, requestedScenario) {
493-
for (const framework of manifest.frameworks.filter(entry => entry.status === 'runnable')) {
497+
for (const framework of manifest.frameworks) {
498+
if (framework.status !== 'runnable') continue
499+
494500
const plannedCommands = getPlannedCommands(framework, requestedScenario)
495501
for (const plannedCommand of plannedCommands) {
496502
const executable = getUnavailableExecutable(plannedCommand.command)
@@ -1016,7 +1022,9 @@ function formatFrameworkLabel (framework, repositoryRoot) {
10161022
*/
10171023
function appendCommandIntegrity (lines, manifest, requestedScenario) {
10181024
const executables = new Map()
1019-
for (const framework of manifest.frameworks.filter(entry => entry.status === 'runnable')) {
1025+
for (const framework of manifest.frameworks) {
1026+
if (framework.status !== 'runnable') continue
1027+
10201028
for (const { command } of getPlannedCommands(framework, requestedScenario)) {
10211029
const executable = getApprovedExecutable(command)
10221030
if (executable) {

ci/test-optimization-validation/redaction.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ const EXACT_SECRET_ASSIGNMENT_NAME_SOURCE = [
2727
'JWT',
2828
'WEBHOOK(?:_URL)?',
2929
].join('|')
30-
const SECRET_NAME_CHARS = String.raw`[A-Za-z0-9_.-]`
30+
const SECRET_NAME_CHARS = '[A-Za-z0-9_.-]'
3131
const SECRET_ASSIGNMENT_NAME_SOURCE = [
32-
String.raw`(?:${EXACT_SECRET_ASSIGNMENT_NAME_SOURCE})`,
33-
String.raw`[A-Za-z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
34-
String.raw`[A-Za-z_]${SECRET_NAME_CHARS}*[-_]PASS`,
35-
String.raw`[A-Za-z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
36-
String.raw`[A-Za-z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
32+
`(?:${EXACT_SECRET_ASSIGNMENT_NAME_SOURCE})`,
33+
`[A-Za-z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
34+
`[A-Za-z_]${SECRET_NAME_CHARS}*[-_]PASS`,
35+
`[A-Za-z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
36+
`[A-Za-z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
3737
'PASS',
3838
'AUTH',
3939
'AUTHORIZATION',
@@ -68,7 +68,7 @@ const SECRET_FLAG_PATTERN = new RegExp(
6868
'gi'
6969
)
7070
const SECRET_FLAG_NAME_PATTERN = new RegExp(
71-
String.raw`^--(?:${SECRET_FLAG_SOURCE})(?:-[A-Za-z0-9]+)*$`,
71+
`^--(?:${SECRET_FLAG_SOURCE})(?:-[A-Za-z0-9]+)*$`,
7272
'i'
7373
)
7474
const AUTH_HEADER_PATTERN = /\b(Bearer)\s+([^\s'",}\]]+)/gi
@@ -92,10 +92,10 @@ const JWT_VALUE_PATTERN = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9
9292
const KNOWN_TOKEN_VALUE_PATTERN =
9393
/\b(?:gh[pousr]_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|glpat-[A-Za-z0-9_-]{20,}|xox[baprs]-[A-Za-z0-9-]{20,})\b/g
9494
const SECRET_HEADER_ENV_NAME_SOURCE = [
95-
String.raw`(?:${SECRET_NAME_SOURCE}|PAT|JWT|WEBHOOK(?:_URL)?)`,
96-
String.raw`[A-Za-z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
97-
String.raw`[A-Za-z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
98-
String.raw`[A-Za-z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
95+
`(?:${SECRET_NAME_SOURCE}|PAT|JWT|WEBHOOK(?:_URL)?)`,
96+
`[A-Za-z_]${SECRET_NAME_CHARS}*(?:${SECRET_NAME_SOURCE})${SECRET_NAME_CHARS}*`,
97+
`[A-Za-z_]${SECRET_NAME_CHARS}*[-_]AUTH(?:ORIZATION)?`,
98+
`[A-Za-z_]${SECRET_NAME_CHARS}*[-_](?:PAT|JWT|WEBHOOK(?:_URL)?)`,
9999
].join('|')
100100
const SECRET_HEADER_NAME_SOURCE = [
101101
'dd-api-key',

ci/test-optimization-validation/scenarios/ci-wiring.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,10 @@ function getMonorepoFindings ({ framework, command, probe }) {
694694
return findings
695695
}
696696

697+
/**
698+
* @param {object|undefined} probe
699+
* @param {string} name
700+
*/
697701
function hasProbeTool (probe, name) {
698702
const signals = [
699703
...(probe?.wrapperSignals || []),
@@ -703,6 +707,9 @@ function hasProbeTool (probe, name) {
703707
return signals.some(signal => signal.name === name)
704708
}
705709

710+
/**
711+
* @param {Array<{ name?: string }>} signals
712+
*/
706713
function formatToolNames (signals) {
707714
const names = []
708715
const seen = new Set()
@@ -715,9 +722,12 @@ function formatToolNames (signals) {
715722

716723
if (names.length === 0) return ''
717724
if (names.length === 1) return names[0]
718-
return `${names.slice(0, -1).join(', ')} and ${names[names.length - 1]}`
725+
return `${names.slice(0, -1).join(', ')} and ${names.at(-1)}`
719726
}
720727

728+
/**
729+
* @param {string|undefined} frameworkName
730+
*/
721731
function getDisplayFrameworkName (frameworkName) {
722732
return {
723733
cucumber: 'Cucumber',

eslint-rules/eslint-prefer-assert-match.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default {
4747
},
4848

4949
create (context) {
50-
const sourceCode = context.getSourceCode()
50+
const sourceCode = context.sourceCode
5151

5252
return {
5353
CallExpression (node) {

eslint-rules/eslint-require-boolean-assert-message.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export default {
106106

107107
if (isTrivialExpression(firstArg)) return
108108

109-
const sourceCode = context.getSourceCode()
109+
const sourceCode = context.sourceCode
110110
const fixMessage = buildAutofixMessage(firstArg, sourceCode)
111111

112112
context.report({

eslint-rules/eslint-safe-typeof-object.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default {
2323
) {
2424
// Get the expression being checked (x or x.y)
2525
const targetNode = node.left.argument
26-
const targetExpression = context.getSourceCode().getText(targetNode)
26+
const targetExpression = context.sourceCode.getText(targetNode)
2727

2828
const hasNullCheck = isGuardedInLogicalExpression(node, targetNode) ||
2929
isGuardedInConditionalExpression(node, targetNode) ||
@@ -384,7 +384,7 @@ function isGuardedByIfStatement (node, targetNode) {
384384
}
385385

386386
function walkAst (context, node, visitor) {
387-
const visitorKeys = context.getSourceCode().visitorKeys
387+
const visitorKeys = context.sourceCode.visitorKeys
388388

389389
/** @type {unknown[]} */
390390
const stack = [node]

eslint.config.mjs

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { readFileSync } from 'fs'
66
import eslintPluginJs from '@eslint/js'
77
import eslintPluginStylistic from '@stylistic/eslint-plugin'
88
import eslintPluginCypress from 'eslint-plugin-cypress'
9-
import eslintPluginImport from 'eslint-plugin-import'
9+
import eslintPluginImport from 'eslint-plugin-import-x'
1010
import eslintPluginJSDoc from 'eslint-plugin-jsdoc'
1111
import eslintPluginMocha from 'eslint-plugin-mocha'
1212
import eslintPluginN from 'eslint-plugin-n'
@@ -265,7 +265,7 @@ export default [
265265
'import/no-self-import': 'error',
266266
'import/order': ['error', {
267267
// `dd-trace` must be allowed first (and is often intentionally required before any other module).
268-
// eslint-plugin-import defaults can exclude some import types (notably `builtin`) from `pathGroups`,
268+
// eslint-plugin-import-x defaults can exclude some import types (notably `builtin`) from `pathGroups`,
269269
// which would make the `dd-trace` exception below a no-op. Make this explicit.
270270
pathGroupsExcludedImportTypes: [],
271271
pathGroups: [
@@ -324,6 +324,9 @@ export default [
324324
'no-sequences': 'error',
325325
'no-template-curly-in-string': 'error',
326326
'no-throw-literal': 'error',
327+
// Surfaces pre-existing latent bugs (always-undefined vars in tests/intake helpers)
328+
// unrelated to this tooling bump; worth a focused follow-up.
329+
'no-unassigned-vars': 'off',
327330
'no-undef-init': 'error',
328331
'no-unmodified-loop-condition': 'error',
329332
'no-unneeded-ternary': ['error', { defaultAssignment: false }],
@@ -353,6 +356,8 @@ export default [
353356
'prefer-const': ['error', { destructuring: 'all' }],
354357
'prefer-promise-reject-errors': 'error',
355358
'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
359+
// Newly enabled by the ESLint 10 bump; deferred with no-unassigned-vars above.
360+
'preserve-caught-error': 'off',
356361
'promise/param-names': 'error',
357362
'symbol-description': 'error',
358363
'unicode-bom': ['error', 'never'],
@@ -580,41 +585,121 @@ export default [
580585

581586
...eslintPluginUnicorn.configs.recommended.rules,
582587

583-
// Overriding recommended unicorn rules
584-
'unicorn/catch-error-name': ['off', { name: 'err' }], // 166 errors
588+
// Overriding recommended unicorn rules.
589+
// Rules not listed here are left at the `recommended` default. The v65→v68 bump
590+
// turned ~130 rules on in `recommended`; the entries below are the ones that fire
591+
// on our source and are intentionally kept off (counts are from the v68 run).
592+
'unicorn/catch-error-name': ['off', { name: 'err' }], // Many errors
585593
'unicorn/expiring-todo-comments': 'off',
586-
'unicorn/explicit-length-check': 'off', // 68 errors
587-
'unicorn/filename-case': ['off', { case: 'kebabCase' }], // 59 errors
588-
'unicorn/prefer-at': 'off', // 17 errors | Difficult to fix
589-
'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }],
590-
'unicorn/prevent-abbreviations': 'off', // too strict
594+
'unicorn/filename-case': ['off', { case: 'kebabCase' }], // Many errors
595+
'unicorn/name-replacements': 'off', // Many errors | naming churn (split out of prevent-abbreviations)
596+
'unicorn/prevent-abbreviations': 'off', // Many errors
591597

592598
// These rules require a newer Node.js version than we support
593599
'unicorn/no-array-reverse': 'off', // Node.js 20
594600
'unicorn/no-array-sort': 'off', // Node.js 20
601+
'unicorn/prefer-dispose': 'off', // Explicit resource management (newer Node.js)
602+
'unicorn/prefer-iterator-to-array': 'off', // Iterator helpers (Node.js 22)
603+
'unicorn/prefer-iterator-to-array-at-end': 'off', // Iterator helpers (Node.js 22)
604+
'unicorn/prefer-promise-with-resolvers': 'off', // 6 errors | Promise.withResolvers (Node.js 22)
605+
'unicorn/prefer-temporal': 'off', // Temporal is not stable on supported Node.js
606+
'unicorn/prefer-uint8array-base64': 'off', // Uint8Array base64 (Node.js 22)
595607

596-
// These rules could potentially evaluated again at a much later point
608+
// These rules could potentially be evaluated again at a much later point
609+
'unicorn/class-reference-in-static-methods': 'off', // 6 errors
610+
'unicorn/consistent-class-member-order': 'off', // 55 errors | ordering churn
611+
'unicorn/consistent-conditional-object-spread': 'off', // 3 errors
612+
'unicorn/consistent-optional-chaining': 'off', // 3 errors
613+
'unicorn/explicit-length-check': 'off', // Not a big advantage
614+
'unicorn/explicit-timer-delay': 'off', // Covered by our own timer lint rules
597615
'unicorn/no-array-callback-reference': 'off',
616+
'unicorn/no-computed-property-existence-check': 'off', // 160 errors | needs an audit
617+
'unicorn/no-declarations-before-early-exit': 'off', // 62 errors
618+
'unicorn/no-duplicate-if-branches': 'off', // 1 error | may surface real bugs
619+
'unicorn/no-duplicate-logical-operands': 'off', // 2 errors | may surface real bugs
620+
'unicorn/no-error-property-assignment': 'off', // 6 errors
598621
'unicorn/no-for-loop': 'off', // Activate if this is resolved https://github.com/sindresorhus/eslint-plugin-unicorn/issues/2664
599-
'unicorn/no-nested-ternary': 'off', // Not really an issue in the code and the benefit is small
622+
'unicorn/no-incorrect-template-string-interpolation': 'off', // 3 errors | audit for real bugs first
623+
'unicorn/no-invalid-argument-count': 'off', // 98 errors | high false-positive risk, worth a focused pass
624+
'unicorn/no-loop-iterable-mutation': 'off', // 2 errors | may surface real bugs
625+
'unicorn/no-nonstandard-builtin-properties': 'off', // 34 errors | needs an audit
600626
'unicorn/no-this-assignment': 'off', // This would need some further refactoring and the benefit is small
627+
'unicorn/no-undeclared-class-members': 'off', // 272 errors | requires declaring every field
628+
'unicorn/no-unreadable-array-destructuring': 'off', // 4 errors | not autofixable, needs manual rewrite
629+
'unicorn/no-unreadable-for-of-expression': 'off', // 32 errors
630+
'unicorn/no-unreadable-object-destructuring': 'off', // 57 errors
631+
'unicorn/no-unsafe-string-replacement': 'off', // 6 errors
632+
'unicorn/no-useless-recursion': 'off', // 2 errors
601633
'unicorn/prefer-code-point': 'off', // Should be activated, but needs a refactor of some code
634+
'unicorn/prefer-early-return': 'off', // 67 errors | tension with our positive-`if` style
635+
'unicorn/prefer-hoisting-branch-code': 'off', // 2 errors | reshapes branch bodies
636+
'unicorn/prefer-minimal-ternary': 'off', // 24 errors
637+
'unicorn/prefer-number-is-safe-integer': 'off', // 17 errors
638+
'unicorn/prefer-object-iterable-methods': 'off', // 56 errors
639+
'unicorn/prefer-queue-microtask': 'off', // process.nextTick semantics differ
640+
'unicorn/prefer-smaller-scope': 'off', // 3 errors
641+
'unicorn/prefer-split-limit': 'off', // 23 errors
642+
'unicorn/require-array-sort-compare': 'off', // 8 errors | may surface real default-sort bugs
602643

603644
// The following rules should not be activated!
645+
'unicorn/consistent-boolean-name': 'off', // Would rename public API and config booleans
604646
'unicorn/import-style': 'off', // Questionable benefit
647+
'unicorn/max-nested-calls': 'off', // Questionable benefit
605648
'unicorn/no-array-reduce': 'off', // Questionable benefit
606-
'unicorn/no-hex-escape': 'off', // Questionable benefit
649+
'unicorn/no-array-splice': 'off', // toSpliced copies the whole array (perf)
650+
'unicorn/no-break-in-nested-loop': 'off', // Conflicts with our performance-oriented loops
651+
'unicorn/no-global-object-property-assignment': 'off', // We use globalThis[Symbol.for('dd-trace')]
652+
'unicorn/no-nested-ternary': 'off', // Not really an issue in the code and the benefit is small
607653
'unicorn/no-new-array': 'off', // new Array is often used for performance reasons
608654
'unicorn/no-null': 'off', // We do not control external APIs and it is hard to differentiate these
655+
'unicorn/no-return-array-push': 'off', // Questionable benefit
656+
'unicorn/no-this-outside-of-class': 'off', // This will not work for us
657+
'unicorn/no-top-level-assignment-in-function': 'off', // Module-level singletons are assigned from functions
658+
'unicorn/no-useless-else': 'off', // Covered by core no-else-return
659+
'unicorn/operator-assignment': 'off', // Covered by core operator-assignment
660+
'unicorn/prefer-array-last-methods': 'off', // Questionable benefit
661+
'unicorn/prefer-await': 'off', // We avoid async/await in production hot paths
609662
'unicorn/prefer-event-target': 'off', // Benefit only outside of Node.js
610663
'unicorn/prefer-global-this': 'off', // Questionable benefit in Node.js alone
664+
'unicorn/prefer-includes-over-repeated-comparisons': 'off', // Bad for performance
611665
'unicorn/prefer-math-trunc': 'off', // Math.trunc is not a 1-to-1 replacement for most of our usage
612666
'unicorn/prefer-module': 'off', // We use CJS
613667
'unicorn/prefer-node-protocol': 'off', // May not be used due to guardrails
668+
'unicorn/prefer-number-coercion': 'off', // Number() is not a 1-to-1 replacement for parseInt/parseFloat
669+
'unicorn/prefer-private-class-fields': 'off', // Many `_underscore` fields cross module boundaries
614670
'unicorn/prefer-reflect-apply': 'off', // Questionable benefit and more than 500 matches
671+
'unicorn/prefer-short-arrow-method': 'off', // Method shorthand is intentional; arrow properties change `this`
615672
'unicorn/prefer-switch': 'off', // Questionable benefit
616673
'unicorn/prefer-top-level-await': 'off', // Only useful when using ESM
674+
'unicorn/prefer-unicode-code-point-escapes': 'off', // Replaces the dropped no-hex-escape; questionable benefit
617675
'unicorn/switch-case-braces': 'off', // Questionable benefit
676+
677+
// Safe to enable in a follow-up: autofixable and aligned with our style. Kept off
678+
// here only to keep this version bump free of source churn (counts from the v68 run).
679+
'unicorn/logical-assignment-operators': 'off', // 42 errors | matches our ??=/||= usage
680+
'unicorn/no-confusing-array-splice': 'off', // 1 error
681+
'unicorn/no-for-each': 'off', // 10 errors | we already prefer for-of in production
682+
'unicorn/no-negated-array-predicate': 'off', // 2 errors
683+
'unicorn/no-negated-comparison': 'off', // 1 error
684+
'unicorn/no-subtraction-comparison': 'off', // 2 errors
685+
'unicorn/no-unnecessary-boolean-comparison': 'off', // 6 errors
686+
'unicorn/no-unnecessary-global-this': 'off', // 4 errors
687+
'unicorn/no-unnecessary-splice': 'off', // 2 errors
688+
'unicorn/no-useless-concat': 'off', // 4 errors
689+
'unicorn/no-useless-continue': 'off', // 1 error
690+
'unicorn/no-useless-delete-check': 'off', // 1 error
691+
'unicorn/no-useless-fallback-in-spread': 'off', // 5 errors
692+
'unicorn/no-useless-override': 'off', // 1 error
693+
'unicorn/no-useless-template-literals': 'off', // 13 errors
694+
'unicorn/prefer-array-from-map': 'off', // 6 errors
695+
'unicorn/prefer-boolean-return': 'off', // 1 error
696+
'unicorn/prefer-continue': 'off', // 52 errors
697+
'unicorn/prefer-direct-iteration': 'off', // 5 errors
698+
'unicorn/prefer-else-if': 'off', // 6 errors
699+
'unicorn/prefer-global-number-constants': 'off', // 3 errors
700+
'unicorn/prefer-logical-operator-over-ternary': 'off', // 3 errors
701+
'unicorn/prefer-ternary': 'off', // 16 errors
702+
'unicorn/prefer-unary-minus': 'off', // 1 error
618703
},
619704
},
620705
{

0 commit comments

Comments
 (0)