| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-04-22 16:53:07 -07:00
										 |  |  |  * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org> | 
					
						
							| 
									
										
										
										
											2023-04-13 00:47:15 +02:00
										 |  |  |  * Copyright (c) 2021-2023, 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 { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | GC_DEFINE_ALLOCATOR(ProxyConstructor); | 
					
						
							| 
									
										
										
										
											2023-11-19 09:45:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 00:22:35 +01:00
										 |  |  | // 10.5.14 ProxyCreate ( target, handler ), https://tc39.es/ecma262/#sec-proxycreate
 | 
					
						
							| 
									
										
										
										
											2022-08-21 20:38:35 +01:00
										 |  |  | static ThrowCompletionOr<ProxyObject*> proxy_create(VM& vm, Value target, Value handler) | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-08-21 20:38:35 +01:00
										 |  |  |     auto& realm = *vm.current_realm(); | 
					
						
							| 
									
										
										
										
											2023-04-14 17:06:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 1. If target is not an Object, throw a TypeError exception.
 | 
					
						
							| 
									
										
										
										
											2021-10-29 01:06:20 +03:00
										 |  |  |     if (!target.is_object()) | 
					
						
							| 
									
										
										
										
											2023-08-09 08:49:02 +02:00
										 |  |  |         return vm.throw_completion<TypeError>(ErrorType::ProxyConstructorBadType, "target", target.to_string_without_side_effects()); | 
					
						
							| 
									
										
										
										
											2023-04-14 17:06:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 2. If handler is not an Object, throw a TypeError exception.
 | 
					
						
							| 
									
										
										
										
											2021-10-29 01:06:20 +03:00
										 |  |  |     if (!handler.is_object()) | 
					
						
							| 
									
										
										
										
											2023-08-09 08:49:02 +02:00
										 |  |  |         return vm.throw_completion<TypeError>(ErrorType::ProxyConstructorBadType, "handler", handler.to_string_without_side_effects()); | 
					
						
							| 
									
										
										
										
											2023-04-14 17:06:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 3. Let P be MakeBasicObject(« [[ProxyHandler]], [[ProxyTarget]] »).
 | 
					
						
							|  |  |  |     // 4. Set P's essential internal methods, except for [[Call]] and [[Construct]], to the definitions specified in 10.5.
 | 
					
						
							|  |  |  |     // 5.  IsCallable(target) is true, then
 | 
					
						
							|  |  |  |     //    a. Set P.[[Call]] as specified in 10.5.12.
 | 
					
						
							|  |  |  |     //    b. If IsConstructor(target) is true, then
 | 
					
						
							|  |  |  |     //        i. Set P.[[Construct]] as specified in 10.5.13.
 | 
					
						
							|  |  |  |     // 6. Set P.[[ProxyTarget]] to target.
 | 
					
						
							|  |  |  |     // 7. Set P.[[ProxyHandler]] to handler.
 | 
					
						
							|  |  |  |     // 8. Return P.
 | 
					
						
							| 
									
										
										
										
											2022-12-13 20:49:50 +00:00
										 |  |  |     return ProxyObject::create(realm, target.as_object(), handler.as_object()).ptr(); | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-16 00:20:49 +01:00
										 |  |  | ProxyConstructor::ProxyConstructor(Realm& realm) | 
					
						
							| 
									
										
										
										
											2023-04-13 00:47:15 +02:00
										 |  |  |     : NativeFunction(realm.vm().names.Proxy.as_string(), realm.intrinsics().function_prototype()) | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-20 15:40:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-07 08:41:28 +02:00
										 |  |  | void ProxyConstructor::initialize(Realm& realm) | 
					
						
							| 
									
										
										
										
											2020-06-20 15:40:48 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-13 23:49:19 +02:00
										 |  |  |     auto& vm = this->vm(); | 
					
						
							| 
									
										
										
										
											2023-08-07 08:41:28 +02:00
										 |  |  |     Base::initialize(realm); | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |     u8 attr = Attribute::Writable | Attribute::Configurable; | 
					
						
							| 
									
										
										
										
											2022-08-22 21:47:35 +01:00
										 |  |  |     define_native_function(realm, vm.names.revocable, revocable, 2, attr); | 
					
						
							| 
									
										
										
										
											2021-07-08 02:49:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     define_direct_property(vm.names.length, Value(2), Attribute::Configurable); | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							| 
									
										
										
										
											2021-10-20 21:16:30 +01:00
										 |  |  | ThrowCompletionOr<Value> ProxyConstructor::call() | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-02 09:39:20 +00:00
										 |  |  |     auto& vm = this->vm(); | 
					
						
							| 
									
										
										
										
											2023-04-14 17:06:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 1. If NewTarget is undefined, throw a TypeError exception.
 | 
					
						
							| 
									
										
										
										
											2022-08-16 20:33:17 +01:00
										 |  |  |     return vm.throw_completion<TypeError>(ErrorType::ConstructorWithoutNew, vm.names.Proxy); | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | ThrowCompletionOr<GC::Ref<Object>> ProxyConstructor::construct(FunctionObject&) | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-27 18:45:21 +02:00
										 |  |  |     auto& vm = this->vm(); | 
					
						
							| 
									
										
										
										
											2023-04-14 17:06:08 +02:00
										 |  |  |     auto target = vm.argument(0); | 
					
						
							|  |  |  |     auto handler = vm.argument(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 2. Return ? ProxyCreate(target, handler).
 | 
					
						
							|  |  |  |     return *TRY(proxy_create(vm, target, handler)); | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											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-10-29 01:06:57 +03:00
										 |  |  | JS_DEFINE_NATIVE_FUNCTION(ProxyConstructor::revocable) | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-08-21 20:38:35 +01:00
										 |  |  |     auto& realm = *vm.current_realm(); | 
					
						
							| 
									
										
										
										
											2023-04-14 17:06:08 +02:00
										 |  |  |     auto target = vm.argument(0); | 
					
						
							|  |  |  |     auto handler = vm.argument(1); | 
					
						
							| 
									
										
										
										
											2022-08-16 00:20:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  |     // 1. Let p be ? ProxyCreate(target, handler).
 | 
					
						
							| 
									
										
										
										
											2023-04-14 17:06:08 +02:00
										 |  |  |     auto* proxy = TRY(proxy_create(vm, target, handler)); | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  |     // 2. Let revokerClosure be a new Abstract Closure with no parameters that captures nothing and performs the following steps when called:
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  |     auto revoker_closure = [proxy_handle = make_root(proxy)](auto&) -> ThrowCompletionOr<Value> { | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  |         // a. Let F be the active function object.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // b. Let p be F.[[RevocableProxy]].
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |         auto& proxy = const_cast<ProxyObject&>(*proxy_handle.cell()); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // c. If p is null, return undefined.
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |         if (proxy.is_revoked()) | 
					
						
							|  |  |  |             return js_undefined(); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // d. Set F.[[RevocableProxy]] to null.
 | 
					
						
							|  |  |  |         // e. Assert: p is a Proxy object.
 | 
					
						
							|  |  |  |         // f. Set p.[[ProxyTarget]] to null.
 | 
					
						
							|  |  |  |         // g. Set p.[[ProxyHandler]] to null.
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |         proxy.revoke(); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // h. Return undefined.
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |         return js_undefined(); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 20:54:39 +02:00
										 |  |  |     // 3. Let revoker be CreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »).
 | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  |     // 4. Set revoker.[[RevocableProxy]] to p.
 | 
					
						
							| 
									
										
										
										
											2022-12-13 20:49:50 +00:00
										 |  |  |     auto revoker = NativeFunction::create(realm, move(revoker_closure), 0, ""); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 20:54:39 +02:00
										 |  |  |     // 5. Let result be OrdinaryObjectCreate(%Object.prototype%).
 | 
					
						
							| 
									
										
										
										
											2022-12-13 20:49:50 +00:00
										 |  |  |     auto result = Object::create(realm, realm.intrinsics().object_prototype()); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 6. Perform ! CreateDataPropertyOrThrow(result, "proxy", p).
 | 
					
						
							| 
									
										
										
										
											2021-10-03 01:18:46 +01:00
										 |  |  |     MUST(result->create_data_property_or_throw(vm.names.proxy, proxy)); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 7. Perform ! CreateDataPropertyOrThrow(result, "revoke", revoker).
 | 
					
						
							| 
									
										
										
										
											2021-10-03 01:18:46 +01:00
										 |  |  |     MUST(result->create_data_property_or_throw(vm.names.revoke, revoker)); | 
					
						
							| 
									
										
										
										
											2022-02-20 17:51:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 8. Return result.
 | 
					
						
							| 
									
										
										
										
											2021-06-08 21:48:43 +01:00
										 |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2020-06-03 14:34:52 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |