/src/serenity/Userland/Libraries/LibJS/AST.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020-2024, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org> |
4 | | * Copyright (c) 2021-2022, David Tuin <davidot@serenityos.org> |
5 | | * |
6 | | * SPDX-License-Identifier: BSD-2-Clause |
7 | | */ |
8 | | |
9 | | #include <AK/Demangle.h> |
10 | | #include <AK/HashMap.h> |
11 | | #include <AK/HashTable.h> |
12 | | #include <AK/QuickSort.h> |
13 | | #include <AK/ScopeGuard.h> |
14 | | #include <AK/StringBuilder.h> |
15 | | #include <AK/TemporaryChange.h> |
16 | | #include <LibCrypto/BigInt/SignedBigInteger.h> |
17 | | #include <LibJS/AST.h> |
18 | | #include <LibJS/Heap/ConservativeVector.h> |
19 | | #include <LibJS/Heap/MarkedVector.h> |
20 | | #include <LibJS/Runtime/AbstractOperations.h> |
21 | | #include <LibJS/Runtime/Accessor.h> |
22 | | #include <LibJS/Runtime/Array.h> |
23 | | #include <LibJS/Runtime/BigInt.h> |
24 | | #include <LibJS/Runtime/ECMAScriptFunctionObject.h> |
25 | | #include <LibJS/Runtime/Error.h> |
26 | | #include <LibJS/Runtime/FunctionEnvironment.h> |
27 | | #include <LibJS/Runtime/GlobalEnvironment.h> |
28 | | #include <LibJS/Runtime/GlobalObject.h> |
29 | | #include <LibJS/Runtime/Iterator.h> |
30 | | #include <LibJS/Runtime/NativeFunction.h> |
31 | | #include <LibJS/Runtime/ObjectEnvironment.h> |
32 | | #include <LibJS/Runtime/PrimitiveString.h> |
33 | | #include <LibJS/Runtime/PromiseCapability.h> |
34 | | #include <LibJS/Runtime/PromiseConstructor.h> |
35 | | #include <LibJS/Runtime/Reference.h> |
36 | | #include <LibJS/Runtime/RegExpObject.h> |
37 | | #include <LibJS/Runtime/Shape.h> |
38 | | #include <LibJS/Runtime/ValueInlines.h> |
39 | | #include <typeinfo> |
40 | | |
41 | | namespace JS { |
42 | | |
43 | | ASTNode::ASTNode(SourceRange source_range) |
44 | 6.22M | : m_start_offset(source_range.start.offset) |
45 | 6.22M | , m_source_code(source_range.code) |
46 | 6.22M | , m_end_offset(source_range.end.offset) |
47 | 6.22M | { |
48 | 6.22M | } |
49 | | |
50 | | SourceRange ASTNode::source_range() const |
51 | 599 | { |
52 | 599 | return m_source_code->range_from_offsets(m_start_offset, m_end_offset); |
53 | 599 | } |
54 | | |
55 | | ByteString ASTNode::class_name() const |
56 | 146 | { |
57 | | // NOTE: We strip the "JS::" prefix. |
58 | 146 | auto const* typename_ptr = typeid(*this).name(); |
59 | 146 | return demangle({ typename_ptr, strlen(typename_ptr) }).substring(4); |
60 | 146 | } |
61 | | |
62 | | static void print_indent(int indent) |
63 | 0 | { |
64 | 0 | out("{}", ByteString::repeated(' ', indent * 2)); |
65 | 0 | } |
66 | | |
67 | | static void update_function_name(Value value, DeprecatedFlyString const& name) |
68 | 0 | { |
69 | 0 | if (!value.is_function()) |
70 | 0 | return; |
71 | 0 | auto& function = value.as_function(); |
72 | 0 | if (is<ECMAScriptFunctionObject>(function) && function.name().is_empty()) |
73 | 0 | static_cast<ECMAScriptFunctionObject&>(function).set_name(name); |
74 | 0 | } |
75 | | |
76 | | void LabelledStatement::dump(int indent) const |
77 | 0 | { |
78 | 0 | ASTNode::dump(indent); |
79 | |
|
80 | 0 | print_indent(indent + 1); |
81 | 0 | outln("(Label)"); |
82 | 0 | print_indent(indent + 2); |
83 | 0 | outln("\"{}\"", m_label); |
84 | |
|
85 | 0 | print_indent(indent + 1); |
86 | 0 | outln("(Labelled item)"); |
87 | 0 | m_labelled_item->dump(indent + 2); |
88 | 0 | } |
89 | | |
90 | | // 15.2.5 Runtime Semantics: InstantiateOrdinaryFunctionExpression, https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression |
91 | | Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, DeprecatedFlyString given_name) const |
92 | 0 | { |
93 | 0 | auto& realm = *vm.current_realm(); |
94 | |
|
95 | 0 | if (given_name.is_empty()) |
96 | 0 | given_name = ""; |
97 | 0 | auto has_own_name = !name().is_empty(); |
98 | |
|
99 | 0 | auto const used_name = has_own_name ? name() : given_name.view(); |
100 | 0 | auto environment = NonnullGCPtr { *vm.running_execution_context().lexical_environment }; |
101 | 0 | if (has_own_name) { |
102 | 0 | VERIFY(environment); |
103 | 0 | environment = new_declarative_environment(*environment); |
104 | 0 | MUST(environment->create_immutable_binding(vm, name(), false)); |
105 | 0 | } |
106 | | |
107 | 0 | auto private_environment = vm.running_execution_context().private_environment; |
108 | |
|
109 | 0 | auto closure = ECMAScriptFunctionObject::create(realm, used_name, source_text(), body(), parameters(), function_length(), local_variables_names(), environment, private_environment, kind(), is_strict_mode(), |
110 | 0 | parsing_insights(), is_arrow_function()); |
111 | | |
112 | | // FIXME: 6. Perform SetFunctionName(closure, name). |
113 | | // FIXME: 7. Perform MakeConstructor(closure). |
114 | |
|
115 | 0 | if (has_own_name) |
116 | 0 | MUST(environment->initialize_binding(vm, name(), closure, Environment::InitializeBindingHint::Normal)); |
117 | |
|
118 | 0 | return closure; |
119 | 0 | } |
120 | | |
121 | | Optional<ByteString> CallExpression::expression_string() const |
122 | 0 | { |
123 | 0 | if (is<Identifier>(*m_callee)) |
124 | 0 | return static_cast<Identifier const&>(*m_callee).string(); |
125 | | |
126 | 0 | if (is<MemberExpression>(*m_callee)) |
127 | 0 | return static_cast<MemberExpression const&>(*m_callee).to_string_approximation(); |
128 | | |
129 | 0 | return {}; |
130 | 0 | } |
131 | | |
132 | | static ThrowCompletionOr<ClassElementName> class_key_to_property_name(VM& vm, Expression const& key, Value prop_key) |
133 | 0 | { |
134 | 0 | if (is<PrivateIdentifier>(key)) { |
135 | 0 | auto& private_identifier = static_cast<PrivateIdentifier const&>(key); |
136 | 0 | auto private_environment = vm.running_execution_context().private_environment; |
137 | 0 | VERIFY(private_environment); |
138 | 0 | return ClassElementName { private_environment->resolve_private_identifier(private_identifier.string()) }; |
139 | 0 | } |
140 | | |
141 | 0 | VERIFY(!prop_key.is_empty()); |
142 | | |
143 | 0 | if (prop_key.is_object()) |
144 | 0 | prop_key = TRY(prop_key.to_primitive(vm, Value::PreferredType::String)); |
145 | |
|
146 | 0 | auto property_key = TRY(PropertyKey::from_value(vm, prop_key)); |
147 | 0 | return ClassElementName { property_key }; |
148 | 0 | } |
149 | | |
150 | | // 15.4.5 Runtime Semantics: MethodDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-methoddefinitionevaluation |
151 | | ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluation(VM& vm, Object& target, Value property_key) const |
152 | 0 | { |
153 | 0 | auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key)); |
154 | |
|
155 | 0 | auto& method_function = *ECMAScriptFunctionObject::create(*vm.current_realm(), m_function->name(), m_function->source_text(), m_function->body(), m_function->parameters(), m_function->function_length(), m_function->local_variables_names(), vm.lexical_environment(), vm.running_execution_context().private_environment, m_function->kind(), m_function->is_strict_mode(), |
156 | 0 | m_function->parsing_insights(), m_function->is_arrow_function()); |
157 | |
|
158 | 0 | auto method_value = Value(&method_function); |
159 | 0 | method_function.make_method(target); |
160 | |
|
161 | 0 | auto set_function_name = [&](ByteString prefix = "") { |
162 | 0 | auto name = property_key_or_private_name.visit( |
163 | 0 | [&](PropertyKey const& property_key) -> ByteString { |
164 | 0 | if (property_key.is_symbol()) { |
165 | 0 | auto description = property_key.as_symbol()->description(); |
166 | 0 | if (!description.has_value() || description->is_empty()) |
167 | 0 | return ""; |
168 | 0 | return ByteString::formatted("[{}]", *description); |
169 | 0 | } else { |
170 | 0 | return property_key.to_string(); |
171 | 0 | } |
172 | 0 | }, |
173 | 0 | [&](PrivateName const& private_name) -> ByteString { |
174 | 0 | return private_name.description; |
175 | 0 | }); |
176 | |
|
177 | 0 | update_function_name(method_value, ByteString::formatted("{}{}{}", prefix, prefix.is_empty() ? "" : " ", name)); |
178 | 0 | }; |
179 | |
|
180 | 0 | if (property_key_or_private_name.has<PropertyKey>()) { |
181 | 0 | auto& property_key = property_key_or_private_name.get<PropertyKey>(); |
182 | 0 | switch (kind()) { |
183 | 0 | case ClassMethod::Kind::Method: |
184 | 0 | set_function_name(); |
185 | 0 | TRY(target.define_property_or_throw(property_key, { .value = method_value, .writable = true, .enumerable = false, .configurable = true })); |
186 | 0 | break; |
187 | 0 | case ClassMethod::Kind::Getter: |
188 | 0 | set_function_name("get"); |
189 | 0 | TRY(target.define_property_or_throw(property_key, { .get = &method_function, .enumerable = true, .configurable = true })); |
190 | 0 | break; |
191 | 0 | case ClassMethod::Kind::Setter: |
192 | 0 | set_function_name("set"); |
193 | 0 | TRY(target.define_property_or_throw(property_key, { .set = &method_function, .enumerable = true, .configurable = true })); |
194 | 0 | break; |
195 | 0 | default: |
196 | 0 | VERIFY_NOT_REACHED(); |
197 | 0 | } |
198 | | |
199 | 0 | return ClassValue { normal_completion({}) }; |
200 | 0 | } else { |
201 | 0 | auto& private_name = property_key_or_private_name.get<PrivateName>(); |
202 | 0 | switch (kind()) { |
203 | 0 | case Kind::Method: |
204 | 0 | set_function_name(); |
205 | 0 | return ClassValue { PrivateElement { private_name, PrivateElement::Kind::Method, method_value } }; |
206 | 0 | case Kind::Getter: |
207 | 0 | set_function_name("get"); |
208 | 0 | return ClassValue { PrivateElement { private_name, PrivateElement::Kind::Accessor, Value(Accessor::create(vm, &method_function, nullptr)) } }; |
209 | 0 | case Kind::Setter: |
210 | 0 | set_function_name("set"); |
211 | 0 | return ClassValue { PrivateElement { private_name, PrivateElement::Kind::Accessor, Value(Accessor::create(vm, nullptr, &method_function)) } }; |
212 | 0 | default: |
213 | 0 | VERIFY_NOT_REACHED(); |
214 | 0 | } |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | | void ClassFieldInitializerStatement::dump(int) const |
219 | 0 | { |
220 | | // This should not be dumped as it is never part of an actual AST. |
221 | 0 | VERIFY_NOT_REACHED(); |
222 | 0 | } |
223 | | |
224 | | // 15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classfielddefinitionevaluation |
225 | | ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation(VM& vm, Object& target, Value property_key) const |
226 | 0 | { |
227 | 0 | auto& realm = *vm.current_realm(); |
228 | |
|
229 | 0 | auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key)); |
230 | 0 | GCPtr<ECMAScriptFunctionObject> initializer; |
231 | 0 | if (m_initializer) { |
232 | 0 | auto copy_initializer = m_initializer; |
233 | 0 | auto name = property_key_or_private_name.visit( |
234 | 0 | [&](PropertyKey const& property_key) -> ByteString { |
235 | 0 | return property_key.is_number() ? property_key.to_string() : property_key.to_string_or_symbol().to_display_string(); |
236 | 0 | }, |
237 | 0 | [&](PrivateName const& private_name) -> ByteString { |
238 | 0 | return private_name.description; |
239 | 0 | }); |
240 | | |
241 | | // FIXME: A potential optimization is not creating the functions here since these are never directly accessible. |
242 | 0 | auto function_code = create_ast_node<ClassFieldInitializerStatement>(m_initializer->source_range(), copy_initializer.release_nonnull(), name); |
243 | 0 | FunctionParsingInsights parsing_insights; |
244 | 0 | parsing_insights.uses_this_from_environment = true; |
245 | 0 | parsing_insights.uses_this = true; |
246 | 0 | initializer = ECMAScriptFunctionObject::create(realm, "field", ByteString::empty(), *function_code, {}, 0, {}, vm.lexical_environment(), vm.running_execution_context().private_environment, FunctionKind::Normal, true, parsing_insights, false, property_key_or_private_name); |
247 | 0 | initializer->make_method(target); |
248 | 0 | } |
249 | |
|
250 | 0 | return ClassValue { |
251 | 0 | ClassFieldDefinition { |
252 | 0 | move(property_key_or_private_name), |
253 | 0 | move(initializer), |
254 | 0 | } |
255 | 0 | }; |
256 | 0 | } |
257 | | |
258 | | static Optional<DeprecatedFlyString> nullopt_or_private_identifier_description(Expression const& expression) |
259 | 0 | { |
260 | 0 | if (is<PrivateIdentifier>(expression)) |
261 | 0 | return static_cast<PrivateIdentifier const&>(expression).string(); |
262 | 0 | return {}; |
263 | 0 | } |
264 | | |
265 | | Optional<DeprecatedFlyString> ClassField::private_bound_identifier() const |
266 | 0 | { |
267 | 0 | return nullopt_or_private_identifier_description(*m_key); |
268 | 0 | } |
269 | | |
270 | | Optional<DeprecatedFlyString> ClassMethod::private_bound_identifier() const |
271 | 0 | { |
272 | 0 | return nullopt_or_private_identifier_description(*m_key); |
273 | 0 | } |
274 | | |
275 | | // 15.7.11 Runtime Semantics: ClassStaticBlockDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classstaticblockdefinitionevaluation |
276 | | ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_evaluation(VM& vm, Object& home_object, Value) const |
277 | 0 | { |
278 | 0 | auto& realm = *vm.current_realm(); |
279 | | |
280 | | // 1. Let lex be the running execution context's LexicalEnvironment. |
281 | 0 | auto lexical_environment = vm.running_execution_context().lexical_environment; |
282 | | |
283 | | // 2. Let privateEnv be the running execution context's PrivateEnvironment. |
284 | 0 | auto private_environment = vm.running_execution_context().private_environment; |
285 | | |
286 | | // 3. Let sourceText be the empty sequence of Unicode code points. |
287 | | // 4. Let formalParameters be an instance of the production FormalParameters : [empty] . |
288 | | // 5. Let bodyFunction be OrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameters, ClassStaticBlockBody, non-lexical-this, lex, privateEnv). |
289 | | // Note: The function bodyFunction is never directly accessible to ECMAScript code. |
290 | 0 | FunctionParsingInsights parsing_insights; |
291 | 0 | parsing_insights.uses_this_from_environment = true; |
292 | 0 | parsing_insights.uses_this = true; |
293 | 0 | auto body_function = ECMAScriptFunctionObject::create(realm, ByteString::empty(), ByteString::empty(), *m_function_body, {}, 0, m_function_body->local_variables_names(), lexical_environment, private_environment, FunctionKind::Normal, true, parsing_insights, false); |
294 | | |
295 | | // 6. Perform MakeMethod(bodyFunction, homeObject). |
296 | 0 | body_function->make_method(home_object); |
297 | | |
298 | | // 7. Return the ClassStaticBlockDefinition Record { [[BodyFunction]]: bodyFunction }. |
299 | 0 | return ClassValue { normal_completion(body_function) }; |
300 | 0 | } |
301 | | |
302 | | ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_constructor(VM& vm, Environment* class_environment, Environment* environment, Value super_class, ReadonlySpan<Value> element_keys, Optional<DeprecatedFlyString> const& binding_name, DeprecatedFlyString const& class_name) const |
303 | 0 | { |
304 | 0 | auto& realm = *vm.current_realm(); |
305 | | |
306 | | // We might not set the lexical environment but we always want to restore it eventually. |
307 | 0 | ArmedScopeGuard restore_environment = [&] { |
308 | 0 | vm.running_execution_context().lexical_environment = environment; |
309 | 0 | }; |
310 | |
|
311 | 0 | vm.running_execution_context().lexical_environment = class_environment; |
312 | |
|
313 | 0 | auto proto_parent = GCPtr { realm.intrinsics().object_prototype() }; |
314 | 0 | auto constructor_parent = realm.intrinsics().function_prototype(); |
315 | |
|
316 | 0 | if (!m_super_class.is_null()) { |
317 | 0 | if (super_class.is_null()) { |
318 | 0 | proto_parent = nullptr; |
319 | 0 | } else if (!super_class.is_constructor()) { |
320 | 0 | return vm.throw_completion<TypeError>(ErrorType::ClassExtendsValueNotAConstructorOrNull, super_class.to_string_without_side_effects()); |
321 | 0 | } else { |
322 | 0 | auto super_class_prototype = TRY(super_class.get(vm, vm.names.prototype)); |
323 | 0 | if (!super_class_prototype.is_null() && !super_class_prototype.is_object()) |
324 | 0 | return vm.throw_completion<TypeError>(ErrorType::ClassExtendsValueInvalidPrototype, super_class_prototype.to_string_without_side_effects()); |
325 | | |
326 | 0 | if (super_class_prototype.is_null()) |
327 | 0 | proto_parent = nullptr; |
328 | 0 | else |
329 | 0 | proto_parent = super_class_prototype.as_object(); |
330 | |
|
331 | 0 | constructor_parent = super_class.as_object(); |
332 | 0 | } |
333 | 0 | } |
334 | | |
335 | 0 | auto prototype = Object::create_prototype(realm, proto_parent); |
336 | 0 | VERIFY(prototype); |
337 | | |
338 | | // FIXME: Step 14.a is done in the parser. By using a synthetic super(...args) which does not call @@iterator of %Array.prototype% |
339 | 0 | auto const& constructor = *m_constructor; |
340 | 0 | auto parsing_insights = constructor.parsing_insights(); |
341 | 0 | parsing_insights.uses_this_from_environment = true; |
342 | 0 | parsing_insights.uses_this = true; |
343 | 0 | auto class_constructor = ECMAScriptFunctionObject::create( |
344 | 0 | realm, |
345 | 0 | constructor.name(), |
346 | 0 | constructor.source_text(), |
347 | 0 | constructor.body(), |
348 | 0 | constructor.parameters(), |
349 | 0 | constructor.function_length(), |
350 | 0 | constructor.local_variables_names(), |
351 | 0 | vm.lexical_environment(), |
352 | 0 | vm.running_execution_context().private_environment, |
353 | 0 | constructor.kind(), |
354 | 0 | constructor.is_strict_mode(), |
355 | 0 | parsing_insights, |
356 | 0 | constructor.is_arrow_function()); |
357 | |
|
358 | 0 | class_constructor->set_name(class_name); |
359 | 0 | class_constructor->set_home_object(prototype); |
360 | 0 | class_constructor->set_is_class_constructor(); |
361 | 0 | class_constructor->define_direct_property(vm.names.prototype, prototype, Attribute::Writable); |
362 | 0 | TRY(class_constructor->internal_set_prototype_of(constructor_parent)); |
363 | |
|
364 | 0 | if (!m_super_class.is_null()) |
365 | 0 | class_constructor->set_constructor_kind(ECMAScriptFunctionObject::ConstructorKind::Derived); |
366 | |
|
367 | 0 | prototype->define_direct_property(vm.names.constructor, class_constructor, Attribute::Writable | Attribute::Configurable); |
368 | |
|
369 | 0 | using StaticElement = Variant<ClassFieldDefinition, JS::NonnullGCPtr<ECMAScriptFunctionObject>>; |
370 | |
|
371 | 0 | ConservativeVector<PrivateElement> static_private_methods(vm.heap()); |
372 | 0 | ConservativeVector<PrivateElement> instance_private_methods(vm.heap()); |
373 | 0 | ConservativeVector<ClassFieldDefinition> instance_fields(vm.heap()); |
374 | 0 | ConservativeVector<StaticElement> static_elements(vm.heap()); |
375 | |
|
376 | 0 | for (size_t element_index = 0; element_index < m_elements.size(); element_index++) { |
377 | 0 | auto const& element = m_elements[element_index]; |
378 | | |
379 | | // Note: All ClassElementEvaluation start with evaluating the name (or we fake it). |
380 | 0 | auto element_value = TRY(element->class_element_evaluation(vm, element->is_static() ? *class_constructor : *prototype, element_keys[element_index])); |
381 | |
|
382 | 0 | if (element_value.has<PrivateElement>()) { |
383 | 0 | auto& container = element->is_static() ? static_private_methods : instance_private_methods; |
384 | |
|
385 | 0 | auto& private_element = element_value.get<PrivateElement>(); |
386 | |
|
387 | 0 | auto added_to_existing = false; |
388 | | // FIXME: We can skip this loop in most cases. |
389 | 0 | for (auto& existing : container) { |
390 | 0 | if (existing.key == private_element.key) { |
391 | 0 | VERIFY(existing.kind == PrivateElement::Kind::Accessor); |
392 | 0 | VERIFY(private_element.kind == PrivateElement::Kind::Accessor); |
393 | 0 | auto& accessor = private_element.value.as_accessor(); |
394 | 0 | if (!accessor.getter()) |
395 | 0 | existing.value.as_accessor().set_setter(accessor.setter()); |
396 | 0 | else |
397 | 0 | existing.value.as_accessor().set_getter(accessor.getter()); |
398 | 0 | added_to_existing = true; |
399 | 0 | } |
400 | 0 | } |
401 | | |
402 | 0 | if (!added_to_existing) |
403 | 0 | container.append(move(element_value.get<PrivateElement>())); |
404 | 0 | } else if (auto* class_field_definition_ptr = element_value.get_pointer<ClassFieldDefinition>()) { |
405 | 0 | if (element->is_static()) |
406 | 0 | static_elements.append(move(*class_field_definition_ptr)); |
407 | 0 | else |
408 | 0 | instance_fields.append(move(*class_field_definition_ptr)); |
409 | 0 | } else if (element->class_element_kind() == ClassElement::ElementKind::StaticInitializer) { |
410 | | // We use Completion to hold the ClassStaticBlockDefinition Record. |
411 | 0 | VERIFY(element_value.has<Completion>() && element_value.get<Completion>().value().has_value()); |
412 | 0 | auto& element_object = element_value.get<Completion>().value()->as_object(); |
413 | 0 | VERIFY(is<ECMAScriptFunctionObject>(element_object)); |
414 | 0 | static_elements.append(NonnullGCPtr { static_cast<ECMAScriptFunctionObject&>(element_object) }); |
415 | 0 | } |
416 | 0 | } |
417 | | |
418 | 0 | vm.running_execution_context().lexical_environment = environment; |
419 | 0 | restore_environment.disarm(); |
420 | |
|
421 | 0 | if (binding_name.has_value()) |
422 | 0 | MUST(class_environment->initialize_binding(vm, binding_name.value(), class_constructor, Environment::InitializeBindingHint::Normal)); |
423 | |
|
424 | 0 | for (auto& field : instance_fields) |
425 | 0 | class_constructor->add_field(field); |
426 | |
|
427 | 0 | for (auto& private_method : instance_private_methods) |
428 | 0 | class_constructor->add_private_method(private_method); |
429 | |
|
430 | 0 | for (auto& method : static_private_methods) |
431 | 0 | TRY(class_constructor->private_method_or_accessor_add(move(method))); |
432 | |
|
433 | 0 | for (auto& element : static_elements) { |
434 | 0 | TRY(element.visit( |
435 | 0 | [&](ClassFieldDefinition& field) -> ThrowCompletionOr<void> { |
436 | 0 | return TRY(class_constructor->define_field(field)); |
437 | 0 | }, |
438 | 0 | [&](Handle<ECMAScriptFunctionObject> static_block_function) -> ThrowCompletionOr<void> { |
439 | 0 | VERIFY(!static_block_function.is_null()); |
440 | | // We discard any value returned here. |
441 | 0 | TRY(call(vm, *static_block_function.cell(), class_constructor)); |
442 | 0 | return {}; |
443 | 0 | })); |
444 | 0 | } |
445 | |
|
446 | 0 | class_constructor->set_source_text(source_text()); |
447 | |
|
448 | 0 | return { class_constructor }; |
449 | 0 | } |
450 | | |
451 | | void ASTNode::dump(int indent) const |
452 | 0 | { |
453 | 0 | print_indent(indent); |
454 | 0 | outln("{}", class_name()); |
455 | 0 | } |
456 | | |
457 | | void ScopeNode::dump(int indent) const |
458 | 0 | { |
459 | 0 | ASTNode::dump(indent); |
460 | 0 | if (!m_children.is_empty()) { |
461 | 0 | print_indent(indent + 1); |
462 | 0 | outln("(Children)"); |
463 | 0 | for (auto& child : children()) |
464 | 0 | child->dump(indent + 2); |
465 | 0 | } |
466 | 0 | } |
467 | | |
468 | | void BinaryExpression::dump(int indent) const |
469 | 0 | { |
470 | 0 | char const* op_string = nullptr; |
471 | 0 | switch (m_op) { |
472 | 0 | case BinaryOp::Addition: |
473 | 0 | op_string = "+"; |
474 | 0 | break; |
475 | 0 | case BinaryOp::Subtraction: |
476 | 0 | op_string = "-"; |
477 | 0 | break; |
478 | 0 | case BinaryOp::Multiplication: |
479 | 0 | op_string = "*"; |
480 | 0 | break; |
481 | 0 | case BinaryOp::Division: |
482 | 0 | op_string = "/"; |
483 | 0 | break; |
484 | 0 | case BinaryOp::Modulo: |
485 | 0 | op_string = "%"; |
486 | 0 | break; |
487 | 0 | case BinaryOp::Exponentiation: |
488 | 0 | op_string = "**"; |
489 | 0 | break; |
490 | 0 | case BinaryOp::StrictlyEquals: |
491 | 0 | op_string = "==="; |
492 | 0 | break; |
493 | 0 | case BinaryOp::StrictlyInequals: |
494 | 0 | op_string = "!=="; |
495 | 0 | break; |
496 | 0 | case BinaryOp::LooselyEquals: |
497 | 0 | op_string = "=="; |
498 | 0 | break; |
499 | 0 | case BinaryOp::LooselyInequals: |
500 | 0 | op_string = "!="; |
501 | 0 | break; |
502 | 0 | case BinaryOp::GreaterThan: |
503 | 0 | op_string = ">"; |
504 | 0 | break; |
505 | 0 | case BinaryOp::GreaterThanEquals: |
506 | 0 | op_string = ">="; |
507 | 0 | break; |
508 | 0 | case BinaryOp::LessThan: |
509 | 0 | op_string = "<"; |
510 | 0 | break; |
511 | 0 | case BinaryOp::LessThanEquals: |
512 | 0 | op_string = "<="; |
513 | 0 | break; |
514 | 0 | case BinaryOp::BitwiseAnd: |
515 | 0 | op_string = "&"; |
516 | 0 | break; |
517 | 0 | case BinaryOp::BitwiseOr: |
518 | 0 | op_string = "|"; |
519 | 0 | break; |
520 | 0 | case BinaryOp::BitwiseXor: |
521 | 0 | op_string = "^"; |
522 | 0 | break; |
523 | 0 | case BinaryOp::LeftShift: |
524 | 0 | op_string = "<<"; |
525 | 0 | break; |
526 | 0 | case BinaryOp::RightShift: |
527 | 0 | op_string = ">>"; |
528 | 0 | break; |
529 | 0 | case BinaryOp::UnsignedRightShift: |
530 | 0 | op_string = ">>>"; |
531 | 0 | break; |
532 | 0 | case BinaryOp::In: |
533 | 0 | op_string = "in"; |
534 | 0 | break; |
535 | 0 | case BinaryOp::InstanceOf: |
536 | 0 | op_string = "instanceof"; |
537 | 0 | break; |
538 | 0 | } |
539 | | |
540 | 0 | print_indent(indent); |
541 | 0 | outln("{}", class_name()); |
542 | 0 | m_lhs->dump(indent + 1); |
543 | 0 | print_indent(indent + 1); |
544 | 0 | outln("{}", op_string); |
545 | 0 | m_rhs->dump(indent + 1); |
546 | 0 | } |
547 | | |
548 | | void LogicalExpression::dump(int indent) const |
549 | 0 | { |
550 | 0 | char const* op_string = nullptr; |
551 | 0 | switch (m_op) { |
552 | 0 | case LogicalOp::And: |
553 | 0 | op_string = "&&"; |
554 | 0 | break; |
555 | 0 | case LogicalOp::Or: |
556 | 0 | op_string = "||"; |
557 | 0 | break; |
558 | 0 | case LogicalOp::NullishCoalescing: |
559 | 0 | op_string = "??"; |
560 | 0 | break; |
561 | 0 | } |
562 | | |
563 | 0 | print_indent(indent); |
564 | 0 | outln("{}", class_name()); |
565 | 0 | m_lhs->dump(indent + 1); |
566 | 0 | print_indent(indent + 1); |
567 | 0 | outln("{}", op_string); |
568 | 0 | m_rhs->dump(indent + 1); |
569 | 0 | } |
570 | | |
571 | | void UnaryExpression::dump(int indent) const |
572 | 0 | { |
573 | 0 | char const* op_string = nullptr; |
574 | 0 | switch (m_op) { |
575 | 0 | case UnaryOp::BitwiseNot: |
576 | 0 | op_string = "~"; |
577 | 0 | break; |
578 | 0 | case UnaryOp::Not: |
579 | 0 | op_string = "!"; |
580 | 0 | break; |
581 | 0 | case UnaryOp::Plus: |
582 | 0 | op_string = "+"; |
583 | 0 | break; |
584 | 0 | case UnaryOp::Minus: |
585 | 0 | op_string = "-"; |
586 | 0 | break; |
587 | 0 | case UnaryOp::Typeof: |
588 | 0 | op_string = "typeof "; |
589 | 0 | break; |
590 | 0 | case UnaryOp::Void: |
591 | 0 | op_string = "void "; |
592 | 0 | break; |
593 | 0 | case UnaryOp::Delete: |
594 | 0 | op_string = "delete "; |
595 | 0 | break; |
596 | 0 | } |
597 | | |
598 | 0 | print_indent(indent); |
599 | 0 | outln("{}", class_name()); |
600 | 0 | print_indent(indent + 1); |
601 | 0 | outln("{}", op_string); |
602 | 0 | m_lhs->dump(indent + 1); |
603 | 0 | } |
604 | | |
605 | | void CallExpression::dump(int indent) const |
606 | 0 | { |
607 | 0 | print_indent(indent); |
608 | 0 | if (is<NewExpression>(*this)) |
609 | 0 | outln("CallExpression [new]"); |
610 | 0 | else |
611 | 0 | outln("CallExpression"); |
612 | 0 | m_callee->dump(indent + 1); |
613 | 0 | for (auto& argument : arguments()) |
614 | 0 | argument.value->dump(indent + 1); |
615 | 0 | } |
616 | | |
617 | | void SuperCall::dump(int indent) const |
618 | 0 | { |
619 | 0 | print_indent(indent); |
620 | 0 | outln("SuperCall"); |
621 | 0 | for (auto& argument : m_arguments) |
622 | 0 | argument.value->dump(indent + 1); |
623 | 0 | } |
624 | | |
625 | | void ClassDeclaration::dump(int indent) const |
626 | 0 | { |
627 | 0 | ASTNode::dump(indent); |
628 | 0 | m_class_expression->dump(indent + 1); |
629 | 0 | } |
630 | | |
631 | | ThrowCompletionOr<void> ClassDeclaration::for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const |
632 | 1 | { |
633 | 1 | if (!m_class_expression->m_name) |
634 | 0 | return {}; |
635 | | |
636 | 1 | return callback(*m_class_expression->m_name); |
637 | 1 | } |
638 | | |
639 | | void ClassExpression::dump(int indent) const |
640 | 0 | { |
641 | 0 | print_indent(indent); |
642 | 0 | outln("ClassExpression: \"{}\"", name()); |
643 | |
|
644 | 0 | print_indent(indent); |
645 | 0 | outln("(Constructor)"); |
646 | 0 | m_constructor->dump(indent + 1); |
647 | |
|
648 | 0 | if (!m_super_class.is_null()) { |
649 | 0 | print_indent(indent); |
650 | 0 | outln("(Super Class)"); |
651 | 0 | m_super_class->dump(indent + 1); |
652 | 0 | } |
653 | |
|
654 | 0 | print_indent(indent); |
655 | 0 | outln("(Elements)"); |
656 | 0 | for (auto& method : m_elements) |
657 | 0 | method->dump(indent + 1); |
658 | 0 | } |
659 | | |
660 | | void ClassMethod::dump(int indent) const |
661 | 0 | { |
662 | 0 | ASTNode::dump(indent); |
663 | |
|
664 | 0 | print_indent(indent); |
665 | 0 | outln("(Key)"); |
666 | 0 | m_key->dump(indent + 1); |
667 | |
|
668 | 0 | char const* kind_string = nullptr; |
669 | 0 | switch (m_kind) { |
670 | 0 | case Kind::Method: |
671 | 0 | kind_string = "Method"; |
672 | 0 | break; |
673 | 0 | case Kind::Getter: |
674 | 0 | kind_string = "Getter"; |
675 | 0 | break; |
676 | 0 | case Kind::Setter: |
677 | 0 | kind_string = "Setter"; |
678 | 0 | break; |
679 | 0 | } |
680 | 0 | print_indent(indent); |
681 | 0 | outln("Kind: {}", kind_string); |
682 | |
|
683 | 0 | print_indent(indent); |
684 | 0 | outln("Static: {}", is_static()); |
685 | |
|
686 | 0 | print_indent(indent); |
687 | 0 | outln("(Function)"); |
688 | 0 | m_function->dump(indent + 1); |
689 | 0 | } |
690 | | |
691 | | void ClassField::dump(int indent) const |
692 | 0 | { |
693 | 0 | ASTNode::dump(indent); |
694 | 0 | print_indent(indent); |
695 | 0 | outln("(Key)"); |
696 | 0 | m_key->dump(indent + 1); |
697 | |
|
698 | 0 | print_indent(indent); |
699 | 0 | outln("Static: {}", is_static()); |
700 | |
|
701 | 0 | if (m_initializer) { |
702 | 0 | print_indent(indent); |
703 | 0 | outln("(Initializer)"); |
704 | 0 | m_initializer->dump(indent + 1); |
705 | 0 | } |
706 | 0 | } |
707 | | |
708 | | void StaticInitializer::dump(int indent) const |
709 | 0 | { |
710 | 0 | ASTNode::dump(indent); |
711 | 0 | m_function_body->dump(indent + 1); |
712 | 0 | } |
713 | | |
714 | | void StringLiteral::dump(int indent) const |
715 | 0 | { |
716 | 0 | print_indent(indent); |
717 | 0 | outln("StringLiteral \"{}\"", m_value); |
718 | 0 | } |
719 | | |
720 | | void SuperExpression::dump(int indent) const |
721 | 0 | { |
722 | 0 | print_indent(indent); |
723 | 0 | outln("super"); |
724 | 0 | } |
725 | | |
726 | | void NumericLiteral::dump(int indent) const |
727 | 0 | { |
728 | 0 | print_indent(indent); |
729 | 0 | outln("NumericLiteral {}", m_value); |
730 | 0 | } |
731 | | |
732 | | void BigIntLiteral::dump(int indent) const |
733 | 0 | { |
734 | 0 | print_indent(indent); |
735 | 0 | outln("BigIntLiteral {}", m_value); |
736 | 0 | } |
737 | | |
738 | | void BooleanLiteral::dump(int indent) const |
739 | 0 | { |
740 | 0 | print_indent(indent); |
741 | 0 | outln("BooleanLiteral {}", m_value); |
742 | 0 | } |
743 | | |
744 | | void NullLiteral::dump(int indent) const |
745 | 0 | { |
746 | 0 | print_indent(indent); |
747 | 0 | outln("null"); |
748 | 0 | } |
749 | | |
750 | | bool BindingPattern::contains_expression() const |
751 | 0 | { |
752 | 0 | for (auto& entry : entries) { |
753 | 0 | if (entry.name.has<NonnullRefPtr<Expression const>>()) |
754 | 0 | return true; |
755 | 0 | if (entry.initializer) |
756 | 0 | return true; |
757 | 0 | if (auto binding_ptr = entry.alias.get_pointer<NonnullRefPtr<BindingPattern const>>(); binding_ptr && (*binding_ptr)->contains_expression()) |
758 | 0 | return true; |
759 | 0 | } |
760 | 0 | return false; |
761 | 0 | } |
762 | | |
763 | | ThrowCompletionOr<void> BindingPattern::for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const |
764 | 0 | { |
765 | 0 | for (auto const& entry : entries) { |
766 | 0 | auto const& alias = entry.alias; |
767 | 0 | if (alias.has<NonnullRefPtr<Identifier const>>()) { |
768 | 0 | TRY(callback(alias.get<NonnullRefPtr<Identifier const>>())); |
769 | 0 | } else if (alias.has<NonnullRefPtr<BindingPattern const>>()) { |
770 | 0 | TRY(alias.get<NonnullRefPtr<BindingPattern const>>()->for_each_bound_identifier(forward<decltype(callback)>(callback))); |
771 | 0 | } else { |
772 | 0 | auto const& name = entry.name; |
773 | 0 | if (name.has<NonnullRefPtr<Identifier const>>()) |
774 | 0 | TRY(callback(name.get<NonnullRefPtr<Identifier const>>())); |
775 | 0 | } |
776 | 0 | } |
777 | 0 | return {}; |
778 | 0 | } |
779 | | |
780 | | void BindingPattern::dump(int indent) const |
781 | 0 | { |
782 | 0 | print_indent(indent); |
783 | 0 | outln("BindingPattern {}", kind == Kind::Array ? "Array" : "Object"); |
784 | |
|
785 | 0 | for (auto& entry : entries) { |
786 | 0 | print_indent(indent + 1); |
787 | 0 | outln("(Property)"); |
788 | |
|
789 | 0 | if (kind == Kind::Object) { |
790 | 0 | print_indent(indent + 2); |
791 | 0 | outln("(Identifier)"); |
792 | 0 | if (entry.name.has<NonnullRefPtr<Identifier const>>()) { |
793 | 0 | entry.name.get<NonnullRefPtr<Identifier const>>()->dump(indent + 3); |
794 | 0 | } else if (entry.name.has<NonnullRefPtr<Expression const>>()) { |
795 | 0 | entry.name.get<NonnullRefPtr<Expression const>>()->dump(indent + 3); |
796 | 0 | } else { |
797 | 0 | VERIFY(entry.name.has<Empty>()); |
798 | 0 | print_indent(indent + 3); |
799 | 0 | outln("<empty>"); |
800 | 0 | } |
801 | 0 | } else if (entry.is_elision()) { |
802 | 0 | print_indent(indent + 2); |
803 | 0 | outln("(Elision)"); |
804 | 0 | continue; |
805 | 0 | } |
806 | | |
807 | 0 | print_indent(indent + 2); |
808 | 0 | outln("(Pattern{})", entry.is_rest ? " rest=true" : ""); |
809 | 0 | if (entry.alias.has<NonnullRefPtr<Identifier const>>()) { |
810 | 0 | entry.alias.get<NonnullRefPtr<Identifier const>>()->dump(indent + 3); |
811 | 0 | } else if (entry.alias.has<NonnullRefPtr<BindingPattern const>>()) { |
812 | 0 | entry.alias.get<NonnullRefPtr<BindingPattern const>>()->dump(indent + 3); |
813 | 0 | } else if (entry.alias.has<NonnullRefPtr<MemberExpression const>>()) { |
814 | 0 | entry.alias.get<NonnullRefPtr<MemberExpression const>>()->dump(indent + 3); |
815 | 0 | } else { |
816 | 0 | print_indent(indent + 3); |
817 | 0 | outln("<empty>"); |
818 | 0 | } |
819 | |
|
820 | 0 | if (entry.initializer) { |
821 | 0 | print_indent(indent + 2); |
822 | 0 | outln("(Initializer)"); |
823 | 0 | entry.initializer->dump(indent + 3); |
824 | 0 | } |
825 | 0 | } |
826 | 0 | } |
827 | | |
828 | | void FunctionNode::dump(int indent, ByteString const& class_name) const |
829 | 0 | { |
830 | 0 | print_indent(indent); |
831 | 0 | auto is_async = m_kind == FunctionKind::Async || m_kind == FunctionKind::AsyncGenerator; |
832 | 0 | auto is_generator = m_kind == FunctionKind::Generator || m_kind == FunctionKind::AsyncGenerator; |
833 | 0 | outln("{}{}{} '{}'", class_name, is_async ? " async" : "", is_generator ? "*" : "", name()); |
834 | 0 | if (m_parsing_insights.contains_direct_call_to_eval) { |
835 | 0 | print_indent(indent + 1); |
836 | 0 | outln("\033[31;1m(direct eval)\033[0m"); |
837 | 0 | } |
838 | 0 | if (!m_parameters.is_empty()) { |
839 | 0 | print_indent(indent + 1); |
840 | 0 | outln("(Parameters)"); |
841 | |
|
842 | 0 | for (auto& parameter : m_parameters) { |
843 | 0 | parameter.binding.visit( |
844 | 0 | [&](Identifier const& identifier) { |
845 | 0 | if (parameter.is_rest) { |
846 | 0 | print_indent(indent + 2); |
847 | 0 | out("..."); |
848 | 0 | identifier.dump(0); |
849 | 0 | } else { |
850 | 0 | identifier.dump(indent + 2); |
851 | 0 | } |
852 | 0 | }, |
853 | 0 | [&](BindingPattern const& pattern) { |
854 | 0 | pattern.dump(indent + 2); |
855 | 0 | }); |
856 | 0 | if (parameter.default_value) |
857 | 0 | parameter.default_value->dump(indent + 3); |
858 | 0 | } |
859 | 0 | } |
860 | 0 | print_indent(indent + 1); |
861 | 0 | outln("(Body)"); |
862 | 0 | body().dump(indent + 2); |
863 | 0 | } |
864 | | |
865 | | void FunctionDeclaration::dump(int indent) const |
866 | 0 | { |
867 | 0 | FunctionNode::dump(indent, class_name()); |
868 | 0 | } |
869 | | |
870 | | ThrowCompletionOr<void> FunctionDeclaration::for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const |
871 | 17 | { |
872 | 17 | if (!m_name) |
873 | 0 | return {}; |
874 | 17 | return callback(*m_name); |
875 | 17 | } |
876 | | |
877 | | void FunctionExpression::dump(int indent) const |
878 | 0 | { |
879 | 0 | FunctionNode::dump(indent, class_name()); |
880 | 0 | } |
881 | | |
882 | | void YieldExpression::dump(int indent) const |
883 | 0 | { |
884 | 0 | ASTNode::dump(indent); |
885 | 0 | if (argument()) |
886 | 0 | argument()->dump(indent + 1); |
887 | 0 | } |
888 | | |
889 | | void AwaitExpression::dump(int indent) const |
890 | 0 | { |
891 | 0 | ASTNode::dump(indent); |
892 | 0 | m_argument->dump(indent + 1); |
893 | 0 | } |
894 | | |
895 | | void ReturnStatement::dump(int indent) const |
896 | 0 | { |
897 | 0 | ASTNode::dump(indent); |
898 | 0 | if (argument()) |
899 | 0 | argument()->dump(indent + 1); |
900 | 0 | } |
901 | | |
902 | | void IfStatement::dump(int indent) const |
903 | 0 | { |
904 | 0 | ASTNode::dump(indent); |
905 | |
|
906 | 0 | print_indent(indent); |
907 | 0 | outln("If"); |
908 | 0 | predicate().dump(indent + 1); |
909 | 0 | consequent().dump(indent + 1); |
910 | 0 | if (alternate()) { |
911 | 0 | print_indent(indent); |
912 | 0 | outln("Else"); |
913 | 0 | alternate()->dump(indent + 1); |
914 | 0 | } |
915 | 0 | } |
916 | | |
917 | | void WhileStatement::dump(int indent) const |
918 | 0 | { |
919 | 0 | ASTNode::dump(indent); |
920 | |
|
921 | 0 | print_indent(indent); |
922 | 0 | outln("While"); |
923 | 0 | test().dump(indent + 1); |
924 | 0 | body().dump(indent + 1); |
925 | 0 | } |
926 | | |
927 | | void WithStatement::dump(int indent) const |
928 | 0 | { |
929 | 0 | ASTNode::dump(indent); |
930 | |
|
931 | 0 | print_indent(indent + 1); |
932 | 0 | outln("Object"); |
933 | 0 | object().dump(indent + 2); |
934 | 0 | print_indent(indent + 1); |
935 | 0 | outln("Body"); |
936 | 0 | body().dump(indent + 2); |
937 | 0 | } |
938 | | |
939 | | void DoWhileStatement::dump(int indent) const |
940 | 0 | { |
941 | 0 | ASTNode::dump(indent); |
942 | |
|
943 | 0 | print_indent(indent); |
944 | 0 | outln("DoWhile"); |
945 | 0 | test().dump(indent + 1); |
946 | 0 | body().dump(indent + 1); |
947 | 0 | } |
948 | | |
949 | | void ForStatement::dump(int indent) const |
950 | 0 | { |
951 | 0 | ASTNode::dump(indent); |
952 | |
|
953 | 0 | print_indent(indent); |
954 | 0 | outln("For"); |
955 | 0 | if (init()) |
956 | 0 | init()->dump(indent + 1); |
957 | 0 | if (test()) |
958 | 0 | test()->dump(indent + 1); |
959 | 0 | if (update()) |
960 | 0 | update()->dump(indent + 1); |
961 | 0 | body().dump(indent + 1); |
962 | 0 | } |
963 | | |
964 | | void ForInStatement::dump(int indent) const |
965 | 0 | { |
966 | 0 | ASTNode::dump(indent); |
967 | |
|
968 | 0 | print_indent(indent); |
969 | 0 | outln("ForIn"); |
970 | 0 | lhs().visit([&](auto& lhs) { lhs->dump(indent + 1); });Unexecuted instantiation: AST.cpp:auto JS::ForInStatement::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::ASTNode const> const>(AK::NonnullRefPtr<JS::ASTNode const> const&) const Unexecuted instantiation: AST.cpp:auto JS::ForInStatement::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::BindingPattern const> const>(AK::NonnullRefPtr<JS::BindingPattern const> const&) const |
971 | 0 | rhs().dump(indent + 1); |
972 | 0 | body().dump(indent + 1); |
973 | 0 | } |
974 | | |
975 | | void ForOfStatement::dump(int indent) const |
976 | 0 | { |
977 | 0 | ASTNode::dump(indent); |
978 | |
|
979 | 0 | print_indent(indent); |
980 | 0 | outln("ForOf"); |
981 | 0 | lhs().visit([&](auto& lhs) { lhs->dump(indent + 1); });Unexecuted instantiation: AST.cpp:auto JS::ForOfStatement::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::ASTNode const> const>(AK::NonnullRefPtr<JS::ASTNode const> const&) const Unexecuted instantiation: AST.cpp:auto JS::ForOfStatement::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::BindingPattern const> const>(AK::NonnullRefPtr<JS::BindingPattern const> const&) const |
982 | 0 | rhs().dump(indent + 1); |
983 | 0 | body().dump(indent + 1); |
984 | 0 | } |
985 | | |
986 | | void ForAwaitOfStatement::dump(int indent) const |
987 | 0 | { |
988 | 0 | ASTNode::dump(indent); |
989 | |
|
990 | 0 | print_indent(indent); |
991 | 0 | outln("ForAwaitOf"); |
992 | 0 | m_lhs.visit([&](auto& lhs) { lhs->dump(indent + 1); });Unexecuted instantiation: AST.cpp:auto JS::ForAwaitOfStatement::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::ASTNode const> const>(AK::NonnullRefPtr<JS::ASTNode const> const&) const Unexecuted instantiation: AST.cpp:auto JS::ForAwaitOfStatement::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::BindingPattern const> const>(AK::NonnullRefPtr<JS::BindingPattern const> const&) const |
993 | 0 | m_rhs->dump(indent + 1); |
994 | 0 | m_body->dump(indent + 1); |
995 | 0 | } |
996 | | |
997 | | void Identifier::dump(int indent) const |
998 | 0 | { |
999 | 0 | print_indent(indent); |
1000 | 0 | if (is_local()) { |
1001 | 0 | outln("Identifier \"{}\" is_local=(true) index=({})", m_string, m_local_variable_index); |
1002 | 0 | } else if (is_global()) { |
1003 | 0 | outln("Identifier \"{}\" is_global=(true)", m_string); |
1004 | 0 | } else { |
1005 | 0 | outln("Identifier \"{}\"", m_string); |
1006 | 0 | } |
1007 | 0 | } |
1008 | | |
1009 | | void PrivateIdentifier::dump(int indent) const |
1010 | 0 | { |
1011 | 0 | print_indent(indent); |
1012 | 0 | outln("PrivateIdentifier \"{}\"", m_string); |
1013 | 0 | } |
1014 | | |
1015 | | void SpreadExpression::dump(int indent) const |
1016 | 0 | { |
1017 | 0 | ASTNode::dump(indent); |
1018 | 0 | m_target->dump(indent + 1); |
1019 | 0 | } |
1020 | | |
1021 | | void ThisExpression::dump(int indent) const |
1022 | 0 | { |
1023 | 0 | ASTNode::dump(indent); |
1024 | 0 | } |
1025 | | |
1026 | | void AssignmentExpression::dump(int indent) const |
1027 | 0 | { |
1028 | 0 | char const* op_string = nullptr; |
1029 | 0 | switch (m_op) { |
1030 | 0 | case AssignmentOp::Assignment: |
1031 | 0 | op_string = "="; |
1032 | 0 | break; |
1033 | 0 | case AssignmentOp::AdditionAssignment: |
1034 | 0 | op_string = "+="; |
1035 | 0 | break; |
1036 | 0 | case AssignmentOp::SubtractionAssignment: |
1037 | 0 | op_string = "-="; |
1038 | 0 | break; |
1039 | 0 | case AssignmentOp::MultiplicationAssignment: |
1040 | 0 | op_string = "*="; |
1041 | 0 | break; |
1042 | 0 | case AssignmentOp::DivisionAssignment: |
1043 | 0 | op_string = "/="; |
1044 | 0 | break; |
1045 | 0 | case AssignmentOp::ModuloAssignment: |
1046 | 0 | op_string = "%="; |
1047 | 0 | break; |
1048 | 0 | case AssignmentOp::ExponentiationAssignment: |
1049 | 0 | op_string = "**="; |
1050 | 0 | break; |
1051 | 0 | case AssignmentOp::BitwiseAndAssignment: |
1052 | 0 | op_string = "&="; |
1053 | 0 | break; |
1054 | 0 | case AssignmentOp::BitwiseOrAssignment: |
1055 | 0 | op_string = "|="; |
1056 | 0 | break; |
1057 | 0 | case AssignmentOp::BitwiseXorAssignment: |
1058 | 0 | op_string = "^="; |
1059 | 0 | break; |
1060 | 0 | case AssignmentOp::LeftShiftAssignment: |
1061 | 0 | op_string = "<<="; |
1062 | 0 | break; |
1063 | 0 | case AssignmentOp::RightShiftAssignment: |
1064 | 0 | op_string = ">>="; |
1065 | 0 | break; |
1066 | 0 | case AssignmentOp::UnsignedRightShiftAssignment: |
1067 | 0 | op_string = ">>>="; |
1068 | 0 | break; |
1069 | 0 | case AssignmentOp::AndAssignment: |
1070 | 0 | op_string = "&&="; |
1071 | 0 | break; |
1072 | 0 | case AssignmentOp::OrAssignment: |
1073 | 0 | op_string = "||="; |
1074 | 0 | break; |
1075 | 0 | case AssignmentOp::NullishAssignment: |
1076 | 0 | op_string = "\?\?="; |
1077 | 0 | break; |
1078 | 0 | } |
1079 | | |
1080 | 0 | ASTNode::dump(indent); |
1081 | 0 | print_indent(indent + 1); |
1082 | 0 | outln("{}", op_string); |
1083 | 0 | m_lhs.visit([&](auto& lhs) { lhs->dump(indent + 1); });Unexecuted instantiation: AST.cpp:auto JS::AssignmentExpression::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::Expression const> const>(AK::NonnullRefPtr<JS::Expression const> const&) const Unexecuted instantiation: AST.cpp:auto JS::AssignmentExpression::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::BindingPattern const> const>(AK::NonnullRefPtr<JS::BindingPattern const> const&) const |
1084 | 0 | m_rhs->dump(indent + 1); |
1085 | 0 | } |
1086 | | |
1087 | | void UpdateExpression::dump(int indent) const |
1088 | 0 | { |
1089 | 0 | char const* op_string = nullptr; |
1090 | 0 | switch (m_op) { |
1091 | 0 | case UpdateOp::Increment: |
1092 | 0 | op_string = "++"; |
1093 | 0 | break; |
1094 | 0 | case UpdateOp::Decrement: |
1095 | 0 | op_string = "--"; |
1096 | 0 | break; |
1097 | 0 | } |
1098 | | |
1099 | 0 | ASTNode::dump(indent); |
1100 | 0 | if (m_prefixed) { |
1101 | 0 | print_indent(indent + 1); |
1102 | 0 | outln("{}", op_string); |
1103 | 0 | } |
1104 | 0 | m_argument->dump(indent + 1); |
1105 | 0 | if (!m_prefixed) { |
1106 | 0 | print_indent(indent + 1); |
1107 | 0 | outln("{}", op_string); |
1108 | 0 | } |
1109 | 0 | } |
1110 | | |
1111 | | ThrowCompletionOr<void> VariableDeclaration::for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const |
1112 | 17 | { |
1113 | 17 | for (auto const& entry : declarations()) { |
1114 | 17 | TRY(entry->target().visit( |
1115 | 17 | [&](NonnullRefPtr<Identifier const> const& id) { |
1116 | 17 | return callback(id); |
1117 | 17 | }, |
1118 | 17 | [&](NonnullRefPtr<BindingPattern const> const& binding) { |
1119 | 17 | return binding->for_each_bound_identifier([&](auto const& id) { |
1120 | 17 | return callback(id); |
1121 | 17 | }); |
1122 | 17 | })); |
1123 | 17 | } |
1124 | | |
1125 | 17 | return {}; |
1126 | 17 | } |
1127 | | |
1128 | | void VariableDeclaration::dump(int indent) const |
1129 | 0 | { |
1130 | 0 | char const* declaration_kind_string = nullptr; |
1131 | 0 | switch (m_declaration_kind) { |
1132 | 0 | case DeclarationKind::Let: |
1133 | 0 | declaration_kind_string = "Let"; |
1134 | 0 | break; |
1135 | 0 | case DeclarationKind::Var: |
1136 | 0 | declaration_kind_string = "Var"; |
1137 | 0 | break; |
1138 | 0 | case DeclarationKind::Const: |
1139 | 0 | declaration_kind_string = "Const"; |
1140 | 0 | break; |
1141 | 0 | } |
1142 | | |
1143 | 0 | ASTNode::dump(indent); |
1144 | 0 | print_indent(indent + 1); |
1145 | 0 | outln("{}", declaration_kind_string); |
1146 | |
|
1147 | 0 | for (auto& declarator : m_declarations) |
1148 | 0 | declarator->dump(indent + 1); |
1149 | 0 | } |
1150 | | |
1151 | | ThrowCompletionOr<void> UsingDeclaration::for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const |
1152 | 0 | { |
1153 | 0 | for (auto const& entry : m_declarations) { |
1154 | 0 | VERIFY(entry->target().has<NonnullRefPtr<Identifier const>>()); |
1155 | 0 | TRY(callback(entry->target().get<NonnullRefPtr<Identifier const>>())); |
1156 | 0 | } |
1157 | | |
1158 | 0 | return {}; |
1159 | 0 | } |
1160 | | |
1161 | | void UsingDeclaration::dump(int indent) const |
1162 | 0 | { |
1163 | 0 | ASTNode::dump(indent); |
1164 | 0 | print_indent(indent + 1); |
1165 | 0 | for (auto& declarator : m_declarations) |
1166 | 0 | declarator->dump(indent + 1); |
1167 | 0 | } |
1168 | | |
1169 | | void VariableDeclarator::dump(int indent) const |
1170 | 0 | { |
1171 | 0 | ASTNode::dump(indent); |
1172 | 0 | m_target.visit([indent](auto const& value) { value->dump(indent + 1); });Unexecuted instantiation: AST.cpp:auto JS::VariableDeclarator::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::Identifier const> >(AK::NonnullRefPtr<JS::Identifier const> const&) const Unexecuted instantiation: AST.cpp:auto JS::VariableDeclarator::dump(int) const::$_0::operator()<AK::NonnullRefPtr<JS::BindingPattern const> >(AK::NonnullRefPtr<JS::BindingPattern const> const&) const |
1173 | 0 | if (m_init) |
1174 | 0 | m_init->dump(indent + 1); |
1175 | 0 | } |
1176 | | |
1177 | | void ObjectProperty::dump(int indent) const |
1178 | 0 | { |
1179 | 0 | ASTNode::dump(indent); |
1180 | |
|
1181 | 0 | if (m_property_type == Type::Spread) { |
1182 | 0 | print_indent(indent + 1); |
1183 | 0 | outln("...Spreading"); |
1184 | 0 | m_key->dump(indent + 1); |
1185 | 0 | } else { |
1186 | 0 | m_key->dump(indent + 1); |
1187 | 0 | m_value->dump(indent + 1); |
1188 | 0 | } |
1189 | 0 | } |
1190 | | |
1191 | | void ObjectExpression::dump(int indent) const |
1192 | 0 | { |
1193 | 0 | ASTNode::dump(indent); |
1194 | 0 | for (auto& property : m_properties) { |
1195 | 0 | property->dump(indent + 1); |
1196 | 0 | } |
1197 | 0 | } |
1198 | | |
1199 | | void ExpressionStatement::dump(int indent) const |
1200 | 0 | { |
1201 | 0 | ASTNode::dump(indent); |
1202 | 0 | m_expression->dump(indent + 1); |
1203 | 0 | } |
1204 | | |
1205 | | void MemberExpression::dump(int indent) const |
1206 | 0 | { |
1207 | 0 | print_indent(indent); |
1208 | 0 | outln("{}(computed={})", class_name(), is_computed()); |
1209 | 0 | m_object->dump(indent + 1); |
1210 | 0 | m_property->dump(indent + 1); |
1211 | 0 | } |
1212 | | |
1213 | | ByteString MemberExpression::to_string_approximation() const |
1214 | 0 | { |
1215 | 0 | ByteString object_string = "<object>"; |
1216 | 0 | if (is<Identifier>(*m_object)) |
1217 | 0 | object_string = static_cast<Identifier const&>(*m_object).string(); |
1218 | 0 | if (is_computed()) |
1219 | 0 | return ByteString::formatted("{}[<computed>]", object_string); |
1220 | 0 | if (is<PrivateIdentifier>(*m_property)) |
1221 | 0 | return ByteString::formatted("{}.{}", object_string, verify_cast<PrivateIdentifier>(*m_property).string()); |
1222 | 0 | return ByteString::formatted("{}.{}", object_string, verify_cast<Identifier>(*m_property).string()); |
1223 | 0 | } |
1224 | | |
1225 | | bool MemberExpression::ends_in_private_name() const |
1226 | 0 | { |
1227 | 0 | if (is_computed()) |
1228 | 0 | return false; |
1229 | 0 | if (is<PrivateIdentifier>(*m_property)) |
1230 | 0 | return true; |
1231 | 0 | if (is<MemberExpression>(*m_property)) |
1232 | 0 | return static_cast<MemberExpression const&>(*m_property).ends_in_private_name(); |
1233 | 0 | return false; |
1234 | 0 | } |
1235 | | |
1236 | | void OptionalChain::dump(int indent) const |
1237 | 0 | { |
1238 | 0 | print_indent(indent); |
1239 | 0 | outln("{}", class_name()); |
1240 | 0 | m_base->dump(indent + 1); |
1241 | 0 | for (auto& reference : m_references) { |
1242 | 0 | reference.visit( |
1243 | 0 | [&](Call const& call) { |
1244 | 0 | print_indent(indent + 1); |
1245 | 0 | outln("Call({})", call.mode == Mode::Optional ? "Optional" : "Not Optional"); |
1246 | 0 | for (auto& argument : call.arguments) |
1247 | 0 | argument.value->dump(indent + 2); |
1248 | 0 | }, |
1249 | 0 | [&](ComputedReference const& ref) { |
1250 | 0 | print_indent(indent + 1); |
1251 | 0 | outln("ComputedReference({})", ref.mode == Mode::Optional ? "Optional" : "Not Optional"); |
1252 | 0 | ref.expression->dump(indent + 2); |
1253 | 0 | }, |
1254 | 0 | [&](MemberReference const& ref) { |
1255 | 0 | print_indent(indent + 1); |
1256 | 0 | outln("MemberReference({})", ref.mode == Mode::Optional ? "Optional" : "Not Optional"); |
1257 | 0 | ref.identifier->dump(indent + 2); |
1258 | 0 | }, |
1259 | 0 | [&](PrivateMemberReference const& ref) { |
1260 | 0 | print_indent(indent + 1); |
1261 | 0 | outln("PrivateMemberReference({})", ref.mode == Mode::Optional ? "Optional" : "Not Optional"); |
1262 | 0 | ref.private_identifier->dump(indent + 2); |
1263 | 0 | }); |
1264 | 0 | } |
1265 | 0 | } |
1266 | | |
1267 | | void MetaProperty::dump(int indent) const |
1268 | 0 | { |
1269 | 0 | ByteString name; |
1270 | 0 | if (m_type == MetaProperty::Type::NewTarget) |
1271 | 0 | name = "new.target"; |
1272 | 0 | else if (m_type == MetaProperty::Type::ImportMeta) |
1273 | 0 | name = "import.meta"; |
1274 | 0 | else |
1275 | 0 | VERIFY_NOT_REACHED(); |
1276 | 0 | print_indent(indent); |
1277 | 0 | outln("{} {}", class_name(), name); |
1278 | 0 | } |
1279 | | |
1280 | | void ImportCall::dump(int indent) const |
1281 | 0 | { |
1282 | 0 | ASTNode::dump(indent); |
1283 | 0 | print_indent(indent); |
1284 | 0 | outln("(Specifier)"); |
1285 | 0 | m_specifier->dump(indent + 1); |
1286 | 0 | if (m_options) { |
1287 | 0 | outln("(Options)"); |
1288 | 0 | m_options->dump(indent + 1); |
1289 | 0 | } |
1290 | 0 | } |
1291 | | |
1292 | | void RegExpLiteral::dump(int indent) const |
1293 | 0 | { |
1294 | 0 | print_indent(indent); |
1295 | 0 | outln("{} (/{}/{})", class_name(), pattern(), flags()); |
1296 | 0 | } |
1297 | | |
1298 | | void ArrayExpression::dump(int indent) const |
1299 | 0 | { |
1300 | 0 | ASTNode::dump(indent); |
1301 | 0 | for (auto& element : m_elements) { |
1302 | 0 | if (element) { |
1303 | 0 | element->dump(indent + 1); |
1304 | 0 | } else { |
1305 | 0 | print_indent(indent + 1); |
1306 | 0 | outln("<empty>"); |
1307 | 0 | } |
1308 | 0 | } |
1309 | 0 | } |
1310 | | |
1311 | | void TemplateLiteral::dump(int indent) const |
1312 | 0 | { |
1313 | 0 | ASTNode::dump(indent); |
1314 | 0 | for (auto& expression : m_expressions) |
1315 | 0 | expression->dump(indent + 1); |
1316 | 0 | } |
1317 | | |
1318 | | void TaggedTemplateLiteral::dump(int indent) const |
1319 | 0 | { |
1320 | 0 | ASTNode::dump(indent); |
1321 | 0 | print_indent(indent + 1); |
1322 | 0 | outln("(Tag)"); |
1323 | 0 | m_tag->dump(indent + 2); |
1324 | 0 | print_indent(indent + 1); |
1325 | 0 | outln("(Template Literal)"); |
1326 | 0 | m_template_literal->dump(indent + 2); |
1327 | 0 | } |
1328 | | |
1329 | | void TryStatement::dump(int indent) const |
1330 | 0 | { |
1331 | 0 | ASTNode::dump(indent); |
1332 | 0 | print_indent(indent); |
1333 | 0 | outln("(Block)"); |
1334 | 0 | block().dump(indent + 1); |
1335 | |
|
1336 | 0 | if (handler()) { |
1337 | 0 | print_indent(indent); |
1338 | 0 | outln("(Handler)"); |
1339 | 0 | handler()->dump(indent + 1); |
1340 | 0 | } |
1341 | |
|
1342 | 0 | if (finalizer()) { |
1343 | 0 | print_indent(indent); |
1344 | 0 | outln("(Finalizer)"); |
1345 | 0 | finalizer()->dump(indent + 1); |
1346 | 0 | } |
1347 | 0 | } |
1348 | | |
1349 | | void CatchClause::dump(int indent) const |
1350 | 0 | { |
1351 | 0 | print_indent(indent); |
1352 | 0 | m_parameter.visit( |
1353 | 0 | [&](DeprecatedFlyString const& parameter) { |
1354 | 0 | if (parameter.is_empty()) |
1355 | 0 | outln("CatchClause"); |
1356 | 0 | else |
1357 | 0 | outln("CatchClause ({})", parameter); |
1358 | 0 | }, |
1359 | 0 | [&](NonnullRefPtr<BindingPattern const> const& pattern) { |
1360 | 0 | outln("CatchClause"); |
1361 | 0 | print_indent(indent); |
1362 | 0 | outln("(Parameter)"); |
1363 | 0 | pattern->dump(indent + 2); |
1364 | 0 | }); |
1365 | |
|
1366 | 0 | body().dump(indent + 1); |
1367 | 0 | } |
1368 | | |
1369 | | void ThrowStatement::dump(int indent) const |
1370 | 0 | { |
1371 | 0 | ASTNode::dump(indent); |
1372 | 0 | argument().dump(indent + 1); |
1373 | 0 | } |
1374 | | |
1375 | | void SwitchStatement::dump(int indent) const |
1376 | 0 | { |
1377 | 0 | ASTNode::dump(indent); |
1378 | 0 | m_discriminant->dump(indent + 1); |
1379 | 0 | for (auto& switch_case : m_cases) { |
1380 | 0 | switch_case->dump(indent + 1); |
1381 | 0 | } |
1382 | 0 | } |
1383 | | |
1384 | | void SwitchCase::dump(int indent) const |
1385 | 0 | { |
1386 | 0 | print_indent(indent + 1); |
1387 | 0 | if (m_test) { |
1388 | 0 | outln("(Test)"); |
1389 | 0 | m_test->dump(indent + 2); |
1390 | 0 | } else { |
1391 | 0 | outln("(Default)"); |
1392 | 0 | } |
1393 | 0 | print_indent(indent + 1); |
1394 | 0 | outln("(Consequent)"); |
1395 | 0 | ScopeNode::dump(indent + 2); |
1396 | 0 | } |
1397 | | |
1398 | | void ConditionalExpression::dump(int indent) const |
1399 | 0 | { |
1400 | 0 | ASTNode::dump(indent); |
1401 | 0 | print_indent(indent + 1); |
1402 | 0 | outln("(Test)"); |
1403 | 0 | m_test->dump(indent + 2); |
1404 | 0 | print_indent(indent + 1); |
1405 | 0 | outln("(Consequent)"); |
1406 | 0 | m_consequent->dump(indent + 2); |
1407 | 0 | print_indent(indent + 1); |
1408 | 0 | outln("(Alternate)"); |
1409 | 0 | m_alternate->dump(indent + 2); |
1410 | 0 | } |
1411 | | |
1412 | | void SequenceExpression::dump(int indent) const |
1413 | 0 | { |
1414 | 0 | ASTNode::dump(indent); |
1415 | 0 | for (auto& expression : m_expressions) |
1416 | 0 | expression->dump(indent + 1); |
1417 | 0 | } |
1418 | | |
1419 | | bool ScopeNode::has_non_local_lexical_declarations() const |
1420 | 0 | { |
1421 | 0 | bool result = false; |
1422 | 0 | MUST(for_each_lexically_declared_identifier([&](Identifier const& identifier) { |
1423 | 0 | if (!identifier.is_local()) |
1424 | 0 | result = true; |
1425 | 0 | })); |
1426 | 0 | return result; |
1427 | 0 | } |
1428 | | |
1429 | | ThrowCompletionOr<void> ScopeNode::for_each_lexically_scoped_declaration(ThrowCompletionOrVoidCallback<Declaration const&>&& callback) const |
1430 | 28 | { |
1431 | 28 | for (auto& declaration : m_lexical_declarations) |
1432 | 0 | TRY(callback(declaration)); |
1433 | | |
1434 | 28 | return {}; |
1435 | 28 | } |
1436 | | |
1437 | | ThrowCompletionOr<void> ScopeNode::for_each_lexically_declared_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const |
1438 | 28 | { |
1439 | 28 | for (auto const& declaration : m_lexical_declarations) { |
1440 | 0 | TRY(declaration->for_each_bound_identifier([&](auto const& identifier) { |
1441 | 0 | return callback(identifier); |
1442 | 0 | })); |
1443 | 0 | } |
1444 | 28 | return {}; |
1445 | 28 | } |
1446 | | |
1447 | | ThrowCompletionOr<void> ScopeNode::for_each_var_declared_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&& callback) const |
1448 | 28 | { |
1449 | 28 | for (auto& declaration : m_var_declarations) { |
1450 | 0 | TRY(declaration->for_each_bound_identifier([&](auto const& id) { |
1451 | 0 | return callback(id); |
1452 | 0 | })); |
1453 | 0 | } |
1454 | 28 | return {}; |
1455 | 28 | } |
1456 | | |
1457 | | ThrowCompletionOr<void> ScopeNode::for_each_var_function_declaration_in_reverse_order(ThrowCompletionOrVoidCallback<FunctionDeclaration const&>&& callback) const |
1458 | 28 | { |
1459 | 28 | for (ssize_t i = m_var_declarations.size() - 1; i >= 0; i--) { |
1460 | 0 | auto& declaration = m_var_declarations[i]; |
1461 | 0 | if (is<FunctionDeclaration>(declaration)) |
1462 | 0 | TRY(callback(static_cast<FunctionDeclaration const&>(*declaration))); |
1463 | 0 | } |
1464 | 28 | return {}; |
1465 | 28 | } |
1466 | | |
1467 | | ThrowCompletionOr<void> ScopeNode::for_each_var_scoped_variable_declaration(ThrowCompletionOrVoidCallback<VariableDeclaration const&>&& callback) const |
1468 | 28 | { |
1469 | 28 | for (auto& declaration : m_var_declarations) { |
1470 | 0 | if (!is<FunctionDeclaration>(declaration)) { |
1471 | 0 | VERIFY(is<VariableDeclaration>(declaration)); |
1472 | 0 | TRY(callback(static_cast<VariableDeclaration const&>(*declaration))); |
1473 | 0 | } |
1474 | 0 | } |
1475 | 28 | return {}; |
1476 | 28 | } |
1477 | | |
1478 | | ThrowCompletionOr<void> ScopeNode::for_each_function_hoistable_with_annexB_extension(ThrowCompletionOrVoidCallback<FunctionDeclaration&>&& callback) const |
1479 | 28 | { |
1480 | 28 | for (auto& function : m_functions_hoistable_with_annexB_extension) { |
1481 | | // We need const_cast here since it might have to set a property on function declaration. |
1482 | 0 | TRY(callback(const_cast<FunctionDeclaration&>(*function))); |
1483 | 0 | } |
1484 | 28 | return {}; |
1485 | 28 | } |
1486 | | |
1487 | | void ScopeNode::add_lexical_declaration(NonnullRefPtr<Declaration const> declaration) |
1488 | 94 | { |
1489 | 94 | m_lexical_declarations.append(move(declaration)); |
1490 | 94 | } |
1491 | | |
1492 | | void ScopeNode::add_var_scoped_declaration(NonnullRefPtr<Declaration const> declaration) |
1493 | 51 | { |
1494 | 51 | m_var_declarations.append(move(declaration)); |
1495 | 51 | } |
1496 | | |
1497 | | void ScopeNode::add_hoisted_function(NonnullRefPtr<FunctionDeclaration const> declaration) |
1498 | 93 | { |
1499 | 93 | m_functions_hoistable_with_annexB_extension.append(move(declaration)); |
1500 | 93 | } |
1501 | | |
1502 | | DeprecatedFlyString ExportStatement::local_name_for_default = "*default*"; |
1503 | | |
1504 | | static void dump_assert_clauses(ModuleRequest const& request) |
1505 | 0 | { |
1506 | 0 | if (!request.attributes.is_empty()) { |
1507 | 0 | out("[ "); |
1508 | 0 | for (auto& assertion : request.attributes) |
1509 | 0 | out("{}: {}, ", assertion.key, assertion.value); |
1510 | 0 | out(" ]"); |
1511 | 0 | } |
1512 | 0 | } |
1513 | | |
1514 | | void ExportStatement::dump(int indent) const |
1515 | 0 | { |
1516 | 0 | ASTNode::dump(indent); |
1517 | 0 | print_indent(indent + 1); |
1518 | 0 | outln("(ExportEntries)"); |
1519 | |
|
1520 | 0 | auto string_or_null = [](Optional<DeprecatedFlyString> const& string) -> ByteString { |
1521 | 0 | if (!string.has_value()) { |
1522 | 0 | return "null"; |
1523 | 0 | } |
1524 | 0 | return ByteString::formatted("\"{}\"", string); |
1525 | 0 | }; |
1526 | |
|
1527 | 0 | for (auto& entry : m_entries) { |
1528 | 0 | print_indent(indent + 2); |
1529 | 0 | out("ExportName: {}, ImportName: {}, LocalName: {}, ModuleRequest: ", |
1530 | 0 | string_or_null(entry.export_name), |
1531 | 0 | entry.is_module_request() ? string_or_null(entry.local_or_import_name) : "null", |
1532 | 0 | entry.is_module_request() ? "null" : string_or_null(entry.local_or_import_name)); |
1533 | 0 | if (entry.is_module_request()) { |
1534 | 0 | out("{}", entry.m_module_request->module_specifier); |
1535 | 0 | dump_assert_clauses(*entry.m_module_request); |
1536 | 0 | outln(); |
1537 | 0 | } else { |
1538 | 0 | outln("null"); |
1539 | 0 | } |
1540 | 0 | } |
1541 | |
|
1542 | 0 | if (m_statement) { |
1543 | 0 | print_indent(indent + 1); |
1544 | 0 | outln("(Statement)"); |
1545 | 0 | m_statement->dump(indent + 2); |
1546 | 0 | } |
1547 | 0 | } |
1548 | | |
1549 | | void ImportStatement::dump(int indent) const |
1550 | 0 | { |
1551 | 0 | ASTNode::dump(indent); |
1552 | 0 | print_indent(indent + 1); |
1553 | 0 | if (m_entries.is_empty()) { |
1554 | | // direct from "module" import |
1555 | 0 | outln("Entire module '{}'", m_module_request.module_specifier); |
1556 | 0 | dump_assert_clauses(m_module_request); |
1557 | 0 | } else { |
1558 | 0 | outln("(ExportEntries) from {}", m_module_request.module_specifier); |
1559 | 0 | dump_assert_clauses(m_module_request); |
1560 | |
|
1561 | 0 | for (auto& entry : m_entries) { |
1562 | 0 | print_indent(indent + 2); |
1563 | 0 | outln("ImportName: {}, LocalName: {}", entry.import_name, entry.local_name); |
1564 | 0 | } |
1565 | 0 | } |
1566 | 0 | } |
1567 | | |
1568 | | bool ExportStatement::has_export(DeprecatedFlyString const& export_name) const |
1569 | 0 | { |
1570 | 0 | return any_of(m_entries.begin(), m_entries.end(), [&](auto& entry) { |
1571 | | // Make sure that empty exported names does not overlap with anything |
1572 | 0 | if (entry.kind != ExportEntry::Kind::NamedExport) |
1573 | 0 | return false; |
1574 | 0 | return entry.export_name == export_name; |
1575 | 0 | }); |
1576 | 0 | } |
1577 | | |
1578 | | bool ImportStatement::has_bound_name(DeprecatedFlyString const& name) const |
1579 | 0 | { |
1580 | 0 | return any_of(m_entries.begin(), m_entries.end(), [&](auto& entry) { |
1581 | 0 | return entry.local_name == name; |
1582 | 0 | }); |
1583 | 0 | } |
1584 | | |
1585 | | // 14.2.3 BlockDeclarationInstantiation ( code, env ), https://tc39.es/ecma262/#sec-blockdeclarationinstantiation |
1586 | | void ScopeNode::block_declaration_instantiation(VM& vm, Environment* environment) const |
1587 | 0 | { |
1588 | | // See also B.3.2.6 Changes to BlockDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-blockdeclarationinstantiation |
1589 | 0 | auto& realm = *vm.current_realm(); |
1590 | |
|
1591 | 0 | VERIFY(environment); |
1592 | | |
1593 | | // 1. Let declarations be the LexicallyScopedDeclarations of code. |
1594 | | |
1595 | | // 2. Let privateEnv be the running execution context's PrivateEnvironment. |
1596 | 0 | auto private_environment = vm.running_execution_context().private_environment; |
1597 | | |
1598 | | // Note: All the calls here are ! and thus we do not need to TRY this callback. |
1599 | | // We use MUST to ensure it does not throw and to avoid discarding the returned ThrowCompletionOr<void>. |
1600 | | // 3. For each element d of declarations, do |
1601 | 0 | MUST(for_each_lexically_scoped_declaration([&](Declaration const& declaration) { |
1602 | 0 | auto is_constant_declaration = declaration.is_constant_declaration(); |
1603 | | // NOTE: Due to the use of MUST with `create_immutable_binding` and `create_mutable_binding` below, |
1604 | | // an exception should not result from `for_each_bound_name`. |
1605 | | // a. For each element dn of the BoundNames of d, do |
1606 | 0 | MUST(declaration.for_each_bound_identifier([&](auto const& identifier) { |
1607 | 0 | if (identifier.is_local()) { |
1608 | | // NOTE: No need to create bindings for local variables as their values are not stored in an environment. |
1609 | 0 | return; |
1610 | 0 | } |
1611 | |
|
1612 | 0 | auto const& name = identifier.string(); |
1613 | | // i. If IsConstantDeclaration of d is true, then |
1614 | 0 | if (is_constant_declaration) { |
1615 | | // 1. Perform ! env.CreateImmutableBinding(dn, true). |
1616 | 0 | MUST(environment->create_immutable_binding(vm, name, true)); |
1617 | 0 | } |
1618 | | // ii. Else, |
1619 | 0 | else { |
1620 | | // 1. Perform ! env.CreateMutableBinding(dn, false). NOTE: This step is replaced in section B.3.2.6. |
1621 | 0 | if (!MUST(environment->has_binding(name))) |
1622 | 0 | MUST(environment->create_mutable_binding(vm, name, false)); |
1623 | 0 | } |
1624 | 0 | })); |
1625 | | |
1626 | | // b. If d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then |
1627 | 0 | if (is<FunctionDeclaration>(declaration)) { |
1628 | | // i. Let fn be the sole element of the BoundNames of d. |
1629 | 0 | auto& function_declaration = static_cast<FunctionDeclaration const&>(declaration); |
1630 | | |
1631 | | // ii. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv. |
1632 | 0 | auto function = ECMAScriptFunctionObject::create(realm, function_declaration.name(), function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), function_declaration.local_variables_names(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(), |
1633 | 0 | function_declaration.parsing_insights()); |
1634 | | |
1635 | | // iii. Perform ! env.InitializeBinding(fn, fo). NOTE: This step is replaced in section B.3.2.6. |
1636 | 0 | if (function_declaration.name_identifier()->is_local()) { |
1637 | 0 | auto& running_execution_context = vm.running_execution_context(); |
1638 | 0 | auto number_of_registers = running_execution_context.executable->number_of_registers; |
1639 | 0 | auto number_of_constants = running_execution_context.executable->constants.size(); |
1640 | 0 | running_execution_context.local(function_declaration.name_identifier()->local_variable_index() + number_of_registers + number_of_constants) = function; |
1641 | 0 | } else { |
1642 | 0 | VERIFY(is<DeclarativeEnvironment>(*environment)); |
1643 | 0 | static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, vm, function_declaration.name(), function); |
1644 | 0 | } |
1645 | 0 | } |
1646 | 0 | })); |
1647 | 0 | } |
1648 | | |
1649 | | // 16.1.7 GlobalDeclarationInstantiation ( script, env ), https://tc39.es/ecma262/#sec-globaldeclarationinstantiation |
1650 | | ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, GlobalEnvironment& global_environment) const |
1651 | 28 | { |
1652 | 28 | auto& realm = *vm.current_realm(); |
1653 | | |
1654 | | // 1. Let lexNames be the LexicallyDeclaredNames of script. |
1655 | | // 2. Let varNames be the VarDeclaredNames of script. |
1656 | | // 3. For each element name of lexNames, do |
1657 | 28 | TRY(for_each_lexically_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> { |
1658 | 28 | auto const& name = identifier.string(); |
1659 | | |
1660 | | // a. If env.HasVarDeclaration(name) is true, throw a SyntaxError exception. |
1661 | 28 | if (global_environment.has_var_declaration(name)) |
1662 | 28 | return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name); |
1663 | | |
1664 | | // b. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception. |
1665 | 28 | if (global_environment.has_lexical_declaration(name)) |
1666 | 28 | return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, name); |
1667 | | |
1668 | | // c. Let hasRestrictedGlobal be ? env.HasRestrictedGlobalProperty(name). |
1669 | 28 | auto has_restricted_global = TRY(global_environment.has_restricted_global_property(name)); |
1670 | | |
1671 | | // d. If hasRestrictedGlobal is true, throw a SyntaxError exception. |
1672 | 28 | if (has_restricted_global) |
1673 | 28 | return vm.throw_completion<SyntaxError>(ErrorType::RestrictedGlobalProperty, name); |
1674 | | |
1675 | 28 | return {}; |
1676 | 28 | })); |
1677 | | |
1678 | | // 4. For each element name of varNames, do |
1679 | 28 | TRY(for_each_var_declared_identifier([&](auto const& identifier) -> ThrowCompletionOr<void> { |
1680 | | // a. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception. |
1681 | 28 | if (global_environment.has_lexical_declaration(identifier.string())) |
1682 | 28 | return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, identifier.string()); |
1683 | | |
1684 | 28 | return {}; |
1685 | 28 | })); |
1686 | | |
1687 | | // 5. Let varDeclarations be the VarScopedDeclarations of script. |
1688 | | // 6. Let functionsToInitialize be a new empty List. |
1689 | 28 | Vector<FunctionDeclaration const&> functions_to_initialize; |
1690 | | |
1691 | | // 7. Let declaredFunctionNames be a new empty List. |
1692 | 28 | HashTable<DeprecatedFlyString> declared_function_names; |
1693 | | |
1694 | | // 8. For each element d of varDeclarations, in reverse List order, do |
1695 | | |
1696 | 28 | TRY(for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) -> ThrowCompletionOr<void> { |
1697 | | // a. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then |
1698 | | // i. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration. |
1699 | | // Note: This is checked in for_each_var_function_declaration_in_reverse_order. |
1700 | | |
1701 | | // ii. NOTE: If there are multiple function declarations for the same name, the last declaration is used. |
1702 | | |
1703 | | // iii. Let fn be the sole element of the BoundNames of d. |
1704 | | |
1705 | | // iv. If fn is not an element of declaredFunctionNames, then |
1706 | 28 | if (declared_function_names.set(function.name()) != AK::HashSetResult::InsertedNewEntry) |
1707 | 28 | return {}; |
1708 | | |
1709 | | // 1. Let fnDefinable be ? env.CanDeclareGlobalFunction(fn). |
1710 | 28 | auto function_definable = TRY(global_environment.can_declare_global_function(function.name())); |
1711 | | |
1712 | | // 2. If fnDefinable is false, throw a TypeError exception. |
1713 | 28 | if (!function_definable) |
1714 | 28 | return vm.throw_completion<TypeError>(ErrorType::CannotDeclareGlobalFunction, function.name()); |
1715 | | |
1716 | | // 3. Append fn to declaredFunctionNames. |
1717 | | // Note: Already done in step iv. above. |
1718 | | |
1719 | | // 4. Insert d as the first element of functionsToInitialize. |
1720 | | // NOTE: Since prepending is much slower, we just append |
1721 | | // and iterate in reverse order in step 16 below. |
1722 | 28 | functions_to_initialize.append(function); |
1723 | 28 | return {}; |
1724 | 28 | })); |
1725 | | |
1726 | | // 9. Let declaredVarNames be a new empty List. |
1727 | 28 | HashTable<DeprecatedFlyString> declared_var_names; |
1728 | | |
1729 | | // 10. For each element d of varDeclarations, do |
1730 | 28 | TRY(for_each_var_scoped_variable_declaration([&](Declaration const& declaration) { |
1731 | | // a. If d is a VariableDeclaration, a ForBinding, or a BindingIdentifier, then |
1732 | | // Note: This is done in for_each_var_scoped_variable_declaration. |
1733 | | |
1734 | | // i. For each String vn of the BoundNames of d, do |
1735 | 28 | return declaration.for_each_bound_identifier([&](auto const& identifier) -> ThrowCompletionOr<void> { |
1736 | 28 | auto const& name = identifier.string(); |
1737 | | // 1. If vn is not an element of declaredFunctionNames, then |
1738 | 28 | if (declared_function_names.contains(name)) |
1739 | 28 | return {}; |
1740 | | |
1741 | | // a. Let vnDefinable be ? env.CanDeclareGlobalVar(vn). |
1742 | 28 | auto var_definable = TRY(global_environment.can_declare_global_var(name)); |
1743 | | |
1744 | | // b. If vnDefinable is false, throw a TypeError exception. |
1745 | 28 | if (!var_definable) |
1746 | 28 | return vm.throw_completion<TypeError>(ErrorType::CannotDeclareGlobalVariable, name); |
1747 | | |
1748 | | // c. If vn is not an element of declaredVarNames, then |
1749 | | // i. Append vn to declaredVarNames. |
1750 | 28 | declared_var_names.set(name); |
1751 | 28 | return {}; |
1752 | 28 | }); |
1753 | 28 | })); |
1754 | | |
1755 | | // 11. NOTE: No abnormal terminations occur after this algorithm step if the global object is an ordinary object. However, if the global object is a Proxy exotic object it may exhibit behaviours that cause abnormal terminations in some of the following steps. |
1756 | | // 12. NOTE: Annex B.3.2.2 adds additional steps at this point. |
1757 | | |
1758 | | // 12. Let strict be IsStrict of script. |
1759 | | // 13. If strict is false, then |
1760 | 28 | if (!m_is_strict_mode) { |
1761 | | // a. Let declaredFunctionOrVarNames be the list-concatenation of declaredFunctionNames and declaredVarNames. |
1762 | | // b. For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause Contained within script, do |
1763 | 28 | TRY(for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) -> ThrowCompletionOr<void> { |
1764 | | // i. Let F be StringValue of the BindingIdentifier of f. |
1765 | 28 | auto function_name = function_declaration.name(); |
1766 | | |
1767 | | // ii. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for script, then |
1768 | | // Note: This step is already performed during parsing and for_each_function_hoistable_with_annexB_extension so this always passes here. |
1769 | | |
1770 | | // 1. If env.HasLexicalDeclaration(F) is false, then |
1771 | 28 | if (global_environment.has_lexical_declaration(function_name)) |
1772 | 28 | return {}; |
1773 | | |
1774 | | // a. Let fnDefinable be ? env.CanDeclareGlobalVar(F). |
1775 | 28 | auto function_definable = TRY(global_environment.can_declare_global_function(function_name)); |
1776 | | // b. If fnDefinable is true, then |
1777 | | |
1778 | 28 | if (!function_definable) |
1779 | 28 | return {}; |
1780 | | |
1781 | | // i. NOTE: A var binding for F is only instantiated here if it is neither a VarDeclaredName nor the name of another FunctionDeclaration. |
1782 | | |
1783 | | // ii. If declaredFunctionOrVarNames does not contain F, then |
1784 | | |
1785 | 28 | if (!declared_function_names.contains(function_name) && !declared_var_names.contains(function_name)) { |
1786 | | // i. Perform ? env.CreateGlobalVarBinding(F, false). |
1787 | 28 | TRY(global_environment.create_global_var_binding(function_name, false)); |
1788 | | |
1789 | | // ii. Append F to declaredFunctionOrVarNames. |
1790 | 28 | declared_function_names.set(function_name); |
1791 | 28 | } |
1792 | | |
1793 | | // iii. When the FunctionDeclaration f is evaluated, perform the following steps in place of the FunctionDeclaration Evaluation algorithm provided in 15.2.6: |
1794 | | // i. Let genv be the running execution context's VariableEnvironment. |
1795 | | // ii. Let benv be the running execution context's LexicalEnvironment. |
1796 | | // iii. Let fobj be ! benv.GetBindingValue(F, false). |
1797 | | // iv. Perform ? genv.SetMutableBinding(F, fobj, false). |
1798 | | // v. Return unused. |
1799 | 28 | function_declaration.set_should_do_additional_annexB_steps(); |
1800 | | |
1801 | 28 | return {}; |
1802 | 28 | })); |
1803 | | |
1804 | | // We should not use declared function names below here anymore since these functions are not in there in the spec. |
1805 | 28 | declared_function_names.clear(); |
1806 | 28 | } |
1807 | | |
1808 | | // 13. Let lexDeclarations be the LexicallyScopedDeclarations of script. |
1809 | | // 14. Let privateEnv be null. |
1810 | 28 | PrivateEnvironment* private_environment = nullptr; |
1811 | | |
1812 | | // 15. For each element d of lexDeclarations, do |
1813 | 28 | TRY(for_each_lexically_scoped_declaration([&](Declaration const& declaration) { |
1814 | | // a. NOTE: Lexically declared names are only instantiated here but not initialized. |
1815 | | // b. For each element dn of the BoundNames of d, do |
1816 | 28 | return declaration.for_each_bound_identifier([&](auto const& identifier) -> ThrowCompletionOr<void> { |
1817 | 28 | auto const& name = identifier.string(); |
1818 | | // i. If IsConstantDeclaration of d is true, then |
1819 | 28 | if (declaration.is_constant_declaration()) { |
1820 | | // 1. Perform ? env.CreateImmutableBinding(dn, true). |
1821 | 28 | TRY(global_environment.create_immutable_binding(vm, name, true)); |
1822 | 28 | } |
1823 | | // ii. Else, |
1824 | 28 | else { |
1825 | | // 1. Perform ? env.CreateMutableBinding(dn, false). |
1826 | 28 | TRY(global_environment.create_mutable_binding(vm, name, false)); |
1827 | 28 | } |
1828 | | |
1829 | 28 | return {}; |
1830 | 28 | }); |
1831 | 28 | })); |
1832 | | |
1833 | | // 16. For each Parse Node f of functionsToInitialize, do |
1834 | | // NOTE: We iterate in reverse order since we appended the functions |
1835 | | // instead of prepending. We append because prepending is much slower |
1836 | | // and we only use the created vector here. |
1837 | 28 | for (auto& declaration : functions_to_initialize.in_reverse()) { |
1838 | | // a. Let fn be the sole element of the BoundNames of f. |
1839 | | // b. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv. |
1840 | 0 | auto function = ECMAScriptFunctionObject::create(realm, declaration.name(), declaration.source_text(), declaration.body(), declaration.parameters(), declaration.function_length(), declaration.local_variables_names(), &global_environment, private_environment, declaration.kind(), declaration.is_strict_mode(), |
1841 | 0 | declaration.parsing_insights()); |
1842 | | |
1843 | | // c. Perform ? env.CreateGlobalFunctionBinding(fn, fo, false). |
1844 | 0 | TRY(global_environment.create_global_function_binding(declaration.name(), function, false)); |
1845 | 0 | } |
1846 | | |
1847 | | // 17. For each String vn of declaredVarNames, do |
1848 | 28 | for (auto& var_name : declared_var_names) { |
1849 | | // a. Perform ? env.CreateGlobalVarBinding(vn, false). |
1850 | 0 | TRY(global_environment.create_global_var_binding(var_name, false)); |
1851 | 0 | } |
1852 | | |
1853 | | // 18. Return unused. |
1854 | 28 | return {}; |
1855 | 28 | } |
1856 | | |
1857 | | ModuleRequest::ModuleRequest(DeprecatedFlyString module_specifier_, Vector<ImportAttribute> attributes) |
1858 | 0 | : module_specifier(move(module_specifier_)) |
1859 | 0 | , attributes(move(attributes)) |
1860 | 0 | { |
1861 | | // Perform step 10.e. from EvaluateImportCall, https://tc39.es/proposal-import-attributes/#sec-evaluate-import-call |
1862 | | // or step 2. from WithClauseToAttributes, https://tc39.es/proposal-import-attributes/#sec-with-clause-to-attributes |
1863 | | // e. / 2. Sort assertions by the code point order of the [[Key]] of each element. |
1864 | | // NOTE: This sorting is observable only in that hosts are prohibited from distinguishing among assertions by the order they occur in. |
1865 | 0 | quick_sort(this->attributes, [](ImportAttribute const& lhs, ImportAttribute const& rhs) { |
1866 | 0 | return lhs.key < rhs.key; |
1867 | 0 | }); |
1868 | 0 | } |
1869 | | |
1870 | | ByteString SourceRange::filename() const |
1871 | 0 | { |
1872 | 0 | return code->filename().to_byte_string(); |
1873 | 0 | } |
1874 | | |
1875 | | NonnullRefPtr<CallExpression> CallExpression::create(SourceRange source_range, NonnullRefPtr<Expression const> callee, ReadonlySpan<Argument> arguments, InvocationStyleEnum invocation_style, InsideParenthesesEnum inside_parens) |
1876 | 928 | { |
1877 | 928 | return ASTNodeWithTailArray::create<CallExpression>(arguments.size(), move(source_range), move(callee), arguments, invocation_style, inside_parens); |
1878 | 928 | } |
1879 | | |
1880 | | NonnullRefPtr<NewExpression> NewExpression::create(SourceRange source_range, NonnullRefPtr<Expression const> callee, ReadonlySpan<Argument> arguments, InvocationStyleEnum invocation_style, InsideParenthesesEnum inside_parens) |
1881 | 0 | { |
1882 | 0 | return ASTNodeWithTailArray::create<NewExpression>(arguments.size(), move(source_range), move(callee), arguments, invocation_style, inside_parens); |
1883 | 0 | } |
1884 | | |
1885 | | } |