import * as ts from 'typescript' ; import { Checker } from '../../checker' ; import { AbsoluteMatcher } from '../absolute_matcher' ; import { isExpressionOfAllowedTrustedType } from '../is_trusted_type' ; import { TrustedTypesConfig } from '../trusted_types_configuration' ; import { PatternEngine } from './pattern_engine' ; function isCalledWithAllowedTrustedType ( tc , n , allowedTrustedType ) { const par = n . parent ; if ( allowedTrustedType && ts . isCallExpression ( par ) && par . arguments . length > 0 && isExpressionOfAllowedTrustedType ( tc , par . arguments [ 0 ] , allowedTrustedType ) ) { return true ; } return false ; } function isPolyfill ( n , matcher ) { if ( matcher . filePath === 'GLOBAL' ) { const parent = n . parent ; if ( parent && ts . isBinaryExpression ( parent ) && parent . left === n && parent . operatorToken . kind === ts . SyntaxKind . EqualsToken ) { return true ; } } return false ; } function checkIdentifierNode ( tc , n , matcher , allowedTrustedType ) { const wholeExp = ts . isPropertyAccessExpression ( n . parent ) ? n . parent : n ; if ( isPolyfill ( wholeExp , matcher ) ) return ; if ( ! matcher . matches ( n , tc ) ) return ; if ( isCalledWithAllowedTrustedType ( tc , n , allowedTrustedType ) ) return ; return wholeExp ; } function checkElementAccessNode ( tc , n , matcher , allowedTrustedType ) { if ( isPolyfill ( n , matcher ) ) return ; if ( ! matcher . matches ( n . argumentExpression , tc ) ) return ; if ( isCalledWithAllowedTrustedType ( tc , n , allowedTrustedType ) ) return ; return n ; } /** Engine for the BANNED_NAME pattern */ export class NameEngine extends PatternEngine { protected readonly banImport : boolean = false ; register ( checker ) { for ( const value of this . config . values ) { const matcher = new AbsoluteMatcher ( value , this . banImport ) ; const bannedIdName = matcher . bannedName . split ( '.' ) . pop ( ) ! ; checker . onNamedIdentifier ( bannedIdName , this . wrapCheckWithAllowlistingAndFixer ( ( tc , n ) => checkIdentifierNode ( tc , n , matcher , this . config . allowedTrustedType ) ) , this . config . errorCode ) ; checker . onStringLiteralElementAccess ( bannedIdName , this . wrapCheckWithAllowlistingAndFixer ( ( tc , n ) => checkElementAccessNode ( tc , n , matcher , this . config . allowedTrustedType ) ) , this . config . errorCode ) ; } } } /** Engine for the BANNED_IMPORTED_NAME pattern */ export class ImportedNameEngine extends NameEngine { protected override readonly banImport : boolean = true ; }