[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/timers/ -> timers.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 Yahoo! Inc. All rights reserved.
   4  Licensed under the BSD License.
   5  http://yuilibrary.com/license/
   6  */
   7  
   8  YUI.add('timers', function (Y, NAME) {
   9  
  10  /**
  11  Provides utilities for timed asynchronous callback execution.
  12  Y.soon is a setImmediate/process.nextTick/setTimeout wrapper.
  13  
  14  This module includes [asap.js](https://github.com/kriskowal/asap) for scheduling
  15  asynchronous tasks.
  16  
  17  @module timers
  18  @author Steven Olmsted
  19  **/
  20  
  21  // Hack. asap.js is written as a Node module and expects require, module and
  22  // global to be available in the module's scope.
  23  var module = {},
  24      global = Y.config.global;
  25  
  26  // `asap` only requires a `queue` module that is bundled into this same file.
  27  function require(mod) {
  28      return Queue;
  29  }
  30  "use strict";
  31  
  32  module.exports = Queue;
  33  function Queue(capacity) {
  34      this.capacity = this.snap(capacity);
  35      this.length = 0;
  36      this.front = 0;
  37      this.initialize();
  38  }
  39  
  40  Queue.prototype.push = function (value) {
  41      var length = this.length;
  42      if (this.capacity <= length) {
  43          this.grow(this.snap(this.capacity * this.growFactor));
  44      }
  45      var index = (this.front + length) & (this.capacity - 1);
  46      this[index] = value;
  47      this.length = length + 1;
  48  };
  49  
  50  Queue.prototype.shift = function () {
  51      var front = this.front;
  52      var result = this[front];
  53  
  54      this[front] = void 0;
  55      this.front = (front + 1) & (this.capacity - 1);
  56      this.length--;
  57      return result;
  58  };
  59  
  60  Queue.prototype.grow = function (capacity) {
  61      var oldFront = this.front;
  62      var oldCapacity = this.capacity;
  63      var oldQueue = new Array(oldCapacity);
  64      var length = this.length;
  65  
  66      copy(this, 0, oldQueue, 0, oldCapacity);
  67      this.capacity = capacity;
  68      this.initialize();
  69      this.front = 0;
  70      if (oldFront + length <= oldCapacity) {
  71          // Can perform direct linear copy
  72          copy(oldQueue, oldFront, this, 0, length);
  73      } else {
  74          // Cannot perform copy directly, perform as much as possible at the
  75          // end, and then copy the rest to the beginning of the buffer
  76          var lengthBeforeWrapping =
  77              length - ((oldFront + length) & (oldCapacity - 1));
  78          copy(
  79              oldQueue,
  80              oldFront,
  81              this,
  82              0,
  83              lengthBeforeWrapping
  84          );
  85          copy(
  86              oldQueue,
  87              0,
  88              this,
  89              lengthBeforeWrapping,
  90              length - lengthBeforeWrapping
  91          );
  92      }
  93  };
  94  
  95  Queue.prototype.initialize = function () {
  96      var length = this.capacity;
  97      for (var i = 0; i < length; ++i) {
  98          this[i] = void 0;
  99      }
 100  };
 101  
 102  Queue.prototype.snap = function (capacity) {
 103      if (typeof capacity !== "number") {
 104          return this.minCapacity;
 105      }
 106      return pow2AtLeast(
 107          Math.min(this.maxCapacity, Math.max(this.minCapacity, capacity))
 108      );
 109  };
 110  
 111  Queue.prototype.maxCapacity = (1 << 30) | 0;
 112  Queue.prototype.minCapacity = 16;
 113  Queue.prototype.growFactor = 8;
 114  
 115  function copy(source, sourceIndex, target, targetIndex, length) {
 116      for (var index = 0; index < length; ++index) {
 117          target[index + targetIndex] = source[index + sourceIndex];
 118      }
 119  }
 120  
 121  function pow2AtLeast(n) {
 122      n = n >>> 0;
 123      n = n - 1;
 124      n = n | (n >> 1);
 125      n = n | (n >> 2);
 126      n = n | (n >> 4);
 127      n = n | (n >> 8);
 128      n = n | (n >> 16);
 129      return n + 1;
 130  }
 131  "use strict";
 132  
 133  // Use the fastest possible means to execute a task in a future turn
 134  // of the event loop.
 135  
 136  // Queue is a circular buffer with good locality of reference and doesn't
 137  // allocate new memory unless there are more than `InitialCapacity` parallel
 138  // tasks in which case it will resize itself generously to x8 more capacity.
 139  // The use case of asap should require no or few amount of resizes during
 140  // runtime.
 141  // Calling a task frees a slot immediately so if the calling
 142  // has a side effect of queuing itself again, it can be sustained
 143  // without additional memory
 144  // Queue specifically uses
 145  // http://en.wikipedia.org/wiki/Circular_buffer#Use_a_Fill_Count
 146  // Because:
 147  // 1. We need fast .length operation, since queue
 148  //   could have changed after every iteration
 149  // 2. Modulus can be negated by using power-of-two
 150  //   capacities and replacing it with bitwise AND
 151  // 3. It will not be used in a multi-threaded situation.
 152  
 153  var Queue = require("./queue");
 154  
 155  //1024 = InitialCapacity
 156  var queue = new Queue(1024);
 157  var flushing = false;
 158  var requestFlush = void 0;
 159  var hasSetImmediate = typeof setImmediate === "function";
 160  var domain;
 161  
 162  // Avoid shims from browserify.
 163  // The existence of `global` in browsers is guaranteed by browserify.
 164  var process = global.process;
 165  
 166  // Note that some fake-Node environments,
 167  // like the Mocha test runner, introduce a `process` global.
 168  var isNodeJS = !!process && ({}).toString.call(process) === "[object process]";
 169  
 170  function flush() {
 171      /* jshint loopfunc: true */
 172  
 173      while (queue.length > 0) {
 174          var task = queue.shift();
 175  
 176          try {
 177              task.call();
 178  
 179          } catch (e) {
 180              if (isNodeJS) {
 181                  // In node, uncaught exceptions are considered fatal errors.
 182                  // Re-throw them to interrupt flushing!
 183  
 184                  // Ensure continuation if an uncaught exception is suppressed
 185                  // listening process.on("uncaughtException") or domain("error").
 186                  requestFlush();
 187  
 188                  throw e;
 189  
 190              } else {
 191                  // In browsers, uncaught exceptions are not fatal.
 192                  // Re-throw them asynchronously to avoid slow-downs.
 193                  setTimeout(function () {
 194                      throw e;
 195                  }, 0);
 196              }
 197          }
 198      }
 199  
 200      flushing = false;
 201  }
 202  
 203  if (isNodeJS) {
 204      // Node.js
 205      requestFlush = function () {
 206          // Ensure flushing is not bound to any domain.
 207          var currentDomain = process.domain;
 208          if (currentDomain) {
 209              domain = domain || (1,require)("domain");
 210              domain.active = process.domain = null;
 211          }
 212  
 213          // Avoid tick recursion - use setImmediate if it exists.
 214          if (flushing && hasSetImmediate) {
 215              setImmediate(flush);
 216          } else {
 217              process.nextTick(flush);
 218          }
 219  
 220          if (currentDomain) {
 221              domain.active = process.domain = currentDomain;
 222          }
 223      };
 224  
 225  } else if (hasSetImmediate) {
 226      // In IE10, or https://github.com/NobleJS/setImmediate
 227      requestFlush = function () {
 228          setImmediate(flush);
 229      };
 230  
 231  } else if (typeof MessageChannel !== "undefined") {
 232      // modern browsers
 233      // http://www.nonblocking.io/2011/06/windownexttick.html
 234      var channel = new MessageChannel();
 235      // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
 236      // working message ports the first time a page loads.
 237      channel.port1.onmessage = function () {
 238          requestFlush = requestPortFlush;
 239          channel.port1.onmessage = flush;
 240          flush();
 241      };
 242      var requestPortFlush = function () {
 243          // Opera requires us to provide a message payload, regardless of
 244          // whether we use it.
 245          channel.port2.postMessage(0);
 246      };
 247      requestFlush = function () {
 248          setTimeout(flush, 0);
 249          requestPortFlush();
 250      };
 251  
 252  } else {
 253      // old browsers
 254      requestFlush = function () {
 255          setTimeout(flush, 0);
 256      };
 257  }
 258  
 259  function asap(task) {
 260      if (isNodeJS && process.domain) {
 261          task = process.domain.bind(task);
 262      }
 263  
 264      queue.push(task);
 265  
 266      if (!flushing) {
 267          requestFlush();
 268          flushing = true;
 269      }
 270  };
 271  
 272  module.exports = asap;
 273  /**
 274  Y.soon accepts a callback function.  The callback function will be called
 275  once in a future turn of the JavaScript event loop.  If the function
 276  requires a specific execution context or arguments, wrap it with Y.bind.
 277  Y.soon returns an object with a cancel method.  If the cancel method is
 278  called before the callback function, the callback function won't be
 279  called.
 280  
 281  @method soon
 282  @for YUI
 283  @param {Function} callbackFunction
 284  @return {Object} An object with a cancel method.  If the cancel method is
 285      called before the callback function, the callback function won't be
 286      called.
 287  **/
 288  function soon(callbackFunction) {
 289      var canceled;
 290  
 291      soon._asynchronizer(function () {
 292          // Some asynchronizers may provide their own cancellation
 293          // methods such as clearImmediate or clearTimeout but some
 294          // asynchronizers do not.  For simplicity, cancellation is
 295          // entirely handled here rather than wrapping the other methods.
 296          // All asynchronizers are expected to always call this anonymous
 297          // function.
 298          if (!canceled) {
 299              callbackFunction();
 300          }
 301      });
 302  
 303      return {
 304          cancel: function () {
 305              canceled = 1;
 306          }
 307      };
 308  }
 309  
 310  soon._asynchronizer = asap;
 311  soon._impl = 'asap';
 312  
 313  Y.soon = soon;
 314  
 315  
 316  }, '3.17.2', {"requires": ["yui-base"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1