1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef frontend_ForOfLoopControl_h
8 #define frontend_ForOfLoopControl_h
10 #include "mozilla/Maybe.h" // mozilla::Maybe
12 #include <stdint.h> // int32_t, uint32_t
14 #include "frontend/BytecodeControlStructures.h" // NestableControl, LoopControl
15 #include "frontend/IteratorKind.h" // IteratorKind
16 #include "frontend/SelfHostedIter.h" // SelfHostedIter
17 #include "frontend/TryEmitter.h" // TryEmitter
18 #include "vm/CompletionKind.h" // CompletionKind
23 struct BytecodeEmitter
;
27 class ForOfLoopControl
: public LoopControl
{
28 // The stack depth of the iterator.
31 // For-of loops, when throwing from non-iterator code (i.e. from the body
32 // or from evaluating the LHS of the loop condition), need to call
33 // IteratorClose. This is done by enclosing the body of the loop with
34 // try-catch and calling IteratorClose in the `catch` block.
36 // If IteratorClose itself throws, we must not re-call
37 // IteratorClose. Since non-local jumps like break and return call
38 // IteratorClose, whenever a non-local jump is emitted, we must
39 // prevent the catch block from catching any exception thrown from
40 // IteratorClose. We do this by wrapping the non-local jump in a
41 // ForOfIterClose try-note.
44 // // Operations for iterator (IteratorNext etc) are outside of
49 // // Before non-local jump, close iterator.
50 // CloseIter(iter, CompletionKind::Return); // Covered by
55 // // When propagating an exception, we swallow any exceptions
56 // // thrown while closing the iterator.
57 // CloseIter(iter, CompletionKind::Throw);
61 mozilla::Maybe
<TryEmitter
> tryCatch_
;
63 // Used to track if any yields were emitted between calls to to
64 // emitBeginCodeNeedingIteratorClose and emitEndCodeNeedingIteratorClose.
65 uint32_t numYieldsAtBeginCodeNeedingIterClose_
;
67 SelfHostedIter selfHostedIter_
;
69 IteratorKind iterKind_
;
72 ForOfLoopControl(BytecodeEmitter
* bce
, int32_t iterDepth
,
73 SelfHostedIter selfHostedIter
, IteratorKind iterKind
);
75 [[nodiscard
]] bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter
* bce
);
76 [[nodiscard
]] bool emitEndCodeNeedingIteratorClose(BytecodeEmitter
* bce
);
78 [[nodiscard
]] bool emitIteratorCloseInInnermostScopeWithTryNote(
80 CompletionKind completionKind
= CompletionKind::Normal
);
81 [[nodiscard
]] bool emitIteratorCloseInScope(
82 BytecodeEmitter
* bce
, EmitterScope
& currentScope
,
83 CompletionKind completionKind
= CompletionKind::Normal
);
85 [[nodiscard
]] bool emitPrepareForNonLocalJumpFromScope(
86 BytecodeEmitter
* bce
, EmitterScope
& currentScope
, bool isTarget
,
87 BytecodeOffset
* tryNoteStart
);
90 inline bool NestableControl::is
<ForOfLoopControl
>() const {
91 return kind_
== StatementKind::ForOfLoop
;
94 } /* namespace frontend */
97 #endif /* frontend_ForOfLoopControl_h */