[react-packager][streamline oss] Move open sourced JS source to react-native-github

This commit is contained in:
Spencer Ahrens
2015-02-19 20:10:52 -08:00
commit efae175a8e
434 changed files with 44658 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule Dimensions
*/
'use strict';
var NativeModules = require('NativeModules');
var invariant = require('invariant');
var mergeInto = require('mergeInto');
var dimensions = NativeModules.RKUIManager.Dimensions;
class Dimensions {
/**
* This should only be called from native code.
*
* @param {object} dims Simple string-keyed object of dimensions to set
*/
static set(dims) {
mergeInto(dimensions, dims);
return true;
}
/**
* Initial dimensions are set before `runApplication` is called so they should
* be available before any other require's are run, but may be updated later.
*
* Note: Although dimensions are available immediately, they may change (e.g
* due to device rotation) so any rendering logic or styles that depend on
* these constants should try to call this function on every render, rather
* than caching the value (for example, using inline styles rather than
* setting a value in a `StyleSheet`).
*
* @param {string} dim Name of dimension as defined when calling `set`.
* @returns {Object?} Value for the dimension.
*/
static get(dim) {
invariant(dimensions[dim], 'No dimension set for key ' + dim);
return dimensions[dim];
}
}
module.exports = Dimensions;

View File

@@ -0,0 +1,21 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule ErrorUtils
*/
var GLOBAL = this;
/**
* 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 original defined in a file named error-guard.js.
*/
module.exports = GLOBAL.ErrorUtils;

View File

@@ -0,0 +1,476 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule MessageQueue
*/
'use strict';
var ErrorUtils = require('ErrorUtils');
var invariant = require('invariant');
var warning = require('warning');
var JSTimersExecution = require('JSTimersExecution');
var INTERNAL_ERROR = 'Error in MessageQueue implementation';
/**
* So as not to confuse static build system.
*/
var requireFunc = require;
/**
* @param {Object!} module Module instance, must be loaded.
* @param {string} methodName Name of method in `module`.
* @param {array<*>} params Arguments to method.
* @returns {*} Return value of method invocation.
*/
var jsCall = function(module, methodName, params) {
return module[methodName].apply(module, params);
};
/**
* A utility for aggregating "work" to be done, and potentially transferring
* that work to another thread. Each instance of `MessageQueue` has the notion
* of a "target" thread - the thread that the work will be sent to.
*
* TODO: Long running callback results, and streaming callback results (ability
* for a callback to be invoked multiple times).
*
* @param {object} moduleNameToID Used to translate module/method names into
* efficient numeric IDs.
* @class MessageQueue
*/
var MessageQueue = function(remoteModulesConfig, localModulesConfig, customRequire) {
this._requireFunc = customRequire || requireFunc;
this._initBookeeping();
this._initNamingMap(remoteModulesConfig, localModulesConfig);
};
// REQUEST: Parallell arrays:
var REQUEST_MODULE_IDS = 0;
var REQUEST_METHOD_IDS = 1;
var REQUEST_PARAMSS = 2;
// RESPONSE: Parallell arrays:
var RESPONSE_CBIDS = 3;
var RESPONSE_RETURN_VALUES = 4;
/**
* Utility to catch errors and prevent having to bind, or execute a bound
* function, while catching errors in a process and returning a resulting
* return value. This ensures that even if a process fails, we can still return
* *some* values (from `_flushedQueueUnguarded` for example). Glorified
* try/catch/finally that invokes the global `onerror`.
*
* @param {function} operation Function to execute, likely populates the
* message buffer.
* @param {Array<*>} operationArguments Arguments passed to `operation`.
* @param {function} getReturnValue Returns a return value - will be invoked
* even if the `operation` fails half way through completing its task.
* @return {object} Return value returned from `getReturnValue`.
*/
var guardReturn = function(operation, operationArguments, getReturnValue, context) {
if (operation) {
ErrorUtils.applyWithGuard(operation, context, operationArguments);
}
if (getReturnValue) {
return ErrorUtils.applyWithGuard(getReturnValue, context, null);
}
return null;
};
/**
* Bookkeeping logic for callbackIDs. We ensure that success and error
* callbacks are numerically adjacent.
*
* We could have also stored the association between success cbID and errorCBID
* in a map without relying on this adjacency, but the bookkeeping here avoids
* an additional two maps to associate in each direction, and avoids growing
* dictionaries (new fields). Instead, we compute pairs of callback IDs, by
* populating the `res` argument to `allocateCallbackIDs` (in conjunction with
* pooling). Behind this bookeeping API, we ensure that error and success
* callback IDs are always adjacent so that when one is invoked, we always know
* how to free the memory of the other. By using this API, it is impossible to
* create malformed callbackIDs that are not adjacent.
*/
var createBookkeeping = function() {
return {
/**
* Incrementing callback ID. Must start at 1 - otherwise converted null
* values which become zero are not distinguishable from a GUID of zero.
*/
GUID: 1,
errorCallbackIDForSuccessCallbackID: function(successID) {
return successID + 1;
},
successCallbackIDForErrorCallbackID: function(errorID) {
return errorID - 1;
},
allocateCallbackIDs: function(res) {
res.successCallbackID = this.GUID++;
res.errorCallbackID = this.GUID++;
},
isSuccessCallback: function(id) {
return id % 2 === 1;
}
};
};
var MessageQueueMixin = {
/**
* Creates an efficient wire protocol for communicating across a bridge.
* Avoids allocating strings.
*
* @param {object} remoteModulesConfig Configuration of modules and their
* methods.
*/
_initNamingMap: function(remoteModulesConfig, localModulesConfig) {
this._remoteModuleNameToModuleID = {};
this._remoteModuleIDToModuleName = {}; // Reverse
this._remoteModuleNameToMethodNameToID = {};
this._remoteModuleNameToMethodIDToName = {}; // Reverse
this._localModuleNameToModuleID = {};
this._localModuleIDToModuleName = {}; // Reverse
this._localModuleNameToMethodNameToID = {};
this._localModuleNameToMethodIDToName = {}; // Reverse
function fillMappings(
modulesConfig,
moduleNameToModuleID,
moduleIDToModuleName,
moduleNameToMethodNameToID,
moduleNameToMethodIDToName
) {
for (var moduleName in modulesConfig) {
var moduleConfig = modulesConfig[moduleName];
var moduleID = moduleConfig.moduleID;
moduleNameToModuleID[moduleName] = moduleID;
moduleIDToModuleName[moduleID] = moduleName; // Reverse
moduleNameToMethodNameToID[moduleName] = {};
moduleNameToMethodIDToName[moduleName] = {}; // Reverse
var methods = moduleConfig.methods;
for (var methodName in methods) {
var methodID = methods[methodName].methodID;
moduleNameToMethodNameToID[moduleName][methodName] =
methodID;
moduleNameToMethodIDToName[moduleName][methodID] =
methodName; // Reverse
}
}
}
fillMappings(
remoteModulesConfig,
this._remoteModuleNameToModuleID,
this._remoteModuleIDToModuleName,
this._remoteModuleNameToMethodNameToID,
this._remoteModuleNameToMethodIDToName
);
fillMappings(
localModulesConfig,
this._localModuleNameToModuleID,
this._localModuleIDToModuleName,
this._localModuleNameToMethodNameToID,
this._localModuleNameToMethodIDToName
);
},
_initBookeeping: function() {
this._POOLED_CBIDS = {errorCallbackID: null, successCallbackID: null};
this._bookkeeping = createBookkeeping();
/**
* Stores callbacks so that we may simulate asynchronous return values from
* other threads. Remote invocations in other threads can pass return values
* back asynchronously to the requesting thread.
*/
this._threadLocalCallbacksByID = [];
this._threadLocalScopesByID = [];
/**
* Memory efficient parallel arrays. Each index cuts through the three
* arrays and forms a remote invocation of methodName(params) whos return
* value will be reported back to the other thread by way of the
* corresponding id in cbIDs. Each entry (A-D in the graphic below),
* represents a work item of the following form:
* - moduleID: ID of module to invoke method from.
* - methodID: ID of method in module to invoke.
* - params: List of params to pass to method.
* - cbID: ID to respond back to originating thread with.
*
* TODO: We can make this even more efficient (memory) by creating a single
* array, that is always pushed `n` elements as a time.
*/
this._outgoingItems = [
/*REQUEST_MODULE_IDS: */ [/* +-+ +-+ +-+ +-+ */],
/*REQUEST_METHOD_IDS: */ [/* |A| |B| |C| |D| */],
/*REQUEST_PARAMSS: */ [/* |-| |-| |-| |-| */],
/*RESPONSE_CBIDS: */ [/* +-+ +-+ +-+ +-+ */],
/* |E| |F| |G| |H| */
/*RESPONSE_RETURN_VALUES: */ [/* +-+ +-+ +-+ +-+ */]
];
/**
* Used to allow returning the buffer, while at the same time clearing it in
* a memory efficient manner.
*/
this._outgoingItemsSwap = [[], [], [], [], []];
},
invokeCallback: function(cbID, args) {
return guardReturn(this._invokeCallback, [cbID, args], null, this);
},
_invokeCallback: function(cbID, args) {
try {
var cb = this._threadLocalCallbacksByID[cbID];
var scope = this._threadLocalScopesByID[cbID];
warning(
cb,
'Cannot find callback with CBID %s. Native module may have invoked ' +
'both the success callback and the error callback.',
cbID
);
cb.apply(scope, args);
} catch(ie_requires_catch) {
throw ie_requires_catch;
} finally {
// Clear out the memory regardless of success or failure.
this._freeResourcesForCallbackID(cbID);
}
},
invokeCallbackAndReturnFlushedQueue: function(cbID, args) {
if (this._enableLogging) {
this._loggedIncomingItems.push([new Date().getTime(), cbID, args]);
}
return guardReturn(
this._invokeCallback,
[cbID, args],
this._flushedQueueUnguarded,
this
);
},
callFunction: function(moduleID, methodID, params) {
return guardReturn(this._callFunction, [moduleID, methodID, params], null, this);
},
_callFunction: function(moduleID, methodID, params) {
var moduleName = this._localModuleIDToModuleName[moduleID];
var methodName = this._localModuleNameToMethodIDToName[moduleName][methodID];
var ret = jsCall(this._requireFunc(moduleName), methodName, params);
return ret;
},
callFunctionReturnFlushedQueue: function(moduleID, methodID, params) {
if (this._enableLogging) {
this._loggedIncomingItems.push([new Date().getTime(), moduleID, methodID, params]);
}
return guardReturn(
this._callFunction,
[moduleID, methodID, params],
this._flushedQueueUnguarded,
this
);
},
setLoggingEnabled: function(enabled) {
this._enableLogging = enabled;
this._loggedIncomingItems = [];
this._loggedOutgoingItems = [[], [], [], [], []];
},
getLoggedIncomingItems: function() {
return this._loggedIncomingItems;
},
getLoggedOutgoingItems: function() {
return this._loggedOutgoingItems;
},
replayPreviousLog: function(previousLog) {
this._outgoingItems = previousLog;
},
/**
* Simple helpers for clearing the queues. This doesn't handle the fact that
* memory in the current buffer is leaked until the next frame or update - but
* that will typically be on the order of < 500ms.
*/
_swapAndReinitializeBuffer: function() {
// Outgoing requests
var currentOutgoingItems = this._outgoingItems;
var nextOutgoingItems = this._outgoingItemsSwap;
nextOutgoingItems[REQUEST_MODULE_IDS].length = 0;
nextOutgoingItems[REQUEST_METHOD_IDS].length = 0;
nextOutgoingItems[REQUEST_PARAMSS].length = 0;
// Outgoing responses
nextOutgoingItems[RESPONSE_CBIDS].length = 0;
nextOutgoingItems[RESPONSE_RETURN_VALUES].length = 0;
this._outgoingItemsSwap = currentOutgoingItems;
this._outgoingItems = nextOutgoingItems;
},
/**
* @param {string} moduleID JS module name.
* @param {methodName} methodName Method in module to invoke.
* @param {array<*>?} params Array representing arguments to method.
* @param {string} cbID Unique ID to pass back in potential response.
*/
_pushRequestToOutgoingItems: function(moduleID, methodName, params) {
this._outgoingItems[REQUEST_MODULE_IDS].push(moduleID);
this._outgoingItems[REQUEST_METHOD_IDS].push(methodName);
this._outgoingItems[REQUEST_PARAMSS].push(params);
if (this._enableLogging) {
this._loggedOutgoingItems[REQUEST_MODULE_IDS].push(moduleID);
this._loggedOutgoingItems[REQUEST_METHOD_IDS].push(methodName);
this._loggedOutgoingItems[REQUEST_PARAMSS].push(params);
}
},
/**
* @param {string} cbID Unique ID that other side of bridge has remembered.
* @param {*} returnValue Return value to pass to callback on other side of
* bridge.
*/
_pushResponseToOutgoingItems: function(cbID, returnValue) {
this._outgoingItems[RESPONSE_CBIDS].push(cbID);
this._outgoingItems[RESPONSE_RETURN_VALUES].push(returnValue);
},
_freeResourcesForCallbackID: function(cbID) {
var correspondingCBID = this._bookkeeping.isSuccessCallback(cbID) ?
this._bookkeeping.errorCallbackIDForSuccessCallbackID(cbID) :
this._bookkeeping.successCallbackIDForErrorCallbackID(cbID);
this._threadLocalCallbacksByID[cbID] = null;
this._threadLocalScopesByID[cbID] = null;
if (this._threadLocalCallbacksByID[correspondingCBID]) {
this._threadLocalCallbacksByID[correspondingCBID] = null;
this._threadLocalScopesByID[correspondingCBID] = null;
}
},
/**
* @param {Function} onFail Function to store in current thread for later
* lookup, when request fails.
* @param {Function} onSucc Function to store in current thread for later
* lookup, when request succeeds.
* @param {Object?=} scope Scope to invoke `cb` with.
* @param {Object?=} res Resulting callback ids. Use `this._POOLED_CBIDS`.
*/
_storeCallbacksInCurrentThread: function(onFail, onSucc, scope) {
invariant(onFail || onSucc, INTERNAL_ERROR);
this._bookkeeping.allocateCallbackIDs(this._POOLED_CBIDS);
var succCBID = this._POOLED_CBIDS.successCallbackID;
var errorCBID = this._POOLED_CBIDS.errorCallbackID;
this._threadLocalCallbacksByID[errorCBID] = onFail;
this._threadLocalCallbacksByID[succCBID] = onSucc;
this._threadLocalScopesByID[errorCBID] = scope;
this._threadLocalScopesByID[succCBID] = scope;
},
/**
* IMPORTANT: There is possibly a timing issue with this form of flushing. We
* are currently not seeing any problems but the potential issue to look out
* for is:
* - While flushing this._outgoingItems contains the work for the other thread
* to perform.
* - To mitigate this, we never allow enqueueing messages if the queue is
* already reserved - as long as it is reserved, it could be in the midst of
* a flush.
*
* If this ever occurs we can easily eliminate the race condition. We can
* completely solve any ambiguity by sending messages such that we'll never
* try to reserve the queue when already reserved. Here's the pseudocode:
*
* var defensiveCopy = efficientDefensiveCopy(this._outgoingItems);
* this._swapAndReinitializeBuffer();
*/
flushedQueue: function() {
return guardReturn(null, null, this._flushedQueueUnguarded, this);
},
_flushedQueueUnguarded: function() {
// Call the functions registred via setImmediate
JSTimersExecution.callImmediates();
var currentOutgoingItems = this._outgoingItems;
this._swapAndReinitializeBuffer();
var ret = currentOutgoingItems[REQUEST_MODULE_IDS].length ||
currentOutgoingItems[RESPONSE_RETURN_VALUES].length ? currentOutgoingItems : null;
return ret;
},
callDeprecated: function(moduleName, methodName, params, cb, scope) {
invariant(
!cb || typeof cb === 'function',
'Last argument (callback) must be function'
);
// Store callback _before_ sending the request, just in case the MailBox
// returns the response in a blocking manner
if (cb) {
this._storeCallbacksInCurrentThread(null, cb, scope, this._POOLED_CBIDS);
params.push(this._POOLED_CBIDS.successCallbackID);
}
var moduleID = this._remoteModuleNameToModuleID[moduleName];
if (moduleID === undefined || moduleID === null) {
throw new Error('Unrecognized module name:' + moduleName);
}
var methodID = this._remoteModuleNameToMethodNameToID[moduleName][methodName];
if (methodID === undefined || moduleID === null) {
throw new Error('Unrecognized method name:' + methodName);
}
this._pushRequestToOutgoingItems(moduleID, methodID, params);
},
call: function(moduleName, methodName, params, onFail, onSucc, scope) {
invariant(
(!onFail || typeof onFail === 'function') &&
(!onSucc || typeof onSucc === 'function'),
'Callbacks must be functions'
);
// Store callback _before_ sending the request, just in case the MailBox
// returns the response in a blocking manner.
if (onFail || onSucc) {
this._storeCallbacksInCurrentThread(onFail, onSucc, scope, this._POOLED_CBIDS);
params.push(this._POOLED_CBIDS.errorCallbackID);
params.push(this._POOLED_CBIDS.successCallbackID);
}
var moduleID = this._remoteModuleNameToModuleID[moduleName];
if (moduleID === undefined || moduleID === null) {
throw new Error('Unrecognized module name:' + moduleName);
}
var methodID = this._remoteModuleNameToMethodNameToID[moduleName][methodName];
if (methodID === undefined || moduleID === null) {
throw new Error('Unrecognized method name:' + methodName);
}
this._pushRequestToOutgoingItems(moduleID, methodID, params);
},
__numPendingCallbacksOnlyUseMeInTestCases: function() {
var callbacks = this._threadLocalCallbacksByID;
var total = 0;
for (var i = 0; i < callbacks.length; i++) {
if (callbacks[i]) {
total++;
}
}
return total;
}
};
Object.assign(MessageQueue.prototype, MessageQueueMixin);
module.exports = MessageQueue;

