fixup! feat(ivy): Add AOT handling for bare classes with Input and Output decorators
This commit is contained in:
parent
244ee5846d
commit
70b1b8385f
@ -9,8 +9,7 @@ import {ConstantPool} from '@angular/compiler';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ResourceLoader, SelectorScopeRegistry} from '../../ngtsc/annotations';
|
import {BaseDefDecoratorHandler, ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ResourceLoader, SelectorScopeRegistry} from '../../ngtsc/annotations';
|
||||||
import {BaseDefDecoratorHandler} from '../../ngtsc/annotations/src/base_def';
|
|
||||||
import {Decorator} from '../../ngtsc/host';
|
import {Decorator} from '../../ngtsc/host';
|
||||||
import {CompileResult, DecoratorHandler} from '../../ngtsc/transform';
|
import {CompileResult, DecoratorHandler} from '../../ngtsc/transform';
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ export interface AnalyzedFile {
|
|||||||
|
|
||||||
export interface MatchingHandler<A, M> {
|
export interface MatchingHandler<A, M> {
|
||||||
handler: DecoratorHandler<A, M>;
|
handler: DecoratorHandler<A, M>;
|
||||||
decorator: Decorator;
|
match: M;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,9 +79,10 @@ export class Analyzer {
|
|||||||
|undefined {
|
|undefined {
|
||||||
const matchingHandlers =
|
const matchingHandlers =
|
||||||
this.handlers
|
this.handlers
|
||||||
.map(
|
.map(handler => ({
|
||||||
handler =>
|
handler,
|
||||||
({handler, decorator: handler.detect(clazz.declaration, clazz.decorators)}))
|
decorator: handler.detect(clazz.declaration, clazz.decorators),
|
||||||
|
}))
|
||||||
.filter(isMatchingHandler);
|
.filter(isMatchingHandler);
|
||||||
|
|
||||||
if (matchingHandlers.length > 1) {
|
if (matchingHandlers.length > 1) {
|
||||||
@ -105,5 +105,5 @@ export class Analyzer {
|
|||||||
|
|
||||||
function isMatchingHandler<A, M>(handler: Partial<MatchingHandler<A, M>>):
|
function isMatchingHandler<A, M>(handler: Partial<MatchingHandler<A, M>>):
|
||||||
handler is MatchingHandler<A, M> {
|
handler is MatchingHandler<A, M> {
|
||||||
return !!handler.decorator;
|
return !!handler.match;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export {ResourceLoader} from './src/api';
|
export {ResourceLoader} from './src/api';
|
||||||
|
export {BaseDefDecoratorHandler} from './src/base_def';
|
||||||
export {ComponentDecoratorHandler} from './src/component';
|
export {ComponentDecoratorHandler} from './src/component';
|
||||||
export {DirectiveDecoratorHandler} from './src/directive';
|
export {DirectiveDecoratorHandler} from './src/directive';
|
||||||
export {InjectableDecoratorHandler} from './src/injectable';
|
export {InjectableDecoratorHandler} from './src/injectable';
|
||||||
|
@ -32,7 +32,7 @@ export class BaseDefDecoratorHandler implements
|
|||||||
|undefined {
|
|undefined {
|
||||||
if (containsNgTopLevelDecorator(decorators)) {
|
if (containsNgTopLevelDecorator(decorators)) {
|
||||||
// If the class is already decorated by @Component or @Directive let that
|
// 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;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,10 +67,16 @@ export class BaseDefDecoratorHandler implements
|
|||||||
metadata.inputs.forEach(({decorator, property}) => {
|
metadata.inputs.forEach(({decorator, property}) => {
|
||||||
const propName = property.name;
|
const propName = property.name;
|
||||||
const args = decorator.args;
|
const args = decorator.args;
|
||||||
const value: string|[string, string] = args && args.length >= 1 ?
|
let value: string|[string, string];
|
||||||
[staticallyResolve(args[0], this.reflector, this.checker) as string, propName] :
|
if (args && args.length > 0) {
|
||||||
propName;
|
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;
|
inputs[propName] = value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -80,9 +86,16 @@ export class BaseDefDecoratorHandler implements
|
|||||||
metadata.outputs.forEach(({decorator, property}) => {
|
metadata.outputs.forEach(({decorator, property}) => {
|
||||||
const propName = property.name;
|
const propName = property.name;
|
||||||
const args = decorator.args;
|
const args = decorator.args;
|
||||||
const value = args && args.length >= 1 ?
|
let value: string;
|
||||||
staticallyResolve(args[0], this.reflector, this.checker) as string :
|
if (args && args.length > 0) {
|
||||||
propName;
|
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;
|
outputs[propName] = value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import {DtsFileTransformer} from './declaration';
|
|||||||
interface EmitFieldOperation<A, M> {
|
interface EmitFieldOperation<A, M> {
|
||||||
adapter: DecoratorHandler<A, M>;
|
adapter: DecoratorHandler<A, M>;
|
||||||
analysis: AnalysisOutput<A>;
|
analysis: AnalysisOutput<A>;
|
||||||
decorator: Decorator;
|
metadata: M;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +104,7 @@ export class IvyCompilation {
|
|||||||
this.analysis.set(node, {
|
this.analysis.set(node, {
|
||||||
adapter,
|
adapter,
|
||||||
analysis: analysis.analysis,
|
analysis: analysis.analysis,
|
||||||
decorator: metadata,
|
metadata: metadata,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ export class IvyCompilation {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.analysis.get(original) !.decorator;
|
return this.analysis.get(original) !.metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1979,7 +1979,6 @@ describe('compiler compliance', () => {
|
|||||||
// ...
|
// ...
|
||||||
`;
|
`;
|
||||||
const result = compile(files, angularFiles);
|
const result = compile(files, angularFiles);
|
||||||
debugger;
|
|
||||||
expectEmit(result.source, expectedOutput, 'Invalid base definition');
|
expectEmit(result.source, expectedOutput, 'Invalid base definition');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2019,7 +2018,7 @@ describe('compiler compliance', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const result = compile(files, angularFiles);
|
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', () => {
|
it('should NOT add ngBaseDef if @Directive is present', () => {
|
||||||
@ -2057,7 +2056,7 @@ describe('compiler compliance', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const result = compile(files, angularFiles);
|
const result = compile(files, angularFiles);
|
||||||
expect(result.source.indexOf('ngBaseDef')).toBe(-1);
|
expect(result.source).not.toContain('ngBaseDef');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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.
|
* Does the work of creating the `ngBaseDef` property for the @Input and @Output decorators.
|
||||||
* @param key "inputs" or "outputs"
|
* @param key "inputs" or "outputs"
|
||||||
@ -787,7 +792,7 @@ const updateBaseDefFromIOProp = (getProp: (baseDef: {inputs?: any, outputs?: any
|
|||||||
(target: any, name: string, ...args: any[]) => {
|
(target: any, name: string, ...args: any[]) => {
|
||||||
const constructor = target.constructor;
|
const constructor = target.constructor;
|
||||||
|
|
||||||
if (!constructor.hasOwnProperty('ngBaseDef')) {
|
if (!constructor.hasOwnProperty(NG_BASE_DEF)) {
|
||||||
initializeBaseDef(target);
|
initializeBaseDef(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user