mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:52:43 +00:00 
			
		
		
		
	 98d8a858cd
			
		
	
	
		98d8a858cd
		
	
	
	
	
		
			
			These should all have a name with an empty string. Not only does test262 verify this, but it also verifies that (for the executor) the name property is defined after the length property.
		
			
				
	
	
		
			98 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <LibJS/Runtime/Error.h>
 | |
| #include <LibJS/Runtime/MarkedValueList.h>
 | |
| #include <LibJS/Runtime/NativeFunction.h>
 | |
| #include <LibJS/Runtime/PromiseReaction.h>
 | |
| 
 | |
| namespace JS {
 | |
| 
 | |
| // 27.2.1.5 NewPromiseCapability ( C ), https://tc39.es/ecma262/#sec-newpromisecapability
 | |
| PromiseCapability new_promise_capability(GlobalObject& global_object, Value constructor)
 | |
| {
 | |
|     auto& vm = global_object.vm();
 | |
|     if (!constructor.is_constructor()) {
 | |
|         vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
 | |
|         return {};
 | |
|     }
 | |
| 
 | |
|     struct {
 | |
|         Value resolve { js_undefined() };
 | |
|         Value reject { js_undefined() };
 | |
|     } promise_capability_functions;
 | |
| 
 | |
|     // 27.2.1.5.1 GetCapabilitiesExecutor Functions, https://tc39.es/ecma262/#sec-getcapabilitiesexecutor-functions
 | |
|     auto* executor = NativeFunction::create(global_object, "", [&promise_capability_functions](auto& vm, auto& global_object) -> Value {
 | |
|         auto resolve = vm.argument(0);
 | |
|         auto reject = vm.argument(1);
 | |
|         // No idea what other engines say here.
 | |
|         if (!promise_capability_functions.resolve.is_undefined()) {
 | |
|             vm.template throw_exception<TypeError>(global_object, ErrorType::GetCapabilitiesExecutorCalledMultipleTimes);
 | |
|             return {};
 | |
|         }
 | |
|         if (!promise_capability_functions.reject.is_undefined()) {
 | |
|             vm.template throw_exception<TypeError>(global_object, ErrorType::GetCapabilitiesExecutorCalledMultipleTimes);
 | |
|             return {};
 | |
|         }
 | |
|         promise_capability_functions.resolve = resolve;
 | |
|         promise_capability_functions.reject = reject;
 | |
|         return js_undefined();
 | |
|     });
 | |
|     executor->define_direct_property(vm.names.length, Value(2), Attribute::Configurable);
 | |
|     executor->define_direct_property(vm.names.name, js_string(vm, String::empty()), Attribute::Configurable);
 | |
| 
 | |
|     MarkedValueList arguments(vm.heap());
 | |
|     arguments.append(executor);
 | |
|     auto promise = vm.construct(constructor.as_function(), constructor.as_function(), move(arguments));
 | |
|     if (vm.exception())
 | |
|         return {};
 | |
| 
 | |
|     // I'm not sure if we could VERIFY(promise.is_object()) instead - the spec doesn't have this check...
 | |
|     if (!promise.is_object()) {
 | |
|         vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, promise.to_string_without_side_effects());
 | |
|         return {};
 | |
|     }
 | |
| 
 | |
|     if (!promise_capability_functions.resolve.is_function()) {
 | |
|         vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, promise_capability_functions.resolve.to_string_without_side_effects());
 | |
|         return {};
 | |
|     }
 | |
|     if (!promise_capability_functions.reject.is_function()) {
 | |
|         vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, promise_capability_functions.reject.to_string_without_side_effects());
 | |
|         return {};
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|         &promise.as_object(),
 | |
|         &promise_capability_functions.resolve.as_function(),
 | |
|         &promise_capability_functions.reject.as_function(),
 | |
|     };
 | |
| }
 | |
| 
 | |
| PromiseReaction::PromiseReaction(Type type, Optional<PromiseCapability> capability, Optional<JobCallback> handler)
 | |
|     : m_type(type)
 | |
|     , m_capability(move(capability))
 | |
|     , m_handler(move(handler))
 | |
| {
 | |
| }
 | |
| 
 | |
| void PromiseReaction::visit_edges(Cell::Visitor& visitor)
 | |
| {
 | |
|     Cell::visit_edges(visitor);
 | |
|     if (m_capability.has_value()) {
 | |
|         auto& capability = m_capability.value();
 | |
|         visitor.visit(capability.promise);
 | |
|         visitor.visit(capability.resolve);
 | |
|         visitor.visit(capability.reject);
 | |
|     }
 | |
|     if (m_handler.has_value()) {
 | |
|         auto& handler = m_handler.value();
 | |
|         visitor.visit(handler.callback);
 | |
|     }
 | |
| }
 | |
| 
 | |
| }
 |