зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 0705d5b86ad7 (bug 1331092)
This commit is contained in:
Родитель
3ed58db45c
Коммит
ee7e020090
|
@ -852,7 +852,7 @@ struct JSClass {
|
|||
// application.
|
||||
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT \
|
||||
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 45)
|
||||
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 41)
|
||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||
#define JSCLASS_GLOBAL_FLAGS \
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function AsyncIteratorIdentity() {
|
||||
return this;
|
||||
}
|
|
@ -12,12 +12,10 @@
|
|||
|
||||
#include "jscntxt.h"
|
||||
#include "jsexn.h"
|
||||
#include "jsiter.h"
|
||||
|
||||
#include "gc/Heap.h"
|
||||
#include "js/Debug.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
@ -38,16 +36,6 @@ enum PromiseHandler {
|
|||
PromiseHandlerThrower,
|
||||
PromiseHandlerAsyncFunctionAwaitFulfilled,
|
||||
PromiseHandlerAsyncFunctionAwaitRejected,
|
||||
PromiseHandlerAsyncGeneratorAwaitFulfilled,
|
||||
PromiseHandlerAsyncGeneratorAwaitRejected,
|
||||
|
||||
// Async Iteration proposal 6.1.1.2.1.
|
||||
// Async iterator handlers take the resolved value and create new iterator
|
||||
// objects. To do so it needs to forward whether the iterator is done. In
|
||||
// spec, this is achieved via the [[Done]] internal slot. We enumerate both
|
||||
// true and false cases here.
|
||||
PromiseHandlerAsyncIteratorValueUnwrapDone,
|
||||
PromiseHandlerAsyncIteratorValueUnwrapNotDone,
|
||||
};
|
||||
|
||||
enum ResolutionMode {
|
||||
|
@ -190,7 +178,6 @@ enum ReactionRecordSlots {
|
|||
ReactionRecordSlot_IncumbentGlobalObject,
|
||||
ReactionRecordSlot_Flags,
|
||||
ReactionRecordSlot_HandlerArg,
|
||||
ReactionRecordSlot_Generator,
|
||||
ReactionRecordSlots,
|
||||
};
|
||||
|
||||
|
@ -198,7 +185,6 @@ enum ReactionRecordSlots {
|
|||
#define REACTION_FLAG_FULFILLED 0x2
|
||||
#define REACTION_FLAG_IGNORE_DEFAULT_RESOLUTION 0x4
|
||||
#define REACTION_FLAG_ASYNC_FUNCTION_AWAIT 0x8
|
||||
#define REACTION_FLAG_ASYNC_GENERATOR_AWAIT 0x10
|
||||
|
||||
// ES2016, 25.4.1.2.
|
||||
class PromiseReactionRecord : public NativeObject
|
||||
|
@ -234,22 +220,6 @@ class PromiseReactionRecord : public NativeObject
|
|||
int32_t flags = this->flags();
|
||||
return flags & REACTION_FLAG_ASYNC_FUNCTION_AWAIT;
|
||||
}
|
||||
void setIsAsyncGeneratorAwait(Handle<AsyncGeneratorObject*> asyncGenObj) {
|
||||
int32_t flags = this->flags();
|
||||
flags |= REACTION_FLAG_ASYNC_GENERATOR_AWAIT;
|
||||
setFixedSlot(ReactionRecordSlot_Flags, Int32Value(flags));
|
||||
|
||||
setFixedSlot(ReactionRecordSlot_Generator, ObjectValue(*asyncGenObj));
|
||||
}
|
||||
bool isAsyncGeneratorAwait() {
|
||||
int32_t flags = this->flags();
|
||||
return flags & REACTION_FLAG_ASYNC_GENERATOR_AWAIT;
|
||||
}
|
||||
AsyncGeneratorObject* asyncGenerator() {
|
||||
MOZ_ASSERT(isAsyncGeneratorAwait());
|
||||
return &getFixedSlot(ReactionRecordSlot_Generator).toObject()
|
||||
.as<AsyncGeneratorObject>();
|
||||
}
|
||||
Value handler() {
|
||||
MOZ_ASSERT(targetState() != JS::PromiseState::Pending);
|
||||
uint32_t slot = targetState() == JS::PromiseState::Fulfilled
|
||||
|
@ -874,34 +844,6 @@ AsyncFunctionAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord
|
|||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
AsyncGeneratorAwaitPromiseReactionJob(JSContext* cx, Handle<PromiseReactionRecord*> reaction,
|
||||
MutableHandleValue rval)
|
||||
{
|
||||
MOZ_ASSERT(reaction->isAsyncGeneratorAwait());
|
||||
|
||||
RootedValue handlerVal(cx, reaction->handler());
|
||||
RootedValue argument(cx, reaction->handlerArg());
|
||||
Rooted<AsyncGeneratorObject*> asyncGenObj(cx, reaction->asyncGenerator());
|
||||
|
||||
int32_t handlerNum = int32_t(handlerVal.toNumber());
|
||||
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled ||
|
||||
handlerNum == PromiseHandlerAsyncGeneratorAwaitRejected);
|
||||
|
||||
// Await's handlers don't return a value, nor throw exception.
|
||||
// They fail only on OOM.
|
||||
if (handlerNum == PromiseHandlerAsyncGeneratorAwaitFulfilled) {
|
||||
if (!AsyncGeneratorAwaitedFulfilled(cx, asyncGenObj, argument))
|
||||
return false;
|
||||
} else {
|
||||
if (!AsyncGeneratorAwaitedRejected(cx, asyncGenObj, argument))
|
||||
return false;
|
||||
}
|
||||
|
||||
rval.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ES2016, 25.4.2.1.
|
||||
/**
|
||||
* Callback triggering the fulfill/reject reaction for a resolved Promise,
|
||||
|
@ -940,8 +882,6 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
|
|||
Rooted<PromiseReactionRecord*> reaction(cx, &reactionObj->as<PromiseReactionRecord>());
|
||||
if (reaction->isAsyncFunctionAwait())
|
||||
return AsyncFunctionAwaitPromiseReactionJob(cx, reaction, args.rval());
|
||||
if (reaction->isAsyncGeneratorAwait())
|
||||
return AsyncGeneratorAwaitPromiseReactionJob(cx, reaction, args.rval());
|
||||
|
||||
// Step 3.
|
||||
RootedValue handlerVal(cx, reaction->handler());
|
||||
|
@ -958,21 +898,11 @@ PromiseReactionJob(JSContext* cx, unsigned argc, Value* vp)
|
|||
// Step 4.
|
||||
if (handlerNum == PromiseHandlerIdentity) {
|
||||
handlerResult = argument;
|
||||
} else if (handlerNum == PromiseHandlerThrower) {
|
||||
} else {
|
||||
// Step 5.
|
||||
MOZ_ASSERT(handlerNum == PromiseHandlerThrower);
|
||||
resolutionMode = RejectMode;
|
||||
handlerResult = argument;
|
||||
} else {
|
||||
MOZ_ASSERT(handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone ||
|
||||
handlerNum == PromiseHandlerAsyncIteratorValueUnwrapNotDone);
|
||||
|
||||
bool done = handlerNum == PromiseHandlerAsyncIteratorValueUnwrapDone;
|
||||
// Async Iteration proposal 6.1.1.2.1 step 1.
|
||||
RootedObject resultObj(cx, CreateIterResultObject(cx, argument, done));
|
||||
if (!resultObj)
|
||||
return false;
|
||||
|
||||
handlerResult = ObjectValue(*resultObj);
|
||||
}
|
||||
} else {
|
||||
// Step 6.
|
||||
|
@ -2261,185 +2191,6 @@ js::AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, Hand
|
|||
return PerformPromiseThenWithReaction(cx, promise, reaction);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 5.1 steps 2-9.
|
||||
MOZ_MUST_USE bool
|
||||
js::AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value)
|
||||
{
|
||||
// Step 2.
|
||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
||||
if (!promise)
|
||||
return false;
|
||||
|
||||
// Steps 3.
|
||||
if (!ResolvePromiseInternal(cx, promise, value))
|
||||
return false;
|
||||
|
||||
// Steps 4-5.
|
||||
RootedValue onFulfilled(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitFulfilled));
|
||||
RootedValue onRejected(cx, Int32Value(PromiseHandlerAsyncGeneratorAwaitRejected));
|
||||
|
||||
RootedObject incumbentGlobal(cx);
|
||||
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
|
||||
return false;
|
||||
|
||||
// Step 6 (skipped).
|
||||
|
||||
// Steps 7-8.
|
||||
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, nullptr,
|
||||
onFulfilled, onRejected,
|
||||
nullptr, nullptr,
|
||||
incumbentGlobal));
|
||||
if (!reaction)
|
||||
return false;
|
||||
|
||||
reaction->setIsAsyncGeneratorAwait(asyncGenObj);
|
||||
|
||||
// Step 9.
|
||||
return PerformPromiseThenWithReaction(cx, promise, reaction);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.3.3.
|
||||
MOZ_MUST_USE bool
|
||||
js::AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value, bool done)
|
||||
{
|
||||
// Step 1 (implicit).
|
||||
|
||||
// Steps 2-3.
|
||||
MOZ_ASSERT(!asyncGenObj->isQueueEmpty());
|
||||
|
||||
// Step 4.
|
||||
Rooted<AsyncGeneratorRequest*> request(
|
||||
cx, AsyncGeneratorObject::dequeueRequest(cx, asyncGenObj));
|
||||
if (!request)
|
||||
return false;
|
||||
|
||||
// Step 5.
|
||||
RootedObject resultPromise(cx, request->promise());
|
||||
|
||||
// Step 6.
|
||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
||||
if (!promise)
|
||||
return false;
|
||||
|
||||
// Step 7.
|
||||
if (!ResolvePromiseInternal(cx, promise, value))
|
||||
return false;
|
||||
|
||||
// Steps 8-9.
|
||||
RootedValue onFulfilled(cx, Int32Value(done
|
||||
? PromiseHandlerAsyncIteratorValueUnwrapDone
|
||||
: PromiseHandlerAsyncIteratorValueUnwrapNotDone));
|
||||
|
||||
RootedObject incumbentGlobal(cx);
|
||||
if (!GetObjectFromIncumbentGlobal(cx, &incumbentGlobal))
|
||||
return false;
|
||||
|
||||
// Step 10.
|
||||
Rooted<PromiseReactionRecord*> reaction(cx, NewReactionRecord(cx, resultPromise, onFulfilled,
|
||||
UndefinedHandleValue,
|
||||
nullptr, nullptr,
|
||||
incumbentGlobal));
|
||||
if (!reaction)
|
||||
return false;
|
||||
|
||||
if (!PerformPromiseThenWithReaction(cx, promise, reaction))
|
||||
return false;
|
||||
|
||||
// Step 11.
|
||||
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
|
||||
return false;
|
||||
|
||||
// Step 12.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.3.4.
|
||||
MOZ_MUST_USE bool
|
||||
js::AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue exception)
|
||||
{
|
||||
// Step 1 (implicit).
|
||||
|
||||
// Steps 2-3.
|
||||
MOZ_ASSERT(!asyncGenObj->isQueueEmpty());
|
||||
|
||||
// Step 4.
|
||||
Rooted<AsyncGeneratorRequest*> request(
|
||||
cx, AsyncGeneratorObject::dequeueRequest(cx, asyncGenObj));
|
||||
if (!request)
|
||||
return false;
|
||||
|
||||
// Step 5.
|
||||
RootedObject resultPromise(cx, request->promise());
|
||||
|
||||
// Step 6.
|
||||
if (!RejectMaybeWrappedPromise(cx, resultPromise, exception))
|
||||
return false;
|
||||
|
||||
// Step 7.
|
||||
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
|
||||
return false;
|
||||
|
||||
// Step 8.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.3.6.
|
||||
MOZ_MUST_USE bool
|
||||
js::AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal,
|
||||
CompletionKind completionKind, HandleValue completionValue,
|
||||
MutableHandleValue result)
|
||||
{
|
||||
// Step 1 (implicit).
|
||||
|
||||
// Step 2.
|
||||
RootedObject resultPromise(cx, CreatePromiseObjectWithoutResolutionFunctions(cx));
|
||||
if (!resultPromise)
|
||||
return false;
|
||||
|
||||
// Step 3.
|
||||
if (!asyncGenVal.isObject() || !asyncGenVal.toObject().is<AsyncGeneratorObject>()) {
|
||||
// Step 3.a.
|
||||
RootedValue badGeneratorError(cx);
|
||||
if (!GetTypeError(cx, JSMSG_NOT_AN_ASYNC_GENERATOR, &badGeneratorError))
|
||||
return false;
|
||||
|
||||
// Step 3.b.
|
||||
if (!RejectMaybeWrappedPromise(cx, resultPromise, badGeneratorError))
|
||||
return false;
|
||||
|
||||
// Step 3.c.
|
||||
result.setObject(*resultPromise);
|
||||
return true;
|
||||
}
|
||||
|
||||
Rooted<AsyncGeneratorObject*> asyncGenObj(
|
||||
cx, &asyncGenVal.toObject().as<AsyncGeneratorObject>());
|
||||
|
||||
// Step 5 (reordered).
|
||||
Rooted<AsyncGeneratorRequest*> request(
|
||||
cx, AsyncGeneratorRequest::create(cx, completionKind, completionValue, resultPromise));
|
||||
if (!request)
|
||||
return false;
|
||||
|
||||
// Steps 4, 6.
|
||||
if (!AsyncGeneratorObject::enqueueRequest(cx, asyncGenObj, request))
|
||||
return false;
|
||||
|
||||
// Step 7.
|
||||
if (!asyncGenObj->isExecuting()) {
|
||||
// Step 8.
|
||||
if (!AsyncGeneratorResumeNext(cx, asyncGenObj))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 9.
|
||||
result.setObject(*resultPromise);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ES2016, 25.4.5.3.
|
||||
bool
|
||||
js::Promise_then(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
|
|
@ -135,23 +135,6 @@ AsyncFunctionThrown(JSContext* cx, Handle<PromiseObject*> resultPromise);
|
|||
MOZ_MUST_USE bool
|
||||
AsyncFunctionAwait(JSContext* cx, Handle<PromiseObject*> resultPromise, HandleValue value);
|
||||
|
||||
class AsyncGeneratorObject;
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
AsyncGeneratorAwait(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj, HandleValue value);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
AsyncGeneratorResolve(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value, bool done);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
AsyncGeneratorReject(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue exception);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
AsyncGeneratorEnqueue(JSContext* cx, HandleValue asyncGenVal, CompletionKind completionKind,
|
||||
HandleValue completionValue, MutableHandleValue result);
|
||||
|
||||
/**
|
||||
* A PromiseTask represents a task that can be dispatched to a helper thread
|
||||
* (via StartPromiseTask), executed (by implementing PromiseTask::execute()),
|
||||
|
|
|
@ -778,15 +778,3 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu
|
|||
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
|
||||
return compiler.compileStandaloneFunction(fun, NotGenerator, AsyncFunction, parameterListEnd);
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
const Maybe<uint32_t>& parameterListEnd)
|
||||
{
|
||||
RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
|
||||
|
||||
BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope);
|
||||
return compiler.compileStandaloneFunction(fun, StarGenerator, AsyncFunction, parameterListEnd);
|
||||
}
|
||||
|
|
|
@ -89,12 +89,6 @@ CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fun,
|
|||
JS::SourceBufferHolder& srcBuf,
|
||||
const mozilla::Maybe<uint32_t>& parameterListEnd);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
CompileStandaloneAsyncGenerator(JSContext* cx, MutableHandleFunction fun,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
const mozilla::Maybe<uint32_t>& parameterListEnd);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
CompileAsyncFunctionBody(JSContext* cx, MutableHandleFunction fun,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
|
|
|
@ -7841,8 +7841,7 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
|||
MOZ_ASSERT(fun->isArrow() == (pn->getOp() == JSOP_LAMBDA_ARROW));
|
||||
if (funbox->isAsync()) {
|
||||
MOZ_ASSERT(!needsProto);
|
||||
return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow(),
|
||||
fun->isStarGenerator());
|
||||
return emitAsyncWrapper(index, funbox->needsHomeObject(), fun->isArrow());
|
||||
}
|
||||
|
||||
if (fun->isArrow()) {
|
||||
|
@ -7897,11 +7896,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
|||
MOZ_ASSERT(pn->getOp() == JSOP_NOP);
|
||||
switchToPrologue();
|
||||
if (funbox->isAsync()) {
|
||||
if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow(),
|
||||
fun->isStarGenerator()))
|
||||
{
|
||||
if (!emitAsyncWrapper(index, fun->isMethod(), fun->isArrow()))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!emitIndex32(JSOP_LAMBDA, index))
|
||||
return false;
|
||||
|
@ -7917,12 +7913,10 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
|||
// initialize the binding name of the function in the current scope.
|
||||
|
||||
bool isAsync = funbox->isAsync();
|
||||
bool isStarGenerator = funbox->isStarGenerator();
|
||||
auto emitLambda = [index, isAsync, isStarGenerator](BytecodeEmitter* bce,
|
||||
const NameLocation&, bool) {
|
||||
auto emitLambda = [index, isAsync](BytecodeEmitter* bce, const NameLocation&, bool) {
|
||||
if (isAsync) {
|
||||
return bce->emitAsyncWrapper(index, /* needsHomeObject = */ false,
|
||||
/* isArrow = */ false, isStarGenerator);
|
||||
/* isArrow = */ false);
|
||||
}
|
||||
return bce->emitIndexOp(JSOP_LAMBDA, index);
|
||||
};
|
||||
|
@ -7957,8 +7951,7 @@ BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) {
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow,
|
||||
bool isStarGenerator)
|
||||
BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow)
|
||||
{
|
||||
// needsHomeObject can be true for propertyList for extended class.
|
||||
// In that case push both unwrapped and wrapped function, in order to
|
||||
|
@ -7990,13 +7983,8 @@ BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isA
|
|||
if (!emit1(JSOP_DUP))
|
||||
return false;
|
||||
}
|
||||
if (isStarGenerator) {
|
||||
if (!emit1(JSOP_TOASYNCGEN))
|
||||
return false;
|
||||
} else {
|
||||
if (!emit1(JSOP_TOASYNC))
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOP_TOASYNC))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -619,8 +619,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow);
|
||||
MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow,
|
||||
bool isStarGenerator);
|
||||
MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow);
|
||||
|
||||
MOZ_MUST_USE bool emitComputedPropertyName(ParseNode* computedPropName);
|
||||
|
||||
|
|
|
@ -3753,12 +3753,10 @@ Parser<ParseHandler>::functionStmt(uint32_t preludeStart, YieldHandling yieldHan
|
|||
|
||||
GeneratorKind generatorKind = NotGenerator;
|
||||
if (tt == TOK_MUL) {
|
||||
#ifdef RELEASE_OR_BETA
|
||||
if (asyncKind != SyncFunction) {
|
||||
error(JSMSG_ASYNC_GENERATOR);
|
||||
return null();
|
||||
}
|
||||
#endif
|
||||
generatorKind = StarGenerator;
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
@ -3827,12 +3825,10 @@ Parser<ParseHandler>::functionExpr(uint32_t preludeStart, InvokedPrediction invo
|
|||
return null();
|
||||
|
||||
if (tt == TOK_MUL) {
|
||||
#ifdef RELEASE_OR_BETA
|
||||
if (asyncKind != SyncFunction) {
|
||||
error(JSMSG_ASYNC_GENERATOR);
|
||||
return null();
|
||||
}
|
||||
#endif
|
||||
generatorKind = StarGenerator;
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
@ -9292,6 +9288,11 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
|
|||
|
||||
bool isGenerator = false;
|
||||
bool isAsync = false;
|
||||
if (ltok == TOK_MUL) {
|
||||
isGenerator = true;
|
||||
if (!tokenStream.getToken(<ok))
|
||||
return null();
|
||||
}
|
||||
|
||||
if (ltok == TOK_ASYNC) {
|
||||
// AsyncMethod[Yield, Await]:
|
||||
|
@ -9320,15 +9321,9 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
|
|||
}
|
||||
}
|
||||
|
||||
if (ltok == TOK_MUL) {
|
||||
#ifdef RELEASE_OR_BETA
|
||||
if (isAsync && isGenerator) {
|
||||
error(JSMSG_ASYNC_GENERATOR);
|
||||
return null();
|
||||
#else
|
||||
isGenerator = true;
|
||||
if (!tokenStream.getToken(<ok))
|
||||
return null();
|
||||
#endif
|
||||
}
|
||||
|
||||
propAtom.set(nullptr);
|
||||
|
|
|
@ -591,6 +591,3 @@ MSG_DEF(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON,0, JSEXN_INTERNALERR, "P
|
|||
// Iterator
|
||||
MSG_DEF(JSMSG_RETURN_NOT_CALLABLE, 0, JSEXN_TYPEERR, "property 'return' of iterator is not callable")
|
||||
MSG_DEF(JSMSG_ITERATOR_NO_THROW, 0, JSEXN_TYPEERR, "iterator does not have a 'throw' method")
|
||||
|
||||
// Async Iteration
|
||||
MSG_DEF(JSMSG_NOT_AN_ASYNC_GENERATOR, 0, JSEXN_TYPEERR, "Not an async generator")
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
#include "js/StructuredClone.h"
|
||||
#include "js/Utility.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
#include "vm/DateObject.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
|
@ -3616,11 +3615,6 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, Handle
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (IsWrappedAsyncGenerator(fun)) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (CanReuseScriptForClone(cx->compartment(), fun, env)) {
|
||||
// If the script is to be reused, either the script can already handle
|
||||
// non-syntactic scopes, or there is only the standard global lexical
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "js/CallNonGenericMethod.h"
|
||||
#include "js/Proxy.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/Interpreter.h"
|
||||
|
@ -307,8 +306,6 @@ CallerGetterImpl(JSContext* cx, const CallArgs& args)
|
|||
JSFunction* callerFun = &callerObj->as<JSFunction>();
|
||||
if (IsWrappedAsyncFunction(callerFun))
|
||||
callerFun = GetUnwrappedAsyncFunction(callerFun);
|
||||
else if (IsWrappedAsyncGenerator(callerFun))
|
||||
callerFun = GetUnwrappedAsyncGenerator(callerFun);
|
||||
MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
|
||||
|
||||
if (callerFun->strict()) {
|
||||
|
@ -405,15 +402,13 @@ static const JSPropertySpec function_properties[] = {
|
|||
static bool
|
||||
ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId id)
|
||||
{
|
||||
bool isAsyncGenerator = IsWrappedAsyncGenerator(fun);
|
||||
|
||||
MOZ_ASSERT_IF(!isAsyncGenerator, fun->isInterpreted() || fun->isAsmJSNative());
|
||||
MOZ_ASSERT(fun->isInterpreted() || fun->isAsmJSNative());
|
||||
MOZ_ASSERT(id == NameToId(cx->names().prototype));
|
||||
|
||||
// Assert that fun is not a compiler-created function object, which
|
||||
// must never leak to script or embedding code and then be mutated.
|
||||
// Also assert that fun is not bound, per the ES5 15.3.4.5 ref above.
|
||||
MOZ_ASSERT_IF(!isAsyncGenerator, !IsInternalFunctionObject(*fun));
|
||||
MOZ_ASSERT(!IsInternalFunctionObject(*fun));
|
||||
MOZ_ASSERT(!fun->isBoundFunction());
|
||||
|
||||
// Make the prototype object an instance of Object with the same parent as
|
||||
|
@ -423,9 +418,7 @@ ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId
|
|||
bool isStarGenerator = fun->isStarGenerator();
|
||||
Rooted<GlobalObject*> global(cx, &fun->global());
|
||||
RootedObject objProto(cx);
|
||||
if (isAsyncGenerator)
|
||||
objProto = GlobalObject::getOrCreateAsyncGeneratorPrototype(cx, global);
|
||||
else if (isStarGenerator)
|
||||
if (isStarGenerator)
|
||||
objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
|
||||
else
|
||||
objProto = GlobalObject::getOrCreateObjectPrototype(cx, global);
|
||||
|
@ -441,7 +434,7 @@ ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId
|
|||
// non-enumerable, and writable. However, per the 15 July 2013 ES6 draft,
|
||||
// section 15.19.3, the .prototype of a generator function does not link
|
||||
// back with a .constructor.
|
||||
if (!isStarGenerator && !isAsyncGenerator) {
|
||||
if (!isStarGenerator) {
|
||||
RootedValue objVal(cx, ObjectValue(*fun));
|
||||
if (!DefineProperty(cx, proto, cx->names().constructor, objVal, nullptr, nullptr, 0))
|
||||
return false;
|
||||
|
@ -491,13 +484,11 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
|||
* - Arrow functions
|
||||
* - Function.prototype
|
||||
*/
|
||||
if (!IsWrappedAsyncGenerator(fun)) {
|
||||
if (fun->isBuiltin())
|
||||
if (fun->isBuiltin())
|
||||
return true;
|
||||
if (!fun->isConstructor()) {
|
||||
if (!fun->isStarGenerator() && !fun->isLegacyGenerator() && !fun->isAsync())
|
||||
return true;
|
||||
if (!fun->isConstructor()) {
|
||||
if (!fun->isStarGenerator() && !fun->isLegacyGenerator() && !fun->isAsync())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ResolveInterpretedFunctionPrototype(cx, fun, id))
|
||||
|
@ -994,10 +985,6 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
|
|||
RootedFunction unwrapped(cx, GetUnwrappedAsyncFunction(fun));
|
||||
return FunctionToString(cx, unwrapped, prettyPrint);
|
||||
}
|
||||
if (IsWrappedAsyncGenerator(fun)) {
|
||||
RootedFunction unwrapped(cx, GetUnwrappedAsyncGenerator(fun));
|
||||
return FunctionToString(cx, unwrapped, prettyPrint);
|
||||
}
|
||||
|
||||
StringBuffer out(cx);
|
||||
RootedScript script(cx);
|
||||
|
@ -1650,14 +1637,10 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
|
|||
&mutedErrors);
|
||||
|
||||
const char* introductionType = "Function";
|
||||
if (isAsync) {
|
||||
if (isStarGenerator)
|
||||
introductionType = "AsyncGenerator";
|
||||
else
|
||||
introductionType = "AsyncFunction";
|
||||
} else if (generatorKind != NotGenerator) {
|
||||
if (isAsync)
|
||||
introductionType = "AsyncFunction";
|
||||
else if (generatorKind != NotGenerator)
|
||||
introductionType = "GeneratorFunction";
|
||||
}
|
||||
|
||||
const char* introducerFilename = filename;
|
||||
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
|
||||
|
@ -1784,20 +1767,12 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
|
|||
: SourceBufferHolder::NoOwnership;
|
||||
bool ok;
|
||||
SourceBufferHolder srcBuf(chars.begin().get(), chars.length(), ownership);
|
||||
if (isAsync) {
|
||||
if (isStarGenerator) {
|
||||
ok = frontend::CompileStandaloneAsyncGenerator(cx, &fun, options, srcBuf,
|
||||
parameterListEnd);
|
||||
} else {
|
||||
ok = frontend::CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf,
|
||||
parameterListEnd);
|
||||
}
|
||||
} else {
|
||||
if (isStarGenerator)
|
||||
ok = frontend::CompileStandaloneGenerator(cx, &fun, options, srcBuf, parameterListEnd);
|
||||
else
|
||||
ok = frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, parameterListEnd);
|
||||
}
|
||||
if (isAsync)
|
||||
ok = frontend::CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf, parameterListEnd);
|
||||
else if (isStarGenerator)
|
||||
ok = frontend::CompileStandaloneGenerator(cx, &fun, options, srcBuf, parameterListEnd);
|
||||
else
|
||||
ok = frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, parameterListEnd);
|
||||
|
||||
// Step 33.
|
||||
args.rval().setObject(*fun);
|
||||
|
@ -1823,7 +1798,7 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Save the callee before it's reset in FunctionConstructor().
|
||||
// Save the callee before its reset in FunctionConstructor().
|
||||
RootedObject newTarget(cx);
|
||||
if (args.isConstructing())
|
||||
newTarget = &args.newTarget().toObject();
|
||||
|
@ -1855,40 +1830,6 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Save the callee before its reset in FunctionConstructor().
|
||||
RootedObject newTarget(cx);
|
||||
if (args.isConstructing())
|
||||
newTarget = &args.newTarget().toObject();
|
||||
else
|
||||
newTarget = &args.callee();
|
||||
|
||||
if (!FunctionConstructor(cx, args, StarGenerator, AsyncFunction))
|
||||
return false;
|
||||
|
||||
RootedObject proto(cx);
|
||||
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
|
||||
return false;
|
||||
|
||||
if (!proto) {
|
||||
proto = GlobalObject::getOrCreateAsyncGenerator(cx, cx->global());
|
||||
if (!proto)
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedFunction unwrapped(cx, &args.rval().toObject().as<JSFunction>());
|
||||
RootedObject wrapped(cx, WrapAsyncGeneratorWithProto(cx, unwrapped, proto));
|
||||
if (!wrapped)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*wrapped);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSFunction::isBuiltinFunctionConstructor()
|
||||
{
|
||||
|
|
|
@ -647,9 +647,6 @@ Generator(JSContext* cx, unsigned argc, Value* vp);
|
|||
extern bool
|
||||
AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
extern bool
|
||||
AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Allocate a new function backed by a JSNative. Note that by default this
|
||||
// creates a singleton object.
|
||||
extern JSFunction*
|
||||
|
|
|
@ -938,30 +938,28 @@ js::GetIteratorObject(JSContext* cx, HandleObject obj, uint32_t flags)
|
|||
return iterator;
|
||||
}
|
||||
|
||||
// ES 2017 draft 7.4.7.
|
||||
JSObject*
|
||||
js::CreateIterResultObject(JSContext* cx, HandleValue value, bool done)
|
||||
js::CreateItrResultObject(JSContext* cx, HandleValue value, bool done)
|
||||
{
|
||||
// Step 1 (implicit).
|
||||
// FIXME: We can cache the iterator result object shape somewhere.
|
||||
AssertHeapIsIdle();
|
||||
|
||||
// Step 2.
|
||||
RootedObject resultObj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!resultObj)
|
||||
RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, cx->global()));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
// Step 3.
|
||||
if (!DefineProperty(cx, resultObj, cx->names().value, value))
|
||||
RootedPlainObject obj(cx, NewObjectWithGivenProto<PlainObject>(cx, proto));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
// Step 4.
|
||||
if (!DefineProperty(cx, resultObj, cx->names().done,
|
||||
done ? TrueHandleValue : FalseHandleValue))
|
||||
{
|
||||
if (!DefineProperty(cx, obj, cx->names().value, value))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
return resultObj;
|
||||
RootedValue doneBool(cx, BooleanValue(done));
|
||||
if (!DefineProperty(cx, obj, cx->names().done, doneBool))
|
||||
return nullptr;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -210,10 +210,10 @@ ThrowStopIteration(JSContext* cx);
|
|||
|
||||
/*
|
||||
* Create an object of the form { value: VALUE, done: DONE }.
|
||||
* ES 2017 draft 7.4.7.
|
||||
* ES6 draft from 2013-09-05, section 25.4.3.4.
|
||||
*/
|
||||
extern JSObject*
|
||||
CreateIterResultObject(JSContext* cx, HandleValue value, bool done);
|
||||
CreateItrResultObject(JSContext* cx, HandleValue value, bool done);
|
||||
|
||||
extern JSObject*
|
||||
InitLegacyIteratorClass(JSContext* cx, HandleObject obj);
|
||||
|
|
|
@ -311,7 +311,6 @@ UNIFIED_SOURCES += [
|
|||
'vm/ArgumentsObject.cpp',
|
||||
'vm/ArrayBufferObject.cpp',
|
||||
'vm/AsyncFunction.cpp',
|
||||
'vm/AsyncIteration.cpp',
|
||||
'vm/Caches.cpp',
|
||||
'vm/CallNonGenericMethod.cpp',
|
||||
'vm/CharacterEncoding.cpp',
|
||||
|
@ -754,7 +753,6 @@ selfhosted.inputs = [
|
|||
'builtin/SelfHostingDefines.h',
|
||||
'builtin/Utilities.js',
|
||||
'builtin/Array.js',
|
||||
'builtin/AsyncIteration.js',
|
||||
'builtin/Classes.js',
|
||||
'builtin/Date.js',
|
||||
'builtin/Error.js',
|
||||
|
|
|
@ -86,7 +86,6 @@
|
|||
#include "threading/Thread.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
#include "vm/Compression.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
|
@ -2396,8 +2395,6 @@ ValueToScript(JSContext* cx, HandleValue v, JSFunction** funp = nullptr)
|
|||
// Get unwrapped async function.
|
||||
if (IsWrappedAsyncFunction(fun))
|
||||
fun = GetUnwrappedAsyncFunction(fun);
|
||||
if (IsWrappedAsyncGenerator(fun))
|
||||
fun = GetUnwrappedAsyncGenerator(fun);
|
||||
|
||||
if (!fun->isInterpreted()) {
|
||||
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_SCRIPTS_ONLY);
|
||||
|
|
|
@ -9,6 +9,9 @@ if (typeof Reflect !== "undefined" && Reflect.parse) {
|
|||
assertEq(Reflect.parse("async function a() {}").body[0].async, true);
|
||||
assertEq(Reflect.parse("() => {}").body[0].async, undefined);
|
||||
|
||||
// Async generators are not allowed (with regards to spec)
|
||||
assertThrows(() => Reflect.parse("async function* a() {}"), SyntaxError);
|
||||
|
||||
// No line terminator after async
|
||||
assertEq(Reflect.parse("async\nfunction a(){}").body[0].expression.name, "async");
|
||||
|
||||
|
|
|
@ -1,564 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "vm/AsyncIteration.h"
|
||||
|
||||
#include "jsarray.h"
|
||||
#include "jscompartment.h"
|
||||
|
||||
#include "builtin/Promise.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
|
||||
#include "jscntxtinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
#define UNWRAPPED_ASYNC_WRAPPED_SLOT 1
|
||||
#define WRAPPED_ASYNC_UNWRAPPED_SLOT 0
|
||||
|
||||
// Async Iteration proposal 2.3.10 Runtime Semantics: EvaluateBody.
|
||||
static bool
|
||||
WrappedAsyncGenerator(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
RootedFunction wrapped(cx, &args.callee().as<JSFunction>());
|
||||
RootedValue unwrappedVal(cx, wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT));
|
||||
RootedFunction unwrapped(cx, &unwrappedVal.toObject().as<JSFunction>());
|
||||
RootedValue thisValue(cx, args.thisv());
|
||||
|
||||
// Step 1.
|
||||
RootedValue generatorVal(cx);
|
||||
InvokeArgs args2(cx);
|
||||
if (!args2.init(cx, argc))
|
||||
return false;
|
||||
for (size_t i = 0, len = argc; i < len; i++)
|
||||
args2[i].set(args[i]);
|
||||
if (!Call(cx, unwrappedVal, thisValue, args2, &generatorVal))
|
||||
return false;
|
||||
|
||||
// Step 2.
|
||||
Rooted<AsyncGeneratorObject*> asyncGenObj(
|
||||
cx, AsyncGeneratorObject::create(cx, wrapped, generatorVal));
|
||||
if (!asyncGenObj)
|
||||
return false;
|
||||
|
||||
// Step 3 (skipped).
|
||||
// Done in AsyncGeneratorObject::create and generator.
|
||||
|
||||
// Step 4.
|
||||
args.rval().setObject(*asyncGenObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto)
|
||||
{
|
||||
MOZ_ASSERT(unwrapped->isAsync());
|
||||
MOZ_ASSERT(proto, "We need an explicit prototype to avoid the default"
|
||||
"%FunctionPrototype% fallback in NewFunctionWithProto().");
|
||||
|
||||
// Create a new function with AsyncGeneratorPrototype, reusing the name and
|
||||
// the length of `unwrapped`.
|
||||
|
||||
RootedAtom funName(cx, unwrapped->explicitName());
|
||||
uint16_t length;
|
||||
if (!JSFunction::getLength(cx, unwrapped, &length))
|
||||
return nullptr;
|
||||
|
||||
RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncGenerator, length,
|
||||
JSFunction::NATIVE_FUN, nullptr,
|
||||
funName, proto,
|
||||
AllocKind::FUNCTION_EXTENDED,
|
||||
TenuredObject));
|
||||
if (!wrapped)
|
||||
return nullptr;
|
||||
|
||||
if (unwrapped->hasCompileTimeName())
|
||||
wrapped->setCompileTimeName(unwrapped->compileTimeName());
|
||||
|
||||
// Link them to each other to make GetWrappedAsyncGenerator and
|
||||
// GetUnwrappedAsyncGenerator work.
|
||||
unwrapped->setExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT, ObjectValue(*wrapped));
|
||||
wrapped->setExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT, ObjectValue(*unwrapped));
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::WrapAsyncGenerator(JSContext* cx, HandleFunction unwrapped)
|
||||
{
|
||||
RootedObject proto(cx, GlobalObject::getOrCreateAsyncGenerator(cx, cx->global()));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
return WrapAsyncGeneratorWithProto(cx, unwrapped, proto);
|
||||
}
|
||||
|
||||
bool
|
||||
js::IsWrappedAsyncGenerator(JSFunction* fun)
|
||||
{
|
||||
return fun->maybeNative() == WrappedAsyncGenerator;
|
||||
}
|
||||
|
||||
JSFunction*
|
||||
js::GetWrappedAsyncGenerator(JSFunction* unwrapped)
|
||||
{
|
||||
MOZ_ASSERT(unwrapped->isAsync());
|
||||
return &unwrapped->getExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT).toObject().as<JSFunction>();
|
||||
}
|
||||
|
||||
JSFunction*
|
||||
js::GetUnwrappedAsyncGenerator(JSFunction* wrapped)
|
||||
{
|
||||
MOZ_ASSERT(IsWrappedAsyncGenerator(wrapped));
|
||||
JSFunction* unwrapped = &wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT)
|
||||
.toObject().as<JSFunction>();
|
||||
MOZ_ASSERT(unwrapped->isAsync());
|
||||
return unwrapped;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
CompletionKind completionKind, HandleValue argument);
|
||||
|
||||
// Async Iteration proposal 5.1.1 Await Fulfilled Functions.
|
||||
MOZ_MUST_USE bool
|
||||
js::AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value)
|
||||
{
|
||||
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Normal, value);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 5.1.2 Await Rejected Functions.
|
||||
MOZ_MUST_USE bool
|
||||
js::AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue reason)
|
||||
{
|
||||
return AsyncGeneratorResume(cx, asyncGenObj, CompletionKind::Throw, reason);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.1.2 AsyncGenerator.prototype.next.
|
||||
static bool
|
||||
AsyncGeneratorNext(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Steps 1-3.
|
||||
return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Normal, args.get(0),
|
||||
args.rval());
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.1.3 AsyncGenerator.prototype.return.
|
||||
static bool
|
||||
AsyncGeneratorReturn(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Steps 1-3.
|
||||
return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Return, args.get(0),
|
||||
args.rval());
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.1.4 AsyncGenerator.prototype.throw.
|
||||
static bool
|
||||
AsyncGeneratorThrow(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Steps 1-3.
|
||||
return AsyncGeneratorEnqueue(cx, args.thisv(), CompletionKind::Throw, args.get(0),
|
||||
args.rval());
|
||||
}
|
||||
|
||||
const Class AsyncGeneratorObject::class_ = {
|
||||
"AsyncGenerator",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorObject::Slots)
|
||||
};
|
||||
|
||||
// ES 2017 draft 9.1.13.
|
||||
template <typename ProtoGetter>
|
||||
static JSObject*
|
||||
OrdinaryCreateFromConstructor(JSContext* cx, HandleFunction fun,
|
||||
ProtoGetter protoGetter, const Class* clasp)
|
||||
{
|
||||
// Step 1 (skipped).
|
||||
|
||||
// Step 2.
|
||||
RootedValue protoVal(cx);
|
||||
if (!GetProperty(cx, fun, fun, cx->names().prototype, &protoVal))
|
||||
return nullptr;
|
||||
|
||||
RootedObject proto(cx, protoVal.isObject() ? &protoVal.toObject() : nullptr);
|
||||
if (!proto) {
|
||||
proto = protoGetter(cx, cx->global());
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
return NewNativeObjectWithGivenProto(cx, clasp, proto);
|
||||
}
|
||||
|
||||
/* static */ AsyncGeneratorObject*
|
||||
AsyncGeneratorObject::create(JSContext* cx, HandleFunction asyncGen, HandleValue generatorVal)
|
||||
{
|
||||
MOZ_ASSERT(generatorVal.isObject());
|
||||
MOZ_ASSERT(generatorVal.toObject().is<GeneratorObject>());
|
||||
|
||||
RootedObject obj(
|
||||
cx, OrdinaryCreateFromConstructor(cx, asyncGen,
|
||||
GlobalObject::getOrCreateAsyncGeneratorPrototype,
|
||||
&class_));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
Handle<AsyncGeneratorObject*> asyncGenObj = obj.as<AsyncGeneratorObject>();
|
||||
|
||||
// Async Iteration proposal 6.4.3.2 AsyncGeneratorStart.
|
||||
// Step 6.
|
||||
asyncGenObj->setGenerator(generatorVal);
|
||||
|
||||
// Step 7.
|
||||
asyncGenObj->setSuspendedStart();
|
||||
|
||||
// Step 8.
|
||||
asyncGenObj->clearSingleQueueRequest();
|
||||
|
||||
return asyncGenObj;
|
||||
}
|
||||
|
||||
/* static */ MOZ_MUST_USE bool
|
||||
AsyncGeneratorObject::enqueueRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
Handle<AsyncGeneratorRequest*> request)
|
||||
{
|
||||
if (asyncGenObj->isSingleQueue()) {
|
||||
if (asyncGenObj->isSingleQueueEmpty()) {
|
||||
asyncGenObj->setSingleQueueRequest(request);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedArrayObject queue(cx, NewDenseEmptyArray(cx));
|
||||
if (!queue)
|
||||
return false;
|
||||
|
||||
if (!NewbornArrayPush(cx, queue, ObjectValue(*asyncGenObj->singleQueueRequest())))
|
||||
return false;
|
||||
if (!NewbornArrayPush(cx, queue, ObjectValue(*request)))
|
||||
return false;
|
||||
|
||||
asyncGenObj->setQueue(queue);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedArrayObject queue(cx, asyncGenObj->queue());
|
||||
|
||||
FixedInvokeArgs<1> args(cx);
|
||||
args[0].setObject(*request);
|
||||
args.setThis(ObjectValue(*queue));
|
||||
return CallJSNative(cx, array_push, args);
|
||||
}
|
||||
|
||||
/* static */ AsyncGeneratorRequest*
|
||||
AsyncGeneratorObject::dequeueRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
||||
{
|
||||
if (asyncGenObj->isSingleQueue()) {
|
||||
AsyncGeneratorRequest* request = asyncGenObj->singleQueueRequest();
|
||||
asyncGenObj->clearSingleQueueRequest();
|
||||
return request;
|
||||
}
|
||||
|
||||
RootedArrayObject queue(cx, asyncGenObj->queue());
|
||||
|
||||
FixedInvokeArgs<0> args(cx);
|
||||
args.setThis(ObjectValue(*queue));
|
||||
if (!CallJSNative(cx, array_shift, args))
|
||||
return nullptr;
|
||||
|
||||
return &args.rval().toObject().as<AsyncGeneratorRequest>();
|
||||
}
|
||||
|
||||
/* static */ AsyncGeneratorRequest*
|
||||
AsyncGeneratorObject::peekRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
||||
{
|
||||
if (asyncGenObj->isSingleQueue())
|
||||
return asyncGenObj->singleQueueRequest();
|
||||
|
||||
RootedArrayObject queue(cx, asyncGenObj->queue());
|
||||
|
||||
RootedValue requestVal(cx);
|
||||
if (!GetElement(cx, queue, queue, 0, &requestVal))
|
||||
return nullptr;
|
||||
|
||||
return &requestVal.toObject().as<AsyncGeneratorRequest>();
|
||||
}
|
||||
|
||||
const Class AsyncGeneratorRequest::class_ = {
|
||||
"AsyncGeneratorRequest",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(AsyncGeneratorRequest::Slots)
|
||||
};
|
||||
|
||||
// Async Iteration proposal 6.4.3.1.
|
||||
/* static */ AsyncGeneratorRequest*
|
||||
AsyncGeneratorRequest::create(JSContext* cx, CompletionKind completionKind_,
|
||||
HandleValue completionValue_, HandleObject promise_)
|
||||
{
|
||||
RootedObject obj(cx, NewNativeObjectWithGivenProto(cx, &class_, nullptr));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
Handle<AsyncGeneratorRequest*> request = obj.as<AsyncGeneratorRequest>();
|
||||
request->setCompletionKind(completionKind_);
|
||||
request->setCompletionValue(completionValue_);
|
||||
request->setPromise(promise_);
|
||||
return request;
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.3.2 steps 5.d-g.
|
||||
static MOZ_MUST_USE bool
|
||||
AsyncGeneratorReturned(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value)
|
||||
{
|
||||
// Step 5.d.
|
||||
asyncGenObj->setCompleted();
|
||||
|
||||
// Step 5.e (done in bytecode).
|
||||
// Step 5.f.i (implicit).
|
||||
|
||||
// Step 5.g.
|
||||
return AsyncGeneratorResolve(cx, asyncGenObj, value, true);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.3.2 steps 5.d, f.
|
||||
static MOZ_MUST_USE bool
|
||||
AsyncGeneratorThrown(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
||||
{
|
||||
// Step 5.d.
|
||||
asyncGenObj->setCompleted();
|
||||
|
||||
// Not much we can do about uncatchable exceptions, so just bail.
|
||||
if (!cx->isExceptionPending())
|
||||
return false;
|
||||
|
||||
// Step 5.f.i.
|
||||
RootedValue value(cx);
|
||||
if (!GetAndClearException(cx, &value))
|
||||
return false;
|
||||
|
||||
// Step 5.f.ii.
|
||||
return AsyncGeneratorReject(cx, asyncGenObj, value);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.3.5.
|
||||
MOZ_MUST_USE bool
|
||||
js::AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj)
|
||||
{
|
||||
// Step 1 (implicit).
|
||||
|
||||
// Steps 2-3.
|
||||
MOZ_ASSERT(!asyncGenObj->isExecuting());
|
||||
|
||||
// Steps 4-5.
|
||||
if (asyncGenObj->isQueueEmpty())
|
||||
return true;
|
||||
|
||||
// Steps 6-7.
|
||||
Rooted<AsyncGeneratorRequest*> request(
|
||||
cx, AsyncGeneratorObject::peekRequest(cx, asyncGenObj));
|
||||
if (!request)
|
||||
return false;
|
||||
|
||||
// Step 8.
|
||||
CompletionKind completionKind = request->completionKind();
|
||||
|
||||
// Step 9.
|
||||
if (completionKind != CompletionKind::Normal) {
|
||||
// Step 9.a.
|
||||
if (asyncGenObj->isSuspendedStart())
|
||||
asyncGenObj->setCompleted();
|
||||
|
||||
// Step 9.b.
|
||||
if (asyncGenObj->isCompleted()) {
|
||||
// Step 9.b.i.
|
||||
RootedValue value(cx, request->completionValue());
|
||||
if (completionKind == CompletionKind::Return)
|
||||
return AsyncGeneratorResolve(cx, asyncGenObj, value, true);
|
||||
// Step 9.b.ii.
|
||||
return AsyncGeneratorReject(cx, asyncGenObj, value);
|
||||
}
|
||||
} else if (asyncGenObj->isCompleted()) {
|
||||
// Step 10.
|
||||
return AsyncGeneratorResolve(cx, asyncGenObj, UndefinedHandleValue, true);
|
||||
}
|
||||
|
||||
// Step 11.
|
||||
MOZ_ASSERT(asyncGenObj->isSuspendedStart() || asyncGenObj->isSuspendedYield());
|
||||
|
||||
// Step 15 (reordered).
|
||||
asyncGenObj->setExecuting();
|
||||
|
||||
RootedValue argument(cx, request->completionValue());
|
||||
|
||||
// Steps 12-14, 16-20.
|
||||
return AsyncGeneratorResume(cx, asyncGenObj, completionKind, argument);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.2.1.2 (partially).
|
||||
// Most steps are done in generator.
|
||||
static MOZ_MUST_USE bool
|
||||
AsyncGeneratorYield(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value, bool done)
|
||||
{
|
||||
// Step 6.
|
||||
asyncGenObj->setSuspendedYield();
|
||||
|
||||
// Step 10.c.
|
||||
return AsyncGeneratorResolve(cx, asyncGenObj, value, done);
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.4.3.5 steps 12-14, 16-20.
|
||||
// Async Iteration proposal 6.2.1.2 step 10.
|
||||
// Async Iteration proposal 6.4.3.2 step 5.f-g.
|
||||
// Async Iteration proposal 5.1 steps 2-9.
|
||||
// Execution context switching is handled in generator.
|
||||
static MOZ_MUST_USE bool
|
||||
AsyncGeneratorResume(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
CompletionKind completionKind, HandleValue argument)
|
||||
{
|
||||
RootedValue generatorVal(cx, asyncGenObj->generatorVal());
|
||||
|
||||
// 6.4.3.5 steps 12-14, 16-20.
|
||||
HandlePropertyName funName = completionKind == CompletionKind::Normal
|
||||
? cx->names().StarGeneratorNext
|
||||
: completionKind == CompletionKind::Throw
|
||||
? cx->names().StarGeneratorThrow
|
||||
: cx->names().StarGeneratorReturn;
|
||||
FixedInvokeArgs<1> args(cx);
|
||||
args[0].set(argument);
|
||||
RootedValue result(cx);
|
||||
if (!CallSelfHostedFunction(cx, funName, generatorVal, args, &result)) {
|
||||
// 6.4.3.2 step 5.d, f.
|
||||
return AsyncGeneratorThrown(cx, asyncGenObj);
|
||||
}
|
||||
|
||||
// The following code corresponds to the following 3 cases:
|
||||
// * yield
|
||||
// * await
|
||||
// * return
|
||||
// For await and return, property access is done on an internal result
|
||||
// object and it's not observable.
|
||||
// For yield, it's done on an user-provided result object, and it's
|
||||
// observable, so perform in that order in all cases.
|
||||
|
||||
RootedObject resultObj(cx, &result.toObject());
|
||||
RootedValue value(cx);
|
||||
RootedValue doneVal(cx);
|
||||
|
||||
// 6.2.1.2 step 10.a.
|
||||
if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value))
|
||||
return false;
|
||||
|
||||
// 6.2.1.2 step 10.b.
|
||||
if (!GetProperty(cx, resultObj, resultObj, cx->names().done, &doneVal))
|
||||
return false;
|
||||
|
||||
// 6.2.1.2 step 10.c.
|
||||
if (asyncGenObj->generatorObj()->isAfterYield())
|
||||
return AsyncGeneratorYield(cx, asyncGenObj, value, ToBoolean(doneVal));
|
||||
|
||||
// 6.4.3.2 step 5.d-g.
|
||||
if (ToBoolean(doneVal)) {
|
||||
MOZ_ASSERT(!asyncGenObj->generatorObj()->isAfterAwait());
|
||||
return AsyncGeneratorReturned(cx, asyncGenObj, value);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(asyncGenObj->generatorObj()->isAfterAwait());
|
||||
|
||||
// 5.1 steps 2-9.
|
||||
return AsyncGeneratorAwait(cx, asyncGenObj, value);
|
||||
}
|
||||
|
||||
static const JSFunctionSpec async_iterator_proto_methods[] = {
|
||||
JS_SELF_HOSTED_SYM_FN(asyncIterator, "AsyncIteratorIdentity", 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static const JSFunctionSpec async_generator_methods[] = {
|
||||
JS_FN("next", AsyncGeneratorNext, 1, 0),
|
||||
JS_FN("throw", AsyncGeneratorThrow, 1, 0),
|
||||
JS_FN("return", AsyncGeneratorReturn, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
/* static */ MOZ_MUST_USE bool
|
||||
GlobalObject::initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
if (global->getReservedSlot(ASYNC_ITERATOR_PROTO).isObject())
|
||||
return true;
|
||||
|
||||
// Async Iteration proposal 6.1.2 %AsyncIteratorPrototype%.
|
||||
RootedObject asyncIterProto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
||||
if (!asyncIterProto)
|
||||
return false;
|
||||
if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr, async_iterator_proto_methods))
|
||||
return false;
|
||||
|
||||
// Async Iteration proposal 6.4.1 %AsyncGeneratorPrototype%.
|
||||
RootedObject asyncGenProto(
|
||||
cx, GlobalObject::createBlankPrototypeInheriting(cx, global, &PlainObject::class_,
|
||||
asyncIterProto));
|
||||
if (!asyncGenProto)
|
||||
return false;
|
||||
if (!DefinePropertiesAndFunctions(cx, asyncGenProto, nullptr, async_generator_methods) ||
|
||||
!DefineToStringTag(cx, asyncGenProto, cx->names().AsyncGenerator))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Async Iteration proposal 6.3.3 %AsyncGenerator%.
|
||||
RootedObject asyncGenerator(cx, NewSingletonObjectWithFunctionPrototype(cx, global));
|
||||
if (!asyncGenerator)
|
||||
return false;
|
||||
if (!JSObject::setDelegate(cx, asyncGenerator))
|
||||
return false;
|
||||
if (!LinkConstructorAndPrototype(cx, asyncGenerator, asyncGenProto, JSPROP_READONLY,
|
||||
JSPROP_READONLY) ||
|
||||
!DefineToStringTag(cx, asyncGenerator, cx->names().AsyncGeneratorFunction))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue function(cx, global->getConstructor(JSProto_Function));
|
||||
if (!function.toObjectOrNull())
|
||||
return false;
|
||||
RootedObject proto(cx, &function.toObject());
|
||||
RootedAtom name(cx, cx->names().AsyncGeneratorFunction);
|
||||
|
||||
// Async Iteration proposal 6.3.2 %AsyncGeneratorFunction%.
|
||||
RootedObject asyncGenFunction(
|
||||
cx, NewFunctionWithProto(cx, AsyncGeneratorConstructor, 1, JSFunction::NATIVE_CTOR,
|
||||
nullptr, name, proto, gc::AllocKind::FUNCTION, SingletonObject));
|
||||
if (!asyncGenFunction)
|
||||
return false;
|
||||
if (!LinkConstructorAndPrototype(cx, asyncGenFunction, asyncGenerator,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY, JSPROP_READONLY))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
global->setReservedSlot(ASYNC_ITERATOR_PROTO, ObjectValue(*asyncIterProto));
|
||||
global->setReservedSlot(ASYNC_GENERATOR, ObjectValue(*asyncGenerator));
|
||||
global->setReservedSlot(ASYNC_GENERATOR_FUNCTION, ObjectValue(*asyncGenFunction));
|
||||
global->setReservedSlot(ASYNC_GENERATOR_PROTO, ObjectValue(*asyncGenProto));
|
||||
return true;
|
||||
}
|
|
@ -1,204 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef vm_AsyncIteration_h
|
||||
#define vm_AsyncIteration_h
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "builtin/Promise.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
// Async generator consists of 2 functions, |wrapped| and |unwrapped|.
|
||||
// |unwrapped| is a generator function compiled from async generator script,
|
||||
// |await| behaves just like |yield| there. |unwrapped| isn't exposed to user
|
||||
// script.
|
||||
// |wrapped| is a native function that is the value of async generator.
|
||||
|
||||
JSObject*
|
||||
WrapAsyncGeneratorWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto);
|
||||
|
||||
JSObject*
|
||||
WrapAsyncGenerator(JSContext* cx, HandleFunction unwrapped);
|
||||
|
||||
bool
|
||||
IsWrappedAsyncGenerator(JSFunction* fun);
|
||||
|
||||
JSFunction*
|
||||
GetWrappedAsyncGenerator(JSFunction* unwrapped);
|
||||
|
||||
JSFunction*
|
||||
GetUnwrappedAsyncGenerator(JSFunction* wrapped);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
AsyncGeneratorAwaitedFulfilled(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue value);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
AsyncGeneratorAwaitedRejected(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
HandleValue reason);
|
||||
|
||||
class AsyncGeneratorRequest : public NativeObject
|
||||
{
|
||||
private:
|
||||
enum AsyncGeneratorRequestSlots {
|
||||
Slot_CompletionKind = 0,
|
||||
Slot_CompletionValue,
|
||||
Slot_Promise,
|
||||
Slots,
|
||||
};
|
||||
|
||||
void setCompletionKind(CompletionKind completionKind_) {
|
||||
setFixedSlot(Slot_CompletionKind,
|
||||
Int32Value(static_cast<int32_t>(completionKind_)));
|
||||
}
|
||||
void setCompletionValue(HandleValue completionValue_) {
|
||||
setFixedSlot(Slot_CompletionValue, completionValue_);
|
||||
}
|
||||
void setPromise(HandleObject promise_) {
|
||||
setFixedSlot(Slot_Promise, ObjectValue(*promise_));
|
||||
}
|
||||
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
static AsyncGeneratorRequest*
|
||||
create(JSContext* cx, CompletionKind completionKind, HandleValue completionValue,
|
||||
HandleObject promise);
|
||||
|
||||
CompletionKind completionKind() const {
|
||||
return static_cast<CompletionKind>(getFixedSlot(Slot_CompletionKind).toInt32());
|
||||
}
|
||||
JS::Value completionValue() const {
|
||||
return getFixedSlot(Slot_CompletionValue);
|
||||
}
|
||||
JSObject* promise() const {
|
||||
return &getFixedSlot(Slot_Promise).toObject();
|
||||
}
|
||||
};
|
||||
|
||||
class AsyncGeneratorObject : public NativeObject
|
||||
{
|
||||
private:
|
||||
enum AsyncGeneratorObjectSlots {
|
||||
Slot_State = 0,
|
||||
Slot_Generator,
|
||||
Slot_QueueOrRequest,
|
||||
Slots
|
||||
};
|
||||
|
||||
enum State {
|
||||
State_SuspendedStart,
|
||||
State_SuspendedYield,
|
||||
State_Executing,
|
||||
State_Completed
|
||||
};
|
||||
|
||||
State state() const {
|
||||
return static_cast<State>(getFixedSlot(Slot_State).toInt32());
|
||||
}
|
||||
void setState(State state_) {
|
||||
setFixedSlot(Slot_State, Int32Value(state_));
|
||||
}
|
||||
|
||||
void setGenerator(const Value& value) {
|
||||
setFixedSlot(Slot_Generator, value);
|
||||
}
|
||||
|
||||
// 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
|
||||
// array is created and requests are pushed into it, and the array is
|
||||
// stored to the slot.
|
||||
|
||||
bool isSingleQueue() const {
|
||||
return getFixedSlot(Slot_QueueOrRequest).isNull() ||
|
||||
getFixedSlot(Slot_QueueOrRequest).toObject().is<AsyncGeneratorRequest>();
|
||||
}
|
||||
bool isSingleQueueEmpty() const {
|
||||
return getFixedSlot(Slot_QueueOrRequest).isNull();
|
||||
}
|
||||
void setSingleQueueRequest(AsyncGeneratorRequest* request) {
|
||||
setFixedSlot(Slot_QueueOrRequest, ObjectValue(*request));
|
||||
}
|
||||
void clearSingleQueueRequest() {
|
||||
setFixedSlot(Slot_QueueOrRequest, NullHandleValue);
|
||||
}
|
||||
AsyncGeneratorRequest* singleQueueRequest() const {
|
||||
return &getFixedSlot(Slot_QueueOrRequest).toObject().as<AsyncGeneratorRequest>();
|
||||
}
|
||||
|
||||
ArrayObject* queue() const {
|
||||
return &getFixedSlot(Slot_QueueOrRequest).toObject().as<ArrayObject>();
|
||||
}
|
||||
void setQueue(JSObject* queue_) {
|
||||
setFixedSlot(Slot_QueueOrRequest, ObjectValue(*queue_));
|
||||
}
|
||||
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
static AsyncGeneratorObject*
|
||||
create(JSContext* cx, HandleFunction asyncGen, HandleValue generatorVal);
|
||||
|
||||
bool isSuspendedStart() const {
|
||||
return state() == State_SuspendedStart;
|
||||
}
|
||||
bool isSuspendedYield() const {
|
||||
return state() == State_SuspendedYield;
|
||||
}
|
||||
bool isExecuting() const {
|
||||
return state() == State_Executing;
|
||||
}
|
||||
bool isCompleted() const {
|
||||
return state() == State_Completed;
|
||||
}
|
||||
|
||||
void setSuspendedStart() {
|
||||
setState(State_SuspendedStart);
|
||||
}
|
||||
void setSuspendedYield() {
|
||||
setState(State_SuspendedYield);
|
||||
}
|
||||
void setExecuting() {
|
||||
setState(State_Executing);
|
||||
}
|
||||
void setCompleted() {
|
||||
setState(State_Completed);
|
||||
}
|
||||
|
||||
JS::Value generatorVal() const {
|
||||
return getFixedSlot(Slot_Generator);
|
||||
}
|
||||
GeneratorObject* generatorObj() const {
|
||||
return &getFixedSlot(Slot_Generator).toObject().as<GeneratorObject>();
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
enqueueRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
|
||||
Handle<AsyncGeneratorRequest*> request);
|
||||
|
||||
static AsyncGeneratorRequest*
|
||||
dequeueRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj);
|
||||
|
||||
static AsyncGeneratorRequest*
|
||||
peekRequest(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj);
|
||||
|
||||
bool isQueueEmpty() const {
|
||||
if (isSingleQueue())
|
||||
return isSingleQueueEmpty();
|
||||
return queue()->length() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
AsyncGeneratorResumeNext(JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* vm_AsyncIteration_h */
|
|
@ -31,8 +31,6 @@
|
|||
macro(as, as, "as") \
|
||||
macro(Async, Async, "Async") \
|
||||
macro(AsyncFunction, AsyncFunction, "AsyncFunction") \
|
||||
macro(AsyncGenerator, AsyncGenerator, "AsyncGenerator") \
|
||||
macro(AsyncGeneratorFunction, AsyncGeneratorFunction, "AsyncGeneratorFunction") \
|
||||
macro(AsyncWrapped, AsyncWrapped, "AsyncWrapped") \
|
||||
macro(async, async, "async") \
|
||||
macro(await, await, "await") \
|
||||
|
@ -321,7 +319,6 @@
|
|||
macro(star, star, "*") \
|
||||
macro(starDefaultStar, starDefaultStar, "*default*") \
|
||||
macro(StarGeneratorNext, StarGeneratorNext, "StarGeneratorNext") \
|
||||
macro(StarGeneratorReturn, StarGeneratorReturn, "StarGeneratorReturn") \
|
||||
macro(StarGeneratorThrow, StarGeneratorThrow, "StarGeneratorThrow") \
|
||||
macro(startTimestamp, startTimestamp, "startTimestamp") \
|
||||
macro(state, state, "state") \
|
||||
|
|
|
@ -98,10 +98,6 @@ class GlobalObject : public NativeObject
|
|||
STAR_GENERATOR_FUNCTION,
|
||||
ASYNC_FUNCTION_PROTO,
|
||||
ASYNC_FUNCTION,
|
||||
ASYNC_ITERATOR_PROTO,
|
||||
ASYNC_GENERATOR,
|
||||
ASYNC_GENERATOR_FUNCTION,
|
||||
ASYNC_GENERATOR_PROTO,
|
||||
MAP_ITERATOR_PROTO,
|
||||
SET_ITERATOR_PROTO,
|
||||
COLLATOR_PROTO,
|
||||
|
@ -633,30 +629,6 @@ class GlobalObject : public NativeObject
|
|||
return getOrCreateObject(cx, global, ASYNC_FUNCTION, initAsyncFunction);
|
||||
}
|
||||
|
||||
static NativeObject*
|
||||
getOrCreateAsyncIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_ITERATOR_PROTO,
|
||||
initAsyncGenerators));
|
||||
}
|
||||
|
||||
static NativeObject*
|
||||
getOrCreateAsyncGenerator(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_GENERATOR,
|
||||
initAsyncGenerators));
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
getOrCreateAsyncGeneratorFunction(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
return getOrCreateObject(cx, global, ASYNC_GENERATOR_FUNCTION, initAsyncGenerators);
|
||||
}
|
||||
|
||||
static NativeObject*
|
||||
getOrCreateAsyncGeneratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_GENERATOR_PROTO,
|
||||
initAsyncGenerators));
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
getOrCreateMapIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
|
||||
return getOrCreateObject(cx, global, MAP_ITERATOR_PROTO, initMapIteratorProto);
|
||||
|
@ -803,8 +775,6 @@ class GlobalObject : public NativeObject
|
|||
|
||||
static bool initAsyncFunction(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
||||
static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
||||
// Implemented in builtin/MapObject.cpp.
|
||||
static bool initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
|
||||
static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "jit/Ion.h"
|
||||
#include "jit/IonAnalysis.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
#include "vm/Opcodes.h"
|
||||
|
@ -1923,6 +1922,7 @@ CASE(EnableInterruptsPseudoOpcode)
|
|||
/* Various 1-byte no-ops. */
|
||||
CASE(JSOP_NOP)
|
||||
CASE(JSOP_NOP_DESTRUCTURING)
|
||||
CASE(JSOP_UNUSED192)
|
||||
CASE(JSOP_UNUSED210)
|
||||
CASE(JSOP_UNUSED211)
|
||||
CASE(JSOP_UNUSED220)
|
||||
|
@ -3566,18 +3566,6 @@ CASE(JSOP_TOASYNC)
|
|||
}
|
||||
END_CASE(JSOP_TOASYNC)
|
||||
|
||||
CASE(JSOP_TOASYNCGEN)
|
||||
{
|
||||
ReservedRooted<JSFunction*> unwrapped(&rootFunction0,
|
||||
®S.sp[-1].toObject().as<JSFunction>());
|
||||
JSObject* wrapped = WrapAsyncGenerator(cx, unwrapped);
|
||||
if (!wrapped)
|
||||
goto error;
|
||||
|
||||
REGS.sp[-1].setObject(*wrapped);
|
||||
}
|
||||
END_CASE(JSOP_TOASYNCGEN)
|
||||
|
||||
CASE(JSOP_SETFUNNAME)
|
||||
{
|
||||
MOZ_ASSERT(REGS.stackDepth() >= 2);
|
||||
|
|
|
@ -1967,15 +1967,7 @@
|
|||
* Stack: this => this
|
||||
*/ \
|
||||
macro(JSOP_CHECKTHISREINIT,191,"checkthisreinit",NULL,1, 1, 1, JOF_BYTE) \
|
||||
/*
|
||||
* Pops the top of stack value as 'unwrapped', converts it to async
|
||||
* generator 'wrapped', and pushes 'wrapped' back on the stack.
|
||||
* Category: Statements
|
||||
* Type: Generator
|
||||
* Operands:
|
||||
* Stack: unwrapped => wrapped
|
||||
*/ \
|
||||
macro(JSOP_TOASYNCGEN, 192, "toasyncgen", NULL, 1, 1, 1, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED192, 192,"unused192", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
\
|
||||
/*
|
||||
* Pops the top two values on the stack as 'propval' and 'obj', pushes
|
||||
|
|
Загрузка…
Ссылка в новой задаче