twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

debuggability.js (32170B)


      1 "use strict";
      2 module.exports = function(Promise, Context,
      3     enableAsyncHooks, disableAsyncHooks) {
      4 var async = Promise._async;
      5 var Warning = require("./errors").Warning;
      6 var util = require("./util");
      7 var es5 = require("./es5");
      8 var canAttachTrace = util.canAttachTrace;
      9 var unhandledRejectionHandled;
     10 var possiblyUnhandledRejection;
     11 var bluebirdFramePattern =
     12     /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/;
     13 var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/;
     14 var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/;
     15 var stackFramePattern = null;
     16 var formatStack = null;
     17 var indentStackFrames = false;
     18 var printWarning;
     19 var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 &&
     20                         (false ||
     21                          util.env("BLUEBIRD_DEBUG") ||
     22                          util.env("NODE_ENV") === "development"));
     23 
     24 var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 &&
     25     (debugging || util.env("BLUEBIRD_WARNINGS")));
     26 
     27 var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 &&
     28     (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES")));
     29 
     30 var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 &&
     31     (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN"));
     32 
     33 var deferUnhandledRejectionCheck;
     34 (function() {
     35     var promises = [];
     36 
     37     function unhandledRejectionCheck() {
     38         for (var i = 0; i < promises.length; ++i) {
     39             promises[i]._notifyUnhandledRejection();
     40         }
     41         unhandledRejectionClear();
     42     }
     43 
     44     function unhandledRejectionClear() {
     45         promises.length = 0;
     46     }
     47 
     48     deferUnhandledRejectionCheck = function(promise) {
     49         promises.push(promise);
     50         setTimeout(unhandledRejectionCheck, 1);
     51     };
     52 
     53     es5.defineProperty(Promise, "_unhandledRejectionCheck", {
     54         value: unhandledRejectionCheck
     55     });
     56     es5.defineProperty(Promise, "_unhandledRejectionClear", {
     57         value: unhandledRejectionClear
     58     });
     59 })();
     60 
     61 Promise.prototype.suppressUnhandledRejections = function() {
     62     var target = this._target();
     63     target._bitField = ((target._bitField & (~1048576)) |
     64                       524288);
     65 };
     66 
     67 Promise.prototype._ensurePossibleRejectionHandled = function () {
     68     if ((this._bitField & 524288) !== 0) return;
     69     this._setRejectionIsUnhandled();
     70     deferUnhandledRejectionCheck(this);
     71 };
     72 
     73 Promise.prototype._notifyUnhandledRejectionIsHandled = function () {
     74     fireRejectionEvent("rejectionHandled",
     75                                   unhandledRejectionHandled, undefined, this);
     76 };
     77 
     78 Promise.prototype._setReturnedNonUndefined = function() {
     79     this._bitField = this._bitField | 268435456;
     80 };
     81 
     82 Promise.prototype._returnedNonUndefined = function() {
     83     return (this._bitField & 268435456) !== 0;
     84 };
     85 
     86 Promise.prototype._notifyUnhandledRejection = function () {
     87     if (this._isRejectionUnhandled()) {
     88         var reason = this._settledValue();
     89         this._setUnhandledRejectionIsNotified();
     90         fireRejectionEvent("unhandledRejection",
     91                                       possiblyUnhandledRejection, reason, this);
     92     }
     93 };
     94 
     95 Promise.prototype._setUnhandledRejectionIsNotified = function () {
     96     this._bitField = this._bitField | 262144;
     97 };
     98 
     99 Promise.prototype._unsetUnhandledRejectionIsNotified = function () {
    100     this._bitField = this._bitField & (~262144);
    101 };
    102 
    103 Promise.prototype._isUnhandledRejectionNotified = function () {
    104     return (this._bitField & 262144) > 0;
    105 };
    106 
    107 Promise.prototype._setRejectionIsUnhandled = function () {
    108     this._bitField = this._bitField | 1048576;
    109 };
    110 
    111 Promise.prototype._unsetRejectionIsUnhandled = function () {
    112     this._bitField = this._bitField & (~1048576);
    113     if (this._isUnhandledRejectionNotified()) {
    114         this._unsetUnhandledRejectionIsNotified();
    115         this._notifyUnhandledRejectionIsHandled();
    116     }
    117 };
    118 
    119 Promise.prototype._isRejectionUnhandled = function () {
    120     return (this._bitField & 1048576) > 0;
    121 };
    122 
    123 Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) {
    124     return warn(message, shouldUseOwnTrace, promise || this);
    125 };
    126 
    127 Promise.onPossiblyUnhandledRejection = function (fn) {
    128     var context = Promise._getContext();
    129     possiblyUnhandledRejection = util.contextBind(context, fn);
    130 };
    131 
    132 Promise.onUnhandledRejectionHandled = function (fn) {
    133     var context = Promise._getContext();
    134     unhandledRejectionHandled = util.contextBind(context, fn);
    135 };
    136 
    137 var disableLongStackTraces = function() {};
    138 Promise.longStackTraces = function () {
    139     if (async.haveItemsQueued() && !config.longStackTraces) {
    140         throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    141     }
    142     if (!config.longStackTraces && longStackTracesIsSupported()) {
    143         var Promise_captureStackTrace = Promise.prototype._captureStackTrace;
    144         var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace;
    145         var Promise_dereferenceTrace = Promise.prototype._dereferenceTrace;
    146         config.longStackTraces = true;
    147         disableLongStackTraces = function() {
    148             if (async.haveItemsQueued() && !config.longStackTraces) {
    149                 throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    150             }
    151             Promise.prototype._captureStackTrace = Promise_captureStackTrace;
    152             Promise.prototype._attachExtraTrace = Promise_attachExtraTrace;
    153             Promise.prototype._dereferenceTrace = Promise_dereferenceTrace;
    154             Context.deactivateLongStackTraces();
    155             config.longStackTraces = false;
    156         };
    157         Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace;
    158         Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace;
    159         Promise.prototype._dereferenceTrace = longStackTracesDereferenceTrace;
    160         Context.activateLongStackTraces();
    161     }
    162 };
    163 
    164 Promise.hasLongStackTraces = function () {
    165     return config.longStackTraces && longStackTracesIsSupported();
    166 };
    167 
    168 
    169 var legacyHandlers = {
    170     unhandledrejection: {
    171         before: function() {
    172             var ret = util.global.onunhandledrejection;
    173             util.global.onunhandledrejection = null;
    174             return ret;
    175         },
    176         after: function(fn) {
    177             util.global.onunhandledrejection = fn;
    178         }
    179     },
    180     rejectionhandled: {
    181         before: function() {
    182             var ret = util.global.onrejectionhandled;
    183             util.global.onrejectionhandled = null;
    184             return ret;
    185         },
    186         after: function(fn) {
    187             util.global.onrejectionhandled = fn;
    188         }
    189     }
    190 };
    191 
    192 var fireDomEvent = (function() {
    193     var dispatch = function(legacy, e) {
    194         if (legacy) {
    195             var fn;
    196             try {
    197                 fn = legacy.before();
    198                 return !util.global.dispatchEvent(e);
    199             } finally {
    200                 legacy.after(fn);
    201             }
    202         } else {
    203             return !util.global.dispatchEvent(e);
    204         }
    205     };
    206     try {
    207         if (typeof CustomEvent === "function") {
    208             var event = new CustomEvent("CustomEvent");
    209             util.global.dispatchEvent(event);
    210             return function(name, event) {
    211                 name = name.toLowerCase();
    212                 var eventData = {
    213                     detail: event,
    214                     cancelable: true
    215                 };
    216                 var domEvent = new CustomEvent(name, eventData);
    217                 es5.defineProperty(
    218                     domEvent, "promise", {value: event.promise});
    219                 es5.defineProperty(
    220                     domEvent, "reason", {value: event.reason});
    221 
    222                 return dispatch(legacyHandlers[name], domEvent);
    223             };
    224         } else if (typeof Event === "function") {
    225             var event = new Event("CustomEvent");
    226             util.global.dispatchEvent(event);
    227             return function(name, event) {
    228                 name = name.toLowerCase();
    229                 var domEvent = new Event(name, {
    230                     cancelable: true
    231                 });
    232                 domEvent.detail = event;
    233                 es5.defineProperty(domEvent, "promise", {value: event.promise});
    234                 es5.defineProperty(domEvent, "reason", {value: event.reason});
    235                 return dispatch(legacyHandlers[name], domEvent);
    236             };
    237         } else {
    238             var event = document.createEvent("CustomEvent");
    239             event.initCustomEvent("testingtheevent", false, true, {});
    240             util.global.dispatchEvent(event);
    241             return function(name, event) {
    242                 name = name.toLowerCase();
    243                 var domEvent = document.createEvent("CustomEvent");
    244                 domEvent.initCustomEvent(name, false, true,
    245                     event);
    246                 return dispatch(legacyHandlers[name], domEvent);
    247             };
    248         }
    249     } catch (e) {}
    250     return function() {
    251         return false;
    252     };
    253 })();
    254 
    255 var fireGlobalEvent = (function() {
    256     if (util.isNode) {
    257         return function() {
    258             return process.emit.apply(process, arguments);
    259         };
    260     } else {
    261         if (!util.global) {
    262             return function() {
    263                 return false;
    264             };
    265         }
    266         return function(name) {
    267             var methodName = "on" + name.toLowerCase();
    268             var method = util.global[methodName];
    269             if (!method) return false;
    270             method.apply(util.global, [].slice.call(arguments, 1));
    271             return true;
    272         };
    273     }
    274 })();
    275 
    276 function generatePromiseLifecycleEventObject(name, promise) {
    277     return {promise: promise};
    278 }
    279 
    280 var eventToObjectGenerator = {
    281     promiseCreated: generatePromiseLifecycleEventObject,
    282     promiseFulfilled: generatePromiseLifecycleEventObject,
    283     promiseRejected: generatePromiseLifecycleEventObject,
    284     promiseResolved: generatePromiseLifecycleEventObject,
    285     promiseCancelled: generatePromiseLifecycleEventObject,
    286     promiseChained: function(name, promise, child) {
    287         return {promise: promise, child: child};
    288     },
    289     warning: function(name, warning) {
    290         return {warning: warning};
    291     },
    292     unhandledRejection: function (name, reason, promise) {
    293         return {reason: reason, promise: promise};
    294     },
    295     rejectionHandled: generatePromiseLifecycleEventObject
    296 };
    297 
    298 var activeFireEvent = function (name) {
    299     var globalEventFired = false;
    300     try {
    301         globalEventFired = fireGlobalEvent.apply(null, arguments);
    302     } catch (e) {
    303         async.throwLater(e);
    304         globalEventFired = true;
    305     }
    306 
    307     var domEventFired = false;
    308     try {
    309         domEventFired = fireDomEvent(name,
    310                     eventToObjectGenerator[name].apply(null, arguments));
    311     } catch (e) {
    312         async.throwLater(e);
    313         domEventFired = true;
    314     }
    315 
    316     return domEventFired || globalEventFired;
    317 };
    318 
    319 Promise.config = function(opts) {
    320     opts = Object(opts);
    321     if ("longStackTraces" in opts) {
    322         if (opts.longStackTraces) {
    323             Promise.longStackTraces();
    324         } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) {
    325             disableLongStackTraces();
    326         }
    327     }
    328     if ("warnings" in opts) {
    329         var warningsOption = opts.warnings;
    330         config.warnings = !!warningsOption;
    331         wForgottenReturn = config.warnings;
    332 
    333         if (util.isObject(warningsOption)) {
    334             if ("wForgottenReturn" in warningsOption) {
    335                 wForgottenReturn = !!warningsOption.wForgottenReturn;
    336             }
    337         }
    338     }
    339     if ("cancellation" in opts && opts.cancellation && !config.cancellation) {
    340         if (async.haveItemsQueued()) {
    341             throw new Error(
    342                 "cannot enable cancellation after promises are in use");
    343         }
    344         Promise.prototype._clearCancellationData =
    345             cancellationClearCancellationData;
    346         Promise.prototype._propagateFrom = cancellationPropagateFrom;
    347         Promise.prototype._onCancel = cancellationOnCancel;
    348         Promise.prototype._setOnCancel = cancellationSetOnCancel;
    349         Promise.prototype._attachCancellationCallback =
    350             cancellationAttachCancellationCallback;
    351         Promise.prototype._execute = cancellationExecute;
    352         propagateFromFunction = cancellationPropagateFrom;
    353         config.cancellation = true;
    354     }
    355     if ("monitoring" in opts) {
    356         if (opts.monitoring && !config.monitoring) {
    357             config.monitoring = true;
    358             Promise.prototype._fireEvent = activeFireEvent;
    359         } else if (!opts.monitoring && config.monitoring) {
    360             config.monitoring = false;
    361             Promise.prototype._fireEvent = defaultFireEvent;
    362         }
    363     }
    364     if ("asyncHooks" in opts && util.nodeSupportsAsyncResource) {
    365         var prev = config.asyncHooks;
    366         var cur = !!opts.asyncHooks;
    367         if (prev !== cur) {
    368             config.asyncHooks = cur;
    369             if (cur) {
    370                 enableAsyncHooks();
    371             } else {
    372                 disableAsyncHooks();
    373             }
    374         }
    375     }
    376     return Promise;
    377 };
    378 
    379 function defaultFireEvent() { return false; }
    380 
    381 Promise.prototype._fireEvent = defaultFireEvent;
    382 Promise.prototype._execute = function(executor, resolve, reject) {
    383     try {
    384         executor(resolve, reject);
    385     } catch (e) {
    386         return e;
    387     }
    388 };
    389 Promise.prototype._onCancel = function () {};
    390 Promise.prototype._setOnCancel = function (handler) { ; };
    391 Promise.prototype._attachCancellationCallback = function(onCancel) {
    392     ;
    393 };
    394 Promise.prototype._captureStackTrace = function () {};
    395 Promise.prototype._attachExtraTrace = function () {};
    396 Promise.prototype._dereferenceTrace = function () {};
    397 Promise.prototype._clearCancellationData = function() {};
    398 Promise.prototype._propagateFrom = function (parent, flags) {
    399     ;
    400     ;
    401 };
    402 
    403 function cancellationExecute(executor, resolve, reject) {
    404     var promise = this;
    405     try {
    406         executor(resolve, reject, function(onCancel) {
    407             if (typeof onCancel !== "function") {
    408                 throw new TypeError("onCancel must be a function, got: " +
    409                                     util.toString(onCancel));
    410             }
    411             promise._attachCancellationCallback(onCancel);
    412         });
    413     } catch (e) {
    414         return e;
    415     }
    416 }
    417 
    418 function cancellationAttachCancellationCallback(onCancel) {
    419     if (!this._isCancellable()) return this;
    420 
    421     var previousOnCancel = this._onCancel();
    422     if (previousOnCancel !== undefined) {
    423         if (util.isArray(previousOnCancel)) {
    424             previousOnCancel.push(onCancel);
    425         } else {
    426             this._setOnCancel([previousOnCancel, onCancel]);
    427         }
    428     } else {
    429         this._setOnCancel(onCancel);
    430     }
    431 }
    432 
    433 function cancellationOnCancel() {
    434     return this._onCancelField;
    435 }
    436 
    437 function cancellationSetOnCancel(onCancel) {
    438     this._onCancelField = onCancel;
    439 }
    440 
    441 function cancellationClearCancellationData() {
    442     this._cancellationParent = undefined;
    443     this._onCancelField = undefined;
    444 }
    445 
    446 function cancellationPropagateFrom(parent, flags) {
    447     if ((flags & 1) !== 0) {
    448         this._cancellationParent = parent;
    449         var branchesRemainingToCancel = parent._branchesRemainingToCancel;
    450         if (branchesRemainingToCancel === undefined) {
    451             branchesRemainingToCancel = 0;
    452         }
    453         parent._branchesRemainingToCancel = branchesRemainingToCancel + 1;
    454     }
    455     if ((flags & 2) !== 0 && parent._isBound()) {
    456         this._setBoundTo(parent._boundTo);
    457     }
    458 }
    459 
    460 function bindingPropagateFrom(parent, flags) {
    461     if ((flags & 2) !== 0 && parent._isBound()) {
    462         this._setBoundTo(parent._boundTo);
    463     }
    464 }
    465 var propagateFromFunction = bindingPropagateFrom;
    466 
    467 function boundValueFunction() {
    468     var ret = this._boundTo;
    469     if (ret !== undefined) {
    470         if (ret instanceof Promise) {
    471             if (ret.isFulfilled()) {
    472                 return ret.value();
    473             } else {
    474                 return undefined;
    475             }
    476         }
    477     }
    478     return ret;
    479 }
    480 
    481 function longStackTracesCaptureStackTrace() {
    482     this._trace = new CapturedTrace(this._peekContext());
    483 }
    484 
    485 function longStackTracesAttachExtraTrace(error, ignoreSelf) {
    486     if (canAttachTrace(error)) {
    487         var trace = this._trace;
    488         if (trace !== undefined) {
    489             if (ignoreSelf) trace = trace._parent;
    490         }
    491         if (trace !== undefined) {
    492             trace.attachExtraTrace(error);
    493         } else if (!error.__stackCleaned__) {
    494             var parsed = parseStackAndMessage(error);
    495             util.notEnumerableProp(error, "stack",
    496                 parsed.message + "\n" + parsed.stack.join("\n"));
    497             util.notEnumerableProp(error, "__stackCleaned__", true);
    498         }
    499     }
    500 }
    501 
    502 function longStackTracesDereferenceTrace() {
    503     this._trace = undefined;
    504 }
    505 
    506 function checkForgottenReturns(returnValue, promiseCreated, name, promise,
    507                                parent) {
    508     if (returnValue === undefined && promiseCreated !== null &&
    509         wForgottenReturn) {
    510         if (parent !== undefined && parent._returnedNonUndefined()) return;
    511         if ((promise._bitField & 65535) === 0) return;
    512 
    513         if (name) name = name + " ";
    514         var handlerLine = "";
    515         var creatorLine = "";
    516         if (promiseCreated._trace) {
    517             var traceLines = promiseCreated._trace.stack.split("\n");
    518             var stack = cleanStack(traceLines);
    519             for (var i = stack.length - 1; i >= 0; --i) {
    520                 var line = stack[i];
    521                 if (!nodeFramePattern.test(line)) {
    522                     var lineMatches = line.match(parseLinePattern);
    523                     if (lineMatches) {
    524                         handlerLine  = "at " + lineMatches[1] +
    525                             ":" + lineMatches[2] + ":" + lineMatches[3] + " ";
    526                     }
    527                     break;
    528                 }
    529             }
    530 
    531             if (stack.length > 0) {
    532                 var firstUserLine = stack[0];
    533                 for (var i = 0; i < traceLines.length; ++i) {
    534 
    535                     if (traceLines[i] === firstUserLine) {
    536                         if (i > 0) {
    537                             creatorLine = "\n" + traceLines[i - 1];
    538                         }
    539                         break;
    540                     }
    541                 }
    542 
    543             }
    544         }
    545         var msg = "a promise was created in a " + name +
    546             "handler " + handlerLine + "but was not returned from it, " +
    547             "see http://goo.gl/rRqMUw" +
    548             creatorLine;
    549         promise._warn(msg, true, promiseCreated);
    550     }
    551 }
    552 
    553 function deprecated(name, replacement) {
    554     var message = name +
    555         " is deprecated and will be removed in a future version.";
    556     if (replacement) message += " Use " + replacement + " instead.";
    557     return warn(message);
    558 }
    559 
    560 function warn(message, shouldUseOwnTrace, promise) {
    561     if (!config.warnings) return;
    562     var warning = new Warning(message);
    563     var ctx;
    564     if (shouldUseOwnTrace) {
    565         promise._attachExtraTrace(warning);
    566     } else if (config.longStackTraces && (ctx = Promise._peekContext())) {
    567         ctx.attachExtraTrace(warning);
    568     } else {
    569         var parsed = parseStackAndMessage(warning);
    570         warning.stack = parsed.message + "\n" + parsed.stack.join("\n");
    571     }
    572 
    573     if (!activeFireEvent("warning", warning)) {
    574         formatAndLogError(warning, "", true);
    575     }
    576 }
    577 
    578 function reconstructStack(message, stacks) {
    579     for (var i = 0; i < stacks.length - 1; ++i) {
    580         stacks[i].push("From previous event:");
    581         stacks[i] = stacks[i].join("\n");
    582     }
    583     if (i < stacks.length) {
    584         stacks[i] = stacks[i].join("\n");
    585     }
    586     return message + "\n" + stacks.join("\n");
    587 }
    588 
    589 function removeDuplicateOrEmptyJumps(stacks) {
    590     for (var i = 0; i < stacks.length; ++i) {
    591         if (stacks[i].length === 0 ||
    592             ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) {
    593             stacks.splice(i, 1);
    594             i--;
    595         }
    596     }
    597 }
    598 
    599 function removeCommonRoots(stacks) {
    600     var current = stacks[0];
    601     for (var i = 1; i < stacks.length; ++i) {
    602         var prev = stacks[i];
    603         var currentLastIndex = current.length - 1;
    604         var currentLastLine = current[currentLastIndex];
    605         var commonRootMeetPoint = -1;
    606 
    607         for (var j = prev.length - 1; j >= 0; --j) {
    608             if (prev[j] === currentLastLine) {
    609                 commonRootMeetPoint = j;
    610                 break;
    611             }
    612         }
    613 
    614         for (var j = commonRootMeetPoint; j >= 0; --j) {
    615             var line = prev[j];
    616             if (current[currentLastIndex] === line) {
    617                 current.pop();
    618                 currentLastIndex--;
    619             } else {
    620                 break;
    621             }
    622         }
    623         current = prev;
    624     }
    625 }
    626 
    627 function cleanStack(stack) {
    628     var ret = [];
    629     for (var i = 0; i < stack.length; ++i) {
    630         var line = stack[i];
    631         var isTraceLine = "    (No stack trace)" === line ||
    632             stackFramePattern.test(line);
    633         var isInternalFrame = isTraceLine && shouldIgnore(line);
    634         if (isTraceLine && !isInternalFrame) {
    635             if (indentStackFrames && line.charAt(0) !== " ") {
    636                 line = "    " + line;
    637             }
    638             ret.push(line);
    639         }
    640     }
    641     return ret;
    642 }
    643 
    644 function stackFramesAsArray(error) {
    645     var stack = error.stack.replace(/\s+$/g, "").split("\n");
    646     for (var i = 0; i < stack.length; ++i) {
    647         var line = stack[i];
    648         if ("    (No stack trace)" === line || stackFramePattern.test(line)) {
    649             break;
    650         }
    651     }
    652     if (i > 0 && error.name != "SyntaxError") {
    653         stack = stack.slice(i);
    654     }
    655     return stack;
    656 }
    657 
    658 function parseStackAndMessage(error) {
    659     var stack = error.stack;
    660     var message = error.toString();
    661     stack = typeof stack === "string" && stack.length > 0
    662                 ? stackFramesAsArray(error) : ["    (No stack trace)"];
    663     return {
    664         message: message,
    665         stack: error.name == "SyntaxError" ? stack : cleanStack(stack)
    666     };
    667 }
    668 
    669 function formatAndLogError(error, title, isSoft) {
    670     if (typeof console !== "undefined") {
    671         var message;
    672         if (util.isObject(error)) {
    673             var stack = error.stack;
    674             message = title + formatStack(stack, error);
    675         } else {
    676             message = title + String(error);
    677         }
    678         if (typeof printWarning === "function") {
    679             printWarning(message, isSoft);
    680         } else if (typeof console.log === "function" ||
    681             typeof console.log === "object") {
    682             console.log(message);
    683         }
    684     }
    685 }
    686 
    687 function fireRejectionEvent(name, localHandler, reason, promise) {
    688     var localEventFired = false;
    689     try {
    690         if (typeof localHandler === "function") {
    691             localEventFired = true;
    692             if (name === "rejectionHandled") {
    693                 localHandler(promise);
    694             } else {
    695                 localHandler(reason, promise);
    696             }
    697         }
    698     } catch (e) {
    699         async.throwLater(e);
    700     }
    701 
    702     if (name === "unhandledRejection") {
    703         if (!activeFireEvent(name, reason, promise) && !localEventFired) {
    704             formatAndLogError(reason, "Unhandled rejection ");
    705         }
    706     } else {
    707         activeFireEvent(name, promise);
    708     }
    709 }
    710 
    711 function formatNonError(obj) {
    712     var str;
    713     if (typeof obj === "function") {
    714         str = "[function " +
    715             (obj.name || "anonymous") +
    716             "]";
    717     } else {
    718         str = obj && typeof obj.toString === "function"
    719             ? obj.toString() : util.toString(obj);
    720         var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
    721         if (ruselessToString.test(str)) {
    722             try {
    723                 var newStr = JSON.stringify(obj);
    724                 str = newStr;
    725             }
    726             catch(e) {
    727 
    728             }
    729         }
    730         if (str.length === 0) {
    731             str = "(empty array)";
    732         }
    733     }
    734     return ("(<" + snip(str) + ">, no stack trace)");
    735 }
    736 
    737 function snip(str) {
    738     var maxChars = 41;
    739     if (str.length < maxChars) {
    740         return str;
    741     }
    742     return str.substr(0, maxChars - 3) + "...";
    743 }
    744 
    745 function longStackTracesIsSupported() {
    746     return typeof captureStackTrace === "function";
    747 }
    748 
    749 var shouldIgnore = function() { return false; };
    750 var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;
    751 function parseLineInfo(line) {
    752     var matches = line.match(parseLineInfoRegex);
    753     if (matches) {
    754         return {
    755             fileName: matches[1],
    756             line: parseInt(matches[2], 10)
    757         };
    758     }
    759 }
    760 
    761 function setBounds(firstLineError, lastLineError) {
    762     if (!longStackTracesIsSupported()) return;
    763     var firstStackLines = (firstLineError.stack || "").split("\n");
    764     var lastStackLines = (lastLineError.stack || "").split("\n");
    765     var firstIndex = -1;
    766     var lastIndex = -1;
    767     var firstFileName;
    768     var lastFileName;
    769     for (var i = 0; i < firstStackLines.length; ++i) {
    770         var result = parseLineInfo(firstStackLines[i]);
    771         if (result) {
    772             firstFileName = result.fileName;
    773             firstIndex = result.line;
    774             break;
    775         }
    776     }
    777     for (var i = 0; i < lastStackLines.length; ++i) {
    778         var result = parseLineInfo(lastStackLines[i]);
    779         if (result) {
    780             lastFileName = result.fileName;
    781             lastIndex = result.line;
    782             break;
    783         }
    784     }
    785     if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName ||
    786         firstFileName !== lastFileName || firstIndex >= lastIndex) {
    787         return;
    788     }
    789 
    790     shouldIgnore = function(line) {
    791         if (bluebirdFramePattern.test(line)) return true;
    792         var info = parseLineInfo(line);
    793         if (info) {
    794             if (info.fileName === firstFileName &&
    795                 (firstIndex <= info.line && info.line <= lastIndex)) {
    796                 return true;
    797             }
    798         }
    799         return false;
    800     };
    801 }
    802 
    803 function CapturedTrace(parent) {
    804     this._parent = parent;
    805     this._promisesCreated = 0;
    806     var length = this._length = 1 + (parent === undefined ? 0 : parent._length);
    807     captureStackTrace(this, CapturedTrace);
    808     if (length > 32) this.uncycle();
    809 }
    810 util.inherits(CapturedTrace, Error);
    811 Context.CapturedTrace = CapturedTrace;
    812 
    813 CapturedTrace.prototype.uncycle = function() {
    814     var length = this._length;
    815     if (length < 2) return;
    816     var nodes = [];
    817     var stackToIndex = {};
    818 
    819     for (var i = 0, node = this; node !== undefined; ++i) {
    820         nodes.push(node);
    821         node = node._parent;
    822     }
    823     length = this._length = i;
    824     for (var i = length - 1; i >= 0; --i) {
    825         var stack = nodes[i].stack;
    826         if (stackToIndex[stack] === undefined) {
    827             stackToIndex[stack] = i;
    828         }
    829     }
    830     for (var i = 0; i < length; ++i) {
    831         var currentStack = nodes[i].stack;
    832         var index = stackToIndex[currentStack];
    833         if (index !== undefined && index !== i) {
    834             if (index > 0) {
    835                 nodes[index - 1]._parent = undefined;
    836                 nodes[index - 1]._length = 1;
    837             }
    838             nodes[i]._parent = undefined;
    839             nodes[i]._length = 1;
    840             var cycleEdgeNode = i > 0 ? nodes[i - 1] : this;
    841 
    842             if (index < length - 1) {
    843                 cycleEdgeNode._parent = nodes[index + 1];
    844                 cycleEdgeNode._parent.uncycle();
    845                 cycleEdgeNode._length =
    846                     cycleEdgeNode._parent._length + 1;
    847             } else {
    848                 cycleEdgeNode._parent = undefined;
    849                 cycleEdgeNode._length = 1;
    850             }
    851             var currentChildLength = cycleEdgeNode._length + 1;
    852             for (var j = i - 2; j >= 0; --j) {
    853                 nodes[j]._length = currentChildLength;
    854                 currentChildLength++;
    855             }
    856             return;
    857         }
    858     }
    859 };
    860 
    861 CapturedTrace.prototype.attachExtraTrace = function(error) {
    862     if (error.__stackCleaned__) return;
    863     this.uncycle();
    864     var parsed = parseStackAndMessage(error);
    865     var message = parsed.message;
    866     var stacks = [parsed.stack];
    867 
    868     var trace = this;
    869     while (trace !== undefined) {
    870         stacks.push(cleanStack(trace.stack.split("\n")));
    871         trace = trace._parent;
    872     }
    873     removeCommonRoots(stacks);
    874     removeDuplicateOrEmptyJumps(stacks);
    875     util.notEnumerableProp(error, "stack", reconstructStack(message, stacks));
    876     util.notEnumerableProp(error, "__stackCleaned__", true);
    877 };
    878 
    879 var captureStackTrace = (function stackDetection() {
    880     var v8stackFramePattern = /^\s*at\s*/;
    881     var v8stackFormatter = function(stack, error) {
    882         if (typeof stack === "string") return stack;
    883 
    884         if (error.name !== undefined &&
    885             error.message !== undefined) {
    886             return error.toString();
    887         }
    888         return formatNonError(error);
    889     };
    890 
    891     if (typeof Error.stackTraceLimit === "number" &&
    892         typeof Error.captureStackTrace === "function") {
    893         Error.stackTraceLimit += 6;
    894         stackFramePattern = v8stackFramePattern;
    895         formatStack = v8stackFormatter;
    896         var captureStackTrace = Error.captureStackTrace;
    897 
    898         shouldIgnore = function(line) {
    899             return bluebirdFramePattern.test(line);
    900         };
    901         return function(receiver, ignoreUntil) {
    902             Error.stackTraceLimit += 6;
    903             captureStackTrace(receiver, ignoreUntil);
    904             Error.stackTraceLimit -= 6;
    905         };
    906     }
    907     var err = new Error();
    908 
    909     if (typeof err.stack === "string" &&
    910         err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) {
    911         stackFramePattern = /@/;
    912         formatStack = v8stackFormatter;
    913         indentStackFrames = true;
    914         return function captureStackTrace(o) {
    915             o.stack = new Error().stack;
    916         };
    917     }
    918 
    919     var hasStackAfterThrow;
    920     try { throw new Error(); }
    921     catch(e) {
    922         hasStackAfterThrow = ("stack" in e);
    923     }
    924     if (!("stack" in err) && hasStackAfterThrow &&
    925         typeof Error.stackTraceLimit === "number") {
    926         stackFramePattern = v8stackFramePattern;
    927         formatStack = v8stackFormatter;
    928         return function captureStackTrace(o) {
    929             Error.stackTraceLimit += 6;
    930             try { throw new Error(); }
    931             catch(e) { o.stack = e.stack; }
    932             Error.stackTraceLimit -= 6;
    933         };
    934     }
    935 
    936     formatStack = function(stack, error) {
    937         if (typeof stack === "string") return stack;
    938 
    939         if ((typeof error === "object" ||
    940             typeof error === "function") &&
    941             error.name !== undefined &&
    942             error.message !== undefined) {
    943             return error.toString();
    944         }
    945         return formatNonError(error);
    946     };
    947 
    948     return null;
    949 
    950 })([]);
    951 
    952 if (typeof console !== "undefined" && typeof console.warn !== "undefined") {
    953     printWarning = function (message) {
    954         console.warn(message);
    955     };
    956     if (util.isNode && process.stderr.isTTY) {
    957         printWarning = function(message, isSoft) {
    958             var color = isSoft ? "\u001b[33m" : "\u001b[31m";
    959             console.warn(color + message + "\u001b[0m\n");
    960         };
    961     } else if (!util.isNode && typeof (new Error().stack) === "string") {
    962         printWarning = function(message, isSoft) {
    963             console.warn("%c" + message,
    964                         isSoft ? "color: darkorange" : "color: red");
    965         };
    966     }
    967 }
    968 
    969 var config = {
    970     warnings: warnings,
    971     longStackTraces: false,
    972     cancellation: false,
    973     monitoring: false,
    974     asyncHooks: false
    975 };
    976 
    977 if (longStackTraces) Promise.longStackTraces();
    978 
    979 return {
    980     asyncHooks: function() {
    981         return config.asyncHooks;
    982     },
    983     longStackTraces: function() {
    984         return config.longStackTraces;
    985     },
    986     warnings: function() {
    987         return config.warnings;
    988     },
    989     cancellation: function() {
    990         return config.cancellation;
    991     },
    992     monitoring: function() {
    993         return config.monitoring;
    994     },
    995     propagateFromFunction: function() {
    996         return propagateFromFunction;
    997     },
    998     boundValueFunction: function() {
    999         return boundValueFunction;
   1000     },
   1001     checkForgottenReturns: checkForgottenReturns,
   1002     setBounds: setBounds,
   1003     warn: warn,
   1004     deprecated: deprecated,
   1005     CapturedTrace: CapturedTrace,
   1006     fireDomEvent: fireDomEvent,
   1007     fireGlobalEvent: fireGlobalEvent
   1008 };
   1009 };