| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/GlobalObject.h>
 | 
					
						
							| 
									
										
										
										
											2023-07-19 06:54:48 -04:00
										 |  |  | #include <LibJS/Runtime/Iterator.h>
 | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | #include <LibJS/Runtime/IteratorHelper.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/Realm.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace JS { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | GC_DEFINE_ALLOCATOR(IteratorHelper); | 
					
						
							| 
									
										
										
										
											2023-11-19 09:45:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | ThrowCompletionOr<GC::Ref<IteratorHelper>> IteratorHelper::create(Realm& realm, GC::Ref<IteratorRecord> underlying_iterator, GC::Ref<Closure> closure, GC::Ptr<AbruptClosure> abrupt_closure) | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-11-14 05:50:17 +13:00
										 |  |  |     return realm.create<IteratorHelper>(realm, realm.intrinsics().iterator_helper_prototype(), move(underlying_iterator), closure, abrupt_closure); | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | IteratorHelper::IteratorHelper(Realm& realm, Object& prototype, GC::Ref<IteratorRecord> underlying_iterator, GC::Ref<Closure> closure, GC::Ptr<AbruptClosure> abrupt_closure) | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  |     : GeneratorObject(realm, prototype, realm.vm().running_execution_context().copy(), "Iterator Helper"sv) | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  |     , m_underlying_iterator(move(underlying_iterator)) | 
					
						
							| 
									
										
										
										
											2024-08-18 14:54:48 +12:00
										 |  |  |     , m_closure(closure) | 
					
						
							|  |  |  |     , m_abrupt_closure(abrupt_closure) | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void IteratorHelper::visit_edges(Visitor& visitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Base::visit_edges(visitor); | 
					
						
							| 
									
										
										
										
											2023-12-07 10:44:41 +01:00
										 |  |  |     visitor.visit(m_underlying_iterator); | 
					
						
							| 
									
										
										
										
											2024-08-18 14:54:48 +12:00
										 |  |  |     visitor.visit(m_closure); | 
					
						
							|  |  |  |     visitor.visit(m_abrupt_closure); | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Value IteratorHelper::result(Value value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  |     set_generator_state(value.is_undefined() ? GeneratorState::Completed : GeneratorState::SuspendedYield); | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  |     return value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  | ThrowCompletionOr<Value> IteratorHelper::close_result(VM& vm, Completion completion) | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  |     set_generator_state(GeneratorState::Completed); | 
					
						
							| 
									
										
										
										
											2025-04-04 18:11:45 +02:00
										 |  |  |     return TRY(iterator_close(vm, underlying_iterator(), move(completion))); | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-09 04:23:30 +03:00
										 |  |  | ThrowCompletionOr<GeneratorObject::IterationResult> IteratorHelper::execute(VM& vm, JS::Completion const& completion) | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     ScopeGuard guard { [&] { vm.pop_execution_context(); } }; | 
					
						
							| 
									
										
										
										
											2023-07-16 15:50:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (completion.is_abrupt()) { | 
					
						
							| 
									
										
										
										
											2025-05-09 04:23:30 +03:00
										 |  |  |         if (m_abrupt_closure) { | 
					
						
							|  |  |  |             auto abrupt_result = TRY(m_abrupt_closure->function()(vm, *this, completion)); | 
					
						
							|  |  |  |             return IterationResult(abrupt_result, true); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         auto close_result = TRY(this->close_result(vm, completion)); | 
					
						
							|  |  |  |         return IterationResult(close_result, true); | 
					
						
							| 
									
										
										
										
											2023-07-16 15:50:56 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 14:54:48 +12:00
										 |  |  |     auto result_value = m_closure->function()(vm, *this); | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (result_value.is_throw_completion()) { | 
					
						
							|  |  |  |         set_generator_state(GeneratorState::Completed); | 
					
						
							| 
									
										
										
										
											2025-05-09 04:23:30 +03:00
										 |  |  |         return result_value.throw_completion(); | 
					
						
							| 
									
										
										
										
											2023-07-16 15:04:59 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-09 04:23:30 +03:00
										 |  |  |     return IterationResult(result(result_value.release_value()), generator_state() == GeneratorState::Completed); | 
					
						
							| 
									
										
										
										
											2023-06-25 09:39:33 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |