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.

1009 lines
31 KiB

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