2015-05-19 17:29:10 -04:00
|
|
|
import {Type, isPresent, global, stringify} from 'angular2/src/facade/lang';
|
2015-04-24 16:17:36 -04:00
|
|
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
|
|
|
import {GetterFn, SetterFn, MethodFn} from './types';
|
|
|
|
|
|
|
|
export class ReflectionCapabilities {
|
2015-05-01 17:05:19 -04:00
|
|
|
private _reflect: any;
|
|
|
|
|
|
|
|
constructor(reflect?: any) { this._reflect = isPresent(reflect) ? reflect : global.Reflect; }
|
|
|
|
|
|
|
|
factory(t: Type): Function {
|
|
|
|
switch (t.length) {
|
2015-04-24 16:17:36 -04:00
|
|
|
case 0:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function() { return new t(); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 1:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function(a1) { return new t(a1); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 2:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function(a1, a2) { return new t(a1, a2); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 3:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function(a1, a2, a3) { return new t(a1, a2, a3); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 4:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function(a1, a2, a3, a4) { return new t(a1, a2, a3, a4); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 5:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function(a1, a2, a3, a4, a5) { return new t(a1, a2, a3, a4, a5); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 6:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function(a1, a2, a3, a4, a5, a6) { return new t(a1, a2, a3, a4, a5, a6); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 7:
|
2015-05-01 17:05:19 -04:00
|
|
|
return function(a1, a2, a3, a4, a5, a6, a7) { return new t(a1, a2, a3, a4, a5, a6, a7); };
|
2015-04-24 16:17:36 -04:00
|
|
|
case 8:
|
|
|
|
return function(a1, a2, a3, a4, a5, a6, a7, a8) {
|
2015-05-01 17:05:19 -04:00
|
|
|
return new t(a1, a2, a3, a4, a5, a6, a7, a8);
|
2015-04-24 16:17:36 -04:00
|
|
|
};
|
|
|
|
case 9:
|
|
|
|
return function(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
2015-05-01 17:05:19 -04:00
|
|
|
return new t(a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
2015-04-24 16:17:36 -04:00
|
|
|
};
|
|
|
|
case 10:
|
|
|
|
return function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
2015-05-01 17:05:19 -04:00
|
|
|
return new t(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
|
2015-04-24 16:17:36 -04:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-05-19 17:29:10 -04:00
|
|
|
throw new Error(
|
|
|
|
`Cannot create a factory for '${stringify(t)}' because its constructor has more than 10 arguments`);
|
2015-04-24 16:17:36 -04:00
|
|
|
}
|
|
|
|
|
2015-04-29 19:22:38 -04:00
|
|
|
_zipTypesAndAnnotaions(paramTypes, paramAnnotations): List<List<any>> {
|
2015-05-18 02:11:13 -04:00
|
|
|
var result;
|
|
|
|
|
|
|
|
if (typeof paramTypes === 'undefined') {
|
|
|
|
result = ListWrapper.createFixedSize(paramAnnotations.length);
|
|
|
|
} else {
|
|
|
|
result = ListWrapper.createFixedSize(paramTypes.length);
|
|
|
|
}
|
|
|
|
|
2015-04-29 19:22:38 -04:00
|
|
|
for (var i = 0; i < result.length; i++) {
|
|
|
|
// TS outputs Object for parameters without types, while Traceur omits
|
|
|
|
// the annotations. For now we preserve the Traceur behavior to aid
|
|
|
|
// migration, but this can be revisited.
|
2015-05-18 02:11:13 -04:00
|
|
|
if (typeof paramTypes === 'undefined') {
|
|
|
|
result[i] = [];
|
|
|
|
} else if (paramTypes[i] != Object) {
|
2015-04-29 19:22:38 -04:00
|
|
|
result[i] = [paramTypes[i]];
|
|
|
|
} else {
|
|
|
|
result[i] = [];
|
|
|
|
}
|
2015-05-06 13:06:30 -04:00
|
|
|
if (isPresent(paramAnnotations) && isPresent(paramAnnotations[i])) {
|
2015-04-29 19:22:38 -04:00
|
|
|
result[i] = result[i].concat(paramAnnotations[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-04-24 16:17:36 -04:00
|
|
|
parameters(typeOfFunc): List<List<any>> {
|
2015-04-28 21:17:00 -04:00
|
|
|
// Prefer the direct API.
|
|
|
|
if (isPresent(typeOfFunc.parameters)) {
|
|
|
|
return typeOfFunc.parameters;
|
|
|
|
}
|
2015-05-01 17:05:19 -04:00
|
|
|
if (isPresent(this._reflect) && isPresent(this._reflect.getMetadata)) {
|
|
|
|
var paramAnnotations = this._reflect.getMetadata('parameters', typeOfFunc);
|
|
|
|
var paramTypes = this._reflect.getMetadata('design:paramtypes', typeOfFunc);
|
2015-04-29 19:22:38 -04:00
|
|
|
if (isPresent(paramTypes) || isPresent(paramAnnotations)) {
|
|
|
|
return this._zipTypesAndAnnotaions(paramTypes, paramAnnotations);
|
2015-04-28 21:17:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ListWrapper.createFixedSize(typeOfFunc.length);
|
2015-04-24 16:17:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
annotations(typeOfFunc): List<any> {
|
2015-04-28 21:17:00 -04:00
|
|
|
// Prefer the direct API.
|
|
|
|
if (isPresent(typeOfFunc.annotations)) {
|
|
|
|
return typeOfFunc.annotations;
|
|
|
|
}
|
2015-05-01 17:05:19 -04:00
|
|
|
if (isPresent(this._reflect) && isPresent(this._reflect.getMetadata)) {
|
|
|
|
var annotations = this._reflect.getMetadata('annotations', typeOfFunc);
|
2015-04-28 21:17:00 -04:00
|
|
|
if (isPresent(annotations)) return annotations;
|
|
|
|
}
|
|
|
|
return [];
|
2015-04-24 16:17:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
getter(name: string): GetterFn { return new Function('o', 'return o.' + name + ';'); }
|
|
|
|
|
|
|
|
setter(name: string): SetterFn { return new Function('o', 'v', 'return o.' + name + ' = v;'); }
|
|
|
|
|
|
|
|
method(name: string): MethodFn {
|
|
|
|
let functionBody = `if (!o.${name}) throw new Error('"${name}" is undefined');
|
|
|
|
return o.${name}.apply(o, args);`;
|
|
|
|
return new Function('o', 'args', functionBody);
|
|
|
|
}
|
|
|
|
}
|