UNPKG

preemptive-animation-frame

Version:
115 lines (97 loc) 10.6 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.forceAnimationFrame = exports.cancelAnimationFrame = exports.requestAnimationFrame = exports.now = undefined; var _requestPolyfilledAnimationFrame = require('request-polyfilled-animation-frame'); var RAF = _interopRequireWildcard(_requestPolyfilledAnimationFrame); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } // Invariants: // 1. In the NO_REQUEST state, there is never a scheduled animation frame. // 2. In the PENDING_REQUEST and EXTRA_REQUEST states, there is always exactly // one scheduled animation frame. var NO_REQUEST = 0; var PENDING_REQUEST = 1; var EXTRA_REQUEST = 2; var requestID = null; var nextID = 0; var state = NO_REQUEST; var requests = []; var ids = []; var absent = new Error('absent'); var now = exports.now = RAF.now; var requestAnimationFrame = exports.requestAnimationFrame = function requestAnimationFrame(request) { if (state === NO_REQUEST) { requestID = RAF.requestAnimationFrame(performAnimationFrame); } var id = ++nextID; requests.push(request); ids.push(id); state = PENDING_REQUEST; return id; }; var cancelAnimationFrame = exports.cancelAnimationFrame = function cancelAnimationFrame(id) { var index = ids.indexOf(id); if (index >= 0) { ids.splice(index, 1); requests.splice(index, 1); } }; var forceAnimationFrame = exports.forceAnimationFrame = function forceAnimationFrame() { var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : now(); switch (state) { case NO_REQUEST: break; default: if (requestID != null) { RAF.cancelAnimationFrame(requestID); requestID = null; } performAnimationFrame(time); } }; var performAnimationFrame = function performAnimationFrame(time) { switch (state) { case NO_REQUEST: // This state should not be possible. How can there be no // request, yet somehow we are actively fulfilling a // request? throw Error('Unexpected frame request'); case PENDING_REQUEST: // At this point, we do not *know* that another frame is // needed, but we make an extra frame request just in // case. It's possible to drop a frame if frame is requested // too late, so we just do it preemptively. requestID = RAF.requestAnimationFrame(performAnimationFrame); state = EXTRA_REQUEST; ids.splice(0); dispatchAnimationFrame(requests.splice(0), 0, time); break; case EXTRA_REQUEST: // Turns out the extra request was not needed, so we will // stop requesting. No reason to call it all the time if // no one needs it. state = NO_REQUEST; break; } }; var dispatchAnimationFrame = function dispatchAnimationFrame(requests, index, time) { var exception = absent; var count = requests.length; try { while (index < count) { var request = requests[index]; index = index + 1; request(time); } } catch (error) { exception = error; } if (index < count) { dispatchAnimationFrame(requests, index, time); } if (exception !== absent) { throw exception; } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9wcmVlbXB0aXZlLWFuaW1hdGlvbi1mcmFtZS5qcyJdLCJuYW1lcyI6WyJSQUYiLCJOT19SRVFVRVNUIiwiUEVORElOR19SRVFVRVNUIiwiRVhUUkFfUkVRVUVTVCIsInJlcXVlc3RJRCIsIm5leHRJRCIsInN0YXRlIiwicmVxdWVzdHMiLCJpZHMiLCJhYnNlbnQiLCJFcnJvciIsIm5vdyIsInJlcXVlc3RBbmltYXRpb25GcmFtZSIsInJlcXVlc3QiLCJwZXJmb3JtQW5pbWF0aW9uRnJhbWUiLCJpZCIsInB1c2giLCJjYW5jZWxBbmltYXRpb25GcmFtZSIsImluZGV4IiwiaW5kZXhPZiIsInNwbGljZSIsImZvcmNlQW5pbWF0aW9uRnJhbWUiLCJ0aW1lIiwiZGlzcGF0Y2hBbmltYXRpb25GcmFtZSIsImV4Y2VwdGlvbiIsImNvdW50IiwibGVuZ3RoIiwiZXJyb3IiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFFQTs7SUFBWUEsRzs7OztBQUtaO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBTUMsYUFBYSxDQUFuQjs7QUFDQSxJQUFNQyxrQkFBa0IsQ0FBeEI7QUFDQSxJQUFNQyxnQkFBZ0IsQ0FBdEI7O0FBRUEsSUFBSUMsWUFBb0IsSUFBeEI7QUFDQSxJQUFJQyxTQUFnQixDQUFwQjtBQUNBLElBQUlDLFFBQWNMLFVBQWxCO0FBQ0EsSUFBSU0sV0FBcUMsRUFBekM7QUFDQSxJQUFJQyxNQUFvQixFQUF4Qjs7QUFFQSxJQUFNQyxTQUFTLElBQUlDLEtBQUosQ0FBVSxRQUFWLENBQWY7O0FBRU8sSUFBTUMsb0JBQU1YLElBQUlXLEdBQWhCOztBQUVBLElBQU1DLHdEQUF3QixTQUF4QkEscUJBQXdCLENBQUtDLE9BQUwsRUFBa0M7QUFDckUsTUFBSVAsVUFBVUwsVUFBZCxFQUEwQjtBQUN4QkcsZ0JBQVlKLElBQUlZLHFCQUFKLENBQTBCRSxxQkFBMUIsQ0FBWjtBQUNEOztBQUVELE1BQU1DLEtBQUssRUFBRVYsTUFBYjtBQUNBRSxXQUFTUyxJQUFULENBQWNILE9BQWQ7QUFDQUwsTUFBSVEsSUFBSixDQUFTRCxFQUFUO0FBQ0FULFVBQVFKLGVBQVI7QUFDQSxTQUFPYSxFQUFQO0FBQ0QsQ0FWTTs7QUFZQSxJQUFNRSxzREFDWCxTQURXQSxvQkFDWCxDQUFDRixFQUFELEVBQW9CO0FBQ2xCLE1BQU1HLFFBQVFWLElBQUlXLE9BQUosQ0FBWUosRUFBWixDQUFkO0FBQ0EsTUFBSUcsU0FBUyxDQUFiLEVBQWdCO0FBQ2RWLFFBQUlZLE1BQUosQ0FBV0YsS0FBWCxFQUFrQixDQUFsQjtBQUNBWCxhQUFTYSxNQUFULENBQWdCRixLQUFoQixFQUF1QixDQUF2QjtBQUNEO0FBQ0YsQ0FQSTs7QUFTQSxJQUFNRyxvREFDWCxTQURXQSxtQkFDWCxHQUFxQjtBQUFBLE1BQXBCQyxJQUFvQix1RUFBVlgsS0FBVTs7QUFDbkIsVUFBUUwsS0FBUjtBQUNFLFNBQUtMLFVBQUw7QUFDRTtBQUNGO0FBQ0UsVUFBSUcsYUFBYSxJQUFqQixFQUF1QjtBQUNyQkosWUFBSWlCLG9CQUFKLENBQXlCYixTQUF6QjtBQUNBQSxvQkFBWSxJQUFaO0FBQ0Q7QUFDRFUsNEJBQXNCUSxJQUF0QjtBQVJKO0FBVUQsQ0FaSTs7QUFjUCxJQUFNUix3QkFDSixTQURJQSxxQkFDSixDQUFDUSxJQUFELEVBQWU7QUFDYixVQUFRaEIsS0FBUjtBQUNFLFNBQUtMLFVBQUw7QUFDRTtBQUNBO0FBQ0E7QUFDQSxZQUFNUyxNQUFNLDBCQUFOLENBQU47QUFDRixTQUFLUixlQUFMO0FBQ0U7QUFDQTtBQUNBO0FBQ0E7QUFDQUUsa0JBQVlKLElBQUlZLHFCQUFKLENBQTBCRSxxQkFBMUIsQ0FBWjtBQUNBUixjQUFRSCxhQUFSO0FBQ0FLLFVBQUlZLE1BQUosQ0FBVyxDQUFYO0FBQ0FHLDZCQUF1QmhCLFNBQVNhLE1BQVQsQ0FBZ0IsQ0FBaEIsQ0FBdkIsRUFBMkMsQ0FBM0MsRUFBOENFLElBQTlDO0FBQ0E7QUFDRixTQUFLbkIsYUFBTDtBQUNFO0FBQ0E7QUFDQTtBQUNBRyxjQUFRTCxVQUFSO0FBQ0E7QUFyQko7QUF1QkQsQ0F6Qkg7O0FBMkJBLElBQU1zQix5QkFBeUIsU0FBekJBLHNCQUF5QixDQUFLaEIsUUFBTCxFQUNLVyxLQURMLEVBRUtJLElBRkwsRUFFbUI7QUFDaEQsTUFBSUUsWUFBWWYsTUFBaEI7QUFDQSxNQUFNZ0IsUUFBUWxCLFNBQVNtQixNQUF2QjtBQUNBLE1BQUk7QUFDRixXQUFPUixRQUFRTyxLQUFmLEVBQXNCO0FBQ3BCLFVBQU1aLFVBQVVOLFNBQVNXLEtBQVQsQ0FBaEI7QUFDQUEsY0FBUUEsUUFBUSxDQUFoQjtBQUNBTCxjQUFRUyxJQUFSO0FBQ0Q7QUFDRixHQU5ELENBTUUsT0FBT0ssS0FBUCxFQUFjO0FBQ2RILGdCQUFZRyxLQUFaO0FBQ0Q7O0FBRUQsTUFBSVQsUUFBUU8sS0FBWixFQUFtQjtBQUNqQkYsMkJBQXVCaEIsUUFBdkIsRUFBaUNXLEtBQWpDLEVBQXdDSSxJQUF4QztBQUNEOztBQUVELE1BQUlFLGNBQWNmLE1BQWxCLEVBQTBCO0FBQ3hCLFVBQU1lLFNBQU47QUFDRDtBQUNGLENBdEJEIiwiZmlsZSI6InByZWVtcHRpdmUtYW5pbWF0aW9uLWZyYW1lLmpzIiwic291cmNlUm9vdCI6InNyYyIsInNvdXJjZXNDb250ZW50IjpbIi8qIEBmbG93ICovXG5cbmltcG9ydCAqIGFzIFJBRiBmcm9tICdyZXF1ZXN0LXBvbHlmaWxsZWQtYW5pbWF0aW9uLWZyYW1lJ1xuXG50eXBlIFRpbWUgPSBudW1iZXJcbnR5cGUgU3RhdGUgPSAwIHwgMSB8IDJcblxuLy8gSW52YXJpYW50czpcbi8vIDEuIEluIHRoZSBOT19SRVFVRVNUIHN0YXRlLCB0aGVyZSBpcyBuZXZlciBhIHNjaGVkdWxlZCBhbmltYXRpb24gZnJhbWUuXG4vLyAyLiBJbiB0aGUgUEVORElOR19SRVFVRVNUIGFuZCBFWFRSQV9SRVFVRVNUIHN0YXRlcywgdGhlcmUgaXMgYWx3YXlzIGV4YWN0bHlcbi8vIG9uZSBzY2hlZHVsZWQgYW5pbWF0aW9uIGZyYW1lLlxuY29uc3QgTk9fUkVRVUVTVCA9IDBcbmNvbnN0IFBFTkRJTkdfUkVRVUVTVCA9IDFcbmNvbnN0IEVYVFJBX1JFUVVFU1QgPSAyXG5cbmxldCByZXF1ZXN0SUQ6P251bWJlciA9IG51bGxcbmxldCBuZXh0SUQ6bnVtYmVyID0gMFxubGV0IHN0YXRlOlN0YXRlID0gTk9fUkVRVUVTVFxubGV0IHJlcXVlc3RzOkFycmF5PCh0aW1lOlRpbWUpID0+IGFueT4gPSBbXVxubGV0IGlkczpBcnJheTxudW1iZXI+ID0gW11cblxuY29uc3QgYWJzZW50ID0gbmV3IEVycm9yKCdhYnNlbnQnKVxuXG5leHBvcnQgY29uc3Qgbm93ID0gUkFGLm5vd1xuXG5leHBvcnQgY29uc3QgcmVxdWVzdEFuaW1hdGlvbkZyYW1lID0gPGE+IChyZXF1ZXN0Oih0aW1lOlRpbWUpID0+IGEpID0+IHtcbiAgaWYgKHN0YXRlID09PSBOT19SRVFVRVNUKSB7XG4gICAgcmVxdWVzdElEID0gUkFGLnJlcXVlc3RBbmltYXRpb25GcmFtZShwZXJmb3JtQW5pbWF0aW9uRnJhbWUpXG4gIH1cblxuICBjb25zdCBpZCA9ICsrbmV4dElEXG4gIHJlcXVlc3RzLnB1c2gocmVxdWVzdClcbiAgaWRzLnB1c2goaWQpXG4gIHN0YXRlID0gUEVORElOR19SRVFVRVNUXG4gIHJldHVybiBpZFxufVxuXG5leHBvcnQgY29uc3QgY2FuY2VsQW5pbWF0aW9uRnJhbWUgPVxuICAoaWQ6bnVtYmVyKTp2b2lkID0+IHtcbiAgICBjb25zdCBpbmRleCA9IGlkcy5pbmRleE9mKGlkKVxuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICBpZHMuc3BsaWNlKGluZGV4LCAxKVxuICAgICAgcmVxdWVzdHMuc3BsaWNlKGluZGV4LCAxKVxuICAgIH1cbiAgfVxuXG5leHBvcnQgY29uc3QgZm9yY2VBbmltYXRpb25GcmFtZSA9XG4gICh0aW1lOlRpbWU9bm93KCkpID0+IHtcbiAgICBzd2l0Y2ggKHN0YXRlKSB7XG4gICAgICBjYXNlIE5PX1JFUVVFU1Q6XG4gICAgICAgIGJyZWFrXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAocmVxdWVzdElEICE9IG51bGwpIHtcbiAgICAgICAgICBSQUYuY2FuY2VsQW5pbWF0aW9uRnJhbWUocmVxdWVzdElEKVxuICAgICAgICAgIHJlcXVlc3RJRCA9IG51bGxcbiAgICAgICAgfVxuICAgICAgICBwZXJmb3JtQW5pbWF0aW9uRnJhbWUodGltZSlcbiAgICB9XG4gIH1cblxuY29uc3QgcGVyZm9ybUFuaW1hdGlvbkZyYW1lID1cbiAgKHRpbWU6VGltZSkgPT4ge1xuICAgIHN3aXRjaCAoc3RhdGUpIHtcbiAgICAgIGNhc2UgTk9fUkVRVUVTVDpcbiAgICAgICAgLy8gVGhpcyBzdGF0ZSBzaG91bGQgbm90IGJlIHBvc3NpYmxlLiBIb3cgY2FuIHRoZXJlIGJlIG5vXG4gICAgICAgIC8vIHJlcXVlc3QsIHlldCBzb21laG93IHdlIGFyZSBhY3RpdmVseSBmdWxmaWxsaW5nIGFcbiAgICAgICAgLy8gcmVxdWVzdD9cbiAgICAgICAgdGhyb3cgRXJyb3IoJ1VuZXhwZWN0ZWQgZnJhbWUgcmVxdWVzdCcpXG4gICAgICBjYXNlIFBFTkRJTkdfUkVRVUVTVDpcbiAgICAgICAgLy8gQXQgdGhpcyBwb2ludCwgd2UgZG8gbm90ICprbm93KiB0aGF0IGFub3RoZXIgZnJhbWUgaXNcbiAgICAgICAgLy8gbmVlZGVkLCBidXQgd2UgbWFrZSBhbiBleHRyYSBmcmFtZSByZXF1ZXN0IGp1c3QgaW5cbiAgICAgICAgLy8gY2FzZS4gSXQncyBwb3NzaWJsZSB0byBkcm9wIGEgZnJhbWUgaWYgZnJhbWUgaXMgcmVxdWVzdGVkXG4gICAgICAgIC8vIHRvbyBsYXRlLCBzbyB3ZSBqdXN0IGRvIGl0IHByZWVtcHRpdmVseS5cbiAgICAgICAgcmVxdWVzdElEID0gUkFGLnJlcXVlc3RBbmltYXRpb25GcmFtZShwZXJmb3JtQW5pbWF0aW9uRnJhbWUpXG4gICAgICAgIHN0YXRlID0gRVhUUkFfUkVRVUVTVFxuICAgICAgICBpZHMuc3BsaWNlKDApXG4gICAgICAgIGRpc3BhdGNoQW5pbWF0aW9uRnJhbWUocmVxdWVzdHMuc3BsaWNlKDApLCAwLCB0aW1lKVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSBFWFRSQV9SRVFVRVNUOlxuICAgICAgICAvLyBUdXJucyBvdXQgdGhlIGV4dHJhIHJlcXVlc3Qgd2FzIG5vdCBuZWVkZWQsIHNvIHdlIHdpbGxcbiAgICAgICAgLy8gc3RvcCByZXF1ZXN0aW5nLiBObyByZWFzb24gdG8gY2FsbCBpdCBhbGwgdGhlIHRpbWUgaWZcbiAgICAgICAgLy8gbm8gb25lIG5lZWRzIGl0LlxuICAgICAgICBzdGF0ZSA9IE5PX1JFUVVFU1RcbiAgICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuY29uc3QgZGlzcGF0Y2hBbmltYXRpb25GcmFtZSA9IDxhPiAocmVxdWVzdHM6QXJyYXk8KHRpbWU6VGltZSkgPT4gYT4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleDpudW1iZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lOlRpbWUpID0+IHtcbiAgbGV0IGV4Y2VwdGlvbiA9IGFic2VudFxuICBjb25zdCBjb3VudCA9IHJlcXVlc3RzLmxlbmd0aFxuICB0cnkge1xuICAgIHdoaWxlIChpbmRleCA8IGNvdW50KSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gcmVxdWVzdHNbaW5kZXhdXG4gICAgICBpbmRleCA9IGluZGV4ICsgMVxuICAgICAgcmVxdWVzdCh0aW1lKVxuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBleGNlcHRpb24gPSBlcnJvclxuICB9XG5cbiAgaWYgKGluZGV4IDwgY291bnQpIHtcbiAgICBkaXNwYXRjaEFuaW1hdGlvbkZyYW1lKHJlcXVlc3RzLCBpbmRleCwgdGltZSlcbiAgfVxuXG4gIGlmIChleGNlcHRpb24gIT09IGFic2VudCkge1xuICAgIHRocm93IGV4Y2VwdGlvblxuICB9XG59XG4iXX0=