Bug 1328820 - Add documentation comment to Promise.h, AsyncFunction.h, and AsyncIteration.h r=anba DONTBUILD comment-only

This commit is contained in:
Tooru Fujisawa 2018-08-29 12:15:32 +09:00
Родитель 544b61c613
Коммит 1e093ed64e
3 изменённых файлов: 157 добавлений и 11 удалений

Просмотреть файл

@ -15,18 +15,53 @@
namespace js { namespace js {
enum PromiseSlots { enum PromiseSlots {
// Int32 value with PROMISE_FLAG_* flags below.
PromiseSlot_Flags = 0, PromiseSlot_Flags = 0,
// * if this promise is pending, reaction objects
// * undefined if there's no reaction
// * maybe-wrapped PromiseReactionRecord if there's only one reacion
// * dense array if there are two or more more reactions
// * if this promise is fulfilled, the resolution value
// * if this promise is rejected, the reason for the rejection
PromiseSlot_ReactionsOrResult, PromiseSlot_ReactionsOrResult,
// * if this promise is pending, resolve/reject functions.
// This slot holds only the reject function. The resolve function is
// reachable from the reject function's extended slot.
// * if this promise is either fulfilled or rejected, undefined
// * (special case) if this promise is the return value of an async function
// invocation, the generator object for the function's internal generator
PromiseSlot_RejectFunction, PromiseSlot_RejectFunction,
PromiseSlot_AwaitGenerator = PromiseSlot_RejectFunction, PromiseSlot_AwaitGenerator = PromiseSlot_RejectFunction,
// Promise object's debug info, which is created on demand.
// * if this promise has no debug info, undefined
// * if this promise contains only its process-unique ID, the ID's number
// value
// * otherwise a PromiseDebugInfo object
PromiseSlot_DebugInfo, PromiseSlot_DebugInfo,
PromiseSlots, PromiseSlots,
}; };
// This promise is either fulfilled or rejected.
// If this flag is not set, this promise is pending.
#define PROMISE_FLAG_RESOLVED 0x1 #define PROMISE_FLAG_RESOLVED 0x1
// If this flag and PROMISE_FLAG_RESOLVED are set, this promise is fulfilled.
// If only PROMISE_FLAG_RESOLVED is set, this promise is rejected.
#define PROMISE_FLAG_FULFILLED 0x2 #define PROMISE_FLAG_FULFILLED 0x2
// Indicates the promise has ever had a fulfillment or rejection handler;
// used in unhandled rejection tracking.
#define PROMISE_FLAG_HANDLED 0x4 #define PROMISE_FLAG_HANDLED 0x4
// This promise uses the default resolving functions.
// The PromiseSlot_RejectFunction slot is not used.
#define PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS 0x08 #define PROMISE_FLAG_DEFAULT_RESOLVING_FUNCTIONS 0x08
// This promise is the return value of an async function invocation.
#define PROMISE_FLAG_ASYNC 0x10 #define PROMISE_FLAG_ASYNC 0x10
class AutoSetNewObjectMetadata; class AutoSetNewObjectMetadata;
@ -92,7 +127,10 @@ class PromiseObject : public NativeObject
return resolutionTime() - allocationTime(); return resolutionTime() - allocationTime();
} }
MOZ_MUST_USE bool dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> values); MOZ_MUST_USE bool dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> values);
// Return the process-unique ID of this promise. Only used by the debugger.
uint64_t getID(); uint64_t getID();
bool isUnhandled() { bool isUnhandled() {
MOZ_ASSERT(state() == JS::PromiseState::Rejected); MOZ_ASSERT(state() == JS::PromiseState::Rejected);
return !(flags() & PROMISE_FLAG_HANDLED); return !(flags() & PROMISE_FLAG_HANDLED);
@ -113,9 +151,18 @@ class PromiseObject : public NativeObject
MOZ_MUST_USE JSObject* MOZ_MUST_USE JSObject*
GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises); GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises);
// Whether to create a promise as the return value of Promise#{then,catch}.
// If the return value is known to be unused, and if the operation is known
// to be unobservable, we can skip creating the promise.
enum class CreateDependentPromise { enum class CreateDependentPromise {
// The return value is not known to be unused.
Always, Always,
// The return value is known to be unused.
SkipIfCtorUnobservable, SkipIfCtorUnobservable,
// The return value is known to be unused, and the operation is known
// to be unobservable.
Never Never
}; };
@ -144,9 +191,17 @@ MOZ_MUST_USE JSObject*
PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value); PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value);
/**
* Create the promise object which will be used as the return value of an async
* function.
*/
MOZ_MUST_USE PromiseObject* MOZ_MUST_USE PromiseObject*
CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal); CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal);
/**
* Returns true if the given object is a promise created by
* CreatePromiseObjectForAsync function.
*/
MOZ_MUST_USE bool MOZ_MUST_USE bool
IsPromiseForAsync(JSObject* promise); IsPromiseForAsync(JSObject* promise);

Просмотреть файл

@ -12,21 +12,44 @@
namespace js { namespace js {
// An async function is implemented using two function objects, which are
// referred to as the "unwrapped" and the "wrapped" async function object.
// The unwrapped function is a generator function compiled from the async
// function's script. |await| expressions within the async function are
// compiled like |yield| expression for the generator function with dedicated
// opcode,. The unwrapped function is never exposed to user script.
// The wrapped function is a native function which wraps the generator function,
// hence its name, and is the publicly exposed object of the async function.
//
// The unwrapped async function is created while compiling the async function,
// and the wrapped async function is created while executing the async function
// declaration or expression.
// Returns a wrapped async function from an unwrapped async function.
JSFunction* JSFunction*
GetWrappedAsyncFunction(JSFunction* unwrapped); GetWrappedAsyncFunction(JSFunction* unwrapped);
// Returns an unwrapped async function from a wrapped async function.
JSFunction* JSFunction*
GetUnwrappedAsyncFunction(JSFunction* wrapped); GetUnwrappedAsyncFunction(JSFunction* wrapped);
// Returns true if the given function is a wrapped async function.
bool bool
IsWrappedAsyncFunction(JSFunction* fun); IsWrappedAsyncFunction(JSFunction* fun);
// Create a wrapped async function from unwrapped async function with given
// prototype object.
JSObject* JSObject*
WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto); WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto);
// Create a wrapped async function from unwrapped async function with default
// prototype object.
JSObject* JSObject*
WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped); WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped);
// Resume the async function when the `await` operand resolves.
// Split into two functions depending on whether the awaited value was
// fulfilled or rejected.
MOZ_MUST_USE bool MOZ_MUST_USE bool
AsyncFunctionAwaitedFulfilled(JSContext* cx, Handle<PromiseObject*> resultPromise, AsyncFunctionAwaitedFulfilled(JSContext* cx, Handle<PromiseObject*> resultPromise,
HandleValue generatorVal, HandleValue value); HandleValue generatorVal, HandleValue value);

Просмотреть файл