View File

@@ -0,0 +1,54 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule PixelRatio
*/
'use strict';
var Dimensions = require('Dimensions');
/**
* PixelRatio class gives access to the device pixel density.
*
* Some examples:
* - PixelRatio.get() === 2
* - iPhone 4, 4S
* - iPhone 5, 5c, 5s
* - iPhone 6
*
* - PixelRatio.get() === 3
* - iPhone 6 plus
*
* There are a few use cases for using PixelRatio:
*
* == Displaying a line that's as thin as the device permits
*
* A width of 1 is actually pretty thick on an iPhone 4+, we can do one that's
* thinner using a width of 1 / PixelRatio.get(). It's a technique that works
* on all the devices independent of their pixel density.
*
* style={{ borderWidth: 1 / PixelRatio.get() }}
*
* == Fetching a correctly sized image
*
* You should get a higher resolution image if you are on a high pixel density
* device. A good rule of thumb is to multiply the size of the image you display
* by the pixel ratio.
*
* var image = getImage({
* width: 200 * PixelRatio.get(),
* height: 100 * PixelRatio.get()
* });
* <Image source={image} style={{width: 200, height: 100}} />
*/
class PixelRatio {
static get() {
return Dimensions.get('window').scale;
}
static startDetecting() {
// no-op for iOS, but this is useful for other platforms
}
};
module.exports = PixelRatio;

