Code coverage report for promise/lib/core.js

Statements: 99.04% (103 / 104)      Branches: 97.78% (44 / 45)      Functions: 94.12% (16 / 17)      Lines: 99.01% (100 / 101)      Ignored: none     

All files » promise/lib/ » core.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185    1   1                                     1 1 1 1001905 1001905   50 50       1 1001762 1001762   81 81     1 1001976 1001976   141 141       1   1 2003091     2003091 1   2003090 2003090 2003090 2003090 1000863   1   1 1001820 1   1001819 1001819 1001819     1 1 1 1 1     1 3002989 1000351   3002989 2001178 2001178   1001811 1001811 1001811 49 26   23   49   1001762 1001762 81   1001681       1   2002957 2         2002955       1001905 1001905 50   1001855       1000351 1000351 1000351 1000351 1504 1113 1113     1001441 1001441 1001441     1 873 873 873   1 2002665 2001169   2002665     1 1001820 1001820 1001820                 1 1001976 1001976 1001368 1001250 1001250   709 677 677   1001976 40 40      
'use strict';
 
var asap = require('asap/raw');
 
function noop() {}
 
// States:
//
// 0 - pending
// 1 - fulfilled with _value
// 2 - rejected with _value
// 3 - adopted the state of another promise, _value
//
// once the state is no longer pending (0) it is immutable
 
// All `_` prefixed properties will be reduced to `_{random number}`
// at build time to obfuscate them and discourage their use.
// We don't use symbols or Object.defineProperty to fully hide them
// because the performance isn't good enough.
 
 
// to avoid using try/catch inside critical functions, we
// extract them to here.
var LAST_ERROR = null;
var IS_ERROR = {};
function getThen(obj) {
  try {
    return obj.then;
  } catch (ex) {
    LAST_ERROR = ex;
    return IS_ERROR;
  }
}
 
function tryCallOne(fn, a) {
  try {
    return fn(a);
  } catch (ex) {
    LAST_ERROR = ex;
    return IS_ERROR;
  }
}
function tryCallTwo(fn, a, b) {
  try {
    fn(a, b);
  } catch (ex) {
    LAST_ERROR = ex;
    return IS_ERROR;
  }
}
 
module.exports = Promise;
 
function Promise(fn) {
  Iif (typeof this !== 'object') {
    throw new TypeError('Promises must be constructed via new');
  }
  if (typeof fn !== 'function') {
    throw new TypeError('not a function');
  }
  this._14 = 0;
  this._34 = null;
  this._62 = [];
  if (fn === noop) return;
  doResolve(fn, this);
}
Promise._72 = noop;
 
Promise.prototype.then = function(onFulfilled, onRejected) {
  if (this.constructor !== Promise) {
    return safeThen(this, onFulfilled, onRejected);
  }
  var res = new Promise(noop);
  handle(this, new Handler(onFulfilled, onRejected, res));
  return res;
};
 
function safeThen(self, onFulfilled, onRejected) {
  return new self.constructor(function (resolve, reject) {
    var res = new Promise(noop);
    res.then(resolve, reject);
    handle(self, new Handler(onFulfilled, onRejected, res));
  });
};
function handle(self, deferred) {
  while (self._14 === 3) {
    self = self._34;
  }
  if (self._14 === 0) {
    self._62.push(deferred);
    return;
  }
  asap(function() {
    var cb = self._14 === 1 ? deferred.onFulfilled : deferred.onRejected;
    if (cb === null) {
      if (self._14 === 1) {
        resolve(deferred.promise, self._34);
      } else {
        reject(deferred.promise, self._34);
      }
      return;
    }
    var ret = tryCallOne(cb, self._34);
    if (ret === IS_ERROR) {
      reject(deferred.promise, LAST_ERROR);
    } else {
      resolve(deferred.promise, ret);
    }
  });
}
function resolve(self, newValue) {
  // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
  if (newValue === self) {
    return reject(
      self,
      new TypeError('A promise cannot be resolved with itself.')
    );
  }
  if (
    newValue &&
    (typeof newValue === 'object' || typeof newValue === 'function')
  ) {
    var then = getThen(newValue);
    if (then === IS_ERROR) {
      return reject(self, LAST_ERROR);
    }
    if (
      then === self.then &&
      newValue instanceof Promise
    ) {
      self._14 = 3;
      self._34 = newValue;
      finale(self);
      return;
    } else if (typeof then === 'function') {
      doResolve(then.bind(newValue), self);
      return;
    }
  }
  self._14 = 1;
  self._34 = newValue;
  finale(self);
}
 
function reject(self, newValue) {
  self._14 = 2;
  self._34 = newValue;
  finale(self);
}
function finale(self) {
  for (var i = 0; i < self._62.length; i++) {
    handle(self, self._62[i]);
  }
  self._62 = null;
}
 
function Handler(onFulfilled, onRejected, promise){
  this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
  this.onRejected = typeof onRejected === 'function' ? onRejected : null;
  this.promise = promise;
}
 
/**
 * Take a potentially misbehaving resolver function and make sure
 * onFulfilled and onRejected are only called once.
 *
 * Makes no guarantees about asynchrony.
 */
function doResolve(fn, promise) {
  var done = false;
  var res = tryCallTwo(fn, function (value) {
    if (done) return;
    done = true;
    resolve(promise, value);
  }, function (reason) {
    if (done) return;
    done = true;
    reject(promise, reason);
  })
  if (!done && res === IS_ERROR) {
    done = true;
    reject(promise, LAST_ERROR);
  }
}