Backed out changeset 852edb03db18 (bug 1905435) for causing multiple failures. CLOSED...
[gecko.git] / js / src / frontend / ForOfLoopControl.h
blob5ffda9a8ba8d8559c53127665cc3dd7062c3f452
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
20 namespace js {
21 namespace frontend {
23 struct BytecodeEmitter;
24 class BytecodeOffset;
25 class EmitterScope;
27 class ForOfLoopControl : public LoopControl {
28 // The stack depth of the iterator.
29 int32_t iterDepth_;
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.
43 // for (x of y) {
44 // // Operations for iterator (IteratorNext etc) are outside of
45 // // try-block.
46 // try {
47 // ...
48 // if (...) {
49 // // Before non-local jump, close iterator.
50 // CloseIter(iter, CompletionKind::Return); // Covered by
51 // return; // trynote
52 // }
53 // ...
54 // } catch (e) {
55 // // When propagating an exception, we swallow any exceptions
56 // // thrown while closing the iterator.
57 // CloseIter(iter, CompletionKind::Throw);
58 // throw e;
59 // }
60 // }
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_;
71 public:
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(
79 BytecodeEmitter* bce,
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);
89 template <>
90 inline bool NestableControl::is<ForOfLoopControl>() const {
91 return kind_ == StatementKind::ForOfLoop;
94 } /* namespace frontend */
95 } /* namespace js */
97 #endif /* frontend_ForOfLoopControl_h */