View File

@@ -0,0 +1,11 @@
/**
* @providesModule Platform
*/
'use strict';
var Platform = {
OS: 'ios',
};
module.exports = Platform;

View File

@@ -0,0 +1,37 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule RCTLog
*/
/* globals nativeLoggingHook */
'use strict';
var invariant = require('invariant');
var levelsMap = {
log: 'log',
info: 'info',
warn: 'warn',
error: 'error',
mustfix: 'error',
};
class RCTLog {
// level one of log, info, warn, error, mustfix
static logIfNoNativeHook() {
var args = Array.prototype.slice.call(arguments);
var level = args.shift();
var logFn = levelsMap[level];
invariant(
logFn,
'Level "' + level + '" not one of ' + Object.keys(levelsMap)
);
if (typeof nativeLoggingHook === 'undefined') {
// We already printed in xcode, so only log here if using a js debugger
console[logFn].apply(console, args);
}
return true;
}
}
module.exports = RCTLog;

View File

@@ -0,0 +1,56 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule RCTRenderingPerf
*/
'use strict';
var ReactDefaultPerf = require('ReactDefaultPerf');
var ReactPerf = require('ReactPerf');
var invariant = require('invariant');
var perfModules = [];
var enabled = false;
var RCTRenderingPerf = {
// Once perf is enabled, it stays enabled
toggle: function() {
console.log('Render perfomance measurements enabled');
enabled = true;
},
start: function() {
if (!enabled) {
return;
}
ReactDefaultPerf.start();
perfModules.forEach((module) => module.start());
},
stop: function() {
if (!enabled) {
return;
}
ReactDefaultPerf.stop();
ReactDefaultPerf.printInclusive();
ReactDefaultPerf.printWasted();
perfModules.forEach((module) => module.stop());
},
register: function(module) {
invariant(
typeof module.start === 'function',
'Perf module should have start() function'
);
invariant(
typeof module.stop === 'function',
'Perf module should have stop() function'
);
perfModules.push(module);
}
};
module.exports = RCTRenderingPerf;

