Spaces:
Paused
Paused
| ; | |
| module.exports = function(Promise, Context, | |
| enableAsyncHooks, disableAsyncHooks) { | |
| var async = Promise._async; | |
| var Warning = require("./errors").Warning; | |
| var util = require("./util"); | |
| var es5 = require("./es5"); | |
| var canAttachTrace = util.canAttachTrace; | |
| var unhandledRejectionHandled; | |
| var possiblyUnhandledRejection; | |
| var bluebirdFramePattern = | |
| /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/; | |
| var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/; | |
| var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/; | |
| var stackFramePattern = null; | |
| var formatStack = null; | |
| var indentStackFrames = false; | |
| var printWarning; | |
| var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && | |
| (false || | |
| util.env("BLUEBIRD_DEBUG") || | |
| util.env("NODE_ENV") === "development")); | |
| var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && | |
| (debugging || util.env("BLUEBIRD_WARNINGS"))); | |
| var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && | |
| (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES"))); | |
| var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && | |
| (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN")); | |
| var deferUnhandledRejectionCheck; | |
| (function() { | |
| var promises = []; | |
| function unhandledRejectionCheck() { | |
| for (var i = 0; i < promises.length; ++i) { | |
| promises[i]._notifyUnhandledRejection(); | |
| } | |
| unhandledRejectionClear(); | |
| } | |
| function unhandledRejectionClear() { | |
| promises.length = 0; | |
| } | |
| deferUnhandledRejectionCheck = function(promise) { | |
| promises.push(promise); | |
| setTimeout(unhandledRejectionCheck, 1); | |
| }; | |
| es5.defineProperty(Promise, "_unhandledRejectionCheck", { | |
| value: unhandledRejectionCheck | |
| }); | |
| es5.defineProperty(Promise, "_unhandledRejectionClear", { | |
| value: unhandledRejectionClear | |
| }); | |
| })(); | |
| Promise.prototype.suppressUnhandledRejections = function() { | |
| var target = this._target(); | |
| target._bitField = ((target._bitField & (~1048576)) | | |
| 524288); | |
| }; | |
| Promise.prototype._ensurePossibleRejectionHandled = function () { | |
| if ((this._bitField & 524288) !== 0) return; | |
| this._setRejectionIsUnhandled(); | |
| deferUnhandledRejectionCheck(this); | |
| }; | |
| Promise.prototype._notifyUnhandledRejectionIsHandled = function () { | |
| fireRejectionEvent("rejectionHandled", | |
| unhandledRejectionHandled, undefined, this); | |
| }; | |
| Promise.prototype._setReturnedNonUndefined = function() { | |
| this._bitField = this._bitField | 268435456; | |
| }; | |
| Promise.prototype._returnedNonUndefined = function() { | |
| return (this._bitField & 268435456) !== 0; | |
| }; | |
| Promise.prototype._notifyUnhandledRejection = function () { | |
| if (this._isRejectionUnhandled()) { | |
| var reason = this._settledValue(); | |
| this._setUnhandledRejectionIsNotified(); | |
| fireRejectionEvent("unhandledRejection", | |
| possiblyUnhandledRejection, reason, this); | |
| } | |
| }; | |
| Promise.prototype._setUnhandledRejectionIsNotified = function () { | |
| this._bitField = this._bitField | 262144; | |
| }; | |
| Promise.prototype._unsetUnhandledRejectionIsNotified = function () { | |
| this._bitField = this._bitField & (~262144); | |
| }; | |
| Promise.prototype._isUnhandledRejectionNotified = function () { | |
| return (this._bitField & 262144) > 0; | |
| }; | |
| Promise.prototype._setRejectionIsUnhandled = function () { | |
| this._bitField = this._bitField | 1048576; | |
| }; | |
| Promise.prototype._unsetRejectionIsUnhandled = function () { | |
| this._bitField = this._bitField & (~1048576); | |
| if (this._isUnhandledRejectionNotified()) { | |
| this._unsetUnhandledRejectionIsNotified(); | |
| this._notifyUnhandledRejectionIsHandled(); | |
| } | |
| }; | |
| Promise.prototype._isRejectionUnhandled = function () { | |
| return (this._bitField & 1048576) > 0; | |
| }; | |
| Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) { | |
| return warn(message, shouldUseOwnTrace, promise || this); | |
| }; | |
| Promise.onPossiblyUnhandledRejection = function (fn) { | |
| var context = Promise._getContext(); | |
| possiblyUnhandledRejection = util.contextBind(context, fn); | |
| }; | |
| Promise.onUnhandledRejectionHandled = function (fn) { | |
| var context = Promise._getContext(); | |
| unhandledRejectionHandled = util.contextBind(context, fn); | |
| }; | |
| var disableLongStackTraces = function() {}; | |
| Promise.longStackTraces = function () { | |
| if (async.haveItemsQueued() && !config.longStackTraces) { | |
| throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); | |
| } | |
| if (!config.longStackTraces && longStackTracesIsSupported()) { | |
| var Promise_captureStackTrace = Promise.prototype._captureStackTrace; | |
| var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace; | |
| var Promise_dereferenceTrace = Promise.prototype._dereferenceTrace; | |
| config.longStackTraces = true; | |
| disableLongStackTraces = function() { | |
| if (async.haveItemsQueued() && !config.longStackTraces) { | |
| throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); | |
| } | |
| Promise.prototype._captureStackTrace = Promise_captureStackTrace; | |
| Promise.prototype._attachExtraTrace = Promise_attachExtraTrace; | |
| Promise.prototype._dereferenceTrace = Promise_dereferenceTrace; | |
| Context.deactivateLongStackTraces(); | |
| config.longStackTraces = false; | |
| }; | |
| Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace; | |
| Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace; | |
| Promise.prototype._dereferenceTrace = longStackTracesDereferenceTrace; | |
| Context.activateLongStackTraces(); | |
| } | |
| }; | |
| Promise.hasLongStackTraces = function () { | |
| return config.longStackTraces && longStackTracesIsSupported(); | |
| }; | |
| var legacyHandlers = { | |
| unhandledrejection: { | |
| before: function() { | |
| var ret = util.global.onunhandledrejection; | |
| util.global.onunhandledrejection = null; | |
| return ret; | |
| }, | |
| after: function(fn) { | |
| util.global.onunhandledrejection = fn; | |
| } | |
| }, | |
| rejectionhandled: { | |
| before: function() { | |
| var ret = util.global.onrejectionhandled; | |
| util.global.onrejectionhandled = null; | |
| return ret; | |
| }, | |
| after: function(fn) { | |
| util.global.onrejectionhandled = fn; | |
| } | |
| } | |
| }; | |
| var fireDomEvent = (function() { | |
| var dispatch = function(legacy, e) { | |
| if (legacy) { | |
| var fn; | |
| try { | |
| fn = legacy.before(); | |
| return !util.global.dispatchEvent(e); | |
| } finally { | |
| legacy.after(fn); | |
| } | |
| } else { | |
| return !util.global.dispatchEvent(e); | |
| } | |
| }; | |
| try { | |
| if (typeof CustomEvent === "function") { | |
| var event = new CustomEvent("CustomEvent"); | |
| util.global.dispatchEvent(event); | |
| return function(name, event) { | |
| name = name.toLowerCase(); | |
| var eventData = { | |
| detail: event, | |
| cancelable: true | |
| }; | |
| var domEvent = new CustomEvent(name, eventData); | |
| es5.defineProperty( | |
| domEvent, "promise", {value: event.promise}); | |
| es5.defineProperty( | |
| domEvent, "reason", {value: event.reason}); | |
| return dispatch(legacyHandlers[name], domEvent); | |
| }; | |
| } else if (typeof Event === "function") { | |
| var event = new Event("CustomEvent"); | |
| util.global.dispatchEvent(event); | |
| return function(name, event) { | |
| name = name.toLowerCase(); | |
| var domEvent = new Event(name, { | |
| cancelable: true | |
| }); | |
| domEvent.detail = event; | |
| es5.defineProperty(domEvent, "promise", {value: event.promise}); | |
| es5.defineProperty(domEvent, "reason", {value: event.reason}); | |
| return dispatch(legacyHandlers[name], domEvent); | |
| }; | |
| } else { | |
| var event = document.createEvent("CustomEvent"); | |
| event.initCustomEvent("testingtheevent", false, true, {}); | |
| util.global.dispatchEvent(event); | |
| return function(name, event) { | |
| name = name.toLowerCase(); | |
| var domEvent = document.createEvent("CustomEvent"); | |
| domEvent.initCustomEvent(name, false, true, | |
| event); | |
| return dispatch(legacyHandlers[name], domEvent); | |
| }; | |
| } | |
| } catch (e) {} | |
| return function() { | |
| return false; | |
| }; | |
| })(); | |
| var fireGlobalEvent = (function() { | |
| if (util.isNode) { | |
| return function() { | |
| return process.emit.apply(process, arguments); | |
| }; | |
| } else { | |
| if (!util.global) { | |
| return function() { | |
| return false; | |
| }; | |
| } | |
| return function(name) { | |
| var methodName = "on" + name.toLowerCase(); | |
| var method = util.global[methodName]; | |
| if (!method) return false; | |
| method.apply(util.global, [].slice.call(arguments, 1)); | |
| return true; | |
| }; | |
| } | |
| })(); | |
| function generatePromiseLifecycleEventObject(name, promise) { | |
| return {promise: promise}; | |
| } | |
| var eventToObjectGenerator = { | |
| promiseCreated: generatePromiseLifecycleEventObject, | |
| promiseFulfilled: generatePromiseLifecycleEventObject, | |
| promiseRejected: generatePromiseLifecycleEventObject, | |
| promiseResolved: generatePromiseLifecycleEventObject, | |
| promiseCancelled: generatePromiseLifecycleEventObject, | |
| promiseChained: function(name, promise, child) { | |
| return {promise: promise, child: child}; | |
| }, | |
| warning: function(name, warning) { | |
| return {warning: warning}; | |
| }, | |
| unhandledRejection: function (name, reason, promise) { | |
| return {reason: reason, promise: promise}; | |
| }, | |
| rejectionHandled: generatePromiseLifecycleEventObject | |
| }; | |
| var activeFireEvent = function (name) { | |
| var globalEventFired = false; | |
| try { | |
| globalEventFired = fireGlobalEvent.apply(null, arguments); | |
| } catch (e) { | |
| async.throwLater(e); | |
| globalEventFired = true; | |
| } | |
| var domEventFired = false; | |
| try { | |
| domEventFired = fireDomEvent(name, | |
| eventToObjectGenerator[name].apply(null, arguments)); | |
| } catch (e) { | |
| async.throwLater(e); | |
| domEventFired = true; | |
| } | |
| return domEventFired || globalEventFired; | |
| }; | |
| Promise.config = function(opts) { | |
| opts = Object(opts); | |
| if ("longStackTraces" in opts) { | |
| if (opts.longStackTraces) { | |
| Promise.longStackTraces(); | |
| } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) { | |
| disableLongStackTraces(); | |
| } | |
| } | |
| if ("warnings" in opts) { | |
| var warningsOption = opts.warnings; | |
| config.warnings = !!warningsOption; | |
| wForgottenReturn = config.warnings; | |
| if (util.isObject(warningsOption)) { | |
| if ("wForgottenReturn" in warningsOption) { | |
| wForgottenReturn = !!warningsOption.wForgottenReturn; | |
| } | |
| } | |
| } | |
| if ("cancellation" in opts && opts.cancellation && !config.cancellation) { | |
| if (async.haveItemsQueued()) { | |
| throw new Error( | |
| "cannot enable cancellation after promises are in use"); | |
| } | |
| Promise.prototype._clearCancellationData = | |
| cancellationClearCancellationData; | |
| Promise.prototype._propagateFrom = cancellationPropagateFrom; | |
| Promise.prototype._onCancel = cancellationOnCancel; | |
| Promise.prototype._setOnCancel = cancellationSetOnCancel; | |
| Promise.prototype._attachCancellationCallback = | |
| cancellationAttachCancellationCallback; | |
| Promise.prototype._execute = cancellationExecute; | |
| propagateFromFunction = cancellationPropagateFrom; | |
| config.cancellation = true; | |
| } | |
| if ("monitoring" in opts) { | |
| if (opts.monitoring && !config.monitoring) { | |
| config.monitoring = true; | |
| Promise.prototype._fireEvent = activeFireEvent; | |
| } else if (!opts.monitoring && config.monitoring) { | |
| config.monitoring = false; | |
| Promise.prototype._fireEvent = defaultFireEvent; | |
| } | |
| } | |
| if ("asyncHooks" in opts && util.nodeSupportsAsyncResource) { | |
| var prev = config.asyncHooks; | |
| var cur = !!opts.asyncHooks; | |
| if (prev !== cur) { | |
| config.asyncHooks = cur; | |
| if (cur) { | |
| enableAsyncHooks(); | |
| } else { | |
| disableAsyncHooks(); | |
| } | |
| } | |
| } | |
| return Promise; | |
| }; | |
| function defaultFireEvent() { return false; } | |
| Promise.prototype._fireEvent = defaultFireEvent; | |
| Promise.prototype._execute = function(executor, resolve, reject) { | |
| try { | |
| executor(resolve, reject); | |
| } catch (e) { | |
| return e; | |
| } | |
| }; | |
| Promise.prototype._onCancel = function () {}; | |
| Promise.prototype._setOnCancel = function (handler) { ; }; | |
| Promise.prototype._attachCancellationCallback = function(onCancel) { | |
| ; | |
| }; | |
| Promise.prototype._captureStackTrace = function () {}; | |
| Promise.prototype._attachExtraTrace = function () {}; | |
| Promise.prototype._dereferenceTrace = function () {}; | |
| Promise.prototype._clearCancellationData = function() {}; | |
| Promise.prototype._propagateFrom = function (parent, flags) { | |
| ; | |
| ; | |
| }; | |
| function cancellationExecute(executor, resolve, reject) { | |
| var promise = this; | |
| try { | |
| executor(resolve, reject, function(onCancel) { | |
| if (typeof onCancel !== "function") { | |
| throw new TypeError("onCancel must be a function, got: " + | |
| util.toString(onCancel)); | |
| } | |
| promise._attachCancellationCallback(onCancel); | |
| }); | |
| } catch (e) { | |
| return e; | |
| } | |
| } | |
| function cancellationAttachCancellationCallback(onCancel) { | |
| if (!this._isCancellable()) return this; | |
| var previousOnCancel = this._onCancel(); | |
| if (previousOnCancel !== undefined) { | |
| if (util.isArray(previousOnCancel)) { | |
| previousOnCancel.push(onCancel); | |
| } else { | |
| this._setOnCancel([previousOnCancel, onCancel]); | |
| } | |
| } else { | |
| this._setOnCancel(onCancel); | |
| } | |
| } | |
| function cancellationOnCancel() { | |
| return this._onCancelField; | |
| } | |
| function cancellationSetOnCancel(onCancel) { | |
| this._onCancelField = onCancel; | |
| } | |
| function cancellationClearCancellationData() { | |
| this._cancellationParent = undefined; | |
| this._onCancelField = undefined; | |
| } | |
| function cancellationPropagateFrom(parent, flags) { | |
| if ((flags & 1) !== 0) { | |
| this._cancellationParent = parent; | |
| var branchesRemainingToCancel = parent._branchesRemainingToCancel; | |
| if (branchesRemainingToCancel === undefined) { | |
| branchesRemainingToCancel = 0; | |
| } | |
| parent._branchesRemainingToCancel = branchesRemainingToCancel + 1; | |
| } | |
| if ((flags & 2) !== 0 && parent._isBound()) { | |
| this._setBoundTo(parent._boundTo); | |
| } | |
| } | |
| function bindingPropagateFrom(parent, flags) { | |
| if ((flags & 2) !== 0 && parent._isBound()) { | |
| this._setBoundTo(parent._boundTo); | |
| } | |
| } | |
| var propagateFromFunction = bindingPropagateFrom; | |
| function boundValueFunction() { | |
| var ret = this._boundTo; | |
| if (ret !== undefined) { | |
| if (ret instanceof Promise) { | |
| if (ret.isFulfilled()) { | |
| return ret.value(); | |
| } else { | |
| return undefined; | |
| } | |
| } | |
| } | |
| return ret; | |
| } | |
| function longStackTracesCaptureStackTrace() { | |
| this._trace = new CapturedTrace(this._peekContext()); | |
| } | |
| function longStackTracesAttachExtraTrace(error, ignoreSelf) { | |
| if (canAttachTrace(error)) { | |
| var trace = this._trace; | |
| if (trace !== undefined) { | |
| if (ignoreSelf) trace = trace._parent; | |
| } | |
| if (trace !== undefined) { | |
| trace.attachExtraTrace(error); | |
| } else if (!error.__stackCleaned__) { | |
| var parsed = parseStackAndMessage(error); | |
| util.notEnumerableProp(error, "stack", | |
| parsed.message + "\n" + parsed.stack.join("\n")); | |
| util.notEnumerableProp(error, "__stackCleaned__", true); | |
| } | |
| } | |
| } | |
| function longStackTracesDereferenceTrace() { | |
| this._trace = undefined; | |
| } | |
| function checkForgottenReturns(returnValue, promiseCreated, name, promise, | |
| parent) { | |
| if (returnValue === undefined && promiseCreated !== null && | |
| wForgottenReturn) { | |
| if (parent !== undefined && parent._returnedNonUndefined()) return; | |
| if ((promise._bitField & 65535) === 0) return; | |
| if (name) name = name + " "; | |
| var handlerLine = ""; | |
| var creatorLine = ""; | |
| if (promiseCreated._trace) { | |
| var traceLines = promiseCreated._trace.stack.split("\n"); | |
| var stack = cleanStack(traceLines); | |
| for (var i = stack.length - 1; i >= 0; --i) { | |
| var line = stack[i]; | |
| if (!nodeFramePattern.test(line)) { | |
| var lineMatches = line.match(parseLinePattern); | |
| if (lineMatches) { | |
| handlerLine = "at " + lineMatches[1] + | |
| ":" + lineMatches[2] + ":" + lineMatches[3] + " "; | |
| } | |
| break; | |
| } | |
| } | |
| if (stack.length > 0) { | |
| var firstUserLine = stack[0]; | |
| for (var i = 0; i < traceLines.length; ++i) { | |
| if (traceLines[i] === firstUserLine) { | |
| if (i > 0) { | |
| creatorLine = "\n" + traceLines[i - 1]; | |
| } | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| var msg = "a promise was created in a " + name + | |
| "handler " + handlerLine + "but was not returned from it, " + | |
| "see http://goo.gl/rRqMUw" + | |
| creatorLine; | |
| promise._warn(msg, true, promiseCreated); | |
| } | |
| } | |
| function deprecated(name, replacement) { | |
| var message = name + | |
| " is deprecated and will be removed in a future version."; | |
| if (replacement) message += " Use " + replacement + " instead."; | |
| return warn(message); | |
| } | |
| function warn(message, shouldUseOwnTrace, promise) { | |
| if (!config.warnings) return; | |
| var warning = new Warning(message); | |
| var ctx; | |
| if (shouldUseOwnTrace) { | |
| promise._attachExtraTrace(warning); | |
| } else if (config.longStackTraces && (ctx = Promise._peekContext())) { | |
| ctx.attachExtraTrace(warning); | |
| } else { | |
| var parsed = parseStackAndMessage(warning); | |
| warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); | |
| } | |
| if (!activeFireEvent("warning", warning)) { | |
| formatAndLogError(warning, "", true); | |
| } | |
| } | |
| function reconstructStack(message, stacks) { | |
| for (var i = 0; i < stacks.length - 1; ++i) { | |
| stacks[i].push("From previous event:"); | |
| stacks[i] = stacks[i].join("\n"); | |
| } | |
| if (i < stacks.length) { | |
| stacks[i] = stacks[i].join("\n"); | |
| } | |
| return message + "\n" + stacks.join("\n"); | |
| } | |
| function removeDuplicateOrEmptyJumps(stacks) { | |
| for (var i = 0; i < stacks.length; ++i) { | |
| if (stacks[i].length === 0 || | |
| ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { | |
| stacks.splice(i, 1); | |
| i--; | |
| } | |
| } | |
| } | |
| function removeCommonRoots(stacks) { | |
| var current = stacks[0]; | |
| for (var i = 1; i < stacks.length; ++i) { | |
| var prev = stacks[i]; | |
| var currentLastIndex = current.length - 1; | |
| var currentLastLine = current[currentLastIndex]; | |
| var commonRootMeetPoint = -1; | |
| for (var j = prev.length - 1; j >= 0; --j) { | |
| if (prev[j] === currentLastLine) { | |
| commonRootMeetPoint = j; | |
| break; | |
| } | |
| } | |
| for (var j = commonRootMeetPoint; j >= 0; --j) { | |
| var line = prev[j]; | |
| if (current[currentLastIndex] === line) { | |
| current.pop(); | |
| currentLastIndex--; | |
| } else { | |
| break; | |
| } | |
| } | |
| current = prev; | |
| } | |
| } | |
| function cleanStack(stack) { | |
| var ret = []; | |
| for (var i = 0; i < stack.length; ++i) { | |
| var line = stack[i]; | |
| var isTraceLine = " (No stack trace)" === line || | |
| stackFramePattern.test(line); | |
| var isInternalFrame = isTraceLine && shouldIgnore(line); | |
| if (isTraceLine && !isInternalFrame) { | |
| if (indentStackFrames && line.charAt(0) !== " ") { | |
| line = " " + line; | |
| } | |
| ret.push(line); | |
| } | |
| } | |
| return ret; | |
| } | |
| function stackFramesAsArray(error) { | |
| var stack = error.stack.replace(/\s+$/g, "").split("\n"); | |
| for (var i = 0; i < stack.length; ++i) { | |
| var line = stack[i]; | |
| if (" (No stack trace)" === line || stackFramePattern.test(line)) { | |
| break; | |
| } | |
| } | |
| if (i > 0 && error.name != "SyntaxError") { | |
| stack = stack.slice(i); | |
| } | |
| return stack; | |
| } | |
| function parseStackAndMessage(error) { | |
| var stack = error.stack; | |
| var message = error.toString(); | |
| stack = typeof stack === "string" && stack.length > 0 | |
| ? stackFramesAsArray(error) : [" (No stack trace)"]; | |
| return { | |
| message: message, | |
| stack: error.name == "SyntaxError" ? stack : cleanStack(stack) | |
| }; | |
| } | |
| function formatAndLogError(error, title, isSoft) { | |
| if (typeof console !== "undefined") { | |
| var message; | |
| if (util.isObject(error)) { | |
| var stack = error.stack; | |
| message = title + formatStack(stack, error); | |
| } else { | |
| message = title + String(error); | |
| } | |
| if (typeof printWarning === "function") { | |
| printWarning(message, isSoft); | |
| } else if (typeof console.log === "function" || | |
| typeof console.log === "object") { | |
| console.log(message); | |
| } | |
| } | |
| } | |
| function fireRejectionEvent(name, localHandler, reason, promise) { | |
| var localEventFired = false; | |
| try { | |
| if (typeof localHandler === "function") { | |
| localEventFired = true; | |
| if (name === "rejectionHandled") { | |
| localHandler(promise); | |
| } else { | |
| localHandler(reason, promise); | |
| } | |
| } | |
| } catch (e) { | |
| async.throwLater(e); | |
| } | |
| if (name === "unhandledRejection") { | |
| if (!activeFireEvent(name, reason, promise) && !localEventFired) { | |
| formatAndLogError(reason, "Unhandled rejection "); | |
| } | |
| } else { | |
| activeFireEvent(name, promise); | |
| } | |
| } | |
| function formatNonError(obj) { | |
| var str; | |
| if (typeof obj === "function") { | |
| str = "[function " + | |
| (obj.name || "anonymous") + | |
| "]"; | |
| } else { | |
| str = obj && typeof obj.toString === "function" | |
| ? obj.toString() : util.toString(obj); | |
| var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; | |
| if (ruselessToString.test(str)) { | |
| try { | |
| var newStr = JSON.stringify(obj); | |
| str = newStr; | |
| } | |
| catch(e) { | |
| } | |
| } | |
| if (str.length === 0) { | |
| str = "(empty array)"; | |
| } | |
| } | |
| return ("(<" + snip(str) + ">, no stack trace)"); | |
| } | |
| function snip(str) { | |
| var maxChars = 41; | |
| if (str.length < maxChars) { | |
| return str; | |
| } | |
| return str.substr(0, maxChars - 3) + "..."; | |
| } | |
| function longStackTracesIsSupported() { | |
| return typeof captureStackTrace === "function"; | |
| } | |
| var shouldIgnore = function() { return false; }; | |
| var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; | |
| function parseLineInfo(line) { | |
| var matches = line.match(parseLineInfoRegex); | |
| if (matches) { | |
| return { | |
| fileName: matches[1], | |
| line: parseInt(matches[2], 10) | |
| }; | |
| } | |
| } | |
| function setBounds(firstLineError, lastLineError) { | |
| if (!longStackTracesIsSupported()) return; | |
| var firstStackLines = (firstLineError.stack || "").split("\n"); | |
| var lastStackLines = (lastLineError.stack || "").split("\n"); | |
| var firstIndex = -1; | |
| var lastIndex = -1; | |
| var firstFileName; | |
| var lastFileName; | |
| for (var i = 0; i < firstStackLines.length; ++i) { | |
| var result = parseLineInfo(firstStackLines[i]); | |
| if (result) { | |
| firstFileName = result.fileName; | |
| firstIndex = result.line; | |
| break; | |
| } | |
| } | |
| for (var i = 0; i < lastStackLines.length; ++i) { | |
| var result = parseLineInfo(lastStackLines[i]); | |
| if (result) { | |
| lastFileName = result.fileName; | |
| lastIndex = result.line; | |
| break; | |
| } | |
| } | |
| if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || | |
| firstFileName !== lastFileName || firstIndex >= lastIndex) { | |
| return; | |
| } | |
| shouldIgnore = function(line) { | |
| if (bluebirdFramePattern.test(line)) return true; | |
| var info = parseLineInfo(line); | |
| if (info) { | |
| if (info.fileName === firstFileName && | |
| (firstIndex <= info.line && info.line <= lastIndex)) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| }; | |
| } | |
| function CapturedTrace(parent) { | |
| this._parent = parent; | |
| this._promisesCreated = 0; | |
| var length = this._length = 1 + (parent === undefined ? 0 : parent._length); | |
| captureStackTrace(this, CapturedTrace); | |
| if (length > 32) this.uncycle(); | |
| } | |
| util.inherits(CapturedTrace, Error); | |
| Context.CapturedTrace = CapturedTrace; | |
| CapturedTrace.prototype.uncycle = function() { | |
| var length = this._length; | |
| if (length < 2) return; | |
| var nodes = []; | |
| var stackToIndex = {}; | |
| for (var i = 0, node = this; node !== undefined; ++i) { | |
| nodes.push(node); | |
| node = node._parent; | |
| } | |
| length = this._length = i; | |
| for (var i = length - 1; i >= 0; --i) { | |
| var stack = nodes[i].stack; | |
| if (stackToIndex[stack] === undefined) { | |
| stackToIndex[stack] = i; | |
| } | |
| } | |
| for (var i = 0; i < length; ++i) { | |
| var currentStack = nodes[i].stack; | |
| var index = stackToIndex[currentStack]; | |
| if (index !== undefined && index !== i) { | |
| if (index > 0) { | |
| nodes[index - 1]._parent = undefined; | |
| nodes[index - 1]._length = 1; | |
| } | |
| nodes[i]._parent = undefined; | |
| nodes[i]._length = 1; | |
| var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; | |
| if (index < length - 1) { | |
| cycleEdgeNode._parent = nodes[index + 1]; | |
| cycleEdgeNode._parent.uncycle(); | |
| cycleEdgeNode._length = | |
| cycleEdgeNode._parent._length + 1; | |
| } else { | |
| cycleEdgeNode._parent = undefined; | |
| cycleEdgeNode._length = 1; | |
| } | |
| var currentChildLength = cycleEdgeNode._length + 1; | |
| for (var j = i - 2; j >= 0; --j) { | |
| nodes[j]._length = currentChildLength; | |
| currentChildLength++; | |
| } | |
| return; | |
| } | |
| } | |
| }; | |
| CapturedTrace.prototype.attachExtraTrace = function(error) { | |
| if (error.__stackCleaned__) return; | |
| this.uncycle(); | |
| var parsed = parseStackAndMessage(error); | |
| var message = parsed.message; | |
| var stacks = [parsed.stack]; | |
| var trace = this; | |
| while (trace !== undefined) { | |
| stacks.push(cleanStack(trace.stack.split("\n"))); | |
| trace = trace._parent; | |
| } | |
| removeCommonRoots(stacks); | |
| removeDuplicateOrEmptyJumps(stacks); | |
| util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); | |
| util.notEnumerableProp(error, "__stackCleaned__", true); | |
| }; | |
| var captureStackTrace = (function stackDetection() { | |
| var v8stackFramePattern = /^\s*at\s*/; | |
| var v8stackFormatter = function(stack, error) { | |
| if (typeof stack === "string") return stack; | |
| if (error.name !== undefined && | |
| error.message !== undefined) { | |
| return error.toString(); | |
| } | |
| return formatNonError(error); | |
| }; | |
| if (typeof Error.stackTraceLimit === "number" && | |
| typeof Error.captureStackTrace === "function") { | |
| Error.stackTraceLimit += 6; | |
| stackFramePattern = v8stackFramePattern; | |
| formatStack = v8stackFormatter; | |
| var captureStackTrace = Error.captureStackTrace; | |
| shouldIgnore = function(line) { | |
| return bluebirdFramePattern.test(line); | |
| }; | |
| return function(receiver, ignoreUntil) { | |
| Error.stackTraceLimit += 6; | |
| captureStackTrace(receiver, ignoreUntil); | |
| Error.stackTraceLimit -= 6; | |
| }; | |
| } | |
| var err = new Error(); | |
| if (typeof err.stack === "string" && | |
| err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { | |
| stackFramePattern = /@/; | |
| formatStack = v8stackFormatter; | |
| indentStackFrames = true; | |
| return function captureStackTrace(o) { | |
| o.stack = new Error().stack; | |
| }; | |
| } | |
| var hasStackAfterThrow; | |
| try { throw new Error(); } | |
| catch(e) { | |
| hasStackAfterThrow = ("stack" in e); | |
| } | |
| if (!("stack" in err) && hasStackAfterThrow && | |
| typeof Error.stackTraceLimit === "number") { | |
| stackFramePattern = v8stackFramePattern; | |
| formatStack = v8stackFormatter; | |
| return function captureStackTrace(o) { | |
| Error.stackTraceLimit += 6; | |
| try { throw new Error(); } | |
| catch(e) { o.stack = e.stack; } | |
| Error.stackTraceLimit -= 6; | |
| }; | |
| } | |
| formatStack = function(stack, error) { | |
| if (typeof stack === "string") return stack; | |
| if ((typeof error === "object" || | |
| typeof error === "function") && | |
| error.name !== undefined && | |
| error.message !== undefined) { | |
| return error.toString(); | |
| } | |
| return formatNonError(error); | |
| }; | |
| return null; | |
| })([]); | |
| if (typeof console !== "undefined" && typeof console.warn !== "undefined") { | |
| printWarning = function (message) { | |
| console.warn(message); | |
| }; | |
| if (util.isNode && process.stderr.isTTY) { | |
| printWarning = function(message, isSoft) { | |
| var color = isSoft ? "\u001b[33m" : "\u001b[31m"; | |
| console.warn(color + message + "\u001b[0m\n"); | |
| }; | |
| } else if (!util.isNode && typeof (new Error().stack) === "string") { | |
| printWarning = function(message, isSoft) { | |
| console.warn("%c" + message, | |
| isSoft ? "color: darkorange" : "color: red"); | |
| }; | |
| } | |
| } | |
| var config = { | |
| warnings: warnings, | |
| longStackTraces: false, | |
| cancellation: false, | |
| monitoring: false, | |
| asyncHooks: false | |
| }; | |
| if (longStackTraces) Promise.longStackTraces(); | |
| return { | |
| asyncHooks: function() { | |
| return config.asyncHooks; | |
| }, | |
| longStackTraces: function() { | |
| return config.longStackTraces; | |
| }, | |
| warnings: function() { | |
| return config.warnings; | |
| }, | |
| cancellation: function() { | |
| return config.cancellation; | |
| }, | |
| monitoring: function() { | |
| return config.monitoring; | |
| }, | |
| propagateFromFunction: function() { | |
| return propagateFromFunction; | |
| }, | |
| boundValueFunction: function() { | |
| return boundValueFunction; | |
| }, | |
| checkForgottenReturns: checkForgottenReturns, | |
| setBounds: setBounds, | |
| warn: warn, | |
| deprecated: deprecated, | |
| CapturedTrace: CapturedTrace, | |
| fireDomEvent: fireDomEvent, | |
| fireGlobalEvent: fireGlobalEvent | |
| }; | |
| }; | |