2020-03-07 18:42:11 +00:00
|
|
|
/*
|
2024-02-03 19:16:02 +00:00
|
|
|
* Copyright (c) 2020-2024, Andreas Kling <kling@serenityos.org>
|
2022-01-02 20:37:50 +00:00
|
|
|
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
|
2022-01-16 22:51:28 +00:00
|
|
|
* Copyright (c) 2021-2022, David Tuin <davidot@serenityos.org>
|
2020-03-07 18:42:11 +00:00
|
|
|
*
|
2021-04-22 08:24:48 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-03-07 18:42:11 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
#include <AK/ByteString.h>
|
2023-01-09 00:23:00 +00:00
|
|
|
#include <AK/DeprecatedFlyString.h>
|
2020-03-21 00:29:00 +00:00
|
|
|
#include <AK/HashMap.h>
|
2021-05-29 11:33:19 +00:00
|
|
|
#include <AK/OwnPtr.h>
|
2020-03-18 10:23:53 +00:00
|
|
|
#include <AK/RefPtr.h>
|
2021-05-29 11:33:19 +00:00
|
|
|
#include <AK/Variant.h>
|
2020-03-12 11:22:13 +00:00
|
|
|
#include <AK/Vector.h>
|
2022-02-12 16:24:08 +00:00
|
|
|
#include <LibJS/Bytecode/CodeGenerationError.h>
|
2023-11-10 16:55:34 +00:00
|
|
|
#include <LibJS/Bytecode/Executable.h>
|
2023-06-28 16:17:13 +00:00
|
|
|
#include <LibJS/Bytecode/IdentifierTable.h>
|
2024-02-03 19:16:02 +00:00
|
|
|
#include <LibJS/Bytecode/Operand.h>
|
2020-03-07 18:42:11 +00:00
|
|
|
#include <LibJS/Forward.h>
|
2022-02-04 15:22:29 +00:00
|
|
|
#include <LibJS/Heap/Handle.h>
|
2022-04-19 22:06:45 +00:00
|
|
|
#include <LibJS/Runtime/ClassFieldDefinition.h>
|
2022-01-02 20:37:50 +00:00
|
|
|
#include <LibJS/Runtime/Completion.h>
|
2021-10-06 23:06:21 +00:00
|
|
|
#include <LibJS/Runtime/EnvironmentCoordinate.h>
|
2021-11-10 21:16:07 +00:00
|
|
|
#include <LibJS/Runtime/FunctionKind.h>
|
2022-11-23 13:18:38 +00:00
|
|
|
#include <LibJS/Runtime/ModuleRequest.h>
|
2021-10-24 14:01:24 +00:00
|
|
|
#include <LibJS/Runtime/PropertyKey.h>
|
2021-09-14 02:26:31 +00:00
|
|
|
#include <LibJS/Runtime/Reference.h>
|
2020-03-16 13:20:30 +00:00
|
|
|
#include <LibJS/Runtime/Value.h>
|
2020-12-28 17:15:22 +00:00
|
|
|
#include <LibJS/SourceRange.h>
|
2021-07-29 14:34:37 +00:00
|
|
|
#include <LibRegex/Regex.h>
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
namespace JS {
|
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
class Declaration;
|
|
|
|
class ClassDeclaration;
|
2020-06-04 12:48:36 +00:00
|
|
|
class FunctionDeclaration;
|
2021-05-29 11:33:19 +00:00
|
|
|
class Identifier;
|
2021-09-17 23:11:32 +00:00
|
|
|
class MemberExpression;
|
2021-09-22 10:44:56 +00:00
|
|
|
class VariableDeclaration;
|
2020-04-13 14:42:54 +00:00
|
|
|
|
2020-03-18 10:23:53 +00:00
|
|
|
template<class T, class... Args>
|
|
|
|
static inline NonnullRefPtr<T>
|
2020-12-28 17:15:22 +00:00
|
|
|
create_ast_node(SourceRange range, Args&&... args)
|
2020-03-18 10:23:53 +00:00
|
|
|
{
|
2022-11-27 11:32:05 +00:00
|
|
|
return adopt_ref(*new T(move(range), forward<Args>(args)...));
|
2020-03-18 10:23:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class ASTNode : public RefCounted<ASTNode> {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2022-03-14 16:25:06 +00:00
|
|
|
virtual ~ASTNode() = default;
|
2022-11-27 11:33:02 +00:00
|
|
|
|
|
|
|
// NOTE: This is here to stop ASAN complaining about mismatch between new/delete sizes in ASTNodeWithTailArray.
|
|
|
|
void operator delete(void* ptr) { ::operator delete(ptr); }
|
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const;
|
2020-03-07 18:42:11 +00:00
|
|
|
virtual void dump(int indent) const;
|
|
|
|
|
2022-11-24 14:38:52 +00:00
|
|
|
[[nodiscard]] SourceRange source_range() const;
|
2023-07-27 12:40:01 +00:00
|
|
|
UnrealizedSourceRange unrealized_source_range() const
|
|
|
|
{
|
|
|
|
return { m_source_code, m_start_offset, m_end_offset };
|
|
|
|
}
|
2022-11-27 00:15:37 +00:00
|
|
|
u32 start_offset() const { return m_start_offset; }
|
2023-05-28 06:28:43 +00:00
|
|
|
u32 end_offset() const { return m_end_offset; }
|
|
|
|
|
|
|
|
SourceCode const& source_code() const { return *m_source_code; }
|
2022-11-24 14:38:52 +00:00
|
|
|
|
|
|
|
void set_end_offset(Badge<Parser>, u32 end_offset) { m_end_offset = end_offset; }
|
2020-12-28 17:15:22 +00:00
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString class_name() const;
|
2021-01-17 08:21:15 +00:00
|
|
|
|
2021-06-13 09:23:23 +00:00
|
|
|
template<typename T>
|
|
|
|
bool fast_is() const = delete;
|
|
|
|
|
|
|
|
virtual bool is_new_expression() const { return false; }
|
|
|
|
virtual bool is_member_expression() const { return false; }
|
|
|
|
virtual bool is_super_expression() const { return false; }
|
2021-10-07 10:05:13 +00:00
|
|
|
virtual bool is_function_expression() const { return false; }
|
|
|
|
virtual bool is_class_expression() const { return false; }
|
2021-06-13 09:23:23 +00:00
|
|
|
virtual bool is_expression_statement() const { return false; }
|
|
|
|
virtual bool is_identifier() const { return false; }
|
2022-03-05 22:49:37 +00:00
|
|
|
virtual bool is_private_identifier() const { return false; }
|
2021-06-13 09:23:23 +00:00
|
|
|
virtual bool is_scope_node() const { return false; }
|
|
|
|
virtual bool is_program() const { return false; }
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_class_declaration() const { return false; }
|
2021-10-07 21:07:52 +00:00
|
|
|
virtual bool is_function_declaration() const { return false; }
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_variable_declaration() const { return false; }
|
|
|
|
virtual bool is_import_call() const { return false; }
|
|
|
|
virtual bool is_array_expression() const { return false; }
|
|
|
|
virtual bool is_object_expression() const { return false; }
|
|
|
|
virtual bool is_string_literal() const { return false; }
|
|
|
|
virtual bool is_update_expression() const { return false; }
|
|
|
|
virtual bool is_call_expression() const { return false; }
|
|
|
|
virtual bool is_labelled_statement() const { return false; }
|
|
|
|
virtual bool is_iteration_statement() const { return false; }
|
|
|
|
virtual bool is_class_method() const { return false; }
|
2021-06-13 09:23:23 +00:00
|
|
|
|
2020-03-07 18:42:11 +00:00
|
|
|
protected:
|
LibJS: Reduce AST memory usage by shrink-wrapping source range info
Before this change, each AST node had a 64-byte SourceRange member.
This SourceRange had the following layout:
filename: StringView (16 bytes)
start: Position (24 bytes)
end: Position (24 bytes)
The Position structs have { line, column, offset }, all members size_t.
To reduce memory consumption, AST nodes now only store the following:
source_code: NonnullRefPtr<SourceCode> (8 bytes)
start_offset: u32 (4 bytes)
end_offset: u32 (4 bytes)
SourceCode is a new ref-counted data structure that keeps the filename
and original parsed source code in a single location, and all AST nodes
have a pointer to it.
The start_offset and end_offset can be turned into (line, column) when
necessary by calling SourceCode::range_from_offsets(). This will walk
the source code string and compute line/column numbers on the fly, so
it's not necessarily fast, but it should be rare since this information
is primarily used for diagnostics and exception stack traces.
With this, ASTNode shrinks from 80 bytes to 32 bytes. This gives us a
~23% reduction in memory usage when loading twitter.com/awesomekling
(330 MiB before, 253 MiB after!) :^)
2022-11-21 16:37:38 +00:00
|
|
|
explicit ASTNode(SourceRange);
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
private:
|
2022-11-26 18:01:55 +00:00
|
|
|
// NOTE: These members are carefully ordered so that `m_start_offset` is packed with the padding after RefCounted::m_ref_count.
|
|
|
|
// This creates a 4-byte padding hole after `m_end_offset` which is used to pack subclasses better.
|
LibJS: Reduce AST memory usage by shrink-wrapping source range info
Before this change, each AST node had a 64-byte SourceRange member.
This SourceRange had the following layout:
filename: StringView (16 bytes)
start: Position (24 bytes)
end: Position (24 bytes)
The Position structs have { line, column, offset }, all members size_t.
To reduce memory consumption, AST nodes now only store the following:
source_code: NonnullRefPtr<SourceCode> (8 bytes)
start_offset: u32 (4 bytes)
end_offset: u32 (4 bytes)
SourceCode is a new ref-counted data structure that keeps the filename
and original parsed source code in a single location, and all AST nodes
have a pointer to it.
The start_offset and end_offset can be turned into (line, column) when
necessary by calling SourceCode::range_from_offsets(). This will walk
the source code string and compute line/column numbers on the fly, so
it's not necessarily fast, but it should be rare since this information
is primarily used for diagnostics and exception stack traces.
With this, ASTNode shrinks from 80 bytes to 32 bytes. This gives us a
~23% reduction in memory usage when loading twitter.com/awesomekling
(330 MiB before, 253 MiB after!) :^)
2022-11-21 16:37:38 +00:00
|
|
|
u32 m_start_offset { 0 };
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<SourceCode const> m_source_code;
|
LibJS: Reduce AST memory usage by shrink-wrapping source range info
Before this change, each AST node had a 64-byte SourceRange member.
This SourceRange had the following layout:
filename: StringView (16 bytes)
start: Position (24 bytes)
end: Position (24 bytes)
The Position structs have { line, column, offset }, all members size_t.
To reduce memory consumption, AST nodes now only store the following:
source_code: NonnullRefPtr<SourceCode> (8 bytes)
start_offset: u32 (4 bytes)
end_offset: u32 (4 bytes)
SourceCode is a new ref-counted data structure that keeps the filename
and original parsed source code in a single location, and all AST nodes
have a pointer to it.
The start_offset and end_offset can be turned into (line, column) when
necessary by calling SourceCode::range_from_offsets(). This will walk
the source code string and compute line/column numbers on the fly, so
it's not necessarily fast, but it should be rare since this information
is primarily used for diagnostics and exception stack traces.
With this, ASTNode shrinks from 80 bytes to 32 bytes. This gives us a
~23% reduction in memory usage when loading twitter.com/awesomekling
(330 MiB before, 253 MiB after!) :^)
2022-11-21 16:37:38 +00:00
|
|
|
u32 m_end_offset { 0 };
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2022-11-27 11:33:02 +00:00
|
|
|
// This is a helper class that packs an array of T after the AST node, all in the same allocation.
|
|
|
|
template<typename Derived, typename Base, typename T>
|
|
|
|
class ASTNodeWithTailArray : public Base {
|
|
|
|
public:
|
|
|
|
virtual ~ASTNodeWithTailArray() override
|
|
|
|
{
|
|
|
|
for (auto& value : tail_span())
|
|
|
|
value.~T();
|
|
|
|
}
|
|
|
|
|
2023-02-05 19:02:54 +00:00
|
|
|
ReadonlySpan<T> tail_span() const { return { tail_data(), tail_size() }; }
|
2022-11-27 11:33:02 +00:00
|
|
|
|
|
|
|
T const* tail_data() const { return reinterpret_cast<T const*>(reinterpret_cast<uintptr_t>(this) + sizeof(Derived)); }
|
|
|
|
size_t tail_size() const { return m_tail_size; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
template<typename ActualDerived = Derived, typename... Args>
|
|
|
|
static NonnullRefPtr<ActualDerived> create(size_t tail_size, SourceRange source_range, Args&&... args)
|
|
|
|
{
|
|
|
|
static_assert(sizeof(ActualDerived) == sizeof(Derived), "This leaf class cannot add more members");
|
|
|
|
static_assert(alignof(ActualDerived) % alignof(T) == 0, "Need padding for tail array");
|
2023-08-08 11:11:33 +00:00
|
|
|
auto* memory = ::operator new(sizeof(ActualDerived) + tail_size * sizeof(T));
|
2022-11-27 11:33:02 +00:00
|
|
|
return adopt_ref(*::new (memory) ActualDerived(move(source_range), forward<Args>(args)...));
|
|
|
|
}
|
|
|
|
|
2023-02-05 19:02:54 +00:00
|
|
|
ASTNodeWithTailArray(SourceRange source_range, ReadonlySpan<T> values)
|
2022-11-27 11:33:02 +00:00
|
|
|
: Base(move(source_range))
|
|
|
|
, m_tail_size(values.size())
|
|
|
|
{
|
|
|
|
VERIFY(values.size() <= NumericLimits<u32>::max());
|
|
|
|
for (size_t i = 0; i < values.size(); ++i)
|
|
|
|
new (&tail_data()[i]) T(values[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
T* tail_data() { return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(this) + sizeof(Derived)); }
|
|
|
|
|
|
|
|
u32 m_tail_size { 0 };
|
|
|
|
};
|
|
|
|
|
2020-03-11 18:27:43 +00:00
|
|
|
class Statement : public ASTNode {
|
2020-05-28 18:09:19 +00:00
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit Statement(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2023-11-10 16:55:34 +00:00
|
|
|
|
2023-11-27 12:23:59 +00:00
|
|
|
Bytecode::Executable* bytecode_executable() const { return m_bytecode_executable; }
|
|
|
|
void set_bytecode_executable(Bytecode::Executable* bytecode_executable) { m_bytecode_executable = make_handle(bytecode_executable); }
|
2023-11-10 16:55:34 +00:00
|
|
|
|
|
|
|
private:
|
2023-11-27 12:23:59 +00:00
|
|
|
Handle<Bytecode::Executable> m_bytecode_executable;
|
2021-09-18 21:01:54 +00:00
|
|
|
};
|
|
|
|
|
2022-01-05 17:54:25 +00:00
|
|
|
// 14.13 Labelled Statements, https://tc39.es/ecma262/#sec-labelled-statements
|
2023-08-13 10:53:46 +00:00
|
|
|
class LabelledStatement final : public Statement {
|
2022-01-05 17:54:25 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
LabelledStatement(SourceRange source_range, DeprecatedFlyString label, NonnullRefPtr<Statement const> labelled_item)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2022-01-05 17:54:25 +00:00
|
|
|
, m_label(move(label))
|
|
|
|
, m_labelled_item(move(labelled_item))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const;
|
2022-01-05 17:54:25 +00:00
|
|
|
|
2023-01-09 00:23:00 +00:00
|
|
|
DeprecatedFlyString const& label() const { return m_label; }
|
|
|
|
DeprecatedFlyString& label() { return m_label; }
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Statement const> const& labelled_item() const { return m_labelled_item; }
|
2022-01-05 17:54:25 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_labelled_statement() const final { return true; }
|
|
|
|
|
2023-01-09 00:23:00 +00:00
|
|
|
DeprecatedFlyString m_label;
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Statement const> m_labelled_item;
|
2022-01-05 17:54:25 +00:00
|
|
|
};
|
|
|
|
|
2021-09-18 21:01:54 +00:00
|
|
|
class LabelableStatement : public Statement {
|
|
|
|
public:
|
|
|
|
using Statement::Statement;
|
2020-12-28 17:15:22 +00:00
|
|
|
|
2023-01-09 00:23:00 +00:00
|
|
|
Vector<DeprecatedFlyString> const& labels() const { return m_labels; }
|
|
|
|
virtual void add_label(DeprecatedFlyString string) { m_labels.append(move(string)); }
|
2020-05-28 18:09:19 +00:00
|
|
|
|
|
|
|
protected:
|
2023-01-09 00:23:00 +00:00
|
|
|
Vector<DeprecatedFlyString> m_labels;
|
2021-09-18 21:01:54 +00:00
|
|
|
};
|
|
|
|
|
LibJS: Replace the custom unwind mechanism with completions :^)
This includes:
- Parsing proper LabelledStatements with try_parse_labelled_statement()
- Removing LabelableStatement
- Implementing the LoopEvaluation semantics via loop_evaluation() in
each IterationStatement subclass; and IterationStatement evaluation
via {For,ForIn,ForOf,ForAwaitOf,While,DoWhile}Statement::execute()
- Updating ReturnStatement, BreakStatement and ContinueStatement to
return the appropriate completion types
- Basically reimplementing TryStatement and SwitchStatement according to
the spec, using completions
- Honoring result completion types in AsyncBlockStart and
OrdinaryCallEvaluateBody
- Removing any uses of the VM unwind mechanism - most importantly,
VM::throw_exception() now exclusively sets an exception and no longer
triggers any unwinding mechanism.
However, we already did a good job updating all of LibWeb and userland
applications to not use it, and the few remaining uses elsewhere don't
rely on unwinding AFAICT.
2022-01-05 18:11:16 +00:00
|
|
|
class IterationStatement : public Statement {
|
2021-09-18 21:01:54 +00:00
|
|
|
public:
|
LibJS: Replace the custom unwind mechanism with completions :^)
This includes:
- Parsing proper LabelledStatements with try_parse_labelled_statement()
- Removing LabelableStatement
- Implementing the LoopEvaluation semantics via loop_evaluation() in
each IterationStatement subclass; and IterationStatement evaluation
via {For,ForIn,ForOf,ForAwaitOf,While,DoWhile}Statement::execute()
- Updating ReturnStatement, BreakStatement and ContinueStatement to
return the appropriate completion types
- Basically reimplementing TryStatement and SwitchStatement according to
the spec, using completions
- Honoring result completion types in AsyncBlockStart and
OrdinaryCallEvaluateBody
- Removing any uses of the VM unwind mechanism - most importantly,
VM::throw_exception() now exclusively sets an exception and no longer
triggers any unwinding mechanism.
However, we already did a good job updating all of LibWeb and userland
applications to not use it, and the few remaining uses elsewhere don't
rely on unwinding AFAICT.
2022-01-05 18:11:16 +00:00
|
|
|
using Statement::Statement;
|
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const;
|
2022-02-13 12:07:38 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
virtual bool is_iteration_statement() const final { return true; }
|
2020-03-11 18:27:43 +00:00
|
|
|
};
|
|
|
|
|
2020-05-03 09:59:00 +00:00
|
|
|
class EmptyStatement final : public Statement {
|
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit EmptyStatement(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-05-03 09:59:00 +00:00
|
|
|
};
|
|
|
|
|
2020-03-11 18:27:43 +00:00
|
|
|
class ErrorStatement final : public Statement {
|
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit ErrorStatement(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-11 18:27:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ExpressionStatement final : public Statement {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ExpressionStatement(SourceRange source_range, NonnullRefPtr<Expression const> expression)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_expression(move(expression))
|
2020-03-11 18:27:43 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-11-01 21:49:25 +00:00
|
|
|
|
2023-07-08 02:48:11 +00:00
|
|
|
Expression const& expression() const { return m_expression; }
|
2020-03-11 18:27:43 +00:00
|
|
|
|
|
|
|
private:
|
2021-06-13 09:23:23 +00:00
|
|
|
virtual bool is_expression_statement() const override { return true; }
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_expression;
|
2020-03-11 18:27:43 +00:00
|
|
|
};
|
|
|
|
|
2022-02-07 12:31:01 +00:00
|
|
|
template<typename Func, typename... Args>
|
2022-10-16 22:06:11 +00:00
|
|
|
concept ThrowCompletionOrVoidFunction = requires(Func func, Args... args) {
|
2023-07-08 02:44:33 +00:00
|
|
|
{
|
|
|
|
func(args...)
|
|
|
|
}
|
|
|
|
-> SameAs<ThrowCompletionOr<void>>;
|
|
|
|
};
|
2022-02-07 12:31:01 +00:00
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
template<typename... Args>
|
2022-02-07 12:31:01 +00:00
|
|
|
class ThrowCompletionOrVoidCallback : public Function<ThrowCompletionOr<void>(Args...)> {
|
2021-09-22 10:44:56 +00:00
|
|
|
public:
|
|
|
|
template<typename CallableType>
|
2022-10-16 22:06:11 +00:00
|
|
|
ThrowCompletionOrVoidCallback(CallableType&& callable)
|
|
|
|
requires(VoidFunction<CallableType, Args...>)
|
2022-02-07 12:31:01 +00:00
|
|
|
: Function<ThrowCompletionOr<void>(Args...)>([callable = forward<CallableType>(callable)](Args... args) {
|
2021-10-03 11:58:52 +00:00
|
|
|
callable(args...);
|
2022-02-07 12:31:01 +00:00
|
|
|
return ThrowCompletionOr<void> {};
|
2021-09-22 10:44:56 +00:00
|
|
|
})
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename CallableType>
|
2022-10-16 22:06:11 +00:00
|
|
|
ThrowCompletionOrVoidCallback(CallableType&& callable)
|
|
|
|
requires(ThrowCompletionOrVoidFunction<CallableType, Args...>)
|
2022-02-07 12:31:01 +00:00
|
|
|
: Function<ThrowCompletionOr<void>(Args...)>(forward<CallableType>(callable))
|
2021-09-22 10:44:56 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
LibJS: Replace the custom unwind mechanism with completions :^)
This includes:
- Parsing proper LabelledStatements with try_parse_labelled_statement()
- Removing LabelableStatement
- Implementing the LoopEvaluation semantics via loop_evaluation() in
each IterationStatement subclass; and IterationStatement evaluation
via {For,ForIn,ForOf,ForAwaitOf,While,DoWhile}Statement::execute()
- Updating ReturnStatement, BreakStatement and ContinueStatement to
return the appropriate completion types
- Basically reimplementing TryStatement and SwitchStatement according to
the spec, using completions
- Honoring result completion types in AsyncBlockStart and
OrdinaryCallEvaluateBody
- Removing any uses of the VM unwind mechanism - most importantly,
VM::throw_exception() now exclusively sets an exception and no longer
triggers any unwinding mechanism.
However, we already did a good job updating all of LibWeb and userland
applications to not use it, and the few remaining uses elsewhere don't
rely on unwinding AFAICT.
2022-01-05 18:11:16 +00:00
|
|
|
class ScopeNode : public Statement {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
|
|
|
template<typename T, typename... Args>
|
2020-12-28 17:15:22 +00:00
|
|
|
T& append(SourceRange range, Args&&... args)
|
2020-03-07 18:42:11 +00:00
|
|
|
{
|
2020-12-28 17:15:22 +00:00
|
|
|
auto child = create_ast_node<T>(range, forward<Args>(args)...);
|
2020-03-07 18:42:11 +00:00
|
|
|
m_children.append(move(child));
|
2023-03-06 13:17:01 +00:00
|
|
|
return static_cast<T&>(*m_children.last());
|
2020-03-07 18:42:11 +00:00
|
|
|
}
|
2023-02-19 21:07:52 +00:00
|
|
|
void append(NonnullRefPtr<Statement const> child)
|
2020-03-11 18:27:43 +00:00
|
|
|
{
|
|
|
|
m_children.append(move(child));
|
|
|
|
}
|
2020-03-07 18:42:11 +00:00
|
|
|
|
2022-11-26 19:45:06 +00:00
|
|
|
void shrink_to_fit()
|
|
|
|
{
|
|
|
|
m_children.shrink_to_fit();
|
|
|
|
m_lexical_declarations.shrink_to_fit();
|
|
|
|
m_var_declarations.shrink_to_fit();
|
|
|
|
m_functions_hoistable_with_annexB_extension.shrink_to_fit();
|
|
|
|
}
|
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<Statement const>> const& children() const { return m_children; }
|
2020-03-07 18:42:11 +00:00
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-07 18:42:11 +00:00
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
void add_var_scoped_declaration(NonnullRefPtr<Declaration const> variables);
|
|
|
|
void add_lexical_declaration(NonnullRefPtr<Declaration const> variables);
|
|
|
|
void add_hoisted_function(NonnullRefPtr<FunctionDeclaration const> declaration);
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2021-10-05 11:59:04 +00:00
|
|
|
[[nodiscard]] bool has_lexical_declarations() const { return !m_lexical_declarations.is_empty(); }
|
|
|
|
[[nodiscard]] bool has_var_declarations() const { return !m_var_declarations.is_empty(); }
|
|
|
|
|
2021-10-08 00:22:02 +00:00
|
|
|
[[nodiscard]] size_t var_declaration_count() const { return m_var_declarations.size(); }
|
|
|
|
[[nodiscard]] size_t lexical_declaration_count() const { return m_lexical_declarations.size(); }
|
|
|
|
|
2022-02-07 12:31:01 +00:00
|
|
|
ThrowCompletionOr<void> for_each_lexically_scoped_declaration(ThrowCompletionOrVoidCallback<Declaration const&>&& callback) const;
|
2023-07-06 15:49:38 +00:00
|
|
|
ThrowCompletionOr<void> for_each_lexically_declared_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2023-07-05 00:10:40 +00:00
|
|
|
ThrowCompletionOr<void> for_each_var_declared_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2022-02-07 12:31:01 +00:00
|
|
|
ThrowCompletionOr<void> for_each_var_function_declaration_in_reverse_order(ThrowCompletionOrVoidCallback<FunctionDeclaration const&>&& callback) const;
|
|
|
|
ThrowCompletionOr<void> for_each_var_scoped_variable_declaration(ThrowCompletionOrVoidCallback<VariableDeclaration const&>&& callback) const;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2023-06-16 14:12:11 +00:00
|
|
|
void block_declaration_instantiation(VM&, Environment*) const;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2022-02-07 12:31:01 +00:00
|
|
|
ThrowCompletionOr<void> for_each_function_hoistable_with_annexB_extension(ThrowCompletionOrVoidCallback<FunctionDeclaration&>&& callback) const;
|
2020-05-28 05:22:08 +00:00
|
|
|
|
2023-07-04 22:14:41 +00:00
|
|
|
Vector<DeprecatedFlyString> const& local_variables_names() const { return m_local_variables_names; }
|
|
|
|
size_t add_local_variable(DeprecatedFlyString name)
|
|
|
|
{
|
|
|
|
auto index = m_local_variables_names.size();
|
2023-08-08 11:11:33 +00:00
|
|
|
m_local_variables_names.append(move(name));
|
2023-07-04 22:14:41 +00:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2020-03-07 18:42:11 +00:00
|
|
|
protected:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit ScopeNode(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
private:
|
2021-06-13 09:23:23 +00:00
|
|
|
virtual bool is_scope_node() const final { return true; }
|
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<Statement const>> m_children;
|
|
|
|
Vector<NonnullRefPtr<Declaration const>> m_lexical_declarations;
|
|
|
|
Vector<NonnullRefPtr<Declaration const>> m_var_declarations;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<FunctionDeclaration const>> m_functions_hoistable_with_annexB_extension;
|
2023-07-04 22:14:41 +00:00
|
|
|
|
|
|
|
Vector<DeprecatedFlyString> m_local_variables_names;
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
// ImportEntry Record, https://tc39.es/ecma262/#table-importentry-record-fields
|
|
|
|
struct ImportEntry {
|
2024-01-24 19:45:11 +00:00
|
|
|
Optional<DeprecatedFlyString> import_name; // [[ImportName]]: stored string if Optional is not empty, NAMESPACE-OBJECT otherwise
|
|
|
|
DeprecatedFlyString local_name; // [[LocalName]]
|
2022-11-23 11:16:51 +00:00
|
|
|
|
2024-01-24 19:45:11 +00:00
|
|
|
ImportEntry(Optional<DeprecatedFlyString> import_name_, DeprecatedFlyString local_name_)
|
2022-11-23 11:16:51 +00:00
|
|
|
: import_name(move(import_name_))
|
|
|
|
, local_name(move(local_name_))
|
|
|
|
{
|
|
|
|
}
|
2022-01-16 22:51:28 +00:00
|
|
|
|
2024-01-24 19:45:11 +00:00
|
|
|
bool is_namespace() const { return !import_name.has_value(); }
|
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
ModuleRequest const& module_request() const
|
|
|
|
{
|
|
|
|
VERIFY(m_module_request);
|
|
|
|
return *m_module_request;
|
|
|
|
}
|
2022-01-16 22:51:28 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
private:
|
|
|
|
friend class ImportStatement;
|
2024-01-24 19:45:11 +00:00
|
|
|
ModuleRequest* m_module_request = nullptr; // [[ModuleRequest]]
|
2022-11-23 11:16:51 +00:00
|
|
|
};
|
2021-08-14 15:42:30 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
class ImportStatement final : public Statement {
|
|
|
|
public:
|
2021-12-20 14:29:25 +00:00
|
|
|
explicit ImportStatement(SourceRange source_range, ModuleRequest from_module, Vector<ImportEntry> entries = {})
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2021-12-20 14:29:25 +00:00
|
|
|
, m_module_request(move(from_module))
|
2021-08-14 15:42:30 +00:00
|
|
|
, m_entries(move(entries))
|
|
|
|
{
|
2022-01-16 22:51:28 +00:00
|
|
|
for (auto& entry : m_entries)
|
|
|
|
entry.m_module_request = &m_module_request;
|
2021-08-14 15:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2023-06-27 18:46:41 +00:00
|
|
|
|
2023-01-09 00:23:00 +00:00
|
|
|
bool has_bound_name(DeprecatedFlyString const& name) const;
|
2022-01-16 22:51:28 +00:00
|
|
|
Vector<ImportEntry> const& entries() const { return m_entries; }
|
|
|
|
ModuleRequest const& module_request() const { return m_module_request; }
|
2021-08-14 15:42:30 +00:00
|
|
|
|
|
|
|
private:
|
2021-12-20 14:29:25 +00:00
|
|
|
ModuleRequest m_module_request;
|
2021-08-14 15:42:30 +00:00
|
|
|
Vector<ImportEntry> m_entries;
|
|
|
|
};
|
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
// ExportEntry Record, https://tc39.es/ecma262/#table-exportentry-records
|
|
|
|
struct ExportEntry {
|
|
|
|
enum class Kind {
|
|
|
|
NamedExport,
|
|
|
|
ModuleRequestAll,
|
|
|
|
ModuleRequestAllButDefault,
|
|
|
|
// EmptyNamedExport is a special type for export {} from "module",
|
|
|
|
// which should import the module without getting any of the exports
|
|
|
|
// however we don't want give it a fake export name which may get
|
|
|
|
// duplicates
|
|
|
|
EmptyNamedExport,
|
|
|
|
} kind;
|
|
|
|
|
2024-01-24 19:45:11 +00:00
|
|
|
Optional<DeprecatedFlyString> export_name; // [[ExportName]]
|
|
|
|
Optional<DeprecatedFlyString> local_or_import_name; // Either [[ImportName]] or [[LocalName]]
|
2022-11-23 11:16:51 +00:00
|
|
|
|
2024-01-24 19:45:11 +00:00
|
|
|
ExportEntry(Kind export_kind, Optional<DeprecatedFlyString> export_name_, Optional<DeprecatedFlyString> local_or_import_name_)
|
2022-11-23 11:16:51 +00:00
|
|
|
: kind(export_kind)
|
|
|
|
, export_name(move(export_name_))
|
|
|
|
, local_or_import_name(move(local_or_import_name_))
|
|
|
|
{
|
|
|
|
}
|
2022-01-16 22:51:28 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
bool is_module_request() const
|
|
|
|
{
|
|
|
|
return m_module_request != nullptr;
|
|
|
|
}
|
2021-08-14 15:42:30 +00:00
|
|
|
|
2024-01-24 19:45:11 +00:00
|
|
|
static ExportEntry indirect_export_entry(ModuleRequest const& module_request, Optional<DeprecatedFlyString> export_name, Optional<DeprecatedFlyString> import_name)
|
2022-11-23 11:16:51 +00:00
|
|
|
{
|
|
|
|
ExportEntry entry { Kind::NamedExport, move(export_name), move(import_name) };
|
|
|
|
entry.m_module_request = &module_request;
|
|
|
|
return entry;
|
|
|
|
}
|
2021-08-14 15:42:30 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
ModuleRequest const& module_request() const
|
|
|
|
{
|
|
|
|
VERIFY(m_module_request);
|
|
|
|
return *m_module_request;
|
|
|
|
}
|
2022-01-16 22:51:28 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
private:
|
|
|
|
ModuleRequest const* m_module_request { nullptr }; // [[ModuleRequest]]
|
|
|
|
friend class ExportStatement;
|
2022-01-27 00:54:47 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
public:
|
2023-01-09 00:23:00 +00:00
|
|
|
static ExportEntry named_export(DeprecatedFlyString export_name, DeprecatedFlyString local_name)
|
2022-11-23 11:16:51 +00:00
|
|
|
{
|
|
|
|
return ExportEntry { Kind::NamedExport, move(export_name), move(local_name) };
|
|
|
|
}
|
2022-01-27 00:54:47 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
static ExportEntry all_but_default_entry()
|
|
|
|
{
|
|
|
|
return ExportEntry { Kind::ModuleRequestAllButDefault, {}, {} };
|
|
|
|
}
|
2022-01-16 22:51:28 +00:00
|
|
|
|
2023-01-09 00:23:00 +00:00
|
|
|
static ExportEntry all_module_request(DeprecatedFlyString export_name)
|
2022-11-23 11:16:51 +00:00
|
|
|
{
|
|
|
|
return ExportEntry { Kind::ModuleRequestAll, move(export_name), {} };
|
|
|
|
}
|
2022-01-16 22:51:28 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
static ExportEntry empty_named_export()
|
|
|
|
{
|
|
|
|
return ExportEntry { Kind::EmptyNamedExport, {}, {} };
|
|
|
|
}
|
|
|
|
};
|
2022-08-29 20:12:25 +00:00
|
|
|
|
2022-11-23 11:16:51 +00:00
|
|
|
class ExportStatement final : public Statement {
|
|
|
|
public:
|
2023-01-09 00:23:00 +00:00
|
|
|
static DeprecatedFlyString local_name_for_default;
|
2021-08-14 15:42:30 +00:00
|
|
|
|
2024-01-24 19:45:11 +00:00
|
|
|
ExportStatement(SourceRange source_range, RefPtr<ASTNode const> statement, Vector<ExportEntry> entries, bool is_default_export, Optional<ModuleRequest> module_request)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2021-08-14 15:42:30 +00:00
|
|
|
, m_statement(move(statement))
|
|
|
|
, m_entries(move(entries))
|
2022-01-16 22:51:28 +00:00
|
|
|
, m_is_default_export(is_default_export)
|
2022-01-27 00:54:47 +00:00
|
|
|
, m_module_request(move(module_request))
|
2021-08-14 15:42:30 +00:00
|
|
|
{
|
2024-01-24 19:45:11 +00:00
|
|
|
if (m_module_request.has_value()) {
|
2022-01-27 00:54:47 +00:00
|
|
|
for (auto& entry : m_entries)
|
2024-01-24 19:45:11 +00:00
|
|
|
entry.m_module_request = &m_module_request.value();
|
2022-01-27 00:54:47 +00:00
|
|
|
}
|
2021-08-14 15:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2023-06-24 14:07:43 +00:00
|
|
|
|
2023-01-09 00:23:00 +00:00
|
|
|
bool has_export(DeprecatedFlyString const& export_name) const;
|
2021-08-14 15:42:30 +00:00
|
|
|
|
2021-11-26 23:01:23 +00:00
|
|
|
bool has_statement() const { return m_statement; }
|
|
|
|
Vector<ExportEntry> const& entries() const { return m_entries; }
|
|
|
|
|
2022-01-16 22:51:28 +00:00
|
|
|
bool is_default_export() const { return m_is_default_export; }
|
|
|
|
|
|
|
|
ASTNode const& statement() const
|
|
|
|
{
|
|
|
|
VERIFY(m_statement);
|
|
|
|
return *m_statement;
|
|
|
|
}
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
ModuleRequest const& module_request() const
|
2022-01-27 01:44:03 +00:00
|
|
|
{
|
2024-01-24 19:45:11 +00:00
|
|
|
return m_module_request.value();
|
2022-01-27 01:44:03 +00:00
|
|
|
}
|
|
|
|
|
2021-08-14 15:42:30 +00:00
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<ASTNode const> m_statement;
|
2021-08-14 15:42:30 +00:00
|
|
|
Vector<ExportEntry> m_entries;
|
2022-01-16 22:51:28 +00:00
|
|
|
bool m_is_default_export { false };
|
2024-01-24 19:45:11 +00:00
|
|
|
Optional<ModuleRequest> m_module_request;
|
2021-08-14 15:42:30 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class Program final : public ScopeNode {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2021-08-14 15:30:37 +00:00
|
|
|
enum class Type {
|
|
|
|
Script,
|
|
|
|
Module
|
|
|
|
};
|
|
|
|
|
|
|
|
explicit Program(SourceRange source_range, Type program_type)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ScopeNode(move(source_range))
|
2021-08-14 15:30:37 +00:00
|
|
|
, m_type(program_type)
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-07 18:42:11 +00:00
|
|
|
|
2020-10-04 00:02:43 +00:00
|
|
|
bool is_strict_mode() const { return m_is_strict_mode; }
|
|
|
|
void set_strict_mode() { m_is_strict_mode = true; }
|
|
|
|
|
2021-08-14 15:30:37 +00:00
|
|
|
Type type() const { return m_type; }
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
void append_import(NonnullRefPtr<ImportStatement const> import_statement)
|
2021-08-14 15:42:30 +00:00
|
|
|
{
|
|
|
|
m_imports.append(import_statement);
|
2023-08-08 11:11:33 +00:00
|
|
|
append(move(import_statement));
|
2021-08-14 15:42:30 +00:00
|
|
|
}
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
void append_export(NonnullRefPtr<ExportStatement const> export_statement)
|
2021-08-14 15:42:30 +00:00
|
|
|
{
|
|
|
|
m_exports.append(export_statement);
|
2023-08-08 11:11:33 +00:00
|
|
|
append(move(export_statement));
|
2021-08-14 15:42:30 +00:00
|
|
|
}
|
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<ImportStatement const>> const& imports() const { return m_imports; }
|
|
|
|
Vector<NonnullRefPtr<ExportStatement const>> const& exports() const { return m_exports; }
|
2021-08-14 15:42:30 +00:00
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<ImportStatement const>>& imports() { return m_imports; }
|
|
|
|
Vector<NonnullRefPtr<ExportStatement const>>& exports() { return m_exports; }
|
2022-01-27 01:44:03 +00:00
|
|
|
|
2022-01-18 17:55:19 +00:00
|
|
|
bool has_top_level_await() const { return m_has_top_level_await; }
|
|
|
|
void set_has_top_level_await() { m_has_top_level_await = true; }
|
|
|
|
|
2023-06-15 08:37:42 +00:00
|
|
|
ThrowCompletionOr<void> global_declaration_instantiation(VM&, GlobalEnvironment&) const;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2020-03-07 18:42:11 +00:00
|
|
|
private:
|
2021-06-13 09:23:23 +00:00
|
|
|
virtual bool is_program() const override { return true; }
|
|
|
|
|
2020-10-04 00:02:43 +00:00
|
|
|
bool m_is_strict_mode { false };
|
2021-08-14 15:30:37 +00:00
|
|
|
Type m_type { Type::Script };
|
2021-08-14 15:42:30 +00:00
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<ImportStatement const>> m_imports;
|
|
|
|
Vector<NonnullRefPtr<ExportStatement const>> m_exports;
|
2022-01-18 17:55:19 +00:00
|
|
|
bool m_has_top_level_await { false };
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class BlockStatement final : public ScopeNode {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit BlockStatement(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ScopeNode(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2021-09-22 10:44:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class FunctionBody final : public ScopeNode {
|
|
|
|
public:
|
|
|
|
explicit FunctionBody(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ScopeNode(move(source_range))
|
2021-09-22 10:44:56 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_strict_mode() { m_in_strict_mode = true; }
|
|
|
|
|
|
|
|
bool in_strict_mode() const { return m_in_strict_mode; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool m_in_strict_mode { false };
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-03-19 10:12:08 +00:00
|
|
|
class Expression : public ASTNode {
|
2020-04-27 10:10:16 +00:00
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit Expression(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-19 10:12:08 +00:00
|
|
|
};
|
|
|
|
|
2020-04-04 19:32:10 +00:00
|
|
|
class Declaration : public Statement {
|
2020-12-28 17:15:22 +00:00
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit Declaration(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
virtual ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const = 0;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
|
|
|
// 8.1.3 Static Semantics: IsConstantDeclaration, https://tc39.es/ecma262/#sec-static-semantics-isconstantdeclaration
|
|
|
|
virtual bool is_constant_declaration() const { return false; }
|
|
|
|
|
|
|
|
virtual bool is_lexical_declaration() const { return false; }
|
2020-04-04 19:32:10 +00:00
|
|
|
};
|
|
|
|
|
2020-10-22 22:30:07 +00:00
|
|
|
class ErrorDeclaration final : public Declaration {
|
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit ErrorDeclaration(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Declaration(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&&) const override
|
|
|
|
{
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
}
|
2020-10-22 22:30:07 +00:00
|
|
|
};
|
|
|
|
|
2021-05-29 11:33:19 +00:00
|
|
|
struct BindingPattern : RefCounted<BindingPattern> {
|
2021-06-13 01:04:28 +00:00
|
|
|
// This covers both BindingProperty and BindingElement, hence the more generic name
|
|
|
|
struct BindingEntry {
|
|
|
|
// If this entry represents a BindingElement, then name will be Empty
|
2023-02-19 21:07:52 +00:00
|
|
|
Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<Expression const>, Empty> name {};
|
|
|
|
Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>, NonnullRefPtr<MemberExpression const>, Empty> alias {};
|
|
|
|
RefPtr<Expression const> initializer {};
|
2021-05-29 11:33:19 +00:00
|
|
|
bool is_rest { false };
|
2021-06-13 01:04:28 +00:00
|
|
|
|
|
|
|
bool is_elision() const { return name.has<Empty>() && alias.has<Empty>(); }
|
2021-05-29 11:33:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum class Kind {
|
|
|
|
Array,
|
|
|
|
Object,
|
|
|
|
};
|
|
|
|
|
|
|
|
void dump(int indent) const;
|
2021-06-13 01:04:28 +00:00
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const;
|
2021-05-29 11:33:19 +00:00
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
bool contains_expression() const;
|
|
|
|
|
2021-06-13 01:04:28 +00:00
|
|
|
Vector<BindingEntry> entries;
|
2021-05-29 11:33:19 +00:00
|
|
|
Kind kind { Kind::Object };
|
|
|
|
};
|
|
|
|
|
2023-07-01 21:35:51 +00:00
|
|
|
class Identifier final : public Expression {
|
|
|
|
public:
|
|
|
|
explicit Identifier(SourceRange source_range, DeprecatedFlyString string)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2023-07-01 21:35:51 +00:00
|
|
|
, m_string(move(string))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
DeprecatedFlyString const& string() const { return m_string; }
|
|
|
|
|
|
|
|
bool is_local() const { return m_local_variable_index.has_value(); }
|
|
|
|
size_t local_variable_index() const
|
|
|
|
{
|
|
|
|
VERIFY(m_local_variable_index.has_value());
|
|
|
|
return m_local_variable_index.value();
|
|
|
|
}
|
|
|
|
void set_local_variable_index(size_t index) { m_local_variable_index = index; }
|
|
|
|
|
2023-07-12 02:02:27 +00:00
|
|
|
bool is_global() const { return m_is_global; }
|
|
|
|
void set_is_global() { m_is_global = true; }
|
|
|
|
|
2023-07-01 21:35:51 +00:00
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2023-07-01 21:35:51 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
virtual bool is_identifier() const override { return true; }
|
|
|
|
|
|
|
|
DeprecatedFlyString m_string;
|
|
|
|
|
|
|
|
Optional<size_t> m_local_variable_index;
|
2023-07-12 02:02:27 +00:00
|
|
|
bool m_is_global { false };
|
2023-07-01 21:35:51 +00:00
|
|
|
};
|
|
|
|
|
2023-07-06 15:49:38 +00:00
|
|
|
struct FunctionParameter {
|
|
|
|
Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>> binding;
|
|
|
|
RefPtr<Expression const> default_value;
|
|
|
|
bool is_rest { false };
|
2023-11-27 12:23:59 +00:00
|
|
|
Handle<Bytecode::Executable> bytecode_executable {};
|
2023-07-06 15:49:38 +00:00
|
|
|
};
|
|
|
|
|
2020-03-19 10:12:08 +00:00
|
|
|
class FunctionNode {
|
|
|
|
public:
|
2023-07-01 21:35:51 +00:00
|
|
|
StringView name() const { return m_name ? m_name->string().view() : ""sv; }
|
2023-07-08 17:31:41 +00:00
|
|
|
RefPtr<Identifier const> name_identifier() const { return m_name; }
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString const& source_text() const { return m_source_text; }
|
2021-06-10 21:43:06 +00:00
|
|
|
Statement const& body() const { return *m_body; }
|
2023-07-08 02:48:11 +00:00
|
|
|
Vector<FunctionParameter> const& parameters() const { return m_parameters; }
|
2020-06-04 12:48:36 +00:00
|
|
|
i32 function_length() const { return m_function_length; }
|
2023-07-04 22:14:41 +00:00
|
|
|
Vector<DeprecatedFlyString> const& local_variables_names() const { return m_local_variables_names; }
|
2020-10-04 00:02:43 +00:00
|
|
|
bool is_strict_mode() const { return m_is_strict_mode; }
|
LibJS: Add an optimization to avoid needless arguments object creation
This gives FunctionNode a "might need arguments object" boolean flag and
sets it based on the simplest possible heuristic for this: if we
encounter an identifier called "arguments" or "eval" up to the next
(nested) function declaration or expression, we won't need an arguments
object. Otherwise, we *might* need one - the final decision is made in
the FunctionDeclarationInstantiation AO.
Now, this is obviously not perfect. Even if you avoid eval, something
like `foo.arguments` will still trigger a false positive - but it's a
start and already massively cuts down on needlessly allocated objects,
especially in real-world code that is often minified, and so a full
"arguments" identifier will be an actual arguments object more often
than not.
To illustrate the actual impact of this change, here's the number of
allocated arguments objects during a full test-js run:
Before:
- Unmapped arguments objects: 78765
- Mapped arguments objects: 2455
After:
- Unmapped arguments objects: 18
- Mapped arguments objects: 37
This results in a ~5% speedup of test-js on my Linux host machine, and
about 3.5% on i686 Serenity in QEMU (warm runs, average of 5).
The following microbenchmark (calling an empty function 1M times) runs
25% faster on Linux and 45% on Serenity:
function foo() {}
for (var i = 0; i < 1_000_000; ++i)
foo();
test262 reports no changes in either direction, apart from a speedup :^)
2021-10-05 07:44:58 +00:00
|
|
|
bool might_need_arguments_object() const { return m_might_need_arguments_object; }
|
2021-10-08 10:43:38 +00:00
|
|
|
bool contains_direct_call_to_eval() const { return m_contains_direct_call_to_eval; }
|
2021-06-11 08:45:49 +00:00
|
|
|
bool is_arrow_function() const { return m_is_arrow_function; }
|
2021-06-10 23:08:05 +00:00
|
|
|
FunctionKind kind() const { return m_kind; }
|
2020-03-19 10:12:08 +00:00
|
|
|
|
|
|
|
protected:
|
2023-12-16 14:19:34 +00:00
|
|
|
FunctionNode(RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, Vector<FunctionParameter> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, bool might_need_arguments_object, bool contains_direct_call_to_eval, bool is_arrow_function, Vector<DeprecatedFlyString> local_variables_names)
|
2021-06-24 11:38:21 +00:00
|
|
|
: m_name(move(name))
|
2022-01-18 23:46:16 +00:00
|
|
|
, m_source_text(move(source_text))
|
2020-03-07 18:42:11 +00:00
|
|
|
, m_body(move(body))
|
2020-03-12 11:22:13 +00:00
|
|
|
, m_parameters(move(parameters))
|
2020-05-06 03:02:14 +00:00
|
|
|
, m_function_length(function_length)
|
2021-06-10 23:08:05 +00:00
|
|
|
, m_kind(kind)
|
2020-10-04 00:02:43 +00:00
|
|
|
, m_is_strict_mode(is_strict_mode)
|
LibJS: Add an optimization to avoid needless arguments object creation
This gives FunctionNode a "might need arguments object" boolean flag and
sets it based on the simplest possible heuristic for this: if we
encounter an identifier called "arguments" or "eval" up to the next
(nested) function declaration or expression, we won't need an arguments
object. Otherwise, we *might* need one - the final decision is made in
the FunctionDeclarationInstantiation AO.
Now, this is obviously not perfect. Even if you avoid eval, something
like `foo.arguments` will still trigger a false positive - but it's a
start and already massively cuts down on needlessly allocated objects,
especially in real-world code that is often minified, and so a full
"arguments" identifier will be an actual arguments object more often
than not.
To illustrate the actual impact of this change, here's the number of
allocated arguments objects during a full test-js run:
Before:
- Unmapped arguments objects: 78765
- Mapped arguments objects: 2455
After:
- Unmapped arguments objects: 18
- Mapped arguments objects: 37
This results in a ~5% speedup of test-js on my Linux host machine, and
about 3.5% on i686 Serenity in QEMU (warm runs, average of 5).
The following microbenchmark (calling an empty function 1M times) runs
25% faster on Linux and 45% on Serenity:
function foo() {}
for (var i = 0; i < 1_000_000; ++i)
foo();
test262 reports no changes in either direction, apart from a speedup :^)
2021-10-05 07:44:58 +00:00
|
|
|
, m_might_need_arguments_object(might_need_arguments_object)
|
2021-10-08 10:43:38 +00:00
|
|
|
, m_contains_direct_call_to_eval(contains_direct_call_to_eval)
|
2021-06-11 08:45:49 +00:00
|
|
|
, m_is_arrow_function(is_arrow_function)
|
2023-08-08 11:11:33 +00:00
|
|
|
, m_local_variables_names(move(local_variables_names))
|
2020-03-07 18:42:11 +00:00
|
|
|
{
|
LibJS: Add an optimization to avoid needless arguments object creation
This gives FunctionNode a "might need arguments object" boolean flag and
sets it based on the simplest possible heuristic for this: if we
encounter an identifier called "arguments" or "eval" up to the next
(nested) function declaration or expression, we won't need an arguments
object. Otherwise, we *might* need one - the final decision is made in
the FunctionDeclarationInstantiation AO.
Now, this is obviously not perfect. Even if you avoid eval, something
like `foo.arguments` will still trigger a false positive - but it's a
start and already massively cuts down on needlessly allocated objects,
especially in real-world code that is often minified, and so a full
"arguments" identifier will be an actual arguments object more often
than not.
To illustrate the actual impact of this change, here's the number of
allocated arguments objects during a full test-js run:
Before:
- Unmapped arguments objects: 78765
- Mapped arguments objects: 2455
After:
- Unmapped arguments objects: 18
- Mapped arguments objects: 37
This results in a ~5% speedup of test-js on my Linux host machine, and
about 3.5% on i686 Serenity in QEMU (warm runs, average of 5).
The following microbenchmark (calling an empty function 1M times) runs
25% faster on Linux and 45% on Serenity:
function foo() {}
for (var i = 0; i < 1_000_000; ++i)
foo();
test262 reports no changes in either direction, apart from a speedup :^)
2021-10-05 07:44:58 +00:00
|
|
|
if (m_is_arrow_function)
|
|
|
|
VERIFY(!m_might_need_arguments_object);
|
2020-03-07 18:42:11 +00:00
|
|
|
}
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
void dump(int indent, ByteString const& class_name) const;
|
2020-03-19 10:12:08 +00:00
|
|
|
|
2023-07-01 21:35:51 +00:00
|
|
|
RefPtr<Identifier const> m_name { nullptr };
|
2023-07-01 22:04:07 +00:00
|
|
|
|
|
|
|
private:
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_source_text;
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2022-11-23 12:12:36 +00:00
|
|
|
Vector<FunctionParameter> const m_parameters;
|
2023-11-10 16:55:34 +00:00
|
|
|
i32 const m_function_length;
|
2021-06-10 23:08:05 +00:00
|
|
|
FunctionKind m_kind;
|
2022-11-26 19:07:09 +00:00
|
|
|
bool m_is_strict_mode : 1 { false };
|
|
|
|
bool m_might_need_arguments_object : 1 { false };
|
|
|
|
bool m_contains_direct_call_to_eval : 1 { false };
|
|
|
|
bool m_is_arrow_function : 1 { false };
|
2023-07-04 22:14:41 +00:00
|
|
|
|
|
|
|
Vector<DeprecatedFlyString> m_local_variables_names;
|
2020-03-19 10:12:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class FunctionDeclaration final
|
2020-04-04 19:32:10 +00:00
|
|
|
: public Declaration
|
2020-03-19 10:12:08 +00:00
|
|
|
, public FunctionNode {
|
|
|
|
public:
|
2020-03-19 10:52:56 +00:00
|
|
|
static bool must_have_name() { return true; }
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
FunctionDeclaration(SourceRange source_range, RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, Vector<FunctionParameter> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, bool might_need_arguments_object, bool contains_direct_call_to_eval, Vector<DeprecatedFlyString> local_variables_names)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Declaration(move(source_range))
|
|
|
|
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, might_need_arguments_object, contains_direct_call_to_eval, false, move(local_variables_names))
|
2020-03-19 10:12:08 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&&) const override;
|
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
virtual bool is_function_declaration() const override { return true; }
|
|
|
|
|
|
|
|
void set_should_do_additional_annexB_steps() { m_is_hoisted = true; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool m_is_hoisted { false };
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-05-26 17:52:03 +00:00
|
|
|
class FunctionExpression final
|
|
|
|
: public Expression
|
2020-03-19 10:12:08 +00:00
|
|
|
, public FunctionNode {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2020-03-19 10:52:56 +00:00
|
|
|
static bool must_have_name() { return false; }
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
FunctionExpression(SourceRange source_range, RefPtr<Identifier const> name, ByteString source_text, NonnullRefPtr<Statement const> body, Vector<FunctionParameter> parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, bool might_need_arguments_object, bool contains_direct_call_to_eval, Vector<DeprecatedFlyString> local_variables_names, bool is_arrow_function = false)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
|
|
|
, FunctionNode(move(name), move(source_text), move(body), move(parameters), function_length, kind, is_strict_mode, might_need_arguments_object, contains_direct_call_to_eval, is_arrow_function, move(local_variables_names))
|
2020-03-19 10:12:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name, Optional<Bytecode::Operand> preferred_dst = {}) const;
|
2021-06-11 08:46:46 +00:00
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
bool has_name() const { return !name().is_empty(); }
|
|
|
|
|
2023-06-23 12:27:42 +00:00
|
|
|
Value instantiate_ordinary_function_expression(VM&, DeprecatedFlyString given_name) const;
|
2021-10-07 10:05:13 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
virtual bool is_function_expression() const override { return true; }
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-03-11 18:27:43 +00:00
|
|
|
class ErrorExpression final : public Expression {
|
|
|
|
public:
|
2020-12-28 17:15:22 +00:00
|
|
|
explicit ErrorExpression(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-11 18:27:43 +00:00
|
|
|
};
|
|
|
|
|
2021-06-10 21:08:30 +00:00
|
|
|
class YieldExpression final : public Expression {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
explicit YieldExpression(SourceRange source_range, RefPtr<Expression const> argument, bool is_yield_from)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-06-10 21:08:30 +00:00
|
|
|
, m_argument(move(argument))
|
2021-06-14 11:16:41 +00:00
|
|
|
, m_is_yield_from(is_yield_from)
|
2021-06-10 21:08:30 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const* argument() const { return m_argument; }
|
2021-06-14 11:16:41 +00:00
|
|
|
bool is_yield_from() const { return m_is_yield_from; }
|
2021-06-10 21:08:30 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2021-06-10 21:08:30 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<Expression const> m_argument;
|
2021-06-14 11:16:41 +00:00
|
|
|
bool m_is_yield_from { false };
|
2021-06-10 21:08:30 +00:00
|
|
|
};
|
|
|
|
|
2021-11-09 20:52:21 +00:00
|
|
|
class AwaitExpression final : public Expression {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
explicit AwaitExpression(SourceRange source_range, NonnullRefPtr<Expression const> argument)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-11-09 20:52:21 +00:00
|
|
|
, m_argument(move(argument))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2021-11-09 20:52:21 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_argument;
|
2021-11-09 20:52:21 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class ReturnStatement final : public Statement {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
explicit ReturnStatement(SourceRange source_range, RefPtr<Expression const> argument)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_argument(move(argument))
|
2020-03-07 18:42:11 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const* argument() const { return m_argument; }
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<Expression const> m_argument;
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class IfStatement final : public Statement {
|
2020-03-08 05:58:58 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
IfStatement(SourceRange source_range, NonnullRefPtr<Expression const> predicate, NonnullRefPtr<Statement const> consequent, RefPtr<Statement const> alternate)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_predicate(move(predicate))
|
2020-03-08 05:58:58 +00:00
|
|
|
, m_consequent(move(consequent))
|
|
|
|
, m_alternate(move(alternate))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& predicate() const { return *m_predicate; }
|
|
|
|
Statement const& consequent() const { return *m_consequent; }
|
|
|
|
Statement const* alternate() const { return m_alternate; }
|
2020-03-08 05:58:58 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-08 05:58:58 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_predicate;
|
|
|
|
NonnullRefPtr<Statement const> m_consequent;
|
|
|
|
RefPtr<Statement const> m_alternate;
|
2020-03-08 05:58:58 +00:00
|
|
|
};
|
|
|
|
|
2021-09-18 21:01:54 +00:00
|
|
|
class WhileStatement final : public IterationStatement {
|
2020-03-08 19:22:21 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
WhileStatement(SourceRange source_range, NonnullRefPtr<Expression const> test, NonnullRefPtr<Statement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: IterationStatement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_test(move(test))
|
2020-03-08 19:22:21 +00:00
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& test() const { return *m_test; }
|
|
|
|
Statement const& body() const { return *m_body; }
|
2020-03-08 19:22:21 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-08 19:22:21 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_test;
|
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2020-03-08 19:22:21 +00:00
|
|
|
};
|
|
|
|
|
2021-09-18 21:01:54 +00:00
|
|
|
class DoWhileStatement final : public IterationStatement {
|
2020-04-04 19:29:23 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
DoWhileStatement(SourceRange source_range, NonnullRefPtr<Expression const> test, NonnullRefPtr<Statement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: IterationStatement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_test(move(test))
|
2020-04-04 19:29:23 +00:00
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& test() const { return *m_test; }
|
|
|
|
Statement const& body() const { return *m_body; }
|
2020-04-04 19:29:23 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-04 19:29:23 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_test;
|
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2020-04-04 19:29:23 +00:00
|
|
|
};
|
|
|
|
|
2020-11-28 14:05:57 +00:00
|
|
|
class WithStatement final : public Statement {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
WithStatement(SourceRange source_range, NonnullRefPtr<Expression const> object, NonnullRefPtr<Statement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_object(move(object))
|
2020-11-28 14:05:57 +00:00
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& object() const { return *m_object; }
|
|
|
|
Statement const& body() const { return *m_body; }
|
2020-11-28 14:05:57 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-11-28 14:05:57 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_object;
|
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2020-11-28 14:05:57 +00:00
|
|
|
};
|
|
|
|
|
2021-09-18 21:01:54 +00:00
|
|
|
class ForStatement final : public IterationStatement {
|
2020-03-12 12:12:12 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ForStatement(SourceRange source_range, RefPtr<ASTNode const> init, RefPtr<Expression const> test, RefPtr<Expression const> update, NonnullRefPtr<Statement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: IterationStatement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_init(move(init))
|
2020-03-12 12:12:12 +00:00
|
|
|
, m_test(move(test))
|
|
|
|
, m_update(move(update))
|
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
ASTNode const* init() const { return m_init; }
|
|
|
|
Expression const* test() const { return m_test; }
|
|
|
|
Expression const* update() const { return m_update; }
|
|
|
|
Statement const& body() const { return *m_body; }
|
2020-03-12 12:12:12 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-12 12:12:12 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<ASTNode const> m_init;
|
|
|
|
RefPtr<Expression const> m_test;
|
|
|
|
RefPtr<Expression const> m_update;
|
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2020-03-12 12:12:12 +00:00
|
|
|
};
|
|
|
|
|
2021-09-18 21:01:54 +00:00
|
|
|
class ForInStatement final : public IterationStatement {
|
2020-04-21 18:21:26 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ForInStatement(SourceRange source_range, Variant<NonnullRefPtr<ASTNode const>, NonnullRefPtr<BindingPattern const>> lhs, NonnullRefPtr<Expression const> rhs, NonnullRefPtr<Statement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: IterationStatement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_lhs(move(lhs))
|
2020-04-21 18:21:26 +00:00
|
|
|
, m_rhs(move(rhs))
|
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
auto const& lhs() const { return m_lhs; }
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& rhs() const { return *m_rhs; }
|
|
|
|
Statement const& body() const { return *m_body; }
|
2020-04-21 18:21:26 +00:00
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-21 18:21:26 +00:00
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
Variant<NonnullRefPtr<ASTNode const>, NonnullRefPtr<BindingPattern const>> m_lhs;
|
|
|
|
NonnullRefPtr<Expression const> m_rhs;
|
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2020-04-21 18:21:26 +00:00
|
|
|
};
|
|
|
|
|
2021-09-18 21:01:54 +00:00
|
|
|
class ForOfStatement final : public IterationStatement {
|
2020-04-21 18:21:26 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ForOfStatement(SourceRange source_range, Variant<NonnullRefPtr<ASTNode const>, NonnullRefPtr<BindingPattern const>> lhs, NonnullRefPtr<Expression const> rhs, NonnullRefPtr<Statement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: IterationStatement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_lhs(move(lhs))
|
2020-04-21 18:21:26 +00:00
|
|
|
, m_rhs(move(rhs))
|
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
auto const& lhs() const { return m_lhs; }
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& rhs() const { return *m_rhs; }
|
|
|
|
Statement const& body() const { return *m_body; }
|
2020-04-21 18:21:26 +00:00
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-21 18:21:26 +00:00
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
Variant<NonnullRefPtr<ASTNode const>, NonnullRefPtr<BindingPattern const>> m_lhs;
|
|
|
|
NonnullRefPtr<Expression const> m_rhs;
|
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2020-04-21 18:21:26 +00:00
|
|
|
};
|
|
|
|
|
2021-11-23 15:09:28 +00:00
|
|
|
class ForAwaitOfStatement final : public IterationStatement {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ForAwaitOfStatement(SourceRange source_range, Variant<NonnullRefPtr<ASTNode const>, NonnullRefPtr<BindingPattern const>> lhs, NonnullRefPtr<Expression const> rhs, NonnullRefPtr<Statement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: IterationStatement(move(source_range))
|
2021-11-23 15:09:28 +00:00
|
|
|
, m_lhs(move(lhs))
|
|
|
|
, m_rhs(move(rhs))
|
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2021-11-23 15:09:28 +00:00
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
Variant<NonnullRefPtr<ASTNode const>, NonnullRefPtr<BindingPattern const>> m_lhs;
|
|
|
|
NonnullRefPtr<Expression const> m_rhs;
|
|
|
|
NonnullRefPtr<Statement const> m_body;
|
2021-11-23 15:09:28 +00:00
|
|
|
};
|
|
|
|
|
2020-03-07 18:42:11 +00:00
|
|
|
enum class BinaryOp {
|
2020-04-05 11:56:53 +00:00
|
|
|
Addition,
|
|
|
|
Subtraction,
|
|
|
|
Multiplication,
|
|
|
|
Division,
|
2020-04-04 19:17:34 +00:00
|
|
|
Modulo,
|
2020-04-05 12:40:00 +00:00
|
|
|
Exponentiation,
|
2021-09-23 22:06:10 +00:00
|
|
|
StrictlyEquals,
|
|
|
|
StrictlyInequals,
|
|
|
|
LooselyEquals,
|
|
|
|
LooselyInequals,
|
2020-03-10 10:35:05 +00:00
|
|
|
GreaterThan,
|
2020-03-12 12:07:08 +00:00
|
|
|
GreaterThanEquals,
|
2020-03-10 10:35:05 +00:00
|
|
|
LessThan,
|
2020-03-12 12:07:08 +00:00
|
|
|
LessThanEquals,
|
2020-03-10 10:35:05 +00:00
|
|
|
BitwiseAnd,
|
|
|
|
BitwiseOr,
|
|
|
|
BitwiseXor,
|
|
|
|
LeftShift,
|
|
|
|
RightShift,
|
2020-04-23 14:43:10 +00:00
|
|
|
UnsignedRightShift,
|
2020-04-23 15:06:01 +00:00
|
|
|
In,
|
2020-03-28 15:56:54 +00:00
|
|
|
InstanceOf,
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class BinaryExpression final : public Expression {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
BinaryExpression(SourceRange source_range, BinaryOp op, NonnullRefPtr<Expression const> lhs, NonnullRefPtr<Expression const> rhs)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_op(op)
|
2020-03-07 18:42:11 +00:00
|
|
|
, m_lhs(move(lhs))
|
|
|
|
, m_rhs(move(rhs))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
BinaryOp m_op;
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_lhs;
|
|
|
|
NonnullRefPtr<Expression const> m_rhs;
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-03-08 05:55:44 +00:00
|
|
|
enum class LogicalOp {
|
|
|
|
And,
|
|
|
|
Or,
|
2020-04-17 23:49:11 +00:00
|
|
|
NullishCoalescing,
|
2020-03-08 05:55:44 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class LogicalExpression final : public Expression {
|
2020-03-08 05:55:44 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
LogicalExpression(SourceRange source_range, LogicalOp op, NonnullRefPtr<Expression const> lhs, NonnullRefPtr<Expression const> rhs)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_op(op)
|
2020-03-08 05:55:44 +00:00
|
|
|
, m_lhs(move(lhs))
|
|
|
|
, m_rhs(move(rhs))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-08 05:55:44 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
LogicalOp m_op;
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_lhs;
|
|
|
|
NonnullRefPtr<Expression const> m_rhs;
|
2020-03-08 05:55:44 +00:00
|
|
|
};
|
|
|
|
|
2020-03-08 21:27:18 +00:00
|
|
|
enum class UnaryOp {
|
2020-03-14 18:43:35 +00:00
|
|
|
BitwiseNot,
|
2020-03-09 17:04:44 +00:00
|
|
|
Not,
|
2020-04-02 16:58:39 +00:00
|
|
|
Plus,
|
|
|
|
Minus,
|
2020-03-17 19:33:32 +00:00
|
|
|
Typeof,
|
2020-04-15 16:55:03 +00:00
|
|
|
Void,
|
2020-04-26 11:53:40 +00:00
|
|
|
Delete,
|
2020-03-08 21:27:18 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class UnaryExpression final : public Expression {
|
2020-03-08 21:27:18 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
UnaryExpression(SourceRange source_range, UnaryOp op, NonnullRefPtr<Expression const> lhs)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_op(op)
|
2020-03-08 21:27:18 +00:00
|
|
|
, m_lhs(move(lhs))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-08 21:27:18 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
UnaryOp m_op;
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_lhs;
|
2020-03-08 21:27:18 +00:00
|
|
|
};
|
|
|
|
|
2020-04-07 13:11:05 +00:00
|
|
|
class SequenceExpression final : public Expression {
|
|
|
|
public:
|
2023-03-06 13:17:01 +00:00
|
|
|
SequenceExpression(SourceRange source_range, Vector<NonnullRefPtr<Expression const>> expressions)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_expressions(move(expressions))
|
2020-04-07 13:11:05 +00:00
|
|
|
{
|
2021-03-16 21:03:31 +00:00
|
|
|
VERIFY(m_expressions.size() >= 2);
|
2020-04-07 13:11:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-07 13:11:05 +00:00
|
|
|
|
|
|
|
private:
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<Expression const>> m_expressions;
|
2020-04-07 13:11:05 +00:00
|
|
|
};
|
|
|
|
|
2023-11-17 20:07:23 +00:00
|
|
|
class PrimitiveLiteral : public Expression {
|
2020-03-12 11:19:11 +00:00
|
|
|
public:
|
2023-11-17 20:07:23 +00:00
|
|
|
virtual Value value() const = 0;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
explicit PrimitiveLiteral(SourceRange source_range)
|
2023-11-17 19:26:57 +00:00
|
|
|
: Expression(move(source_range))
|
2023-11-17 20:07:23 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class BooleanLiteral final : public PrimitiveLiteral {
|
|
|
|
public:
|
|
|
|
explicit BooleanLiteral(SourceRange source_range, bool value)
|
|
|
|
: PrimitiveLiteral(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_value(value)
|
2020-03-12 11:19:11 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-12 11:19:11 +00:00
|
|
|
|
2023-11-17 20:07:23 +00:00
|
|
|
virtual Value value() const override { return Value(m_value); }
|
|
|
|
|
2020-03-12 11:19:11 +00:00
|
|
|
private:
|
|
|
|
bool m_value { false };
|
|
|
|
};
|
|
|
|
|
2023-11-17 20:07:23 +00:00
|
|
|
class NumericLiteral final : public PrimitiveLiteral {
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2020-12-28 17:15:22 +00:00
|
|
|
explicit NumericLiteral(SourceRange source_range, double value)
|
2023-11-17 20:07:23 +00:00
|
|
|
: PrimitiveLiteral(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_value(value)
|
2020-03-12 11:19:11 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-12 11:19:11 +00:00
|
|
|
|
2023-11-17 20:07:23 +00:00
|
|
|
virtual Value value() const override { return m_value; }
|
|
|
|
|
2020-03-12 11:19:11 +00:00
|
|
|
private:
|
2021-03-21 17:03:00 +00:00
|
|
|
Value m_value;
|
2020-03-12 11:19:11 +00:00
|
|
|
};
|
|
|
|
|
2023-11-17 19:26:57 +00:00
|
|
|
class BigIntLiteral final : public Expression {
|
2020-06-06 00:14:10 +00:00
|
|
|
public:
|
2023-12-16 14:19:34 +00:00
|
|
|
explicit BigIntLiteral(SourceRange source_range, ByteString value)
|
2023-11-17 19:26:57 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_value(move(value))
|
2020-06-06 00:14:10 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-06-06 00:14:10 +00:00
|
|
|
|
|
|
|
private:
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_value;
|
2020-06-06 00:14:10 +00:00
|
|
|
};
|
|
|
|
|
2023-11-17 19:26:57 +00:00
|
|
|
class StringLiteral final : public Expression {
|
2020-03-12 11:19:11 +00:00
|
|
|
public:
|
2023-12-16 14:19:34 +00:00
|
|
|
explicit StringLiteral(SourceRange source_range, ByteString value)
|
2023-11-17 19:26:57 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_value(move(value))
|
2020-03-07 18:42:11 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-11-01 21:49:25 +00:00
|
|
|
|
|
|
|
StringView value() const { return m_value; }
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_string_literal() const override { return true; }
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_value;
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2023-11-17 20:07:23 +00:00
|
|
|
class NullLiteral final : public PrimitiveLiteral {
|
2020-03-15 21:32:34 +00:00
|
|
|
public:
|
2020-12-28 17:15:22 +00:00
|
|
|
explicit NullLiteral(SourceRange source_range)
|
2023-11-17 20:07:23 +00:00
|
|
|
: PrimitiveLiteral(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-15 21:32:34 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2023-11-17 20:07:23 +00:00
|
|
|
|
|
|
|
virtual Value value() const override { return js_null(); }
|
2020-03-15 21:32:34 +00:00
|
|
|
};
|
|
|
|
|
2023-11-17 19:26:57 +00:00
|
|
|
class RegExpLiteral final : public Expression {
|
2020-06-03 23:05:49 +00:00
|
|
|
public:
|
2023-12-16 14:19:34 +00:00
|
|
|
RegExpLiteral(SourceRange source_range, regex::Parser::Result parsed_regex, ByteString parsed_pattern, regex::RegexOptions<ECMAScriptFlags> parsed_flags, ByteString pattern, ByteString flags)
|
2023-11-17 19:26:57 +00:00
|
|
|
: Expression(move(source_range))
|
2021-07-29 14:34:37 +00:00
|
|
|
, m_parsed_regex(move(parsed_regex))
|
|
|
|
, m_parsed_pattern(move(parsed_pattern))
|
2023-08-08 11:11:33 +00:00
|
|
|
, m_parsed_flags(parsed_flags)
|
2021-05-10 10:56:08 +00:00
|
|
|
, m_pattern(move(pattern))
|
|
|
|
, m_flags(move(flags))
|
2020-06-03 23:05:49 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-06-03 23:05:49 +00:00
|
|
|
|
2021-07-29 14:34:37 +00:00
|
|
|
regex::Parser::Result const& parsed_regex() const { return m_parsed_regex; }
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString const& parsed_pattern() const { return m_parsed_pattern; }
|
2021-07-29 14:34:37 +00:00
|
|
|
regex::RegexOptions<ECMAScriptFlags> const& parsed_flags() const { return m_parsed_flags; }
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString const& pattern() const { return m_pattern; }
|
|
|
|
ByteString const& flags() const { return m_flags; }
|
2020-06-03 23:05:49 +00:00
|
|
|
|
|
|
|
private:
|
2021-07-29 14:34:37 +00:00
|
|
|
regex::Parser::Result m_parsed_regex;
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_parsed_pattern;
|
2021-07-29 14:34:37 +00:00
|
|
|
regex::RegexOptions<ECMAScriptFlags> m_parsed_flags;
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_pattern;
|
|
|
|
ByteString m_flags;
|
2020-06-03 23:05:49 +00:00
|
|
|
};
|
|
|
|
|
2021-10-12 20:45:52 +00:00
|
|
|
class PrivateIdentifier final : public Expression {
|
|
|
|
public:
|
2023-01-09 00:23:00 +00:00
|
|
|
explicit PrivateIdentifier(SourceRange source_range, DeprecatedFlyString string)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-10-12 20:45:52 +00:00
|
|
|
, m_string(move(string))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-01-09 00:23:00 +00:00
|
|
|
DeprecatedFlyString const& string() const { return m_string; }
|
2021-10-12 20:45:52 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
2022-03-05 23:48:44 +00:00
|
|
|
virtual bool is_private_identifier() const override { return true; }
|
|
|
|
|
2021-10-12 20:45:52 +00:00
|
|
|
private:
|
2023-01-09 00:23:00 +00:00
|
|
|
DeprecatedFlyString m_string;
|
2021-10-12 20:45:52 +00:00
|
|
|
};
|
|
|
|
|
2021-10-06 23:09:04 +00:00
|
|
|
class ClassElement : public ASTNode {
|
|
|
|
public:
|
|
|
|
ClassElement(SourceRange source_range, bool is_static)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2021-10-06 23:09:04 +00:00
|
|
|
, m_is_static(is_static)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class ElementKind {
|
|
|
|
Method,
|
|
|
|
Field,
|
2021-10-20 19:29:47 +00:00
|
|
|
StaticInitializer,
|
2021-10-06 23:09:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
virtual ElementKind class_element_kind() const = 0;
|
|
|
|
bool is_static() const { return m_is_static; }
|
|
|
|
|
2021-10-20 19:29:47 +00:00
|
|
|
// We use the Completion also as a ClassStaticBlockDefinition Record.
|
2021-10-12 20:45:52 +00:00
|
|
|
using ClassValue = Variant<ClassFieldDefinition, Completion, PrivateElement>;
|
2023-06-25 15:33:17 +00:00
|
|
|
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const = 0;
|
2021-10-06 23:09:04 +00:00
|
|
|
|
2023-07-08 02:48:11 +00:00
|
|
|
virtual Optional<DeprecatedFlyString> private_bound_identifier() const { return {}; }
|
2021-10-12 20:45:52 +00:00
|
|
|
|
2021-10-06 23:09:04 +00:00
|
|
|
private:
|
|
|
|
bool m_is_static { false };
|
|
|
|
};
|
|
|
|
|
|
|
|
class ClassMethod final : public ClassElement {
|
2020-06-08 18:31:21 +00:00
|
|
|
public:
|
|
|
|
enum class Kind {
|
|
|
|
Method,
|
|
|
|
Getter,
|
|
|
|
Setter,
|
|
|
|
};
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
ClassMethod(SourceRange source_range, NonnullRefPtr<Expression const> key, NonnullRefPtr<FunctionExpression const> function, Kind kind, bool is_static)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ClassElement(move(source_range), is_static)
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_key(move(key))
|
2020-06-08 18:31:21 +00:00
|
|
|
, m_function(move(function))
|
|
|
|
, m_kind(kind)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& key() const { return *m_key; }
|
2020-06-08 18:31:21 +00:00
|
|
|
Kind kind() const { return m_kind; }
|
2021-10-06 23:09:04 +00:00
|
|
|
virtual ElementKind class_element_kind() const override { return ElementKind::Method; }
|
2020-06-08 18:31:21 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2023-06-25 15:33:17 +00:00
|
|
|
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const override;
|
2023-01-09 00:23:00 +00:00
|
|
|
virtual Optional<DeprecatedFlyString> private_bound_identifier() const override;
|
2020-06-08 18:31:21 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_class_method() const override { return true; }
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_key;
|
|
|
|
NonnullRefPtr<FunctionExpression const> m_function;
|
2020-06-08 18:31:21 +00:00
|
|
|
Kind m_kind;
|
|
|
|
};
|
|
|
|
|
2021-10-06 23:09:04 +00:00
|
|
|
class ClassField final : public ClassElement {
|
2021-08-28 15:11:05 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ClassField(SourceRange source_range, NonnullRefPtr<Expression const> key, RefPtr<Expression const> init, bool contains_direct_call_to_eval, bool is_static)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ClassElement(move(source_range), is_static)
|
2021-08-28 15:11:05 +00:00
|
|
|
, m_key(move(key))
|
|
|
|
, m_initializer(move(init))
|
2021-10-13 17:59:38 +00:00
|
|
|
, m_contains_direct_call_to_eval(contains_direct_call_to_eval)
|
2021-08-28 15:11:05 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Expression const& key() const { return *m_key; }
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<Expression const> const& initializer() const { return m_initializer; }
|
|
|
|
RefPtr<Expression const>& initializer() { return m_initializer; }
|
2021-08-28 15:11:05 +00:00
|
|
|
|
2021-10-06 23:09:04 +00:00
|
|
|
virtual ElementKind class_element_kind() const override { return ElementKind::Field; }
|
|
|
|
|
2021-08-28 15:11:05 +00:00
|
|
|
virtual void dump(int indent) const override;
|
2023-06-25 15:33:17 +00:00
|
|
|
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const override;
|
2023-01-09 00:23:00 +00:00
|
|
|
virtual Optional<DeprecatedFlyString> private_bound_identifier() const override;
|
2021-08-28 15:11:05 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_key;
|
|
|
|
RefPtr<Expression const> m_initializer;
|
2021-10-13 17:59:38 +00:00
|
|
|
bool m_contains_direct_call_to_eval { false };
|
2021-08-28 15:11:05 +00:00
|
|
|
};
|
|
|
|
|
2021-10-20 19:29:47 +00:00
|
|
|
class StaticInitializer final : public ClassElement {
|
|
|
|
public:
|
|
|
|
StaticInitializer(SourceRange source_range, NonnullRefPtr<FunctionBody> function_body, bool contains_direct_call_to_eval)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ClassElement(move(source_range), true)
|
2021-10-20 19:29:47 +00:00
|
|
|
, m_function_body(move(function_body))
|
|
|
|
, m_contains_direct_call_to_eval(contains_direct_call_to_eval)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ElementKind class_element_kind() const override { return ElementKind::StaticInitializer; }
|
2023-06-25 15:33:17 +00:00
|
|
|
virtual ThrowCompletionOr<ClassValue> class_element_evaluation(VM&, Object& home_object) const override;
|
2021-10-20 19:29:47 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
NonnullRefPtr<FunctionBody> m_function_body;
|
|
|
|
bool m_contains_direct_call_to_eval { false };
|
|
|
|
};
|
|
|
|
|
2020-06-08 18:31:21 +00:00
|
|
|
class SuperExpression final : public Expression {
|
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit SuperExpression(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-06-08 18:31:21 +00:00
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2021-06-13 09:23:23 +00:00
|
|
|
|
|
|
|
virtual bool is_super_expression() const override { return true; }
|
2020-06-08 18:31:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ClassExpression final : public Expression {
|
|
|
|
public:
|
2023-12-16 14:19:34 +00:00
|
|
|
ClassExpression(SourceRange source_range, RefPtr<Identifier const> name, ByteString source_text, RefPtr<FunctionExpression const> constructor, RefPtr<Expression const> super_class, Vector<NonnullRefPtr<ClassElement const>> elements)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_name(move(name))
|
2022-01-18 23:46:16 +00:00
|
|
|
, m_source_text(move(source_text))
|
2020-06-08 18:31:21 +00:00
|
|
|
, m_constructor(move(constructor))
|
|
|
|
, m_super_class(move(super_class))
|
2021-10-06 23:09:04 +00:00
|
|
|
, m_elements(move(elements))
|
2020-06-08 18:31:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-06-30 13:51:39 +00:00
|
|
|
StringView name() const { return m_name ? m_name->string().view() : ""sv; }
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString const& source_text() const { return m_source_text; }
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<FunctionExpression const> constructor() const { return m_constructor; }
|
2020-06-08 18:31:21 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name, Optional<Bytecode::Operand> preferred_dst = {}) const;
|
2020-06-08 18:31:21 +00:00
|
|
|
|
2023-06-30 13:51:39 +00:00
|
|
|
bool has_name() const { return m_name; }
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2024-01-24 19:55:56 +00:00
|
|
|
ThrowCompletionOr<ECMAScriptFunctionObject*> class_definition_evaluation(VM&, Optional<DeprecatedFlyString> const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
|
|
|
ThrowCompletionOr<ECMAScriptFunctionObject*> create_class_constructor(VM&, Environment* class_environment, Environment* environment, Value super_class, Optional<DeprecatedFlyString> const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2020-06-08 18:31:21 +00:00
|
|
|
private:
|
2021-10-07 10:05:13 +00:00
|
|
|
virtual bool is_class_expression() const override { return true; }
|
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
friend ClassDeclaration;
|
|
|
|
|
2023-06-30 13:51:39 +00:00
|
|
|
RefPtr<Identifier const> m_name;
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString m_source_text;
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<FunctionExpression const> m_constructor;
|
|
|
|
RefPtr<Expression const> m_super_class;
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<ClassElement const>> m_elements;
|
2020-06-08 18:31:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ClassDeclaration final : public Declaration {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ClassDeclaration(SourceRange source_range, NonnullRefPtr<ClassExpression const> class_expression)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Declaration(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_class_expression(move(class_expression))
|
2020-06-08 18:31:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-06-08 18:31:21 +00:00
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&&) const override;
|
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
virtual bool is_lexical_declaration() const override { return true; }
|
|
|
|
|
2021-11-26 23:01:23 +00:00
|
|
|
StringView name() const { return m_class_expression->name(); }
|
|
|
|
|
2020-06-08 18:31:21 +00:00
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_class_declaration() const override { return true; }
|
|
|
|
|
2022-01-18 18:07:13 +00:00
|
|
|
friend ExportStatement;
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<ClassExpression const> m_class_expression;
|
2020-06-08 18:31:21 +00:00
|
|
|
};
|
|
|
|
|
2023-06-17 08:11:23 +00:00
|
|
|
// We use this class to mimic Initializer : = AssignmentExpression of
|
|
|
|
// 10.2.1.3 Runtime Semantics: EvaluateBody, https://tc39.es/ecma262/#sec-runtime-semantics-evaluatebody
|
|
|
|
class ClassFieldInitializerStatement final : public Statement {
|
|
|
|
public:
|
|
|
|
ClassFieldInitializerStatement(SourceRange source_range, NonnullRefPtr<Expression const> expression, DeprecatedFlyString field_name)
|
|
|
|
: Statement(move(source_range))
|
|
|
|
, m_expression(move(expression))
|
|
|
|
, m_class_field_identifier_name(move(field_name))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2023-06-17 08:11:23 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
NonnullRefPtr<Expression const> m_expression;
|
|
|
|
DeprecatedFlyString m_class_field_identifier_name; // [[ClassFieldIdentifierName]]
|
|
|
|
};
|
|
|
|
|
2020-04-27 06:05:37 +00:00
|
|
|
class SpreadExpression final : public Expression {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
explicit SpreadExpression(SourceRange source_range, NonnullRefPtr<Expression const> target)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-06-24 11:38:21 +00:00
|
|
|
, m_target(move(target))
|
2020-04-27 06:05:37 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-27 06:05:37 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_target;
|
2020-04-27 06:05:37 +00:00
|
|
|
};
|
|
|
|
|
2020-04-12 22:42:14 +00:00
|
|
|
class ThisExpression final : public Expression {
|
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit ThisExpression(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-04-12 22:42:14 +00:00
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-12 22:42:14 +00:00
|
|
|
};
|
|
|
|
|
2022-11-26 18:51:50 +00:00
|
|
|
struct CallExpressionArgument {
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> value;
|
2022-11-26 18:51:50 +00:00
|
|
|
bool is_spread;
|
|
|
|
};
|
|
|
|
|
2023-06-15 09:43:48 +00:00
|
|
|
enum InvocationStyleEnum {
|
|
|
|
Parenthesized,
|
|
|
|
NotParenthesized,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum InsideParenthesesEnum {
|
|
|
|
InsideParentheses,
|
|
|
|
NotInsideParentheses,
|
|
|
|
};
|
|
|
|
|
2022-11-26 18:51:50 +00:00
|
|
|
class CallExpression : public ASTNodeWithTailArray<CallExpression, Expression, CallExpressionArgument> {
|
|
|
|
friend class ASTNodeWithTailArray;
|
|
|
|
|
2023-06-15 09:43:48 +00:00
|
|
|
InvocationStyleEnum m_invocation_style;
|
|
|
|
InsideParenthesesEnum m_inside_parentheses;
|
|
|
|
|
2020-03-07 18:42:11 +00:00
|
|
|
public:
|
2022-11-26 18:51:50 +00:00
|
|
|
using Argument = CallExpressionArgument;
|
2020-05-06 05:36:24 +00:00
|
|
|
|
2023-06-15 09:43:48 +00:00
|
|
|
static NonnullRefPtr<CallExpression> create(SourceRange, NonnullRefPtr<Expression const> callee, ReadonlySpan<Argument> arguments, InvocationStyleEnum invocation_style, InsideParenthesesEnum inside_parens);
|
2020-03-07 18:42:11 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-07 18:42:11 +00:00
|
|
|
|
2021-07-02 16:25:32 +00:00
|
|
|
Expression const& callee() const { return m_callee; }
|
|
|
|
|
2023-02-05 19:02:54 +00:00
|
|
|
ReadonlySpan<Argument> arguments() const { return tail_span(); }
|
2021-07-02 16:25:32 +00:00
|
|
|
|
2023-06-15 09:43:48 +00:00
|
|
|
bool is_parenthesized() const { return m_invocation_style == InvocationStyleEnum::Parenthesized; }
|
|
|
|
bool is_inside_parens() const { return m_inside_parentheses == InsideParenthesesEnum::InsideParentheses; }
|
|
|
|
void set_inside_parens() { m_inside_parentheses = InsideParenthesesEnum::InsideParentheses; }
|
|
|
|
|
2022-11-26 18:51:50 +00:00
|
|
|
protected:
|
2023-06-15 09:43:48 +00:00
|
|
|
CallExpression(SourceRange source_range, NonnullRefPtr<Expression const> callee, ReadonlySpan<Argument> arguments, InvocationStyleEnum invocation_style, InsideParenthesesEnum inside_parens = InsideParenthesesEnum::NotInsideParentheses)
|
2022-11-26 18:51:50 +00:00
|
|
|
: ASTNodeWithTailArray(move(source_range), arguments)
|
2023-06-15 09:43:48 +00:00
|
|
|
, m_invocation_style(invocation_style)
|
|
|
|
, m_inside_parentheses(inside_parens)
|
2022-11-26 18:51:50 +00:00
|
|
|
, m_callee(move(callee))
|
|
|
|
{
|
|
|
|
}
|
2021-07-02 16:43:25 +00:00
|
|
|
|
2022-11-26 18:51:50 +00:00
|
|
|
virtual bool is_call_expression() const override { return true; }
|
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
Optional<ByteString> expression_string() const;
|
2022-11-26 18:51:50 +00:00
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_callee;
|
2020-03-07 18:42:11 +00:00
|
|
|
};
|
|
|
|
|
2020-03-28 15:33:52 +00:00
|
|
|
class NewExpression final : public CallExpression {
|
2022-11-26 18:51:50 +00:00
|
|
|
friend class ASTNodeWithTailArray;
|
|
|
|
|
2020-03-28 15:33:52 +00:00
|
|
|
public:
|
2023-06-15 09:43:48 +00:00
|
|
|
static NonnullRefPtr<NewExpression> create(SourceRange, NonnullRefPtr<Expression const> callee, ReadonlySpan<Argument> arguments, InvocationStyleEnum invocation_style, InsideParenthesesEnum inside_parens);
|
2021-06-13 09:23:23 +00:00
|
|
|
|
|
|
|
virtual bool is_new_expression() const override { return true; }
|
2022-11-26 18:51:50 +00:00
|
|
|
|
|
|
|
private:
|
2023-06-15 09:43:48 +00:00
|
|
|
NewExpression(SourceRange source_range, NonnullRefPtr<Expression const> callee, ReadonlySpan<Argument> arguments, InvocationStyleEnum invocation_style, InsideParenthesesEnum inside_parens)
|
|
|
|
: CallExpression(move(source_range), move(callee), arguments, invocation_style, inside_parens)
|
2022-11-26 18:51:50 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-28 15:33:52 +00:00
|
|
|
};
|
|
|
|
|
2022-11-26 18:51:50 +00:00
|
|
|
static_assert(sizeof(NewExpression) == sizeof(CallExpression), "Adding members to NewExpression will break CallExpression memory layout");
|
|
|
|
|
2021-07-02 17:30:38 +00:00
|
|
|
class SuperCall final : public Expression {
|
|
|
|
public:
|
2022-08-20 15:27:02 +00:00
|
|
|
// This is here to be able to make a constructor like
|
|
|
|
// constructor(...args) { super(...args); } which does not use @@iterator of %Array.prototype%.
|
|
|
|
enum class IsPartOfSyntheticConstructor {
|
|
|
|
No,
|
|
|
|
Yes,
|
|
|
|
};
|
|
|
|
|
2021-07-02 17:30:38 +00:00
|
|
|
SuperCall(SourceRange source_range, Vector<CallExpression::Argument> arguments)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-07-02 17:30:38 +00:00
|
|
|
, m_arguments(move(arguments))
|
2022-08-20 15:27:02 +00:00
|
|
|
, m_is_synthetic(IsPartOfSyntheticConstructor::No)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SuperCall(SourceRange source_range, IsPartOfSyntheticConstructor is_part_of_synthetic_constructor, CallExpression::Argument constructor_argument)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2022-08-20 15:27:02 +00:00
|
|
|
, m_arguments({ move(constructor_argument) })
|
|
|
|
, m_is_synthetic(IsPartOfSyntheticConstructor::Yes)
|
2021-07-02 17:30:38 +00:00
|
|
|
{
|
2022-08-20 15:27:02 +00:00
|
|
|
VERIFY(is_part_of_synthetic_constructor == IsPartOfSyntheticConstructor::Yes);
|
2021-07-02 17:30:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2021-07-02 17:30:38 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Vector<CallExpression::Argument> const m_arguments;
|
2022-08-20 15:27:02 +00:00
|
|
|
IsPartOfSyntheticConstructor const m_is_synthetic;
|
2021-07-02 17:30:38 +00:00
|
|
|
};
|
|
|
|
|
2020-03-09 20:13:55 +00:00
|
|
|
enum class AssignmentOp {
|
2020-03-12 12:54:56 +00:00
|
|
|
Assignment,
|
|
|
|
AdditionAssignment,
|
|
|
|
SubtractionAssignment,
|
|
|
|
MultiplicationAssignment,
|
|
|
|
DivisionAssignment,
|
2020-05-04 22:07:05 +00:00
|
|
|
ModuloAssignment,
|
2020-05-04 22:03:35 +00:00
|
|
|
ExponentiationAssignment,
|
2020-05-04 21:34:45 +00:00
|
|
|
BitwiseAndAssignment,
|
|
|
|
BitwiseOrAssignment,
|
|
|
|
BitwiseXorAssignment,
|
2020-04-23 12:36:14 +00:00
|
|
|
LeftShiftAssignment,
|
2020-04-23 12:45:19 +00:00
|
|
|
RightShiftAssignment,
|
2020-04-23 14:43:10 +00:00
|
|
|
UnsignedRightShiftAssignment,
|
2020-10-05 15:49:43 +00:00
|
|
|
AndAssignment,
|
|
|
|
OrAssignment,
|
|
|
|
NullishAssignment,
|
2020-03-09 20:13:55 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class AssignmentExpression final : public Expression {
|
2020-03-09 20:13:55 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
AssignmentExpression(SourceRange source_range, AssignmentOp op, NonnullRefPtr<Expression const> lhs, NonnullRefPtr<Expression const> rhs)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_op(op)
|
2020-03-09 20:13:55 +00:00
|
|
|
, m_lhs(move(lhs))
|
|
|
|
, m_rhs(move(rhs))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
AssignmentExpression(SourceRange source_range, AssignmentOp op, NonnullRefPtr<BindingPattern const> lhs, NonnullRefPtr<Expression const> rhs)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-07-10 20:46:17 +00:00
|
|
|
, m_op(op)
|
|
|
|
, m_lhs(move(lhs))
|
|
|
|
, m_rhs(move(rhs))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-03-09 20:13:55 +00:00
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-09 20:13:55 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
AssignmentOp m_op;
|
2023-02-19 21:07:52 +00:00
|
|
|
Variant<NonnullRefPtr<Expression const>, NonnullRefPtr<BindingPattern const>> m_lhs;
|
|
|
|
NonnullRefPtr<Expression const> m_rhs;
|
2020-03-09 20:13:55 +00:00
|
|
|
};
|
|
|
|
|
2020-03-12 11:45:45 +00:00
|
|
|
enum class UpdateOp {
|
|
|
|
Increment,
|
|
|
|
Decrement,
|
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class UpdateExpression final : public Expression {
|
2020-03-12 11:45:45 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
UpdateExpression(SourceRange source_range, UpdateOp op, NonnullRefPtr<Expression const> argument, bool prefixed = false)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_op(op)
|
2020-03-12 11:45:45 +00:00
|
|
|
, m_argument(move(argument))
|
2020-03-14 18:44:57 +00:00
|
|
|
, m_prefixed(prefixed)
|
2020-03-12 11:45:45 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-12 11:45:45 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_update_expression() const override { return true; }
|
|
|
|
|
2020-03-12 11:45:45 +00:00
|
|
|
UpdateOp m_op;
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_argument;
|
2020-03-14 18:44:57 +00:00
|
|
|
bool m_prefixed;
|
2020-03-12 11:45:45 +00:00
|
|
|
};
|
|
|
|
|
2020-04-08 09:59:18 +00:00
|
|
|
enum class DeclarationKind {
|
2020-03-11 19:09:20 +00:00
|
|
|
Var,
|
|
|
|
Let,
|
2020-03-12 12:24:34 +00:00
|
|
|
Const,
|
2020-03-11 19:09:20 +00:00
|
|
|
};
|
|
|
|
|
2020-04-04 19:46:25 +00:00
|
|
|
class VariableDeclarator final : public ASTNode {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
VariableDeclarator(SourceRange source_range, NonnullRefPtr<Identifier const> id)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2021-05-29 11:33:19 +00:00
|
|
|
, m_target(move(id))
|
2020-04-21 18:21:26 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
VariableDeclarator(SourceRange source_range, NonnullRefPtr<Identifier const> target, RefPtr<Expression const> init)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2021-05-29 11:33:19 +00:00
|
|
|
, m_target(move(target))
|
2020-04-04 19:46:25 +00:00
|
|
|
, m_init(move(init))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
VariableDeclarator(SourceRange source_range, Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>> target, RefPtr<Expression const> init)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2021-05-29 11:33:19 +00:00
|
|
|
, m_target(move(target))
|
|
|
|
, m_init(move(init))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
auto& target() const { return m_target; }
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const* init() const { return m_init; }
|
2020-04-04 19:46:25 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>> m_target;
|
|
|
|
RefPtr<Expression const> m_init;
|
2020-04-04 19:46:25 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class VariableDeclaration final : public Declaration {
|
2020-03-09 20:13:55 +00:00
|
|
|
public:
|
2023-03-06 13:17:01 +00:00
|
|
|
VariableDeclaration(SourceRange source_range, DeclarationKind declaration_kind, Vector<NonnullRefPtr<VariableDeclarator const>> declarations)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Declaration(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_declaration_kind(declaration_kind)
|
2020-04-04 19:46:25 +00:00
|
|
|
, m_declarations(move(declarations))
|
2020-03-09 20:13:55 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-04-08 09:59:18 +00:00
|
|
|
DeclarationKind declaration_kind() const { return m_declaration_kind; }
|
2020-03-09 20:13:55 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-09 20:13:55 +00:00
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<VariableDeclarator const>> const& declarations() const { return m_declarations; }
|
2020-04-13 14:42:54 +00:00
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&&) const override;
|
|
|
|
|
2023-07-08 02:48:11 +00:00
|
|
|
virtual bool is_constant_declaration() const override { return m_declaration_kind == DeclarationKind::Const; }
|
2021-09-22 10:44:56 +00:00
|
|
|
|
|
|
|
virtual bool is_lexical_declaration() const override { return m_declaration_kind != DeclarationKind::Var; }
|
|
|
|
|
2020-03-09 20:13:55 +00:00
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_variable_declaration() const override { return true; }
|
|
|
|
|
2020-04-08 09:59:18 +00:00
|
|
|
DeclarationKind m_declaration_kind;
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<VariableDeclarator const>> m_declarations;
|
2020-03-09 20:13:55 +00:00
|
|
|
};
|
|
|
|
|
2022-12-20 21:09:57 +00:00
|
|
|
class UsingDeclaration final : public Declaration {
|
|
|
|
public:
|
2023-03-06 13:17:01 +00:00
|
|
|
UsingDeclaration(SourceRange source_range, Vector<NonnullRefPtr<VariableDeclarator const>> declarations)
|
2022-12-20 21:09:57 +00:00
|
|
|
: Declaration(move(source_range))
|
|
|
|
, m_declarations(move(declarations))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
2023-07-01 22:04:07 +00:00
|
|
|
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&&) const override;
|
|
|
|
|
2023-07-08 02:48:11 +00:00
|
|
|
virtual bool is_constant_declaration() const override { return true; }
|
2022-12-20 21:09:57 +00:00
|
|
|
|
|
|
|
virtual bool is_lexical_declaration() const override { return true; }
|
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<VariableDeclarator const>> const& declarations() const { return m_declarations; }
|
2022-12-23 00:45:29 +00:00
|
|
|
|
2022-12-20 21:09:57 +00:00
|
|
|
private:
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<VariableDeclarator const>> m_declarations;
|
2022-12-20 21:09:57 +00:00
|
|
|
};
|
|
|
|
|
2020-04-23 18:37:53 +00:00
|
|
|
class ObjectProperty final : public ASTNode {
|
|
|
|
public:
|
2022-11-26 18:55:46 +00:00
|
|
|
enum class Type : u8 {
|
2020-05-22 00:28:28 +00:00
|
|
|
KeyValue,
|
|
|
|
Getter,
|
|
|
|
Setter,
|
|
|
|
Spread,
|
2022-03-05 21:44:49 +00:00
|
|
|
ProtoSetter,
|
2020-05-22 00:28:28 +00:00
|
|
|
};
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
ObjectProperty(SourceRange source_range, NonnullRefPtr<Expression const> key, RefPtr<Expression const> value, Type property_type, bool is_method)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2020-05-22 00:28:28 +00:00
|
|
|
, m_property_type(property_type)
|
2020-06-08 18:31:21 +00:00
|
|
|
, m_is_method(is_method)
|
2022-11-26 18:55:46 +00:00
|
|
|
, m_key(move(key))
|
|
|
|
, m_value(move(value))
|
2020-04-23 18:37:53 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& key() const { return m_key; }
|
|
|
|
Expression const& value() const
|
2020-05-29 05:50:06 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(m_value);
|
2020-05-29 05:50:06 +00:00
|
|
|
return *m_value;
|
|
|
|
}
|
2020-04-23 18:37:53 +00:00
|
|
|
|
2020-05-22 00:28:28 +00:00
|
|
|
Type type() const { return m_property_type; }
|
2020-06-08 18:31:21 +00:00
|
|
|
bool is_method() const { return m_is_method; }
|
2020-04-28 04:52:47 +00:00
|
|
|
|
2020-04-23 18:37:53 +00:00
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
2020-05-22 00:28:28 +00:00
|
|
|
Type m_property_type;
|
2020-06-08 18:31:21 +00:00
|
|
|
bool m_is_method { false };
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_key;
|
|
|
|
RefPtr<Expression const> m_value;
|
2020-04-23 18:37:53 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class ObjectExpression final : public Expression {
|
2020-03-09 20:28:31 +00:00
|
|
|
public:
|
2023-03-06 13:17:01 +00:00
|
|
|
explicit ObjectExpression(SourceRange source_range, Vector<NonnullRefPtr<ObjectProperty>> properties = {})
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_properties(move(properties))
|
2020-03-21 00:29:00 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-09 20:28:31 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-09 20:28:31 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_object_expression() const override { return true; }
|
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<ObjectProperty>> m_properties;
|
2020-03-09 20:28:31 +00:00
|
|
|
};
|
|
|
|
|
2020-09-16 18:13:32 +00:00
|
|
|
class ArrayExpression final : public Expression {
|
2020-03-20 19:29:57 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ArrayExpression(SourceRange source_range, Vector<RefPtr<Expression const>> elements)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_elements(move(elements))
|
2020-03-20 19:29:57 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
Vector<RefPtr<Expression const>> const& elements() const { return m_elements; }
|
2020-03-20 19:29:57 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-20 19:29:57 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_array_expression() const override { return true; }
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
Vector<RefPtr<Expression const>> m_elements;
|
2020-03-20 19:29:57 +00:00
|
|
|
};
|
|
|
|
|
LibJS: Add template literals
Adds fully functioning template literals. Because template literals
contain expressions, most of the work has to be done in the Lexer rather
than the Parser. And because of the complexity of template literals
(expressions, nesting, escapes, etc), the Lexer needs to have some
template-related state.
When entering a new template literal, a TemplateLiteralStart token is
emitted. When inside a literal, all text will be parsed up until a '${'
or '`' (or EOF, but that's a syntax error) is seen, and then a
TemplateLiteralExprStart token is emitted. At this point, the Lexer
proceeds as normal, however it keeps track of the number of opening
and closing curly braces it has seen in order to determine the close
of the expression. Once it finds a matching curly brace for the '${',
a TemplateLiteralExprEnd token is emitted and the state is updated
accordingly.
When the Lexer is inside of a template literal, but not an expression,
and sees a '`', this must be the closing grave: a TemplateLiteralEnd
token is emitted.
The state required to correctly parse template strings consists of a
vector (for nesting) of two pieces of information: whether or not we
are in a template expression (as opposed to a template string); and
the count of the number of unmatched open curly braces we have seen
(only applicable if the Lexer is currently in a template expression).
TODO: Add support for template literal newlines in the JS REPL (this will
cause a syntax error currently):
> `foo
> bar`
'foo
bar'
2020-05-03 22:41:14 +00:00
|
|
|
class TemplateLiteral final : public Expression {
|
|
|
|
public:
|
2023-03-06 13:17:01 +00:00
|
|
|
TemplateLiteral(SourceRange source_range, Vector<NonnullRefPtr<Expression const>> expressions)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_expressions(move(expressions))
|
2020-05-06 23:34:14 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
TemplateLiteral(SourceRange source_range, Vector<NonnullRefPtr<Expression const>> expressions, Vector<NonnullRefPtr<Expression const>> raw_strings)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_expressions(move(expressions))
|
2020-05-06 23:34:14 +00:00
|
|
|
, m_raw_strings(move(raw_strings))
|
LibJS: Add template literals
Adds fully functioning template literals. Because template literals
contain expressions, most of the work has to be done in the Lexer rather
than the Parser. And because of the complexity of template literals
(expressions, nesting, escapes, etc), the Lexer needs to have some
template-related state.
When entering a new template literal, a TemplateLiteralStart token is
emitted. When inside a literal, all text will be parsed up until a '${'
or '`' (or EOF, but that's a syntax error) is seen, and then a
TemplateLiteralExprStart token is emitted. At this point, the Lexer
proceeds as normal, however it keeps track of the number of opening
and closing curly braces it has seen in order to determine the close
of the expression. Once it finds a matching curly brace for the '${',
a TemplateLiteralExprEnd token is emitted and the state is updated
accordingly.
When the Lexer is inside of a template literal, but not an expression,
and sees a '`', this must be the closing grave: a TemplateLiteralEnd
token is emitted.
The state required to correctly parse template strings consists of a
vector (for nesting) of two pieces of information: whether or not we
are in a template expression (as opposed to a template string); and
the count of the number of unmatched open curly braces we have seen
(only applicable if the Lexer is currently in a template expression).
TODO: Add support for template literal newlines in the JS REPL (this will
cause a syntax error currently):
> `foo
> bar`
'foo
bar'
2020-05-03 22:41:14 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
LibJS: Add template literals
Adds fully functioning template literals. Because template literals
contain expressions, most of the work has to be done in the Lexer rather
than the Parser. And because of the complexity of template literals
(expressions, nesting, escapes, etc), the Lexer needs to have some
template-related state.
When entering a new template literal, a TemplateLiteralStart token is
emitted. When inside a literal, all text will be parsed up until a '${'
or '`' (or EOF, but that's a syntax error) is seen, and then a
TemplateLiteralExprStart token is emitted. At this point, the Lexer
proceeds as normal, however it keeps track of the number of opening
and closing curly braces it has seen in order to determine the close
of the expression. Once it finds a matching curly brace for the '${',
a TemplateLiteralExprEnd token is emitted and the state is updated
accordingly.
When the Lexer is inside of a template literal, but not an expression,
and sees a '`', this must be the closing grave: a TemplateLiteralEnd
token is emitted.
The state required to correctly parse template strings consists of a
vector (for nesting) of two pieces of information: whether or not we
are in a template expression (as opposed to a template string); and
the count of the number of unmatched open curly braces we have seen
(only applicable if the Lexer is currently in a template expression).
TODO: Add support for template literal newlines in the JS REPL (this will
cause a syntax error currently):
> `foo
> bar`
'foo
bar'
2020-05-03 22:41:14 +00:00
|
|
|
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<Expression const>> const& expressions() const { return m_expressions; }
|
|
|
|
Vector<NonnullRefPtr<Expression const>> const& raw_strings() const { return m_raw_strings; }
|
LibJS: Add template literals
Adds fully functioning template literals. Because template literals
contain expressions, most of the work has to be done in the Lexer rather
than the Parser. And because of the complexity of template literals
(expressions, nesting, escapes, etc), the Lexer needs to have some
template-related state.
When entering a new template literal, a TemplateLiteralStart token is
emitted. When inside a literal, all text will be parsed up until a '${'
or '`' (or EOF, but that's a syntax error) is seen, and then a
TemplateLiteralExprStart token is emitted. At this point, the Lexer
proceeds as normal, however it keeps track of the number of opening
and closing curly braces it has seen in order to determine the close
of the expression. Once it finds a matching curly brace for the '${',
a TemplateLiteralExprEnd token is emitted and the state is updated
accordingly.
When the Lexer is inside of a template literal, but not an expression,
and sees a '`', this must be the closing grave: a TemplateLiteralEnd
token is emitted.
The state required to correctly parse template strings consists of a
vector (for nesting) of two pieces of information: whether or not we
are in a template expression (as opposed to a template string); and
the count of the number of unmatched open curly braces we have seen
(only applicable if the Lexer is currently in a template expression).
TODO: Add support for template literal newlines in the JS REPL (this will
cause a syntax error currently):
> `foo
> bar`
'foo
bar'
2020-05-03 22:41:14 +00:00
|
|
|
|
|
|
|
private:
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<Expression const>> const m_expressions;
|
|
|
|
Vector<NonnullRefPtr<Expression const>> const m_raw_strings;
|
LibJS: Add template literals
Adds fully functioning template literals. Because template literals
contain expressions, most of the work has to be done in the Lexer rather
than the Parser. And because of the complexity of template literals
(expressions, nesting, escapes, etc), the Lexer needs to have some
template-related state.
When entering a new template literal, a TemplateLiteralStart token is
emitted. When inside a literal, all text will be parsed up until a '${'
or '`' (or EOF, but that's a syntax error) is seen, and then a
TemplateLiteralExprStart token is emitted. At this point, the Lexer
proceeds as normal, however it keeps track of the number of opening
and closing curly braces it has seen in order to determine the close
of the expression. Once it finds a matching curly brace for the '${',
a TemplateLiteralExprEnd token is emitted and the state is updated
accordingly.
When the Lexer is inside of a template literal, but not an expression,
and sees a '`', this must be the closing grave: a TemplateLiteralEnd
token is emitted.
The state required to correctly parse template strings consists of a
vector (for nesting) of two pieces of information: whether or not we
are in a template expression (as opposed to a template string); and
the count of the number of unmatched open curly braces we have seen
(only applicable if the Lexer is currently in a template expression).
TODO: Add support for template literal newlines in the JS REPL (this will
cause a syntax error currently):
> `foo
> bar`
'foo
bar'
2020-05-03 22:41:14 +00:00
|
|
|
};
|
|
|
|
|
2020-05-06 09:17:35 +00:00
|
|
|
class TaggedTemplateLiteral final : public Expression {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
TaggedTemplateLiteral(SourceRange source_range, NonnullRefPtr<Expression const> tag, NonnullRefPtr<TemplateLiteral const> template_literal)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_tag(move(tag))
|
2020-05-06 09:17:35 +00:00
|
|
|
, m_template_literal(move(template_literal))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-05-06 09:17:35 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> const m_tag;
|
|
|
|
NonnullRefPtr<TemplateLiteral const> const m_template_literal;
|
2020-05-06 09:17:35 +00:00
|
|
|
};
|
|
|
|
|
2020-03-11 17:58:19 +00:00
|
|
|
class MemberExpression final : public Expression {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
MemberExpression(SourceRange source_range, NonnullRefPtr<Expression const> object, NonnullRefPtr<Expression const> property, bool computed = false)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2022-11-26 18:04:15 +00:00
|
|
|
, m_computed(computed)
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_object(move(object))
|
2020-03-11 17:58:19 +00:00
|
|
|
, m_property(move(property))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-11 17:58:19 +00:00
|
|
|
|
2020-03-20 19:51:03 +00:00
|
|
|
bool is_computed() const { return m_computed; }
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& object() const { return *m_object; }
|
|
|
|
Expression const& property() const { return *m_property; }
|
2020-03-15 14:01:10 +00:00
|
|
|
|
2023-12-16 14:19:34 +00:00
|
|
|
ByteString to_string_approximation() const;
|
2020-04-19 00:12:51 +00:00
|
|
|
|
2021-10-12 20:45:52 +00:00
|
|
|
bool ends_in_private_name() const;
|
|
|
|
|
2020-03-11 17:58:19 +00:00
|
|
|
private:
|
2021-06-13 09:23:23 +00:00
|
|
|
virtual bool is_member_expression() const override { return true; }
|
|
|
|
|
2022-11-26 18:04:15 +00:00
|
|
|
bool m_computed { false };
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_object;
|
|
|
|
NonnullRefPtr<Expression const> m_property;
|
2020-03-11 17:58:19 +00:00
|
|
|
};
|
|
|
|
|
2021-09-14 02:26:31 +00:00
|
|
|
class OptionalChain final : public Expression {
|
|
|
|
public:
|
|
|
|
enum class Mode {
|
|
|
|
Optional,
|
|
|
|
NotOptional,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Call {
|
|
|
|
Vector<CallExpression::Argument> arguments;
|
|
|
|
Mode mode;
|
|
|
|
};
|
|
|
|
struct ComputedReference {
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> expression;
|
2021-09-14 02:26:31 +00:00
|
|
|
Mode mode;
|
|
|
|
};
|
|
|
|
struct MemberReference {
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Identifier const> identifier;
|
2021-09-14 02:26:31 +00:00
|
|
|
Mode mode;
|
|
|
|
};
|
2021-10-18 21:32:47 +00:00
|
|
|
struct PrivateMemberReference {
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<PrivateIdentifier const> private_identifier;
|
2021-10-18 21:32:47 +00:00
|
|
|
Mode mode;
|
|
|
|
};
|
2021-09-14 02:26:31 +00:00
|
|
|
|
2021-10-18 21:32:47 +00:00
|
|
|
using Reference = Variant<Call, ComputedReference, MemberReference, PrivateMemberReference>;
|
2021-09-14 02:26:31 +00:00
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
OptionalChain(SourceRange source_range, NonnullRefPtr<Expression const> base, Vector<Reference> references)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-09-14 02:26:31 +00:00
|
|
|
, m_base(move(base))
|
|
|
|
, m_references(move(references))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2023-06-17 13:50:23 +00:00
|
|
|
|
|
|
|
Expression const& base() const { return *m_base; }
|
|
|
|
Vector<Reference> const& references() const { return m_references; }
|
2021-09-14 02:26:31 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_base;
|
2021-09-14 02:26:31 +00:00
|
|
|
Vector<Reference> m_references;
|
|
|
|
};
|
|
|
|
|
2020-11-02 21:27:42 +00:00
|
|
|
class MetaProperty final : public Expression {
|
|
|
|
public:
|
|
|
|
enum class Type {
|
|
|
|
NewTarget,
|
|
|
|
ImportMeta,
|
|
|
|
};
|
|
|
|
|
2020-12-28 17:15:22 +00:00
|
|
|
MetaProperty(SourceRange source_range, Type type)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_type(type)
|
2020-11-02 21:27:42 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-11-02 21:27:42 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Type m_type;
|
|
|
|
};
|
|
|
|
|
2021-11-26 22:45:10 +00:00
|
|
|
class ImportCall final : public Expression {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ImportCall(SourceRange source_range, NonnullRefPtr<Expression const> specifier, RefPtr<Expression const> options)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-11-26 22:45:10 +00:00
|
|
|
, m_specifier(move(specifier))
|
|
|
|
, m_options(move(options))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2021-11-26 22:45:10 +00:00
|
|
|
|
|
|
|
private:
|
2022-02-13 12:07:38 +00:00
|
|
|
virtual bool is_import_call() const override { return true; }
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_specifier;
|
|
|
|
RefPtr<Expression const> m_options;
|
2021-11-26 22:45:10 +00:00
|
|
|
};
|
|
|
|
|
2020-04-03 10:14:28 +00:00
|
|
|
class ConditionalExpression final : public Expression {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
ConditionalExpression(SourceRange source_range, NonnullRefPtr<Expression const> test, NonnullRefPtr<Expression const> consequent, NonnullRefPtr<Expression const> alternate)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_test(move(test))
|
2020-04-03 10:14:28 +00:00
|
|
|
, m_consequent(move(consequent))
|
|
|
|
, m_alternate(move(alternate))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-03 10:14:28 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_test;
|
|
|
|
NonnullRefPtr<Expression const> m_consequent;
|
|
|
|
NonnullRefPtr<Expression const> m_alternate;
|
2020-04-03 10:14:28 +00:00
|
|
|
};
|
|
|
|
|
2020-03-24 13:03:55 +00:00
|
|
|
class CatchClause final : public ASTNode {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
CatchClause(SourceRange source_range, DeprecatedFlyString parameter, NonnullRefPtr<BlockStatement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2021-06-24 11:38:21 +00:00
|
|
|
, m_parameter(move(parameter))
|
2020-03-24 13:03:55 +00:00
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
CatchClause(SourceRange source_range, NonnullRefPtr<BindingPattern const> parameter, NonnullRefPtr<BlockStatement const> body)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ASTNode(move(source_range))
|
2021-07-11 10:45:38 +00:00
|
|
|
, m_parameter(move(parameter))
|
|
|
|
, m_body(move(body))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
auto& parameter() const { return m_parameter; }
|
2021-06-10 21:43:06 +00:00
|
|
|
BlockStatement const& body() const { return m_body; }
|
2020-03-24 13:03:55 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
Variant<DeprecatedFlyString, NonnullRefPtr<BindingPattern const>> m_parameter;
|
|
|
|
NonnullRefPtr<BlockStatement const> m_body;
|
2020-03-24 13:03:55 +00:00
|
|
|
};
|
|
|
|
|
LibJS: Replace the custom unwind mechanism with completions :^)
This includes:
- Parsing proper LabelledStatements with try_parse_labelled_statement()
- Removing LabelableStatement
- Implementing the LoopEvaluation semantics via loop_evaluation() in
each IterationStatement subclass; and IterationStatement evaluation
via {For,ForIn,ForOf,ForAwaitOf,While,DoWhile}Statement::execute()
- Updating ReturnStatement, BreakStatement and ContinueStatement to
return the appropriate completion types
- Basically reimplementing TryStatement and SwitchStatement according to
the spec, using completions
- Honoring result completion types in AsyncBlockStart and
OrdinaryCallEvaluateBody
- Removing any uses of the VM unwind mechanism - most importantly,
VM::throw_exception() now exclusively sets an exception and no longer
triggers any unwinding mechanism.
However, we already did a good job updating all of LibWeb and userland
applications to not use it, and the few remaining uses elsewhere don't
rely on unwinding AFAICT.
2022-01-05 18:11:16 +00:00
|
|
|
class TryStatement final : public Statement {
|
2020-03-24 13:03:55 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
TryStatement(SourceRange source_range, NonnullRefPtr<BlockStatement const> block, RefPtr<CatchClause const> handler, RefPtr<BlockStatement const> finalizer)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_block(move(block))
|
2020-03-24 13:03:55 +00:00
|
|
|
, m_handler(move(handler))
|
|
|
|
, m_finalizer(move(finalizer))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
BlockStatement const& block() const { return m_block; }
|
|
|
|
CatchClause const* handler() const { return m_handler; }
|
|
|
|
BlockStatement const* finalizer() const { return m_finalizer; }
|
2020-03-24 13:03:55 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-24 13:03:55 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<BlockStatement const> m_block;
|
|
|
|
RefPtr<CatchClause const> m_handler;
|
|
|
|
RefPtr<BlockStatement const> m_finalizer;
|
2020-03-24 13:03:55 +00:00
|
|
|
};
|
|
|
|
|
2020-03-24 21:03:50 +00:00
|
|
|
class ThrowStatement final : public Statement {
|
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
explicit ThrowStatement(SourceRange source_range, NonnullRefPtr<Expression const> argument)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_argument(move(argument))
|
2020-03-24 21:03:50 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const& argument() const { return m_argument; }
|
2020-03-24 21:03:50 +00:00
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-03-24 21:03:50 +00:00
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_argument;
|
2020-03-24 21:03:50 +00:00
|
|
|
};
|
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
class SwitchCase final : public ScopeNode {
|
2020-03-29 11:09:54 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
SwitchCase(SourceRange source_range, RefPtr<Expression const> test)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ScopeNode(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_test(move(test))
|
2020-03-29 11:09:54 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:43:06 +00:00
|
|
|
Expression const* test() const { return m_test; }
|
2020-03-29 12:34:25 +00:00
|
|
|
|
2020-03-29 11:09:54 +00:00
|
|
|
virtual void dump(int indent) const override;
|
|
|
|
|
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
RefPtr<Expression const> m_test;
|
2020-03-29 11:09:54 +00:00
|
|
|
};
|
|
|
|
|
2021-09-22 10:44:56 +00:00
|
|
|
class SwitchStatement final : public ScopeNode {
|
2020-03-29 11:09:54 +00:00
|
|
|
public:
|
2023-02-19 21:07:52 +00:00
|
|
|
SwitchStatement(SourceRange source_range, NonnullRefPtr<Expression const> discriminant)
|
2023-08-08 11:11:33 +00:00
|
|
|
: ScopeNode(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
, m_discriminant(move(discriminant))
|
2020-03-29 11:09:54 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dump(int indent) const override;
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<DeprecatedFlyString> const&, Optional<Bytecode::Operand> preferred_dst = {}) const;
|
2020-03-29 11:09:54 +00:00
|
|
|
|
2023-02-19 21:07:52 +00:00
|
|
|
void add_case(NonnullRefPtr<SwitchCase const> switch_case) { m_cases.append(move(switch_case)); }
|
2021-09-22 10:44:56 +00:00
|
|
|
|
2020-03-29 11:09:54 +00:00
|
|
|
private:
|
2023-02-19 21:07:52 +00:00
|
|
|
NonnullRefPtr<Expression const> m_discriminant;
|
2023-03-06 13:17:01 +00:00
|
|
|
Vector<NonnullRefPtr<SwitchCase const>> m_cases;
|
2020-03-29 11:09:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class BreakStatement final : public Statement {
|
|
|
|
public:
|
2024-01-24 18:32:02 +00:00
|
|
|
BreakStatement(SourceRange source_range, Optional<DeprecatedFlyString> target_label)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2021-06-24 11:38:21 +00:00
|
|
|
, m_target_label(move(target_label))
|
2020-05-28 19:02:32 +00:00
|
|
|
{
|
|
|
|
}
|
2020-03-29 11:09:54 +00:00
|
|
|
|
2024-01-24 18:32:02 +00:00
|
|
|
Optional<DeprecatedFlyString> const& target_label() const { return m_target_label; }
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-05-28 19:02:32 +00:00
|
|
|
|
2020-03-29 11:09:54 +00:00
|
|
|
private:
|
2024-01-24 18:32:02 +00:00
|
|
|
Optional<DeprecatedFlyString> m_target_label;
|
2020-03-29 11:09:54 +00:00
|
|
|
};
|
|
|
|
|
2020-04-04 22:22:42 +00:00
|
|
|
class ContinueStatement final : public Statement {
|
|
|
|
public:
|
2024-01-24 18:32:02 +00:00
|
|
|
ContinueStatement(SourceRange source_range, Optional<DeprecatedFlyString> target_label)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2021-06-24 11:38:21 +00:00
|
|
|
, m_target_label(move(target_label))
|
2020-05-28 19:02:32 +00:00
|
|
|
{
|
|
|
|
}
|
2020-04-04 22:22:42 +00:00
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-04 22:22:42 +00:00
|
|
|
|
2024-01-24 18:32:02 +00:00
|
|
|
Optional<DeprecatedFlyString> const& target_label() const { return m_target_label; }
|
2020-05-28 19:02:32 +00:00
|
|
|
|
2020-04-04 22:22:42 +00:00
|
|
|
private:
|
2024-01-24 18:32:02 +00:00
|
|
|
Optional<DeprecatedFlyString> m_target_label;
|
2020-04-04 22:22:42 +00:00
|
|
|
};
|
|
|
|
|
2020-04-30 16:26:27 +00:00
|
|
|
class DebuggerStatement final : public Statement {
|
|
|
|
public:
|
2021-06-24 11:38:21 +00:00
|
|
|
explicit DebuggerStatement(SourceRange source_range)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Statement(move(source_range))
|
2020-12-28 17:15:22 +00:00
|
|
|
{
|
|
|
|
}
|
2020-04-30 16:26:27 +00:00
|
|
|
|
2024-02-03 19:16:02 +00:00
|
|
|
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::Operand> preferred_dst = {}) const override;
|
2020-04-30 16:26:27 +00:00
|
|
|
};
|
|
|
|
|
2021-09-14 02:26:31 +00:00
|
|
|
class SyntheticReferenceExpression final : public Expression {
|
|
|
|
public:
|
|
|
|
explicit SyntheticReferenceExpression(SourceRange source_range, Reference reference, Value value)
|
2023-08-08 11:11:33 +00:00
|
|
|
: Expression(move(source_range))
|
2021-09-14 02:26:31 +00:00
|
|
|
, m_reference(move(reference))
|
|
|
|
, m_value(value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Reference m_reference;
|
|
|
|
Value m_value;
|
|
|
|
};
|
|
|
|
|
2021-06-13 09:23:23 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<NewExpression>() const { return is_new_expression(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<MemberExpression>() const { return is_member_expression(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<SuperExpression>() const { return is_super_expression(); }
|
|
|
|
|
2021-10-07 10:05:13 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<FunctionExpression>() const { return is_function_expression(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ClassExpression>() const { return is_class_expression(); }
|
|
|
|
|
2021-06-13 09:23:23 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<Identifier>() const { return is_identifier(); }
|
|
|
|
|
2022-03-05 22:49:37 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<PrivateIdentifier>() const { return is_private_identifier(); }
|
|
|
|
|
2021-06-13 09:23:23 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ExpressionStatement>() const { return is_expression_statement(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ScopeNode>() const { return is_scope_node(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<Program>() const { return is_program(); }
|
|
|
|
|
2022-02-13 12:07:38 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ClassDeclaration>() const { return is_class_declaration(); }
|
|
|
|
|
2021-10-07 21:07:52 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<FunctionDeclaration>() const { return is_function_declaration(); }
|
|
|
|
|
2022-02-13 12:07:38 +00:00
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<VariableDeclaration>() const { return is_variable_declaration(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ArrayExpression>() const { return is_array_expression(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ObjectExpression>() const { return is_object_expression(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ImportCall>() const { return is_import_call(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<StringLiteral>() const { return is_string_literal(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<UpdateExpression>() const { return is_update_expression(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<CallExpression>() const { return is_call_expression(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<LabelledStatement>() const { return is_labelled_statement(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<IterationStatement>() const { return is_iteration_statement(); }
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline bool ASTNode::fast_is<ClassMethod>() const { return is_class_method(); }
|
|
|
|
|
2020-03-07 18:42:11 +00:00
|
|
|
}
|