diff --git a/src/ts/Cancellation.ts b/src/ts/Cancellation.ts --- a/src/ts/Cancellation.ts +++ b/src/ts/Cancellation.ts @@ -40,21 +40,21 @@ export class Cancellation implements ICa else this._cbs.push(cb); - let me = this; + const me = this; return { - destroy() { - me._unregister(cb); - } + destroy() { + me._unregister(cb); + } }; } } - + private _unregister(cb) { - if(this._cbs) { - let i = this._cbs.indexOf(cb); - if ( i>=0 ) - this._cbs.splice(i,1); - } + if (this._cbs) { + const i = this._cbs.indexOf(cb); + if (i >= 0) + this._cbs.splice(i, 1); + } } private _cancel(reason) { @@ -63,7 +63,6 @@ export class Cancellation implements ICa this._reason = (reason = reason || new Error("Operation cancelled")); - if (this._cbs) { this._cbs.forEach(cb => cb(reason)); this._cbs = null; @@ -83,7 +82,7 @@ export class Cancellation implements ICa }, register(_cb: (e: any) => void): IDestroyable { - return destroyed; + return destroyed; } }; -} \ No newline at end of file +} diff --git a/src/ts/Observable.ts b/src/ts/Observable.ts --- a/src/ts/Observable.ts +++ b/src/ts/Observable.ts @@ -1,36 +1,30 @@ -import { IObservable, IDestroyable, ICancellation } from './interfaces'; -import { Cancellation } from './Cancellation' -import { argumentNotNull } from './safe'; - +import { IObservable, IDestroyable, ICancellation } from "./interfaces"; +import { Cancellation } from "./Cancellation"; +import { argumentNotNull } from "./safe"; -interface Handler { - (x: T): void -} +type Handler = (x: T) => void; -interface Initializer { - (notify: Handler, error?: (e: any) => void, complete?: () => void): void; -} +type Initializer = (notify: Handler, error?: (e: any) => void, complete?: () => void) => void; // TODO: think about to move this interfaces.ts and make it public interface IObserver { - next(event: T): void + next(event: T): void; - error(e: any): void + error(e: any): void; - complete(): void + complete(): void; } -const noop = () => {}; +const noop = () => { }; export class Observable implements IObservable { private _once = new Array>(); private _observers = new Array>(); + private _complete: boolean; - private _complete: boolean - - private _error: any + private _error: any; constructor(func?: Initializer) { if (func) @@ -43,21 +37,21 @@ export class Observable implements IO /** * Registers handlers for the current observable object. - * + * * @param next the handler for events * @param error the handler for a error * @param complete the handler for a completion * @returns {IDestroyable} the handler for the current subscription, this * handler can be used to unsubscribe from events. - * + * */ on(next: Handler, error?: Handler, complete?: () => void): IDestroyable { argumentNotNull(next, "next"); - let me = this; + const me = this; - let observer: IObserver & IDestroyable = { - next: next, + const observer: IObserver & IDestroyable = { + next, error: error ? error.bind(null) : noop, complete: complete ? complete.bind(null) : noop, @@ -68,7 +62,6 @@ export class Observable implements IO this._addObserver(observer); - return observer; } @@ -90,19 +83,19 @@ export class Observable implements IO /** * Waits for the next event. This method can't be used to read messages * as a sequence since it can skip some messages between calls. - * + * * @param ct a cancellation token */ next(ct: ICancellation = Cancellation.none): Promise { return new Promise((resolve, reject) => { - let observer: IObserver = { + const observer: IObserver = { next: resolve, error: reject, complete: () => reject("No more events are available") }; if (this._addOnce(observer) && ct.isSupported()) { - ct.register((e) => { + ct.register(e => { this._removeOnce(observer); reject(e); }); @@ -131,48 +124,44 @@ export class Observable implements IO } private _removeOnce(d: IObserver) { - let i = this._once.indexOf(d); + const i = this._once.indexOf(d); if (i >= 0) this._once.splice(i, 1); } private _removeObserver(d: IObserver) { - let i = this._observers.indexOf(d); + const i = this._observers.indexOf(d); if (i >= 0) this._observers.splice(i, 1); } private _notify(guard: (observer: IObserver) => void) { - if (this._once.length) { - for (let i = 0; i < this._once.length; i++) - guard(this._once[i]); - this._once = []; - } + this._once.forEach(guard); + this._once = []; - for (let i = 0; i < this._observers.length; i++) - guard(this._observers[i]); + this._observers.forEach(guard); } protected _notifyNext(evt: T) { - let guard = (observer: IObserver) => { + const guard = (observer: IObserver) => { try { observer.next(evt); } catch (e) { this.onObserverException(e); } - } + }; this._notify(guard); } protected _notifyError(e: any) { - let guard = (observer: IObserver) => { + const guard = (observer: IObserver) => { try { observer.error(e); } catch (e) { this.onObserverException(e); } - } + }; this._notify(guard); this._observers = []; @@ -180,16 +169,16 @@ export class Observable implements IO } protected _notifyCompleted() { - let guard = (observer: IObserver) => { + const guard = (observer: IObserver) => { try { observer.complete(); } catch (e) { this.onObserverException(e); } - } + }; this._notify(guard); this._observers = []; this._complete = true; } -} \ No newline at end of file +} diff --git a/src/ts/Uuid.ts b/src/ts/Uuid.ts --- a/src/ts/Uuid.ts +++ b/src/ts/Uuid.ts @@ -8,7 +8,7 @@ declare var window: any; -let _window: any = 'undefined' !== typeof window ? window : null; +const _window: any = "undefined" !== typeof window ? window : null; // Unique ID creation requires a high quality random # generator. We // feature @@ -19,14 +19,14 @@ let _rng; function setupBrowser() { // Allow for MSIE11 msCrypto - let _crypto = _window.crypto || _window.msCrypto; + const _crypto = _window.crypto || _window.msCrypto; if (!_rng && _crypto && _crypto.getRandomValues) { // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto // // Moderately fast, high quality try { - let _rnds8 = new Uint8Array(16); + const _rnds8 = new Uint8Array(16); _rng = function whatwgRNG() { _crypto.getRandomValues(_rnds8); return _rnds8; @@ -41,9 +41,9 @@ function setupBrowser() { // If all else fails, use Math.random(). It's fast, but is of // unspecified // quality. - let _rnds = new Array(16); - _rng = function () { - for (var i = 0, r; i < 16; i++) { + const _rnds = new Array(16); + _rng = () => { + for (let i = 0, r; i < 16; i++) { if ((i & 0x03) === 0) { r = Math.random() * 0x100000000; } @@ -52,7 +52,7 @@ function setupBrowser() { return _rnds; }; - if ('undefined' !== typeof console && console.warn) { + if ("undefined" !== typeof console && console.warn) { console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()"); } } @@ -63,12 +63,10 @@ function setupNode() { // http://nodejs.org/docs/v0.6.2/api/crypto.html // // Moderately fast, high quality - if ('function' === typeof require) { + if ("function" === typeof require) { try { - let _rb = require('crypto').randomBytes; - _rng = _rb && function () { - return _rb(16); - }; + const _rb = require("crypto").randomBytes; + _rng = _rb && (() => _rb(16)); _rng(); } catch (e) { /**/ } } @@ -81,22 +79,22 @@ if (_window) { } // Buffer class to use -let BufferClass = ('function' === typeof Buffer) ? Buffer : Array; +const BufferClass = ("function" === typeof Buffer) ? Buffer : Array; // Maps for number <-> hex string conversion -let _byteToHex = []; -let _hexToByte = {}; +const _byteToHex = []; +const _hexToByte = {}; for (let i = 0; i < 256; i++) { _byteToHex[i] = (i + 0x100).toString(16).substr(1); _hexToByte[_byteToHex[i]] = i; } // **`parse()` - Parse a UUID into it's component bytes** -function _parse(s, buf?, offset?): Array { - let i = (buf && offset) || 0, ii = 0; +export function _parse(s, buf?, offset?): Array { + const i = (buf && offset) || 0; let ii = 0; buf = buf || []; - s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) { + s.toLowerCase().replace(/[0-9a-f]{2}/g, oct => { if (ii < 16) { // Don't overflow! buf[i + ii++] = _hexToByte[oct]; } @@ -112,11 +110,11 @@ function _parse(s, buf?, offset?): Array // **`unparse()` - Convert UUID byte array (ala parse()) into a string** function _unparse(buf, offset?): string { - let i = offset || 0, bth = _byteToHex; + let i = offset || 0; const bth = _byteToHex; return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + - bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] + "-" + + bth[buf[i++]] + bth[buf[i++]] + "-" + bth[buf[i++]] + + bth[buf[i++]] + "-" + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; } @@ -126,11 +124,11 @@ function _unparse(buf, offset?): string // and http://docs.python.org/library/uuid.html // random #'s we need to init node and clockseq -let _seedBytes = _rng(); +const _seedBytes = _rng(); // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = // 1) -let _nodeId = [ +const _nodeId = [ _seedBytes[0] | 0x01, _seedBytes[1], _seedBytes[2], @@ -143,12 +141,12 @@ let _nodeId = [ let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; // Previous uuid creation time -let _lastMSecs = 0, _lastNSecs = 0; +let _lastMSecs = 0; let _lastNSecs = 0; // See https://github.com/broofa/node-uuid for API details -function _v1(options?, buf?, offset?): string { +export function _v1(options?, buf?, offset?): string { let i = buf && offset || 0; - let b = buf || []; + const b = buf || []; options = options || {}; @@ -170,7 +168,7 @@ function _v1(options?, buf?, offset?): s let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) - let dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000; + const dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression if (dt < 0 && options.clockseq == null) { @@ -187,7 +185,7 @@ function _v1(options?, buf?, offset?): s // Per 4.2.1.2 Throw error if too many uuids are requested if (nsecs >= 10000) { throw new Error( - 'uuid.v1(): Can\'t create more than 10M uuids/sec'); + "uuid.v1(): Can't create more than 10M uuids/sec"); } _lastMSecs = msecs; @@ -198,14 +196,14 @@ function _v1(options?, buf?, offset?): s msecs += 12219292800000; // `time_low` - let tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; b[i++] = tl >>> 24 & 0xff; b[i++] = tl >>> 16 & 0xff; b[i++] = tl >>> 8 & 0xff; b[i++] = tl & 0xff; // `time_mid` - let tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + const tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; b[i++] = tmh >>> 8 & 0xff; b[i++] = tmh & 0xff; @@ -220,7 +218,7 @@ function _v1(options?, buf?, offset?): s b[i++] = clockseq & 0xff; // `node` - let node = options.node || _nodeId; + const node = options.node || _nodeId; for (let n = 0; n < 6; n++) { b[i + n] = node[n]; } @@ -231,17 +229,17 @@ function _v1(options?, buf?, offset?): s // **`v4()` - Generate random UUID** // See https://github.com/broofa/node-uuid for API details -function _v4(options?, buf?, offset?): string { +export function _v4(options?, buf?, offset?): string { // Deprecated - 'format' argument, as supported in v1.2 - let i = buf && offset || 0; + const i = buf && offset || 0; - if (typeof (options) === 'string') { - buf = (options === 'binary') ? new BufferClass(16) : null; + if (typeof (options) === "string") { + buf = (options === "binary") ? new BufferClass(16) : null; options = null; } options = options || {}; - let rnds = options.random || (options.rng || _rng)(); + const rnds = options.random || (options.rng || _rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` rnds[6] = (rnds[6] & 0x0f) | 0x40; @@ -266,5 +264,4 @@ export namespace Uuid { export const v1 = _v1; export const empty = "00000000-0000-0000-0000-000000000000"; export const parse = _parse; - export const unparse = _unparse; -} \ No newline at end of file +} diff --git a/src/ts/di/ActivationContext.ts b/src/ts/di/ActivationContext.ts --- a/src/ts/di/ActivationContext.ts +++ b/src/ts/di/ActivationContext.ts @@ -3,28 +3,26 @@ import { argumentNotNull, argumentNotEmp import { Descriptor, ServiceMap, isDescriptor } from "./interfaces"; import { Container } from "./Container"; -let trace = TraceSource.get("di"); +const trace = TraceSource.get("@implab/core/di/ActivationContext"); -export class ActivationContextInfo { - name: string +export interface ActivationContextInfo { + name: string; - service: string + service: Descriptor; - scope: ServiceMap + scope: ServiceMap; } +export class ActivationContext { + _cache: object; -export class ActivationContext { - _cache: object - - _services: ServiceMap + _services: ServiceMap; - _stack: ActivationContextInfo[] + _stack: ActivationContextInfo[]; - _visited: any + _visited: object; - container: any - + container: Container; constructor(container: Container, services: ServiceMap, cache?: object, visited?) { argumentNotNull(container, "container"); @@ -38,20 +36,20 @@ export class ActivationContext { } getService(name, def?): any { - let d = this._services[name]; + const d = this._services[name]; if (!d) if (arguments.length > 1) return def; else - throw new Error("Service '" + name + "' not found"); + throw new Error(`Service ${name} not found`); return d.activate(this, name); } /** * registers services local to the the activation context - * + * * @name{string} the name of the service * @service{string} the service descriptor to register */ @@ -68,47 +66,43 @@ export class ActivationContext { this._cache, this._visited ); - } - has(id) { + has(id: string) { return id in this._cache; } - get(id) { + get(id: string) { return this._cache[id]; } - store(id, value) { + store(id: string, value) { return (this._cache[id] = value); } - parse(data: any, name) { - var me = this; + parse(data: object, name: string) { if (isPrimitive(data)) return data; if (isDescriptor(data)) { return data.activate(this, name); } else if (data instanceof Array) { - me.enter(name); - var v = data.map(function (x, i) { - return me.parse(x, "." + i); - }); - me.leave(); + this.enter(name); + const v = data.map( (x, i) => this.parse(x, `[${i}]`)); + this.leave(); return v; } else { - me.enter(name); - var result = {}; - for (var p in data) - result[p] = me.parse(data[p], "." + p); - me.leave(); + this.enter(name); + const result = {}; + for (const p in data) + result[p] = this.parse(data[p], "." + p); + this.leave(); return result; } } - visit(id) { - var count = this._visited[id] || 0; + visit(id: string) { + const count = this._visited[id] || 0; this._visited[id] = count + 1; return count; } @@ -117,12 +111,12 @@ export class ActivationContext { return this._stack.slice().reverse(); } - enter(name, d?, localize?) { + enter(name: string, d?: Descriptor, localize?: boolean) { if (trace.isLogEnabled()) trace.log("enter " + name + " " + (d || "") + (localize ? " localize" : "")); this._stack.push({ - name: name, + name, service: d, scope: this._services }); @@ -131,10 +125,10 @@ export class ActivationContext { } leave() { - var ctx = this._stack.pop(); + const ctx = this._stack.pop(); this._services = ctx.scope; if (trace.isLogEnabled()) trace.log("leave " + ctx.name + " " + (ctx.service || "")); } -} \ No newline at end of file +} diff --git a/src/ts/di/ActivationError.ts b/src/ts/di/ActivationError.ts --- a/src/ts/di/ActivationError.ts +++ b/src/ts/di/ActivationError.ts @@ -1,13 +1,13 @@ import { ActivationContextInfo } from "./ActivationContext"; export class ActivationError { - activationStack: ActivationContextInfo[] + activationStack: ActivationContextInfo[]; - service: string + service: string; - innerException: any + innerException: any; - message: string + message: string; constructor(service: string, activationStack: ActivationContextInfo[], innerException) { this.message = "Failed to activate the service"; @@ -17,7 +17,7 @@ export class ActivationError { } toString() { - var parts = [this.message]; + const parts = [this.message]; if (this.service) parts.push("when activating: " + this.service.toString()); @@ -26,12 +26,11 @@ export class ActivationError { if (this.activationStack) { parts.push("at"); - this.activationStack.forEach(function (x) { - parts.push(" " + x.name + " " + - (x.service ? x.service.toString() : "")); - }); + this.activationStack + .forEach(x => parts.push(` ${x.name} ${x.service ? x.service.toString() : ""}`)); + } return parts.join("\n"); } -} \ No newline at end of file +} diff --git a/src/ts/di/AggregateDescriptor.ts b/src/ts/di/AggregateDescriptor.ts --- a/src/ts/di/AggregateDescriptor.ts +++ b/src/ts/di/AggregateDescriptor.ts @@ -1,11 +1,11 @@ import { Descriptor } from "./interfaces"; import { ActivationContext } from "./ActivationContext"; -export class AggregateDescriptor implements Descriptor { - _value: T; +export class AggregateDescriptor implements Descriptor { + _value: object; - constructor(value: T) { - + constructor(value: object) { + this._value = value; } activate(context: ActivationContext, name: string) { @@ -18,7 +18,7 @@ export class AggregateDescriptor impl isInstanceCreated(): boolean { return false; } - getInstance(): T { - throw new Error("Not supported exception"); + getInstance(): any { + throw new Error("Not supported"); } } diff --git a/src/ts/di/Container.ts b/src/ts/di/Container.ts --- a/src/ts/di/Container.ts +++ b/src/ts/di/Container.ts @@ -176,10 +176,6 @@ export class Container { owner: this }; - function guard(fn: () => PromiseLike) { - return fn(); - } - if (data.$type) { if (data.$type instanceof Function) opts.type = data.$type; @@ -202,7 +198,7 @@ export class Container { if (data.inject instanceof Array) opts.inject = await Promise.all(data.inject.map(x => this._parseObject(x, resolver))); else - opts.inject = this._parseObject(data.inject, resolver); + opts.inject = [await this._parseObject(data.inject, resolver)]; if (data.params) opts.params = this._parse(data.params, resolver); @@ -240,7 +236,7 @@ export class Container { return new ServiceDescriptor(opts); } - _parseObject(data: any, typemap) { + _parseObject(data: object, resolver: ModuleResolverBase) { if (data.constructor && data.constructor.prototype !== Object.prototype) return new ValueDescriptor(data); @@ -248,16 +244,16 @@ export class Container { const o = {}; for (const p in data) - o[p] = this._parse(data[p], typemap); + o[p] = this._parse(data[p], resolver); return o; } - _parseArray(data, typemap) { + _parseArray(data: Array, resolver: ModuleResolverBase) { if (data.constructor && data.constructor.prototype !== Array.prototype) return new ValueDescriptor(data); - return data.map(x => this._parse(x, typemap)); + return data.map(x => this._parse(x, resolver)); } } diff --git a/src/ts/di/ReferenceDescriptor.ts b/src/ts/di/ReferenceDescriptor.ts --- a/src/ts/di/ReferenceDescriptor.ts +++ b/src/ts/di/ReferenceDescriptor.ts @@ -4,15 +4,15 @@ import { ServiceMap, Descriptor } from " import { ActivationError } from "./ActivationError"; export class ReferenceDescriptor implements Descriptor { - _name: string + _name: string; - _lazy = false + _lazy = false; - _optional = false + _optional = false; - _default: any + _default: any; - _services: ServiceMap + _services: ServiceMap; constructor(name: string, lazy: boolean, optional: boolean, def, services: ServiceMap) { argumentNotEmptyString(name, "name"); @@ -24,44 +24,50 @@ export class ReferenceDescriptor impleme } activate(context: ActivationContext, name: string) { - var me = this; - context.enter(name, this, true); - - // добавляем сервисы - if (me._services) { - for (var p in me._services) { - var sv = me._services[p]; - context.register(p, sv); - } - } - - if (me._lazy) { + if (this._lazy) { // сохраняем контекст активации context = context.clone(); - return function (cfg: ServiceMap) { + + // добавляем сервисы + if (this._services) { + for (const p of Object.keys(this._services)) + context.register(p, this._services[p]); + } + + return (cfg: ServiceMap) => { // защищаем контекст на случай исключения в процессе // активации - var ct = context.clone(); + const ct = context.clone(); try { - if (cfg) - for(let k in cfg) - ct.register(k, cfg[v]); + if (cfg) { + for (const k in cfg) + ct.register(k, cfg[k]); + } - return me._optional ? ct.getService(me._name, me._default) : ct - .getService(me._name); + return this._optional ? ct.getService(this._name, this._default) : ct + .getService(this._name); } catch (error) { - throw new ActivationError(me._name, ct.getStack(), error); + throw new ActivationError(this._name, ct.getStack(), error); } }; - } + } else { + context.enter(name, this, !!this._services); + + // добавляем сервисы + if (this._services) { + for (const p of Object.keys(this._services)) + context.register(p, this._services[p]); + } - var v = me._optional ? - context.getService(me._name, me._default) : - context.getService(me._name); + const v = this._optional ? + context.getService(this._name, this._default) : + context.getService(this._name); - context.leave(); - return v; + context.leave(); + + return v; + } } isInstanceCreated() { @@ -73,13 +79,13 @@ export class ReferenceDescriptor impleme } toString() { - var opts = []; + const opts = []; if (this._optional) opts.push("optional"); if (this._lazy) opts.push("lazy"); - var parts = [ + const parts = [ "@ref " ]; if (opts.length) { @@ -97,4 +103,4 @@ export class ReferenceDescriptor impleme return parts.join(""); } -} \ No newline at end of file +} diff --git a/src/ts/di/ServiceDescriptor.ts b/src/ts/di/ServiceDescriptor.ts --- a/src/ts/di/ServiceDescriptor.ts +++ b/src/ts/di/ServiceDescriptor.ts @@ -1,8 +1,8 @@ import { ActivationContext } from "./ActivationContext"; -import { Descriptor, ActivationType, ServiceMap, Constructor, Factory } from "./interfaces"; +import { Descriptor, ActivationType, ServiceMap } from "./interfaces"; import { Container } from "./Container"; -import { argumentNotNull, isPrimitive, oid } from "../safe"; -import { ClientResponse } from "http"; +import { argumentNotNull, isPrimitive, oid, isPromise } from "../safe"; +import { Constructor, Factory } from "../interfaces"; let cacheId = 0; @@ -12,12 +12,12 @@ function injectMethod(target, method, co throw new Error("Method '" + method + "' not found"); if (args instanceof Array) - m.apply(target, context.parse(args, "." + method)); + return m.apply(target, context.parse(args, "." + method)); else - m.call(target, context.parse(args, "." + method)); + return m.call(target, context.parse(args, "." + method)); } -function makeClenupCallback(target, method: (instance) => void | string) { +function makeClenupCallback(target, method: ((instance) => void) | string) { if (typeof (method) === "string") { return () => { target[method](); @@ -29,26 +29,26 @@ function makeClenupCallback(target, meth } } -export interface ServiceDescriptorParams { +export interface ServiceDescriptorParams { activation?: ActivationType; owner: Container; - type?: Constructor; + type?: Constructor; - factory?: Factory; + factory?: Factory; params?; - inject?; + inject?: object[]; services?: ServiceMap; - cleanup?: (instance: T) => void | string; + cleanup?: ((x) => void) | string; } -export class ServiceDescriptor implements Descriptor { - _instance: T = null; +export class ServiceDescriptor implements Descriptor { + _instance; _hasInstance = false; @@ -56,21 +56,21 @@ export class ServiceDescriptor i _services: ServiceMap; - _type: Constructor = null; + _type: Constructor = null; - _factory: Factory = null; + _factory: Factory = null; _params; - _inject: Array; + _inject: object[]; - _cleanup: (instance: T) => void; + _cleanup: ((x) => void) | string; _cacheId: any; _owner: Container; - constructor(opts: ServiceDescriptorParams) { + constructor(opts: ServiceDescriptorParams) { argumentNotNull(opts, "opts"); argumentNotNull(opts.owner, "owner"); @@ -90,7 +90,7 @@ export class ServiceDescriptor i this._params = opts.params; if (opts.inject) - this._inject = opts.inject instanceof Array ? opts.inject : [opts.inject]; + this._inject = opts.inject; if (opts.services) this._services = opts.services; @@ -219,9 +219,17 @@ export class ServiceDescriptor i if (!this._factory) { const ctor = this._type; - this._factory = (...args) => { - return new ctor(...args); - }; + if (this._params && this._params.length) { + this._factory = (...args) => { + const t = Object.create(ctor.prototype); + const inst = ctor.apply(t, args); + return isPrimitive(inst) ? t : inst; + }; + } else { + this._factory = () => { + return new ctor(); + }; + } } if (this._params === undefined) { diff --git a/src/ts/di/ValueDescriptor.ts b/src/ts/di/ValueDescriptor.ts --- a/src/ts/di/ValueDescriptor.ts +++ b/src/ts/di/ValueDescriptor.ts @@ -1,23 +1,23 @@ import { Descriptor } from "./interfaces"; import { ActivationContext } from "./ActivationContext"; -export class ValueDescriptor implements Descriptor { - _value: T +export class ValueDescriptor implements Descriptor { + _value; - constructor(value: T) { + constructor(value) { this._value = value; } activate(context: ActivationContext, name: string) { context.enter(name); - let v = this._value; + const v = this._value; context.leave(); - return v; + return v; } isInstanceCreated(): boolean { return true; } - getInstance(): T { + getInstance() { return this._value; } -} \ No newline at end of file +} diff --git a/src/ts/di/interfaces.ts b/src/ts/di/interfaces.ts --- a/src/ts/di/interfaces.ts +++ b/src/ts/di/interfaces.ts @@ -1,5 +1,6 @@ import { isNull } from "../safe"; import { ActivationContext } from "./ActivationContext"; +import { Constructor, Factory } from "../interfaces"; export interface Descriptor { activate(context: ActivationContext, name?: string); @@ -7,10 +8,6 @@ export interface Descriptor { getInstance(); } -export type Constructor = new (...args: any[]) => T; - -export type Factory = (...args: any[]) => T; - export function isDescriptor(instance): instance is Descriptor { return (!isNull(instance)) && ("activate" in instance); diff --git a/src/ts/interfaces.ts b/src/ts/interfaces.ts --- a/src/ts/interfaces.ts +++ b/src/ts/interfaces.ts @@ -1,3 +1,7 @@ +export type Constructor = new (...args: any[]) => T; + +export type Factory = (...args: any[]) => T; + export interface IDestroyable { destroy(); } @@ -22,18 +26,18 @@ export interface IActivatable { * Starts the component activation * @param ct cancellation token for this operation */ - activate(ct?: ICancellation) : Promise; + activate(ct?: ICancellation): Promise; /** * Starts the component deactivation * @param ct cancellation token for this operation */ - deactivate(ct?: ICancellation) : Promise; + deactivate(ct?: ICancellation): Promise; /** * Sets the activation controller for this component * @param controller The activation controller - * + * * Activation controller checks whether this component * can be activated and manages the active state of the * component @@ -71,6 +75,6 @@ export interface ICancellable { } export interface IObservable { - on(next: (x:T) => void, error?: (e:any) => void, complete?:() => void): IDestroyable; - next(ct?: ICancellation) : Promise; -} \ No newline at end of file + on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable; + next(ct?: ICancellation): Promise; +} diff --git a/src/ts/safe.ts b/src/ts/safe.ts --- a/src/ts/safe.ts +++ b/src/ts/safe.ts @@ -1,7 +1,7 @@ let _nextOid = 0; const _oid = Symbol("__oid"); -export function oid(instance: object) { +export function oid(instance: object): string { if (isNull(instance)) return null; @@ -52,6 +52,10 @@ export function isString(val) { return typeof (val) === "string" || val instanceof String; } +export function isPromise(val): val is PromiseLike { + return "then" in val && val.then instanceof Function; +} + export function isNullOrEmptyString(str) { if (str === null || str === undefined || ((typeof (str) === "string" || str instanceof String) && str.length === 0)) @@ -130,7 +134,7 @@ export function mixin(dest: T, sou const _res = dest as T & S; if (template instanceof Array) { - for (const p of template) { + for (const p of template) { if (p in source) _res[p] = source[p]; } @@ -229,18 +233,17 @@ export function pmap(items, cb) { argumentNotNull(cb, "cb"); if (items && items.then instanceof Function) - return items.then(function (data) { - return pmap(data, cb); - }); + return items.then(data => pmap(data, cb)); if (isNull(items) || !items.length) return items; - var i = 0, - result = []; + let i = 0; + const result = []; function next() { - var r, ri; + let r; + let ri; function chain(x) { result[ri] = x; @@ -251,7 +254,7 @@ export function pmap(items, cb) { r = cb(items[i], i); ri = i; i++; - if (r && r.then) { + if (isPromise(r)) { return r.then(chain); } else { result[ri] = r; @@ -266,22 +269,20 @@ export function pmap(items, cb) { /** * Выбирает первый элемент из последовательности, или обещания, если в * качестве параметра используется обещание, оно должно вернуть массив. - * + * * @param {Function} cb обработчик результата, ему будет передан первый * элемент последовательности в случае успеха * @param {Function} err обработчик исключения, если массив пустой, либо * не массив - * + * * @remarks Если не указаны ни cb ни err, тогда функция вернет либо * обещание, либо первый элемент. * @async */ -export function first(sequence: any, cb: Function, err: Function) { +export function first(sequence, cb: (x) => any, err: (x) => any) { if (sequence) { - if (sequence.then instanceof Function) { - return sequence.then(function (res) { - return first(res, cb, err); - }, err); + if (isPromise(sequence)) { + return sequence.then(res => first(res, cb, err)); } else if (sequence && "length" in sequence) { if (sequence.length === 0) { if (err) @@ -299,7 +300,7 @@ export function first(sequence: any, cb: throw new Error("The sequence is required"); } -export function destroy(d: any) { - if (d && 'destroy' in d) +export function destroy(d) { + if (d && "destroy" in d) d.destroy(); -} \ No newline at end of file +} diff --git a/test/js/plan.js b/test/js/plan.js --- a/test/js/plan.js +++ b/test/js/plan.js @@ -1,3 +1,3 @@ -//define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]); +define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]); //define(["./CancellationTests"]); -define(["./ObservableTests"]); \ No newline at end of file +//define(["./ObservableTests"]); \ No newline at end of file diff --git a/test/ts/dummy.ts b/test/ts/dummy.ts --- a/test/ts/dummy.ts +++ b/test/ts/dummy.ts @@ -1,13 +1,13 @@ -import * as tape from 'tape'; -import * as uuid from '@implab/core/Uuid'; +import * as tape from "tape"; +import { Uuid } from "@implab/core/Uuid"; -tape('simple', function(t){ +tape("simple", t => { t.pass("sync assert"); setTimeout(() => { t.pass("async assert"); - t.comment(uuid()); - t.ok(uuid() != uuid()); + t.comment(Uuid()); + t.ok(Uuid() !== Uuid()); // end should be called after the last assertion t.end(); }, 100); -}); \ No newline at end of file +}); diff --git a/tsconfig.json b/tsconfig.json --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es3", "module": "amd", "sourceMap": true, "outDir" : "build/dist", diff --git a/tsconfig.test.json b/tsconfig.test.json --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -1,12 +1,12 @@ { "compilerOptions": { - "target": "es5", + "target": "es3", "module": "amd", "sourceMap": true, "outDir" : "build/test", "moduleResolution": "node", "lib": [ - "ES2015" + "es2015" ] }, "include" : [