1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5(function(global, utils, extrasUtils) {
6
7"use strict";
8
9%CheckIsBootstrapping();
10
11// -------------------------------------------------------------------
12// Imports
13
14var InternalArray = utils.InternalArray;
15var promiseAsyncStackIDSymbol =
16    utils.ImportNow("promise_async_stack_id_symbol");
17var promiseHandledBySymbol =
18    utils.ImportNow("promise_handled_by_symbol");
19var promiseForwardingHandlerSymbol =
20    utils.ImportNow("promise_forwarding_handler_symbol");
21var promiseHasHandlerSymbol =
22    utils.ImportNow("promise_has_handler_symbol");
23var promiseRejectReactionsSymbol =
24    utils.ImportNow("promise_reject_reactions_symbol");
25var promiseFulfillReactionsSymbol =
26    utils.ImportNow("promise_fulfill_reactions_symbol");
27var promiseDeferredReactionSymbol =
28    utils.ImportNow("promise_deferred_reaction_symbol");
29var promiseHandledHintSymbol =
30    utils.ImportNow("promise_handled_hint_symbol");
31var promiseRawSymbol = utils.ImportNow("promise_raw_symbol");
32var promiseStateSymbol = utils.ImportNow("promise_state_symbol");
33var promiseResultSymbol = utils.ImportNow("promise_result_symbol");
34var SpeciesConstructor;
35var speciesSymbol = utils.ImportNow("species_symbol");
36var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
37var ObjectHasOwnProperty;
38
39utils.Import(function(from) {
40  ObjectHasOwnProperty = from.ObjectHasOwnProperty;
41  SpeciesConstructor = from.SpeciesConstructor;
42});
43
44// -------------------------------------------------------------------
45
46// [[PromiseState]] values:
47// These values should be kept in sync with PromiseStatus in globals.h
48const kPending = 0;
49const kFulfilled = +1;
50const kRejected = +2;
51
52const kResolveCallback = 0;
53const kRejectCallback = 1;
54
55// ES#sec-promise-executor
56// Promise ( executor )
57var GlobalPromise = function Promise(executor) {
58  if (executor === promiseRawSymbol) {
59    return %_NewObject(GlobalPromise, new.target);
60  }
61  if (IS_UNDEFINED(new.target)) throw %make_type_error(kNotAPromise, this);
62  if (!IS_CALLABLE(executor)) {
63    throw %make_type_error(kResolverNotAFunction, executor);
64  }
65
66  var promise = PromiseInit(%_NewObject(GlobalPromise, new.target));
67  // Calling the reject function would be a new exception, so debugEvent = true
68  // TODO(gsathya): Remove container for callbacks when this is moved
69  // to CPP/TF.
70  var callbacks = %create_resolving_functions(promise, true);
71  var debug_is_active = DEBUG_IS_ACTIVE;
72  try {
73    if (debug_is_active) %DebugPushPromise(promise);
74    executor(callbacks[kResolveCallback], callbacks[kRejectCallback]);
75  } %catch (e) {  // Natives syntax to mark this catch block.
76    %_Call(callbacks[kRejectCallback], UNDEFINED, e);
77  } finally {
78    if (debug_is_active) %DebugPopPromise();
79  }
80
81  return promise;
82}
83
84// Core functionality.
85
86function PromiseSet(promise, status, value) {
87  SET_PRIVATE(promise, promiseStateSymbol, status);
88  SET_PRIVATE(promise, promiseResultSymbol, value);
89
90  // There are 3 possible states for the resolve, reject symbols when we add
91  // a new callback --
92  // 1) UNDEFINED -- This is the zero state where there is no callback
93  // registered. When we see this state, we directly attach the callbacks to
94  // the symbol.
95  // 2) !IS_ARRAY -- There is a single callback directly attached to the
96  // symbols. We need to create a new array to store additional callbacks.
97  // 3) IS_ARRAY -- There are multiple callbacks already registered,
98  // therefore we can just push the new callback to the existing array.
99  SET_PRIVATE(promise, promiseFulfillReactionsSymbol, UNDEFINED);
100  SET_PRIVATE(promise, promiseRejectReactionsSymbol, UNDEFINED);
101
102  // This symbol is used only when one deferred needs to be attached. When more
103  // than one deferred need to be attached the promise, we attach them directly
104  // to the promiseFulfillReactionsSymbol and promiseRejectReactionsSymbol and
105  // reset this back to UNDEFINED.
106  SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED);
107
108  return promise;
109}
110
111function PromiseCreateAndSet(status, value) {
112  var promise = new GlobalPromise(promiseRawSymbol);
113  // If debug is active, notify about the newly created promise first.
114  if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED);
115  return PromiseSet(promise, status, value);
116}
117
118function PromiseInit(promise) {
119  return PromiseSet(promise, kPending, UNDEFINED);
120}
121
122function PromiseHandle(value, handler, deferred) {
123  var debug_is_active = DEBUG_IS_ACTIVE;
124  try {
125    if (debug_is_active) %DebugPushPromise(deferred.promise);
126    var result = handler(value);
127    if (IS_UNDEFINED(deferred.resolve)) {
128      ResolvePromise(deferred.promise, result);
129    } else {
130      %_Call(deferred.resolve, UNDEFINED, result);
131    }
132  } %catch (exception) {  // Natives syntax to mark this catch block.
133    try {
134      if (IS_UNDEFINED(deferred.reject)) {
135        // Pass false for debugEvent so .then chaining does not trigger
136        // redundant ExceptionEvents.
137        %PromiseReject(deferred.promise, exception, false);
138        PromiseSet(deferred.promise, kRejected, exception);
139      } else {
140        %_Call(deferred.reject, UNDEFINED, exception);
141      }
142    } catch (e) { }
143  } finally {
144    if (debug_is_active) %DebugPopPromise();
145  }
146}
147
148function PromiseDebugGetInfo(deferreds, status) {
149  var id, name, instrumenting = DEBUG_IS_ACTIVE;
150
151  if (instrumenting) {
152    // In an async function, reuse the existing stack related to the outer
153    // Promise. Otherwise, e.g. in a direct call to then, save a new stack.
154    // Promises with multiple reactions with one or more of them being async
155    // functions will not get a good stack trace, as async functions require
156    // different stacks from direct Promise use, but we save and restore a
157    // stack once for all reactions. TODO(littledan): Improve this case.
158    if (!IS_UNDEFINED(deferreds) &&
159        HAS_PRIVATE(deferreds.promise, promiseHandledBySymbol) &&
160        HAS_PRIVATE(GET_PRIVATE(deferreds.promise, promiseHandledBySymbol),
161                    promiseAsyncStackIDSymbol)) {
162      id = GET_PRIVATE(GET_PRIVATE(deferreds.promise, promiseHandledBySymbol),
163                       promiseAsyncStackIDSymbol);
164      name = "async function";
165    } else {
166      id = %DebugNextMicrotaskId();
167      name = status === kFulfilled ? "Promise.resolve" : "Promise.reject";
168      %DebugAsyncTaskEvent("enqueue", id, name);
169    }
170  }
171  return [id, name];
172}
173
174function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) {
175  var maybeResolveCallbacks =
176      GET_PRIVATE(promise, promiseFulfillReactionsSymbol);
177  if (IS_UNDEFINED(maybeResolveCallbacks)) {
178    SET_PRIVATE(promise, promiseFulfillReactionsSymbol, onResolve);
179    SET_PRIVATE(promise, promiseRejectReactionsSymbol, onReject);
180    SET_PRIVATE(promise, promiseDeferredReactionSymbol, deferred);
181  } else if (!IS_ARRAY(maybeResolveCallbacks)) {
182    var resolveCallbacks = new InternalArray();
183    var rejectCallbacks = new InternalArray();
184    var existingDeferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol);
185
186    resolveCallbacks.push(
187        maybeResolveCallbacks, existingDeferred, onResolve, deferred);
188    rejectCallbacks.push(GET_PRIVATE(promise, promiseRejectReactionsSymbol),
189                         existingDeferred,
190                         onReject,
191                         deferred);
192
193    SET_PRIVATE(promise, promiseFulfillReactionsSymbol, resolveCallbacks);
194    SET_PRIVATE(promise, promiseRejectReactionsSymbol, rejectCallbacks);
195    SET_PRIVATE(promise, promiseDeferredReactionSymbol, UNDEFINED);
196  } else {
197    maybeResolveCallbacks.push(onResolve, deferred);
198    GET_PRIVATE(promise, promiseRejectReactionsSymbol).push(onReject, deferred);
199  }
200}
201
202function PromiseIdResolveHandler(x) { return x; }
203function PromiseIdRejectHandler(r) { %_ReThrow(r); }
204SET_PRIVATE(PromiseIdRejectHandler, promiseForwardingHandlerSymbol, true);
205
206// -------------------------------------------------------------------
207// Define exported functions.
208
209// For bootstrapper.
210
211// ES#sec-ispromise IsPromise ( x )
212function IsPromise(x) {
213  return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol);
214}
215
216function PromiseCreate() {
217  return PromiseInit(new GlobalPromise(promiseRawSymbol));
218}
219
220// ES#sec-promise-resolve-functions
221// Promise Resolve Functions, steps 6-13
222function ResolvePromise(promise, resolution) {
223  if (resolution === promise) {
224    var exception = %make_type_error(kPromiseCyclic, resolution);
225    %PromiseReject(promise, exception, true);
226    PromiseSet(promise, kRejected, exception);
227    return;
228  }
229  if (IS_RECEIVER(resolution)) {
230    // 25.4.1.3.2 steps 8-12
231    try {
232      var then = resolution.then;
233    } catch (e) {
234      %PromiseReject(promise, e, true);
235      PromiseSet(promise, kRejected, e);
236      return;
237    }
238
239    // Resolution is a native promise and if it's already resolved or
240    // rejected, shortcircuit the resolution procedure by directly
241    // reusing the value from the promise.
242    if (IsPromise(resolution) && then === PromiseThen) {
243      var thenableState = GET_PRIVATE(resolution, promiseStateSymbol);
244      if (thenableState === kFulfilled) {
245        // This goes inside the if-else to save one symbol lookup in
246        // the slow path.
247        var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol);
248        %PromiseFulfill(promise, kFulfilled, thenableValue,
249                       promiseFulfillReactionsSymbol);
250        PromiseSet(promise, kFulfilled, thenableValue);
251        SET_PRIVATE(promise, promiseHasHandlerSymbol, true);
252        return;
253      } else if (thenableState === kRejected) {
254        var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol);
255        if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) {
256          // Promise has already been rejected, but had no handler.
257          // Revoke previously triggered reject event.
258          %PromiseRevokeReject(resolution);
259        }
260        // Don't cause a debug event as this case is forwarding a rejection
261        %PromiseReject(promise, thenableValue, false);
262        PromiseSet(promise, kRejected, thenableValue);
263        SET_PRIVATE(resolution, promiseHasHandlerSymbol, true);
264        return;
265      }
266    }
267
268    if (IS_CALLABLE(then)) {
269      if (DEBUG_IS_ACTIVE && IsPromise(resolution)) {
270          // Mark the dependency of the new promise on the resolution
271        SET_PRIVATE(resolution, promiseHandledBySymbol, promise);
272      }
273      %EnqueuePromiseResolveThenableJob(promise, resolution, then);
274      return;
275    }
276  }
277  %PromiseFulfill(promise, kFulfilled, resolution,
278                  promiseFulfillReactionsSymbol);
279  PromiseSet(promise, kFulfilled, resolution);
280}
281
282// Only used by async-await.js
283function RejectPromise(promise, reason, debugEvent) {
284  %PromiseReject(promise, reason, debugEvent);
285  PromiseSet(promise, kRejected, reason);
286}
287
288// Export to bindings
289function DoRejectPromise(promise, reason) {
290  %PromiseReject(promise, reason, true);
291  PromiseSet(promise, kRejected, reason);
292}
293
294// ES#sec-newpromisecapability
295// NewPromiseCapability ( C )
296function NewPromiseCapability(C, debugEvent) {
297  if (C === GlobalPromise) {
298    // Optimized case, avoid extra closure.
299    var promise = PromiseCreate();
300    // TODO(gsathya): Remove container for callbacks when this is
301    // moved to CPP/TF.
302    var callbacks = %create_resolving_functions(promise, debugEvent);
303    return {
304      promise: promise,
305      resolve: callbacks[kResolveCallback],
306      reject: callbacks[kRejectCallback]
307    };
308  }
309
310  var result = {promise: UNDEFINED, resolve: UNDEFINED, reject: UNDEFINED };
311  result.promise = new C((resolve, reject) => {
312    if (!IS_UNDEFINED(result.resolve) || !IS_UNDEFINED(result.reject))
313        throw %make_type_error(kPromiseExecutorAlreadyInvoked);
314    result.resolve = resolve;
315    result.reject = reject;
316  });
317
318  if (!IS_CALLABLE(result.resolve) || !IS_CALLABLE(result.reject))
319      throw %make_type_error(kPromiseNonCallable);
320
321  return result;
322}
323
324// ES#sec-promise.reject
325// Promise.reject ( x )
326function PromiseReject(r) {
327  if (!IS_RECEIVER(this)) {
328    throw %make_type_error(kCalledOnNonObject, PromiseResolve);
329  }
330  if (this === GlobalPromise) {
331    // Optimized case, avoid extra closure.
332    var promise = PromiseCreateAndSet(kRejected, r);
333    // Trigger debug events if the debugger is on, as Promise.reject is
334    // equivalent to throwing an exception directly.
335    %PromiseRejectEventFromStack(promise, r);
336    return promise;
337  } else {
338    var promiseCapability = NewPromiseCapability(this, true);
339    %_Call(promiseCapability.reject, UNDEFINED, r);
340    return promiseCapability.promise;
341  }
342}
343
344function PerformPromiseThen(promise, onResolve, onReject, resultCapability) {
345  if (!IS_CALLABLE(onResolve)) onResolve = PromiseIdResolveHandler;
346  if (!IS_CALLABLE(onReject)) onReject = PromiseIdRejectHandler;
347
348  var status = GET_PRIVATE(promise, promiseStateSymbol);
349  switch (status) {
350    case kPending:
351      PromiseAttachCallbacks(promise, resultCapability, onResolve, onReject);
352      break;
353    case kFulfilled:
354      %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol),
355                                 onResolve, resultCapability, kFulfilled);
356      break;
357    case kRejected:
358      if (!HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) {
359        // Promise has already been rejected, but had no handler.
360        // Revoke previously triggered reject event.
361        %PromiseRevokeReject(promise);
362      }
363      %EnqueuePromiseReactionJob(GET_PRIVATE(promise, promiseResultSymbol),
364                                 onReject, resultCapability, kRejected);
365      break;
366  }
367
368  // Mark this promise as having handler.
369  SET_PRIVATE(promise, promiseHasHandlerSymbol, true);
370  return resultCapability.promise;
371}
372
373// ES#sec-promise.prototype.then
374// Promise.prototype.then ( onFulfilled, onRejected )
375// Multi-unwrapped chaining with thenable coercion.
376function PromiseThen(onResolve, onReject) {
377  var status = GET_PRIVATE(this, promiseStateSymbol);
378  if (IS_UNDEFINED(status)) {
379    throw %make_type_error(kNotAPromise, this);
380  }
381
382  var constructor = SpeciesConstructor(this, GlobalPromise);
383  var resultCapability;
384
385  // The resultCapability.promise is only ever fulfilled internally,
386  // so we don't need the closures to protect against accidentally
387  // calling them multiple times.
388  if (constructor === GlobalPromise) {
389    // TODO(gsathya): Combine this into NewPromiseCapability.
390    resultCapability = {
391      promise: PromiseCreate(),
392      resolve: UNDEFINED,
393      reject: UNDEFINED
394    };
395  } else {
396    // Pass false for debugEvent so .then chaining does not trigger
397    // redundant ExceptionEvents.
398    resultCapability = NewPromiseCapability(constructor, false);
399  }
400  return PerformPromiseThen(this, onResolve, onReject, resultCapability);
401}
402
403// ES#sec-promise.prototype.catch
404// Promise.prototype.catch ( onRejected )
405function PromiseCatch(onReject) {
406  return this.then(UNDEFINED, onReject);
407}
408
409// Combinators.
410
411// ES#sec-promise.resolve
412// Promise.resolve ( x )
413function PromiseResolve(x) {
414  if (!IS_RECEIVER(this)) {
415    throw %make_type_error(kCalledOnNonObject, PromiseResolve);
416  }
417  if (IsPromise(x) && x.constructor === this) return x;
418
419  // Avoid creating resolving functions.
420  if (this === GlobalPromise) {
421    var promise = PromiseCreate();
422    ResolvePromise(promise, x);
423    return promise;
424  }
425
426  // debugEvent is not so meaningful here as it will be resolved
427  var promiseCapability = NewPromiseCapability(this, true);
428  %_Call(promiseCapability.resolve, UNDEFINED, x);
429  return promiseCapability.promise;
430}
431
432// ES#sec-promise.all
433// Promise.all ( iterable )
434function PromiseAll(iterable) {
435  if (!IS_RECEIVER(this)) {
436    throw %make_type_error(kCalledOnNonObject, "Promise.all");
437  }
438
439  // false debugEvent so that forwarding the rejection through all does not
440  // trigger redundant ExceptionEvents
441  var deferred = NewPromiseCapability(this, false);
442  var resolutions = new InternalArray();
443  var count;
444
445  // For catch prediction, don't treat the .then calls as handling it;
446  // instead, recurse outwards.
447  var instrumenting = DEBUG_IS_ACTIVE;
448  if (instrumenting) {
449    SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true);
450  }
451
452  function CreateResolveElementFunction(index, values, promiseCapability) {
453    var alreadyCalled = false;
454    return (x) => {
455      if (alreadyCalled === true) return;
456      alreadyCalled = true;
457      values[index] = x;
458      if (--count === 0) {
459        var valuesArray = [];
460        %MoveArrayContents(values, valuesArray);
461        %_Call(promiseCapability.resolve, UNDEFINED, valuesArray);
462      }
463    };
464  }
465
466  try {
467    var i = 0;
468    count = 1;
469    for (var value of iterable) {
470      var nextPromise = this.resolve(value);
471      ++count;
472      var throwawayPromise = nextPromise.then(
473          CreateResolveElementFunction(i, resolutions, deferred),
474          deferred.reject);
475      // For catch prediction, mark that rejections here are semantically
476      // handled by the combined Promise.
477      if (instrumenting && IsPromise(throwawayPromise)) {
478        SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise);
479      }
480      ++i;
481    }
482
483    // 6.d
484    if (--count === 0) {
485      var valuesArray = [];
486      %MoveArrayContents(resolutions, valuesArray);
487      %_Call(deferred.resolve, UNDEFINED, valuesArray);
488    }
489
490  } catch (e) {
491    %_Call(deferred.reject, UNDEFINED, e);
492  }
493  return deferred.promise;
494}
495
496// ES#sec-promise.race
497// Promise.race ( iterable )
498function PromiseRace(iterable) {
499  if (!IS_RECEIVER(this)) {
500    throw %make_type_error(kCalledOnNonObject, PromiseRace);
501  }
502
503  // false debugEvent so that forwarding the rejection through race does not
504  // trigger redundant ExceptionEvents
505  var deferred = NewPromiseCapability(this, false);
506
507  // For catch prediction, don't treat the .then calls as handling it;
508  // instead, recurse outwards.
509  var instrumenting = DEBUG_IS_ACTIVE;
510  if (instrumenting) {
511    SET_PRIVATE(deferred.reject, promiseForwardingHandlerSymbol, true);
512  }
513
514  try {
515    for (var value of iterable) {
516      var throwawayPromise = this.resolve(value).then(deferred.resolve,
517                                                      deferred.reject);
518      // For catch prediction, mark that rejections here are semantically
519      // handled by the combined Promise.
520      if (instrumenting && IsPromise(throwawayPromise)) {
521        SET_PRIVATE(throwawayPromise, promiseHandledBySymbol, deferred.promise);
522      }
523    }
524  } catch (e) {
525    %_Call(deferred.reject, UNDEFINED, e);
526  }
527  return deferred.promise;
528}
529
530
531// Utility for debugger
532
533function PromiseHasUserDefinedRejectHandlerCheck(handler, deferred) {
534  // Recurse to the forwarding Promise, if any. This may be due to
535  //  - await reaction forwarding to the throwaway Promise, which has
536  //    a dependency edge to the outer Promise.
537  //  - PromiseIdResolveHandler forwarding to the output of .then
538  //  - Promise.all/Promise.race forwarding to a throwaway Promise, which
539  //    has a dependency edge to the generated outer Promise.
540  if (GET_PRIVATE(handler, promiseForwardingHandlerSymbol)) {
541    return PromiseHasUserDefinedRejectHandlerRecursive(deferred.promise);
542  }
543
544  // Otherwise, this is a real reject handler for the Promise
545  return true;
546}
547
548function PromiseHasUserDefinedRejectHandlerRecursive(promise) {
549  // If this promise was marked as being handled by a catch block
550  // in an async function, then it has a user-defined reject handler.
551  if (GET_PRIVATE(promise, promiseHandledHintSymbol)) return true;
552
553  // If this Promise is subsumed by another Promise (a Promise resolved
554  // with another Promise, or an intermediate, hidden, throwaway Promise
555  // within async/await), then recurse on the outer Promise.
556  // In this case, the dependency is one possible way that the Promise
557  // could be resolved, so it does not subsume the other following cases.
558  var outerPromise = GET_PRIVATE(promise, promiseHandledBySymbol);
559  if (outerPromise &&
560      PromiseHasUserDefinedRejectHandlerRecursive(outerPromise)) {
561    return true;
562  }
563
564  var queue = GET_PRIVATE(promise, promiseRejectReactionsSymbol);
565  var deferred = GET_PRIVATE(promise, promiseDeferredReactionSymbol);
566
567  if (IS_UNDEFINED(queue)) return false;
568
569  if (!IS_ARRAY(queue)) {
570    return PromiseHasUserDefinedRejectHandlerCheck(queue, deferred);
571  }
572
573  for (var i = 0; i < queue.length; i += 2) {
574    if (PromiseHasUserDefinedRejectHandlerCheck(queue[i], queue[i + 1])) {
575      return true;
576    }
577  }
578  return false;
579}
580
581// Return whether the promise will be handled by a user-defined reject
582// handler somewhere down the promise chain. For this, we do a depth-first
583// search for a reject handler that's not the default PromiseIdRejectHandler.
584// This function also traverses dependencies of one Promise on another,
585// set up through async/await and Promises resolved with Promises.
586function PromiseHasUserDefinedRejectHandler() {
587  return PromiseHasUserDefinedRejectHandlerRecursive(this);
588};
589
590function MarkPromiseAsHandled(promise) {
591  SET_PRIVATE(promise, promiseHasHandlerSymbol, true);
592}
593
594
595function PromiseSpecies() {
596  return this;
597}
598
599// -------------------------------------------------------------------
600// Install exported functions.
601
602%AddNamedProperty(global, 'Promise', GlobalPromise, DONT_ENUM);
603%AddNamedProperty(GlobalPromise.prototype, toStringTagSymbol, "Promise",
604                  DONT_ENUM | READ_ONLY);
605
606utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
607  "reject", PromiseReject,
608  "all", PromiseAll,
609  "race", PromiseRace,
610  "resolve", PromiseResolve
611]);
612
613utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies);
614
615utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
616  "then", PromiseThen,
617  "catch", PromiseCatch
618]);
619
620%InstallToContext([
621  "promise_catch", PromiseCatch,
622  "promise_create", PromiseCreate,
623  "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler,
624  "promise_reject", DoRejectPromise,
625  // TODO(gsathya): Remove this once we update the promise builtin.
626  "promise_internal_reject", RejectPromise,
627  "promise_resolve", ResolvePromise,
628  "promise_then", PromiseThen,
629  "promise_handle", PromiseHandle,
630  "promise_debug_get_info", PromiseDebugGetInfo
631]);
632
633// This allows extras to create promises quickly without building extra
634// resolve/reject closures, and allows them to later resolve and reject any
635// promise without having to hold on to those closures forever.
636utils.InstallFunctions(extrasUtils, 0, [
637  "createPromise", PromiseCreate,
638  "resolvePromise", ResolvePromise,
639  "rejectPromise", DoRejectPromise,
640  "markPromiseAsHandled", MarkPromiseAsHandled
641]);
642
643utils.Export(function(to) {
644  to.IsPromise = IsPromise;
645  to.PromiseCreate = PromiseCreate;
646  to.PromiseThen = PromiseThen;
647
648  to.GlobalPromise = GlobalPromise;
649  to.NewPromiseCapability = NewPromiseCapability;
650  to.PerformPromiseThen = PerformPromiseThen;
651  to.ResolvePromise = ResolvePromise;
652  to.RejectPromise = RejectPromise;
653});
654
655})
656