Compare commits
14 Commits
2.0.0-beta
...
2.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
06ad112998 | |||
cfa1d17afe | |||
3ca6df87b8 | |||
e310bee9e2 | |||
4902244cce | |||
8db97b0b7a | |||
9be04f8d38 | |||
74e2bd7e3e | |||
52d3980d02 | |||
4e9809bcb2 | |||
bd8a4215dd | |||
d23b973e7a | |||
0dbf959548 | |||
20812f446f |
31
CHANGELOG.md
31
CHANGELOG.md
@ -1,3 +1,24 @@
|
||||
<a name="2.0.0-beta.14"></a>
|
||||
# 2.0.0-beta.14 (2016-04-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **forms:** support both value and ng-value ([8db97b0](https://github.com/angular/angular/commit/8db97b0))
|
||||
* **router:** allow forward slashes in query parameters ([4902244](https://github.com/angular/angular/commit/4902244)), closes [#7824](https://github.com/angular/angular/issues/7824)
|
||||
* **select:** support objects as select values ([74e2bd7](https://github.com/angular/angular/commit/74e2bd7)), closes [#4843](https://github.com/angular/angular/issues/4843) [#7842](https://github.com/angular/angular/issues/7842)
|
||||
* **select:** update name from ng-value to ngValue ([3ca6df8](https://github.com/angular/angular/commit/3ca6df8)), closes [#7939](https://github.com/angular/angular/issues/7939)
|
||||
* **upgrade:** leak when angular1 destroys element ([9be04f8](https://github.com/angular/angular/commit/9be04f8)), closes [#6401](https://github.com/angular/angular/issues/6401) [#7935](https://github.com/angular/angular/issues/7935)
|
||||
|
||||
### Features
|
||||
|
||||
* **dart/transform:** Avoid `print` in transformer code. ([e310bee](https://github.com/angular/angular/commit/e310bee)), closes [#7855](https://github.com/angular/angular/issues/7855)
|
||||
* **static-reflector:** Added StaticReflector ([0dbf959](https://github.com/angular/angular/commit/0dbf959))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="2.0.0-beta.13"></a>
|
||||
# 2.0.0-beta.13 (2016-03-31)
|
||||
|
||||
@ -30,14 +51,20 @@
|
||||
### BREAKING CHANGES
|
||||
|
||||
* For static content projection, elements with *-directives are now matched against the element itself vs the template before.
|
||||
<p *ngIf="condition" foo></p>
|
||||
|
||||
`<p *ngIf="condition" foo></p>`
|
||||
|
||||
Before:
|
||||
```html
|
||||
// Use the implicit template for projection
|
||||
<ng-content select="template"></ng-content>
|
||||
```
|
||||
|
||||
After:
|
||||
```html
|
||||
// Use the actual element for projection
|
||||
<ng-content select="p[foo]"></ng-content>
|
||||
|
||||
```
|
||||
|
||||
<a name="2.0.0-beta.12"></a>
|
||||
# 2.0.0-beta.12 (2016-03-23)
|
||||
|
@ -1,21 +1,83 @@
|
||||
import {
|
||||
Query,
|
||||
Directive,
|
||||
Renderer,
|
||||
Self,
|
||||
forwardRef,
|
||||
Provider,
|
||||
ElementRef,
|
||||
QueryList
|
||||
Input,
|
||||
Host,
|
||||
OnDestroy,
|
||||
Optional
|
||||
} from 'angular2/core';
|
||||
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor';
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
CONST_EXPR,
|
||||
StringWrapper,
|
||||
isPrimitive,
|
||||
isPresent,
|
||||
isBlank,
|
||||
looseIdentical
|
||||
} from 'angular2/src/facade/lang';
|
||||
|
||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
const SELECT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
||||
NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => SelectControlValueAccessor), multi: true}));
|
||||
|
||||
function _buildValueString(id: string, value: any): string {
|
||||
if (isBlank(id)) return `${value}`;
|
||||
if (!isPrimitive(value)) value = "Object";
|
||||
return StringWrapper.slice(`${id}: ${value}`, 0, 50);
|
||||
}
|
||||
|
||||
function _extractId(valueString: string): string {
|
||||
return valueString.split(":")[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* The accessor for writing a value and listening to changes on a select element.
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'select[ngControl],select[ngFormControl],select[ngModel]',
|
||||
host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
|
||||
providers: [SELECT_VALUE_ACCESSOR]
|
||||
})
|
||||
export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||
value: any;
|
||||
_optionMap: Map<string, any> = new Map<string, any>();
|
||||
_idCounter: number = 0;
|
||||
|
||||
onChange = (_: any) => {};
|
||||
onTouched = () => {};
|
||||
|
||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
|
||||
|
||||
writeValue(value: any): void {
|
||||
this.value = value;
|
||||
var valueString = _buildValueString(this._getOptionId(value), value);
|
||||
this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', valueString);
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => any): void {
|
||||
this.onChange = (valueString: string) => { fn(this._getOptionValue(valueString)); };
|
||||
}
|
||||
registerOnTouched(fn: () => any): void { this.onTouched = fn; }
|
||||
|
||||
_registerOption(): string { return (this._idCounter++).toString(); }
|
||||
|
||||
_getOptionId(value: any): string {
|
||||
for (let id of MapWrapper.keys(this._optionMap)) {
|
||||
if (looseIdentical(this._optionMap.get(id), value)) return id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_getOptionValue(valueString: string): any {
|
||||
let value = this._optionMap.get(_extractId(valueString));
|
||||
return isPresent(value) ? value : valueString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks `<option>` as dynamic, so Angular can be notified when options change.
|
||||
*
|
||||
@ -28,36 +90,37 @@ const SELECT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
|
||||
* ```
|
||||
*/
|
||||
@Directive({selector: 'option'})
|
||||
export class NgSelectOption {
|
||||
}
|
||||
export class NgSelectOption implements OnDestroy {
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* The accessor for writing a value and listening to changes on a select element.
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'select[ngControl],select[ngFormControl],select[ngModel]',
|
||||
host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
|
||||
bindings: [SELECT_VALUE_ACCESSOR]
|
||||
})
|
||||
export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||
value: string;
|
||||
onChange = (_: any) => {};
|
||||
onTouched = () => {};
|
||||
|
||||
constructor(private _renderer: Renderer, private _elementRef: ElementRef,
|
||||
@Query(NgSelectOption, {descendants: true}) query: QueryList<NgSelectOption>) {
|
||||
this._updateValueWhenListOfOptionsChanges(query);
|
||||
constructor(private _element: ElementRef, private _renderer: Renderer,
|
||||
@Optional() @Host() private _select: SelectControlValueAccessor) {
|
||||
if (isPresent(this._select)) this.id = this._select._registerOption();
|
||||
}
|
||||
|
||||
writeValue(value: any): void {
|
||||
this.value = value;
|
||||
this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', value);
|
||||
@Input('ngValue')
|
||||
set ngValue(value: any) {
|
||||
if (this._select == null) return;
|
||||
this._select._optionMap.set(this.id, value);
|
||||
this._setElementValue(_buildValueString(this.id, value));
|
||||
this._select.writeValue(this._select.value);
|
||||
}
|
||||
|
||||
registerOnChange(fn: () => any): void { this.onChange = fn; }
|
||||
registerOnTouched(fn: () => any): void { this.onTouched = fn; }
|
||||
@Input('value')
|
||||
set value(value: any) {
|
||||
if (this._select == null) return;
|
||||
this._setElementValue(value);
|
||||
this._select.writeValue(this._select.value);
|
||||
}
|
||||
|
||||
private _updateValueWhenListOfOptionsChanges(query: QueryList<NgSelectOption>) {
|
||||
ObservableWrapper.subscribe(query.changes, (_) => this.writeValue(this.value));
|
||||
_setElementValue(value: string): void {
|
||||
this._renderer.setElementProperty(this._element.nativeElement, 'value', value);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (isPresent(this._select)) {
|
||||
this._select._optionMap.delete(this.id);
|
||||
this._select.writeValue(this._select.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,10 @@ import {NumberWrapper} from "angular2/src/facade/lang";
|
||||
*/
|
||||
export interface Validator { validate(c: modelModule.AbstractControl): {[key: string]: any}; }
|
||||
|
||||
const REQUIRED = Validators.required;
|
||||
|
||||
const REQUIRED_VALIDATOR =
|
||||
CONST_EXPR(new Provider(NG_VALIDATORS, {useValue: Validators.required, multi: true}));
|
||||
CONST_EXPR(new Provider(NG_VALIDATORS, {useValue: REQUIRED, multi: true}));
|
||||
|
||||
/**
|
||||
* A Directive that adds the `required` validator to any controls marked with the
|
||||
|
499
modules/angular2/src/compiler/static_reflector.ts
Normal file
499
modules/angular2/src/compiler/static_reflector.ts
Normal file
@ -0,0 +1,499 @@
|
||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {
|
||||
isArray,
|
||||
isBlank,
|
||||
isNumber,
|
||||
isPresent,
|
||||
isPrimitive,
|
||||
isString,
|
||||
Type
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
AttributeMetadata,
|
||||
DirectiveMetadata,
|
||||
ComponentMetadata,
|
||||
ContentChildrenMetadata,
|
||||
ContentChildMetadata,
|
||||
InputMetadata,
|
||||
HostBindingMetadata,
|
||||
HostListenerMetadata,
|
||||
OutputMetadata,
|
||||
PipeMetadata,
|
||||
ViewMetadata,
|
||||
ViewChildMetadata,
|
||||
ViewChildrenMetadata,
|
||||
ViewQueryMetadata,
|
||||
QueryMetadata,
|
||||
} from 'angular2/src/core/metadata';
|
||||
|
||||
/**
|
||||
* The host of the static resolver is expected to be able to provide module metadata in the form of
|
||||
* ModuleMetadata. Angular 2 CLI will produce this metadata for a module whenever a .d.ts files is
|
||||
* produced and the module has exported variables or classes with decorators. Module metadata can
|
||||
* also be produced directly from TypeScript sources by using MetadataCollector in tools/metadata.
|
||||
*/
|
||||
export interface StaticReflectorHost {
|
||||
/**
|
||||
* Return a ModuleMetadata for the give module.
|
||||
*
|
||||
* @param moduleId is a string identifier for a module in the form that would expected in a
|
||||
* module import of an import statement.
|
||||
* @returns the metadata for the given module.
|
||||
*/
|
||||
getMetadataFor(moduleId: string): {[key: string]: any};
|
||||
}
|
||||
|
||||
/**
|
||||
* A token representing the a reference to a static type.
|
||||
*
|
||||
* This token is unique for a moduleId and name and can be used as a hash table key.
|
||||
*/
|
||||
export class StaticType {
|
||||
constructor(public moduleId: string, public name: string) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* A static reflector implements enough of the Reflector API that is necessary to compile
|
||||
* templates statically.
|
||||
*/
|
||||
export class StaticReflector {
|
||||
private typeCache = new Map<string, StaticType>();
|
||||
private annotationCache = new Map<StaticType, any[]>();
|
||||
private propertyCache = new Map<StaticType, {[key: string]: any}>();
|
||||
private parameterCache = new Map<StaticType, any[]>();
|
||||
private metadataCache = new Map<string, {[key: string]: any}>();
|
||||
|
||||
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
|
||||
|
||||
/**
|
||||
* getStatictype produces a Type whose metadata is known but whose implementation is not loaded.
|
||||
* All types passed to the StaticResolver should be pseudo-types returned by this method.
|
||||
*
|
||||
* @param moduleId the module identifier as would be passed to an import statement.
|
||||
* @param name the name of the type.
|
||||
*/
|
||||
public getStaticType(moduleId: string, name: string): StaticType {
|
||||
let key = `"${moduleId}".${name}`;
|
||||
let result = this.typeCache.get(key);
|
||||
if (!isPresent(result)) {
|
||||
result = new StaticType(moduleId, name);
|
||||
this.typeCache.set(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public annotations(type: StaticType): any[] {
|
||||
let annotations = this.annotationCache.get(type);
|
||||
if (!isPresent(annotations)) {
|
||||
let classMetadata = this.getTypeMetadata(type);
|
||||
if (isPresent(classMetadata['decorators'])) {
|
||||
annotations = (<any[]>classMetadata['decorators'])
|
||||
.map(decorator => this.convertKnownDecorator(type.moduleId, decorator))
|
||||
.filter(decorator => isPresent(decorator));
|
||||
}
|
||||
this.annotationCache.set(type, annotations);
|
||||
}
|
||||
return annotations;
|
||||
}
|
||||
|
||||
public propMetadata(type: StaticType): {[key: string]: any} {
|
||||
let propMetadata = this.propertyCache.get(type);
|
||||
if (!isPresent(propMetadata)) {
|
||||
let classMetadata = this.getTypeMetadata(type);
|
||||
propMetadata = this.getPropertyMetadata(type.moduleId, classMetadata['members']);
|
||||
this.propertyCache.set(type, propMetadata);
|
||||
}
|
||||
return propMetadata;
|
||||
}
|
||||
|
||||
public parameters(type: StaticType): any[] {
|
||||
let parameters = this.parameterCache.get(type);
|
||||
if (!isPresent(parameters)) {
|
||||
let classMetadata = this.getTypeMetadata(type);
|
||||
let ctorData = classMetadata['members']['__ctor__'];
|
||||
if (isPresent(ctorData)) {
|
||||
let ctor = (<any[]>ctorData).find(a => a['__symbolic'] === 'constructor');
|
||||
parameters = this.simplify(type.moduleId, ctor['parameters']);
|
||||
this.parameterCache.set(type, parameters);
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private conversionMap = new Map<StaticType, (moduleContext: string, expression: any) => any>();
|
||||
private initializeConversionMap() {
|
||||
let core_metadata = 'angular2/src/core/metadata';
|
||||
let conversionMap = this.conversionMap;
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Directive'),
|
||||
(moduleContext, expression) => {
|
||||
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
||||
if (!isPresent(p0)) {
|
||||
p0 = {};
|
||||
}
|
||||
return new DirectiveMetadata({
|
||||
selector: p0['selector'],
|
||||
inputs: p0['inputs'],
|
||||
outputs: p0['outputs'],
|
||||
events: p0['events'],
|
||||
host: p0['host'],
|
||||
bindings: p0['bindings'],
|
||||
providers: p0['providers'],
|
||||
exportAs: p0['exportAs'],
|
||||
queries: p0['queries'],
|
||||
});
|
||||
});
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Component'),
|
||||
(moduleContext, expression) => {
|
||||
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
||||
if (!isPresent(p0)) {
|
||||
p0 = {};
|
||||
}
|
||||
return new ComponentMetadata({
|
||||
selector: p0['selector'],
|
||||
inputs: p0['inputs'],
|
||||
outputs: p0['outputs'],
|
||||
properties: p0['properties'],
|
||||
events: p0['events'],
|
||||
host: p0['host'],
|
||||
exportAs: p0['exportAs'],
|
||||
moduleId: p0['moduleId'],
|
||||
bindings: p0['bindings'],
|
||||
providers: p0['providers'],
|
||||
viewBindings: p0['viewBindings'],
|
||||
viewProviders: p0['viewProviders'],
|
||||
changeDetection: p0['changeDetection'],
|
||||
queries: p0['queries'],
|
||||
templateUrl: p0['templateUrl'],
|
||||
template: p0['template'],
|
||||
styleUrls: p0['styleUrls'],
|
||||
styles: p0['styles'],
|
||||
directives: p0['directives'],
|
||||
pipes: p0['pipes'],
|
||||
encapsulation: p0['encapsulation']
|
||||
});
|
||||
});
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Input'),
|
||||
(moduleContext, expression) => new InputMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Output'),
|
||||
(moduleContext, expression) => new OutputMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'View'), (moduleContext, expression) => {
|
||||
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
||||
if (!isPresent(p0)) {
|
||||
p0 = {};
|
||||
}
|
||||
return new ViewMetadata({
|
||||
templateUrl: p0['templateUrl'],
|
||||
template: p0['template'],
|
||||
directives: p0['directives'],
|
||||
pipes: p0['pipes'],
|
||||
encapsulation: p0['encapsulation'],
|
||||
styles: p0['styles'],
|
||||
});
|
||||
});
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Attribute'),
|
||||
(moduleContext, expression) => new AttributeMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Query'), (moduleContext, expression) => {
|
||||
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
||||
let p1 = this.getDecoratorParameter(moduleContext, expression, 1);
|
||||
if (!isPresent(p1)) {
|
||||
p1 = {};
|
||||
}
|
||||
return new QueryMetadata(p0, {descendants: p1.descendants, first: p1.first});
|
||||
});
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'ContentChildren'),
|
||||
(moduleContext, expression) => new ContentChildrenMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'ContentChild'),
|
||||
(moduleContext, expression) => new ContentChildMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'ViewChildren'),
|
||||
(moduleContext, expression) => new ViewChildrenMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'ViewChild'),
|
||||
(moduleContext, expression) => new ViewChildMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'ViewQuery'),
|
||||
(moduleContext, expression) => {
|
||||
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
||||
let p1 = this.getDecoratorParameter(moduleContext, expression, 1);
|
||||
if (!isPresent(p1)) {
|
||||
p1 = {};
|
||||
}
|
||||
return new ViewQueryMetadata(p0, {
|
||||
descendants: p1['descendants'],
|
||||
first: p1['first'],
|
||||
});
|
||||
});
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'Pipe'), (moduleContext, expression) => {
|
||||
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
||||
if (!isPresent(p0)) {
|
||||
p0 = {};
|
||||
}
|
||||
return new PipeMetadata({
|
||||
name: p0['name'],
|
||||
pure: p0['pure'],
|
||||
});
|
||||
});
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'HostBinding'),
|
||||
(moduleContext, expression) => new HostBindingMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0)));
|
||||
conversionMap.set(this.getStaticType(core_metadata, 'HostListener'),
|
||||
(moduleContext, expression) => new HostListenerMetadata(
|
||||
this.getDecoratorParameter(moduleContext, expression, 0),
|
||||
this.getDecoratorParameter(moduleContext, expression, 1)));
|
||||
}
|
||||
|
||||
private convertKnownDecorator(moduleContext: string, expression: {[key: string]: any}): any {
|
||||
let converter = this.conversionMap.get(this.getDecoratorType(moduleContext, expression));
|
||||
if (isPresent(converter)) return converter(moduleContext, expression);
|
||||
return null;
|
||||
}
|
||||
|
||||
private getDecoratorType(moduleContext: string, expression: {[key: string]: any}): StaticType {
|
||||
if (isMetadataSymbolicCallExpression(expression)) {
|
||||
let target = expression['expression'];
|
||||
if (isMetadataSymbolicReferenceExpression(target)) {
|
||||
let moduleId = this.normalizeModuleName(moduleContext, target['module']);
|
||||
return this.getStaticType(moduleId, target['name']);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private getDecoratorParameter(moduleContext: string, expression: {[key: string]: any},
|
||||
index: number): any {
|
||||
if (isMetadataSymbolicCallExpression(expression) && isPresent(expression['arguments']) &&
|
||||
(<any[]>expression['arguments']).length <= index + 1) {
|
||||
return this.simplify(moduleContext, (<any[]>expression['arguments'])[index]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private getPropertyMetadata(moduleContext: string,
|
||||
value: {[key: string]: any}): {[key: string]: any} {
|
||||
if (isPresent(value)) {
|
||||
let result = {};
|
||||
StringMapWrapper.forEach(value, (value, name) => {
|
||||
let data = this.getMemberData(moduleContext, value);
|
||||
if (isPresent(data)) {
|
||||
let propertyData = data.filter(d => d['kind'] == "property")
|
||||
.map(d => d['directives'])
|
||||
.reduce((p, c) => (<any[]>p).concat(<any[]>c), []);
|
||||
if (propertyData.length != 0) {
|
||||
StringMapWrapper.set(result, name, propertyData);
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
private getMemberData(moduleContext: string, member: { [key: string]: any }[]): { [key: string]: any }[] {
|
||||
// clang-format on
|
||||
let result = [];
|
||||
if (isPresent(member)) {
|
||||
for (let item of member) {
|
||||
result.push({
|
||||
kind: item['__symbolic'],
|
||||
directives:
|
||||
isPresent(item['decorators']) ?
|
||||
(<any[]>item['decorators'])
|
||||
.map(decorator => this.convertKnownDecorator(moduleContext, decorator))
|
||||
.filter(d => isPresent(d)) :
|
||||
null
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
public simplify(moduleContext: string, value: any): any {
|
||||
let _this = this;
|
||||
|
||||
function simplify(expression: any): any {
|
||||
if (isPrimitive(expression)) {
|
||||
return expression;
|
||||
}
|
||||
if (isArray(expression)) {
|
||||
let result = [];
|
||||
for (let item of(<any>expression)) {
|
||||
result.push(simplify(item));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (isPresent(expression)) {
|
||||
if (isPresent(expression['__symbolic'])) {
|
||||
switch (expression['__symbolic']) {
|
||||
case "binop":
|
||||
let left = simplify(expression['left']);
|
||||
let right = simplify(expression['right']);
|
||||
switch (expression['operator']) {
|
||||
case '&&':
|
||||
return left && right;
|
||||
case '||':
|
||||
return left || right;
|
||||
case '|':
|
||||
return left | right;
|
||||
case '^':
|
||||
return left ^ right;
|
||||
case '&':
|
||||
return left & right;
|
||||
case '==':
|
||||
return left == right;
|
||||
case '!=':
|
||||
return left != right;
|
||||
case '===':
|
||||
return left === right;
|
||||
case '!==':
|
||||
return left !== right;
|
||||
case '<':
|
||||
return left < right;
|
||||
case '>':
|
||||
return left > right;
|
||||
case '<=':
|
||||
return left <= right;
|
||||
case '>=':
|
||||
return left >= right;
|
||||
case '<<':
|
||||
return left << right;
|
||||
case '>>':
|
||||
return left >> right;
|
||||
case '+':
|
||||
return left + right;
|
||||
case '-':
|
||||
return left - right;
|
||||
case '*':
|
||||
return left * right;
|
||||
case '/':
|
||||
return left / right;
|
||||
case '%':
|
||||
return left % right;
|
||||
}
|
||||
return null;
|
||||
case "pre":
|
||||
let operand = simplify(expression['operand']);
|
||||
switch (expression['operator']) {
|
||||
case '+':
|
||||
return operand;
|
||||
case '-':
|
||||
return -operand;
|
||||
case '!':
|
||||
return !operand;
|
||||
case '~':
|
||||
return ~operand;
|
||||
}
|
||||
return null;
|
||||
case "index":
|
||||
let indexTarget = simplify(expression['expression']);
|
||||
let index = simplify(expression['index']);
|
||||
if (isPresent(indexTarget) && isPrimitive(index)) return indexTarget[index];
|
||||
return null;
|
||||
case "select":
|
||||
let selectTarget = simplify(expression['expression']);
|
||||
let member = simplify(expression['member']);
|
||||
if (isPresent(selectTarget) && isPrimitive(member)) return selectTarget[member];
|
||||
return null;
|
||||
case "reference":
|
||||
let referenceModuleName =
|
||||
_this.normalizeModuleName(moduleContext, expression['module']);
|
||||
let referenceModule = _this.getModuleMetadata(referenceModuleName);
|
||||
let referenceValue = referenceModule['metadata'][expression['name']];
|
||||
if (isClassMetadata(referenceValue)) {
|
||||
// Convert to a pseudo type
|
||||
return _this.getStaticType(referenceModuleName, expression['name']);
|
||||
}
|
||||
return _this.simplify(referenceModuleName, referenceValue);
|
||||
case "call":
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
let result = {};
|
||||
StringMapWrapper.forEach(expression, (value, name) => { result[name] = simplify(value); });
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return simplify(value);
|
||||
}
|
||||
|
||||
private getModuleMetadata(module: string): {[key: string]: any} {
|
||||
let moduleMetadata = this.metadataCache.get(module);
|
||||
if (!isPresent(moduleMetadata)) {
|
||||
moduleMetadata = this.host.getMetadataFor(module);
|
||||
if (!isPresent(moduleMetadata)) {
|
||||
moduleMetadata = {__symbolic: "module", module: module, metadata: {}};
|
||||
}
|
||||
this.metadataCache.set(module, moduleMetadata);
|
||||
}
|
||||
return moduleMetadata;
|
||||
}
|
||||
|
||||
private getTypeMetadata(type: StaticType): {[key: string]: any} {
|
||||
let moduleMetadata = this.getModuleMetadata(type.moduleId);
|
||||
let result = moduleMetadata['metadata'][type.name];
|
||||
if (!isPresent(result)) {
|
||||
result = {__symbolic: "class"};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private normalizeModuleName(from: string, to: string): string {
|
||||
if (to.startsWith('.')) {
|
||||
return pathTo(from, to);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
function isMetadataSymbolicCallExpression(expression: any): boolean {
|
||||
return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'call';
|
||||
}
|
||||
|
||||
function isMetadataSymbolicReferenceExpression(expression: any): boolean {
|
||||
return !isPrimitive(expression) && !isArray(expression) &&
|
||||
expression['__symbolic'] == 'reference';
|
||||
}
|
||||
|
||||
function isClassMetadata(expression: any): boolean {
|
||||
return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'class';
|
||||
}
|
||||
|
||||
function splitPath(path: string): string[] {
|
||||
return path.split(/\/|\\/g);
|
||||
}
|
||||
|
||||
function resolvePath(pathParts: string[]): string {
|
||||
let result = [];
|
||||
ListWrapper.forEachWithIndex(pathParts, (part, index) => {
|
||||
switch (part) {
|
||||
case '':
|
||||
case '.':
|
||||
if (index > 0) return;
|
||||
break;
|
||||
case '..':
|
||||
if (index > 0 && result.length != 0) result.pop();
|
||||
return;
|
||||
}
|
||||
result.push(part);
|
||||
});
|
||||
return result.join('/');
|
||||
}
|
||||
|
||||
function pathTo(from: string, to: string): string {
|
||||
let result = to;
|
||||
if (to.startsWith('.')) {
|
||||
let fromParts = splitPath(from);
|
||||
fromParts.pop(); // remove the file name.
|
||||
let toParts = splitPath(to);
|
||||
result = resolvePath(fromParts.concat(toParts));
|
||||
}
|
||||
return result;
|
||||
}
|
@ -31,7 +31,6 @@ export interface IterableDifferFactory {
|
||||
/**
|
||||
* A repository of different iterable diffing strategies used by NgFor, NgClass, and others.
|
||||
*/
|
||||
@Injectable()
|
||||
@CONST()
|
||||
export class IterableDiffers {
|
||||
constructor(public factories: IterableDifferFactory[]) {}
|
||||
|
@ -23,7 +23,6 @@ export interface KeyValueDifferFactory {
|
||||
/**
|
||||
* A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
|
||||
*/
|
||||
@Injectable()
|
||||
@CONST()
|
||||
export class KeyValueDiffers {
|
||||
constructor(public factories: KeyValueDifferFactory[]) {}
|
||||
|
@ -59,7 +59,6 @@ class UIMessageBusSource extends IsolateMessageBusSource {
|
||||
* Wrapper class that exposes the Isolate
|
||||
* and underlying {@link MessageBus} for lower level message passing.
|
||||
*/
|
||||
@Injectable()
|
||||
class WebWorkerInstance {
|
||||
Isolate worker;
|
||||
MessageBus bus;
|
||||
|
@ -84,6 +84,11 @@ function matchUrlSegment(str: string): string {
|
||||
var match = RegExpWrapper.firstMatch(SEGMENT_RE, str);
|
||||
return isPresent(match) ? match[0] : '';
|
||||
}
|
||||
var QUERY_PARAM_VALUE_RE = RegExpWrapper.create('^[^\\(\\)\\?;&#]+');
|
||||
function matchUrlQueryParamValue(str: string): string {
|
||||
var match = RegExpWrapper.firstMatch(QUERY_PARAM_VALUE_RE, str);
|
||||
return isPresent(match) ? match[0] : '';
|
||||
}
|
||||
|
||||
export class UrlParser {
|
||||
private _remaining: string;
|
||||
@ -163,10 +168,10 @@ export class UrlParser {
|
||||
parseQueryParams(): {[key: string]: any} {
|
||||
var params: {[key: string]: any} = {};
|
||||
this.capture('?');
|
||||
this.parseParam(params);
|
||||
this.parseQueryParam(params);
|
||||
while (this._remaining.length > 0 && this.peekStartsWith('&')) {
|
||||
this.capture('&');
|
||||
this.parseParam(params);
|
||||
this.parseQueryParam(params);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
@ -199,6 +204,25 @@ export class UrlParser {
|
||||
params[key] = value;
|
||||
}
|
||||
|
||||
parseQueryParam(params: {[key: string]: any}): void {
|
||||
var key = matchUrlSegment(this._remaining);
|
||||
if (isBlank(key)) {
|
||||
return;
|
||||
}
|
||||
this.capture(key);
|
||||
var value: any = true;
|
||||
if (this.peekStartsWith('=')) {
|
||||
this.capture('=');
|
||||
var valueMatch = matchUrlQueryParamValue(this._remaining);
|
||||
if (isPresent(valueMatch)) {
|
||||
value = valueMatch;
|
||||
this.capture(value);
|
||||
}
|
||||
}
|
||||
|
||||
params[key] = value;
|
||||
}
|
||||
|
||||
parseAuxiliaryRoutes(): Url[] {
|
||||
var routes: Url[] = [];
|
||||
this.capture('(');
|
||||
|
@ -160,7 +160,7 @@ export class DowngradeNg2ComponentAdapter {
|
||||
}
|
||||
|
||||
registerCleanup() {
|
||||
this.element.bind('$remove', () => this.viewManager.destroyRootHostView(this.hostViewRef));
|
||||
this.element.bind('$destroy', () => this.viewManager.destroyRootHostView(this.hostViewRef));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,14 +94,14 @@ export function main() {
|
||||
});
|
||||
|
||||
it("should return select accessor when provided", () => {
|
||||
var selectAccessor = new SelectControlValueAccessor(null, null, new QueryList<any>());
|
||||
var selectAccessor = new SelectControlValueAccessor(null, null);
|
||||
expect(selectValueAccessor(dir, [defaultAccessor, selectAccessor]))
|
||||
.toEqual(selectAccessor);
|
||||
});
|
||||
|
||||
it("should throw when more than one build-in accessor is provided", () => {
|
||||
var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
|
||||
var selectAccessor = new SelectControlValueAccessor(null, null, new QueryList<any>());
|
||||
var selectAccessor = new SelectControlValueAccessor(null, null);
|
||||
expect(() => selectValueAccessor(dir, [checkboxAccessor, selectAccessor])).toThrowError();
|
||||
});
|
||||
|
||||
|
@ -38,7 +38,7 @@ import {
|
||||
import {Provider, forwardRef, Input} from 'angular2/core';
|
||||
import {By} from 'angular2/platform/browser';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {ObservableWrapper, TimerWrapper} from 'angular2/src/facade/async';
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {PromiseWrapper} from "angular2/src/facade/promise";
|
||||
|
||||
@ -357,8 +357,30 @@ export function main() {
|
||||
});
|
||||
}));
|
||||
|
||||
it("should support <select>",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
describe("should support <select>", () => {
|
||||
it("with basic selection",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async) => {
|
||||
var t = `<select>
|
||||
<option value="SF"></option>
|
||||
<option value="NYC"></option>
|
||||
</select>`;
|
||||
|
||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
|
||||
fixture.detectChanges();
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
var sfOption = fixture.debugElement.query(By.css("option"));
|
||||
|
||||
expect(select.nativeElement.value).toEqual("SF");
|
||||
expect(sfOption.nativeElement.selected).toBe(true);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("with ngControl",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder,
|
||||
async) => {
|
||||
var t = `<div [ngFormModel]="form">
|
||||
<select ngControl="city">
|
||||
<option value="SF"></option>
|
||||
@ -373,10 +395,12 @@ export function main() {
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
var sfOption = fixture.debugElement.query(By.css("option"));
|
||||
expect(select.nativeElement.value).toEqual('SF');
|
||||
|
||||
|
||||
expect(select.nativeElement.value).toEqual("SF");
|
||||
expect(sfOption.nativeElement.selected).toBe(true);
|
||||
|
||||
select.nativeElement.value = 'NYC';
|
||||
select.nativeElement.value = "NYC";
|
||||
dispatchEvent(select.nativeElement, "input");
|
||||
|
||||
expect(fixture.debugElement.componentInstance.form.value).toEqual({"city": 'NYC'});
|
||||
@ -385,7 +409,7 @@ export function main() {
|
||||
});
|
||||
}));
|
||||
|
||||
it("should support <select> with a dynamic list of options",
|
||||
it("with a dynamic list of options",
|
||||
inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => {
|
||||
var t = `<div [ngFormModel]="form">
|
||||
<select ngControl="city">
|
||||
@ -400,14 +424,189 @@ export function main() {
|
||||
|
||||
fixture.debugElement.componentInstance.form =
|
||||
new ControlGroup({"city": new Control("NYC")});
|
||||
|
||||
fixture.debugElement.componentInstance.data = ['SF', 'NYC'];
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
var select = fixture.debugElement.query(By.css('select'));
|
||||
expect(select.nativeElement.value).toEqual('NYC');
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
expect(select.nativeElement.value).toEqual("NYC");
|
||||
})));
|
||||
|
||||
it("with option values that are objects",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async) => {
|
||||
var t = `<div>
|
||||
<select [(ngModel)]="selectedCity">
|
||||
<option *ngFor="#c of list" [ngValue]="c">{{c['name']}}</option>
|
||||
</select>
|
||||
</div>`;
|
||||
|
||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
|
||||
|
||||
var testComp = fixture.debugElement.componentInstance;
|
||||
testComp.list = [{"name": "SF"}, {"name": "NYC"}, {"name": "Buffalo"}];
|
||||
testComp.selectedCity = testComp.list[1];
|
||||
fixture.detectChanges();
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
var nycOption = fixture.debugElement.queryAll(By.css("option"))[1];
|
||||
|
||||
expect(select.nativeElement.value).toEqual("1: Object");
|
||||
expect(nycOption.nativeElement.selected).toBe(true);
|
||||
|
||||
select.nativeElement.value = "2: Object";
|
||||
dispatchEvent(select.nativeElement, "input");
|
||||
fixture.detectChanges();
|
||||
TimerWrapper.setTimeout(() => {
|
||||
expect(testComp.selectedCity['name']).toEqual("Buffalo");
|
||||
async.done();
|
||||
}, 0);
|
||||
});
|
||||
}));
|
||||
|
||||
it("when new options are added",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async) => {
|
||||
var t = `<div>
|
||||
<select [(ngModel)]="selectedCity">
|
||||
<option *ngFor="#c of list" [ngValue]="c">{{c['name']}}</option>
|
||||
</select>
|
||||
</div>`;
|
||||
|
||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
|
||||
|
||||
var testComp: MyComp = fixture.debugElement.componentInstance;
|
||||
testComp.list = [{"name": "SF"}, {"name": "NYC"}];
|
||||
testComp.selectedCity = testComp.list[1];
|
||||
fixture.detectChanges();
|
||||
|
||||
testComp.list.push({"name": "Buffalo"});
|
||||
testComp.selectedCity = testComp.list[2];
|
||||
fixture.detectChanges();
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
var buffalo = fixture.debugElement.queryAll(By.css("option"))[2];
|
||||
expect(select.nativeElement.value).toEqual("2: Object");
|
||||
expect(buffalo.nativeElement.selected).toBe(true);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("when options are removed",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async) => {
|
||||
var t = `<div>
|
||||
<select [(ngModel)]="selectedCity">
|
||||
<option *ngFor="#c of list" [ngValue]="c">{{c}}</option>
|
||||
</select>
|
||||
</div>`;
|
||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
|
||||
|
||||
var testComp: MyComp = fixture.debugElement.componentInstance;
|
||||
testComp.list = [{"name": "SF"}, {"name": "NYC"}];
|
||||
testComp.selectedCity = testComp.list[1];
|
||||
fixture.detectChanges();
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
expect(select.nativeElement.value).toEqual("1: Object");
|
||||
|
||||
testComp.list.pop();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(select.nativeElement.value).not.toEqual("1: Object");
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("when option values change identity while tracking by index",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async) => {
|
||||
var t = `<div>
|
||||
<select [(ngModel)]="selectedCity">
|
||||
<option *ngFor="#c of list; trackBy:customTrackBy" [ngValue]="c">{{c}}</option>
|
||||
</select>
|
||||
</div>`;
|
||||
|
||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
|
||||
|
||||
var testComp = fixture.debugElement.componentInstance;
|
||||
|
||||
testComp.list = [{"name": "SF"}, {"name": "NYC"}];
|
||||
testComp.selectedCity = testComp.list[0];
|
||||
fixture.detectChanges();
|
||||
|
||||
testComp.list[1] = "Buffalo";
|
||||
testComp.selectedCity = testComp.list[1];
|
||||
fixture.detectChanges();
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
var buffalo = fixture.debugElement.queryAll(By.css("option"))[1];
|
||||
|
||||
expect(select.nativeElement.value).toEqual("1: Buffalo");
|
||||
expect(buffalo.nativeElement.selected).toBe(true);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("with duplicate option values",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async) => {
|
||||
var t = `<div>
|
||||
<select [(ngModel)]="selectedCity">
|
||||
<option *ngFor="#c of list" [ngValue]="c">{{c}}</option>
|
||||
</select>
|
||||
</div>`;
|
||||
|
||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
|
||||
|
||||
var testComp = fixture.debugElement.componentInstance;
|
||||
|
||||
testComp.list = [{"name": "NYC"}, {"name": "SF"}, {"name": "SF"}];
|
||||
testComp.selectedCity = testComp.list[0];
|
||||
fixture.detectChanges();
|
||||
|
||||
testComp.selectedCity = testComp.list[1];
|
||||
fixture.detectChanges();
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
var firstSF = fixture.debugElement.queryAll(By.css("option"))[1];
|
||||
|
||||
expect(select.nativeElement.value).toEqual("1: Object");
|
||||
expect(firstSF.nativeElement.selected).toBe(true);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("when option values have same content, but different identities",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async) => {
|
||||
var t = `<div>
|
||||
<select [(ngModel)]="selectedCity">
|
||||
<option *ngFor="#c of list" [ngValue]="c">{{c['name']}}</option>
|
||||
</select>
|
||||
</div>`;
|
||||
|
||||
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((fixture) => {
|
||||
|
||||
var testComp = fixture.debugElement.componentInstance;
|
||||
testComp.list = [{"name": "SF"}, {"name": "NYC"}, {"name": "NYC"}];
|
||||
testComp.selectedCity = testComp.list[0];
|
||||
fixture.detectChanges();
|
||||
|
||||
testComp.selectedCity = testComp.list[2];
|
||||
fixture.detectChanges();
|
||||
|
||||
var select = fixture.debugElement.query(By.css("select"));
|
||||
var secondNYC = fixture.debugElement.queryAll(By.css("option"))[2];
|
||||
|
||||
expect(select.nativeElement.value).toEqual("2: Object");
|
||||
expect(secondNYC.nativeElement.selected).toBe(true);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it("should support custom value accessors",
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var t = `<div [ngFormModel]="form">
|
||||
@ -849,7 +1048,6 @@ export function main() {
|
||||
<input type="radio" name="food" ngControl="chicken" [(ngModel)]="data['chicken1']">
|
||||
<input type="radio" name="food" ngControl="fish" [(ngModel)]="data['fish1']">
|
||||
</form>
|
||||
|
||||
<form>
|
||||
<input type="radio" name="food" ngControl="chicken" [(ngModel)]="data['chicken2']">
|
||||
<input type="radio" name="food" ngControl="fish" [(ngModel)]="data['fish2']">
|
||||
@ -1134,6 +1332,9 @@ class MyComp {
|
||||
form: any;
|
||||
name: string;
|
||||
data: any;
|
||||
list: any[];
|
||||
selectedCity: any;
|
||||
customTrackBy(index: number, obj: any): number { return index; };
|
||||
}
|
||||
|
||||
function sortedClassList(el) {
|
||||
|
441
modules/angular2/test/compiler/static_reflector_spec.ts
Normal file
441
modules/angular2/test/compiler/static_reflector_spec.ts
Normal file
@ -0,0 +1,441 @@
|
||||
import {
|
||||
ddescribe,
|
||||
describe,
|
||||
xdescribe,
|
||||
it,
|
||||
iit,
|
||||
xit,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
AsyncTestCompleter,
|
||||
inject,
|
||||
beforeEachProviders
|
||||
} from 'angular2/testing_internal';
|
||||
|
||||
import {StaticReflector, StaticReflectorHost} from 'angular2/src/compiler/static_reflector';
|
||||
|
||||
export function main() {
|
||||
describe('StaticRefelector', () => {
|
||||
it('should get annotations for NgFor', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
let NgFor = reflector.getStaticType('angular2/src/common/directives/ng_for', 'NgFor');
|
||||
let annotations = reflector.annotations(NgFor);
|
||||
expect(annotations.length).toEqual(1);
|
||||
let annotation = annotations[0];
|
||||
expect(annotation.selector).toEqual('[ngFor][ngForOf]');
|
||||
expect(annotation.inputs).toEqual(['ngForTrackBy', 'ngForOf', 'ngForTemplate']);
|
||||
});
|
||||
|
||||
it('should get constructor for NgFor', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
let NgFor = reflector.getStaticType('angular2/src/common/directives/ng_for', 'NgFor');
|
||||
let ViewContainerRef = reflector.getStaticType('angular2/src/core/linker/view_container_ref',
|
||||
'ViewContainerRef');
|
||||
let TemplateRef =
|
||||
reflector.getStaticType('angular2/src/core/linker/template_ref', 'TemplateRef');
|
||||
let IterableDiffers = reflector.getStaticType(
|
||||
'angular2/src/core/change_detection/differs/iterable_differs', 'IterableDiffers');
|
||||
let ChangeDetectorRef = reflector.getStaticType(
|
||||
'angular2/src/core/change_detection/change_detector_ref', 'ChangeDetectorRef');
|
||||
|
||||
let parameters = reflector.parameters(NgFor);
|
||||
expect(parameters)
|
||||
.toEqual([ViewContainerRef, TemplateRef, IterableDiffers, ChangeDetectorRef]);
|
||||
});
|
||||
|
||||
it('should get annotations for HeroDetailComponent', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
let HeroDetailComponent =
|
||||
reflector.getStaticType('./app/hero-detail.component', 'HeroDetailComponent');
|
||||
let annotations = reflector.annotations(HeroDetailComponent);
|
||||
expect(annotations.length).toEqual(1);
|
||||
let annotation = annotations[0];
|
||||
expect(annotation.selector).toEqual('my-hero-detail');
|
||||
});
|
||||
|
||||
it('should get propMetadata for HeroDetailComponent', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
let HeroDetailComponent =
|
||||
reflector.getStaticType('./app/hero-detail.component', 'HeroDetailComponent');
|
||||
let props = reflector.propMetadata(HeroDetailComponent);
|
||||
expect(props['hero']).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should simplify primitive into itself', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', 1)).toBe(1);
|
||||
expect(reflector.simplify('', true)).toBe(true);
|
||||
expect(reflector.simplify('', "some value")).toBe("some value");
|
||||
});
|
||||
|
||||
it('should simplify an array into a copy of the array', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', [1, 2, 3])).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it('should simplify an object to a copy of the object', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
let expr = {a: 1, b: 2, c: 3};
|
||||
expect(reflector.simplify('', expr)).toEqual(expr);
|
||||
});
|
||||
|
||||
it('should simplify &&', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: true}))).toBe(true);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: true, right: false}))).toBe(false);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: true}))).toBe(false);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&&', left: false, right: false}))).toBe(false);
|
||||
});
|
||||
|
||||
it('should simplify ||', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: true}))).toBe(true);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: true, right: false}))).toBe(true);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: true}))).toBe(true);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '||', left: false, right: false}))).toBe(false);
|
||||
});
|
||||
|
||||
it('should simplify &', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0x0F}))).toBe(0x22 & 0x0F);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '&', left: 0x22, right: 0xF0}))).toBe(0x22 & 0xF0);
|
||||
});
|
||||
|
||||
it('should simplify |', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
|
||||
});
|
||||
|
||||
it('should simplify ^', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0x0F}))).toBe(0x22 | 0x0F);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '|', left: 0x22, right: 0xF0}))).toBe(0x22 | 0xF0);
|
||||
});
|
||||
|
||||
it('should simplify ==', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0x22}))).toBe(0x22 == 0x22);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '==', left: 0x22, right: 0xF0}))).toBe(0x22 == 0xF0);
|
||||
});
|
||||
|
||||
it('should simplify !=', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0x22}))).toBe(0x22 != 0x22);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!=', left: 0x22, right: 0xF0}))).toBe(0x22 != 0xF0);
|
||||
});
|
||||
|
||||
it('should simplify ===', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0x22}))).toBe(0x22 === 0x22);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '===', left: 0x22, right: 0xF0}))).toBe(0x22 === 0xF0);
|
||||
});
|
||||
|
||||
it('should simplify !==', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0x22}))).toBe(0x22 !== 0x22);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '!==', left: 0x22, right: 0xF0}))).toBe(0x22 !== 0xF0);
|
||||
});
|
||||
|
||||
it('should simplify >', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 1}))).toBe(1 > 1);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>', left: 1, right: 0}))).toBe(1 > 0);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>', left: 0, right: 1}))).toBe(0 > 1);
|
||||
});
|
||||
|
||||
it('should simplify >=', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 1}))).toBe(1 >= 1);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>=', left: 1, right: 0}))).toBe(1 >= 0);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>=', left: 0, right: 1}))).toBe(0 >= 1);
|
||||
});
|
||||
|
||||
it('should simplify <=', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 1}))).toBe(1 <= 1);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<=', left: 1, right: 0}))).toBe(1 <= 0);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<=', left: 0, right: 1}))).toBe(0 <= 1);
|
||||
});
|
||||
|
||||
it('should simplify <', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 1}))).toBe(1 < 1);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<', left: 1, right: 0}))).toBe(1 < 0);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<', left: 0, right: 1}))).toBe(0 < 1);
|
||||
});
|
||||
|
||||
it('should simplify <<', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '<<', left: 0x55, right: 2}))).toBe(0x55 << 2);
|
||||
});
|
||||
|
||||
it('should simplify >>', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '>>', left: 0x55, right: 2}))).toBe(0x55 >> 2);
|
||||
});
|
||||
|
||||
it('should simplify +', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '+', left: 0x55, right: 2}))).toBe(0x55 + 2);
|
||||
});
|
||||
|
||||
it('should simplify -', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '-', left: 0x55, right: 2}))).toBe(0x55 - 2);
|
||||
});
|
||||
|
||||
it('should simplify *', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '*', left: 0x55, right: 2}))).toBe(0x55 * 2);
|
||||
});
|
||||
|
||||
it('should simplify /', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '/', left: 0x55, right: 2}))).toBe(0x55 / 2);
|
||||
});
|
||||
|
||||
it('should simplify %', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'binop', operator: '%', left: 0x55, right: 2}))).toBe(0x55 % 2);
|
||||
});
|
||||
|
||||
it('should simplify prefix -', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '-', operand: 2}))).toBe(-2);
|
||||
});
|
||||
|
||||
it('should simplify prefix ~', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '~', operand: 2}))).toBe(~2);
|
||||
});
|
||||
|
||||
it('should simplify prefix !', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '!', operand: true}))).toBe(!true);
|
||||
expect(reflector.simplify('', ({ __symbolic: 'pre', operator: '!', operand: false}))).toBe(!false);
|
||||
});
|
||||
|
||||
it('should simpify an array index', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(reflector.simplify('', ({__symbolic: "index", expression: [1, 2, 3], index: 2})))
|
||||
.toBe(3);
|
||||
});
|
||||
|
||||
it('should simplify an object index', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
let expr = {__symbolic: "select", expression: {a: 1, b: 2, c: 3}, member: "b"};
|
||||
expect(reflector.simplify('', expr)).toBe(2);
|
||||
});
|
||||
|
||||
it('should simplify a module reference', () => {
|
||||
let host = new MockReflectorHost();
|
||||
let reflector = new StaticReflector(host);
|
||||
|
||||
expect(
|
||||
reflector.simplify('./cases', ({__symbolic: "reference", module: "./extern", name: "s"})))
|
||||
.toEqual("s");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class MockReflectorHost implements StaticReflectorHost {
|
||||
getMetadataFor(moduleId: string): any {
|
||||
return {
|
||||
'angular2/src/common/directives/ng_for':
|
||||
{
|
||||
"__symbolic": "module",
|
||||
"module": "./ng_for",
|
||||
"metadata":
|
||||
{
|
||||
"NgFor":
|
||||
{
|
||||
"__symbolic": "class",
|
||||
"decorators":
|
||||
[
|
||||
{
|
||||
"__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic": "reference",
|
||||
"name": "Directive",
|
||||
"module": "../../core/metadata"
|
||||
},
|
||||
"arguments":
|
||||
[
|
||||
{
|
||||
"selector": "[ngFor][ngForOf]",
|
||||
"inputs": ["ngForTrackBy", "ngForOf", "ngForTemplate"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"members":
|
||||
{
|
||||
"__ctor__": [
|
||||
{
|
||||
"__symbolic": "constructor",
|
||||
"parameters":
|
||||
[
|
||||
{
|
||||
"__symbolic": "reference",
|
||||
"module": "../../core/linker/view_container_ref",
|
||||
"name": "ViewContainerRef"
|
||||
},
|
||||
{
|
||||
"__symbolic": "reference",
|
||||
"module": "../../core/linker/template_ref",
|
||||
"name": "TemplateRef"
|
||||
},
|
||||
{
|
||||
"__symbolic": "reference",
|
||||
"module":
|
||||
"../../core/change_detection/differs/iterable_differs",
|
||||
"name": "IterableDiffers"
|
||||
},
|
||||
{
|
||||
"__symbolic": "reference",
|
||||
"module":
|
||||
"../../core/change_detection/change_detector_ref",
|
||||
"name": "ChangeDetectorRef"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'angular2/src/core/linker/view_container_ref':
|
||||
{
|
||||
"module": "./view_container_ref",
|
||||
"metadata": {"ViewContainerRef": {"__symbolic": "class"}}
|
||||
},
|
||||
'angular2/src/core/linker/template_ref':
|
||||
{"module": "./template_ref", "metadata": {"TemplateRef": {"__symbolic": "class"}}},
|
||||
'angular2/src/core/change_detection/differs/iterable_differs':
|
||||
{
|
||||
"module": "./iterable_differs",
|
||||
"metadata": {"IterableDiffers": {"__symbolic": "class"}}
|
||||
},
|
||||
'angular2/src/core/change_detection/change_detector_ref':
|
||||
{
|
||||
"module": "./change_detector_ref",
|
||||
"metadata": {"ChangeDetectorRef": {"__symbolic": "class"}}
|
||||
},
|
||||
'./app/hero-detail.component':
|
||||
{
|
||||
"__symbolic": "module",
|
||||
"module": "./hero-detail.component",
|
||||
"metadata":
|
||||
{
|
||||
"HeroDetailComponent":
|
||||
{
|
||||
"__symbolic": "class",
|
||||
"decorators":
|
||||
[
|
||||
{
|
||||
"__symbolic": "call",
|
||||
"expression": {
|
||||
"__symbolic": "reference",
|
||||
"name": "Component",
|
||||
"module": "angular2/src/core/metadata"
|
||||
},
|
||||
"arguments": [
|
||||
{
|
||||
"selector": "my-hero-detail",
|
||||
"template": "\n <div *ngIf=\"hero\">\n <h2>{{hero.name}} details!</h2>\n <div><label>id: </label>{{hero.id}}</div>\n <div>\n <label>name: </label>\n <input [(ngModel)]=\"hero.name\" placeholder=\"name\"/>\n </div>\n </div>\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"members":
|
||||
{
|
||||
"hero": [
|
||||
{
|
||||
"__symbolic": "property",
|
||||
"decorators":
|
||||
[
|
||||
{
|
||||
"__symbolic": "call",
|
||||
"expression":
|
||||
{
|
||||
"__symbolic": "reference",
|
||||
"name": "Input",
|
||||
"module": "angular2/src/core/metadata"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'./extern': {
|
||||
"__symbolic": "module", module: './extern', metadata: { s: "s" }
|
||||
}
|
||||
}
|
||||
[moduleId];
|
||||
}
|
||||
}
|
@ -124,5 +124,12 @@ export function main() {
|
||||
var url = urlParser.parse('hello/there;sort=asc(modal)?friend=true');
|
||||
expect(url.toString()).toEqual('hello/there;sort=asc(modal)?friend=true');
|
||||
});
|
||||
it('should allow slashes within query parameters', () => {
|
||||
var url = urlParser.parse(
|
||||
'hello?code=4/B8o0n_Y7XZTb-pVKBw5daZyGAUbMljyLf7uNgTy6ja8&scope=https://www.googleapis.com/auth/analytics');
|
||||
expect(url.toString())
|
||||
.toEqual(
|
||||
'hello?code=4/B8o0n_Y7XZTb-pVKBw5daZyGAUbMljyLf7uNgTy6ja8&scope=https://www.googleapis.com/auth/analytics');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -230,6 +230,35 @@ export function main() {
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
it('should properly run cleanup when ng1 directive is destroyed',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
var adapter: UpgradeAdapter = new UpgradeAdapter();
|
||||
var ng1Module = angular.module('ng1', []);
|
||||
var onDestroyed: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
ng1Module.directive('ng1', () => {
|
||||
return {
|
||||
template: '<div ng-if="!destroyIt"><ng2></ng2></div>',
|
||||
controller: function($rootScope, $timeout) {
|
||||
$timeout(function() { $rootScope.destroyIt = true; });
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
var Ng2 = Component({selector: 'ng2', template: 'test'})
|
||||
.Class({
|
||||
constructor: function() {},
|
||||
ngOnDestroy: function() { onDestroyed.emit('destroyed'); }
|
||||
});
|
||||
ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));
|
||||
var element = html('<ng1></ng1>');
|
||||
adapter.bootstrap(element, ['ng1'])
|
||||
.ready((ref) => {onDestroyed.subscribe(() => {
|
||||
ref.dispose();
|
||||
async.done();
|
||||
})});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('upgrade ng1 component', () => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
library angular2.transform.common.async_string_writer;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analyzer/src/generated/java_core.dart';
|
||||
|
||||
/// [PrintWriter] implementation that allows asynchronous printing via
|
||||
@ -18,6 +19,7 @@ class AsyncStringWriter extends PrintWriter {
|
||||
|
||||
AsyncStringWriter([Object content = ""]) : this._(new StringBuffer(content));
|
||||
|
||||
@override
|
||||
void print(x) {
|
||||
_curr.write(x);
|
||||
}
|
||||
@ -54,6 +56,7 @@ class AsyncStringWriter extends PrintWriter {
|
||||
}).whenComplete(_semaphoreDecrementAndCleanup);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => _bufs.map((buf) => '$buf').join('(async gap)');
|
||||
|
||||
void _semaphoreIncrement() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
library angular2.src.transform.common.logging;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io' show stderr;
|
||||
|
||||
import 'package:barback/barback.dart';
|
||||
import 'package:source_span/source_span.dart';
|
||||
@ -49,12 +50,16 @@ void _logElapsed(Stopwatch timer, String operationName, AssetId assetId) {
|
||||
log.fine(buf.toString(), asset: assetId);
|
||||
}
|
||||
|
||||
/// Prints logged messages to the console.
|
||||
/// Writes logged messages to the provided [StringSink].
|
||||
///
|
||||
/// A simple implementation of [TransformLogger] that prints messages to the
|
||||
/// console and discards `asset` and `span` information.
|
||||
class PrintLogger implements TransformLogger {
|
||||
void _printWithPrefix(prefix, msg) => print('$prefix: $msg');
|
||||
/// A simple implementation of [TransformLogger] that writes messages to a
|
||||
/// [StringSink] and discards `asset` and `span` information.
|
||||
class SinkLogger implements TransformLogger {
|
||||
final StringSink _sink;
|
||||
|
||||
SinkLogger(this._sink);
|
||||
|
||||
void _printWithPrefix(prefix, msg) => _sink.writeln('$prefix: $msg');
|
||||
|
||||
@override
|
||||
void info(msg, {AssetId asset, SourceSpan span}) =>
|
||||
@ -74,6 +79,14 @@ class PrintLogger implements TransformLogger {
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints logged messages to stderr.
|
||||
///
|
||||
/// A simple implementation of [TransformLogger] that prints messages to
|
||||
/// [stderr] and discards `asset` and `span` information.
|
||||
class PrintLogger extends SinkLogger {
|
||||
PrintLogger() : super(stderr);
|
||||
}
|
||||
|
||||
class PrintLoggerError extends Error {
|
||||
final String message;
|
||||
final AssetId asset;
|
||||
|
@ -1,12 +1,15 @@
|
||||
library angular2.transform.common.options_reader;
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:barback/barback.dart';
|
||||
|
||||
import 'annotation_matcher.dart';
|
||||
import 'mirror_mode.dart';
|
||||
import 'options.dart';
|
||||
import './url_resolver.dart';
|
||||
|
||||
TransformerOptions parseBarbackSettings(BarbackSettings settings) {
|
||||
TransformerOptions parseBarbackSettings(BarbackSettings settings) {
|
||||
var config = settings.configuration;
|
||||
var entryPoints = _readStringList(config, ENTRY_POINT_PARAM);
|
||||
var initReflector =
|
||||
@ -79,7 +82,8 @@ List<String> _readStringList(Map config, String paramName) {
|
||||
error = true;
|
||||
}
|
||||
if (error) {
|
||||
print('Invalid value for "$paramName" in the Angular 2 transformer.');
|
||||
stderr.writeln(
|
||||
'Invalid value for "$paramName" in the Angular 2 transformer.');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -111,7 +115,7 @@ List<ClassDescriptor> _readCustomAnnotations(Map config) {
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
print(CUSTOM_ANNOTATIONS_ERROR);
|
||||
stderr.writeln(CUSTOM_ANNOTATIONS_ERROR);
|
||||
}
|
||||
return descriptors;
|
||||
}
|
||||
@ -121,7 +125,7 @@ const CUSTOM_ANNOTATIONS_ERROR = '''
|
||||
Expected something that looks like the following:
|
||||
|
||||
transformers:
|
||||
- angular2:
|
||||
- angular2[/transform/codegen]:
|
||||
custom_annotations:
|
||||
- name: MyAnnotation
|
||||
import: 'package:my_package/my_annotation.dart'
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "2.0.0-beta.13",
|
||||
"version": "2.0.0-beta.14",
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular 2 - a web framework for modern web apps",
|
||||
"homepage": "https://github.com/angular/angular",
|
||||
|
@ -777,6 +777,11 @@ const COMMON = [
|
||||
'NgPlural.ngPlural=(value:number)',
|
||||
'NgPluralCase',
|
||||
'NgSelectOption',
|
||||
'NgSelectOption.constructor(_element:ElementRef, _renderer:Renderer, _select:SelectControlValueAccessor)',
|
||||
'NgSelectOption.id:string',
|
||||
'NgSelectOption.ngOnDestroy():any',
|
||||
'NgSelectOption.ngValue=(value:any)',
|
||||
'NgSelectOption.value=(value:any)',
|
||||
'NgStyle',
|
||||
'NgStyle.constructor(_differs:KeyValueDiffers, _ngEl:ElementRef, _renderer:Renderer)',
|
||||
'NgStyle.ngDoCheck():any',
|
||||
@ -798,12 +803,12 @@ const COMMON = [
|
||||
'ReplacePipe.transform(value:any, args:any[]):any',
|
||||
'RequiredValidator',
|
||||
'SelectControlValueAccessor',
|
||||
'SelectControlValueAccessor.constructor(_renderer:Renderer, _elementRef:ElementRef, query:QueryList<NgSelectOption>)',
|
||||
'SelectControlValueAccessor.constructor(_renderer:Renderer, _elementRef:ElementRef)',
|
||||
'SelectControlValueAccessor.onChange:any',
|
||||
'SelectControlValueAccessor.onTouched:any',
|
||||
'SelectControlValueAccessor.registerOnChange(fn:() => any):void',
|
||||
'SelectControlValueAccessor.registerOnChange(fn:(value: any) => any):void',
|
||||
'SelectControlValueAccessor.registerOnTouched(fn:() => any):void',
|
||||
'SelectControlValueAccessor.value:string',
|
||||
'SelectControlValueAccessor.value:any',
|
||||
'SelectControlValueAccessor.writeValue(value:any):void',
|
||||
'SlicePipe',
|
||||
'SlicePipe.transform(value:any, args:any[]):any',
|
||||
|
Reference in New Issue
Block a user