217 lines
6.5 KiB
HTML
217 lines
6.5 KiB
HTML
|
|
<!--
|
||
|
|
@license
|
||
|
|
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
|
||
|
|
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||
|
|
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||
|
|
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||
|
|
Code distributed by Google as part of the polymer project is also
|
||
|
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||
|
|
-->
|
||
|
|
<link rel="import" href="boot.html">
|
||
|
|
|
||
|
|
<script>
|
||
|
|
(function() {
|
||
|
|
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
// Microtask implemented using Mutation Observer
|
||
|
|
let microtaskCurrHandle = 0;
|
||
|
|
let microtaskLastHandle = 0;
|
||
|
|
let microtaskCallbacks = [];
|
||
|
|
let microtaskNodeContent = 0;
|
||
|
|
let microtaskNode = document.createTextNode('');
|
||
|
|
new window.MutationObserver(microtaskFlush).observe(microtaskNode, {characterData: true});
|
||
|
|
|
||
|
|
function microtaskFlush() {
|
||
|
|
const len = microtaskCallbacks.length;
|
||
|
|
for (let i = 0; i < len; i++) {
|
||
|
|
let cb = microtaskCallbacks[i];
|
||
|
|
if (cb) {
|
||
|
|
try {
|
||
|
|
cb();
|
||
|
|
} catch (e) {
|
||
|
|
setTimeout(() => { throw e; });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
microtaskCallbacks.splice(0, len);
|
||
|
|
microtaskLastHandle += len;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Module that provides a number of strategies for enqueuing asynchronous
|
||
|
|
* tasks. Each sub-module provides a standard `run(fn)` interface that returns a
|
||
|
|
* handle, and a `cancel(handle)` interface for canceling async tasks before
|
||
|
|
* they run.
|
||
|
|
*
|
||
|
|
* @namespace
|
||
|
|
* @memberof Polymer
|
||
|
|
* @summary Module that provides a number of strategies for enqueuing asynchronous
|
||
|
|
* tasks.
|
||
|
|
*/
|
||
|
|
Polymer.Async = {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Async interface wrapper around `setTimeout`.
|
||
|
|
*
|
||
|
|
* @namespace
|
||
|
|
* @memberof Polymer.Async
|
||
|
|
* @summary Async interface wrapper around `setTimeout`.
|
||
|
|
*/
|
||
|
|
timeOut: {
|
||
|
|
/**
|
||
|
|
* Returns a sub-module with the async interface providing the provided
|
||
|
|
* delay.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.timeOut
|
||
|
|
* @param {number=} delay Time to wait before calling callbacks in ms
|
||
|
|
* @return {!AsyncInterface} An async timeout interface
|
||
|
|
*/
|
||
|
|
after(delay) {
|
||
|
|
return {
|
||
|
|
run(fn) { return window.setTimeout(fn, delay); },
|
||
|
|
cancel(handle) {
|
||
|
|
window.clearTimeout(handle);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
},
|
||
|
|
/**
|
||
|
|
* Enqueues a function called in the next task.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.timeOut
|
||
|
|
* @param {!Function} fn Callback to run
|
||
|
|
* @param {number=} delay Delay in milliseconds
|
||
|
|
* @return {number} Handle used for canceling task
|
||
|
|
*/
|
||
|
|
run(fn, delay) {
|
||
|
|
return window.setTimeout(fn, delay);
|
||
|
|
},
|
||
|
|
/**
|
||
|
|
* Cancels a previously enqueued `timeOut` callback.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.timeOut
|
||
|
|
* @param {number} handle Handle returned from `run` of callback to cancel
|
||
|
|
* @return {void}
|
||
|
|
*/
|
||
|
|
cancel(handle) {
|
||
|
|
window.clearTimeout(handle);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Async interface wrapper around `requestAnimationFrame`.
|
||
|
|
*
|
||
|
|
* @namespace
|
||
|
|
* @memberof Polymer.Async
|
||
|
|
* @summary Async interface wrapper around `requestAnimationFrame`.
|
||
|
|
*/
|
||
|
|
animationFrame: {
|
||
|
|
/**
|
||
|
|
* Enqueues a function called at `requestAnimationFrame` timing.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.animationFrame
|
||
|
|
* @param {function(number):void} fn Callback to run
|
||
|
|
* @return {number} Handle used for canceling task
|
||
|
|
*/
|
||
|
|
run(fn) {
|
||
|
|
return window.requestAnimationFrame(fn);
|
||
|
|
},
|
||
|
|
/**
|
||
|
|
* Cancels a previously enqueued `animationFrame` callback.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.animationFrame
|
||
|
|
* @param {number} handle Handle returned from `run` of callback to cancel
|
||
|
|
* @return {void}
|
||
|
|
*/
|
||
|
|
cancel(handle) {
|
||
|
|
window.cancelAnimationFrame(handle);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Async interface wrapper around `requestIdleCallback`. Falls back to
|
||
|
|
* `setTimeout` on browsers that do not support `requestIdleCallback`.
|
||
|
|
*
|
||
|
|
* @namespace
|
||
|
|
* @memberof Polymer.Async
|
||
|
|
* @summary Async interface wrapper around `requestIdleCallback`.
|
||
|
|
*/
|
||
|
|
idlePeriod: {
|
||
|
|
/**
|
||
|
|
* Enqueues a function called at `requestIdleCallback` timing.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.idlePeriod
|
||
|
|
* @param {function(!IdleDeadline):void} fn Callback to run
|
||
|
|
* @return {number} Handle used for canceling task
|
||
|
|
*/
|
||
|
|
run(fn) {
|
||
|
|
return window.requestIdleCallback ?
|
||
|
|
window.requestIdleCallback(fn) :
|
||
|
|
window.setTimeout(fn, 16);
|
||
|
|
},
|
||
|
|
/**
|
||
|
|
* Cancels a previously enqueued `idlePeriod` callback.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.idlePeriod
|
||
|
|
* @param {number} handle Handle returned from `run` of callback to cancel
|
||
|
|
* @return {void}
|
||
|
|
*/
|
||
|
|
cancel(handle) {
|
||
|
|
window.cancelIdleCallback ?
|
||
|
|
window.cancelIdleCallback(handle) :
|
||
|
|
window.clearTimeout(handle);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Async interface for enqueuing callbacks that run at microtask timing.
|
||
|
|
*
|
||
|
|
* Note that microtask timing is achieved via a single `MutationObserver`,
|
||
|
|
* and thus callbacks enqueued with this API will all run in a single
|
||
|
|
* batch, and not interleaved with other microtasks such as promises.
|
||
|
|
* Promises are avoided as an implementation choice for the time being
|
||
|
|
* due to Safari bugs that cause Promises to lack microtask guarantees.
|
||
|
|
*
|
||
|
|
* @namespace
|
||
|
|
* @memberof Polymer.Async
|
||
|
|
* @summary Async interface for enqueuing callbacks that run at microtask
|
||
|
|
* timing.
|
||
|
|
*/
|
||
|
|
microTask: {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Enqueues a function called at microtask timing.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.microTask
|
||
|
|
* @param {!Function=} callback Callback to run
|
||
|
|
* @return {number} Handle used for canceling task
|
||
|
|
*/
|
||
|
|
run(callback) {
|
||
|
|
microtaskNode.textContent = microtaskNodeContent++;
|
||
|
|
microtaskCallbacks.push(callback);
|
||
|
|
return microtaskCurrHandle++;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Cancels a previously enqueued `microTask` callback.
|
||
|
|
*
|
||
|
|
* @memberof Polymer.Async.microTask
|
||
|
|
* @param {number} handle Handle returned from `run` of callback to cancel
|
||
|
|
* @return {void}
|
||
|
|
*/
|
||
|
|
cancel(handle) {
|
||
|
|
const idx = handle - microtaskLastHandle;
|
||
|
|
if (idx >= 0) {
|
||
|
|
if (!microtaskCallbacks[idx]) {
|
||
|
|
throw new Error('invalid async handle: ' + handle);
|
||
|
|
}
|
||
|
|
microtaskCallbacks[idx] = null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
})();
|
||
|
|
</script>
|