@ -14,33 +14,55 @@
namespace js { namespace js {
// Async generator consists of 2 functions, |wrapped| and |unwrapped|. // An async generator is implemented using two function objects, which are
// |unwrapped| is a generator function compiled from async generator script, // referred to as the "unwrapped" and the "wrapped" async generator object.
// |await| behaves just like |yield| there. |unwrapped| isn't exposed to user // The unwrapped function is a generator function compiled from the async
// script. // generator's script. |await| expressions within the async generator are
// |wrapped| is a native function that is the value of async generator. // compiled like |yield| expression for the generator function with dedicated
// opcode. The unwrapped function is never exposed to user script.
// The wrapped function is a native function which wraps the generator function,
// hence its name, and is the publicly exposed object of the async generator.
//
// The unwrapped async generator is created while compiling the async generator,
// and the wrapped async generator is created while executing the async
// generator declaration or expression.
// Create a wrapped async generator from an unwrapped async generator with given
// prototype object.
JSObject* JSObject*
WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto); WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto);
// Create a wrapped async generator from an unwrapped async generator
// with default prototype object.
JSObject* JSObject*
WrapAsyncGenerator(JSContext* cx, HandleFunction unwrapped); WrapAsyncGenerator(JSContext* cx, HandleFunction unwrapped);
// Returns true if the given function is a wrapped async generator.
bool bool
IsWrappedAsyncGenerator(JSFunction* fun); IsWrappedAsyncGenerator(JSFunction* fun);
// Returns a wrapped async generator from an unwrapped async generator.
JSFunction* JSFunction*
GetWrappedAsyncGenerator(JSFunction* unwrapped); GetWrappedAsyncGenerator(JSFunction* unwrapped);
// Return an unwrapped async generator from a wrapped async generator.
JSFunction* JSFunction*
GetUnwrappedAsyncGenerator(JSFunction* wrapped); GetUnwrappedAsyncGenerator(JSFunction* wrapped);
// Resume the async generator when the `await` operand fulfills to `value`.
MOZ_MUST_USE bool MOZ_MUST_USE bool
AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue value); HandleValue value);
// Resume the async generator when the `await` operand rejects with `reason`.
MOZ_MUST_USE bool MOZ_MUST_USE bool
AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
HandleValue reason); HandleValue reason);
// Resume the async generator after awaiting on the value passed to
// AsyncGenerator#return, when the async generator was still executing.
// Split into two functions depending on whether the awaited value was
// fulfilled or rejected.
MOZ_MUST_USE bool MOZ_MUST_USE bool
AsyncGeneratorYieldReturnAwaitedFulfilled(JSContext* cx, AsyncGeneratorYieldReturnAwaitedFulfilled(JSContext* cx,
Handle<AsyncGeneratorObject*> asyncGenObj, Handle<AsyncGeneratorObject*> asyncGenObj,
@ -52,13 +74,27 @@ AsyncGeneratorYieldReturnAwaitedRejected(JSContext* cx,
class AsyncGeneratorObject; class AsyncGeneratorObject;
// AsyncGeneratorRequest record in the spec.
// Stores the info from AsyncGenerator#{next,return,throw}.
//
// This object is reused across multiple requests as an optimization, and
// stored in the Slot_CachedRequest slot.
class AsyncGeneratorRequest : public NativeObject class AsyncGeneratorRequest : public NativeObject
{ {
private: private:
enum AsyncGeneratorRequestSlots { enum AsyncGeneratorRequestSlots {
// Int32 value with CompletionKind.
// Normal: next
// Return: return
// Throw: throw
Slot_CompletionKind = 0, Slot_CompletionKind = 0,
// The value passed to AsyncGenerator#{next,return,throw}.
Slot_CompletionValue, Slot_CompletionValue,
// The promise returned by AsyncGenerator#{next,return,throw}.
Slot_Promise, Slot_Promise,
Slots, Slots,
}; };
@ -68,6 +104,7 @@ class AsyncGeneratorRequest : public NativeObject
setFixedSlot(Slot_Promise, ObjectValue(*promise)); setFixedSlot(Slot_Promise, ObjectValue(*promise));
} }
// Clear the request data for reuse.
void clearData() { void clearData() {
setFixedSlot(Slot_CompletionValue, NullValue()); setFixedSlot(Slot_CompletionValue, NullValue());
setFixedSlot(Slot_Promise, NullValue()); setFixedSlot(Slot_Promise, NullValue());
@ -97,23 +134,50 @@ class AsyncGeneratorObject : public NativeObject
{ {
private: private:
enum AsyncGeneratorObjectSlots { enum AsyncGeneratorObjectSlots {
// Int32 value containing one of the |State| fields from below.
Slot_State = 0, Slot_State = 0,
// Generator object for the unwrapped async generator.
Slot_Generator, Slot_Generator,
// * null value if this async generator has no requests
// * AsyncGeneratorRequest if this async generator has only one request
// * list object if this async generator has 2 or more requests
Slot_QueueOrRequest, Slot_QueueOrRequest,
// Cached AsyncGeneratorRequest for later use.
// undefined if there's no cache.
Slot_CachedRequest, Slot_CachedRequest,
Slots Slots
}; };
enum State { enum State {
// "suspendedStart" in the spec.
// Suspended after invocation.
State_SuspendedStart, State_SuspendedStart,
// "suspendedYield" in the spec
// Suspended with `yield` expression.
State_SuspendedYield, State_SuspendedYield,
// "executing" in the spec.
// Resumed from initial suspend or yield, and either running the script
// or awaiting for `await` expression.
State_Executing, State_Executing,
// State_AwaitingYieldReturn corresponds to the case that
// AsyncGenerator#return is called while State_Executing, // Part of "executing" in the spec.
// just like the case that AsyncGenerator#return is called // Awaiting on the value passed by AsyncGenerator#return which is called
// while State_Completed. // while executing.
State_AwaitingYieldReturn, State_AwaitingYieldReturn,
// Part of "executing" in the spec.
// Awaiting on the value passed by AsyncGenerator#return which is called
// after completed.
State_AwaitingReturn, State_AwaitingReturn,
// "completed" in the spec.
// The generator is completed.
State_Completed State_Completed
}; };
@ -129,8 +193,8 @@ class AsyncGeneratorObject : public NativeObject
} }
// Queue is implemented in 2 ways. If only one request is queued ever, // Queue is implemented in 2 ways. If only one request is queued ever,
// request is stored directly to the slot. Once 2 requests are queued, an // request is stored directly to the slot. Once 2 requests are queued, a
// array is created and requests are pushed into it, and the array is // list is created and requests are appended into it, and the list is
// stored to the slot. // stored to the slot.
bool isSingleQueue() const { bool isSingleQueue() const {
@ -267,8 +331,12 @@ class AsyncFromSyncIteratorObject : public NativeObject
{ {
private: private:
enum AsyncFromSyncIteratorObjectSlots { enum AsyncFromSyncIteratorObjectSlots {
// Object that implements the sync iterator protocol.
Slot_Iterator = 0, Slot_Iterator = 0,
// The `next` property of the iterator object.
Slot_NextMethod = 1, Slot_NextMethod = 1,
Slots Slots
}; };