View File

@@ -0,0 +1,97 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule TimerMixin
*/
'use strict';
/**
* Using bare setTimeout, setInterval, setImmediate and
* requestAnimationFrame calls is very dangerous because if you forget to cancel
* the request before the component is unmounted, you risk the callback throwing
* an exception.
*
* If you include TimerMixin, then you can replace your calls
* to `setTimeout(fn, 500)`
* with `this.setTimeout(fn, 500)` (just prepend `this.`)
* and everything will be properly cleaned up for you.
*
* Example:
*
* var Component = React.createClass({
* mixins: [TimerMixin],
* componentDidMount: function() {
* this.setTimeout(
* () => { console.log('I do not leak!'); },
* 500
* );
* }
* });
*/
var setter = function(setter, clearer, array) {
return function(callback, delta) {
var id = setter(() => {
clearer.call(this, id);
callback.apply(this, arguments);
}, delta);
if (!this[array]) {
this[array] = [id];
} else {
this[array].push(id);
}
return id;
};
};
var clearer = function(clearer, array) {
return function(id) {
if (this[array]) {
var index = this[array].indexOf(id);
if (index !== -1) {
this[array].splice(index, 1);
}
}
clearer(id);
};
};
var _timeouts = 'TimerMixin_timeouts';
var _clearTimeout = clearer(clearTimeout, _timeouts);
var _setTimeout = setter(setTimeout, _clearTimeout, _timeouts);
var _intervals = 'TimerMixin_intervals';
var _clearInterval = clearer(clearInterval, _intervals);
var _setInterval = setter(setInterval, () => {/* noop */}, _intervals);
var _immediates = 'TimerMixin_immediates';
var _clearImmediate = clearer(clearImmediate, _immediates);
var _setImmediate = setter(setImmediate, _clearImmediate, _immediates);
var _rafs = 'TimerMixin_rafs';
var _cancelAnimationFrame = clearer(cancelAnimationFrame, _rafs);
var _requestAnimationFrame = setter(requestAnimationFrame, _cancelAnimationFrame, _rafs);
var TimerMixin = {
componentWillUnmount: function() {
this[_timeouts] && this[_timeouts].forEach(this.clearTimeout);
this[_intervals] && this[_intervals].forEach(this.clearInterval);
this[_immediates] && this[_immediates].forEach(this.clearImmediate);
this[_rafs] && this[_rafs].forEach(this.cancelAnimationFrame);
},
setTimeout: _setTimeout,
clearTimeout: _clearTimeout,
setInterval: _setInterval,
clearInterval: _clearInterval,
setImmediate: _setImmediate,
clearImmediate: _clearImmediate,
requestAnimationFrame: _requestAnimationFrame,
cancelAnimationFrame: _cancelAnimationFrame,
};
module.exports = TimerMixin;

