diff --git a/packages/compiler-cli/src/ngcc/src/analyzer.ts b/packages/compiler-cli/src/ngcc/src/analyzer.ts
index 30423bda7c..dfc72254b5 100644
--- a/packages/compiler-cli/src/ngcc/src/analyzer.ts
+++ b/packages/compiler-cli/src/ngcc/src/analyzer.ts
@@ -9,8 +9,7 @@ import {ConstantPool} from '@angular/compiler';
import * as fs from 'fs';
import * as ts from 'typescript';
-import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ResourceLoader, SelectorScopeRegistry} from '../../ngtsc/annotations';
-import {BaseDefDecoratorHandler} from '../../ngtsc/annotations/src/base_def';
+import {BaseDefDecoratorHandler, ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ResourceLoader, SelectorScopeRegistry} from '../../ngtsc/annotations';
import {Decorator} from '../../ngtsc/host';
import {CompileResult, DecoratorHandler} from '../../ngtsc/transform';
@@ -34,7 +33,7 @@ export interface AnalyzedFile {
export interface MatchingHandler {
handler: DecoratorHandler;
- decorator: Decorator;
+ match: M;
}
/**
@@ -80,9 +79,10 @@ export class Analyzer {
|undefined {
const matchingHandlers =
this.handlers
- .map(
- handler =>
- ({handler, decorator: handler.detect(clazz.declaration, clazz.decorators)}))
+ .map(handler => ({
+ handler,
+ decorator: handler.detect(clazz.declaration, clazz.decorators),
+ }))
.filter(isMatchingHandler);
if (matchingHandlers.length > 1) {
@@ -105,5 +105,5 @@ export class Analyzer {
function isMatchingHandler(handler: Partial>):
handler is MatchingHandler {
- return !!handler.decorator;
+ return !!handler.match;
}
diff --git a/packages/compiler-cli/src/ngtsc/annotations/index.ts b/packages/compiler-cli/src/ngtsc/annotations/index.ts
index 3beccc7aa8..77a4860842 100644
--- a/packages/compiler-cli/src/ngtsc/annotations/index.ts
+++ b/packages/compiler-cli/src/ngtsc/annotations/index.ts
@@ -7,6 +7,7 @@
*/
export {ResourceLoader} from './src/api';
+export {BaseDefDecoratorHandler} from './src/base_def';
export {ComponentDecoratorHandler} from './src/component';
export {DirectiveDecoratorHandler} from './src/directive';
export {InjectableDecoratorHandler} from './src/injectable';
diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/base_def.ts b/packages/compiler-cli/src/ngtsc/annotations/src/base_def.ts
index a2a8cf5354..5924bde1e2 100644
--- a/packages/compiler-cli/src/ngtsc/annotations/src/base_def.ts
+++ b/packages/compiler-cli/src/ngtsc/annotations/src/base_def.ts
@@ -32,7 +32,7 @@ export class BaseDefDecoratorHandler implements
|undefined {
if (containsNgTopLevelDecorator(decorators)) {
// If the class is already decorated by @Component or @Directive let that
- // decorator handle this. BaseDef is unnecessary.
+ // DecoratorHandler handle this. BaseDef is unnecessary.
return undefined;
}
@@ -67,10 +67,16 @@ export class BaseDefDecoratorHandler implements
metadata.inputs.forEach(({decorator, property}) => {
const propName = property.name;
const args = decorator.args;
- const value: string|[string, string] = args && args.length >= 1 ?
- [staticallyResolve(args[0], this.reflector, this.checker) as string, propName] :
- propName;
-
+ let value: string|[string, string];
+ if (args && args.length > 0) {
+ const resolvedValue = staticallyResolve(args[0], this.reflector, this.checker);
+ if (typeof resolvedValue !== 'string') {
+ throw new TypeError('Input alias does not resolve to a string value');
+ }
+ value = [resolvedValue, propName];
+ } else {
+ value = propName;
+ }
inputs[propName] = value;
});
}
@@ -80,9 +86,16 @@ export class BaseDefDecoratorHandler implements
metadata.outputs.forEach(({decorator, property}) => {
const propName = property.name;
const args = decorator.args;
- const value = args && args.length >= 1 ?
- staticallyResolve(args[0], this.reflector, this.checker) as string :
- propName;
+ let value: string;
+ if (args && args.length > 0) {
+ const resolvedValue = staticallyResolve(args[0], this.reflector, this.checker);
+ if (typeof resolvedValue !== 'string') {
+ throw new TypeError('Output alias does not resolve to a string value');
+ }
+ value = resolvedValue;
+ } else {
+ value = propName;
+ }
outputs[propName] = value;
});
}
diff --git a/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts b/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts
index 4d9486a3f8..6789d0e807 100644
--- a/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts
+++ b/packages/compiler-cli/src/ngtsc/transform/src/compilation.ts
@@ -22,7 +22,7 @@ import {DtsFileTransformer} from './declaration';
interface EmitFieldOperation {
adapter: DecoratorHandler;
analysis: AnalysisOutput;
- decorator: Decorator;
+ metadata: M;
}
/**
@@ -104,7 +104,7 @@ export class IvyCompilation {
this.analysis.set(node, {
adapter,
analysis: analysis.analysis,
- decorator: metadata,
+ metadata: metadata,
});
}
@@ -185,7 +185,7 @@ export class IvyCompilation {
return undefined;
}
- return this.analysis.get(original) !.decorator;
+ return this.analysis.get(original) !.metadata;
}
/**
diff --git a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts
index cfdd9ec8f0..68444a0c02 100644
--- a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts
+++ b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts
@@ -1979,7 +1979,6 @@ describe('compiler compliance', () => {
// ...
`;
const result = compile(files, angularFiles);
- debugger;
expectEmit(result.source, expectedOutput, 'Invalid base definition');
});
@@ -2019,7 +2018,7 @@ describe('compiler compliance', () => {
}
};
const result = compile(files, angularFiles);
- expect(result.source.indexOf('ngBaseDef')).toBe(-1);
+ expect(result.source).not.toContain('ngBaseDef');
});
it('should NOT add ngBaseDef if @Directive is present', () => {
@@ -2057,7 +2056,7 @@ describe('compiler compliance', () => {
}
};
const result = compile(files, angularFiles);
- expect(result.source.indexOf('ngBaseDef')).toBe(-1);
+ expect(result.source).not.toContain('ngBaseDef');
});
});
});
diff --git a/packages/core/src/metadata/directives.ts b/packages/core/src/metadata/directives.ts
index a8701e2ed4..8dabc20746 100644
--- a/packages/core/src/metadata/directives.ts
+++ b/packages/core/src/metadata/directives.ts
@@ -779,6 +779,11 @@ const initializeBaseDef = (target: any): void => {
}
};
+/**
+ * Used to get the minified alias of ngBaseDef
+ */
+const NG_BASE_DEF = Object.keys({ngBaseDef: true})[0];
+
/**
* Does the work of creating the `ngBaseDef` property for the @Input and @Output decorators.
* @param key "inputs" or "outputs"
@@ -787,7 +792,7 @@ const updateBaseDefFromIOProp = (getProp: (baseDef: {inputs?: any, outputs?: any
(target: any, name: string, ...args: any[]) => {
const constructor = target.constructor;
- if (!constructor.hasOwnProperty('ngBaseDef')) {
+ if (!constructor.hasOwnProperty(NG_BASE_DEF)) {
initializeBaseDef(target);
}