fixup! feat(ivy): Add AOT handling for bare classes with Input and Output decorators

This commit is contained in:
Ben Lesh 2018-08-09 09:16:58 -07:00
parent 244ee5846d
commit 70b1b8385f
6 changed files with 40 additions and 22 deletions

View File

@ -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<A, M> {
handler: DecoratorHandler<A, M>;
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<A, M>(handler: Partial<MatchingHandler<A, M>>):
handler is MatchingHandler<A, M> {
return !!handler.decorator;
return !!handler.match;
}

View File

@ -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';

View File

@ -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;
});
}

View File

@ -22,7 +22,7 @@ import {DtsFileTransformer} from './declaration';
interface EmitFieldOperation<A, M> {
adapter: DecoratorHandler<A, M>;
analysis: AnalysisOutput<A>;
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;
}
/**

View File

@ -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');
});
});
});

View File

@ -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);
}