@@ -16,7 +16,7 @@ import {
1616 SafePropertyRead ,
1717 ThisReceiver ,
1818} from '../../expression_parser/ast' ;
19- import { CssSelector , SelectorMatcher } from '../../selector ' ;
19+ import { CssSelector , SelectorlessMatcher , SelectorMatcher } from '../../directive_matching ' ;
2020import {
2121 BoundAttribute ,
2222 BoundEvent ,
@@ -119,7 +119,7 @@ type DeferBlockScopes = [DeferredBlock, Scope][];
119119 * where a host component (that owns the template) is located
120120 */
121121export function findMatchingDirectivesAndPipes ( template : string , directiveSelectors : string [ ] ) {
122- const matcher = new SelectorMatcher < unknown [ ] > ( ) ;
122+ const matcher = new SelectorMatcher < DirectiveMeta [ ] > ( ) ;
123123 for ( const selector of directiveSelectors ) {
124124 // Create a fake directive instance to account for the logic inside
125125 // of the `R3TargetBinder` class (which invokes the `hasBindingPropertyName`
@@ -137,11 +137,11 @@ export function findMatchingDirectivesAndPipes(template: string, directiveSelect
137137 return false ;
138138 } ,
139139 } ,
140- } ;
140+ } as unknown as DirectiveMeta ;
141141 matcher . addSelectables ( CssSelector . parse ( selector ) , [ fakeDirective ] ) ;
142142 }
143143 const parsedTemplate = parseTemplate ( template , '' /* templateUrl */ ) ;
144- const binder = new R3TargetBinder ( matcher as any ) ;
144+ const binder = new R3TargetBinder ( matcher ) ;
145145 const bound = binder . bind ( { template : parsedTemplate . nodes } ) ;
146146
147147 const eagerDirectiveSelectors = bound . getEagerlyUsedDirectives ( ) . map ( ( dir ) => dir . selector ! ) ;
@@ -159,13 +159,18 @@ export function findMatchingDirectivesAndPipes(template: string, directiveSelect
159159 } ;
160160}
161161
162+ /** Object used to match template nodes to directives. */
163+ export type DirectiveMatcher < DirectiveT extends DirectiveMeta > =
164+ | SelectorMatcher < DirectiveT [ ] >
165+ | SelectorlessMatcher < DirectiveT [ ] > ;
166+
162167/**
163168 * Processes `Target`s with a given set of directives and performs a binding operation, which
164169 * returns an object similar to TypeScript's `ts.TypeChecker` that contains knowledge about the
165170 * target.
166171 */
167172export class R3TargetBinder < DirectiveT extends DirectiveMeta > implements TargetBinder < DirectiveT > {
168- constructor ( private directiveMatcher : SelectorMatcher < DirectiveT [ ] > ) { }
173+ constructor ( private directiveMatcher : DirectiveMatcher < DirectiveT > ) { }
169174
170175 /**
171176 * Perform a binding operation on the given `Target` and return a `BoundTarget` which contains
@@ -497,7 +502,7 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
497502 private isInDeferBlock = false ;
498503
499504 private constructor (
500- private matcher : SelectorMatcher < DirectiveT [ ] > ,
505+ private directiveMatcher : DirectiveMatcher < DirectiveT > ,
501506 private directives : MatchedDirectives < DirectiveT > ,
502507 private eagerDirectives : DirectiveT [ ] ,
503508 private bindings : BindingsMap < DirectiveT > ,
@@ -518,14 +523,14 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
518523 */
519524 static apply < DirectiveT extends DirectiveMeta > (
520525 template : Node [ ] ,
521- selectorMatcher : SelectorMatcher < DirectiveT [ ] > ,
526+ directiveMatcher : DirectiveMatcher < DirectiveT > ,
522527 directives : MatchedDirectives < DirectiveT > ,
523528 eagerDirectives : DirectiveT [ ] ,
524529 bindings : BindingsMap < DirectiveT > ,
525530 references : ReferenceMap < DirectiveT > ,
526531 ) : void {
527532 const matcher = new DirectiveBinder (
528- selectorMatcher ,
533+ directiveMatcher ,
529534 directives ,
530535 eagerDirectives ,
531536 bindings ,
@@ -547,23 +552,23 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
547552 }
548553
549554 visitElementOrTemplate ( node : Element | Template ) : void {
550- // First, determine the HTML shape of the node for the purpose of directive matching.
551- // Do this by building up a `CssSelector` for the node.
552- const cssSelector = createCssSelectorFromNode ( node ) ;
555+ const directives : DirectiveT [ ] = [ ] ;
553556
554- // TODO(crisbeto): account for selectorless directives here.
555- if ( node . directives . length > 0 ) {
556- throw new Error ( 'TODO' ) ;
557- }
557+ if ( this . directiveMatcher instanceof SelectorMatcher ) {
558+ // First, determine the HTML shape of the node for the purpose of directive matching.
559+ // Do this by building up a `CssSelector` for the node.
560+ const cssSelector = createCssSelectorFromNode ( node ) ;
558561
559- // Next, use the `SelectorMatcher` to get the list of directives on the node.
560- const directives : DirectiveT [ ] = [ ] ;
561- this . matcher . match ( cssSelector , ( _selector , results ) => directives . push ( ... results ) ) ;
562- if ( directives . length > 0 ) {
563- this . directives . set ( node , directives ) ;
564- if ( ! this . isInDeferBlock ) {
565- this . eagerDirectives . push ( ... directives ) ;
562+ this . directiveMatcher . match ( cssSelector , ( _selector , results ) => directives . push ( ... results ) ) ;
563+
564+ if ( directives . length > 0 ) {
565+ this . directives . set ( node , directives ) ;
566+ if ( ! this . isInDeferBlock ) {
567+ this . eagerDirectives . push ( ... directives ) ;
568+ }
566569 }
570+ } else {
571+ throw new Error ( 'TODO' ) ;
567572 }
568573
569574 // Resolve any references that are created on this node.
0 commit comments