UNPKG

3.68 kBJavaScriptView Raw
1var Promise = require('unexpected-bluebird');
2var oathbreaker = require('./oathbreaker');
3var throwIfNonUnexpectedError = require('./throwIfNonUnexpectedError');
4
5function makePromise(body) {
6 if (typeof body !== 'function') {
7 throw new TypeError(
8 'expect.promise(...) requires a function argument to be supplied.\n' +
9 'See http://unexpected.js.org/api/promise/ for more details.'
10 );
11 }
12
13 if (body.length === 2) {
14 return new Promise(body);
15 }
16
17 return new Promise(function (resolve, reject) {
18 var runningTasks = 0;
19 var resolvedValue;
20 var outerFunctionHasReturned = false;
21
22 function fulfillIfDone() {
23 if (outerFunctionHasReturned && runningTasks === 0) {
24 resolve(resolvedValue);
25 }
26 }
27
28 function noteResolvedValue(value) {
29 if (
30 typeof value !== 'undefined' &&
31 typeof resolvedValue === 'undefined'
32 ) {
33 resolvedValue = value;
34 }
35 }
36
37 var runner = function (fn) {
38 runningTasks += 1;
39 return function () {
40 var args = [], len = arguments.length;
41 while ( len-- ) args[ len ] = arguments[ len ];
42
43 runningTasks -= 1;
44 var result;
45 try {
46 if (typeof fn === 'function') {
47 result = oathbreaker(fn.apply(void 0, args));
48 if (isPromise(result)) {
49 runningTasks += 1;
50 result.then(function (value) {
51 noteResolvedValue(value);
52 runningTasks -= 1;
53 fulfillIfDone();
54 }, reject);
55 } else {
56 noteResolvedValue(result);
57 }
58 }
59 } catch (e) {
60 return reject(e);
61 }
62 fulfillIfDone();
63 return result;
64 };
65 };
66
67 try {
68 var result = oathbreaker(body(runner));
69 if (isPromise(result)) {
70 runningTasks += 1;
71 result.then(function (value) {
72 noteResolvedValue(value);
73 runningTasks -= 1;
74 fulfillIfDone();
75 }, reject);
76 } else {
77 noteResolvedValue(result);
78 }
79 } catch (e) {
80 return reject(e);
81 }
82 outerFunctionHasReturned = true;
83 fulfillIfDone();
84 });
85}
86
87function isPromise(obj) {
88 return obj && typeof obj === 'object' && typeof obj.then === 'function';
89}
90
91function extractPromisesFromObject(obj) {
92 if (isPromise(obj)) {
93 return [obj];
94 } else if (obj && typeof obj === 'object') {
95 var promises = [];
96 // Object or Array
97 Object.keys(obj).forEach(function (key) {
98 promises.push.apply(promises, extractPromisesFromObject(obj[key]));
99 });
100 return promises;
101 }
102 return [];
103}
104
105['all', 'any', 'settle'].forEach(function (staticMethodName) {
106 makePromise[staticMethodName] = function (obj) {
107 var result = Promise[staticMethodName](extractPromisesFromObject(obj));
108 if (staticMethodName === 'settle') {
109 return result.then(function (promises) {
110 promises.forEach(function (promise) {
111 if (promise.isRejected()) {
112 throwIfNonUnexpectedError(promise.reason());
113 }
114 });
115 return promises;
116 });
117 }
118 return result;
119 };
120});
121
122// Expose all of Bluebird's static methods, except the ones related to long stack traces,
123// unhandled rejections and the scheduler, which we need to manage ourselves:
124Object.keys(Promise).forEach(function (staticMethodName) {
125 if (
126 !/^_|^on|^setScheduler|ongStackTraces/.test(staticMethodName) &&
127 typeof Promise[staticMethodName] === 'function' &&
128 typeof makePromise[staticMethodName] === 'undefined'
129 ) {
130 makePromise[staticMethodName] = Promise[staticMethodName];
131 }
132});
133
134module.exports = makePromise;