@@ -11,6 +11,7 @@ import {
1111 emitDistinctChangesOnlyDefaultValue ,
1212 Expression ,
1313 ExternalExpr ,
14+ ExternalReference ,
1415 ForwardRefHandling ,
1516 getSafePropertyAccessString ,
1617 MaybeForwardRefExpression ,
@@ -395,6 +396,7 @@ export function extractDirectiveMetadata(
395396 : extractHostDirectives (
396397 rawHostDirectives ,
397398 evaluator ,
399+ reflector ,
398400 compilationMode ,
399401 createForwardRefResolver ( isCore ) ,
400402 emitDeclarationOnly ,
@@ -1733,6 +1735,7 @@ function getHostBindingErrorNode(error: ParseError, hostExpr: ts.Expression): ts
17331735function extractHostDirectives (
17341736 rawHostDirectives : ts . Expression ,
17351737 evaluator : PartialEvaluator ,
1738+ reflector : ReflectionHost ,
17361739 compilationMode : CompilationMode ,
17371740 forwardRefResolver : ForeignFunctionResolver ,
17381741 emitDeclarationOnly : boolean ,
@@ -1768,7 +1771,7 @@ function extractHostDirectives(
17681771 }
17691772 }
17701773
1771- let directive : Reference < ClassDeclaration > | Expression ;
1774+ let directive : Reference < ClassDeclaration > | Expression | ExternalReference ;
17721775 let nameForErrors = ( fieldName : string ) => '@Directive.hostDirectives' ;
17731776 if ( compilationMode === CompilationMode . LOCAL && hostReference instanceof DynamicValue ) {
17741777 // At the moment in local compilation we only support simple array for host directives, i.e.,
@@ -1780,22 +1783,38 @@ function extractHostDirectives(
17801783 ! ts . isIdentifier ( hostReference . node ) &&
17811784 ! ts . isPropertyAccessExpression ( hostReference . node )
17821785 ) {
1786+ const compilationModeName = emitDeclarationOnly
1787+ ? 'experimental declaration-only emission'
1788+ : 'local compilation' ;
17831789 throw new FatalDiagnosticError (
17841790 ErrorCode . LOCAL_COMPILATION_UNSUPPORTED_EXPRESSION ,
17851791 hostReference . node ,
1786- `In local compilation mode, host directive cannot be an expression. Use an identifier instead` ,
1792+ `In ${ compilationModeName } mode, host directive cannot be an expression. Use an identifier instead` ,
17871793 ) ;
17881794 }
17891795
17901796 if ( emitDeclarationOnly ) {
1791- throw new FatalDiagnosticError (
1792- ErrorCode . LOCAL_COMPILATION_UNSUPPORTED_EXPRESSION ,
1793- hostReference . node ,
1794- 'External references in host directives are not supported in experimental declaration-only emission mode' ,
1795- ) ;
1797+ if ( ts . isIdentifier ( hostReference . node ) ) {
1798+ const importInfo = reflector . getImportOfIdentifier ( hostReference . node ) ;
1799+ if ( importInfo ) {
1800+ directive = new ExternalReference ( importInfo . from , importInfo . name ) ;
1801+ } else {
1802+ throw new FatalDiagnosticError (
1803+ ErrorCode . LOCAL_COMPILATION_UNSUPPORTED_EXPRESSION ,
1804+ hostReference . node ,
1805+ `In experimental declaration-only emission mode, host directive cannot use indirect external indentifiers. Use a direct external identifier instead` ,
1806+ ) ;
1807+ }
1808+ } else {
1809+ throw new FatalDiagnosticError (
1810+ ErrorCode . LOCAL_COMPILATION_UNSUPPORTED_EXPRESSION ,
1811+ hostReference . node ,
1812+ `In experimental declaration-only emission mode, host directive cannot be an expression. Use an identifier instead` ,
1813+ ) ;
1814+ }
1815+ } else {
1816+ directive = new WrappedNodeExpr ( hostReference . node ) ;
17961817 }
1797-
1798- directive = new WrappedNodeExpr ( hostReference . node ) ;
17991818 } else if ( hostReference instanceof Reference ) {
18001819 directive = hostReference as Reference < ClassDeclaration > ;
18011820 nameForErrors = ( fieldName : string ) =>
@@ -1865,6 +1884,11 @@ function toHostDirectiveMetadata(
18651884 context ,
18661885 refEmitter ,
18671886 ) ;
1887+ } else if ( hostDirective . directive instanceof ExternalReference ) {
1888+ directive = {
1889+ value : new ExternalExpr ( hostDirective . directive ) ,
1890+ type : new ExternalExpr ( hostDirective . directive ) ,
1891+ } ;
18681892 } else {
18691893 directive = {
18701894 value : hostDirective . directive ,
0 commit comments