View File

@@ -0,0 +1,64 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule createStrictShapeTypeChecker
*/
'use strict';
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
var invariant = require('invariant');
var merge = require('merge');
function createStrictShapeTypeChecker(shapeTypes) {
function checkType(isRequired, props, propName, componentName, location) {
if (!props[propName]) {
if (isRequired) {
invariant(
false,
`Required object \`${propName}\` was not specified in `+
`\`${componentName}\`.`
);
}
return;
}
var propValue = props[propName];
var propType = typeof propValue;
var locationName = ReactPropTypeLocationNames[location];
if (propType !== 'object') {
invariant(
false,
`Invalid ${locationName} \`${propName}\` of type \`${propType}\` ` +
`supplied to \`${componentName}\`, expected \`object\`.`
);
}
// We need to check all keys in case some are required but missing from
// props.
var allKeys = merge(props[propName], shapeTypes);
for (var key in allKeys) {
var checker = shapeTypes[key];
if (!checker) {
invariant(
false,
`Invalid props.${propName} key \`${key}\` supplied to \`${componentName}\`.` +
`\nBad object: ` + JSON.stringify(props[propName], null, ' ') +
`\nValid keys: ` + JSON.stringify(Object.keys(shapeTypes), null, ' ')
);
}
var error = checker(propValue, key, componentName, location);
if (error) {
invariant(
false,
error.message +
`\nBad object: ` + JSON.stringify(props[propName], null, ' ')
);
return error;
}
}
}
var chainedCheckType = checkType.bind(null, false);
chainedCheckType.isRequired = checkType.bind(null, true);
return chainedCheckType;
}
module.exports = createStrictShapeTypeChecker;

