UNPKG

injection-js

Version:

Dependency Injection library for JavaScript and TypeScript

244 lines 11.3 kB
/** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { __spreadArrays } from "tslib"; import { global, stringify } from '../facade/lang'; import { Type, isType } from '../facade/type'; /** * Attention: This regex has to hold even if the code is minified! */ export var DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*arguments\)/; var ReflectionCapabilities = /** @class */ (function () { function ReflectionCapabilities(reflect) { this._reflect = reflect || global['Reflect']; } ReflectionCapabilities.prototype.isReflectionEnabled = function () { return true; }; ReflectionCapabilities.prototype.factory = function (t) { return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return new (t.bind.apply(t, __spreadArrays([void 0], args)))(); }; }; /** @internal */ ReflectionCapabilities.prototype._zipTypesAndAnnotations = function (paramTypes, paramAnnotations) { var result; if (typeof paramTypes === 'undefined') { result = new Array(paramAnnotations.length); } else { result = new Array(paramTypes.length); } 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. if (typeof paramTypes === 'undefined') { result[i] = []; // tslint:disable-next-line:triple-equals } else if (paramTypes[i] != Object) { result[i] = [paramTypes[i]]; } else { result[i] = []; } if (paramAnnotations && paramAnnotations[i] != null) { result[i] = result[i].concat(paramAnnotations[i]); } } return result; }; ReflectionCapabilities.prototype._ownParameters = function (type, parentCtor) { // If we have no decorators, we only have function.length as metadata. // In that case, to detect whether a child class declared an own constructor or not, // we need to look inside of that constructor to check whether it is // just calling the parent. // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439 // that sets 'design:paramtypes' to [] // if a class inherits from another class but has no ctor declared itself. if (DELEGATE_CTOR.exec(type.toString())) { return null; } // Prefer the direct API. if (type.parameters && type.parameters !== parentCtor.parameters) { return type.parameters; } // API of tsickle for lowering decorators to properties on the class. var tsickleCtorParams = type.ctorParameters; if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) { // Newer tsickle uses a function closure // Retain the non-function case for compatibility with older tsickle var ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams; var paramTypes = ctorParameters.map(function (ctorParam) { return ctorParam && ctorParam.type; }); var paramAnnotations = ctorParameters.map(function (ctorParam) { return ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators); }); return this._zipTypesAndAnnotations(paramTypes, paramAnnotations); } // API for metadata created by invoking the decorators. if (this._reflect != null && this._reflect.getOwnMetadata != null) { var paramAnnotations = this._reflect.getOwnMetadata('parameters', type); var paramTypes = this._reflect.getOwnMetadata('design:paramtypes', type); if (paramTypes || paramAnnotations) { return this._zipTypesAndAnnotations(paramTypes, paramAnnotations); } } // If a class has no decorators, at least create metadata // based on function.length. // Note: We know that this is a real constructor as we checked // the content of the constructor above. return new Array(type.length).fill(undefined); }; ReflectionCapabilities.prototype.parameters = function (type) { // Note: only report metadata if we have at least one class decorator // to stay in sync with the static reflector. if (!isType(type)) { return []; } var parentCtor = getParentCtor(type); var parameters = this._ownParameters(type, parentCtor); if (!parameters && parentCtor !== Object) { parameters = this.parameters(parentCtor); } return parameters || []; }; ReflectionCapabilities.prototype._ownAnnotations = function (typeOrFunc, parentCtor) { // Prefer the direct API. if (typeOrFunc.annotations && typeOrFunc.annotations !== parentCtor.annotations) { var annotations = typeOrFunc.annotations; if (typeof annotations === 'function' && annotations.annotations) { annotations = annotations.annotations; } return annotations; } // API of tsickle for lowering decorators to properties on the class. if (typeOrFunc.decorators && typeOrFunc.decorators !== parentCtor.decorators) { return convertTsickleDecoratorIntoMetadata(typeOrFunc.decorators); } // API for metadata created by invoking the decorators. if (this._reflect && this._reflect.getOwnMetadata) { return this._reflect.getOwnMetadata('annotations', typeOrFunc); } return null; }; ReflectionCapabilities.prototype.annotations = function (typeOrFunc) { if (!isType(typeOrFunc)) { return []; } var parentCtor = getParentCtor(typeOrFunc); var ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || []; var parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : []; return parentAnnotations.concat(ownAnnotations); }; ReflectionCapabilities.prototype._ownPropMetadata = function (typeOrFunc, parentCtor) { // Prefer the direct API. if (typeOrFunc.propMetadata && typeOrFunc.propMetadata !== parentCtor.propMetadata) { var propMetadata = typeOrFunc.propMetadata; if (typeof propMetadata === 'function' && propMetadata.propMetadata) { propMetadata = propMetadata.propMetadata; } return propMetadata; } // API of tsickle for lowering decorators to properties on the class. if (typeOrFunc.propDecorators && typeOrFunc.propDecorators !== parentCtor.propDecorators) { var propDecorators_1 = typeOrFunc.propDecorators; var propMetadata_1 = {}; Object.keys(propDecorators_1).forEach(function (prop) { propMetadata_1[prop] = convertTsickleDecoratorIntoMetadata(propDecorators_1[prop]); }); return propMetadata_1; } // API for metadata created by invoking the decorators. if (this._reflect && this._reflect.getOwnMetadata) { return this._reflect.getOwnMetadata('propMetadata', typeOrFunc); } return null; }; ReflectionCapabilities.prototype.propMetadata = function (typeOrFunc) { if (!isType(typeOrFunc)) { return {}; } var parentCtor = getParentCtor(typeOrFunc); var propMetadata = {}; if (parentCtor !== Object) { var parentPropMetadata_1 = this.propMetadata(parentCtor); Object.keys(parentPropMetadata_1).forEach(function (propName) { propMetadata[propName] = parentPropMetadata_1[propName]; }); } var ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor); if (ownPropMetadata) { Object.keys(ownPropMetadata).forEach(function (propName) { var decorators = []; if (propMetadata.hasOwnProperty(propName)) { decorators.push.apply(decorators, propMetadata[propName]); } decorators.push.apply(decorators, ownPropMetadata[propName]); propMetadata[propName] = decorators; }); } return propMetadata; }; ReflectionCapabilities.prototype.hasLifecycleHook = function (type, lcProperty) { return type instanceof Type && lcProperty in type.prototype; }; ReflectionCapabilities.prototype.getter = function (name) { return new Function('o', 'return o.' + name + ';'); }; ReflectionCapabilities.prototype.setter = function (name) { return new Function('o', 'v', 'return o.' + name + ' = v;'); }; ReflectionCapabilities.prototype.method = function (name) { var functionBody = "if (!o." + name + ") throw new Error('\"" + name + "\" is undefined');\n return o." + name + ".apply(o, args);"; return new Function('o', 'args', functionBody); }; // There is not a concept of import uri in Js, but this is useful in developing Dart applications. ReflectionCapabilities.prototype.importUri = function (type) { // StaticSymbol if (typeof type === 'object' && type['filePath']) { return type['filePath']; } // Runtime type return "./" + stringify(type); }; ReflectionCapabilities.prototype.resourceUri = function (type) { return "./" + stringify(type); }; ReflectionCapabilities.prototype.resolveIdentifier = function (name, moduleUrl, members, runtime) { return runtime; }; ReflectionCapabilities.prototype.resolveEnum = function (enumIdentifier, name) { return enumIdentifier[name]; }; return ReflectionCapabilities; }()); export { ReflectionCapabilities }; function convertTsickleDecoratorIntoMetadata(decoratorInvocations) { if (!decoratorInvocations) { return []; } return decoratorInvocations.map(function (decoratorInvocation) { var decoratorType = decoratorInvocation.type; var annotationCls = decoratorType.annotationCls; var annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : []; return new (annotationCls.bind.apply(annotationCls, __spreadArrays([void 0], annotationArgs)))(); }); } function getParentCtor(ctor) { if (!ctor.prototype) { return Object; } var parentProto = Object.getPrototypeOf(ctor.prototype); var parentCtor = parentProto ? parentProto.constructor : null; // Note: We always use `Object` as the null value // to simplify checking later on. return parentCtor || Object; } //# sourceMappingURL=reflection_capabilities.js.map