| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-04-22 16:53:07 -07:00
										 |  |  |  * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |  * Copyright (c) 2021, Linus Groh <linusg@serenityos.org> | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/Array.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/Error.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/GlobalObject.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/ProxyConstructor.h>
 | 
					
						
							|  |  |  | #include <LibJS/Runtime/ProxyObject.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace JS { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 00:22:35 +01:00
										 |  |  | // 10.5.14 ProxyCreate ( target, handler ), https://tc39.es/ecma262/#sec-proxycreate
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | static ProxyObject* proxy_create(GlobalObject& global_object, Value target, Value handler) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto& vm = global_object.vm(); | 
					
						
							|  |  |  |     if (!target.is_object()) { | 
					
						
							|  |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::ProxyConstructorBadType, "target", target.to_string_without_side_effects()); | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!handler.is_object()) { | 
					
						
							|  |  |  |         vm.throw_exception<TypeError>(global_object, ErrorType::ProxyConstructorBadType, "handler", handler.to_string_without_side_effects()); | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ProxyObject::create(global_object, target.as_object(), handler.as_object()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-20 15:40:48 +02:00
										 |  |  | ProxyConstructor::ProxyConstructor(GlobalObject& global_object) | 
					
						
							| 
									
										
										
										
											2020-10-13 23:49:19 +02:00
										 |  |  |     : NativeFunction(vm().names.Proxy, *global_object.function_prototype()) | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-20 15:40:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 17:50:18 +02:00
										 |  |  | void ProxyConstructor::initialize(GlobalObject& global_object) | 
					
						
							| 
									
										
										
										
											2020-06-20 15:40:48 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-13 23:49:19 +02:00
										 |  |  |     auto& vm = this->vm(); | 
					
						
							| 
									
										
										
										
											2020-07-22 17:50:18 +02:00
										 |  |  |     NativeFunction::initialize(global_object); | 
					
						
							| 
									
										
										
										
											2020-10-13 23:49:19 +02:00
										 |  |  |     define_property(vm.names.length, Value(2), Attribute::Configurable); | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |     u8 attr = Attribute::Writable | Attribute::Configurable; | 
					
						
							|  |  |  |     define_native_function(vm.names.revocable, revocable, 2, attr); | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ProxyConstructor::~ProxyConstructor() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 00:22:35 +01:00
										 |  |  | // 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler
 | 
					
						
							| 
									
										
										
										
											2020-09-27 17:24:14 +02:00
										 |  |  | Value ProxyConstructor::call() | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-02 09:39:20 +00:00
										 |  |  |     auto& vm = this->vm(); | 
					
						
							|  |  |  |     vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.Proxy); | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 00:22:35 +01:00
										 |  |  | // 28.2.1.1 Proxy ( target, handler ), https://tc39.es/ecma262/#sec-proxy-target-handler
 | 
					
						
							| 
									
										
										
										
											2020-09-27 18:45:21 +02:00
										 |  |  | Value ProxyConstructor::construct(Function&) | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 18:45:21 +02:00
										 |  |  |     auto& vm = this->vm(); | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |     return proxy_create(global_object(), vm.argument(0), vm.argument(1)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 00:22:35 +01:00
										 |  |  | // 28.2.2.1 Proxy.revocable ( target, handler ), https://tc39.es/ecma262/#sec-proxy.revocable
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | JS_DEFINE_NATIVE_FUNCTION(ProxyConstructor::revocable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto* proxy = proxy_create(global_object, vm.argument(0), vm.argument(1)); | 
					
						
							|  |  |  |     if (vm.exception()) | 
					
						
							| 
									
										
										
										
											2020-08-25 12:52:32 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 00:22:35 +01:00
										 |  |  |     // 28.2.2.1.1 Proxy Revocation Functions, https://tc39.es/ecma262/#sec-proxy-revocation-functions
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |     auto* revoker = NativeFunction::create(global_object, "", [proxy_handle = make_handle(proxy)](auto&, auto&) -> Value { | 
					
						
							|  |  |  |         auto& proxy = const_cast<ProxyObject&>(*proxy_handle.cell()); | 
					
						
							|  |  |  |         if (proxy.is_revoked()) | 
					
						
							|  |  |  |             return js_undefined(); | 
					
						
							|  |  |  |         // NOTE: The spec wants us to unset [[ProxyTarget]] and [[ProxyHandler]],
 | 
					
						
							|  |  |  |         // which is their way of revoking the Proxy - this might affect GC-ability,
 | 
					
						
							|  |  |  |         // but AFAICT not doing that should be ok compatibility-wise.
 | 
					
						
							|  |  |  |         proxy.revoke(); | 
					
						
							|  |  |  |         return js_undefined(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     revoker->define_property(vm.names.length, Value(0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto* result = Object::create_empty(global_object); | 
					
						
							|  |  |  |     result->define_property(vm.names.proxy, proxy); | 
					
						
							|  |  |  |     result->define_property(vm.names.revoke, revoker); | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |