You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

debuggability.js 30KB

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