From e4f165d460d8fbc909693894ad06b03ec261dc8e Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sun, 20 Feb 2022 17:15:40 +0000 Subject: [PATCH] LibJS: Add NativeFunction::create() overload for CreateBuiltinFunction Also take a length argument and set the name and length properties internally, instead of at the call site. Additionally, allow passing a realm, prototype, and prefix. --- .../LibJS/Runtime/NativeFunction.cpp | 47 ++++++++++++++++++- .../Libraries/LibJS/Runtime/NativeFunction.h | 5 +- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp index 72bc55acc2..a26db38685 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Andreas Kling - * Copyright (c) 2021, Linus Groh + * Copyright (c) 2021-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -9,15 +9,60 @@ #include #include #include +#include #include namespace JS { +// 10.3.3 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix ] ] ] ), https://tc39.es/ecma262/#sec-createbuiltinfunction +// NOTE: This doesn't consider additionalInternalSlotsList, which is rarely used, and can either be implemented using only the `function` lambda, or needs a NativeFunction subclass. +NativeFunction* NativeFunction::create(GlobalObject& global_object, Function(VM&, GlobalObject&)> behaviour, i32 length, PropertyKey const& name, Optional realm, Optional prototype, Optional const& prefix) +{ + auto& vm = global_object.vm(); + + // 1. If realm is not present, set realm to the current Realm Record. + if (!realm.has_value()) + realm = vm.current_realm(); + + // 2. If prototype is not present, set prototype to realm.[[Intrinsics]].[[%Function.prototype%]]. + if (!prototype.has_value()) + prototype = realm.value()->global_object().function_prototype(); + + // 3. Let internalSlotsList be a List containing the names of all the internal slots that 10.3 requires for the built-in function object that is about to be created. + // 4. Append to internalSlotsList the elements of additionalInternalSlotsList. + + // 5. Let func be a new built-in function object that, when called, performs the action described by behaviour using the provided arguments as the values of the corresponding parameters specified by behaviour. The new function object has internal slots whose names are the elements of internalSlotsList, and an [[InitialName]] internal slot. + // 6. Set func.[[Prototype]] to prototype. + // 7. Set func.[[Extensible]] to true. + // 8. Set func.[[Realm]] to realm. + // 9. Set func.[[InitialName]] to null. + auto* function = global_object.heap().allocate(global_object, global_object, move(behaviour), prototype.value(), *realm.value()); + + // 10. Perform ! SetFunctionLength(func, length). + function->set_function_length(length); + + // 11. If prefix is not present, then + // a. Perform ! SetFunctionName(func, name). + // 12. Else, + // a. Perform ! SetFunctionName(func, name, prefix). + function->set_function_name(name, prefix); + + // 13. Return func. + return function; +} + NativeFunction* NativeFunction::create(GlobalObject& global_object, const FlyString& name, Function(VM&, GlobalObject&)> function) { return global_object.heap().allocate(global_object, name, move(function), *global_object.function_prototype()); } +NativeFunction::NativeFunction(GlobalObject& global_object, Function(VM&, GlobalObject&)> native_function, Object* prototype, Realm& realm) + : FunctionObject(global_object, prototype) + , m_native_function(move(native_function)) + , m_realm(&realm) +{ +} + // FIXME: m_realm is supposed to be the realm argument of CreateBuiltinFunction, or the current // Realm Record. The former is not something that's commonly used or we support, the // latter is impossible as no ExecutionContext exists when most NativeFunctions are created... diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.h b/Userland/Libraries/LibJS/Runtime/NativeFunction.h index a13a471cf2..24775ea61d 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.h +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace JS { @@ -19,9 +20,11 @@ class NativeFunction : public FunctionObject { JS_OBJECT(NativeFunction, FunctionObject); public: + static NativeFunction* create(GlobalObject&, Function(VM&, GlobalObject&)> behaviour, i32 length, PropertyKey const& name, Optional = {}, Optional prototype = {}, Optional const& prefix = {}); static NativeFunction* create(GlobalObject&, const FlyString& name, Function(VM&, GlobalObject&)>); - explicit NativeFunction(FlyString name, Function(VM&, GlobalObject&)>, Object& prototype); + NativeFunction(GlobalObject&, Function(VM&, GlobalObject&)>, Object* prototype, Realm& realm); + NativeFunction(FlyString name, Function(VM&, GlobalObject&)>, Object& prototype); virtual void initialize(GlobalObject&) override { } virtual ~NativeFunction() override;