Bug 1474348 - Part 1: Add accessors for Promise fixed slots and combine default resolving functions flags. r=arai

This commit is contained in:
André Bargull 2018-07-09 09:47:27 -07:00
parent 868533e1cb
commit 9fdd7e6831
3 changed files with 32 additions and 25 deletions

View File

@ -543,14 +543,14 @@ const Class PromiseReactionRecord::class_ = {
static void
AddPromiseFlags(PromiseObject& promise, int32_t flag)
{
int32_t flags = promise.getFixedSlot(PromiseSlot_Flags).toInt32();
int32_t flags = promise.flags();
promise.setFixedSlot(PromiseSlot_Flags, Int32Value(flags | flag));
}
static bool
PromiseHasAnyFlag(PromiseObject& promise, int32_t flag)
{
return promise.getFixedSlot(PromiseSlot_Flags).toInt32() & flag;
return promise.flags() & flag;
}
static bool ResolvePromiseFunction(JSContext* cx, unsigned argc, Value* vp);
@ -926,7 +926,7 @@ ResolvePromise(JSContext* cx, Handle<PromiseObject*> promise, HandleValue valueO
// instead of getting the right list of reactions, we determine the
// resolution type to retrieve the right information from the
// reaction records.
RootedValue reactionsVal(cx, promise->getFixedSlot(PromiseSlot_ReactionsOrResult));
RootedValue reactionsVal(cx, promise->reactions());
// Steps 3-5.
// The same slot is used for the reactions list and the result, so setting
@ -934,7 +934,7 @@ ResolvePromise(JSContext* cx, Handle<PromiseObject*> promise, HandleValue valueO
promise->setFixedSlot(PromiseSlot_ReactionsOrResult, valueOrReason);
// Step 6.
int32_t flags = promise->getFixedSlot(PromiseSlot_Flags).toInt32();
int32_t flags = promise->flags();
flags |= PROMISE_FLAG_RESOLVED;
if (state == JS::PromiseState::Fulfilled)
flags |= PROMISE_FLAG_FULFILLED;
@ -998,8 +998,7 @@ CreatePromiseObjectWithoutResolutionFunctions(JSContext* cx)
if (!promise)
return nullptr;
AddPromiseFlags(*promise, PROMISE_FLAG_DEFAULT_RESOLVE_FUNCTION |
PROMISE_FLAG_DEFAULT_REJECT_FUNCTION);
AddPromiseFlags(*promise, PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS);
return promise;
}
@ -2195,14 +2194,12 @@ RunResolutionFunction(JSContext *cx, HandleObject resolutionFun, HandleValue res
if (promise->state() != JS::PromiseState::Pending)
return true;
if (mode == ResolveMode) {
if (!PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVE_FUNCTION))
return true;
return ResolvePromiseInternal(cx, promise, result);
}
if (!PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_REJECT_FUNCTION))
if (!PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS))
return true;
if (mode == ResolveMode)
return ResolvePromiseInternal(cx, promise, result);
return RejectMaybeWrappedPromise(cx, promiseObj, result);
}
@ -3555,7 +3552,7 @@ PerformPromiseThenWithReaction(JSContext* cx, Handle<PromiseObject*> promise,
Handle<PromiseReactionRecord*> reaction)
{
JS::PromiseState state = promise->state();
int32_t flags = promise->getFixedSlot(PromiseSlot_Flags).toInt32();
int32_t flags = promise->flags();
if (state == JS::PromiseState::Pending) {
// Steps 5,6 (reordered).
// Instead of creating separate reaction records for fulfillment and
@ -3571,7 +3568,7 @@ PerformPromiseThenWithReaction(JSContext* cx, Handle<PromiseObject*> promise,
MOZ_ASSERT_IF(state != JS::PromiseState::Fulfilled, state == JS::PromiseState::Rejected);
// Step 8.a. / 9.b.
RootedValue valueOrReason(cx, promise->getFixedSlot(PromiseSlot_ReactionsOrResult));
RootedValue valueOrReason(cx, promise->valueOrReason());
// We might be operating on a promise from another compartment. In
// that case, we need to wrap the result/reason value before using it.
@ -3728,7 +3725,7 @@ AddPromiseReaction(JSContext* cx, Handle<PromiseObject*> promise,
}
// 25.4.5.3.1 steps 7.a,b.
RootedValue reactionsVal(cx, promise->getFixedSlot(PromiseSlot_ReactionsOrResult));
RootedValue reactionsVal(cx, promise->reactions());
RootedNativeObject reactions(cx);
if (reactionsVal.isUndefined()) {
@ -3825,7 +3822,7 @@ PromiseObject::dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> v
if (state() != JS::PromiseState::Pending)
return true;
RootedValue reactionsVal(cx, getFixedSlot(PromiseSlot_ReactionsOrResult));
RootedValue reactionsVal(cx, reactions());
// If no reactions are pending, we don't have list and are done.
if (reactionsVal.isNullOrUndefined())
@ -3875,7 +3872,7 @@ PromiseObject::resolve(JSContext* cx, Handle<PromiseObject*> promise, HandleValu
if (promise->state() != JS::PromiseState::Pending)
return true;
if (PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVE_FUNCTION))
if (PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS))
return ResolvePromiseInternal(cx, promise, resolutionValue);
RootedObject resolveFun(cx, GetResolveFunctionFromPromise(promise));
@ -3904,7 +3901,7 @@ PromiseObject::reject(JSContext* cx, Handle<PromiseObject*> promise, HandleValue
if (promise->state() != JS::PromiseState::Pending)
return true;
if (PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_REJECT_FUNCTION))
if (PromiseHasAnyFlag(*promise, PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS))
return ResolvePromise(cx, promise, rejectionValue, JS::PromiseState::Rejected);
RootedValue funVal(cx, promise->getFixedSlot(PromiseSlot_RejectFunction));

View File

@ -26,9 +26,8 @@ enum PromiseSlots {
#define PROMISE_FLAG_RESOLVED 0x1
#define PROMISE_FLAG_FULFILLED 0x2
#define PROMISE_FLAG_HANDLED 0x4
#define PROMISE_FLAG_DEFAULT_RESOLVE_FUNCTION 0x08
#define PROMISE_FLAG_DEFAULT_REJECT_FUNCTION 0x10
#define PROMISE_FLAG_ASYNC 0x20
#define PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS 0x08
#define PROMISE_FLAG_ASYNC 0x10
class AutoSetNewObjectMetadata;
@ -46,8 +45,11 @@ class PromiseObject : public NativeObject
static JSObject* unforgeableResolve(JSContext* cx, HandleValue value);
static JSObject* unforgeableReject(JSContext* cx, HandleValue value);
int32_t flags() {
return getFixedSlot(PromiseSlot_Flags).toInt32();
}
JS::PromiseState state() {
int32_t flags = getFixedSlot(PromiseSlot_Flags).toInt32();
int32_t flags = this->flags();
if (!(flags & PROMISE_FLAG_RESOLVED)) {
MOZ_ASSERT(!(flags & PROMISE_FLAG_FULFILLED));
return JS::PromiseState::Pending;
@ -56,6 +58,10 @@ class PromiseObject : public NativeObject
return JS::PromiseState::Fulfilled;
return JS::PromiseState::Rejected;
}
Value reactions() {
MOZ_ASSERT(state() == JS::PromiseState::Pending);
return getFixedSlot(PromiseSlot_ReactionsOrResult);
}
Value value() {
MOZ_ASSERT(state() == JS::PromiseState::Fulfilled);
return getFixedSlot(PromiseSlot_ReactionsOrResult);
@ -64,6 +70,10 @@ class PromiseObject : public NativeObject
MOZ_ASSERT(state() == JS::PromiseState::Rejected);
return getFixedSlot(PromiseSlot_ReactionsOrResult);
}
Value valueOrReason() {
MOZ_ASSERT(state() != JS::PromiseState::Pending);
return getFixedSlot(PromiseSlot_ReactionsOrResult);
}
static MOZ_MUST_USE bool resolve(JSContext* cx, Handle<PromiseObject*> promise,
HandleValue resolutionValue);
@ -85,7 +95,7 @@ class PromiseObject : public NativeObject
uint64_t getID();
bool isUnhandled() {
MOZ_ASSERT(state() == JS::PromiseState::Rejected);
return !(getFixedSlot(PromiseSlot_Flags).toInt32() & PROMISE_FLAG_HANDLED);
return !(flags() & PROMISE_FLAG_HANDLED);
}
};

View File

@ -2099,7 +2099,7 @@ SettlePromiseNow(JSContext* cx, unsigned argc, Value* vp)
return false;
}
int32_t flags = promise->getFixedSlot(PromiseSlot_Flags).toInt32();
int32_t flags = promise->flags();
promise->setFixedSlot(PromiseSlot_Flags,
Int32Value(flags | PROMISE_FLAG_RESOLVED | PROMISE_FLAG_FULFILLED));
promise->setFixedSlot(PromiseSlot_ReactionsOrResult, UndefinedValue());