Instead of using plain objects as Iterator records, causes confusion
about the object itself actually being its [[Iterator]] slot, and
requires non-standard type conversion shenanigans fpr the [[NextValue]]
and [[Done]] internal slots, implement a proper Iterator record struct
and use it throughout.
Also annotate the remaining Iterator AOs with spec comments while we're
here.
This is another major milestone on our journey towards removing global
VM exception state :^)
Does pretty much exactly what it says on the tin: updating
ASTNode::execute() to return a Completion instead of a plain value. This
will *also* allow us to eventually remove the non-standard unwinding
mechanism and purely rely on the various completion types.
In the end this is a nicer API than having separate has_{value,target}()
and having to check those first, and then making another Optional from
the unwrapped value:
completion.has_value() ? completion.value() : Optional<Value> {}
// ^^^^^^^^^^^^^^^^^^
// Implicit creation of non-empty Optional<Value>
This way we need to unwrap the optional ourselves, but can easily pass
it to something else as well.
This is in anticipation of the AST using completions :^)
The spec has a note stating that resolve binding will always return a
reference whose [[ReferencedName]] field is name. However this is not
correct as the underlying method GetIdentifierReference may throw on
env.HasBinding(name) thus it can throw. However, there are some
scenarios where it cannot throw because the reference is known to exist
in that case we use MUST with a comment.
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
And use it to _correctly_ implement state saving for generators.
Prior to this, we were capturing the caller frame, which is completely
irrelevant to the generator frame.
To support situations like this:
function foo() { throw 1; }
try {
foo();
} catch (e) {
}
Each unwind context now keeps track of its origin executable.
When an exception is thrown, we return from run() immediately if the
nearest unwind context isn't in the current executable.
This causes a natural unwind to the point where we find the
catch/finally block(s) to jump into.
We were missing some "break" statements, causing us to actually finish
executing everything within "try" blocks before actually jumping to the
"catch" and/or "finally" blocks.
This is a specialized string table for storing identifiers only.
Identifiers are always FlyStrings, which makes many common operations
faster by allowing O(1) comparison.