Skip to content

💅 useOptionalChain causes crashes when applied to global variables #7517

@ysulyma

Description

@ysulyma

Environment information

CLI:
  Version:                      2.2.4
  Color support:                true

Platform:
  CPU Architecture:             aarch64
  OS:                           macos

Environment:
  BIOME_LOG_PATH:               unset
  BIOME_LOG_PREFIX_NAME:        unset
  BIOME_CONFIG_PATH:            unset
  BIOME_THREADS:                unset
  NO_COLOR:                     unset
  TERM:                         xterm-kitty
  JS_RUNTIME_VERSION:           v18.20.2
  JS_RUNTIME_NAME:              node
  NODE_PACKAGE_MANAGER:         unset

Biome Configuration:
  Status:                       Loaded successfully
  Path:                         biome.json
  Formatter enabled:            true
  Linter enabled:               true
  Assist enabled:               true
  VCS enabled:                  true

Linter:
  JavaScript enabled:           unset
  JSON enabled:                 unset
  CSS enabled:                  unset
  GraphQL enabled:              unset
  Recommended:                  true
  Enabled rules:
    a11y/noAccessKey
    a11y/noAriaHiddenOnFocusable
    a11y/noAriaUnsupportedElements
    a11y/noDistractingElements
    a11y/noHeaderScope
    a11y/noInteractiveElementToNoninteractiveRole
    a11y/noNoninteractiveElementToInteractiveRole
    a11y/noNoninteractiveTabindex
    a11y/noPositiveTabindex
    a11y/noRedundantAlt
    a11y/noRedundantRoles
    a11y/useAltText
    a11y/useAriaActivedescendantWithTabindex
    a11y/useGenericFontNames
    a11y/useHtmlLang
    a11y/useIframeTitle
    a11y/useKeyWithMouseEvents
    a11y/useMediaCaption
    a11y/useValidAriaProps
    a11y/useValidAriaRole
    a11y/useValidAriaValues
    a11y/useValidAutocomplete
    a11y/useValidLang
    complexity/noAdjacentSpacesInRegex
    complexity/noArguments
    complexity/noBannedTypes
    complexity/noCommaOperator
    complexity/noEmptyTypeParameters
    complexity/noExtraBooleanCast
    complexity/noFlatMapIdentity
    complexity/noStaticOnlyClass
    complexity/noThisInStatic
    complexity/noUselessCatch
    complexity/noUselessConstructor
    complexity/noUselessContinue
    complexity/noUselessEmptyExport
    complexity/noUselessEscapeInRegex
    complexity/noUselessFragments
    complexity/noUselessLabel
    complexity/noUselessLoneBlockStatements
    complexity/noUselessRename
    complexity/noUselessStringRaw
    complexity/noUselessTernary
    complexity/noUselessThisAlias
    complexity/noUselessTypeConstraint
    complexity/useFlatMap
    complexity/useIndexOf
    complexity/useNumericLiterals
    complexity/useRegexLiterals
    complexity/useSimpleNumberKeys
    correctness/noChildrenProp
    correctness/noConstAssign
    correctness/noConstantCondition
    correctness/noConstantMathMinMaxClamp
    correctness/noConstructorReturn
    correctness/noEmptyCharacterClassInRegex
    correctness/noEmptyPattern
    correctness/noGlobalObjectCalls
    correctness/noInnerDeclarations
    correctness/noInvalidBuiltinInstantiation
    correctness/noInvalidConstructorSuper
    correctness/noInvalidDirectionInLinearGradient
    correctness/noInvalidGridAreas
    correctness/noInvalidPositionAtImportRule
    correctness/noInvalidUseBeforeDeclaration
    correctness/noMissingVarFunction
    correctness/noNonoctalDecimalEscape
    correctness/noPrecisionLoss
    correctness/noSelfAssign
    correctness/noSetterReturn
    correctness/noStringCaseMismatch
    correctness/noSwitchDeclarations
    correctness/noUnknownFunction
    correctness/noUnknownMediaFeatureName
    correctness/noUnknownProperty
    correctness/noUnknownPseudoClass
    correctness/noUnknownPseudoElement
    correctness/noUnknownTypeSelector
    correctness/noUnknownUnit
    correctness/noUnmatchableAnbSelector
    correctness/noUnreachable
    correctness/noUnreachableSuper
    correctness/noUnsafeFinally
    correctness/noUnsafeOptionalChaining
    correctness/noUnusedFunctionParameters
    correctness/noUnusedImports
    correctness/noUnusedLabels
    correctness/noUnusedPrivateClassMembers
    correctness/noUnusedVariables
    correctness/noVoidElementsWithChildren
    correctness/noVoidTypeReturn
    correctness/useExhaustiveDependencies
    correctness/useGraphqlNamedOperations
    correctness/useIsNan
    correctness/useValidForDirection
    correctness/useValidTypeof
    correctness/useYield
    performance/noDynamicNamespaceImportAccess
    security/noBlankTarget
    security/noDangerouslySetInnerHtml
    security/noDangerouslySetInnerHtmlWithChildren
    security/noGlobalEval
    style/noDescendingSpecificity
    style/noInferrableTypes
    style/noNamespace
    style/noRestrictedGlobals
    style/noRestrictedImports
    style/useArrayLiterals
    style/useAsConstAssertion
    style/useConst
    style/useDeprecatedReason
    style/useExponentiationOperator
    style/useExportType
    style/useImportType
    style/useLiteralEnumMembers
    style/useShorthandFunctionType
    suspicious/noApproximativeNumericConstant
    suspicious/noAsyncPromiseExecutor
    suspicious/noBiomeFirstException
    suspicious/noCatchAssign
    suspicious/noClassAssign
    suspicious/noCommentText
    suspicious/noCompareNegZero
    suspicious/noConfusingLabels
    suspicious/noConfusingVoidType
    suspicious/noConsole
    suspicious/noConstEnum
    suspicious/noControlCharactersInRegex
    suspicious/noDebugger
    suspicious/noDocumentCookie
    suspicious/noDoubleEquals
    suspicious/noDuplicateAtImportRules
    suspicious/noDuplicateCase
    suspicious/noDuplicateClassMembers
    suspicious/noDuplicateCustomProperties
    suspicious/noDuplicateElseIf
    suspicious/noDuplicateFields
    suspicious/noDuplicateFontNames
    suspicious/noDuplicateJsxProps
    suspicious/noDuplicateObjectKeys
    suspicious/noDuplicateParameters
    suspicious/noDuplicateProperties
    suspicious/noDuplicateSelectorsKeyframeBlock
    suspicious/noEmptyBlock
    suspicious/noEmptyInterface
    suspicious/noExplicitAny
    suspicious/noExtraNonNullAssertion
    suspicious/noFallthroughSwitchClause
    suspicious/noFunctionAssign
    suspicious/noGlobalAssign
    suspicious/noImportAssign
    suspicious/noImportantInKeyframe
    suspicious/noIrregularWhitespace
    suspicious/noLabelVar
    suspicious/noMisleadingCharacterClass
    suspicious/noMisleadingInstantiator
    suspicious/noMisrefactoredShorthandAssign
    suspicious/noOctalEscape
    suspicious/noQuickfixBiome
    suspicious/noRedeclare
    suspicious/noRedundantUseStrict
    suspicious/noShorthandPropertyOverrides
    suspicious/noSparseArray
    suspicious/noSuspiciousSemicolonInJsx
    suspicious/noTemplateCurlyInString
    suspicious/noTsIgnore
    suspicious/noUnsafeDeclarationMerging
    suspicious/noUnsafeNegation
    suspicious/noUselessEscapeInString
    suspicious/noUselessRegexBackrefs
    suspicious/noWith
    suspicious/useAdjacentOverloadSignatures
    suspicious/useBiomeIgnoreFolder
    suspicious/useDefaultSwitchClauseLast
    suspicious/useGetterReturn
    suspicious/useGoogleFontDisplay
    suspicious/useNamespaceKeyword

Workspace:
  Open Documents:               0

Rule name

lint/complexity/useOptionalChain

Playground link

https://biomejs.dev/playground/?lintRules=useOptionalChain&analyzerFixMode=safeAndUnsafeFixes&code=YwBvAG4AcwBvAGwAZQAuAGwAbwBnACgAdAB5AHAAZQBvAGYAIAB3AGkAbgBkAG8AdwAgACEAPQA9ACAAIgB1AG4AZABlAGYAaQBuAGUAZAAiACAAJgAmACAAdwBpAG4AZABvAHcALgBsAG8AYwBhAHQAaQBvAG4AKQA7AAoA&language=ts

Expected result

The following snippets of code are not equivalent:

typeof window !== "undefined" && window.location
window?.location

They are obviously inequivalent in the sense that the first can give false while the second can give undefined. This does not matter in practice, so I'm happy to apply the unsafe fix for the rule for local variables.

The issue is with global variables. The above snippets are essentially equivalent when run in a browser. But when run on a server (code like the above is very common in server-side React), the first one will return false while the second will throw a ReferenceError.

Suggestion: allow configuring a list of variable names (e.g. ["document", "window"]) not to apply the fix to

Code of Conduct

  • I agree to follow Biome's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    S-Needs triageStatus: this issue needs to be triaged

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions