initial commit taken from gitlab.lrz.de

This commit is contained in:
privatereese
2018-08-24 18:09:42 +02:00
parent ae54ed4c48
commit fc05486403
28494 changed files with 2159823 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule ErrorUtils
* @flow
*/
/* eslint-disable strict */
/**
* The particular require runtime that we are using looks for a global
* `ErrorUtils` object and if it exists, then it requires modules with the
* error handler specified via ErrorUtils.setGlobalHandler by calling the
* require function with applyWithGuard. Since the require module is loaded
* before any of the modules, this ErrorUtils must be defined (and the handler
* set) globally before requiring anything.
*
* However, we still want to treat ErrorUtils as a module so that other modules
* that use it aren't just using a global variable, so simply export the global
* variable here. ErrorUtils is originally defined in a file named error-guard.js.
*/
module.exports = global.ErrorUtils;

621
node_modules/react-native/Libraries/vendor/core/Map.js generated vendored Normal file
View File

@@ -0,0 +1,621 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Map
* @preventMunge
* @typechecks
*/
/* eslint-disable no-extend-native, no-shadow-restricted-names */
'use strict';
var _shouldPolyfillES6Collection = require('_shouldPolyfillES6Collection');
var guid = require('guid');
var isNode = require('fbjs/lib/isNode');
var toIterator = require('toIterator');
module.exports = (function(global, undefined) {
// Since our implementation is spec-compliant for the most part we can safely
// delegate to a built-in version if exists and is implemented correctly.
// Firefox had gotten a few implementation details wrong across different
// versions so we guard against that.
if (!_shouldPolyfillES6Collection('Map')) {
return global.Map;
}
/**
* == ES6 Map Collection ==
*
* This module is meant to implement a Map collection as described in chapter
* 23.1 of the ES6 specification.
*
* Map objects are collections of key/value pairs where both the keys and
* values may be arbitrary ECMAScript language values. A distinct key value
* may only occur in one key/value pair within the Map's collection.
*
* https://people.mozilla.org/~jorendorff/es6-draft.html#sec-map-objects
*
* There only two -- rather small -- diviations from the spec:
*
* 1. The use of frozen objects as keys.
* We decided not to allow and simply throw an error. The reason being is
* we store a "hash" on the object for fast access to it's place in the
* internal map entries.
* If this turns out to be a popular use case it's possible to implement by
* overiding `Object.freeze` to store a "hash" property on the object
* for later use with the map.
*
* 2. The `size` property on a map object is a regular property and not a
* computed property on the prototype as described by the spec.
* The reason being is that we simply want to support ES3 environments
* which doesn't implement computed properties.
*
* == Usage ==
*
* var map = new Map(iterable);
*
* map.set(key, value);
* map.get(key); // value
* map.has(key); // true
* map.delete(key); // true
*
* var iterator = map.keys();
* iterator.next(); // {value: key, done: false}
*
* var iterator = map.values();
* iterator.next(); // {value: value, done: false}
*
* var iterator = map.entries();
* iterator.next(); // {value: [key, value], done: false}
*
* map.forEach(function(value, key){ this === thisArg }, thisArg);
*
* map.clear(); // resets map.
*/
/**
* Constants
*/
// Kinds of map iterations 23.1.5.3
var KIND_KEY = 'key';
var KIND_VALUE = 'value';
var KIND_KEY_VALUE = 'key+value';
// In older browsers we can't create a null-prototype object so we have to
// defend against key collisions with built-in methods.
var KEY_PREFIX = '$map_';
// This property will be used as the internal size variable to disallow
// writing and to issue warnings for writings in development.
var SECRET_SIZE_PROP;
if (__DEV__) {
SECRET_SIZE_PROP = '$size' + guid();
}
// In oldIE we use the DOM Node `uniqueID` property to get create the hash.
var OLD_IE_HASH_PREFIX = 'IE_HASH_';
class Map {
/**
* 23.1.1.1
* Takes an `iterable` which is basically any object that implements a
* Symbol.iterator (@@iterator) method. The iterable is expected to be a
* collection of pairs. Each pair is a key/value pair that will be used
* to instantiate the map.
*
* @param {*} iterable
*/
constructor(iterable) {
if (!isObject(this)) {
throw new TypeError('Wrong map object type.');
}
initMap(this);
if (iterable != null) {
var it = toIterator(iterable);
var next;
while (!(next = it.next()).done) {
if (!isObject(next.value)) {
throw new TypeError('Expected iterable items to be pair objects.');
}
this.set(next.value[0], next.value[1]);
}
}
}
/**
* 23.1.3.1
* Clears the map from all keys and values.
*/
clear() {
initMap(this);
}
/**
* 23.1.3.7
* Check if a key exists in the collection.
*
* @param {*} key
* @return {boolean}
*/
has(key) {
var index = getIndex(this, key);
return !!(index != null && this._mapData[index]);
}
/**
* 23.1.3.9
* Adds a key/value pair to the collection.
*
* @param {*} key
* @param {*} value
* @return {map}
*/
set(key, value) {
var index = getIndex(this, key);
if (index != null && this._mapData[index]) {
this._mapData[index][1] = value;
} else {
index = this._mapData.push([
key,
value
]) - 1;
setIndex(this, key, index);
if (__DEV__) {
this[SECRET_SIZE_PROP] += 1;
} else {
this.size += 1;
}
}
return this;
}
/**
* 23.1.3.6
* Gets a value associated with a key in the collection.
*
* @param {*} key
* @return {*}
*/
get(key) {
var index = getIndex(this, key);
if (index == null) {
return undefined;
} else {
return this._mapData[index][1];
}
}
/**
* 23.1.3.3
* Delete a key/value from the collection.
*
* @param {*} key
* @return {boolean} Whether the key was found and deleted.
*/
delete(key) {
var index = getIndex(this, key);
if (index != null && this._mapData[index]) {
setIndex(this, key, undefined);
this._mapData[index] = undefined;
if (__DEV__) {
this[SECRET_SIZE_PROP] -= 1;
} else {
this.size -= 1;
}
return true;
} else {
return false;
}
}
/**
* 23.1.3.4
* Returns an iterator over the key/value pairs (in the form of an Array) in
* the collection.
*
* @return {MapIterator}
*/
entries() {
return new MapIterator(this, KIND_KEY_VALUE);
}
/**
* 23.1.3.8
* Returns an iterator over the keys in the collection.
*
* @return {MapIterator}
*/
keys() {
return new MapIterator(this, KIND_KEY);
}
/**
* 23.1.3.11
* Returns an iterator over the values pairs in the collection.
*
* @return {MapIterator}
*/
values() {
return new MapIterator(this, KIND_VALUE);
}
/**
* 23.1.3.5
* Iterates over the key/value pairs in the collection calling `callback`
* with [value, key, map]. An optional `thisArg` can be passed to set the
* context when `callback` is called.
*
* @param {function} callback
* @param {?object} thisArg
*/
forEach(callback, thisArg) {
if (typeof callback !== 'function') {
throw new TypeError('Callback must be callable.');
}
var boundCallback = callback.bind(thisArg || undefined);
var mapData = this._mapData;
// Note that `mapData.length` should be computed on each iteration to
// support iterating over new items in the map that were added after the
// start of the iteration.
for (var i = 0; i < mapData.length; i++) {
var entry = mapData[i];
if (entry != null) {
boundCallback(entry[1], entry[0], this);
}
}
}
}
// 23.1.3.12
Map.prototype[toIterator.ITERATOR_SYMBOL] = Map.prototype.entries;
class MapIterator {
/**
* 23.1.5.1
* Create a `MapIterator` for a given `map`. While this class is private it
* will create objects that will be passed around publicily.
*
* @param {map} map
* @param {string} kind
*/
constructor(map, kind) {
if (!(isObject(map) && map._mapData)) {
throw new TypeError('Object is not a map.');
}
if ([KIND_KEY, KIND_KEY_VALUE, KIND_VALUE].indexOf(kind) === -1) {
throw new Error('Invalid iteration kind.');
}
this._map = map;
this._nextIndex = 0;
this._kind = kind;
}
/**
* 23.1.5.2.1
* Get the next iteration.
*
* @return {object}
*/
next() {
if (!this instanceof Map) {
throw new TypeError('Expected to be called on a MapIterator.');
}
var map = this._map;
var index = this._nextIndex;
var kind = this._kind;
if (map == null) {
return createIterResultObject(undefined, true);
}
var entries = map._mapData;
while (index < entries.length) {
var record = entries[index];
index += 1;
this._nextIndex = index;
if (record) {
if (kind === KIND_KEY) {
return createIterResultObject(record[0], false);
} else if (kind === KIND_VALUE) {
return createIterResultObject(record[1], false);
} else if (kind) {
return createIterResultObject(record, false);
}
}
}
this._map = undefined;
return createIterResultObject(undefined, true);
}
}
// We can put this in the class definition once we have computed props
// transform.
// 23.1.5.2.2
MapIterator.prototype[toIterator.ITERATOR_SYMBOL] = function() {
return this;
};
/**
* Helper Functions.
*/
/**
* Return an index to map.[[MapData]] array for a given Key.
*
* @param {map} map
* @param {*} key
* @return {?number}
*/
function getIndex(map, key) {
if (isObject(key)) {
var hash = getHash(key);
return map._objectIndex[hash];
} else {
var prefixedKey = KEY_PREFIX + key;
if (typeof key === 'string') {
return map._stringIndex[prefixedKey];
} else {
return map._otherIndex[prefixedKey];
}
}
}
/**
* Setup an index that refer to the key's location in map.[[MapData]].
*
* @param {map} map
* @param {*} key
*/
function setIndex(map, key, index) {
var shouldDelete = index == null;
if (isObject(key)) {
var hash = getHash(key);
if (shouldDelete) {
delete map._objectIndex[hash];
} else {
map._objectIndex[hash] = index;
}
} else {
var prefixedKey = KEY_PREFIX + key;
if (typeof key === 'string') {
if (shouldDelete) {
delete map._stringIndex[prefixedKey];
} else {
map._stringIndex[prefixedKey] = index;
}
} else {
if (shouldDelete) {
delete map._otherIndex[prefixedKey];
} else {
map._otherIndex[prefixedKey] = index;
}
}
}
}
/**
* Instantiate a map with internal slots.
*
* @param {map} map
*/
function initMap(map) {
// Data structure design inspired by Traceur's Map implementation.
// We maintain an internal array for all the entries. The array is needed
// to remember order. However, to have a reasonable HashMap performance
// i.e. O(1) for insertion, deletion, and retrieval. We maintain indices
// in objects for fast look ups. Indices are split up according to data
// types to avoid collisions.
map._mapData = [];
// Object index maps from an object "hash" to index. The hash being a unique
// property of our choosing that we associate with the object. Association
// is done by ways of keeping a non-enumerable property on the object.
// Ideally these would be `Object.create(null)` objects but since we're
// trying to support ES3 we'll have to guard against collisions using
// prefixes on the keys rather than rely on null prototype objects.
map._objectIndex = {};
// String index maps from strings to index.
map._stringIndex = {};
// Numbers, booleans, undefined, and null.
map._otherIndex = {};
// Unfortunately we have to support ES3 and cannot have `Map.prototype.size`
// be a getter method but just a regular method. The biggest problem with
// this is safety. Clients can change the size property easily and possibly
// without noticing (e.g. `if (map.size = 1) {..}` kind of typo). What we
// can do to mitigate use getters and setters in development to disallow
// and issue a warning for changing the `size` property.
if (__DEV__) {
if (isES5) {
// If the `SECRET_SIZE_PROP` property is already defined then we're not
// in the first call to `initMap` (e.g. coming from `map.clear()`) so
// all we need to do is reset the size without defining the properties.
if (map.hasOwnProperty(SECRET_SIZE_PROP)) {
map[SECRET_SIZE_PROP] = 0;
} else {
Object.defineProperty(map, SECRET_SIZE_PROP, {
value: 0,
writable: true
});
Object.defineProperty(map, 'size', {
set: (v) => {
console.error(
'PLEASE FIX ME: You are changing the map size property which ' +
'should not be writable and will break in production.'
);
throw new Error('The map size property is not writable.');
},
get: () => map[SECRET_SIZE_PROP]
});
}
// NOTE: Early return to implement immutable `.size` in DEV.
return;
}
}
// This is a diviation from the spec. `size` should be a getter on
// `Map.prototype`. However, we have to support IE8.
map.size = 0;
}
/**
* Check if something is an object.
*
* @param {*} o
* @return {boolean}
*/
function isObject(o) {
return o != null && (typeof o === 'object' || typeof o === 'function');
}
/**
* Create an iteration object.
*
* @param {*} value
* @param {boolean} done
* @return {object}
*/
function createIterResultObject(value, done) {
return {value, done};
}
// Are we in a legit ES5 environment. Spoiler alert: that doesn't include IE8.
var isES5 = (function() {
try {
Object.defineProperty({}, 'x', {});
return true;
} catch (e) {
return false;
}
})();
/**
* Check if an object can be extended.
*
* @param {object|array|function|regexp} o
* @return {boolean}
*/
function isExtensible(o) {
if (!isES5) {
return true;
} else {
return Object.isExtensible(o);
}
}
/**
* IE has a `uniqueID` set on every DOM node. So we construct the hash from
* this uniqueID to avoid memory leaks and the IE cloneNode bug where it
* clones properties in addition to the attributes.
*
* @param {object} node
* @return {?string}
*/
function getIENodeHash(node) {
var uniqueID;
switch (node.nodeType) {
case 1: // Element
uniqueID = node.uniqueID;
break;
case 9: // Document
uniqueID = node.documentElement.uniqueID;
break;
default:
return null;
}
if (uniqueID) {
return OLD_IE_HASH_PREFIX + uniqueID;
} else {
return null;
}
}
var getHash = (function() {
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
var hashProperty = guid();
var hashCounter = 0;
/**
* Get the "hash" associated with an object.
*
* @param {object|array|function|regexp} o
* @return {number}
*/
return function getHash(o) { // eslint-disable-line no-shadow
if (o[hashProperty]) {
return o[hashProperty];
} else if (!isES5 &&
o.propertyIsEnumerable &&
o.propertyIsEnumerable[hashProperty]) {
return o.propertyIsEnumerable[hashProperty];
} else if (!isES5 &&
isNode(o) &&
getIENodeHash(o)) {
return getIENodeHash(o);
} else if (!isES5 && o[hashProperty]) {
return o[hashProperty];
}
if (isExtensible(o)) {
hashCounter += 1;
if (isES5) {
Object.defineProperty(o, hashProperty, {
enumerable: false,
writable: false,
configurable: false,
value: hashCounter
});
} else if (o.propertyIsEnumerable) {
// Since we can't define a non-enumerable property on the object
// we'll hijack one of the less-used non-enumerable properties to
// save our hash on it. Addiotionally, since this is a function it
// will not show up in `JSON.stringify` which is what we want.
o.propertyIsEnumerable = function() {
return propIsEnumerable.apply(this, arguments);
};
o.propertyIsEnumerable[hashProperty] = hashCounter;
} else if (isNode(o)) {
// At this point we couldn't get the IE `uniqueID` to use as a hash
// and we couldn't use a non-enumerable property to exploit the
// dontEnum bug so we simply add the `hashProperty` on the node
// itself.
o[hashProperty] = hashCounter;
} else {
throw new Error('Unable to set a non-enumerable property on object.');
}
return hashCounter;
} else {
throw new Error('Non-extensible objects are not allowed as keys.');
}
};
})();
return Map;
})(Function('return this')()); // eslint-disable-line no-new-func

197
node_modules/react-native/Libraries/vendor/core/Set.js generated vendored Normal file
View File

@@ -0,0 +1,197 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Set
* @preventMunge
* @typechecks
*/
/* eslint-disable no-extend-native */
'use strict';
var Map = require('Map');
var _shouldPolyfillES6Collection = require('_shouldPolyfillES6Collection');
var toIterator = require('toIterator');
module.exports = (function(global) {
// Since our implementation is spec-compliant for the most part we can safely
// delegate to a built-in version if exists and is implemented correctly.
// Firefox had gotten a few implementation details wrong across different
// versions so we guard against that.
// These checks are adapted from es6-shim https://fburl.com/34437854
if (!_shouldPolyfillES6Collection('Set')) {
return global.Set;
}
/**
* == ES6 Set Collection ==
*
* This module is meant to implement a Set collection as described in chapter
* 23.2 of the ES6 specification.
*
* Set objects are collections of unique values. Where values can be any
* JavaScript value.
* https://people.mozilla.org/~jorendorff/es6-draft.html#sec-map-objects
*
* There only two -- rather small -- diviations from the spec:
*
* 1. The use of frozen objects as keys. @see Map module for more on this.
*
* 2. The `size` property on a map object is a regular property and not a
* computed property on the prototype as described by the spec.
* The reason being is that we simply want to support ES3 environments
* which doesn't implement computed properties.
*
* == Usage ==
*
* var set = new set(iterable);
*
* set.set(value);
* set.has(value); // true
* set.delete(value); // true
*
* var iterator = set.keys();
* iterator.next(); // {value: value, done: false}
*
* var iterator = set.values();
* iterator.next(); // {value: value, done: false}
*
* var iterator = set.entries();
* iterator.next(); // {value: [value, value], done: false}
*
* set.forEach(function(value, value){ this === thisArg }, thisArg);
*
* set.clear(); // resets set.
*/
class Set {
/**
* 23.2.1.1
*
* Takes an optional `iterable` (which is basically any object that
* implements a Symbol.iterator (@@iterator) method). That is a collection
* of values used to instantiate the set.
*
* @param {*} iterable
*/
constructor(iterable) {
if (this == null ||
(typeof this !== 'object' && typeof this !== 'function')) {
throw new TypeError('Wrong set object type.');
}
initSet(this);
if (iterable != null) {
var it = toIterator(iterable);
var next;
while (!(next = it.next()).done) {
this.add(next.value);
}
}
}
/**
* 23.2.3.1
*
* If it doesn't already exist in the collection a `value` is added.
*
* @param {*} value
* @return {set}
*/
add(value) {
this._map.set(value, value);
this.size = this._map.size;
return this;
}
/**
* 23.2.3.2
*
* Clears the set.
*/
clear() {
initSet(this);
}
/**
* 23.2.3.4
*
* Deletes a `value` from the collection if it exists.
* Returns true if the value was found and deleted and false otherwise.
*
* @param {*} value
* @return {boolean}
*/
delete(value) {
var ret = this._map.delete(value);
this.size = this._map.size;
return ret;
}
/**
* 23.2.3.5
*
* Returns an iterator over a collection of [value, value] tuples.
*/
entries() {
return this._map.entries();
}
/**
* 23.2.3.6
*
* Iterate over the collection calling `callback` with (value, value, set).
*
* @param {function} callback
*/
forEach(callback) {
var thisArg = arguments[1];
var it = this._map.keys();
var next;
while (!(next = it.next()).done) {
callback.call(thisArg, next.value, next.value, this);
}
}
/**
* 23.2.3.7
*
* Iterate over the collection calling `callback` with (value, value, set).
*
* @param {*} value
* @return {boolean}
*/
has(value) {
return this._map.has(value);
}
/**
* 23.2.3.7
*
* Returns an iterator over the colleciton of values.
*/
values() {
return this._map.values();
}
}
// 23.2.3.11
Set.prototype[toIterator.ITERATOR_SYMBOL] = Set.prototype.values;
// 23.2.3.7
Set.prototype.keys = Set.prototype.values;
function initSet(set) {
set._map = new Map();
set.size = set._map.size;
}
return Set;
})(Function('return this')()); // eslint-disable-line no-new-func

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule _shouldPolyfillES6Collection
* @preventMunge
* @flow
*/
'use strict';
/**
* Checks whether a collection name (e.g. "Map" or "Set") has a native polyfill
* that is safe to be used.
*/
function _shouldActuallyPolyfillES6Collection(collectionName: string): boolean {
var Collection = global[collectionName];
if (Collection == null) {
return true;
}
// The iterator protocol depends on `Symbol.iterator`. If a collection is
// implemented, but `Symbol` is not, it's going to break iteration because
// we'll be using custom "@@iterator" instead, which is not implemented on
// native collections.
if (typeof global.Symbol !== 'function') {
return true;
}
var proto = Collection.prototype;
// These checks are adapted from es6-shim: https://fburl.com/34437854
// NOTE: `isCallableWithoutNew` and `!supportsSubclassing` are not checked
// because they make debugging with "break on exceptions" difficult.
return Collection == null ||
typeof Collection !== 'function' ||
typeof proto.clear !== 'function' ||
new Collection().size !== 0 ||
typeof proto.keys !== 'function' ||
typeof proto.forEach !== 'function';
}
const cache: { [name: string]: bool } = {};
/**
* Checks whether a collection name (e.g. "Map" or "Set") has a native polyfill
* that is safe to be used and caches this result.
* Make sure to make a first call to this function before a corresponding
* property on global was overriden in any way.
*/
function _shouldPolyfillES6Collection(collectionName: string) {
let result = cache[collectionName];
if (result !== undefined) {
return result;
}
result = _shouldActuallyPolyfillES6Collection(collectionName);
cache[collectionName] = result;
return result;
}
module.exports = _shouldPolyfillES6Collection;

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule getObjectValues
* @typechecks
*/
'use strict';
/**
* Retrieve an object's values as an array.
*
* If you are looking for a function that creates an Array instance based
* on an "Array-like" object, use createArrayFrom instead.
*
* @param {object} obj An object.
* @return {array} The object's values.
*/
function getObjectValues(obj) {
var values = [];
for (var key in obj) {
values.push(obj[key]);
}
return values;
}
module.exports = getObjectValues;

View File

@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule guid
*/
/* eslint-disable no-bitwise */
'use strict';
/**
* Module that provides a function for creating a unique identifier.
* The returned value does not conform to the GUID standard, but should
* be globally unique in the context of the browser.
*/
function guid() {
return 'f' + (Math.random() * (1 << 30)).toString(16).replace('.', '');
}
module.exports = guid;

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule isEmpty
*/
'use strict';
/**
* Mimics empty from PHP.
*/
function isEmpty(obj) {
if (Array.isArray(obj)) {
return obj.length === 0;
} else if (typeof obj === 'object') {
for (var i in obj) {
return false;
}
return true;
} else {
return !obj;
}
}
module.exports = isEmpty;

View File

@@ -0,0 +1,50 @@
/**
* @generated SignedSource<<0e3063b19e14ed191102b1dffe45551f>>
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !! This file is a check-in of a static_upstream project! !!
* !! !!
* !! You should not modify this file directly. Instead: !!
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
* !! the latest version from upstream. !!
* !! 2) Make your changes, test them, etc. !!
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
* !! static_upstream. !!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* Copyright 2013-2014 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule merge
*/
"use strict";
var mergeInto = require('mergeInto');
/**
* Shallow merges two structures into a return value, without mutating either.
*
* @param {?object} one Optional object with properties to merge from.
* @param {?object} two Optional object with properties to merge from.
* @return {object} The shallow extension of one by two.
*/
var merge = function(one, two) {
var result = {};
mergeInto(result, one);
mergeInto(result, two);
return result;
};
module.exports = merge;

View File

@@ -0,0 +1,138 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule mergeHelpers
*
* requiresPolyfills: Array.isArray
*/
'use strict';
var invariant = require('fbjs/lib/invariant');
/**
* Maximum number of levels to traverse. Will catch circular structures.
* @const
*/
var MAX_MERGE_DEPTH = 36;
/**
* We won't worry about edge cases like new String('x') or new Boolean(true).
* Functions and Dates are considered terminals, and arrays are not.
* @param {*} o The item/object/value to test.
* @return {boolean} true iff the argument is a terminal.
*/
var isTerminal = function(o) {
return typeof o !== 'object' || o instanceof Date || o === null;
};
var mergeHelpers = {
MAX_MERGE_DEPTH: MAX_MERGE_DEPTH,
isTerminal: isTerminal,
/**
* Converts null/undefined values into empty object.
*
* @param {?Object=} arg Argument to be normalized (nullable optional)
* @return {!Object}
*/
normalizeMergeArg: function(arg) {
return arg === undefined || arg === null ? {} : arg;
},
/**
* If merging Arrays, a merge strategy *must* be supplied. If not, it is
* likely the caller's fault. If this function is ever called with anything
* but `one` and `two` being `Array`s, it is the fault of the merge utilities.
*
* @param {*} one Array to merge into.
* @param {*} two Array to merge from.
*/
checkMergeArrayArgs: function(one, two) {
invariant(
Array.isArray(one) && Array.isArray(two),
'Tried to merge arrays, instead got %s and %s.',
one,
two
);
},
/**
* @param {*} one Object to merge into.
* @param {*} two Object to merge from.
*/
checkMergeObjectArgs: function(one, two) {
mergeHelpers.checkMergeObjectArg(one);
mergeHelpers.checkMergeObjectArg(two);
},
/**
* @param {*} arg
*/
checkMergeObjectArg: function(arg) {
invariant(
!isTerminal(arg) && !Array.isArray(arg),
'Tried to merge an object, instead got %s.',
arg
);
},
/**
* @param {*} arg
*/
checkMergeIntoObjectArg: function(arg) {
invariant(
(!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg),
'Tried to merge into an object, instead got %s.',
arg
);
},
/**
* Checks that a merge was not given a circular object or an object that had
* too great of depth.
*
* @param {number} Level of recursion to validate against maximum.
*/
checkMergeLevel: function(level) {
invariant(
level < MAX_MERGE_DEPTH,
'Maximum deep merge depth exceeded. You may be attempting to merge ' +
'circular structures in an unsupported way.'
);
},
/**
* Checks that the supplied merge strategy is valid.
*
* @param {string} Array merge strategy.
*/
checkArrayStrategy: function(strategy) {
invariant(
strategy === undefined || strategy in mergeHelpers.ArrayStrategies,
'You must provide an array strategy to deep merge functions to ' +
'instruct the deep merge how to resolve merging two arrays.'
);
},
/**
* Set of possible behaviors of merge algorithms when encountering two Arrays
* that must be merged together.
* - `clobber`: The left `Array` is ignored.
* - `indexByIndex`: The result is achieved by recursively deep merging at
* each index. (not yet supported.)
*/
ArrayStrategies: {
Clobber: 'Clobber',
Concat: 'Concat',
IndexByIndex: 'IndexByIndex',
},
};
module.exports = mergeHelpers;

View File

@@ -0,0 +1,59 @@
/**
* @generated SignedSource<<d3caa35be27b17ea4dd4c76bef72d1ab>>
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !! This file is a check-in of a static_upstream project! !!
* !! !!
* !! You should not modify this file directly. Instead: !!
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
* !! the latest version from upstream. !!
* !! 2) Make your changes, test them, etc. !!
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
* !! static_upstream. !!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* Copyright 2013-2014 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule mergeInto
* @typechecks static-only
*/
"use strict";
var mergeHelpers = require('mergeHelpers');
var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg;
var checkMergeIntoObjectArg = mergeHelpers.checkMergeIntoObjectArg;
/**
* Shallow merges two structures by mutating the first parameter.
*
* @param {object|function} one Object to be merged into.
* @param {?object} two Optional object with properties to merge from.
*/
function mergeInto(one, two) {
checkMergeIntoObjectArg(one);
if (two != null) {
checkMergeObjectArg(two);
for (var key in two) {
if (!two.hasOwnProperty(key)) {
continue;
}
one[key] = two[key];
}
}
}
module.exports = mergeInto;

View File

@@ -0,0 +1,169 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule toIterator
*/
'use strict';
/**
* Given an object `toIterator` will return the itrator for that object. If the
* object has a `Symbol.iterator` method we just call that. Otherwise we
* implement the ES6 `Array` and `String` Iterator.
*/
/**
* Constants
*/
var KIND_KEY = 'key';
var KIND_VALUE = 'value';
var KIND_KEY_VAL = 'key+value';
/*global Symbol: true*/
var ITERATOR_SYMBOL = (typeof Symbol === 'function')
? Symbol.iterator
: '@@iterator';
var toIterator = (function() {
if (!(Array.prototype[ITERATOR_SYMBOL] &&
String.prototype[ITERATOR_SYMBOL])) {
// IIFE to avoid creating classes for no reason because of hoisting.
return (function() {
class ArrayIterator {
// 22.1.5.1 CreateArrayIterator Abstract Operation
constructor(array, kind) {
if (!Array.isArray(array)) {
throw new TypeError('Object is not an Array');
}
this._iteratedObject = array;
this._kind = kind;
this._nextIndex = 0;
}
// 22.1.5.2.1 %ArrayIteratorPrototype%.next()
next() {
if (!this instanceof ArrayIterator) {
throw new TypeError('Object is not an ArrayIterator');
}
if (this._iteratedObject == null) {
return createIterResultObject(undefined, true);
}
var array = this._iteratedObject;
var len = this._iteratedObject.length;
var index = this._nextIndex;
var kind = this._kind;
if (index >= len) {
this._iteratedObject = undefined;
return createIterResultObject(undefined, true);
}
this._nextIndex = index + 1;
if (kind === KIND_KEY) {
return createIterResultObject(index, false);
} else if (kind === KIND_VALUE) {
return createIterResultObject(array[index], false);
} else if (kind === KIND_KEY_VAL) {
return createIterResultObject([index, array[index]], false);
}
}
// 22.1.5.2.2 %ArrayIteratorPrototype%[@@iterator]()
'@@iterator'() {
return this;
}
}
class StringIterator {
// 21.1.5.1 CreateStringIterator Abstract Operation
constructor(string) {
if (typeof string !== 'string') {
throw new TypeError('Object is not a string');
}
this._iteratedString = string;
this._nextIndex = 0;
}
// 21.1.5.2.1 %StringIteratorPrototype%.next()
next() {
if (!this instanceof StringIterator) {
throw new TypeError('Object is not a StringIterator');
}
if (this._iteratedString == null) {
return createIterResultObject(undefined, true);
}
var index = this._nextIndex;
var s = this._iteratedString;
var len = s.length;
if (index >= len) {
this._iteratedString = undefined;
return createIterResultObject(undefined, true);
}
var ret;
var first = s.charCodeAt(index);
if (first < 0xD800 || first > 0xDBFF || index + 1 === len) {
ret = s[index];
} else {
var second = s.charCodeAt(index + 1);
if (second < 0xDC00 || second > 0xDFFF) {
ret = s[index];
} else {
ret = s[index] + s[index + 1];
}
}
this._nextIndex = index + ret.length;
return createIterResultObject(ret, false);
}
// 21.1.5.2.2 %StringIteratorPrototype%[@@ITERATOR_SYMBOL]()
'@@iterator'() {
return this;
}
}
// 7.4.7 createIterResultObject(value, done)
function createIterResultObject(value, done) {
return {value: value, done: done};
}
return function(object, kind) {
if (typeof object === 'string') {
return new StringIterator(object);
} else if (Array.isArray(object)) {
return new ArrayIterator(object, kind || KIND_VALUE);
} else {
return object[ITERATOR_SYMBOL]();
}
};
})();
} else {
return function(object) {
return object[ITERATOR_SYMBOL]();
};
}
})();
/**
* Export constants
*/
Object.assign(toIterator, {
KIND_KEY,
KIND_VALUE,
KIND_KEY_VAL,
ITERATOR_SYMBOL
});
module.exports = toIterator;

View File

@@ -0,0 +1,149 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule DocumentSelectionState
* @typechecks
*/
'use strict';
var mixInEventEmitter = require('mixInEventEmitter');
/**
* DocumentSelectionState is responsible for maintaining selection information
* for a document.
*
* It is intended for use by AbstractTextEditor-based components for
* identifying the appropriate start/end positions to modify the
* DocumentContent, and for programmatically setting browser selection when
* components re-render.
*/
class DocumentSelectionState {
/**
* @param {number} anchor
* @param {number} focus
*/
constructor(anchor, focus) {
this._anchorOffset = anchor;
this._focusOffset = focus;
this._hasFocus = false;
}
/**
* Apply an update to the state. If either offset value has changed,
* set the values and emit the `change` event. Otherwise no-op.
*
* @param {number} anchor
* @param {number} focus
*/
update(anchor, focus) {
if (this._anchorOffset !== anchor || this._focusOffset !== focus) {
this._anchorOffset = anchor;
this._focusOffset = focus;
this.emit('update');
}
}
/**
* Given a max text length, constrain our selection offsets to ensure
* that the selection remains strictly within the text range.
*
* @param {number} maxLength
*/
constrainLength(maxLength) {
this.update(
Math.min(this._anchorOffset, maxLength),
Math.min(this._focusOffset, maxLength)
);
}
focus() {
if (!this._hasFocus) {
this._hasFocus = true;
this.emit('focus');
}
}
blur() {
if (this._hasFocus) {
this._hasFocus = false;
this.emit('blur');
}
}
/**
* @return {boolean}
*/
hasFocus() {
return this._hasFocus;
}
/**
* @return {boolean}
*/
isCollapsed() {
return this._anchorOffset === this._focusOffset;
}
/**
* @return {boolean}
*/
isBackward() {
return this._anchorOffset > this._focusOffset;
}
/**
* @return {?number}
*/
getAnchorOffset() {
return this._hasFocus ? this._anchorOffset : null;
}
/**
* @return {?number}
*/
getFocusOffset() {
return this._hasFocus ? this._focusOffset : null;
}
/**
* @return {?number}
*/
getStartOffset() {
return (
this._hasFocus ? Math.min(this._anchorOffset, this._focusOffset) : null
);
}
/**
* @return {?number}
*/
getEndOffset() {
return (
this._hasFocus ? Math.max(this._anchorOffset, this._focusOffset) : null
);
}
/**
* @param {number} start
* @param {number} end
* @return {boolean}
*/
overlaps(start, end) {
return (
this.hasFocus() &&
this.getStartOffset() <= end && start <= this.getEndOffset()
);
}
}
mixInEventEmitter(DocumentSelectionState, {
'blur': true,
'focus': true,
'update': true
});
module.exports = DocumentSelectionState;

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EmitterSubscription
* @flow
*/
'use strict';
const EventSubscription = require('EventSubscription');
import type EventEmitter from 'EventEmitter';
import type EventSubscriptionVendor from 'EventSubscriptionVendor';
/**
* EmitterSubscription represents a subscription with listener and context data.
*/
class EmitterSubscription extends EventSubscription {
emitter: EventEmitter;
listener: Function;
context: ?Object;
/**
* @param {EventEmitter} emitter - The event emitter that registered this
* subscription
* @param {EventSubscriptionVendor} subscriber - The subscriber that controls
* this subscription
* @param {function} listener - Function to invoke when the specified event is
* emitted
* @param {*} context - Optional context object to use when invoking the
* listener
*/
constructor(
emitter: EventEmitter,
subscriber: EventSubscriptionVendor,
listener: Function,
context: ?Object
) {
super(subscriber);
this.emitter = emitter;
this.listener = listener;
this.context = context;
}
/**
* Removes this subscription from the emitter that registered it.
* Note: we're overriding the `remove()` method of EventSubscription here
* but deliberately not calling `super.remove()` as the responsibility
* for removing the subscription lies with the EventEmitter.
*/
remove() {
this.emitter.removeSubscription(this);
}
}
module.exports = EmitterSubscription;

View File

@@ -0,0 +1,218 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EventEmitter
* @noflow
* @typecheck
*/
'use strict';
const EmitterSubscription = require('EmitterSubscription');
const EventSubscriptionVendor = require('EventSubscriptionVendor');
const emptyFunction = require('fbjs/lib/emptyFunction');
const invariant = require('fbjs/lib/invariant');
/**
* @class EventEmitter
* @description
* An EventEmitter is responsible for managing a set of listeners and publishing
* events to them when it is told that such events happened. In addition to the
* data for the given event it also sends a event control object which allows
* the listeners/handlers to prevent the default behavior of the given event.
*
* The emitter is designed to be generic enough to support all the different
* contexts in which one might want to emit events. It is a simple multicast
* mechanism on top of which extra functionality can be composed. For example, a
* more advanced emitter may use an EventHolder and EventFactory.
*/
class EventEmitter {
_subscriber: EventSubscriptionVendor;
_currentSubscription: ?EmitterSubscription;
/**
* @constructor
*
* @param {EventSubscriptionVendor} subscriber - Optional subscriber instance
* to use. If omitted, a new subscriber will be created for the emitter.
*/
constructor(subscriber: ?EventSubscriptionVendor) {
this._subscriber = subscriber || new EventSubscriptionVendor();
}
/**
* Adds a listener to be invoked when events of the specified type are
* emitted. An optional calling context may be provided. The data arguments
* emitted will be passed to the listener function.
*
* TODO: Annotate the listener arg's type. This is tricky because listeners
* can be invoked with varargs.
*
* @param {string} eventType - Name of the event to listen to
* @param {function} listener - Function to invoke when the specified event is
* emitted
* @param {*} context - Optional context object to use when invoking the
* listener
*/
addListener(
eventType: string, listener: Function, context: ?Object): EmitterSubscription {
return (this._subscriber.addSubscription(
eventType,
new EmitterSubscription(this, this._subscriber, listener, context)
) : any);
}
/**
* Similar to addListener, except that the listener is removed after it is
* invoked once.
*
* @param {string} eventType - Name of the event to listen to
* @param {function} listener - Function to invoke only once when the
* specified event is emitted
* @param {*} context - Optional context object to use when invoking the
* listener
*/
once(eventType: string, listener: Function, context: ?Object): EmitterSubscription {
return this.addListener(eventType, (...args) => {
this.removeCurrentListener();
listener.apply(context, args);
});
}
/**
* Removes all of the registered listeners, including those registered as
* listener maps.
*
* @param {?string} eventType - Optional name of the event whose registered
* listeners to remove
*/
removeAllListeners(eventType: ?string) {
this._subscriber.removeAllSubscriptions(eventType);
}
/**
* Provides an API that can be called during an eventing cycle to remove the
* last listener that was invoked. This allows a developer to provide an event
* object that can remove the listener (or listener map) during the
* invocation.
*
* If it is called when not inside of an emitting cycle it will throw.
*
* @throws {Error} When called not during an eventing cycle
*
* @example
* var subscription = emitter.addListenerMap({
* someEvent: function(data, event) {
* console.log(data);
* emitter.removeCurrentListener();
* }
* });
*
* emitter.emit('someEvent', 'abc'); // logs 'abc'
* emitter.emit('someEvent', 'def'); // does not log anything
*/
removeCurrentListener() {
invariant(
!!this._currentSubscription,
'Not in an emitting cycle; there is no current subscription'
);
this.removeSubscription(this._currentSubscription);
}
/**
* Removes a specific subscription. Called by the `remove()` method of the
* subscription itself to ensure any necessary cleanup is performed.
*/
removeSubscription(subscription: EmitterSubscription) {
invariant(
subscription.emitter === this,
'Subscription does not belong to this emitter.'
);
this._subscriber.removeSubscription(subscription);
}
/**
* Returns an array of listeners that are currently registered for the given
* event.
*
* @param {string} eventType - Name of the event to query
* @returns {array}
*/
listeners(eventType: string): [EmitterSubscription] {
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
return subscriptions
? subscriptions.filter(emptyFunction.thatReturnsTrue).map(
function(subscription) {
return subscription.listener;
})
: [];
}
/**
* Emits an event of the given type with the given data. All handlers of that
* particular type will be notified.
*
* @param {string} eventType - Name of the event to emit
* @param {...*} Arbitrary arguments to be passed to each registered listener
*
* @example
* emitter.addListener('someEvent', function(message) {
* console.log(message);
* });
*
* emitter.emit('someEvent', 'abc'); // logs 'abc'
*/
emit(eventType: string) {
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
if (subscriptions) {
for (let i = 0, l = subscriptions.length; i < l; i++) {
const subscription = subscriptions[i];
// The subscription may have been removed during this event loop.
if (subscription) {
this._currentSubscription = subscription;
subscription.listener.apply(
subscription.context,
Array.prototype.slice.call(arguments, 1)
);
}
}
this._currentSubscription = null;
}
}
/**
* Removes the given listener for event of specific type.
*
* @param {string} eventType - Name of the event to emit
* @param {function} listener - Function to invoke when the specified event is
* emitted
*
* @example
* emitter.removeListener('someEvent', function(message) {
* console.log(message);
* }); // removes the listener if already registered
*
*/
removeListener(eventType: String, listener) {
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
if (subscriptions) {
for (let i = 0, l = subscriptions.length; i < l; i++) {
const subscription = subscriptions[i];
// The subscription may have been removed during this event loop.
// its listener matches the listener in method parameters
if (subscription && subscription.listener === listener) {
subscription.remove();
}
}
}
}
}
module.exports = EventEmitter;

View File

@@ -0,0 +1,163 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EventEmitterWithHolding
* @flow
*/
'use strict';
import type EmitterSubscription from 'EmitterSubscription';
import type EventEmitter from 'EventEmitter';
import type EventHolder from 'EventHolder';
/**
* @class EventEmitterWithHolding
* @description
* An EventEmitterWithHolding decorates an event emitter and enables one to
* "hold" or cache events and then have a handler register later to actually
* handle them.
*
* This is separated into its own decorator so that only those who want to use
* the holding functionality have to and others can just use an emitter. Since
* it implements the emitter interface it can also be combined with anything
* that uses an emitter.
*/
class EventEmitterWithHolding {
_emitter: EventEmitter;
_eventHolder: EventHolder;
_currentEventToken: ?Object;
_emittingHeldEvents: boolean;
/**
* @constructor
* @param {object} emitter - The object responsible for emitting the actual
* events.
* @param {object} holder - The event holder that is responsible for holding
* and then emitting held events.
*/
constructor(emitter: EventEmitter, holder: EventHolder) {
this._emitter = emitter;
this._eventHolder = holder;
this._currentEventToken = null;
this._emittingHeldEvents = false;
}
/**
* @see EventEmitter#addListener
*/
addListener(eventType: string, listener: Function, context: ?Object) {
return this._emitter.addListener(eventType, listener, context);
}
/**
* @see EventEmitter#once
*/
once(eventType: string, listener: Function, context: ?Object) {
return this._emitter.once(eventType, listener, context);
}
/**
* Adds a listener to be invoked when events of the specified type are
* emitted. An optional calling context may be provided. The data arguments
* emitted will be passed to the listener function. In addition to subscribing
* to all subsequent events, this method will also handle any events that have
* already been emitted, held, and not released.
*
* @param {string} eventType - Name of the event to listen to
* @param {function} listener - Function to invoke when the specified event is
* emitted
* @param {*} context - Optional context object to use when invoking the
* listener
*
* @example
* emitter.emitAndHold('someEvent', 'abc');
*
* emitter.addRetroactiveListener('someEvent', function(message) {
* console.log(message);
* }); // logs 'abc'
*/
addRetroactiveListener(
eventType: string, listener: Function, context: ?Object): EmitterSubscription {
const subscription = this._emitter.addListener(eventType, listener, context);
this._emittingHeldEvents = true;
this._eventHolder.emitToListener(eventType, listener, context);
this._emittingHeldEvents = false;
return subscription;
}
/**
* @see EventEmitter#removeAllListeners
*/
removeAllListeners(eventType: string) {
this._emitter.removeAllListeners(eventType);
}
/**
* @see EventEmitter#removeCurrentListener
*/
removeCurrentListener() {
this._emitter.removeCurrentListener();
}
/**
* @see EventEmitter#listeners
*/
listeners(eventType: string) /* TODO: Annotate return type here */ {
return this._emitter.listeners(eventType);
}
/**
* @see EventEmitter#emit
*/
emit(eventType: string, ...args: any) {
this._emitter.emit(eventType, ...args);
}
/**
* Emits an event of the given type with the given data, and holds that event
* in order to be able to dispatch it to a later subscriber when they say they
* want to handle held events.
*
* @param {string} eventType - Name of the event to emit
* @param {...*} Arbitrary arguments to be passed to each registered listener
*
* @example
* emitter.emitAndHold('someEvent', 'abc');
*
* emitter.addRetroactiveListener('someEvent', function(message) {
* console.log(message);
* }); // logs 'abc'
*/
emitAndHold(eventType: string, ...args: any) {
this._currentEventToken = this._eventHolder.holdEvent(eventType, ...args);
this._emitter.emit(eventType, ...args);
this._currentEventToken = null;
}
/**
* @see EventHolder#releaseCurrentEvent
*/
releaseCurrentEvent() {
if (this._currentEventToken) {
this._eventHolder.releaseEvent(this._currentEventToken);
} else if (this._emittingHeldEvents) {
this._eventHolder.releaseCurrentEvent();
}
}
/**
* @see EventHolder#releaseEventType
* @param {string} eventType
*/
releaseHeldEventType(eventType: string) {
this._eventHolder.releaseEventType(eventType);
}
}
module.exports = EventEmitterWithHolding;

View File

@@ -0,0 +1,119 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EventHolder
* @flow
*/
'use strict';
const invariant = require('fbjs/lib/invariant');
class EventHolder {
_heldEvents: Object;
_currentEventKey: ?Object;
constructor() {
this._heldEvents = {};
this._currentEventKey = null;
}
/**
* Holds a given event for processing later.
*
* TODO: Annotate return type better. The structural type of the return here
* is pretty obvious.
*
* @param {string} eventType - Name of the event to hold and later emit
* @param {...*} Arbitrary arguments to be passed to each registered listener
* @return {object} Token that can be used to release the held event
*
* @example
*
* holder.holdEvent({someEvent: 'abc'});
*
* holder.emitToHandler({
* someEvent: function(data, event) {
* console.log(data);
* }
* }); //logs 'abc'
*
*/
holdEvent(eventType: string, ...args: any) {
this._heldEvents[eventType] = this._heldEvents[eventType] || [];
const eventsOfType = this._heldEvents[eventType];
const key = {
eventType: eventType,
index: eventsOfType.length
};
eventsOfType.push(args);
return key;
}
/**
* Emits the held events of the specified type to the given listener.
*
* @param {?string} eventType - Optional name of the events to replay
* @param {function} listener - The listener to which to dispatch the event
* @param {?object} context - Optional context object to use when invoking
* the listener
*/
emitToListener(eventType: ?string , listener: Function, context: ?Object) {
const eventsOfType = this._heldEvents[eventType];
if (!eventsOfType) {
return;
}
const origEventKey = this._currentEventKey;
eventsOfType.forEach((/*?array*/ eventHeld, /*number*/ index) => {
if (!eventHeld) {
return;
}
this._currentEventKey = {
eventType: eventType,
index: index
};
listener.apply(context, eventHeld);
});
this._currentEventKey = origEventKey;
}
/**
* Provides an API that can be called during an eventing cycle to release
* the last event that was invoked, so that it is no longer "held".
*
* If it is called when not inside of an emitting cycle it will throw.
*
* @throws {Error} When called not during an eventing cycle
*/
releaseCurrentEvent() {
invariant(
this._currentEventKey !== null,
'Not in an emitting cycle; there is no current event'
);
this._currentEventKey && this.releaseEvent(this._currentEventKey);
}
/**
* Releases the event corresponding to the handle that was returned when the
* event was first held.
*
* @param {object} token - The token returned from holdEvent
*/
releaseEvent(token: Object) {
delete this._heldEvents[token.eventType][token.index];
}
/**
* Releases all events of a certain type.
*
* @param {string} type
*/
releaseEventType(type: string) {
this._heldEvents[type] = [];
}
}
module.exports = EventHolder;

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EventSubscription
* @flow
*/
'use strict';
import type EventSubscriptionVendor from 'EventSubscriptionVendor';
/**
* EventSubscription represents a subscription to a particular event. It can
* remove its own subscription.
*/
class EventSubscription {
eventType: string;
key: number;
subscriber: EventSubscriptionVendor;
/**
* @param {EventSubscriptionVendor} subscriber the subscriber that controls
* this subscription.
*/
constructor(subscriber: EventSubscriptionVendor) {
this.subscriber = subscriber;
}
/**
* Removes this subscription from the subscriber that controls it.
*/
remove() {
this.subscriber.removeSubscription(this);
}
}
module.exports = EventSubscription;

View File

@@ -0,0 +1,98 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EventSubscriptionVendor
* @flow
*/
'use strict';
const invariant = require('fbjs/lib/invariant');
import type EventSubscription from 'EventSubscription';
/**
* EventSubscriptionVendor stores a set of EventSubscriptions that are
* subscribed to a particular event type.
*/
class EventSubscriptionVendor {
_subscriptionsForType: Object;
_currentSubscription: ?EventSubscription;
constructor() {
this._subscriptionsForType = {};
this._currentSubscription = null;
}
/**
* Adds a subscription keyed by an event type.
*
* @param {string} eventType
* @param {EventSubscription} subscription
*/
addSubscription(
eventType: string, subscription: EventSubscription): EventSubscription {
invariant(
subscription.subscriber === this,
'The subscriber of the subscription is incorrectly set.');
if (!this._subscriptionsForType[eventType]) {
this._subscriptionsForType[eventType] = [];
}
const key = this._subscriptionsForType[eventType].length;
this._subscriptionsForType[eventType].push(subscription);
subscription.eventType = eventType;
subscription.key = key;
return subscription;
}
/**
* Removes a bulk set of the subscriptions.
*
* @param {?string} eventType - Optional name of the event type whose
* registered supscriptions to remove, if null remove all subscriptions.
*/
removeAllSubscriptions(eventType: ?string) {
if (eventType === undefined) {
this._subscriptionsForType = {};
} else {
delete this._subscriptionsForType[eventType];
}
}
/**
* Removes a specific subscription. Instead of calling this function, call
* `subscription.remove()` directly.
*
* @param {object} subscription
*/
removeSubscription(subscription: Object) {
const eventType = subscription.eventType;
const key = subscription.key;
const subscriptionsForType = this._subscriptionsForType[eventType];
if (subscriptionsForType) {
delete subscriptionsForType[key];
}
}
/**
* Returns the array of subscriptions that are currently registered for the
* given event type.
*
* Note: This array can be potentially sparse as subscriptions are deleted
* from it when they are removed.
*
* TODO: This returns a nullable array. wat?
*
* @param {string} eventType
* @returns {?array}
*/
getSubscriptionsForType(eventType: string): ?[EventSubscription] {
return this._subscriptionsForType[eventType];
}
}
module.exports = EventSubscriptionVendor;

View File

@@ -0,0 +1,135 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule EventValidator
* @flow
*/
'use strict';
/**
* EventValidator is designed to validate event types to make it easier to catch
* common mistakes. It accepts a map of all of the different types of events
* that the emitter can emit. Then, if a user attempts to emit an event that is
* not one of those specified types the emitter will throw an error. Also, it
* provides a relatively simple matcher so that if it thinks that you likely
* mistyped the event name it will suggest what you might have meant to type in
* the error message.
*/
const EventValidator = {
/**
* @param {Object} emitter - The object responsible for emitting the actual
* events
* @param {Object} types - The collection of valid types that will be used to
* check for errors
* @return {Object} A new emitter with event type validation
* @example
* const types = {someEvent: true, anotherEvent: true};
* const emitter = EventValidator.addValidation(emitter, types);
*/
addValidation: function(emitter: Object, types: Object) {
const eventTypes = Object.keys(types);
const emitterWithValidation = Object.create(emitter);
Object.assign(emitterWithValidation, {
emit: function emit(type, a, b, c, d, e, _) {
assertAllowsEventType(type, eventTypes);
return emitter.emit.call(this, type, a, b, c, d, e, _);
}
});
return emitterWithValidation;
}
};
function assertAllowsEventType(type, allowedTypes) {
if (allowedTypes.indexOf(type) === -1) {
throw new TypeError(errorMessageFor(type, allowedTypes));
}
}
function errorMessageFor(type, allowedTypes) {
let message = 'Unknown event type "' + type + '". ';
if (__DEV__) {
message += recommendationFor(type, allowedTypes);
}
message += 'Known event types: ' + allowedTypes.join(', ') + '.';
return message;
}
// Allow for good error messages
if (__DEV__) {
var recommendationFor = function (type, allowedTypes) {
const closestTypeRecommendation = closestTypeFor(type, allowedTypes);
if (isCloseEnough(closestTypeRecommendation, type)) {
return 'Did you mean "' + closestTypeRecommendation.type + '"? ';
} else {
return '';
}
};
var closestTypeFor = function (type, allowedTypes) {
const typeRecommendations = allowedTypes.map(
typeRecommendationFor.bind(this, type)
);
return typeRecommendations.sort(recommendationSort)[0];
};
var typeRecommendationFor = function (type, recommendedType) {
return {
type: recommendedType,
distance: damerauLevenshteinDistance(type, recommendedType)
};
};
var recommendationSort = function (recommendationA, recommendationB) {
if (recommendationA.distance < recommendationB.distance) {
return -1;
} else if (recommendationA.distance > recommendationB.distance) {
return 1;
} else {
return 0;
}
};
var isCloseEnough = function (closestType, actualType) {
return (closestType.distance / actualType.length) < 0.334;
};
var damerauLevenshteinDistance = function (a, b) {
let i, j;
const d = [];
for (i = 0; i <= a.length; i++) {
d[i] = [i];
}
for (j = 1; j <= b.length; j++) {
d[0][j] = j;
}
for (i = 1; i <= a.length; i++) {
for (j = 1; j <= b.length; j++) {
const cost = a.charAt(i - 1) === b.charAt(j - 1) ? 0 : 1;
d[i][j] = Math.min(
d[i - 1][j] + 1,
d[i][j - 1] + 1,
d[i - 1][j - 1] + cost
);
if (i > 1 && j > 1 &&
a.charAt(i - 1) === b.charAt(j - 2) &&
a.charAt(i - 2) === b.charAt(j - 1)) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
}
}
}
return d[a.length][b.length];
};
}
module.exports = EventValidator;

View File

@@ -0,0 +1,136 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule mixInEventEmitter
* @flow
*/
'use strict';
const EventEmitter = require('EventEmitter');
const EventEmitterWithHolding = require('EventEmitterWithHolding');
const EventHolder = require('EventHolder');
const invariant = require('fbjs/lib/invariant');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const keyOf = require('fbjs/lib/keyOf');
import type EmitterSubscription from 'EmitterSubscription';
const TYPES_KEY = keyOf({__types: true});
/**
* API to setup an object or constructor to be able to emit data events.
*
* @example
* function Dog() { ...dog stuff... }
* mixInEventEmitter(Dog, {bark: true});
*
* var puppy = new Dog();
* puppy.addListener('bark', function (volume) {
* console.log('Puppy', this, 'barked at volume:', volume);
* });
* puppy.emit('bark', 'quiet');
* // Puppy <puppy> barked at volume: quiet
*
*
* // A "singleton" object may also be commissioned:
*
* var Singleton = {};
* mixInEventEmitter(Singleton, {lonely: true});
* Singleton.emit('lonely', true);
*/
function mixInEventEmitter(cls: Function | Object, types: Object) {
invariant(types, 'Must supply set of valid event types');
// If this is a constructor, write to the prototype, otherwise write to the
// singleton object.
const target = cls.prototype || cls;
invariant(!target.__eventEmitter, 'An active emitter is already mixed in');
const ctor = cls.constructor;
if (ctor) {
invariant(
ctor === Object || ctor === Function,
'Mix EventEmitter into a class, not an instance'
);
}
// Keep track of the provided types, union the types if they already exist,
// which allows for prototype subclasses to provide more types.
if (target.hasOwnProperty(TYPES_KEY)) {
Object.assign(target.__types, types);
} else if (target.__types) {
target.__types = Object.assign({}, target.__types, types);
} else {
target.__types = types;
}
Object.assign(target, EventEmitterMixin);
}
const EventEmitterMixin = {
emit: function(eventType, a, b, c, d, e, _) {
return this.__getEventEmitter().emit(eventType, a, b, c, d, e, _);
},
emitAndHold: function(eventType, a, b, c, d, e, _) {
return this.__getEventEmitter().emitAndHold(eventType, a, b, c, d, e, _);
},
addListener: function(eventType, listener, context): EmitterSubscription {
return this.__getEventEmitter().addListener(eventType, listener, context);
},
once: function(eventType, listener, context) {
return this.__getEventEmitter().once(eventType, listener, context);
},
addRetroactiveListener: function(eventType, listener, context) {
return this.__getEventEmitter().addRetroactiveListener(
eventType,
listener,
context
);
},
addListenerMap: function(listenerMap, context) {
return this.__getEventEmitter().addListenerMap(listenerMap, context);
},
addRetroactiveListenerMap: function(listenerMap, context) {
return this.__getEventEmitter().addListenerMap(listenerMap, context);
},
removeAllListeners: function() {
this.__getEventEmitter().removeAllListeners();
},
removeCurrentListener: function() {
this.__getEventEmitter().removeCurrentListener();
},
releaseHeldEventType: function(eventType) {
this.__getEventEmitter().releaseHeldEventType(eventType);
},
__getEventEmitter: function() {
if (!this.__eventEmitter) {
let emitter = new EventEmitter();
if (__DEV__) {
const EventValidator = require('EventValidator');
emitter = EventValidator.addValidation(emitter, this.__types);
}
const holder = new EventHolder();
this.__eventEmitter = new EventEmitterWithHolding(emitter, holder);
}
return this.__eventEmitter;
}
};
module.exports = mixInEventEmitter;