diff --git a/Libraries/CustomComponents/Navigator/Navigation/NavigationEvent.js b/Libraries/CustomComponents/Navigator/Navigation/NavigationEvent.js index b6923b4f2..343e1f3e6 100644 --- a/Libraries/CustomComponents/Navigator/Navigation/NavigationEvent.js +++ b/Libraries/CustomComponents/Navigator/Navigation/NavigationEvent.js @@ -1,20 +1,119 @@ /** - * Copyright 2004-present Facebook. All Rights Reserved. + * Copyright (c) 2015, Facebook, Inc. All rights reserved. + * + * Facebook, Inc. (“Facebook”) owns all right, title and interest, including + * all intellectual property and other proprietary rights, in and to the React + * Native CustomComponents software (the “Software”). Subject to your + * compliance with these terms, you are hereby granted a non-exclusive, + * worldwide, royalty-free copyright license to (1) use and copy the Software; + * and (2) reproduce and distribute the Software as part of your own software + * (“Your Software”). Facebook reserves all rights not expressly granted to + * you in this license agreement. + * + * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED. + * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR + * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @providesModule NavigationEvent * @flow */ 'use strict'; +var invariant = require('invariant'); + +class NavigationEventPool { + _list: Array; + + constructor() { + this._list = []; + } + + get(type: String, target: Object, data: any): NavigationEvent { + var event; + if (this._list.length > 0) { + event = this._list.pop(); + event.constructor.call(event, type, target, data); + } else { + event = new NavigationEvent(type, target, data); + } + return event; + } + + put(event: NavigationEvent) { + this._list.push(event); + } +} + +var _navigationEventPool = new NavigationEventPool(); + class NavigationEvent { - type: String; - target: Object; - data: any; + _data: any; + _defaultPrevented: boolean; + _disposed: boolean; + _target: ?Object; + _type: ?String; + + static pool(type: String, target: Object, data: any): NavigationEvent { + return _navigationEventPool.get(type, target, data); + } constructor(type: String, target: Object, data: any) { - this.type = type; - this.target = target; - this.data = data; + this._type = type; + this._target = target; + this._data = data; + this._defaultPrevented = false; + this._disposed = false; + } + + /* $FlowFixMe - get/set properties not yet supported */ + get type(): string { + return this._type; + } + + /* $FlowFixMe - get/set properties not yet supported */ + get target(): Object { + return this._target; + } + + /* $FlowFixMe - get/set properties not yet supported */ + get data(): any { + return this._data; + } + + /* $FlowFixMe - get/set properties not yet supported */ + get defaultPrevented(): boolean { + return this._defaultPrevented; + } + + preventDefault(): void { + this._defaultPrevented = true; + } + + /** + * Dispose the event. + * NavigationEvent shall be disposed after being emitted by + * `NavigationEventEmitter`. + */ + dispose(): void { + invariant(!this._disposed, 'NavigationEvent is already disposed'); + this._disposed = true; + + // Clean up. + this._type = null; + this._target = null; + this._data = null; + this._defaultPrevented = false; + + // Put this back to the pool to reuse the instance. + _navigationEventPool.put(this); } } diff --git a/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationEvent-test.js b/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationEvent-test.js new file mode 100644 index 000000000..8ae24ddb4 --- /dev/null +++ b/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationEvent-test.js @@ -0,0 +1,71 @@ + +/** + * Copyright (c) 2015, Facebook, Inc. All rights reserved. + * + * Facebook, Inc. (“Facebook”) owns all right, title and interest, including + * all intellectual property and other proprietary rights, in and to the React + * Native CustomComponents software (the “Software”). Subject to your + * compliance with these terms, you are hereby granted a non-exclusive, + * worldwide, royalty-free copyright license to (1) use and copy the Software; + * and (2) reproduce and distribute the Software as part of your own software + * (“Your Software”). Facebook reserves all rights not expressly granted to + * you in this license agreement. + * + * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED. + * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR + * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +'use strict'; + +jest + .dontMock('NavigationEvent') + .dontMock('invariant'); + +var NavigationEvent = require('NavigationEvent'); + +describe('NavigationEvent', () => { + it('constructs', () => { + var target = {}; + var event = new NavigationEvent('foo', target, 123); + expect(event.type).toBe('foo'); + expect(event.target).toBe(target); + expect(event.data).toBe(123); + }); + + it('constructs from pool', () => { + var target = {}; + var event = NavigationEvent.pool('foo', target, 123); + expect(event.type).toBe('foo'); + expect(event.target).toBe(target); + expect(event.data).toBe(123); + }); + + it('prevents default', () => { + var event = new NavigationEvent('foo', {}, 123); + expect(event.defaultPrevented).toBe(false); + event.preventDefault(); + expect(event.defaultPrevented).toBe(true); + }); + + it('recycles', () => { + var event1 = NavigationEvent.pool('foo', {}, 123); + event1.dispose(); + expect(event1.type).toBe(null); + expect(event1.data).toBe(null); + expect(event1.target).toBe(null); + + var event2 = NavigationEvent.pool('bar', {}, 456); + expect(event2.type).toBe('bar'); + expect(event2).toBe(event1); + }); +}); + +