summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2022-02-20 17:15:40 +0000
committerLinus Groh <mail@linusgroh.de>2022-02-20 23:21:40 +0000
commite4f165d460d8fbc909693894ad06b03ec261dc8e (patch)
tree75539ae30b9943fcd4ea7f8b7aea4b05435e4f2e /Userland
parente657e88ed662db962dbb1d6b825cd96be221ad3b (diff)
downloadserenity-e4f165d460d8fbc909693894ad06b03ec261dc8e.zip
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.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Runtime/NativeFunction.cpp47
-rw-r--r--Userland/Libraries/LibJS/Runtime/NativeFunction.h5
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 <kling@serenityos.org>
- * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -9,15 +9,60 @@
#include <LibJS/Runtime/FunctionEnvironment.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/NativeFunction.h>
+#include <LibJS/Runtime/Realm.h>
#include <LibJS/Runtime/Value.h>
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<ThrowCompletionOr<Value>(VM&, GlobalObject&)> behaviour, i32 length, PropertyKey const& name, Optional<Realm*> realm, Optional<Object*> prototype, Optional<StringView> 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<NativeFunction>(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<ThrowCompletionOr<Value>(VM&, GlobalObject&)> function)
{
return global_object.heap().allocate<NativeFunction>(global_object, name, move(function), *global_object.function_prototype());
}
+NativeFunction::NativeFunction(GlobalObject& global_object, Function<ThrowCompletionOr<Value>(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 <AK/Optional.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/FunctionObject.h>
+#include <LibJS/Runtime/PropertyKey.h>
namespace JS {
@@ -19,9 +20,11 @@ class NativeFunction : public FunctionObject {
JS_OBJECT(NativeFunction, FunctionObject);
public:
+ static NativeFunction* create(GlobalObject&, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> behaviour, i32 length, PropertyKey const& name, Optional<Realm*> = {}, Optional<Object*> prototype = {}, Optional<StringView> const& prefix = {});
static NativeFunction* create(GlobalObject&, const FlyString& name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>);
- explicit NativeFunction(FlyString name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>, Object& prototype);
+ NativeFunction(GlobalObject&, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>, Object* prototype, Realm& realm);
+ NativeFunction(FlyString name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>, Object& prototype);
virtual void initialize(GlobalObject&) override { }
virtual ~NativeFunction() override;