Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / third_party / Promises / Promise.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 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 Promises.
18 //
19 //    We identify the following features as required:
20 //
21 //      * Chaining of .then() calls
22 //      * Subclassing by DOM API designers (see ProgressPromise.idl, e.g.)
23 //      * Eventual import or subsetting by TC39 for adding Promises to the
24 //        language directly.
25 //
26 //  Non-Goals:
27 //
28 //    Unifying or describing the internal behavior of events is a non-goal.
29 //    Promises 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 Promises represent the completion of a single operation, past or
48 //    future, an error handling for that operation.
49 //
50 //    Promises 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 Promise.
54 //
55 //      function doAsyncWork() {
56 //        return new Promise(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 //    Promises 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 Promise(function(c) { callbacks = c; });
83 //      // Polyfills in debugging mode provide a "_state" property to track
84 //      // progress.
85 //      assertTrue(f._state == "pending");
86 //      callbacks.resolve(null);
87 //      assertTrue(f._state == "pending");
88 //
89 //      try {
90 //        callbacks.resolve(null);
91 //        // Not reached
92 //        assertTrue(false);
93 //      } catch(e) {
94 //        // Catch the AlreadyResolved error thrown by the second resolve()
95 //        assertTrue(e instanceof AlreadyResolved);
96 //      }
97 //
98 //  Chaining:
99 //
100 //    Chaining is a requirement, meaning that it must be possible to call
101 //    ".then()" and receive a sensible result from which you can ".then()"
102 //    again.
103 //
104 //    Promises return a new automatically-generated Promise from each
105 //    "then()" call. The then()-generated Promises are resolved by the
106 //    callbacks passed to each "then()" invocation. These functions are called
107 //    based on the resolution and their return values are passed onward to the
108 //    next auto-generated Promise:
109 //
110 //      // Example invocation
111 //      var doItAsync = function() {
112 //        var callbacks;
113 //        var f = new Promise(function(c) { callbacks = c; });
114 //        // ...
115 //        return f;
116 //      };
117 //      doItAsync()
118 //          .then(fulfill, reject)
119 //          .then(fulfillIntermediate)
120 //          .then(fulfillFinal);
121 //
122 //    Chaining fast-forwards un-handled values to the next item in the chain
123 //    which registers a handler for that particular disposition (fulfill &
124 //    reject). As in RSVP.js, the "onerror" function passed to then() is
125 //    called here, logging the exception:
126 //
127 //      doItAsync()
128 //          .then(function(){ throw new Error("spurious!"); })
129 //          .then(fulfill) // "fulfill" is not called, and we fast-forward
130 //          .then(null, console.error.bind(console));
131 //
132 //    If the second call were to handle "error", the final callback would not
133 //    receive an "error" unless it also rejected its Promise. e.g.:
134 //
135 //      doItAsync()
136 //          .then(function(){ throw new Error("spurious!"); })
137 //          .then(fulfill, console.error.bind(console)) // logs the error
138 //          .then(null, console.error.bind(console));    // does nothing
139 //
140 //  Return Value Sniffing, value/error Chaining, and Forwarding:
141 //
142 //    Like many other Promise systems, the callbacks for fulfill & error
143 //    are used to resolve the auto-generated Promise returned from a call to
144 //    then(). Below is the basic logic for then() callback return handling.
145 //    Major features:
146 //
147 //      * If the return is a Promise, merge the generated Promise's behavior
148 //        with it.
149 //      * If the callback throws, reject() the generated future with the thrown
150 //        value, even if the value is not an Error.
151 //      * If the return value is any other kind, use it as the "value" for
152 //        resolving the generated Promise.
153 //
154 //    TODO(slightlyoff): updated example logic
155 //
156 //    Similar logic is in place when using the resolve() method to provide a
157 //    value to resolve the Promise with; if a value passed to resolve() is a
158 //    Promise, the value of the "local" future assumes the value of the "far"
159 //    future. If it is any other value, it will be passed to fulfill(). The
160 //    behavior of fulfill is to move the Promise to the "fulfilled" state and
161 //    set .value to whatever value is passed (regardless of type).
162 //
163 //    Pseudo-code for resolve():
164 //
165 //      resolverInstance.resolve = function(value) {
166 //        if (isBrandedAsPromise(value)) {
167 //          value.then(this.resolve, this.reject);
168 //          return;
169 //        }
170 //        this.fulfill(value);
171 //      }.bind(resolverInstance);
172 //
173 //  Delivery order:
174 //
175 //    1) then() callbacks in the order of registration
176 //    2) then() callbacks added after initial dispatch phase ends
177 //
178 //    2 provides for a Promise to have then() callbacks added after it is
179 //    resolved, allowing programmers to treat a Promise object as something
180 //    which is safe to call .then() on at all times. For example, both calls to
181 //    then() in the following example will succeed and both callbacks will
182 //    receive the resolution value, albiet at different times:
183 //
184 //      var callbacks;
185 //      var f = new Promise(function(c) { callbacks = c; });
186 //      setTimeout(callbacks.fulfill.bind(callbacks, "Success!"), 1);
187 //      f.then(function(value) {
188 //        // Just to illuminate the timing, we make sure that our next then()
189 //        // call occurs well outside the current turn.
190 //        setTimeout(function() {
191 //          f.then(console.log.bind(console));
192 //        }, 1);
193 //      });
194 //
195 //    We observe that the second then()-added callback *DOES* log to the
196 //    console, but well after the initial resolution. All conforming
197 //    implementations MUST provide the ability for post-resolution then() calls
198 //    to resolve this way.
199 //
200 //  Cancelation and Timeouts:
201 //
202 //    The passed set of callbacks includes cancel() and timeout() functions.
203 //    These are syntactic sugar that generate Error objects with known name
204 //    values ("Cancel" and "Timeout", respectively). Handling these values is
205 //    done through the usual reject handler of a Promise. Using only fulfill()
206 //    and reject() we can re-create these sugar functions easily:
207 //
208 //      var callbacks;
209 //      var f = new Promise(function(c) { callbacks = c; });
210 //      // Compatible, ad-hoc versions of cancel() and timeout()
211 //      var cancel = function() { callbacks.reject(new Error("Cancel")); };
212 //      var timeout = function() { callbacks.reject(new Error("Timeout")); };
213 //
214 //      // Register a reject handler that understands cancelation and timeout:
215 //      f.then(fulfill, function(reason) {
216 //        switch(reason.name) {
217 //          case "Cancel":
218 //            // handle cancelation...
219 //            break;
220 //          case "Timeout":
221 //            // ...
222 //            break;
223 //          default:
224 //            break;
225 //        }
226 //      });
227 //
228 //    Calling either the ad-hoc cancel() or callbacks.cancel() will have the
229 //    same effect.
230 //
231 //  Errors and Exceptions:
232 //
233 //    As seen in the example code above, exceptions throw by callback handlers
234 //    are caught by the system. This leads to some particular debugging hazards
235 //    which other systems have treated in various ways. Some have opted simply
236 //    not to swallow errors. Some propagate errors in various ways (this design
237 //    employs a variant of that approach).
238 //
239 //    No matter what approach is pursued, integration with developer tooling is
240 //    key. Developer consoles SHOULD log un-caught errors from future chains.
241 //    That is to say, if future.then(onresponse); is the only handler given for
242 //    a resolver which is eventually rejected, developer tools should log the
243 //    unhandled error.
244
245 interface PromiseResolver {
246   // Directly resolves the Promise with the passed value
247   void fulfill(optional any value);
248
249   // Indirectly resolves the Promise, chaining any passed Promise's resolution
250   void resolve(optional any value);
251
252   // Rejects the future
253   void reject(optional any error);
254
255   // Note that implementations may keep internal state here, notably an
256   // "isResovled" flag.
257 };
258
259 callback PromiseCallback = void (PromiseResolver resolver);
260 callback AnyCallback = any (optional any value);
261
262 [Constructor(PromiseCallback init)]
263 interface Promise {
264   /////////////////////////////////
265   // Instance Methods
266
267   // Returns a Promise whose fulfillment value will be the return value
268   // from whichever of the callbacks is eventually invoked.
269   Promise then(optional AnyCallback fulfill, optional AnyCallback reject);
270
271   // A shorthand for not registering only an reject callback. Desugars to:
272   //
273   //    Promise.prototype.catch = function(reject) {
274   //      return this.then(undefined, reject);
275   //    };
276   //
277   Promise catch(optional AnyCallback reject);
278
279   /////////////////////////////////
280   // Statics
281
282   static Promise fulfill(any value);
283   static Promise resolve(any value); // same as any(value)
284   static Promise reject(any value);
285
286   // exposed as "any" in JavaScript, without "_"
287   static Promise _any(any... values);
288   // FIXME: Should be "all"?
289   static Promise every(any... values);
290   static Promise some(any... values);
291 };