View File

@@ -0,0 +1,57 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule deepFreezeAndThrowOnMutationInDev
*/
/**
* If your application is accepting different values for the same field over
* time and is doing a diff on them, you can either (1) create a copy or
* (2) ensure that those values are not mutated behind two passes.
* This function helps you with (2) by freezing the object and throwing if
* the user subsequently modifies the value.
*
* There are two caveats with this function:
* - If the call site is not in strict mode, it will only throw when
* mutating existing fields, adding a new one
* will unfortunately fail silently :(
* - If the object is already frozen or sealed, it will not continue the
* deep traversal and will leave leaf nodes unfrozen.
*
* Freezing the object and adding the throw mechanism is expensive and will
* only be used in DEV.
*/
function deepFreezeAndThrowOnMutationInDev(object) {
if (__DEV__) {
if (typeof object !== 'object' ||
object === null ||
Object.isFrozen(object) ||
Object.isSealed(object)) {
return;
}
for (var key in object) {
if (object.hasOwnProperty(key)) {
object.__defineGetter__(key, identity.bind(null, object[key]));
object.__defineSetter__(key, throwOnImmutableMutation.bind(null, key));
deepFreezeAndThrowOnMutationInDev(object[key]);
}
}
Object.freeze(object);
Object.seal(object);
}
}
function throwOnImmutableMutation(key, value) {
throw Error(
'You attempted to set the key `' + key + '` with the value `' +
JSON.stringify(value) + '` on an object that is meant to be immutable ' +
'and has been frozen.'
);
}
function identity(value) {
return value;
}
module.exports = deepFreezeAndThrowOnMutationInDev;

View File

@@ -0,0 +1,48 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule deepDiffer
* @flow
*/
'use strict';
/*
* @returns {bool} true if different, false if equal
*/
var deepDiffer = function(one: any, two: any): bool {
if (one === two) {
// Short circuit on identical object references instead of traversing them.
return false;
}
if ((typeof one === 'function') && (typeof two === 'function')) {
// We consider all functions equal
return false;
}
if ((typeof one !== 'object') || (one === null)) {
// Primitives can be directly compared
return one !== two;
}
if ((typeof two !== 'object') || (two === null)) {
// We know they are different because the previous case would have triggered
// otherwise.
return true;
}
if (one.constructor !== two.constructor) {
return true;
}
for (var key in one) {
if (deepDiffer(one[key], two[key])) {
return true;
}
}
for (var twoKey in two) {
// The only case we haven't checked yet is keys that are in two but aren't
// in one, which means they are different.
if (one[twoKey] === undefined) {
return true;
}
}
return false;
};
module.exports = deepDiffer;

View File

@@ -0,0 +1,26 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule insetsDiffer
*/
'use strict';
var dummyInsets = {
top: undefined,
left: undefined,
right: undefined,
bottom: undefined,
};
var insetsDiffer = function(one, two) {
one = one || dummyInsets;
two = two || dummyInsets;
return one !== two && (
one.top !== two.top ||
one.left !== two.left ||
one.right !== two.right ||
one.bottom !== two.bottom
);
};
module.exports = insetsDiffer;

