зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1331092 - Part 9: Implement for-await-of. r=shu
This commit is contained in:
Родитель
6cbf77e2ff
Коммит
7361458021
|
@ -2004,11 +2004,15 @@ class ForOfLoopControl : public LoopControl
|
|||
|
||||
bool allowSelfHosted_;
|
||||
|
||||
IteratorKind iterKind_;
|
||||
|
||||
public:
|
||||
ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth, bool allowSelfHosted)
|
||||
ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth, bool allowSelfHosted,
|
||||
IteratorKind iterKind)
|
||||
: LoopControl(bce, StatementKind::ForOfLoop),
|
||||
iterDepth_(iterDepth),
|
||||
allowSelfHosted_(allowSelfHosted)
|
||||
allowSelfHosted_(allowSelfHosted),
|
||||
iterKind_(iterKind)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2064,7 +2068,7 @@ class ForOfLoopControl : public LoopControl
|
|||
bool emitIteratorClose(BytecodeEmitter* bce,
|
||||
CompletionKind completionKind = CompletionKind::Normal) {
|
||||
ptrdiff_t start = bce->offset();
|
||||
if (!bce->emitIteratorClose(IteratorKind::Sync, completionKind, allowSelfHosted_))
|
||||
if (!bce->emitIteratorClose(iterKind_, completionKind, allowSelfHosted_))
|
||||
return false;
|
||||
ptrdiff_t end = bce->offset();
|
||||
return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
|
||||
|
@ -5222,7 +5226,8 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitIteratorNext(ParseNode* pn, bool allowSelfHosted /* = false */)
|
||||
BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = IteratorKind::Sync */,
|
||||
bool allowSelfHosted /* = false */)
|
||||
{
|
||||
MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
|
||||
".next() iteration is prohibited in self-hosted code because it "
|
||||
|
@ -5236,6 +5241,12 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, bool allowSelfHosted /* = false
|
|||
return false;
|
||||
if (!emitCall(JSOP_CALL, 0, pn)) // ... RESULT
|
||||
return false;
|
||||
|
||||
if (iterKind == IteratorKind::Async) {
|
||||
if (!emitAwait()) // ... RESULT
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
|
||||
return false;
|
||||
checkTypeSet(JSOP_CALL);
|
||||
|
@ -6874,7 +6885,7 @@ BytecodeEmitter::emitSpread(bool allowSelfHosted)
|
|||
|
||||
if (!emitDupAt(2)) // ITER ARR I ITER
|
||||
return false;
|
||||
if (!emitIteratorNext(nullptr, allowSelfHosted)) // ITER ARR I RESULT
|
||||
if (!emitIteratorNext(nullptr, IteratorKind::Sync, allowSelfHosted)) // ITER ARR I RESULT
|
||||
return false;
|
||||
if (!emit1(JSOP_DUP)) // ITER ARR I RESULT RESULT
|
||||
return false;
|
||||
|
@ -6974,6 +6985,13 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
MOZ_ASSERT(forOfHead->isKind(PNK_FOROF));
|
||||
MOZ_ASSERT(forOfHead->isArity(PN_TERNARY));
|
||||
|
||||
unsigned iflags = forOfLoop->pn_iflags;
|
||||
IteratorKind iterKind = (iflags & JSITER_FORAWAITOF)
|
||||
? IteratorKind::Async
|
||||
: IteratorKind::Sync;
|
||||
MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox());
|
||||
MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()->isAsync());
|
||||
|
||||
ParseNode* forHeadExpr = forOfHead->pn_kid3;
|
||||
|
||||
// Certain builtins (e.g. Array.from) are implemented in self-hosting
|
||||
|
@ -6989,8 +7007,13 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
// Evaluate the expression being iterated.
|
||||
if (!emitTree(forHeadExpr)) // ITERABLE
|
||||
return false;
|
||||
if (!emitIterator()) // ITER
|
||||
return false;
|
||||
if (iterKind == IteratorKind::Async) {
|
||||
if (!emitAsyncIterator()) // ITER
|
||||
return false;
|
||||
} else {
|
||||
if (!emitIterator()) // ITER
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t iterDepth = stackDepth;
|
||||
|
||||
|
@ -7001,7 +7024,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
if (!emit1(JSOP_UNDEFINED)) // ITER RESULT UNDEF
|
||||
return false;
|
||||
|
||||
ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter);
|
||||
ForOfLoopControl loopInfo(this, iterDepth, allowSelfHostedIter, iterKind);
|
||||
|
||||
// Annotate so IonMonkey can find the loop-closing jump.
|
||||
unsigned noteIndex;
|
||||
|
@ -7097,7 +7120,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte
|
|||
if (!emitDupAt(1)) // ITER UNDEF ITER
|
||||
return false;
|
||||
|
||||
if (!emitIteratorNext(forOfHead, allowSelfHostedIter)) // ITER UNDEF RESULT
|
||||
if (!emitIteratorNext(forOfHead, iterKind, allowSelfHostedIter)) // ITER UNDEF RESULT
|
||||
return false;
|
||||
|
||||
if (!emit1(JSOP_SWAP)) // ITER RESULT UNDEF
|
||||
|
|
|
@ -701,7 +701,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
|
||||
// Pops iterator from the top of the stack. Pushes the result of |.next()|
|
||||
// onto the stack.
|
||||
MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, bool allowSelfHosted = false);
|
||||
MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, IteratorKind kind = IteratorKind::Sync,
|
||||
bool allowSelfHosted = false);
|
||||
MOZ_MUST_USE bool emitIteratorClose(IteratorKind iterKind = IteratorKind::Sync,
|
||||
CompletionKind completionKind = CompletionKind::Normal,
|
||||
bool allowSelfHosted = false);
|
||||
|
|
|
@ -5861,6 +5861,7 @@ Parser<ParseHandler>::matchInOrOf(bool* isForInp, bool* isForOfp)
|
|||
template <class ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
|
||||
IteratorKind iterKind,
|
||||
ParseNodeKind* forHeadKind,
|
||||
Node* forInitialPart,
|
||||
Maybe<ParseContext::Scope>& forLoopLexicalScope,
|
||||
|
@ -5951,6 +5952,11 @@ Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
|
|||
if (!matchInOrOf(&isForIn, &isForOf))
|
||||
return false;
|
||||
|
||||
if (iterKind == IteratorKind::Async && !isForOf) {
|
||||
error(JSMSG_FOR_AWAIT_NOT_OF);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we don't encounter 'in'/'of', we have a for(;;) loop. We've handled
|
||||
// the init expression; the caller handles the rest. Allow the Operand
|
||||
// modifier when regetting: Operand must be used to examine the ';' in
|
||||
|
@ -6024,6 +6030,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
ParseContext::Statement stmt(pc, StatementKind::ForLoop);
|
||||
|
||||
bool isForEach = false;
|
||||
IteratorKind iterKind = IteratorKind::Sync;
|
||||
unsigned iflags = 0;
|
||||
|
||||
if (allowsForEachIn()) {
|
||||
|
@ -6039,6 +6046,19 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
if (pc->isAsync()) {
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_AWAIT))
|
||||
return null();
|
||||
|
||||
if (matched) {
|
||||
iflags |= JSITER_FORAWAITOF;
|
||||
iterKind = IteratorKind::Async;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
|
||||
|
||||
// PNK_FORHEAD, PNK_FORIN, or PNK_FOROF depending on the loop type.
|
||||
|
@ -6076,7 +6096,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
//
|
||||
// In either case the subsequent token can be consistently accessed using
|
||||
// TokenStream::None semantics.
|
||||
if (!forHeadStart(yieldHandling, &headKind, &startNode, forLoopLexicalScope,
|
||||
if (!forHeadStart(yieldHandling, iterKind, &headKind, &startNode, forLoopLexicalScope,
|
||||
&iteratedExpr))
|
||||
{
|
||||
return null();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include "jsiter.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
|
@ -1175,6 +1176,7 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
|
||||
Node forStatement(YieldHandling yieldHandling);
|
||||
bool forHeadStart(YieldHandling yieldHandling,
|
||||
IteratorKind iterKind,
|
||||
ParseNodeKind* forHeadKind,
|
||||
Node* forInitialPart,
|
||||
mozilla::Maybe<ParseContext::Scope>& forLetImpliedScope,
|
||||
|
|
|
@ -593,6 +593,7 @@ MSG_DEF(JSMSG_RETURN_NOT_CALLABLE, 0, JSEXN_TYPEERR, "property 'return' of i
|
|||
MSG_DEF(JSMSG_ITERATOR_NO_THROW, 0, JSEXN_TYPEERR, "iterator does not have a 'throw' method")
|
||||
|
||||
// Async Iteration
|
||||
MSG_DEF(JSMSG_FOR_AWAIT_NOT_OF, 0, JSEXN_TYPEERR, "'for await' loop should be used with 'of'")
|
||||
MSG_DEF(JSMSG_NOT_AN_ASYNC_GENERATOR, 0, JSEXN_TYPEERR, "Not an async generator")
|
||||
MSG_DEF(JSMSG_NOT_AN_ASYNC_ITERATOR, 0, JSEXN_TYPEERR, "Not an async from sync iterator")
|
||||
MSG_DEF(JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.asyncIterator]() returned a non-object value")
|
||||
|
|
|
@ -975,6 +975,7 @@ IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
|
|||
#define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
|
||||
#define JSITER_SYMBOLS 0x20 /* also include symbol property keys */
|
||||
#define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
|
||||
#define JSITER_FORAWAITOF 0x80 /* for-await-of */
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
RunningWithTrustedPrincipals(JSContext* cx);
|
||||
|
|
Загрузка…
Ссылка в новой задаче