coroutine.js: call dump_error for exceptions due to programming errors
[conkeror.git] / modules / coroutine.js
blob456ca80bd30382a17bca3f24e1955f5f15bfa9c5
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  *
4  * Use, modification, and distribution are subject to the terms specified in the
5  * COPYING file.
6 **/
8 function _return_value(x) {
9     this.value = x;
12 function co_return(x) {
13     return new _return_value(x);
16 const CONTINUATION = { toString: function () "[object CONTINUATION]" };
17 const SUSPEND = { toString: function () "[object SUSPEND]" };
19 function is_coroutine(obj) {
20     return obj != null &&
21         typeof(obj) == "object" &&
22         typeof(obj.next) == "function" &&
23         typeof(obj.send) == "function";
26 function _do_call(f) {
27     var cc = yield;
29     var stack = [];
30     var y = undefined;
31     var throw_value = false;
32     while (true) {
33         try {
34             let x;
35             if (throw_value) {
36                 throw_value = false;
37                 x = f.throw(y);
38             }
39             else
40                 x = f.send(y);
42             if (x == CONTINUATION) {
43                 y = cc;
44                 continue;
45             }
47             if (x === SUSPEND) {
48                 try {
49                     x = yield;
50                     y = x;
51                 } catch (e) {
52                     throw_value = true;
53                     y = e;
54                 }
55                 continue;
56             }
58             if (is_coroutine(x))
59             {
60                 stack[stack.length] = f;
61                 f = x;
62                 y = undefined;
63                 continue;
64             }
66             if (x instanceof _return_value) {
67                 if (stack.length == 0)
68                     return;
69                 f.close();
70                 f = stack[stack.length - 1];
71                 stack.length--;
72                 y = x.value;
73                 continue;
74             }
76             // Just return the value back to the function
77             y = x;
78         } catch (e) {
79             if (stack.length == 0)
80                 return;
81             f = stack[stack.length - 1];
82             stack.length--;
83             if (e instanceof StopIteration)
84                 y = undefined;
85             else {
86                 y = e;
87                 throw_value = true;
88             }
89         }
90     }
93 function co_call(f) {
94     if (!is_coroutine(f))
95         return;
96     var g = _do_call(f);
97     g.next();
98     var cc = function (x) {
99         try {
100             g.send(x);
101         } catch (e if e instanceof StopIteration) {}
102         catch (e) {
103             // Dump this error, because it indicates a programming error
104             dump_error(e);
105         }
106     };
107     cc.throw = function (x) {
108         try {
109             g.throw(x);
110         } catch (e if e instanceof StopIteration) {}
111         catch (e) {
112             // Dump this error, because it indicates a programming error
113             dump_error(e);
114         }
115     };
116     try {
117         g.send(cc);
118     } catch (e if e instanceof StopIteration) {}
119     catch (e) {
120         // Dump this error, because it indicates a programming error
121         dump_error(e);
122     }
123     return cc;