'use strict' ; export interface Disposable { dispose ( ) : void ; } export interface Event < T > { ( listener , thisArgs ? , disposables ? ) : Disposable ; } type Listener < T > = [ ( e : T ) => void , any ] | ( ( e : T ) => void ) ; export class Emitter < T > { private static readonly _noop = function ( ) { } ; private _disposed : boolean = false ; private _event ? : Event < T > ; private _deliveryQueue ? : LinkedList < [ Listener < T > , T ] > ; protected listeners ? : LinkedList < Listener < T > > ; /**
     * For the public to allow to subscribe
     * to events from this Emitter
     */ get event ( ) : Event < T > { if ( this . _event == null ) { this . _event = ( listener , thisArgs ? , disposables ? ) => { if ( this . listeners == null ) { this . listeners = new LinkedList ( ) ; } const remove = this . listeners . push ( thisArgs == null ? listener : [ listener , thisArgs ] ) ; const result = { dispose : ( ) => { result . dispose = Emitter . _noop ; if ( ! this . _disposed ) { remove ( ) ; } } , } ; if ( Array . isArray ( disposables ) ) { disposables . push ( result ) ; } return result ; } ; } return this . _event ; } /**
     * To be kept private to fire an event to
     * subscribers
     */ fire ( event ) { if ( this . listeners != null ) { if ( this . _deliveryQueue == null ) { this . _deliveryQueue = new LinkedList ( ) ; } for ( let iter = this . listeners . iterator ( ) , e = iter . next ( ) ; ! e . done ; e = iter . next ( ) ) { this . _deliveryQueue . push ( [ e . value , event ] ) ; } while ( this . _deliveryQueue . size > 0 ) { const [ listener , event ] = this . _deliveryQueue . shift ( ) ! ; try { if ( typeof listener === 'function' ) { listener ( event ) ; } else { listener [ 0 ] . call ( listener [ 1 ] , event ) ; } } catch ( e ) { debugger ; } } } } dispose ( ) { this . listeners ?. clear ( ) ; this . _deliveryQueue ?. clear ( ) ; this . _disposed = true ; } } interface IteratorDefinedResult < T > { readonly done : false ; readonly value : T ; } interface IteratorUndefinedResult { readonly done : true ; readonly value : undefined ; } const FIN = { done : true , value : undefined } ; type IteratorResult < T > = IteratorDefinedResult < T > | IteratorUndefinedResult ; interface Iterator < T > { next ( ) : IteratorResult < T > ; } class Node < E > { static readonly Undefined = new Node < any > ( undefined ) ; element : E ; next : Node < E > ; prev : Node < E > ; constructor ( element ) { this . element = element ; this . next = Node . Undefined ; this . prev = Node . Undefined ; } } class LinkedList < E > { private _first : Node < E > = Node . Undefined ; private _last : Node < E > = Node . Undefined ; private _size : number = 0 ; get size ( ) : number { return this . _size ; } isEmpty ( ) { return this . _first === Node . Undefined ; } clear ( ) { this . _first = Node . Undefined ; this . _last = Node . Undefined ; this . _size = 0 ; } unshift ( element ) { return this . _insert ( element , false ) ; } push ( element ) { return this . _insert ( element , true ) ; } private _insert ( element , atTheEnd ) { const newNode = new Node ( element ) ; if ( this . _first === Node . Undefined ) { this . _first = newNode ; this . _last = newNode ; } else if ( atTheEnd ) { const oldLast = this . _last ; this . _last = newNode ; newNode . prev = oldLast ; oldLast . next = newNode ; } else { const oldFirst = this . _first ; this . _first = newNode ; newNode . next = oldFirst ; oldFirst . prev = newNode ; } this . _size += 1 ; let didRemove = false ; return ( ) => { if ( ! didRemove ) { didRemove = true ; this . _remove ( newNode ) ; } } ; } shift ( ) { if ( this . _first === Node . Undefined ) { return undefined ; } const res = this . _first . element ; this . _remove ( this . _first ) ; return res ; } pop ( ) { if ( this . _last === Node . Undefined ) { return undefined ; } const res = this . _last . element ; this . _remove ( this . _last ) ; return res ; } private _remove ( node ) { if ( node . prev !== Node . Undefined && node . next !== Node . Undefined ) { const anchor = node . prev ; anchor . next = node . next ; node . next . prev = anchor ; } else if ( node . prev === Node . Undefined && node . next === Node . Undefined ) { this . _first = Node . Undefined ; this . _last = Node . Undefined ; } else if ( node . next === Node . Undefined ) { this . _last = this . _last . prev ; this . _last . next = Node . Undefined ; } else if ( node . prev === Node . Undefined ) { this . _first = this . _first . next ; this . _first . prev = Node . Undefined ; } this . _size -= 1 ; } iterator ( ) { let element ; let node = this . _first ; return { next : function ( ) : IteratorResult < E > { if ( node === Node . Undefined ) { return FIN ; } if ( element == null ) { element = { done : false , value : node . element } ; } else { element . value = node . element ; } node = node . next ; return element ; } , } ; } toArray ( ) { const result = [ ] ; for ( let node = this . _first ; node !== Node . Undefined ; node = node . next ) { result . push ( node . element ) ; } return result ; } }