##// END OF EJS Templates
Merged in propose cancellations (pull request #1)...
m407 -
r21:dd8f8dfcd934 merge default
parent child
Show More
@@ -0,0 +1,1
1 *.tgz No newline at end of file
@@ -0,0 +1,25
1 @startuml
2
3 participant Component as a
4 participant Other as b
5
6 [-> a : activate(ct)
7 activate a
8 <-- a : promise
9 a -> a : onActivating(ct)
10 activate a
11 a -> b : doAsyncWork(ct)
12 deactivate a
13 deactivate a
14 activate b
15
16 [-> b : ct.cancel
17 b --> a : reject(Cancelled)
18 deactivate b
19 activate a
20
21 a -> a : setFailState()
22
23 [<-- a : reject(Cancelled)
24
25 @enduml No newline at end of file
@@ -0,0 +1,257
1 # Cancellations. Отмена асинхронных операций
2
3 Использование Promise позволяет организовать обработку результатов работы
4 асинхронных фукнций. Ключевые слова async/await позволяют работать с
5 асинхронными вызовами в стиле процедурного программирования, хотя по сути это
6 событиный подход. При всей своей красоте даннго подхода в нем умышленно
7 отсутсвует механизм отмены асинхронной операции, т.е. ее можно начать, но нельзя
8 отказаться от результатов ее выполнения, даже если это уже не требуется.
9
10 Примером того, когда может потребоваться отмена является загрузка большого
11 файла, при которой пользователю отображается окно хода операции с возможностью
12 ее отмены.
13
14 ```ts
15 // имеется некоторый HTTP клиент
16 let client = new HttpClient();
17
18 // загружается большой файл, с использованием медленного канала
19 let data = await client.getJsonAsync('http://host/large-file.json');
20
21 ```
22
23 Как поступить в данной ситуации, прежде всего нужно, чтобы сама операция
24 поддерживала возможность отмены, предположим, что для этого есть метод
25 `client.abort()`.
26
27 ```ts
28
29 // имеется некоторый HTTP клиент
30 let client = new HttpClient();
31
32 // отображаем окно с информацией о ходе операции
33 let progressView = showProgress("Downloading, please wait...");
34
35 // код оборачивается в try/finally поскольку созданную форму нужно закрыть
36 try {
37 // загружается большой файл, с использованием медленного канала
38 // здесь, в отличии от предыдущего примера, мы не дожидаемся результата,
39 // а запоминаем обещание в переменную downloadTask
40 let downloadTask = client.getJsonAsync('http://host/large-file.json');
41
42 // связываем событие нажатия кнопки с отменой загрузки
43 progressView.once('cancel', () => client.abort());
44
45 // ожидаем окончания загрузки данных
46
47 let data = await downloadTask;
48 } finally {
49 // независимот от результата закрываем форму
50 // при этом также происходит ануллирование подписок на события
51 progressView.close();
52 }
53
54 ```
55
56 Технические приведенное решение выглядит не плохо, но проблемы появляются, когда
57 требуется организовать отмену нескольких операций, особенно если они вложенные.
58
59 ```ts
60 // обновление информации о человеке на форме
61 async function updatePersonInfo(info) {
62 let client = new RestApiClient();
63
64 // выплнение нескольких асинхронных операций
65 let org = await client.getOrgAsync(info.orgId);
66 let city = await client.getCityAsync(info.cityId);
67
68 // обновление содержимого представления
69 renderContent({
70 person: info,
71 org: org,
72 city: city
73 });
74 }
75
76 ```
77
78 Чтобы реализовать возможность отмены такой операции требуется, чтобы в логике
79 самой операции была реализована поддержка отмены. Для реализации этого
80 потребуется чтобы у операции была информация о запросе отмены, причем данная
81 информация относится именно к текущей операции.
82
83 Информацию о состоянии запроса на отмену назовём **маркер отмены (cancellation
84 token)**. Поскольку маркер отмены тесно связан с операцией, его удобно
85 передавать в виде параметра, тогда код операции будет выглядеть так:
86
87 ```ts
88 // обновление информации о человеке на форме
89 // ct - маркер отмены
90 async function updatePersonInfo(info, ct) {
91 let client = new RestApiClient();
92
93 // выплнение нескольких асинхронных операций
94 // маркер отмены просто передается далее по цепочке вызовов, без
95 // дополнительных действий
96 let org = await client.getOrg(info.orgId, ct);
97 let city = await client.getCity(info.cityId, ct);
98
99 // обновление содержимого представления
100 renderContent({
101 person: info,
102 org: org,
103 city: city
104 });
105 }
106
107 ///////////////////////////////////////////////////////////////////////////////
108 // ... где-то в другом месте
109 ///////////////////////////////////////////////////////////////////////////////
110
111 // отображаем окно с информацией о хоже операции
112 let progressView = showProgress("Loading, please wait...");
113
114 // создаем маркер отмены для операции на основе события 'cancel'.
115 let ct = new Cancellation(cancel => progressView.on('cancel', cancel));
116
117 // код оборачивается в try/finally поскольку созданную форму нужно закрыть
118 try {
119 // асинхронно получаем информацию о человеке
120 let data = await getPersonInfo(personId, ct);
121
122 // асинхронно обновляем представление
123 await updatePersonInfo(data, ct);
124 } finally {
125 // независимот от результата закрываем форму
126 // при этом также происходит ануллирование подписок на события
127 progressView.close();
128 }
129
130 ```
131
132 Таким образом тот, кто начинает асинхронную операцию заранее определяет как эта
133 опреция будет отменена.
134
135 Важно понимать, что для реализации отмены операции
136 могут выделаться ресурсы требующие явного освобождения (DOM, таймеры, события),
137 об их освобождении по окончанию операции (успешном или нет) должен позаботиться
138 инициатор этой операции. `Cancellation` выступает только в роли посредника для
139 доставки события отмены операции до конечного получателя, он не отслеживает и
140 не освобождает ресурсы, кроме того, асинхронная операция может его попросту
141 проигнорировать.
142
143 ## `ICancellation` Маркер отмены операции
144
145 Интерфейс маркера отмены операции. Используется асинхронными операциями, чтобы
146 получить оповещение о требуемой отмене.
147
148 ### `isSupported(): boolean`
149
150 Определяет, может ли быть запрошена отмена операции через данный маркер.
151
152 ### `isRequested(): boolean`
153
154 Возвращает текущее состояние запроса на отмену.
155
156 ### `throwIfRequested(): void`
157
158 Если отмена была запрошена, бросает в качестве исключения причину отмены.
159
160 ### `register(cb: (e:any) => void): IDestroyable`
161
162 Метод, зарегистрировать обработчик на запрос отмены. Если отмена была запрошена
163 зарегистрированный обработчик будет вызван ровно один раз, независимо от того,
164 был ли он зарегистрирован до или после запроса отмены.
165
166 Если отмена уже была запрошена, обработчик будет вызван сразу при регистрации,
167 при этом исключения, которые могу возникнуть в обработчике не будут обработаны,
168 а передадуться наверх.
169
170 Вызов данного метода приводит к выделению ресурсов, поэтому операция,
171 зарегистрировавшая обработчик должна освободить подписку, которую вернет метод.
172
173 ```ts
174 async function getAsync(url: string, ct: ICancellation = Cancellation.none) {
175 // переменная в которой будет запомнена подписка на запрос отмены
176 let reg;
177 try {
178 // оборачиваем операцию загрузки в Promise
179 return await new Promise<string>((resolve, reject) => {
180 // объект Xhr
181 const xhr = new XMLHttpRequest();
182 xhr.open("GET", url);
183
184 // регистрируем обработчики Promise
185 xhr.onload = () => resolve(xhr.responseText);
186 xhr.onerror = () => reject(xhr.statusText);
187
188 // отправляем запрос
189 xhr.send();
190
191 // подписываемся на запрос отмены
192 reg = ct.register((e) => {
193 reject(e);
194 xhr.abort();
195 });
196 });
197 } finally {
198 if (reg)
199 reg.destroy();
200 }
201 }
202
203 ```
204
205 Использование метода `register()` предполагается для организации отмены операций
206 не поддерживающих маркеры отмены.
207
208 ## `Cancellation` Источник отмены
209
210 Класс используется для создания маркеров отмены. Позволяет создать маркер при
211 начале асинхронной операции и связать его, например, с событием DOM.
212
213 Также маркер можно создавать, когда требуется сложное условие отмены текущей и
214 всех нижележещих операций.
215
216 Как правило в большинстве операций достаточно маркера переданного в параметрах,
217 этот же маркер может передаваться ниже.
218
219 ### `constructor(exec: (cancel: (reason:any) => void ) => void )`
220
221 Создает новый маркер, при помощи параметра и инициализирует его при помощи
222 фукнции, переданной в параметре `exec`.
223
224 ```ts
225
226 let htimer;
227 let ct = new Cancellation(cancel => {
228 htimer = setTimeout(() => cancel("The request is timed out."), 1000);
229 });
230
231 try {
232 let text = await getAsync(url, ct);
233 } finally {
234 // инициатор должен освобождать ресурсы
235 // передача недействительного htimer не приводит ни к каким последствиям
236 clearTimeout(htimer);
237 }
238
239 ```
240
241 ## `Cancellation.none: ICancellation`
242
243 Статическое свойство только для чтения, в котором находится специальный токен
244 запроса отмены. Этот токен означает, что отмена никогда не может произойти.
245
246 Данный токен рекомендуется использовать как значение по-умолчанию для
247 параметров, принимающих токен отмены.
248
249 ```ts
250
251 async function load(url: string, ct: ICancellation = Cancellation.none) {
252 ct.throwIfRequested();
253
254 // ... the rest of method
255 }
256
257 ``` No newline at end of file
@@ -0,0 +1,89
1 import { ICancellation, IDestroyable } from "./interfaces";
2 import { argumentNotNull } from "./safe";
3
4 const destroyed = {
5 destroy() {
6 }
7 };
8
9 export class Cancellation implements ICancellation {
10 private _reason: any;
11 private _cbs: Array<(e) => void>;
12
13 constructor(action: (cancel: (e) => void) => void) {
14 argumentNotNull(action, "action");
15
16 action(this._cancel.bind(this));
17 }
18
19 isSupported(): boolean {
20 return true;
21 }
22 throwIfRequested(): void {
23 if (this._reason)
24 throw this._reason;
25 }
26
27 isRequested(): boolean {
28 return !!this._reason;
29 }
30
31 register(cb: (e: any) => void): IDestroyable {
32 argumentNotNull(cb, "cb");
33
34 if (this._reason) {
35 cb(this._reason);
36 return destroyed;
37 } else {
38 if (!this._cbs)
39 this._cbs = [cb];
40 else
41 this._cbs.push(cb);
42
43 let me = this;
44 return {
45 destroy() {
46 me._unregister(cb);
47 }
48 };
49 }
50 }
51
52 private _unregister(cb) {
53 if(this._cbs) {
54 let i = this._cbs.indexOf(cb);
55 if ( i>=0 )
56 this._cbs.splice(i,1);
57 }
58 }
59
60 private _cancel(reason) {
61 if (this._reason)
62 return;
63
64 this._reason = (reason = reason || new Error("Operation cancelled"));
65
66
67 if (this._cbs) {
68 this._cbs.forEach(cb => cb(reason));
69 this._cbs = null;
70 }
71 }
72
73 static readonly none: ICancellation = {
74 isSupported(): boolean {
75 return false;
76 },
77
78 throwIfRequested(): void {
79 },
80
81 isRequested(): boolean {
82 return false;
83 },
84
85 register(_cb: (e: any) => void): IDestroyable {
86 return destroyed;
87 }
88 };
89 } No newline at end of file
@@ -0,0 +1,87
1 import { IActivationController, IActivatable, ICancellation } from '../interfaces';
2 import { AsyncComponent } from './AsyncComponent';
3 import { Cancellation } from '../Cancellation';
4 import * as TraceSource from '../log/TraceSource';
5
6 type Constructor<T = {}> = new (...args: any[]) => T;
7
8 const log = TraceSource.get('@implab/core/components/ActivatableMixin');
9
10 function ActivatableMixin<TBase extends Constructor<AsyncComponent>>(Base: TBase) {
11 return class extends Base implements IActivatable {
12 _controller: IActivationController;
13
14 _active: boolean;
15
16 isActive() {
17 return this._active;
18 }
19
20 getActivationController() {
21 return this._controller;
22 }
23
24 setActivationController(controller: IActivationController) {
25 this._controller = controller;
26 }
27
28 async onActivating(ct: ICancellation) {
29 if (this._controller)
30 await this._controller.activating(this, ct);
31 }
32
33 async onActivated(ct: ICancellation) {
34 if (this._controller)
35 await this._controller.activated(this, ct);
36 }
37
38 activate(ct: ICancellation = Cancellation.none) {
39 return this.runOperation(this._activateAsync.bind(this), ct);
40 }
41
42 async _activateAsync(ct: ICancellation) {
43 if (this.isActive())
44 return;
45
46 await this.onActivating(ct);
47 this._active = true;
48 try {
49 await this.onActivated(ct);
50 } catch (e) {
51 log.error("Suppressed onActivated error: {0}", e);
52 }
53 }
54
55 async onDeactivating(ct: ICancellation) {
56 if (this._controller)
57 await this._controller.deactivating(this, ct);
58 }
59
60 async onDeactivated(ct: ICancellation) {
61 if (this._controller)
62 await this._controller.deactivated(this, ct);
63 }
64
65 deactivate(ct: ICancellation = Cancellation.none) {
66 return this.runOperation(this._deactivateAsync.bind(this), ct);
67 }
68
69 async _deactivateAsync(ct: ICancellation) {
70 if (!this.isActive())
71 return;
72 await this.onDeactivating(ct);
73 this._active = false;
74 try {
75 await this.onDeactivated(ct);
76 } catch (e) {
77 log.error("Suppressed onDeactivated error: {0}", e);
78 }
79 }
80 }
81 }
82
83 namespace ActivatableMixin {
84 export const traceSource = log;
85 }
86
87 export = ActivatableMixin; No newline at end of file
@@ -0,0 +1,17
1 import { Cancellation } from "../Cancellation";
2 import { IAsyncComponent, ICancellation } from "../interfaces";
3
4 export class AsyncComponent implements IAsyncComponent {
5 _completion: Promise<void> = Promise.resolve();
6
7 getCompletion() { return this._completion };
8
9 runOperation(op: (ct: ICancellation) => any, ct: ICancellation = Cancellation.none) {
10 // TODO create cancellation source here
11 async function guard() {
12 await op(ct);
13 }
14
15 return this._completion = guard();
16 }
17 } No newline at end of file
@@ -0,0 +1,198
1 import { IObservable, IDestroyable, ICancellation } from '../interfaces';
2 import { Cancellation } from '../Cancellation'
3 import { argumentNotNull } from '../safe';
4
5
6 interface Handler<T> {
7 (x: T): void
8 }
9
10 interface Initializer<T> {
11 (notify: Handler<T>, error?: (e: any) => void, complete?: () => void): void;
12 }
13
14 // TODO: think about to move this interfaces.ts and make it public
15 interface IObserver<T> {
16 next(event: T): void
17
18 error(e: any): void
19
20 complete(): void
21 }
22
23 const noop = () => {};
24
25 class Observable<T> implements IObservable<T> {
26 private _once = new Array<IObserver<T>>();
27
28 private _observers = new Array<IObserver<T>>();
29
30
31 private _complete: boolean
32
33 private _error: any
34
35 constructor(func?: Initializer<T>) {
36 if (func)
37 func(
38 this._notifyNext.bind(this),
39 this._notifyError.bind(this),
40 this._notifyCompleted.bind(this)
41 );
42 }
43
44 /**
45 * Registers handlers for the current observable object.
46 *
47 * @param next the handler for events
48 * @param error the handler for a error
49 * @param complete the handler for a completion
50 * @returns {IDestroyable} the handler for the current subscription, this
51 * handler can be used to unsubscribe from events.
52 *
53 */
54 on(next: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
55 argumentNotNull(next, "next");
56
57 let me = this;
58
59 let observer: IObserver<T> & IDestroyable = {
60 next: next,
61 error: error ? error.bind(null) : noop,
62 complete: complete ? complete.bind(null) : noop,
63
64 destroy() {
65 me._removeObserver(this);
66 }
67 }
68
69 this._addObserver(observer);
70
71
72 return observer;
73 }
74
75 private _addObserver(observer: IObserver<T>) {
76 if (this._complete) {
77 try {
78 if (this._error)
79 observer.error(this._error);
80 else
81 observer.complete();
82 } catch (e) {
83 this.onObserverException(e);
84 }
85 } else {
86 this._observers.push(observer);
87 }
88 }
89
90 /**
91 * Waits for the next event. This method can't be used to read messages
92 * as a sequence since it can skip some messages between calls.
93 *
94 * @param ct a cancellation token
95 */
96 next(ct: ICancellation = Cancellation.none): Promise<T> {
97 return new Promise<T>((resolve, reject) => {
98 let observer: IObserver<T> = {
99 next: resolve,
100 error: reject,
101 complete: () => reject("No more events are available")
102 };
103
104 if (this._addOnce(observer) && ct.isSupported()) {
105 ct.register((e) => {
106 this._removeOnce(observer);
107 reject(e);
108 });
109 }
110 });
111 }
112
113 private _addOnce(observer: IObserver<T>) {
114 if (this._complete) {
115 try {
116 if (this._error)
117 observer.error(this._error);
118 else
119 observer.complete();
120 } catch (e) {
121 this.onObserverException(e);
122 }
123 return false;
124 }
125
126 this._once.push(observer);
127 return true;
128 }
129
130 protected onObserverException(e: any) {
131 }
132
133 private _removeOnce(d: IObserver<T>) {
134 let i = this._once.indexOf(d);
135 if (i >= 0)
136 this._once.splice(i, 1);
137 }
138
139 private _removeObserver(d: IObserver<T>) {
140 let i = this._observers.indexOf(d);
141 if (i >= 0)
142 this._observers.splice(i, 1);
143 }
144
145 private _notify(guard: (observer: IObserver<T>) => void) {
146 if (this._once.length) {
147 for (let i = 0; i < this._once.length; i++)
148 guard(this._once[i]);
149 this._once = [];
150 }
151
152 for (let i = 0; i < this._observers.length; i++)
153 guard(this._observers[i]);
154 }
155
156 protected _notifyNext(evt: T) {
157 let guard = (observer: IObserver<T>) => {
158 try {
159 observer.next(evt);
160 } catch (e) {
161 this.onObserverException(e);
162 }
163 }
164
165 this._notify(guard);
166 }
167
168 protected _notifyError(e: any) {
169 let guard = (observer: IObserver<T>) => {
170 try {
171 observer.error(e);
172 } catch (e) {
173 this.onObserverException(e);
174 }
175 }
176
177 this._notify(guard);
178 this._observers = [];
179 }
180
181 protected _notifyCompleted() {
182 let guard = (observer: IObserver<T>) => {
183 try {
184 observer.complete();
185 } catch (e) {
186 this.onObserverException(e);
187 }
188 }
189
190 this._notify(guard);
191 this._observers = [];
192 }
193 }
194
195 namespace Observable {
196 }
197
198 export = Observable; No newline at end of file
@@ -0,0 +1,76
1 export interface IDestroyable {
2 destroy();
3 }
4
5 export interface ICancellation {
6 throwIfRequested(): void;
7 isRequested(): boolean;
8 isSupported(): boolean;
9 register(cb: (e: any) => void): IDestroyable;
10 }
11
12 /**
13 * Интерфейс поддерживающий асинхронную активацию
14 */
15 export interface IActivatable {
16 /**
17 * @returns Boolean indicates the current state
18 */
19 isActive(): boolean;
20
21 /**
22 * Starts the component activation
23 * @param ct cancellation token for this operation
24 */
25 activate(ct?: ICancellation) : Promise<void>;
26
27 /**
28 * Starts the component deactivation
29 * @param ct cancellation token for this operation
30 */
31 deactivate(ct?: ICancellation) : Promise<void>;
32
33 /**
34 * Sets the activation controller for this component
35 * @param controller The activation controller
36 *
37 * Activation controller checks whether this component
38 * can be activated and manages the active state of the
39 * component
40 */
41 setActivationController(controller: IActivationController);
42
43 /**
44 * Gets the current activation controller for this component
45 */
46 getActivationController(): IActivationController;
47 }
48
49 export interface IActivationController {
50 activating(component: IActivatable, ct?: ICancellation): Promise<void>;
51
52 activated(component: IActivatable, ct?: ICancellation): Promise<void>;
53
54 deactivating(component: IActivatable, ct?: ICancellation): Promise<void>;
55
56 deactivated(component: IActivatable, ct?: ICancellation): Promise<void>;
57
58 deactivate(ct?: ICancellation): Promise<void>;
59
60 activate(component: IActivatable, ct?: ICancellation): Promise<void>;
61
62 getActive(): IActivatable;
63 }
64
65 export interface IAsyncComponent {
66 getCompletion(): Promise<void>;
67 }
68
69 export interface ICancellable {
70 cancel(reason?: any): void;
71 }
72
73 export interface IObservable<T> {
74 on(next: (x:T) => void, error?: (e:any) => void, complete?:() => void): IDestroyable;
75 next(ct?: ICancellation) : Promise<T>;
76 } No newline at end of file
@@ -0,0 +1,21
1 import * as TraceSource from './TraceSource'
2
3 class TraceEvent {
4 readonly source: TraceSource;
5
6 readonly level: Number;
7
8 readonly arg: any;
9
10 constructor(source: TraceSource, level: Number, arg: any) {
11 this.source = source;
12 this.level = level;
13 this.arg = arg;
14 }
15 }
16
17 namespace TraceEvent {
18
19 }
20
21 export = TraceEvent No newline at end of file
@@ -0,0 +1,171
1 import * as format from '../text/format'
2 import { argumentNotNull } from '../safe';
3 import * as Observable from '../components/Observable'
4 import { IDestroyable } from '../interfaces';
5 import * as TraceEvent from './TraceEvent'
6
7 class Registry {
8 static readonly instance = new Registry();
9
10 private _registry: object = new Object();
11 private _listeners: object = new Object();
12 private _nextCookie: number = 1;
13
14 get(id: any): TraceSource {
15 argumentNotNull(id, "id");
16
17 if (this._registry[id])
18 return this._registry[id];
19
20 var source = new TraceSource(id);
21 this._registry[id] = source;
22 this._onNewSource(source);
23
24 return source;
25 }
26
27 add(id: any, source: TraceSource) {
28 argumentNotNull(id, "id");
29 argumentNotNull(source, "source");
30
31 this._registry[id] = source;
32 this._onNewSource(source);
33 }
34
35 _onNewSource(source: TraceSource) {
36 for (let i in this._listeners)
37 this._listeners[i].call(null, source);
38 }
39
40 on(handler: (source: TraceSource) => void): IDestroyable {
41 argumentNotNull(handler, "handler");
42 var me = this;
43
44 var cookie = this._nextCookie++;
45
46 this._listeners[cookie] = handler;
47
48 for (let i in this._registry)
49 handler(this._registry[i]);
50
51 return {
52 destroy() {
53 delete me._listeners[cookie];
54 }
55 };
56 }
57 }
58
59 class TraceSource extends Observable<TraceEvent> {
60 readonly id: any
61
62 level: number
63
64 constructor(id: any) {
65 super();
66 this.id = id || new Object();
67 }
68
69 protected emit(level: number, arg: any) {
70 this._notifyNext(new TraceEvent(this, level, arg));
71 }
72
73 isDebugEnabled() {
74 return this.level >= TraceSource.DebugLevel;
75 }
76
77 debug(msg: string, ...args: any[]) {
78 if (this.isEnabled(TraceSource.DebugLevel))
79 this.emit(TraceSource.DebugLevel, format(msg, args));
80 }
81
82 isLogEnabled() {
83 return this.level >= TraceSource.LogLevel;
84 }
85
86 log(msg: string, ...args: any[]) {
87 if (this.isEnabled(TraceSource.LogLevel))
88 this.emit(TraceSource.LogLevel, format(msg, args));
89 }
90
91 isWarnEnabled() {
92 return this.level >= TraceSource.WarnLevel;
93 }
94
95 warn(msg: string, ...args: any[]) {
96 if (this.isEnabled(TraceSource.WarnLevel))
97 this.emit(TraceSource.WarnLevel, format(msg, args));
98 }
99
100 /**
101 * returns true if errors will be recorded.
102 */
103 isErrorEnabled() {
104 return this.level >= TraceSource.ErrorLevel;
105 }
106
107 /**
108 * Traces a error.
109 *
110 * @param msg the message.
111 * @param args parameters which will be substituted in the message.
112 */
113 error(msg: string, ...args: any[]) {
114 if (this.isEnabled(TraceSource.ErrorLevel))
115 this.emit(TraceSource.ErrorLevel, format(msg, args));
116 }
117
118 /**
119 * Checks whether the specified level is enabled for this
120 * trace source.
121 *
122 * @param level the trace level which should be checked.
123 */
124 isEnabled(level: number) {
125 return (this.level >= level);
126 }
127
128 /**
129 * Traces a raw event, passing data as it is to the underlying listeners
130 *
131 * @param level the level of the event
132 * @param arg the data of the event, can be a simple string or any object.
133 */
134 traceEvent(level: number, arg: any) {
135 if (this.isEnabled(level))
136 this.emit(level, arg);
137 }
138
139 /**
140 * Register the specified handler to be called for every new and already
141 * created trace source.
142 *
143 * @param handler the handler which will be called for each trace source
144 */
145 static on(handler: (source: TraceSource) => void) {
146 return Registry.instance.on(handler);
147 }
148
149 /**
150 * Creates or returns already created trace source for the specified id.
151 *
152 * @param id the id for the trace source
153 */
154 static get(id: any) {
155 return Registry.instance.get(id);
156 }
157 }
158
159 namespace TraceSource {
160 export const DebugLevel = 400;
161
162 export const LogLevel = 300;
163
164 export const WarnLevel = 200;
165
166 export const ErrorLevel = 100;
167
168 export const SilentLevel = 0;
169 }
170
171 export = TraceSource; No newline at end of file
@@ -0,0 +1,35
1 import { IObservable, IDestroyable, ICancellation } from "../../interfaces";
2 import * as TraceEvent from '../TraceEvent';
3 import { Cancellation } from "../../Cancellation";
4 import * as TraceSource from "../TraceSource";
5
6 class ConsoleWriter implements IDestroyable {
7 readonly _subscriptions = new Array<IDestroyable>();
8
9 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
10 var subscription = source.on(this.writeEvent.bind(this));
11 if (ct.isSupported()) {
12 ct.register(subscription.destroy.bind(subscription));
13 }
14 this._subscriptions.push(subscription);
15 }
16
17 writeEvent(next: TraceEvent) {
18 if (next.level >= TraceSource.LogLevel) {
19 console.log(next.source.id.toString(), next.arg);
20 } else if(next.level >= TraceSource.WarnLevel) {
21 console.warn(next.source.id.toString(), next.arg);
22 } else {
23 console.error(next.source.id.toString(), next.arg);
24 }
25 }
26
27 destroy() {
28 this._subscriptions.forEach(x => x.destroy());
29 }
30 }
31
32 namespace ConsoleWriter {
33 }
34
35 export = ConsoleWriter; No newline at end of file
@@ -0,0 +1,231
1 export function argumentNotNull(arg, name) {
2 if (arg === null || arg === undefined)
3 throw new Error("The argument " + name + " can't be null or undefined");
4 }
5
6 export function argumentNotEmptyString(arg, name) {
7 if (typeof (arg) !== "string" || !arg.length)
8 throw new Error("The argument '" + name + "' must be a not empty string");
9 }
10
11 export function argumentNotEmptyArray(arg, name) {
12 if (!(arg instanceof Array) || !arg.length)
13 throw new Error("The argument '" + name + "' must be a not empty array");
14 }
15
16 export function argumentOfType(arg, type, name) {
17 if (!(arg instanceof type))
18 throw new Error("The argument '" + name + "' type doesn't match");
19 }
20
21 export function isNull(arg) {
22 return (arg === null || arg === undefined);
23 }
24
25 export function isPrimitive(arg) {
26 return (arg === null || arg === undefined || typeof (arg) === "string" ||
27 typeof (arg) === "number" || typeof (arg) === "boolean");
28 }
29
30 export function isInteger(arg) {
31 return parseInt(arg) == arg;
32 }
33
34 export function isNumber(arg) {
35 return parseFloat(arg) == arg;
36 }
37
38 export function isString(val) {
39 return typeof (val) == "string" || val instanceof String;
40 }
41
42 export function isNullOrEmptyString(str) {
43 if (str === null || str === undefined ||
44 ((typeof (str) == "string" || str instanceof String) && str.length === 0))
45 return true;
46 }
47
48 export function isNotEmptyArray(arg) {
49 return (arg instanceof Array && arg.length > 0);
50 }
51
52 /**
53 * Выполняет метод для каждого элемента массива, останавливается, когда
54 * либо достигнут конец массива, либо функция <c>cb</c> вернула
55 * значение.
56 *
57 * @param {Array | Object} obj массив элементов для просмотра
58 * @param {Function} cb функция, вызываемая для каждого элемента
59 * @param {Object} thisArg значение, которое будет передано в качестве
60 * <c>this</c> в <c>cb</c>.
61 * @returns Результат вызова функции <c>cb</c>, либо <c>undefined</c>
62 * если достигнут конец массива.
63 */
64 export function each(obj, cb, thisArg) {
65 argumentNotNull(cb, "cb");
66 var i, x;
67 if (obj instanceof Array) {
68 for (i = 0; i < obj.length; i++) {
69 x = cb.call(thisArg, obj[i], i);
70 if (x !== undefined)
71 return x;
72 }
73 } else {
74 var keys = Object.keys(obj);
75 for (i = 0; i < keys.length; i++) {
76 var k = keys[i];
77 x = cb.call(thisArg, obj[k], k);
78 if (x !== undefined)
79 return x;
80 }
81 }
82 }
83
84 /** Wraps the specified function to emulate an asynchronous execution.
85 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
86 * @param{Function|String} fn [Required] Function wich will be wrapped.
87 */
88 export function async(_fn: (...args: any[]) => any, thisArg) : (...args: any[]) => PromiseLike<any> {
89 let fn = _fn;
90
91 if (arguments.length == 2 && !(fn instanceof Function))
92 fn = thisArg[fn];
93
94 if (fn == null)
95 throw new Error("The function must be specified");
96
97 function wrapresult(x, e?) : PromiseLike<any> {
98 if (e) {
99 return {
100 then: function (cb, eb) {
101 try {
102 return eb ? wrapresult(eb(e)) : this;
103 } catch (e2) {
104 return wrapresult(null, e2);
105 }
106 }
107 };
108 } else {
109 if (x && x.then)
110 return x;
111 return {
112 then: function (cb) {
113 try {
114 return cb ? wrapresult(cb(x)) : this;
115 } catch (e2) {
116 return wrapresult(e2);
117 }
118 }
119 };
120 }
121 }
122
123 return function () {
124 try {
125 return wrapresult(fn.apply(thisArg, arguments));
126 } catch (e) {
127 return wrapresult(null, e);
128 }
129 };
130 }
131
132 export function delegate(target, _method: (string | Function)) {
133 let method : Function;
134
135 if (!(_method instanceof Function)) {
136 argumentNotNull(target, "target");
137 method = target[_method];
138 } else {
139 method = _method;
140 }
141
142 if (!(method instanceof Function))
143 throw new Error("'method' argument must be a Function or a method name");
144
145 return function () {
146 return method.apply(target, arguments);
147 };
148 }
149
150 /**
151 * Для каждого элемента массива вызывает указанную функцию и сохраняет
152 * возвращенное значение в массиве результатов.
153 *
154 * @remarks cb может выполняться асинхронно, при этом одновременно будет
155 * только одна операция.
156 *
157 * @async
158 */
159 export function pmap(items, cb) {
160 argumentNotNull(cb, "cb");
161
162 if (items && items.then instanceof Function)
163 return items.then(function (data) {
164 return pmap(data, cb);
165 });
166
167 if (isNull(items) || !items.length)
168 return items;
169
170 var i = 0,
171 result = [];
172
173 function next() {
174 var r, ri;
175
176 function chain(x) {
177 result[ri] = x;
178 return next();
179 }
180
181 while (i < items.length) {
182 r = cb(items[i], i);
183 ri = i;
184 i++;
185 if (r && r.then) {
186 return r.then(chain);
187 } else {
188 result[ri] = r;
189 }
190 }
191 return result;
192 }
193
194 return next();
195 }
196
197 /**
198 * Выбирает первый элемент из последовательности, или обещания, если в
199 * качестве параметра используется обещание, оно должно вернуть массив.
200 *
201 * @param {Function} cb обработчик результата, ему будет передан первый
202 * элемент последовательности в случае успеха
203 * @param {Function} err обработчик исключения, если массив пустой, либо
204 * не массив
205 *
206 * @remarks Если не указаны ни cb ни err, тогда функция вернет либо
207 * обещание, либо первый элемент.
208 * @async
209 */
210 export function first(sequence: any, cb: Function, err: Function) {
211 if (sequence) {
212 if (sequence.then instanceof Function) {
213 return sequence.then(function (res) {
214 return first(res, cb, err);
215 }, err);
216 } else if (sequence && "length" in sequence) {
217 if (sequence.length === 0) {
218 if (err)
219 return err(new Error("The sequence is empty"));
220 else
221 throw new Error("The sequence is empty");
222 }
223 return cb ? cb(sequence[0]) : sequence[0];
224 }
225 }
226
227 if (err)
228 return err(new Error("The sequence is required"));
229 else
230 throw new Error("The sequence is required");
231 } No newline at end of file
@@ -0,0 +1,7
1 declare function format(format: string, ...args: any[]): string;
2
3 declare namespace format {
4
5 }
6
7 export = format; No newline at end of file
@@ -0,0 +1,29
1 define(["tape"], function(tape) {
2 "use strict";
3 var sourceId = '73a633f3-eab8-49b0-8601-07cae710f234';
4 var sourceId2 = '3ba9c7cd-ed77-437b-9a2f-1cbeb1226b5b';
5 tape('Load TraceSource for the module', function(t) {
6 require(["core/log/trace!" + sourceId, "core/log/TraceSource"], function(trace, TraceSource) {
7 t.equal(trace && trace.id, sourceId, "trace should be taken from the loader plugin parameter");
8
9 var count = 0;
10
11 var h = TraceSource.on(function(x) {
12 if(x.id == sourceId || x.id == sourceId2)
13 count++;
14 });
15
16 t.equal(count, 1, "should see created channel immediatelly");
17 t.equal(trace, TraceSource.get(sourceId), "should get same TraceSource from registry");
18 t.equal(count, 1);
19
20 TraceSource.get(sourceId2);
21
22 t.equal(count, 2);
23
24 h.destroy();
25
26 t.end();
27 });
28 });
29 }); No newline at end of file
@@ -0,0 +1,108
1 import * as tape from 'tape';
2 import * as ActivatableMixin from '@implab/core/components/ActivatableMixin';
3 import { AsyncComponent } from '@implab/core/components/AsyncComponent';
4 import { IActivationController, IActivatable, ICancellation } from '@implab/core/interfaces';
5 import { Cancellation } from '@implab/core/Cancellation';
6
7 class SimpleActivatable extends ActivatableMixin(AsyncComponent) {
8
9 }
10
11 class MockActivationController implements IActivationController {
12
13 _active: IActivatable = null;
14
15
16 getActive() : IActivatable {
17 return this._active;
18 }
19
20 async deactivate() {
21 if (this._active)
22 await this._active.deactivate();
23 this._active = null;
24 }
25
26 async activate(component: IActivatable) {
27 if (!component || component.isActive())
28 return;
29 component.setActivationController(this);
30
31 await component.activate();
32 }
33
34 async activating(component: IActivatable, ct: ICancellation = Cancellation.none) {
35 if (component != this._active)
36 await this.deactivate();
37 }
38
39 async activated(component: IActivatable, ct: ICancellation = Cancellation.none) {
40 this._active = component;
41 }
42
43 async deactivating(component: IActivatable, ct: ICancellation = Cancellation.none) {
44
45 }
46
47 async deactivated(component: IActivatable, ct: ICancellation = Cancellation.none) {
48 if (this._active == component)
49 this._active = null;
50 }
51 }
52
53 tape('simple activation',async function(t){
54
55 let a = new SimpleActivatable();
56 t.false(a.isActive());
57
58 await a.activate();
59 t.true(a.isActive());
60
61 await a.deactivate();
62 t.false(a.isActive());
63
64 t.end();
65 });
66
67 tape('controller activation', async function(t) {
68
69 let a = new SimpleActivatable();
70 let c = new MockActivationController();
71
72 t.false(a.isActive(), "the component is not active by default");
73 t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default");
74 t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default");
75
76 t.comment("Active the component through the controller");
77 await c.activate(a);
78 t.true(a.isActive(), "The component should successfully activate");
79 t.equal(c.getActive(), a, "The controller should point to the activated component");
80 t.equal(a.getActivationController(), c, "The component should point to the controller");
81
82 t.comment("Deactive the component throug the controller");
83 await c.deactivate();
84
85 t.false(a.isActive(), "The component should successfully deactivate");
86 t.equal(c.getActive(), null, "The controller shouldn't point to any component");
87 t.equal(a.getActivationController(), c, "The componet should point to it's controller");
88
89 t.end();
90 });
91
92 tape('handle error in onActivating', async function(t) {
93 let a = new SimpleActivatable();
94
95 a.onActivating = async function() {
96 throw "Should fail";
97 };
98
99 try {
100 await a.activate();
101 t.fail("activation should fail");
102 } catch {
103 }
104
105 t.false(a.isActive(), "the component should remain inactive");
106
107 t.end();
108 }); No newline at end of file
@@ -0,0 +1,97
1 import * as tape from 'tape';
2 import { Cancellation } from '@implab/core/Cancellation';
3 import { ICancellation } from '@implab/core/interfaces';
4 import { delay } from './TestTraits';
5
6 tape('standalone cancellation', async t => {
7
8 let doCancel: (e) => void;
9
10 let ct = new Cancellation(cancel => {
11 doCancel = cancel;
12 });
13
14 let counter = 0;
15 let reason = "BILL";
16
17 t.true(ct.isSupported(), "Cancellation must be supported");
18 t.false(ct.isRequested(), "Cancellation shouldn't be requested");
19 ct.throwIfRequested();
20 t.pass("The exception shouldn't be thrown unless the cancellation is requested");
21
22 ct.register(() => counter++);
23 t.equals(counter, 0, "counter should be zero");
24
25 ct.register(() => counter++).destroy();
26
27 doCancel(reason);
28
29 t.true(ct.isRequested(), "Cancellation should be requested");
30 t.equals(counter, 1, "The registered callback should be triggered");
31
32 ct.register(() => counter++);
33 t.equals(counter, 2, "The callback should be triggered immediately");
34
35 let msg;
36 ct.register((e) => msg = e);
37 t.equals(msg, reason, "The cancellation reason should be passed to callback");
38
39 try {
40 msg = null;
41 ct.throwIfRequested();
42 t.fail("The exception should be thrown");
43 } catch (e) {
44 msg = e;
45 }
46 t.equals(msg, reason, "The cancellation reason should be catched");
47
48 t.end();
49 });
50
51 tape('async cancellation', async t => {
52
53 let ct = new Cancellation(cancel => {
54 cancel("STOP!");
55 });
56
57 try {
58 await delay(0, ct);
59 t.fail("Should thow the exception");
60 } catch (e) {
61 t.equals(e, "STOP!", "Should throw the cancellation reason");
62 }
63
64 t.end();
65 });
66
67 tape('cancel with external event', async t => {
68 let ct = new Cancellation((cancel) => {
69 setTimeout(x => cancel('STOP!'), 0);
70 })
71
72 try {
73 await delay(10000, ct);
74 t.fail("Should thow the exception");
75 } catch (e) {
76 t.equals(e, "STOP!", "Should throw the cancellation reason");
77 }
78
79 t.end();
80 });
81
82 tape('operation normal flow', async t => {
83
84 let htimeout;
85 let ct = new Cancellation((cancel) => {
86 htimeout = setTimeout(() => cancel("STOP!"), 1000);
87 });
88
89 try {
90 await delay(0, ct);
91 t.pass("Should pass");
92 } finally {
93 clearTimeout(htimeout);
94 }
95
96 t.end();
97 }); No newline at end of file
@@ -0,0 +1,63
1 import { IObservable, ICancellation, IDestroyable } from "../../build/dist/interfaces";
2 import * as TraceEvent from '../../build/dist/log/TraceEvent';
3 import { Cancellation } from "../../build/dist/Cancellation";
4 import * as TraceSource from "../../build/dist/log/TraceSource";
5 import * as tape from 'tape';
6 import { argumentNotNull } from "../../build/dist/safe";
7
8 export class TapeWriter implements IDestroyable {
9 readonly _tape: tape.Test
10
11 _subscriptions = new Array<IDestroyable>();
12
13 constructor(tape: tape.Test) {
14 argumentNotNull(tape, "tape");
15 this._tape = tape;
16 }
17
18 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
19 let subscription = source.on(this.writeEvent.bind(this));
20 if (ct.isSupported()) {
21 ct.register(subscription.destroy.bind(subscription));
22 }
23 this._subscriptions.push(subscription);
24 }
25
26 writeEvent(next: TraceEvent) {
27 if (next.level >= TraceSource.LogLevel) {
28 this._tape.comment("LOG " + next.arg);
29 } else if (next.level >= TraceSource.WarnLevel) {
30 this._tape.comment("WARN " + next.arg);
31 } else {
32 this._tape.comment("ERROR " + next.arg);
33 }
34 }
35
36 destroy() {
37 this._subscriptions.forEach(x => x.destroy());
38 }
39 }
40
41 export async function delay(timeout: number, ct: ICancellation = Cancellation.none) {
42 let un: IDestroyable;
43
44 try {
45 await new Promise((resolve, reject) => {
46 if (ct.isRequested()) {
47 un = ct.register(reject);
48 } else {
49 let ht = setTimeout(() => {
50 resolve();
51 }, timeout);
52
53 un = ct.register(e => {
54 clearTimeout(ht);
55 reject(e);
56 });
57 }
58 });
59 } finally {
60 if(un)
61 un.destroy();
62 };
63 } No newline at end of file
@@ -0,0 +1,69
1 import * as TraceSource from '@implab/core/log/TraceSource'
2 import * as tape from 'tape';
3 import { TapeWriter } from './TestTraits';
4
5 const sourceId = 'test/TraceSourceTests';
6
7 tape('trace message', t => {
8 let trace = TraceSource.get(sourceId);
9
10 trace.level = TraceSource.DebugLevel;
11
12 let h = trace.on((ev) => {
13 t.equal(ev.source, trace, "sender should be the current trace source");
14 t.equal(ev.level, TraceSource.DebugLevel, "level should be debug level");
15 t.equal(ev.arg, "Hello, World!", "The message should be a formatted message");
16
17 t.end();
18 });
19
20 trace.debug("Hello, {0}!", "World");
21
22 h.destroy();
23 });
24
25 tape('trace event', t => {
26 let trace = TraceSource.get(sourceId);
27
28 trace.level = TraceSource.DebugLevel;
29
30 let event = {
31 name: "custom event"
32 };
33
34 let h = trace.on((ev) => {
35 t.equal(ev.source, trace, "sender should be the current trace source");
36 t.equal(ev.level, TraceSource.DebugLevel, "level should be debug level");
37 t.equal(ev.arg, event, "The message should be the specified object");
38
39 t.end();
40 });
41
42 trace.traceEvent(TraceSource.DebugLevel, event);
43
44 h.destroy();
45 });
46
47 tape('tape comment writer', async t => {
48 let writer = new TapeWriter(t);
49
50 TraceSource.on(ts => {
51 writer.writeEvents(ts);
52 });
53
54 let trace = TraceSource.get(sourceId);
55 trace.level = TraceSource.DebugLevel;
56
57 trace.log("Hello, {0}!", 'World');
58 trace.log("Multi\n line");
59 trace.warn("Look at me!");
60 trace.error("DIE!");
61
62 writer.destroy();
63
64 trace.log("You shouldn't see it!");
65
66 t.comment("DONE");
67
68 t.end();
69 }); No newline at end of file
@@ -1,90 +1,91
1
1
2 println "version: $version"
2 println "version: $version"
3
3
4 def distDir = "$buildDir/dist"
4 def distDir = "$buildDir/dist"
5 def testDir = "$buildDir/test"
5 def testDir = "$buildDir/test"
6
6
7 task clean {
7 task clean {
8 doLast {
8 doLast {
9 delete buildDir
9 delete buildDir
10 delete 'node_modules/@implab'
10 }
11 }
11 }
12 }
12
13
13 task cleanNpm {
14 task cleanNpm {
14 doLast {
15 doLast {
15 delete 'node_modules'
16 delete 'node_modules'
16 }
17 }
17 }
18 }
18
19
19 task _npmInstall() {
20 task _npmInstall() {
20 inputs.file("package.json")
21 inputs.file("package.json")
21 outputs.dir("node_modules")
22 outputs.dir("node_modules")
22 doLast {
23 doLast {
23 exec {
24 exec {
24 commandLine 'npm', 'install'
25 commandLine 'npm', 'install'
25 }
26 }
26 }
27 }
27 }
28 }
28
29
29 task _legacyJs(type:Copy) {
30 task _legacyJs(type:Copy) {
30 from 'src/js/'
31 from 'src/js/'
31 into distDir
32 into distDir
32 }
33 }
33
34
34 task _buildTs(dependsOn: _npmInstall, type:Exec) {
35 task _buildTs(dependsOn: _npmInstall, type:Exec) {
35 inputs.dir('src/ts')
36 inputs.dir('src/ts')
36 inputs.file('tsc.json')
37 inputs.file('tsc.json')
37 outputs.dir(distDir)
38 outputs.dir(distDir)
38
39
39 commandLine 'node_modules/.bin/tsc', '-p', 'tsc.json'
40 commandLine 'node_modules/.bin/tsc', '-p', 'tsc.json'
40 }
41 }
41
42
42 task _packageMeta(type: Copy) {
43 task _packageMeta(type: Copy) {
43 inputs.property("version", version)
44 inputs.property("version", version)
44 from('.') {
45 from('.') {
45 include 'package.json', 'readme.md', 'license', 'history.md'
46 include 'package.json', '.npmignore', 'readme.md', 'license', 'history.md'
46 }
47 }
47 into distDir
48 into distDir
48 doLast {
49 doLast {
49 exec {
50 exec {
50 workingDir distDir
51 workingDir distDir
51 commandLine 'npm', 'version', version
52 commandLine 'npm', 'version', version
52 }
53 }
53 }
54 }
54 }
55 }
55
56
56 task build(dependsOn: [_npmInstall, _buildTs, _legacyJs, _packageMeta]) {
57 task build(dependsOn: [_npmInstall, _buildTs, _legacyJs, _packageMeta]) {
57
58
58 }
59 }
59
60
60 task _localInstall(dependsOn: build, type: Exec) {
61 task _localInstall(dependsOn: build, type: Exec) {
61 inputs.file("$distDir/package.json")
62 inputs.file("$distDir/package.json")
62 outputs.upToDateWhen {
63 outputs.upToDateWhen {
63 new File("$projectDir/node_modules/@implab/core").exists()
64 new File("$projectDir/node_modules/@implab/core").exists()
64 }
65 }
65
66
66 commandLine 'npm', 'install', '--no-save', '--force', distDir
67 commandLine 'npm', 'install', '--no-save', '--force', distDir
67 }
68 }
68
69
69 task copyJsTests(type: Copy) {
70 task copyJsTests(type: Copy) {
70 from 'test/js'
71 from 'test/js'
71 into testDir
72 into testDir
72 }
73 }
73
74
74 task buildTests(dependsOn: _localInstall, type: Exec) {
75 task buildTests(dependsOn: _localInstall, type: Exec) {
75 inputs.dir('test/ts')
76 inputs.dir('test/ts')
76 inputs.file('tsc.test.json')
77 inputs.file('tsc.test.json')
77 outputs.dir(testDir)
78 outputs.dir(testDir)
78
79
79 commandLine 'node_modules/.bin/tsc', '-p', 'tsc.test.json'
80 commandLine 'node_modules/.bin/tsc', '-p', 'tsc.test.json'
80 }
81 }
81
82
82 task test(dependsOn: [copyJsTests, buildTests], type: Exec) {
83 task test(dependsOn: [copyJsTests, buildTests], type: Exec) {
83 commandLine 'node', 'run-amd-tests.js'
84 commandLine 'node', 'run-amd-tests.js'
84 }
85 }
85
86
86 task pack(dependsOn: build, type: Exec) {
87 task pack(dependsOn: build, type: Exec) {
87 workingDir = distDir
88 workingDir = distDir
88
89
89 commandLine 'npm', 'pack'
90 commandLine 'npm', 'pack'
90 } No newline at end of file
91 }
@@ -1,445 +1,445
1 {
1 {
2 "name": "@implab/core",
2 "name": "@implab/core",
3 "version": "0.0.1-dev",
3 "version": "0.0.1-dev",
4 "lockfileVersion": 1,
4 "lockfileVersion": 1,
5 "requires": true,
5 "requires": true,
6 "dependencies": {
6 "dependencies": {
7 "@types/node": {
7 "@types/node": {
8 "version": "10.5.1",
8 "version": "10.5.1",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.1.tgz",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.1.tgz",
10 "integrity": "sha512-AFLl1IALIuyt6oK4AYZsgWVJ/5rnyzQWud7IebaZWWV3YmgtPZkQmYio9R5Ze/2pdd7XfqF5bP+hWS11mAKoOQ==",
10 "integrity": "sha512-AFLl1IALIuyt6oK4AYZsgWVJ/5rnyzQWud7IebaZWWV3YmgtPZkQmYio9R5Ze/2pdd7XfqF5bP+hWS11mAKoOQ==",
11 "dev": true
11 "dev": true
12 },
12 },
13 "@types/tape": {
13 "@types/tape": {
14 "version": "4.2.32",
14 "version": "4.2.32",
15 "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.32.tgz",
15 "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.32.tgz",
16 "integrity": "sha512-xil0KO5wkPoixdBWGIGolPv9dekf6dVkjjJLAFYchfKcd4DICou67rgGCIO7wAh3i5Ff/6j9IDgZz+GU9cMaqQ==",
16 "integrity": "sha512-xil0KO5wkPoixdBWGIGolPv9dekf6dVkjjJLAFYchfKcd4DICou67rgGCIO7wAh3i5Ff/6j9IDgZz+GU9cMaqQ==",
17 "dev": true,
17 "dev": true,
18 "requires": {
18 "requires": {
19 "@types/node": "10.5.1"
19 "@types/node": "10.5.1"
20 }
20 }
21 },
21 },
22 "balanced-match": {
22 "balanced-match": {
23 "version": "1.0.0",
23 "version": "1.0.0",
24 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
24 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
25 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
25 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
26 "dev": true
26 "dev": true
27 },
27 },
28 "brace-expansion": {
28 "brace-expansion": {
29 "version": "1.1.11",
29 "version": "1.1.11",
30 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
30 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
31 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
31 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
32 "dev": true,
32 "dev": true,
33 "requires": {
33 "requires": {
34 "balanced-match": "1.0.0",
34 "balanced-match": "1.0.0",
35 "concat-map": "0.0.1"
35 "concat-map": "0.0.1"
36 }
36 }
37 },
37 },
38 "concat-map": {
38 "concat-map": {
39 "version": "0.0.1",
39 "version": "0.0.1",
40 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
40 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
41 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
41 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
42 "dev": true
42 "dev": true
43 },
43 },
44 "core-util-is": {
44 "core-util-is": {
45 "version": "1.0.2",
45 "version": "1.0.2",
46 "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
46 "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
47 "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
47 "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
48 "dev": true
48 "dev": true
49 },
49 },
50 "deep-equal": {
50 "deep-equal": {
51 "version": "1.0.1",
51 "version": "1.0.1",
52 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
52 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
53 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
53 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
54 "dev": true
54 "dev": true
55 },
55 },
56 "define-properties": {
56 "define-properties": {
57 "version": "1.1.2",
57 "version": "1.1.2",
58 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
58 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
59 "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
59 "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
60 "dev": true,
60 "dev": true,
61 "requires": {
61 "requires": {
62 "foreach": "2.0.5",
62 "foreach": "2.0.5",
63 "object-keys": "1.0.12"
63 "object-keys": "1.0.12"
64 }
64 }
65 },
65 },
66 "defined": {
66 "defined": {
67 "version": "1.0.0",
67 "version": "1.0.0",
68 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
68 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
69 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
69 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
70 "dev": true
70 "dev": true
71 },
71 },
72 "dojo": {
72 "dojo": {
73 "version": "1.13.0",
73 "version": "1.13.0",
74 "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.13.0.tgz",
74 "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.13.0.tgz",
75 "integrity": "sha512-mGoGvsXAbPkUrBnxCoO7m6CFH8jvWq7rAL7fP7jrhJEOyswA/bZwWdXwEH0ovs68t8S0+xOpV/3V7addYbaiAA=="
75 "integrity": "sha512-mGoGvsXAbPkUrBnxCoO7m6CFH8jvWq7rAL7fP7jrhJEOyswA/bZwWdXwEH0ovs68t8S0+xOpV/3V7addYbaiAA=="
76 },
76 },
77 "duplexer": {
77 "duplexer": {
78 "version": "0.1.1",
78 "version": "0.1.1",
79 "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
79 "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
80 "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
80 "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
81 "dev": true
81 "dev": true
82 },
82 },
83 "es-abstract": {
83 "es-abstract": {
84 "version": "1.12.0",
84 "version": "1.12.0",
85 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
85 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
86 "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
86 "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
87 "dev": true,
87 "dev": true,
88 "requires": {
88 "requires": {
89 "es-to-primitive": "1.1.1",
89 "es-to-primitive": "1.1.1",
90 "function-bind": "1.1.1",
90 "function-bind": "1.1.1",
91 "has": "1.0.3",
91 "has": "1.0.3",
92 "is-callable": "1.1.3",
92 "is-callable": "1.1.3",
93 "is-regex": "1.0.4"
93 "is-regex": "1.0.4"
94 }
94 }
95 },
95 },
96 "es-to-primitive": {
96 "es-to-primitive": {
97 "version": "1.1.1",
97 "version": "1.1.1",
98 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
98 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
99 "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
99 "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
100 "dev": true,
100 "dev": true,
101 "requires": {
101 "requires": {
102 "is-callable": "1.1.3",
102 "is-callable": "1.1.3",
103 "is-date-object": "1.0.1",
103 "is-date-object": "1.0.1",
104 "is-symbol": "1.0.1"
104 "is-symbol": "1.0.1"
105 }
105 }
106 },
106 },
107 "faucet": {
107 "faucet": {
108 "version": "0.0.1",
108 "version": "0.0.1",
109 "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz",
109 "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz",
110 "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=",
110 "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=",
111 "dev": true,
111 "dev": true,
112 "requires": {
112 "requires": {
113 "defined": "0.0.0",
113 "defined": "0.0.0",
114 "duplexer": "0.1.1",
114 "duplexer": "0.1.1",
115 "minimist": "0.0.5",
115 "minimist": "0.0.5",
116 "sprintf": "0.1.5",
116 "sprintf": "0.1.5",
117 "tap-parser": "0.4.3",
117 "tap-parser": "0.4.3",
118 "tape": "2.3.3",
118 "tape": "2.3.3",
119 "through2": "0.2.3"
119 "through2": "0.2.3"
120 },
120 },
121 "dependencies": {
121 "dependencies": {
122 "deep-equal": {
122 "deep-equal": {
123 "version": "0.1.2",
123 "version": "0.1.2",
124 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz",
124 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz",
125 "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=",
125 "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=",
126 "dev": true
126 "dev": true
127 },
127 },
128 "defined": {
128 "defined": {
129 "version": "0.0.0",
129 "version": "0.0.0",
130 "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz",
130 "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz",
131 "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=",
131 "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=",
132 "dev": true
132 "dev": true
133 },
133 },
134 "minimist": {
134 "minimist": {
135 "version": "0.0.5",
135 "version": "0.0.5",
136 "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
136 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
137 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
137 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
138 "dev": true
138 "dev": true
139 },
139 },
140 "tape": {
140 "tape": {
141 "version": "2.3.3",
141 "version": "2.3.3",
142 "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
142 "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
143 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
143 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
144 "dev": true,
144 "dev": true,
145 "requires": {
145 "requires": {
146 "deep-equal": "0.1.2",
146 "deep-equal": "0.1.2",
147 "defined": "0.0.0",
147 "defined": "0.0.0",
148 "inherits": "2.0.3",
148 "inherits": "2.0.3",
149 "jsonify": "0.0.0",
149 "jsonify": "0.0.0",
150 "resumer": "0.0.0",
150 "resumer": "0.0.0",
151 "through": "2.3.8"
151 "through": "2.3.8"
152 }
152 }
153 }
153 }
154 }
154 }
155 },
155 },
156 "for-each": {
156 "for-each": {
157 "version": "0.3.3",
157 "version": "0.3.3",
158 "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
158 "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
159 "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
159 "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
160 "dev": true,
160 "dev": true,
161 "requires": {
161 "requires": {
162 "is-callable": "1.1.3"
162 "is-callable": "1.1.3"
163 }
163 }
164 },
164 },
165 "foreach": {
165 "foreach": {
166 "version": "2.0.5",
166 "version": "2.0.5",
167 "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
167 "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
168 "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
168 "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
169 "dev": true
169 "dev": true
170 },
170 },
171 "fs.realpath": {
171 "fs.realpath": {
172 "version": "1.0.0",
172 "version": "1.0.0",
173 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
173 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
174 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
174 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
175 "dev": true
175 "dev": true
176 },
176 },
177 "function-bind": {
177 "function-bind": {
178 "version": "1.1.1",
178 "version": "1.1.1",
179 "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
179 "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
180 "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
180 "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
181 "dev": true
181 "dev": true
182 },
182 },
183 "glob": {
183 "glob": {
184 "version": "7.1.2",
184 "version": "7.1.2",
185 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
185 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
186 "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
186 "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
187 "dev": true,
187 "dev": true,
188 "requires": {
188 "requires": {
189 "fs.realpath": "1.0.0",
189 "fs.realpath": "1.0.0",
190 "inflight": "1.0.6",
190 "inflight": "1.0.6",
191 "inherits": "2.0.3",
191 "inherits": "2.0.3",
192 "minimatch": "3.0.4",
192 "minimatch": "3.0.4",
193 "once": "1.4.0",
193 "once": "1.4.0",
194 "path-is-absolute": "1.0.1"
194 "path-is-absolute": "1.0.1"
195 }
195 }
196 },
196 },
197 "has": {
197 "has": {
198 "version": "1.0.3",
198 "version": "1.0.3",
199 "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
199 "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
200 "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
200 "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
201 "dev": true,
201 "dev": true,
202 "requires": {
202 "requires": {
203 "function-bind": "1.1.1"
203 "function-bind": "1.1.1"
204 }
204 }
205 },
205 },
206 "inflight": {
206 "inflight": {
207 "version": "1.0.6",
207 "version": "1.0.6",
208 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
208 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
209 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
209 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
210 "dev": true,
210 "dev": true,
211 "requires": {
211 "requires": {
212 "once": "1.4.0",
212 "once": "1.4.0",
213 "wrappy": "1.0.2"
213 "wrappy": "1.0.2"
214 }
214 }
215 },
215 },
216 "inherits": {
216 "inherits": {
217 "version": "2.0.3",
217 "version": "2.0.3",
218 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
218 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
219 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
219 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
220 "dev": true
220 "dev": true
221 },
221 },
222 "is-callable": {
222 "is-callable": {
223 "version": "1.1.3",
223 "version": "1.1.3",
224 "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
224 "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
225 "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
225 "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
226 "dev": true
226 "dev": true
227 },
227 },
228 "is-date-object": {
228 "is-date-object": {
229 "version": "1.0.1",
229 "version": "1.0.1",
230 "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
230 "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
231 "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
231 "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
232 "dev": true
232 "dev": true
233 },
233 },
234 "is-regex": {
234 "is-regex": {
235 "version": "1.0.4",
235 "version": "1.0.4",
236 "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
236 "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
237 "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
237 "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
238 "dev": true,
238 "dev": true,
239 "requires": {
239 "requires": {
240 "has": "1.0.3"
240 "has": "1.0.3"
241 }
241 }
242 },
242 },
243 "is-symbol": {
243 "is-symbol": {
244 "version": "1.0.1",
244 "version": "1.0.1",
245 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
245 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
246 "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
246 "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
247 "dev": true
247 "dev": true
248 },
248 },
249 "isarray": {
249 "isarray": {
250 "version": "0.0.1",
250 "version": "0.0.1",
251 "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
251 "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
252 "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
252 "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
253 "dev": true
253 "dev": true
254 },
254 },
255 "jsonify": {
255 "jsonify": {
256 "version": "0.0.0",
256 "version": "0.0.0",
257 "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
257 "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
258 "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
258 "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
259 "dev": true
259 "dev": true
260 },
260 },
261 "minimatch": {
261 "minimatch": {
262 "version": "3.0.4",
262 "version": "3.0.4",
263 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
263 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
264 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
264 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
265 "dev": true,
265 "dev": true,
266 "requires": {
266 "requires": {
267 "brace-expansion": "1.1.11"
267 "brace-expansion": "1.1.11"
268 }
268 }
269 },
269 },
270 "minimist": {
270 "minimist": {
271 "version": "1.2.0",
271 "version": "1.2.0",
272 "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
272 "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
273 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
273 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
274 "dev": true
274 "dev": true
275 },
275 },
276 "object-inspect": {
276 "object-inspect": {
277 "version": "1.6.0",
277 "version": "1.6.0",
278 "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
278 "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
279 "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
279 "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
280 "dev": true
280 "dev": true
281 },
281 },
282 "object-keys": {
282 "object-keys": {
283 "version": "1.0.12",
283 "version": "1.0.12",
284 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
284 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
285 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
285 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
286 "dev": true
286 "dev": true
287 },
287 },
288 "once": {
288 "once": {
289 "version": "1.4.0",
289 "version": "1.4.0",
290 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
290 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
291 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
291 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
292 "dev": true,
292 "dev": true,
293 "requires": {
293 "requires": {
294 "wrappy": "1.0.2"
294 "wrappy": "1.0.2"
295 }
295 }
296 },
296 },
297 "path-is-absolute": {
297 "path-is-absolute": {
298 "version": "1.0.1",
298 "version": "1.0.1",
299 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
299 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
300 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
300 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
301 "dev": true
301 "dev": true
302 },
302 },
303 "path-parse": {
303 "path-parse": {
304 "version": "1.0.5",
304 "version": "1.0.5",
305 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
305 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
306 "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
306 "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
307 "dev": true
307 "dev": true
308 },
308 },
309 "readable-stream": {
309 "readable-stream": {
310 "version": "1.1.14",
310 "version": "1.1.14",
311 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
311 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
312 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
312 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
313 "dev": true,
313 "dev": true,
314 "requires": {
314 "requires": {
315 "core-util-is": "1.0.2",
315 "core-util-is": "1.0.2",
316 "inherits": "2.0.3",
316 "inherits": "2.0.3",
317 "isarray": "0.0.1",
317 "isarray": "0.0.1",
318 "string_decoder": "0.10.31"
318 "string_decoder": "0.10.31"
319 }
319 }
320 },
320 },
321 "requirejs": {
321 "requirejs": {
322 "version": "2.3.5",
322 "version": "2.3.6",
323 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz",
323 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
324 "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==",
324 "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
325 "dev": true
325 "dev": true
326 },
326 },
327 "resolve": {
327 "resolve": {
328 "version": "1.7.1",
328 "version": "1.7.1",
329 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
329 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
330 "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
330 "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
331 "dev": true,
331 "dev": true,
332 "requires": {
332 "requires": {
333 "path-parse": "1.0.5"
333 "path-parse": "1.0.5"
334 }
334 }
335 },
335 },
336 "resumer": {
336 "resumer": {
337 "version": "0.0.0",
337 "version": "0.0.0",
338 "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
338 "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
339 "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
339 "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
340 "dev": true,
340 "dev": true,
341 "requires": {
341 "requires": {
342 "through": "2.3.8"
342 "through": "2.3.8"
343 }
343 }
344 },
344 },
345 "sprintf": {
345 "sprintf": {
346 "version": "0.1.5",
346 "version": "0.1.5",
347 "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
347 "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
348 "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
348 "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
349 "dev": true
349 "dev": true
350 },
350 },
351 "string.prototype.trim": {
351 "string.prototype.trim": {
352 "version": "1.1.2",
352 "version": "1.1.2",
353 "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
353 "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
354 "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
354 "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
355 "dev": true,
355 "dev": true,
356 "requires": {
356 "requires": {
357 "define-properties": "1.1.2",
357 "define-properties": "1.1.2",
358 "es-abstract": "1.12.0",
358 "es-abstract": "1.12.0",
359 "function-bind": "1.1.1"
359 "function-bind": "1.1.1"
360 }
360 }
361 },
361 },
362 "string_decoder": {
362 "string_decoder": {
363 "version": "0.10.31",
363 "version": "0.10.31",
364 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
364 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
365 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
365 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
366 "dev": true
366 "dev": true
367 },
367 },
368 "tap-parser": {
368 "tap-parser": {
369 "version": "0.4.3",
369 "version": "0.4.3",
370 "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz",
370 "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz",
371 "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
371 "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
372 "dev": true,
372 "dev": true,
373 "requires": {
373 "requires": {
374 "inherits": "2.0.3",
374 "inherits": "2.0.3",
375 "readable-stream": "1.1.14"
375 "readable-stream": "1.1.14"
376 }
376 }
377 },
377 },
378 "tape": {
378 "tape": {
379 "version": "4.9.1",
379 "version": "4.9.1",
380 "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz",
380 "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz",
381 "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==",
381 "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==",
382 "dev": true,
382 "dev": true,
383 "requires": {
383 "requires": {
384 "deep-equal": "1.0.1",
384 "deep-equal": "1.0.1",
385 "defined": "1.0.0",
385 "defined": "1.0.0",
386 "for-each": "0.3.3",
386 "for-each": "0.3.3",
387 "function-bind": "1.1.1",
387 "function-bind": "1.1.1",
388 "glob": "7.1.2",
388 "glob": "7.1.2",
389 "has": "1.0.3",
389 "has": "1.0.3",
390 "inherits": "2.0.3",
390 "inherits": "2.0.3",
391 "minimist": "1.2.0",
391 "minimist": "1.2.0",
392 "object-inspect": "1.6.0",
392 "object-inspect": "1.6.0",
393 "resolve": "1.7.1",
393 "resolve": "1.7.1",
394 "resumer": "0.0.0",
394 "resumer": "0.0.0",
395 "string.prototype.trim": "1.1.2",
395 "string.prototype.trim": "1.1.2",
396 "through": "2.3.8"
396 "through": "2.3.8"
397 }
397 }
398 },
398 },
399 "through": {
399 "through": {
400 "version": "2.3.8",
400 "version": "2.3.8",
401 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
401 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
402 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
402 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
403 "dev": true
403 "dev": true
404 },
404 },
405 "through2": {
405 "through2": {
406 "version": "0.2.3",
406 "version": "0.2.3",
407 "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
407 "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
408 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
408 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
409 "dev": true,
409 "dev": true,
410 "requires": {
410 "requires": {
411 "readable-stream": "1.1.14",
411 "readable-stream": "1.1.14",
412 "xtend": "2.1.2"
412 "xtend": "2.1.2"
413 }
413 }
414 },
414 },
415 "typescript": {
415 "typescript": {
416 "version": "2.9.2",
416 "version": "3.0.3",
417 "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
417 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.3.tgz",
418 "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
418 "integrity": "sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg==",
419 "dev": true
419 "dev": true
420 },
420 },
421 "wrappy": {
421 "wrappy": {
422 "version": "1.0.2",
422 "version": "1.0.2",
423 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
423 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
424 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
424 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
425 "dev": true
425 "dev": true
426 },
426 },
427 "xtend": {
427 "xtend": {
428 "version": "2.1.2",
428 "version": "2.1.2",
429 "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
429 "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
430 "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
430 "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
431 "dev": true,
431 "dev": true,
432 "requires": {
432 "requires": {
433 "object-keys": "0.4.0"
433 "object-keys": "0.4.0"
434 },
434 },
435 "dependencies": {
435 "dependencies": {
436 "object-keys": {
436 "object-keys": {
437 "version": "0.4.0",
437 "version": "0.4.0",
438 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
438 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
439 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
439 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
440 "dev": true
440 "dev": true
441 }
441 }
442 }
442 }
443 }
443 }
444 }
444 }
445 }
445 }
@@ -1,23 +1,27
1 var requirejs = require('requirejs');
1 var requirejs = require('requirejs');
2
2
3 requirejs.config({
3 requirejs.config({
4 baseUrl: '.',
4 baseUrl: '.',
5 map: {
5 map: {
6 "*": {
6 "*": {
7 "@implab/core": "core"
7 "@implab/core": "core"
8 }
8 }
9 },
9 },
10 packages: [{
10 packages: [{
11 name: "core",
11 name: "core",
12 location: "build/dist"
12 location: "build/dist"
13 },
13 },
14 {
14 {
15 name: "test",
15 name: "test",
16 location: "build/test"
16 location: "build/test"
17 },
18 {
19 name: "dojo",
20 location: "node_modules/dojo"
17 }
21 }
18 ],
22 ],
19 nodeRequire: require
23 nodeRequire: require
20 });
24 });
21
25
22
26
23 requirejs(['test/plan']); No newline at end of file
27 requirejs(['test/plan']);
@@ -1,299 +1,299
1 define([
1 define([
2 "../declare",
2 "../declare",
3 "../safe",
3 "../safe",
4 "../Uuid",
4 "../Uuid",
5 "../Deferred",
5 "../Deferred",
6 "./ActivationContext",
6 "./ActivationContext",
7 "./Descriptor",
7 "./Descriptor",
8 "./ValueDescriptor",
8 "./ValueDescriptor",
9 "./ReferenceDescriptor",
9 "./ReferenceDescriptor",
10 "./ServiceDescriptor",
10 "./ServiceDescriptor",
11 "./ActivationError"
11 "./ActivationError"
12 ], function (
12 ], function (
13 declare,
13 declare,
14 safe,
14 safe,
15 Uuid,
15 Uuid,
16 Deferred,
16 Deferred,
17 ActivationContext,
17 ActivationContext,
18 Descriptor,
18 Descriptor,
19 Value,
19 Value,
20 Reference,
20 Reference,
21 Service,
21 Service,
22 ActivationError) {
22 ActivationError) {
23 var Container = declare(null, {
23 var Container = declare(null, {
24 _services: null,
24 _services: null,
25 _cache: null,
25 _cache: null,
26 _cleanup: null,
26 _cleanup: null,
27 _root: null,
27 _root: null,
28 _parent: null,
28 _parent: null,
29
29
30 constructor: function (parent) {
30 constructor: function (parent) {
31 this._parent = parent;
31 this._parent = parent;
32 this._services = parent ? Object.create(parent._services) : {};
32 this._services = parent ? Object.create(parent._services) : {};
33 this._cache = {};
33 this._cache = {};
34 this._cleanup = [];
34 this._cleanup = [];
35 this._root = parent ? parent.getRootContainer() : this;
35 this._root = parent ? parent.getRootContainer() : this;
36 this._services.container = new Value(this, true);
36 this._services.container = new Value(this, true);
37 },
37 },
38
38
39 getRootContainer: function () {
39 getRootContainer: function () {
40 return this._root;
40 return this._root;
41 },
41 },
42
42
43 getParent: function () {
43 getParent: function () {
44 return this._parent;
44 return this._parent;
45 },
45 },
46
46
47 /**
47 /**
48 *
48 *
49 */
49 */
50 getService: function (name, def) {
50 getService: function (name, def) {
51 var d = this._services[name];
51 var d = this._services[name];
52 if (!d)
52 if (!d)
53 if (arguments.length > 1)
53 if (arguments.length > 1)
54 return def;
54 return def;
55 else
55 else
56 throw new Error("Service '" + name + "' isn't found");
56 throw new Error("Service '" + name + "' isn't found");
57 if (d.isInstanceCreated())
57 if (d.isInstanceCreated())
58 return d.getInstance();
58 return d.getInstance();
59
59
60 var context = new ActivationContext(this, this._services);
60 var context = new ActivationContext(this, this._services);
61
61
62 try {
62 try {
63 return d.activate(context, name);
63 return d.activate(context, name);
64 } catch (error) {
64 } catch (error) {
65 throw new ActivationError(name, context.getStack(), error);
65 throw new ActivationError(name, context.getStack(), error);
66 }
66 }
67 },
67 },
68
68
69 register: function (name, service) {
69 register: function (name, service) {
70 if (arguments.length == 1) {
70 if (arguments.length == 1) {
71 var data = name;
71 var data = name;
72 for (name in data)
72 for (name in data)
73 this.register(name, data[name]);
73 this.register(name, data[name]);
74 } else {
74 } else {
75 if (!(service instanceof Descriptor))
75 if (!(service instanceof Descriptor))
76 service = new Value(service, true);
76 service = new Value(service, true);
77 this._services[name] = service;
77 this._services[name] = service;
78 }
78 }
79 return this;
79 return this;
80 },
80 },
81
81
82 onDispose: function (callback) {
82 onDispose: function (callback) {
83 if (!(callback instanceof Function))
83 if (!(callback instanceof Function))
84 throw new Error("The callback must be a function");
84 throw new Error("The callback must be a function");
85 this._cleanup.push(callback);
85 this._cleanup.push(callback);
86 },
86 },
87
87
88 dispose: function () {
88 dispose: function () {
89 if (this._cleanup) {
89 if (this._cleanup) {
90 for (var i = 0; i < this._cleanup.length; i++)
90 for (var i = 0; i < this._cleanup.length; i++)
91 this._cleanup[i].call(null);
91 this._cleanup[i].call(null);
92 this._cleanup = null;
92 this._cleanup = null;
93 }
93 }
94 },
94 },
95
95
96 /**
96 /**
97 * @param{String|Object} config
97 * @param{String|Object} config
98 * The configuration of the contaier. Can be either a string or an object,
98 * The configuration of the contaier. Can be either a string or an object,
99 * if the configuration is an object it's treated as a collection of
99 * if the configuration is an object it's treated as a collection of
100 * services which will be registed in the contaier.
100 * services which will be registed in the contaier.
101 *
101 *
102 * @param{Function} opts.contextRequire
102 * @param{Function} opts.contextRequire
103 * The function which will be used to load a configuration or types for services.
103 * The function which will be used to load a configuration or types for services.
104 *
104 *
105 */
105 */
106 configure: function (config, opts) {
106 configure: function (config, opts) {
107 var p, me = this,
107 var p, me = this,
108 contextRequire = (opts && opts.contextRequire);
108 contextRequire = (opts && opts.contextRequire);
109
109
110 if (typeof (config) === "string") {
110 if (typeof (config) === "string") {
111 p = new Deferred();
111 p = new Deferred();
112 if (!contextRequire) {
112 if (!contextRequire) {
113 var shim = [config, new Uuid()].join(config.indexOf("/") != -1 ? "-" : "/");
113 var shim = [config, Uuid()].join(config.indexOf("/") != -1 ? "-" : "/");
114 define(shim, ["require", config], function (ctx, data) {
114 define(shim, ["require", config], function (ctx, data) {
115 p.resolve([data, {
115 p.resolve([data, {
116 contextRequire: ctx
116 contextRequire: ctx
117 }]);
117 }]);
118 });
118 });
119 require([shim]);
119 require([shim]);
120 } else {
120 } else {
121 // TODO how to get correct contextRequire for the relative config module?
121 // TODO how to get correct contextRequire for the relative config module?
122 contextRequire([config], function (data) {
122 contextRequire([config], function (data) {
123 p.resolve([data, {
123 p.resolve([data, {
124 contextRequire: contextRequire
124 contextRequire: contextRequire
125 }]);
125 }]);
126 });
126 });
127 }
127 }
128
128
129 return p.then(function (args) {
129 return p.then(function (args) {
130 return me._configure.apply(me, args);
130 return me._configure.apply(me, args);
131 });
131 });
132 } else {
132 } else {
133 return me._configure(config, opts);
133 return me._configure(config, opts);
134 }
134 }
135 },
135 },
136
136
137 createChildContainer: function () {
137 createChildContainer: function () {
138 return new Container(this);
138 return new Container(this);
139 },
139 },
140
140
141 has: function (id) {
141 has: function (id) {
142 return id in this._cache;
142 return id in this._cache;
143 },
143 },
144
144
145 get: function (id) {
145 get: function (id) {
146 return this._cache[id];
146 return this._cache[id];
147 },
147 },
148
148
149 store: function (id, value) {
149 store: function (id, value) {
150 return (this._cache[id] = value);
150 return (this._cache[id] = value);
151 },
151 },
152
152
153 _configure: function (data, opts) {
153 _configure: function (data, opts) {
154 var typemap = {},
154 var typemap = {},
155 d = new Deferred(),
155 d = new Deferred(),
156 me = this,
156 me = this,
157 p,
157 p,
158 contextRequire = (opts && opts.contextRequire) || require;
158 contextRequire = (opts && opts.contextRequire) || require;
159
159
160 var services = {};
160 var services = {};
161
161
162 for (p in data) {
162 for (p in data) {
163 var service = me._parse(data[p], typemap);
163 var service = me._parse(data[p], typemap);
164 if (!(service instanceof Descriptor))
164 if (!(service instanceof Descriptor))
165 service = new Value(service, false);
165 service = new Value(service, false);
166 services[p] = service;
166 services[p] = service;
167 }
167 }
168
168
169 me.register(services);
169 me.register(services);
170
170
171 var names = [];
171 var names = [];
172
172
173 for (p in typemap)
173 for (p in typemap)
174 names.push(p);
174 names.push(p);
175
175
176 if (names.length) {
176 if (names.length) {
177 contextRequire(names, function () {
177 contextRequire(names, function () {
178 for (var i = 0; i < names.length; i++)
178 for (var i = 0; i < names.length; i++)
179 typemap[names[i]] = arguments[i];
179 typemap[names[i]] = arguments[i];
180 d.resolve(me);
180 d.resolve(me);
181 });
181 });
182 } else {
182 } else {
183 d.resolve(me);
183 d.resolve(me);
184 }
184 }
185 return d.promise;
185 return d.promise;
186 },
186 },
187
187
188 _parse: function (data, typemap) {
188 _parse: function (data, typemap) {
189 if (safe.isPrimitive(data) || data instanceof Descriptor)
189 if (safe.isPrimitive(data) || data instanceof Descriptor)
190 return data;
190 return data;
191 if (data.$dependency)
191 if (data.$dependency)
192 return new Reference(
192 return new Reference(
193 data.$dependency,
193 data.$dependency,
194 data.lazy,
194 data.lazy,
195 data.optional,
195 data.optional,
196 data["default"],
196 data["default"],
197 data.services && this._parseObject(data.services, typemap));
197 data.services && this._parseObject(data.services, typemap));
198 if (data.$value) {
198 if (data.$value) {
199 var raw = !data.parse;
199 var raw = !data.parse;
200 return new Value(raw ? data.$value : this._parse(
200 return new Value(raw ? data.$value : this._parse(
201 data.$value,
201 data.$value,
202 typemap), raw);
202 typemap), raw);
203 }
203 }
204 if (data.$type || data.$factory)
204 if (data.$type || data.$factory)
205 return this._parseService(data, typemap);
205 return this._parseService(data, typemap);
206 if (data instanceof Array)
206 if (data instanceof Array)
207 return this._parseArray(data, typemap);
207 return this._parseArray(data, typemap);
208
208
209 return this._parseObject(data, typemap);
209 return this._parseObject(data, typemap);
210 },
210 },
211
211
212 _parseService: function (data, typemap) {
212 _parseService: function (data, typemap) {
213 var me = this,
213 var me = this,
214 opts = {
214 opts = {
215 owner: this
215 owner: this
216 };
216 };
217 if (data.$type) {
217 if (data.$type) {
218
218
219 opts.type = data.$type;
219 opts.type = data.$type;
220
220
221 if (typeof (data.$type) === "string") {
221 if (typeof (data.$type) === "string") {
222 typemap[data.$type] = null;
222 typemap[data.$type] = null;
223 opts.typeMap = typemap;
223 opts.typeMap = typemap;
224 }
224 }
225 }
225 }
226
226
227 if (data.$factory)
227 if (data.$factory)
228 opts.factory = data.$factory;
228 opts.factory = data.$factory;
229
229
230 if (data.services)
230 if (data.services)
231 opts.services = me._parseObject(data.services, typemap);
231 opts.services = me._parseObject(data.services, typemap);
232 if (data.inject)
232 if (data.inject)
233 opts.inject = data.inject instanceof Array ? data.inject.map(function (x) {
233 opts.inject = data.inject instanceof Array ? data.inject.map(function (x) {
234 return me._parseObject(x, typemap);
234 return me._parseObject(x, typemap);
235 }) : me._parseObject(data.inject, typemap);
235 }) : me._parseObject(data.inject, typemap);
236 if (data.params)
236 if (data.params)
237 opts.params = me._parse(data.params, typemap);
237 opts.params = me._parse(data.params, typemap);
238
238
239 if (data.activation) {
239 if (data.activation) {
240 if (typeof (data.activation) === "string") {
240 if (typeof (data.activation) === "string") {
241 switch (data.activation.toLowerCase()) {
241 switch (data.activation.toLowerCase()) {
242 case "singleton":
242 case "singleton":
243 opts.activation = Service.SINGLETON;
243 opts.activation = Service.SINGLETON;
244 break;
244 break;
245 case "container":
245 case "container":
246 opts.activation = Service.CONTAINER;
246 opts.activation = Service.CONTAINER;
247 break;
247 break;
248 case "hierarchy":
248 case "hierarchy":
249 opts.activation = Service.HIERARCHY;
249 opts.activation = Service.HIERARCHY;
250 break;
250 break;
251 case "context":
251 case "context":
252 opts.activation = Service.CONTEXT;
252 opts.activation = Service.CONTEXT;
253 break;
253 break;
254 case "call":
254 case "call":
255 opts.activation = Service.CALL;
255 opts.activation = Service.CALL;
256 break;
256 break;
257 default:
257 default:
258 throw new Error("Unknown activation type: " +
258 throw new Error("Unknown activation type: " +
259 data.activation);
259 data.activation);
260 }
260 }
261 } else {
261 } else {
262 opts.activation = Number(data.activation);
262 opts.activation = Number(data.activation);
263 }
263 }
264 }
264 }
265
265
266 if (data.cleanup)
266 if (data.cleanup)
267 opts.cleanup = data.cleanup;
267 opts.cleanup = data.cleanup;
268
268
269 return new Service(opts);
269 return new Service(opts);
270 },
270 },
271
271
272 _parseObject: function (data, typemap) {
272 _parseObject: function (data, typemap) {
273 if (data.constructor &&
273 if (data.constructor &&
274 data.constructor.prototype !== Object.prototype)
274 data.constructor.prototype !== Object.prototype)
275 return new Value(data, true);
275 return new Value(data, true);
276
276
277 var o = {};
277 var o = {};
278
278
279 for (var p in data)
279 for (var p in data)
280 o[p] = this._parse(data[p], typemap);
280 o[p] = this._parse(data[p], typemap);
281
281
282 return o;
282 return o;
283 },
283 },
284
284
285 _parseArray: function (data, typemap) {
285 _parseArray: function (data, typemap) {
286 if (data.constructor &&
286 if (data.constructor &&
287 data.constructor.prototype !== Array.prototype)
287 data.constructor.prototype !== Array.prototype)
288 return new Value(data, true);
288 return new Value(data, true);
289
289
290 var me = this;
290 var me = this;
291 return data.map(function (x) {
291 return data.map(function (x) {
292 return me._parse(x, typemap);
292 return me._parse(x, typemap);
293 });
293 });
294 }
294 }
295
295
296 });
296 });
297
297
298 return Container;
298 return Container;
299 }); No newline at end of file
299 });
@@ -1,116 +1,50
1 define(["../text/format"], function (format) {
1 define(["./TraceSource"], function (TraceSource) {
2 'use strict';
2 'use strict';
3
3
4 var listeners = [];
4 return {
5 var channels = {};
6
7 var Trace = function (name) {
8 this.name = name;
9 this._subscribers = [];
10 };
11
12 Trace.prototype.debug = function () {
13 if (Trace.level >= 4)
14 this.notify("debug", format.apply(null, arguments));
15 };
16
17 Trace.prototype.log = function () {
18 if (Trace.level >= 3)
19 this.notify("log", format.apply(null, arguments));
20 };
21
22 Trace.prototype.warn = function () {
23 if (Trace.level >= 2)
24 this.notify("warn", format.apply(null, arguments));
25
26 };
27
5
28 Trace.prototype.error = function () {
6 on: function (filter, cb) {
29 if (Trace.level >= 1)
7 if (arguments.length == 1) {
30 this.notify("error", format.apply(null, arguments));
8 cb = filter;
31 };
9 filter = undefined;
32
10 }
33 Trace.prototype.notify = function (name, msg) {
11 var test;
34 var me = this;
12 if (filter instanceof RegExp) {
35 me._subscribers.forEach(function (cb) {
13 test = function (chId) {
36 cb(me, name, msg);
14 return filter.test(chId);
37 });
15 };
38 };
16 } else if (filter instanceof Function) {
39
17 test = filter;
40 Trace.prototype.subscribe = function (cb) {
18 } else if (filter) {
41 this._subscribers.push(cb);
19 test = function (chId) {
42 };
20 return chId == filter;
43
21 };
44 Trace.prototype.toString = function () {
22 }
45 return this.name;
46 };
47
48 Trace.createChannel = function (type, name, cb) {
49 var chId = name;
50 if (channels[chId])
51 return channels[chId];
52
53 var channel = new type(chId);
54 channels[chId] = channel;
55
56 Trace._onNewChannel(chId, channel);
57 cb(channel);
58 };
59
23
60 Trace._onNewChannel = function (chId, ch) {
24 if (test) {
61 listeners.forEach(function (listener) {
25 TraceSource.on(function (source) {
62 listener(chId, ch);
26 if (test(source.id))
63 });
27 source.on(cb);
64 };
28 });
65
29 } else {
66 Trace.on = function (filter, cb) {
30 TraceSource.on(function (source) {
67 if (arguments.length == 1) {
31 source.on(cb);
68 cb = filter;
32 });
69 filter = undefined;
33 }
70 }
34 },
71 var d, test;
72 if (filter instanceof RegExp) {
73 test = function (chId) {
74 return filter.test(chId);
75 };
76 } else if (filter instanceof Function) {
77 test = filter;
78 } else if (filter) {
79 test = function (chId) {
80 return chId == filter;
81 };
82 }
83
35
84 if (test) {
36 load: function (id, require, cb) {
85 d = function(chId, ch) {
37 if (id) {
86 if(test(chId))
38 cb(TraceSource.get(id));
87 ch.subscribe(cb);
39 } else if (require.module && require.module.mid) {
88 };
40 cb(TraceSource.get(require.module.mid));
89 } else {
41 } else {
90 d = function(chId, ch) {
42 require(['module'], function (module) {
91 ch.subscribe(cb);
43 cb(TraceSource.get(module && module.id));
92 };
44 });
93 }
45 }
94 listeners.push(d);
46 },
95
96 for(var chId in channels)
97 d(chId,channels[chId]);
98 };
99
47
100 Trace.load = function (id, require, cb) {
48 dynamic: true,
101 if (id)
102 Trace.createChannel(Trace, id, cb);
103 else if (require.module && require.module.mid)
104 Trace.createChannel(Trace, require.module.mid, cb);
105 else
106 require(['module'], function (module) {
107 Trace.createChannel(Trace, module && module.id, cb);
108 });
109 };
49 };
110
111 Trace.dynamic = true;
112
113 Trace.level = 4;
114
115 return Trace;
116 }); No newline at end of file
50 });
@@ -1,101 +1,101
1 define(
1 define(
2 [],
2 [],
3 function() {
3 function() {
4 var map = {
4 var map = {
5 "\\{" : "&curlopen;",
5 "\\{" : "&curlopen;",
6 "\\}" : "&curlclose;",
6 "\\}" : "&curlclose;",
7 "&" : "&amp;",
7 "&" : "&amp;",
8 "\\:" : "&colon;"
8 "\\:" : "&colon;"
9 };
9 };
10
10
11 var rev = {
11 var rev = {
12 curlopen : "{",
12 curlopen : "{",
13 curlclose : "}",
13 curlclose : "}",
14 amp : "&",
14 amp : "&",
15 colon : ":"
15 colon : ":"
16 };
16 };
17
17
18 var espaceString = function(s) {
18 var espaceString = function(s) {
19 if (!s)
19 if (!s)
20 return s;
20 return s;
21 return "'" + s.replace(/('|\\)/g, "\\$1") + "'";
21 return "'" + s.replace(/('|\\)/g, "\\$1").replace("\n","\\n") + "'";
22 };
22 };
23
23
24 var encode = function(s) {
24 var encode = function(s) {
25 if (!s)
25 if (!s)
26 return s;
26 return s;
27 return s.replace(/\\{|\\}|&|\\:/g, function(m) {
27 return s.replace(/\\{|\\}|&|\\:|\n/g, function(m) {
28 return map[m] || m;
28 return map[m] || m;
29 });
29 });
30 };
30 };
31
31
32 var decode = function(s) {
32 var decode = function(s) {
33 if (!s)
33 if (!s)
34 return s;
34 return s;
35 return s.replace(/&(\w+);/g, function(m, $1) {
35 return s.replace(/&(\w+);/g, function(m, $1) {
36 return rev[$1] || m;
36 return rev[$1] || m;
37 });
37 });
38 };
38 };
39
39
40 var subst = function(s) {
40 var subst = function(s) {
41 var i = s.indexOf(":"), name, pattern;
41 var i = s.indexOf(":"), name, pattern;
42 if (i >= 0) {
42 if (i >= 0) {
43 name = s.substr(0, i);
43 name = s.substr(0, i);
44 pattern = s.substr(i + 1);
44 pattern = s.substr(i + 1);
45 } else {
45 } else {
46 name = s;
46 name = s;
47 }
47 }
48
48
49 if (pattern)
49 if (pattern)
50 return [
50 return [
51 espaceString(decode(name)),
51 espaceString(decode(name)),
52 espaceString(decode(pattern)) ];
52 espaceString(decode(pattern)) ];
53 else
53 else
54 return [ espaceString(decode(name)) ];
54 return [ espaceString(decode(name)) ];
55 };
55 };
56
56
57 var compile = function(str) {
57 var compile = function(str) {
58 if (!str)
58 if (!str)
59 return function() {};
59 return function() {};
60
60
61 var chunks = encode(str).split("{"), chunk;
61 var chunks = encode(str).split("{"), chunk;
62
62
63 var code = [ "var result=[];" ];
63 var code = [ "var result=[];" ];
64
64
65 for (var i = 0; i < chunks.length; i++) {
65 for (var i = 0; i < chunks.length; i++) {
66 chunk = chunks[i];
66 chunk = chunks[i];
67
67
68 if (i === 0) {
68 if (i === 0) {
69 if (chunk)
69 if (chunk)
70 code.push("result.push(" + espaceString(decode(chunk)) +
70 code.push("result.push(" + espaceString(decode(chunk)) +
71 ");");
71 ");");
72 } else {
72 } else {
73 var len = chunk.indexOf("}");
73 var len = chunk.indexOf("}");
74 if (len < 0)
74 if (len < 0)
75 throw new Error("Unbalanced substitution #" + i);
75 throw new Error("Unbalanced substitution #" + i);
76
76
77 code.push("result.push(subst(" +
77 code.push("result.push(subst(" +
78 subst(chunk.substr(0, len)).join(",") + "));");
78 subst(chunk.substr(0, len)).join(",") + "));");
79 if (chunk.length > len + 1)
79 if (chunk.length > len + 1)
80 code.push("result.push(" +
80 code.push("result.push(" +
81 espaceString(decode(chunk.substr(len + 1))) + ");");
81 espaceString(decode(chunk.substr(len + 1))) + ");");
82 }
82 }
83 }
83 }
84
84
85 code.push("return result.join('');");
85 code.push("return result.join('');");
86
86
87 /* jshint -W054 */
87 /* jshint -W054 */
88 return new Function("subst", code.join("\n"));
88 return new Function("subst", code.join("\n"));
89 };
89 };
90
90
91 var cache = {};
91 var cache = {};
92
92
93 return function(template) {
93 return function(template) {
94 var compiled = cache[template];
94 var compiled = cache[template];
95 if (!compiled) {
95 if (!compiled) {
96 compiled = compile(template);
96 compiled = compile(template);
97 cache[template] = compiled;
97 cache[template] = compiled;
98 }
98 }
99 return compiled;
99 return compiled;
100 };
100 };
101 }); No newline at end of file
101 });
@@ -1,280 +1,282
1 // Typescript port of the uuid.js
1 // Typescript port of the uuid.js
2 // Copyright (c) 2018 Sergey Smirnov
2 // Copyright (c) 2018 Sergey Smirnov
3 // BSD-2-Clause License https://opensource.org/licenses/BSD-2-Clause
3 // BSD-2-Clause License https://opensource.org/licenses/BSD-2-Clause
4 //
4 //
5 // uuid.js
5 // uuid.js
6 // Copyright (c) 2010-2012 Robert Kieffer
6 // Copyright (c) 2010-2012 Robert Kieffer
7 // MIT License - http://opensource.org/licenses/mit-license.php
7 // MIT License - http://opensource.org/licenses/mit-license.php
8
8
9 declare var window: any;
10
9 let _window : any = 'undefined' !== typeof window ? window : null;
11 let _window : any = 'undefined' !== typeof window ? window : null;
10
12
11 // Unique ID creation requires a high quality random # generator. We
13 // Unique ID creation requires a high quality random # generator. We
12 // feature
14 // feature
13 // detect to determine the best RNG source, normalizing to a function
15 // detect to determine the best RNG source, normalizing to a function
14 // that
16 // that
15 // returns 128-bits of randomness, since that's what's usually required
17 // returns 128-bits of randomness, since that's what's usually required
16 let _rng;
18 let _rng;
17
19
18 function setupBrowser() {
20 function setupBrowser() {
19 // Allow for MSIE11 msCrypto
21 // Allow for MSIE11 msCrypto
20 let _crypto = _window.crypto || _window.msCrypto;
22 let _crypto = _window.crypto || _window.msCrypto;
21
23
22 if (!_rng && _crypto && _crypto.getRandomValues) {
24 if (!_rng && _crypto && _crypto.getRandomValues) {
23 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
25 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
24 //
26 //
25 // Moderately fast, high quality
27 // Moderately fast, high quality
26 try {
28 try {
27 let _rnds8 = new Uint8Array(16);
29 let _rnds8 = new Uint8Array(16);
28 _rng = function whatwgRNG() {
30 _rng = function whatwgRNG() {
29 _crypto.getRandomValues(_rnds8);
31 _crypto.getRandomValues(_rnds8);
30 return _rnds8;
32 return _rnds8;
31 };
33 };
32 _rng();
34 _rng();
33 } catch (e) { /**/ }
35 } catch (e) { /**/ }
34 }
36 }
35
37
36 if (!_rng) {
38 if (!_rng) {
37 // Math.random()-based (RNG)
39 // Math.random()-based (RNG)
38 //
40 //
39 // If all else fails, use Math.random(). It's fast, but is of
41 // If all else fails, use Math.random(). It's fast, but is of
40 // unspecified
42 // unspecified
41 // quality.
43 // quality.
42 let _rnds = new Array(16);
44 let _rnds = new Array(16);
43 _rng = function () {
45 _rng = function () {
44 for (var i = 0, r; i < 16; i++) {
46 for (var i = 0, r; i < 16; i++) {
45 if ((i & 0x03) === 0) {
47 if ((i & 0x03) === 0) {
46 r = Math.random() * 0x100000000;
48 r = Math.random() * 0x100000000;
47 }
49 }
48 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
50 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
49 }
51 }
50
52
51 return _rnds;
53 return _rnds;
52 };
54 };
53 if ('undefined' !== typeof console && console.warn) {
55 if ('undefined' !== typeof console && console.warn) {
54 console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
56 console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
55 }
57 }
56 }
58 }
57 }
59 }
58
60
59 function setupNode() {
61 function setupNode() {
60 // Node.js crypto-based RNG -
62 // Node.js crypto-based RNG -
61 // http://nodejs.org/docs/v0.6.2/api/crypto.html
63 // http://nodejs.org/docs/v0.6.2/api/crypto.html
62 //
64 //
63 // Moderately fast, high quality
65 // Moderately fast, high quality
64 if ('function' === typeof require) {
66 if ('function' === typeof require) {
65 try {
67 try {
66 let _rb = require('crypto').randomBytes;
68 let _rb = require('crypto').randomBytes;
67 _rng = _rb && function () {
69 _rng = _rb && function () {
68 return _rb(16);
70 return _rb(16);
69 };
71 };
70 _rng();
72 _rng();
71 } catch (e) { /**/ }
73 } catch (e) { /**/ }
72 }
74 }
73 }
75 }
74
76
75 if (_window) {
77 if (_window) {
76 setupBrowser();
78 setupBrowser();
77 } else {
79 } else {
78 setupNode();
80 setupNode();
79 }
81 }
80
82
81 // Buffer class to use
83 // Buffer class to use
82 let BufferClass = ('function' === typeof Buffer) ? Buffer : Array;
84 let BufferClass = ('function' === typeof Buffer) ? Buffer : Array;
83
85
84 // Maps for number <-> hex string conversion
86 // Maps for number <-> hex string conversion
85 let _byteToHex = [];
87 let _byteToHex = [];
86 let _hexToByte = {};
88 let _hexToByte = {};
87 for (let i = 0; i < 256; i++) {
89 for (let i = 0; i < 256; i++) {
88 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
90 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
89 _hexToByte[_byteToHex[i]] = i;
91 _hexToByte[_byteToHex[i]] = i;
90 }
92 }
91
93
92 // **`parse()` - Parse a UUID into it's component bytes**
94 // **`parse()` - Parse a UUID into it's component bytes**
93 function parse(s, buf?, offset?) : Array<string> {
95 function parse(s, buf?, offset?) : Array<string> {
94 let i = (buf && offset) || 0, ii = 0;
96 let i = (buf && offset) || 0, ii = 0;
95
97
96 buf = buf || [];
98 buf = buf || [];
97 s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) {
99 s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) {
98 if (ii < 16) { // Don't overflow!
100 if (ii < 16) { // Don't overflow!
99 buf[i + ii++] = _hexToByte[oct];
101 buf[i + ii++] = _hexToByte[oct];
100 }
102 }
101 });
103 });
102
104
103 // Zero out remaining bytes if string was short
105 // Zero out remaining bytes if string was short
104 while (ii < 16) {
106 while (ii < 16) {
105 buf[i + ii++] = 0;
107 buf[i + ii++] = 0;
106 }
108 }
107
109
108 return buf;
110 return buf;
109 }
111 }
110
112
111 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
113 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
112 function unparse(buf, offset?) : string {
114 function unparse(buf, offset?) : string {
113 let i = offset || 0, bth = _byteToHex;
115 let i = offset || 0, bth = _byteToHex;
114 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
116 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
115 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' +
117 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' +
116 bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] +
118 bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] +
117 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] +
119 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] +
118 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
120 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
119 }
121 }
120
122
121 // **`v1()` - Generate time-based UUID**
123 // **`v1()` - Generate time-based UUID**
122 //
124 //
123 // Inspired by https://github.com/LiosK/UUID.js
125 // Inspired by https://github.com/LiosK/UUID.js
124 // and http://docs.python.org/library/uuid.html
126 // and http://docs.python.org/library/uuid.html
125
127
126 // random #'s we need to init node and clockseq
128 // random #'s we need to init node and clockseq
127 let _seedBytes = _rng();
129 let _seedBytes = _rng();
128
130
129 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
131 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
130 // 1)
132 // 1)
131 let _nodeId = [
133 let _nodeId = [
132 _seedBytes[0] | 0x01,
134 _seedBytes[0] | 0x01,
133 _seedBytes[1],
135 _seedBytes[1],
134 _seedBytes[2],
136 _seedBytes[2],
135 _seedBytes[3],
137 _seedBytes[3],
136 _seedBytes[4],
138 _seedBytes[4],
137 _seedBytes[5]
139 _seedBytes[5]
138 ];
140 ];
139
141
140 // Per 4.2.2, randomize (14 bit) clockseq
142 // Per 4.2.2, randomize (14 bit) clockseq
141 let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
143 let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
142
144
143 // Previous uuid creation time
145 // Previous uuid creation time
144 let _lastMSecs = 0, _lastNSecs = 0;
146 let _lastMSecs = 0, _lastNSecs = 0;
145
147
146 // See https://github.com/broofa/node-uuid for API details
148 // See https://github.com/broofa/node-uuid for API details
147 function v1(options?, buf?, offset?) : string {
149 function v1(options?, buf?, offset?) : string {
148 let i = buf && offset || 0;
150 let i = buf && offset || 0;
149 let b = buf || [];
151 let b = buf || [];
150
152
151 options = options || {};
153 options = options || {};
152
154
153 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
155 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
154
156
155 // UUID timestamps are 100 nano-second units since the Gregorian
157 // UUID timestamps are 100 nano-second units since the Gregorian
156 // epoch,
158 // epoch,
157 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
159 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
158 // time is handled internally as 'msecs' (integer milliseconds) and
160 // time is handled internally as 'msecs' (integer milliseconds) and
159 // 'nsecs'
161 // 'nsecs'
160 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
162 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
161 // 00:00.
163 // 00:00.
162 let msecs = (options.msecs != null) ? options.msecs : new Date()
164 let msecs = (options.msecs != null) ? options.msecs : new Date()
163 .getTime();
165 .getTime();
164
166
165 // Per 4.2.1.2, use count of uuid's generated during the current
167 // Per 4.2.1.2, use count of uuid's generated during the current
166 // clock
168 // clock
167 // cycle to simulate higher resolution clock
169 // cycle to simulate higher resolution clock
168 let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
170 let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
169
171
170 // Time since last uuid creation (in msecs)
172 // Time since last uuid creation (in msecs)
171 let dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
173 let dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
172
174
173 // Per 4.2.1.2, Bump clockseq on clock regression
175 // Per 4.2.1.2, Bump clockseq on clock regression
174 if (dt < 0 && options.clockseq == null) {
176 if (dt < 0 && options.clockseq == null) {
175 clockseq = clockseq + 1 & 0x3fff;
177 clockseq = clockseq + 1 & 0x3fff;
176 }
178 }
177
179
178 // Reset nsecs if clock regresses (new clockseq) or we've moved onto
180 // Reset nsecs if clock regresses (new clockseq) or we've moved onto
179 // a new
181 // a new
180 // time interval
182 // time interval
181 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
183 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
182 nsecs = 0;
184 nsecs = 0;
183 }
185 }
184
186
185 // Per 4.2.1.2 Throw error if too many uuids are requested
187 // Per 4.2.1.2 Throw error if too many uuids are requested
186 if (nsecs >= 10000) {
188 if (nsecs >= 10000) {
187 throw new Error(
189 throw new Error(
188 'uuid.v1(): Can\'t create more than 10M uuids/sec');
190 'uuid.v1(): Can\'t create more than 10M uuids/sec');
189 }
191 }
190
192
191 _lastMSecs = msecs;
193 _lastMSecs = msecs;
192 _lastNSecs = nsecs;
194 _lastNSecs = nsecs;
193 _clockseq = clockseq;
195 _clockseq = clockseq;
194
196
195 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
197 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
196 msecs += 12219292800000;
198 msecs += 12219292800000;
197
199
198 // `time_low`
200 // `time_low`
199 let tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
201 let tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
200 b[i++] = tl >>> 24 & 0xff;
202 b[i++] = tl >>> 24 & 0xff;
201 b[i++] = tl >>> 16 & 0xff;
203 b[i++] = tl >>> 16 & 0xff;
202 b[i++] = tl >>> 8 & 0xff;
204 b[i++] = tl >>> 8 & 0xff;
203 b[i++] = tl & 0xff;
205 b[i++] = tl & 0xff;
204
206
205 // `time_mid`
207 // `time_mid`
206 let tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
208 let tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
207 b[i++] = tmh >>> 8 & 0xff;
209 b[i++] = tmh >>> 8 & 0xff;
208 b[i++] = tmh & 0xff;
210 b[i++] = tmh & 0xff;
209
211
210 // `time_high_and_version`
212 // `time_high_and_version`
211 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
213 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
212 b[i++] = tmh >>> 16 & 0xff;
214 b[i++] = tmh >>> 16 & 0xff;
213
215
214 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
216 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
215 b[i++] = clockseq >>> 8 | 0x80;
217 b[i++] = clockseq >>> 8 | 0x80;
216
218
217 // `clock_seq_low`
219 // `clock_seq_low`
218 b[i++] = clockseq & 0xff;
220 b[i++] = clockseq & 0xff;
219
221
220 // `node`
222 // `node`
221 let node = options.node || _nodeId;
223 let node = options.node || _nodeId;
222 for (let n = 0; n < 6; n++) {
224 for (let n = 0; n < 6; n++) {
223 b[i + n] = node[n];
225 b[i + n] = node[n];
224 }
226 }
225
227
226 return buf ? buf : unparse(b);
228 return buf ? buf : unparse(b);
227 }
229 }
228
230
229 // **`v4()` - Generate random UUID**
231 // **`v4()` - Generate random UUID**
230
232
231 // See https://github.com/broofa/node-uuid for API details
233 // See https://github.com/broofa/node-uuid for API details
232 function v4(options?, buf?, offset?) : string {
234 function v4(options?, buf?, offset?) : string {
233 // Deprecated - 'format' argument, as supported in v1.2
235 // Deprecated - 'format' argument, as supported in v1.2
234 let i = buf && offset || 0;
236 let i = buf && offset || 0;
235
237
236 if (typeof (options) === 'string') {
238 if (typeof (options) === 'string') {
237 buf = (options === 'binary') ? new BufferClass(16) : null;
239 buf = (options === 'binary') ? new BufferClass(16) : null;
238 options = null;
240 options = null;
239 }
241 }
240 options = options || {};
242 options = options || {};
241
243
242 let rnds = options.random || (options.rng || _rng)();
244 let rnds = options.random || (options.rng || _rng)();
243
245
244 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
246 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
245 rnds[6] = (rnds[6] & 0x0f) | 0x40;
247 rnds[6] = (rnds[6] & 0x0f) | 0x40;
246 rnds[8] = (rnds[8] & 0x3f) | 0x80;
248 rnds[8] = (rnds[8] & 0x3f) | 0x80;
247
249
248 // Copy bytes to buffer, if provided
250 // Copy bytes to buffer, if provided
249 if (buf) {
251 if (buf) {
250 for (let ii = 0; ii < 16; ii++) {
252 for (let ii = 0; ii < 16; ii++) {
251 buf[i + ii] = rnds[ii];
253 buf[i + ii] = rnds[ii];
252 }
254 }
253 }
255 }
254
256
255 return buf || unparse(rnds);
257 return buf || unparse(rnds);
256 }
258 }
257
259
258 // Export public API
260 // Export public API
259 const empty = "00000000-0000-0000-0000-000000000000";
261 const empty = "00000000-0000-0000-0000-000000000000";
260
262
261 interface uuid {
263 interface uuid {
262 (options?, buf?, offset?) : string;
264 (options?, buf?, offset?) : string;
263 v1(options?, buf?, offset?) : string;
265 v1(options?, buf?, offset?) : string;
264 v4(options?, buf?, offset?) : string;
266 v4(options?, buf?, offset?) : string;
265 readonly empty: string;
267 readonly empty: string;
266 parse(s, buf?, offset?) : Array<string>;
268 parse(s, buf?, offset?) : Array<string>;
267 unparse(buf, offset?) : string;
269 unparse(buf, offset?) : string;
268 }
270 }
269
271
270 export = <uuid>(() =>{
272 export = <uuid>(() =>{
271 var f : any = function(options?, buf?, offset?) : string {
273 var f : any = function(options?, buf?, offset?) : string {
272 return v4(options, buf, offset);
274 return v4(options, buf, offset);
273 };
275 };
274 f.v1 = v1;
276 f.v1 = v1;
275 f.v4 = v4;
277 f.v4 = v4;
276 f.empty = empty;
278 f.empty = empty;
277 f.parse = parse;
279 f.parse = parse;
278 f.unparse = unparse;
280 f.unparse = unparse;
279 return f;
281 return f;
280 })(); No newline at end of file
282 })();
@@ -1,1 +1,2
1 define(["./dummy", "./example"]); No newline at end of file
1 define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]);
2 //define(["./CancellationTests"]); No newline at end of file
@@ -1,12 +1,15
1 {
1 {
2 "compilerOptions": {
2 "compilerOptions": {
3 "target": "es5",
3 "target": "es5",
4 "module": "amd",
4 "module": "amd",
5 "sourceMap": true,
5 "sourceMap": true,
6 "outDir" : "build/dist",
6 "outDir" : "build/dist",
7 "declaration": true
7 "declaration": true,
8 "lib": [
9 "ES2015"
10 ]
8 },
11 },
9 "include" : [
12 "include" : [
10 "src/ts/**/*.ts"
13 "src/ts/**/*.ts"
11 ]
14 ]
12 } No newline at end of file
15 }
@@ -1,12 +1,15
1 {
1 {
2 "compilerOptions": {
2 "compilerOptions": {
3 "target": "es5",
3 "target": "es5",
4 "module": "amd",
4 "module": "amd",
5 "sourceMap": true,
5 "sourceMap": true,
6 "outDir" : "build/test",
6 "outDir" : "build/test",
7 "moduleResolution": "node"
7 "moduleResolution": "node",
8 "lib": [
9 "ES2015"
10 ]
8 },
11 },
9 "include" : [
12 "include" : [
10 "test/ts/**/*.ts"
13 "test/ts/**/*.ts"
11 ]
14 ]
12 } No newline at end of file
15 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now