View File

@@ -0,0 +1,39 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule matricesDiffer
*/
'use strict';
/**
* Unrolls an array comparison specially for matrices. Prioritizes
* checking of indices that are most likely to change so that the comparison
* bails as early as possible.
*
* @param {MatrixMath.Matrix} one First matrix.
* @param {MatrixMath.Matrix} two Second matrix.
* @return {boolean} Whether or not the two matrices differ.
*/
var matricesDiffer = function(one, two) {
if (one === two) {
return false;
}
return !one || !two ||
one[12] !== two[12] ||
one[13] !== two[13] ||
one[14] !== two[14] ||
one[5] !== two[5] ||
one[10] !== two[10] ||
one[1] !== two[1] ||
one[2] !== two[2] ||
one[3] !== two[3] ||
one[4] !== two[4] ||
one[6] !== two[6] ||
one[7] !== two[7] ||
one[8] !== two[8] ||
one[9] !== two[9] ||
one[11] !== two[11] ||
one[15] !== two[15];
};
module.exports = matricesDiffer;

View File

@@ -0,0 +1,19 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule pointsDiffer
*/
'use strict';
var dummyPoint = {x: undefined, y: undefined};
var pointsDiffer = function(one, two) {
one = one || dummyPoint;
two = two || dummyPoint;
return one !== two && (
one.x !== two.x ||
one.y !== two.y
);
};
module.exports = pointsDiffer;

View File

@@ -0,0 +1,22 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule logError
*/
'use strict';
/**
* Small utility that can be used as an error handler. You cannot just pass
* `console.error` as a failure callback - it's not properly bound. If passes an
* `Error` object, it will print the message and stack.
*/
var logError = function() {
if (arguments.length === 1 && arguments[0] instanceof Error) {
var err = arguments[0];
console.error('Error: "' + err.message + '". Stack:\n' + err.stack);
} else {
console.error.apply(console, arguments);
}
};
module.exports = logError;

View File

@@ -0,0 +1,28 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule mergeFast
*/
'use strict';
/**
* Faster version of `merge` that doesn't check its arguments and
* also merges prototye inherited properties.
*
* @param {object} one Any non-null object.
* @param {object} two Any non-null object.
* @return {object} Merging of two objects, including prototype
* inherited properties.
*/
var mergeFast = function(one, two) {
var ret = {};
for (var keyOne in one) {
ret[keyOne] = one[keyOne];
}
for (var keyTwo in two) {
ret[keyTwo] = two[keyTwo];
}
return ret;
};
module.exports = mergeFast;

View File

@@ -0,0 +1,21 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule mergeIntoFast
*/
'use strict';
/**
* Faster version of `mergeInto` that doesn't check its arguments and
* also copies over prototye inherited properties.
*
* @param {object} one Object to assign to.
* @param {object} two Object to assign from.
*/
var mergeIntoFast = function(one, two) {
for (var keyTwo in two) {
one[keyTwo] = two[keyTwo];
}
};
module.exports = mergeIntoFast;

View File

@@ -0,0 +1,32 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule truncate
*/
'use strict';
var merge = require('merge');
var defaultOptions = {
breakOnWords: true,
minDelta: 10, // Prevents truncating a tiny bit off the end
elipsis: '...',
};
// maxChars (including elipsis)
var truncate = function(str, maxChars, options) {
options = merge(defaultOptions, options);
if (str && str.length &&
str.length - options.minDelta + options.elipsis.length >= maxChars) {
str = str.slice(0, maxChars - options.elipsis.length + 1);
if (options.breakOnWords) {
var ii = Math.max(str.lastIndexOf(' '), str.lastIndexOf('\n'));
str = str.slice(0, ii);
}
str = str.trim() + options.elipsis;
}
return str;
};
module.exports = truncate;

View File

@@ -0,0 +1,20 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule validAttributesFromPropTypes
*/
'use strict'
function validAttributesFromPropTypes(propTypes) {
var validAttributes = {};
for (var key in propTypes) {
var propType = propTypes[key];
if (propType && propType.isNative) {
var diff = propType.differ;
validAttributes[key] = diff ? {diff} : true;
}
}
return validAttributes;
}
module.exports = validAttributesFromPropTypes;