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 };