-
Notifications
You must be signed in to change notification settings - Fork 3
/
promise.js
105 lines (98 loc) · 2.98 KB
/
promise.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
"use strict";
/* This is minimal implementation of the Nodent runtime that _requires_ external support for Promise, either as a
* platform-supplied global, or by setting $asyncbind.Promise once the runtime is loaded but before it is called,eg:
*
* var _asyncRuntime = require('nodent-runtime/promise') ;
* _asyncRuntime.$asyncbind.Promise = MyPromiseImpl ;
*
* $asyncbind has multiple uses, depending on the parameter list. 'this' is always a function to be bound
*/
function $asyncbind(self,catcher) {
"use strict";
var resolver = this;
switch (catcher) {
case true:
case 0:
return new ($asyncbind.Promise)(self);
case undefined:
return function boundThen() {
return resolver.apply(self,arguments);
}
default:
return function(){
try {
return resolver.apply(self,arguments);
} catch(ex) {
return catcher(ex);
}
}
}
} ;
function $asyncspawn(promiseProvider,self) {
if (!(this instanceof Function)) return ;
var genF = this ;
return new promiseProvider(function enough(resolve, reject) {
var gen = genF.call(self, resolve, reject);
function step(fn,arg) {
var next;
try {
next = fn.call(gen,arg);
if(next.done) {
if (next.value !== resolve) {
if (next.value && next.value===next.value.then)
return next.value(resolve,reject) ;
resolve && resolve(next.value);
resolve = null ;
}
return;
}
if (next.value.then) {
next.value.then(function(v) {
step(gen.next,v);
}, function(e) {
step(gen.throw,e);
});
} else {
step(gen.next,next.value);
}
} catch(e) {
reject && reject(e);
reject = null ;
return;
}
}
step(gen.next);
});
}
function trampoline(t,x,s,e,u){
return function b(q) {
while (q) {
if (q.then) {
q = q.then(b, e) ;
return u?undefined:q;
}
try {
if (q.pop) {
if (q.length)
return q.pop() ? x.call(t) : q;
q = s;
} else
q = q.call(t)
} catch (r) {
return e(r);
}
}
}
};
/*$asyncbind.LazyThenable = $asyncbind.EagerThenable = $asyncbind.Thenable = */
try {
$asyncbind.Promise = Promise;
} catch (ex) {
// No global Promise is defined - maybe the caller will set one.
}
$asyncbind.trampoline = trampoline ;
// Export async bindings
module.exports = {
$asyncbind:$asyncbind,
$asyncspawn:$asyncspawn
};