mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 15:58:39 +09:00
parent
06b3cb6ccd
commit
9379133c2d
6 changed files with 59 additions and 11 deletions
|
|
@ -2029,12 +2029,16 @@ 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),
|
||||
numYieldsAtBeginCodeNeedingIterClose_(UINT32_MAX),
|
||||
allowSelfHosted_(allowSelfHosted)
|
||||
allowSelfHosted_(allowSelfHosted),
|
||||
iterKind_(iterKind)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -2118,7 +2122,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);
|
||||
|
|
@ -5246,7 +5250,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 "
|
||||
|
|
@ -5260,6 +5265,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);
|
||||
|
|
@ -7099,7 +7110,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;
|
||||
|
|
@ -7199,6 +7210,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
|
||||
|
|
@ -7214,8 +7232,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;
|
||||
|
||||
|
|
@ -7226,7 +7249,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;
|
||||
|
|
@ -7322,7 +7345,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
|
||||
|
|
|
|||
|
|
@ -715,7 +715,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);
|
||||
|
|
|
|||
|
|
@ -5972,6 +5972,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,
|
||||
|
|
@ -6062,6 +6063,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
|
||||
|
|
@ -6135,6 +6141,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
ParseContext::Statement stmt(pc, StatementKind::ForLoop);
|
||||
|
||||
bool isForEach = false;
|
||||
IteratorKind iterKind = IteratorKind::Sync;
|
||||
unsigned iflags = 0;
|
||||
|
||||
if (allowsForEachIn()) {
|
||||
|
|
@ -6149,6 +6156,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.
|
||||
|
|
@ -6186,7 +6206,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();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/Array.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "jsiter.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
|
|
@ -1196,6 +1197,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,
|
||||
|
|
|
|||
|
|
@ -595,6 +595,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")
|
||||
|
|
|
|||
|
|
@ -948,6 +948,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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue