Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / third_party / Promises / Future.idl
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  */
4
5 //
6 // Design Notes
7 // ============
8 //
9 //  Goals:
10 //
11 //    This design for a DOM-compatible Future (nee, "Promise") type aims to be
12 //    usable in the majority of the web's single-response asynchronous APIs,
13 //    either directly or through subclass (e.g., to add progress notification).
14 //
15 //    It also aims to enable end-users (non-spec authors) to build systems
16 //    using these types directly without appealing to libraries or DOM magic
17 //    for creating/fulfilling Futures.
18 //
19 //    We identify the following features as required:
20 //
21 //      * Chaining of .then() calls
22 //      * Subclassing by DOM API designers (see ProgressFuture.idl, e.g.)
23 //      * Eventual import or subsetting by TC39 for adding Futures to the
24 //        language directly.
25 //
26 //  Non-Goals:
27 //
28 //    Unifying or describing the internal behavior of events is a non-goal.
29 //    Futures are a single-request/single-repose formalism and may capture
30 //    values from past resposes. Events, on the other hand, describe a series
31 //    of future events. They cover separate use-cases and we do not seek to
32 //    join them here.
33 //
34 //    Compatibility with existing promises/futures/deferreds libraries or
35 //    terminology is a non-goal. Where adopting existing terminology improves
36 //    the usability of this design, we will. Otherwise, appeals to
37 //    compatibility with published libraries, specifications, and practice are
38 //    not compelling. So far, this is compatible with the
39 //    Promises/A+ spec, although largely by accident and in part because it
40 //    leaves core compatibility points (such as defining what it means to be a
41 //    testable "Promise" type in return handling) undefined:
42 //
43 //      https://github.com/promises-aplus/promises-spec
44 //
45 //  Basic API:
46 //
47 //    DOM Futures represent the completion of a single operation, past or
48 //    future, an error handling for that operation.
49 //
50 //    Futures take an initialization function as their only parameter. This
51 //    function is called back synchronously (by the time construction finishes)
52 //    with references to the the resolve and reject functions that can later be
53 //    used to resolve the Future.
54 //
55 //      function doAsyncWork() {
56 //        return new Future(function(r) {
57 //          setTimeout(function() { // ...time passes
58 //            // Do work here
59 //            r.resolve("success");
60 //          }, 100);
61 //        });
62 //      }
63 //
64 //      // Callers of the function can be notified of resolution easily:
65 //      doAsyncWork().then(console.log.bind(console));
66 //
67 //    Futures provide a way for others to be notified when the resolution
68 //    occurs without handing them the ability to resolve the future itself.
69 //    This is accomplished either by providing callbacks to the ".then()"
70 //    method.
71 //
72 //  Processing model:
73 //
74 //    the delivery of any resolution or error must be "apparently
75 //    asynchronous", specifically they must be delayed at least to the "end of
76 //    microtask" as defined for the delivery of mutation observer and
77 //    object.observe() notifications. delivery at any point beyond that, e.g.
78 //    in the next turn or microtask, is allowed, but all implementations must
79 //    demonstrate the following behavior:
80 //
81 //      var callbacks;
82 //      var f = new Future(function(c) { callbacks = c; });
83 //      assertTrue(f.state == "pending");
84 //      callbacks.resolve(null);
85 //      assertTrue(f.state == "pending");
86 //
87 //      try {
88 //        callbacks.resolve(null);
89 //        // Not reached
90 //        assertTrue(false);
91 //      } catch(e) {
92 //        // Catch the AlreadyResolved error thrown by the second resolve()
93 //        assertTrue(e instanceof AlreadyResolved);
94 //      }
95 //
96 //  Chaining:
97 //
98 //    Chaining is a requirement, meaning that it must be possible to call
99 //    ".then()" and receive a sensible result from which you can ".then()"
100 //    again.
101 //
102 //    Futures return a new automatically-generated Future from each
103 //    "then()" call. The then()-generated Futures are resolved by the
104 //    callbacks passed to each "then()" invocation. These functions are called
105 //    based on the resolution and their return values are passed onward to the
106 //    next auto-generated Future:
107 //
108 //      // Example invocation
109 //      var doItAsync = function() {
110 //        var callbacks;
111 //        var f = new Future(function(c) { callbacks = c; });
112 //        // ...
113 //        return f;
114 //      };
115 //      doItAsync()
116 //          .then(accept, reject)
117 //          .then(acceptIntermediate)
118 //          .done(acceptFinal);
119 //
120 //    Chaining fast-forwards un-handled values to the next item in the chain
121 //    which registers a handler for that particular disposition (accept &
122 //    reject). As in RSVP.js, the "onerror" function passed to done() is called
123 //    here, logging the exception:
124 //
125 //      doItAsync()
126 //          .then(function(){ throw new Error("spurious!"); })
127 //          .then(accept) // "accept" is not called, and we fast-forward
128 //          .done(null, console.error.bind(console));
129 //
130 //    If the second call were to handle "error", the final callback would not
131 //    receive an "error" unless it also rejected its Future. e.g.:
132 //
133 //      doItAsync()
134 //          .then(function(){ throw new Error("spurious!"); })
135 //          .then(accept, console.error.bind(console)) // logs the error
136 //          .done(null, console.error.bind(console));    // does nothing
137 //
138 //  Return Value Sniffing, value/error Chaining, and Forwarding:
139 //
140 //    Like many other Future systems, the callbacks for accept & error
141 //    are used to resolve the auto-generated Future returned from a call to
142 //    then(). Below is the basic logic for then() callback return handling.
143 //    Major features:
144 //
145 //      * If the return is a Future, merge the generated Future's behavior
146 //        with it.
147 //      * If the callback throws, reject() the generated future with the thrown
148 //        value, even if the value is not an Error.
149 //      * If the return value is any other kind, use it as the "value" for
150 //        resolving the generated Future.
151 //
152 //    TODO(slightlyoff): updated example logic
153 //
154 //    Similar logic is in place when using the resolve() method to provide a
155 //    value to resolve the Future with; if a value passed to resolve() is a
156 //    Future, the value of the "local" future assumes the value of the "far"
157 //    future. If it is any other value, it will be passed to accept(). The
158 //    behavior of accept is to move the Future to the "accepted" state and
159 //    set .value to whatever value is passed (regardless of type).
160 //
161 //    Pseudo-code for resolve():
162 //
163 //      resolverInstance.resolve = function(value) {
164 //        if (isThenable(value)) {
165 //          value.then(this.resolve, this.reject);
166 //          return;
167 //        }
168 //        this.accept(value);
169 //      }.bind(resolverInstance);
170 //
171 //  Delivery order:
172 //
173 //    1) then() callbacks in the order of registration
174 //    2) then() callbacks added after initial dispatch phase ends
175 //
176 //    2 provides for a Future to have then() callbacks added after it is
177 //    resolved, allowing programmers to treat a Future object as something
178 //    which is safe to call .then() on at all times. For example, both calls to
179 //    then() in the following example will succeed and both callbacks will
180 //    receive the resolution value, albiet at different times:
181 //
182 //      var callbacks;
183 //      var f = new Future(function(c) { callbacks = c; });
184 //      setTimeout(callbacks.accept.bind(callbacks, "Success!"), 1);
185 //      f.then(function(value) {
186 //        // Just to illuminate the timing, we make sure that our next then()
187 //        // call occurs well outside the current turn.
188 //        setTimeout(function() {
189 //          f.then(console.log.bind(console));
190 //        }, 1);
191 //      });
192 //
193 //    We observe that the second then()-added callback *DOES* log to the
194 //    console, but well after the initial resolution. All conforming
195 //    implementations MUST provide the ability for post-resolution then() calls
196 //    to resolve this way.
197 //
198 //  Cancelation and Timeouts:
199 //
200 //    The passed set of callbacks includes cancel() and timeout() functions.
201 //    These are syntactic sugar that generate Error objects with known name
202 //    values ("Cancel" and "Timeout", respectively). Handling these values is
203 //    done through the usual reject handler of a Future. Using only accept()
204 //    and reject() we can re-create these sugar functions easily:
205 //
206 //      var callbacks;
207 //      var f = new Future(function(c) { callbacks = c; });
208 //      // Compatible, ad-hoc versions of cancel() and timeout()
209 //      var cancel = function() { callbacks.reject(new Error("Cancel")); };
210 //      var timeout = function() { callbacks.reject(new Error("Timeout")); };
211 //
212 //      // Register a reject handler that understands cancelation and timeout:
213 //      f.then(accept, function(reason) {
214 //        switch(reason.name) {
215 //          case "Cancel":
216 //            // handle cancelation...
217 //            break;
218 //          case "Timeout":
219 //            // ...
220 //            break;
221 //          default:
222 //            break;
223 //        }
224 //      });
225 //
226 //    Calling either the ad-hoc cancel() or callbacks.cancel() will have the
227 //    same effect.
228 //
229 //  Errors and Exceptions:
230 //
231 //    As seen in the example code above, exceptions throw by callback handlers
232 //    are caught by the system. This leads to some particular debugging hazards
233 //    which other systems have treated in various ways. Some have opted simply
234 //    not to swallow errors. Some propagate errors in various ways (this design
235 //    employs a variant of that approach).
236 //
237 //    No matter what approach is pursued, integration with developer tooling is
238 //    key. Developer consoles SHOULD log un-caught errors from future chains.
239 //    That is to say, if future.done(onresponse); is the only handler given for
240 //    a resolver which is eventually rejected, developer tools should log the
241 //    unhandled error.
242
243 // Futures begin in the "pending" state and progress to other
244 // states. Once moved from the "pending" state, they may never be
245 // returned to it. The states are exclusive.
246 enum FutureState {
247   "pending",
248   "accepted",
249   "rejected"
250 };
251
252 interface FutureResolver {
253   // Directly resolves the Future with the passed value
254   void accept(optional any value); // can throw AlreadyResolved
255
256   // Indirectly resolves the Future, chaining any passed Future's resolution
257   void resolve(optional any value); // can throw AlreadyResolved
258
259   // Rejects the future
260   void reject(optional any error); // can throw AlreadyResolved
261
262   // Rejects with an error of: Error("Cancel")
263   void cancel(); // can throw AlreadyResolved
264
265   // Rejects with an error of: Error("Timeout")
266   void timeout(); // can throw AlreadyResolved
267
268   // false until (and unless) calling any of the above methods would raise an
269   // AlreadyResolved exception
270   readonly attribute boolean isResolved;
271 };
272
273 callback FutureCallback = void (FutureResolver resolver);
274 callback AnyCallback = any (optional any value);
275
276 [Constructor(FutureCallback init)]
277 interface Future {
278   attribute readonly any            value;
279   attribute readonly any            error;
280   attribute readonly FutureState    state;
281
282   // Returns a Future whose fulfillment value will be the return value
283   // from whichever of the callbacks is eventually invoked.
284   Future then(optional AnyCallback accept, optional AnyCallback reject);
285
286   // A shorthand for not registering only an reject callback. Desugars to:
287   //
288   //    Future.prototype.catch = function(reject) {
289   //      return this.then(undefined, reject);
290   //    };
291   Future catch(optional AnyCallback reject);
292
293   // An end-of-chain callback. Equivalent to .then() except it does not generate
294   // a new Future and therefore ignores the return values of the callbacks.
295   void done(optional AnyCallback accept, optional AnyCallback reject);
296 };