docs: function resolvePromise(promise, state, value) {
          var onceWrapper = once();
          if (promise === value) {
              throw new TypeError(TYPE_ERROR);
          }
          if (promise[symbolState] === UNRESOLVED) {
              // should only get value.then once based on promise spec.
              var then = null;
              try {
                  if (typeof value === 'object' || typeof value === 'function') {
                      then = value && value.then;
                  }
              }
              catch (err) {
                  onceWrapper(function () {
                      resolvePromise(promise, false, err);
                  })();
                  return promise;
              }
              // if (value instanceof ZoneAwarePromise) {
              if (state !== REJECTED && value instanceof ZoneAwarePromise &&
                  value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) &&
                  value[symbolState] !== UNRESOLVED) {
                  clearRejectedNoCatch(value);
                  resolvePromise(promise, value[symbolState], value[symbolValue]);
              }
              else if (state !== REJECTED && typeof then === 'function') {
                  try {
                      then.call(value, onceWrapper(makeResolver(promise, state)), onceWrapper(makeResolver(promise, false)));
                  }
                  catch (err) {
                      onceWrapper(function () {
                          resolvePromise(promise, false, err);
                      })();
                  }
              }
              else {
                  promise[symbolState] = state;
                  var queue = promise[symbolValue];
                  promise[symbolValue] = value;
                  if (promise[symbolFinally] === symbolFinally) {
                      // the promise is generated by Promise.prototype.finally
                      if (state === RESOLVED) {
                          // the state is resolved, should ignore the value
                          // and use parent promise value
                          promise[symbolState] = promise[symbolParentPromiseState];
                          promise[symbolValue] = promise[symbolParentPromiseValue];
                      }
                  }
                  // record task information in value when error occurs, so we can
                  // do some additional work such as render longStackTrace
                  if (state === REJECTED && value instanceof Error) {
                      // check if longStackTraceZone is here
                      var trace = Zone.currentTask && Zone.currentTask.data &&
                          Zone.currentTask.data[creationTrace];
                      if (trace) {
                          // only keep the long stack trace into error when in longStackTraceZone
                          ObjectDefineProperty(value, CURRENT_TASK_TRACE_SYMBOL, { configurable: true, enumerable: false, writable: true, value: trace });
                      }
                  }
                  for (var i = 0; i < queue.length;) {
                      scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);
                  }
                  if (queue.length == 0 && state == REJECTED) {
                      promise[symbolState] = REJECTED_NO_CATCH;
                      try {
                          // try to print more readable error log
                          throw new Error('Uncaught (in promise): ' + readableObjectToString(value) +
                              (value && value.stack ? '\n' + value.stack : ''));
                      }
                      catch (err) {
                          var error_1 = err;
                          error_1.rejection = value;
                          error_1.promise = promise;
                          error_1.zone = Zone.current;
                          error_1.task = Zone.currentTask;
                          _uncaughtPromiseErrors.push(error_1);
                          api.scheduleMicroTask(); // to make sure that it is running
                      }
                  }
              }
          }
          // Resolving an already resolved promise is a noop.
          return promise;
      }