2020-04-04 14:34:31 +01:00
|
|
|
/*
|
2023-04-13 00:47:15 +02:00
|
|
|
* Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org>
|
2020-04-04 14:34:31 +01:00
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-04-04 14:34:31 +01:00
|
|
|
*/
|
|
|
|
|
|
2022-01-15 17:26:06 +01:00
|
|
|
#include <LibJS/Runtime/AbstractOperations.h>
|
2021-10-20 21:16:30 +01:00
|
|
|
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
|
2020-04-04 14:34:31 +01:00
|
|
|
#include <LibJS/Runtime/Error.h>
|
|
|
|
|
#include <LibJS/Runtime/FunctionConstructor.h>
|
2021-06-27 21:48:34 +02:00
|
|
|
#include <LibJS/Runtime/FunctionObject.h>
|
2022-01-16 14:14:42 +01:00
|
|
|
#include <LibJS/Runtime/GeneratorPrototype.h>
|
2022-02-07 18:51:58 +01:00
|
|
|
#include <LibJS/Runtime/GlobalEnvironment.h>
|
2020-04-18 13:18:06 +02:00
|
|
|
#include <LibJS/Runtime/GlobalObject.h>
|
2022-01-15 17:26:06 +01:00
|
|
|
#include <LibJS/Runtime/Realm.h>
|
2026-02-23 11:50:46 +01:00
|
|
|
#include <LibJS/RustIntegration.h>
|
|
|
|
|
#include <LibJS/SourceCode.h>
|
2020-04-04 14:34:31 +01:00
|
|
|
|
|
|
|
|
namespace JS {
|
|
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC_DEFINE_ALLOCATOR(FunctionConstructor);
|
2023-11-19 09:45:05 +01:00
|
|
|
|
2022-08-16 00:20:49 +01:00
|
|
|
FunctionConstructor::FunctionConstructor(Realm& realm)
|
2023-04-13 00:47:15 +02:00
|
|
|
: NativeFunction(realm.vm().names.Function.as_string(), realm.intrinsics().function_prototype())
|
2020-04-04 14:34:31 +01:00
|
|
|
{
|
2020-06-20 15:40:48 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-07 08:41:28 +02:00
|
|
|
void FunctionConstructor::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-19 00:38:41 +01:00
|
|
|
|
|
|
|
|
// 20.2.2.2 Function.prototype, https://tc39.es/ecma262/#sec-function.prototype
|
2022-08-27 00:54:55 +01:00
|
|
|
define_direct_property(vm.names.prototype, realm.intrinsics().function_prototype(), 0);
|
2021-06-19 00:38:41 +01:00
|
|
|
|
2021-07-06 02:15:08 +03:00
|
|
|
define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
|
2020-04-04 14:34:31 +01:00
|
|
|
}
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 20.2.1.1.1 CreateDynamicFunction ( constructor, newTarget, kind, parameterArgs, bodyArg ), https://tc39.es/ecma262/#sec-createdynamicfunction
|
2024-12-03 10:56:21 +00:00
|
|
|
ThrowCompletionOr<GC::Ref<ECMAScriptFunctionObject>> FunctionConstructor::create_dynamic_function(VM& vm, FunctionObject& constructor, FunctionObject* new_target, FunctionKind kind, ReadonlySpan<Value> parameter_args, Value body_arg)
|
2024-11-03 20:10:56 +13:00
|
|
|
{
|
|
|
|
|
// 1. If newTarget is undefined, set newTarget to constructor.
|
2022-01-15 17:26:06 +01:00
|
|
|
if (new_target == nullptr)
|
|
|
|
|
new_target = &constructor;
|
|
|
|
|
|
|
|
|
|
StringView prefix;
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ref<Object> (Intrinsics::*fallback_prototype)() = nullptr;
|
2022-01-15 17:26:06 +01:00
|
|
|
|
|
|
|
|
switch (kind) {
|
2024-11-03 20:10:56 +13:00
|
|
|
// 2. If kind is normal, then
|
2022-01-15 17:26:06 +01:00
|
|
|
case FunctionKind::Normal:
|
|
|
|
|
// a. Let prefix be "function".
|
|
|
|
|
prefix = "function"sv;
|
|
|
|
|
|
|
|
|
|
// b. Let exprSym be the grammar symbol FunctionExpression.
|
|
|
|
|
// c. Let bodySym be the grammar symbol FunctionBody[~Yield, ~Await].
|
|
|
|
|
// d. Let parameterSym be the grammar symbol FormalParameters[~Yield, ~Await].
|
|
|
|
|
|
|
|
|
|
// e. Let fallbackProto be "%Function.prototype%".
|
2022-08-27 00:54:55 +01:00
|
|
|
fallback_prototype = &Intrinsics::function_prototype;
|
2022-01-15 17:26:06 +01:00
|
|
|
break;
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 3. Else if kind is generator, then
|
2022-01-15 17:26:06 +01:00
|
|
|
case FunctionKind::Generator:
|
|
|
|
|
// a. Let prefix be "function*".
|
|
|
|
|
prefix = "function*"sv;
|
|
|
|
|
|
|
|
|
|
// b. Let exprSym be the grammar symbol GeneratorExpression.
|
|
|
|
|
// c. Let bodySym be the grammar symbol GeneratorBody.
|
|
|
|
|
// d. Let parameterSym be the grammar symbol FormalParameters[+Yield, ~Await].
|
|
|
|
|
|
|
|
|
|
// e. Let fallbackProto be "%GeneratorFunction.prototype%".
|
2022-08-27 00:54:55 +01:00
|
|
|
fallback_prototype = &Intrinsics::generator_function_prototype;
|
2022-01-15 17:26:06 +01:00
|
|
|
break;
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 4. Else if kind is async, then
|
2022-01-15 17:26:06 +01:00
|
|
|
case FunctionKind::Async:
|
|
|
|
|
// a. Let prefix be "async function".
|
|
|
|
|
prefix = "async function"sv;
|
|
|
|
|
|
|
|
|
|
// b. Let exprSym be the grammar symbol AsyncFunctionExpression.
|
|
|
|
|
// c. Let bodySym be the grammar symbol AsyncFunctionBody.
|
|
|
|
|
// d. Let parameterSym be the grammar symbol FormalParameters[~Yield, +Await].
|
|
|
|
|
|
|
|
|
|
// e. Let fallbackProto be "%AsyncFunction.prototype%".
|
2022-08-27 00:54:55 +01:00
|
|
|
fallback_prototype = &Intrinsics::async_function_prototype;
|
2022-01-15 17:26:06 +01:00
|
|
|
break;
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 5. Else,
|
2022-01-15 17:26:06 +01:00
|
|
|
case FunctionKind::AsyncGenerator:
|
2024-11-03 20:10:56 +13:00
|
|
|
// a. Assert: kind is async-generator.
|
2022-01-15 17:26:06 +01:00
|
|
|
|
|
|
|
|
// b. Let prefix be "async function*".
|
|
|
|
|
prefix = "async function*"sv;
|
|
|
|
|
|
|
|
|
|
// c. Let exprSym be the grammar symbol AsyncGeneratorExpression.
|
|
|
|
|
// d. Let bodySym be the grammar symbol AsyncGeneratorBody.
|
|
|
|
|
// e. Let parameterSym be the grammar symbol FormalParameters[+Yield, +Await].
|
|
|
|
|
|
|
|
|
|
// f. Let fallbackProto be "%AsyncGeneratorFunction.prototype%".
|
2022-08-27 00:54:55 +01:00
|
|
|
fallback_prototype = &Intrinsics::async_generator_function_prototype;
|
2022-01-15 17:26:06 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 6. Let argCount be the number of elements in parameterArgs.
|
2024-12-03 10:56:21 +00:00
|
|
|
auto arg_count = parameter_args.size();
|
2024-11-03 20:10:56 +13:00
|
|
|
|
|
|
|
|
// 7. Let parameterStrings be a new empty List.
|
2024-12-03 10:56:21 +00:00
|
|
|
Vector<String> parameter_strings;
|
|
|
|
|
parameter_strings.ensure_capacity(arg_count);
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 8. For each element arg of parameterArgs, do
|
2024-12-03 10:56:21 +00:00
|
|
|
for (auto const& parameter_value : parameter_args) {
|
|
|
|
|
// a. Append ? ToString(arg) to parameterStrings.
|
|
|
|
|
parameter_strings.unchecked_append(TRY(parameter_value.to_string(vm)));
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 9. Let bodyString be ? ToString(bodyArg).
|
2024-12-03 10:56:21 +00:00
|
|
|
auto body_string = TRY(body_arg.to_string(vm));
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 10. Let currentRealm be the current Realm Record.
|
|
|
|
|
auto& realm = *vm.current_realm();
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2024-12-03 10:56:21 +00:00
|
|
|
// 11. Let P be the empty String.
|
2024-11-03 20:10:56 +13:00
|
|
|
String parameters_string;
|
|
|
|
|
|
2024-12-03 10:56:21 +00:00
|
|
|
// 12. If argCount > 0, then
|
2024-11-03 20:10:56 +13:00
|
|
|
if (arg_count > 0) {
|
|
|
|
|
// a. Set P to parameterStrings[0].
|
|
|
|
|
// b. Let k be 1.
|
|
|
|
|
// c. Repeat, while k < argCount,
|
|
|
|
|
// i. Let nextArgString be parameterStrings[k].
|
|
|
|
|
// ii. Set P to the string-concatenation of P, "," (a comma), and nextArgString.
|
|
|
|
|
// iii. Set k to k + 1.
|
|
|
|
|
parameters_string = MUST(String::join(',', parameter_strings));
|
2020-04-04 14:34:31 +01:00
|
|
|
}
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2024-12-03 10:56:21 +00:00
|
|
|
// 13. Let bodyParseString be the string-concatenation of 0x000A (LINE FEED), bodyString, and 0x000A (LINE FEED).
|
2024-11-03 20:10:56 +13:00
|
|
|
auto body_parse_string = ByteString::formatted("\n{}\n", body_string);
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2024-12-03 10:56:21 +00:00
|
|
|
// 14. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyParseString, and "}".
|
|
|
|
|
// 15. Let sourceText be StringToCodePoints(sourceString).
|
2024-11-03 20:10:56 +13:00
|
|
|
auto source_text = ByteString::formatted("{} anonymous({}\n) {{{}}}", prefix, parameters_string, body_parse_string);
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2024-12-03 10:56:21 +00:00
|
|
|
// 16. Perform ? HostEnsureCanCompileStrings(currentRealm, parameterStrings, bodyString, sourceString, FUNCTION, parameterArgs, bodyArg).
|
|
|
|
|
TRY(vm.host_ensure_can_compile_strings(realm, parameter_strings, body_string, source_text, CompilationType::Function, parameter_args, body_arg));
|
|
|
|
|
|
2026-02-23 11:50:46 +01:00
|
|
|
GC::Ptr<SharedFunctionInstanceData> function_data;
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2026-02-23 11:50:46 +01:00
|
|
|
auto rust_compilation = RustIntegration::compile_dynamic_function(vm, source_text, parameters_string, body_parse_string, kind);
|
2026-03-19 12:26:15 -05:00
|
|
|
if (!rust_compilation.has_value())
|
|
|
|
|
return vm.throw_completion<SyntaxError>("Failed to compile dynamic function"_string);
|
|
|
|
|
if (rust_compilation->is_error())
|
|
|
|
|
return vm.throw_completion<SyntaxError>(rust_compilation->release_error());
|
|
|
|
|
function_data = rust_compilation->value();
|
2020-09-27 18:45:21 +02:00
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 25. Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
|
2022-08-21 19:24:32 +01:00
|
|
|
auto* prototype = TRY(get_prototype_from_constructor(vm, *new_target, fallback_prototype));
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 26. Let env be currentRealm.[[GlobalEnv]].
|
2022-08-16 00:20:49 +01:00
|
|
|
auto& environment = realm.global_environment();
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2022-04-22 19:10:27 +01:00
|
|
|
// 27. Let privateEnv be null.
|
2022-05-01 01:10:05 +02:00
|
|
|
PrivateEnvironment* private_environment = nullptr;
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2025-12-20 14:23:47 -06:00
|
|
|
auto function = ECMAScriptFunctionObject::create_from_function_data(
|
|
|
|
|
realm,
|
2026-02-23 11:50:46 +01:00
|
|
|
*function_data,
|
2025-12-20 14:23:47 -06:00
|
|
|
&environment,
|
|
|
|
|
private_environment,
|
|
|
|
|
*prototype);
|
2022-01-15 17:26:06 +01:00
|
|
|
|
|
|
|
|
// FIXME: Remove the name argument from create() and do this instead.
|
2022-04-22 19:10:27 +01:00
|
|
|
// 29. Perform SetFunctionName(F, "anonymous").
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2022-04-22 19:10:27 +01:00
|
|
|
// 30. If kind is generator, then
|
2022-01-15 17:26:06 +01:00
|
|
|
if (kind == FunctionKind::Generator) {
|
2022-05-02 20:54:39 +02:00
|
|
|
// a. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
|
2024-05-04 15:48:23 +02:00
|
|
|
prototype = Object::create_prototype(realm, realm.intrinsics().generator_function_prototype_prototype());
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2022-05-02 20:54:39 +02:00
|
|
|
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
|
2022-01-15 17:26:06 +01:00
|
|
|
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
|
|
|
|
}
|
2022-04-22 19:10:27 +01:00
|
|
|
// 31. Else if kind is asyncGenerator, then
|
2022-01-15 17:26:06 +01:00
|
|
|
else if (kind == FunctionKind::AsyncGenerator) {
|
2022-05-02 20:54:39 +02:00
|
|
|
// a. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
|
2024-05-04 15:48:23 +02:00
|
|
|
prototype = Object::create_prototype(realm, realm.intrinsics().async_generator_function_prototype_prototype());
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2022-05-02 20:54:39 +02:00
|
|
|
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
|
2022-05-05 09:06:14 +02:00
|
|
|
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
2022-01-15 17:26:06 +01:00
|
|
|
}
|
2022-04-22 19:10:27 +01:00
|
|
|
// 32. Else if kind is normal, perform MakeConstructor(F).
|
2022-01-15 17:26:06 +01:00
|
|
|
else if (kind == FunctionKind::Normal) {
|
|
|
|
|
// FIXME: Implement MakeConstructor
|
2024-05-04 15:48:23 +02:00
|
|
|
prototype = Object::create_prototype(realm, realm.intrinsics().object_prototype());
|
2022-01-15 17:26:06 +01:00
|
|
|
prototype->define_direct_property(vm.names.constructor, function, Attribute::Writable | Attribute::Configurable);
|
|
|
|
|
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-22 19:10:27 +01:00
|
|
|
// 33. NOTE: Functions whose kind is async are not constructible and do not have a [[Construct]] internal method or a "prototype" property.
|
2022-01-15 17:26:06 +01:00
|
|
|
|
2022-04-22 19:10:27 +01:00
|
|
|
// 34. Return F.
|
2024-11-03 20:10:56 +13:00
|
|
|
return function;
|
2021-06-16 10:52:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
2021-10-20 21:16:30 +01:00
|
|
|
ThrowCompletionOr<Value> FunctionConstructor::call()
|
2021-06-16 10:52:48 -07:00
|
|
|
{
|
2021-10-20 21:16:30 +01:00
|
|
|
return TRY(construct(*this));
|
2021-06-16 10:52:48 -07:00
|
|
|
}
|
|
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 20.2.1.1 Function ( ...parameterArgs, bodyArg ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
2024-11-15 04:01:23 +13:00
|
|
|
ThrowCompletionOr<GC::Ref<Object>> FunctionConstructor::construct(FunctionObject& new_target)
|
2021-06-16 10:52:48 -07:00
|
|
|
{
|
2021-10-20 21:16:30 +01:00
|
|
|
auto& vm = this->vm();
|
2021-06-16 10:52:48 -07:00
|
|
|
|
2026-03-08 12:30:23 +01:00
|
|
|
ReadonlySpan<Value> arguments = vm.running_execution_context().arguments_span();
|
2024-12-03 10:56:21 +00:00
|
|
|
|
|
|
|
|
ReadonlySpan<Value> parameter_args = arguments;
|
|
|
|
|
if (!parameter_args.is_empty())
|
|
|
|
|
parameter_args = parameter_args.slice(0, parameter_args.size() - 1);
|
|
|
|
|
|
2022-01-15 17:26:06 +01:00
|
|
|
// 1. Let C be the active function object.
|
|
|
|
|
auto* constructor = vm.active_function_object();
|
2020-09-27 18:45:21 +02:00
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 2. If bodyArg is not present, set bodyArg to the empty String.
|
2024-12-03 10:56:21 +00:00
|
|
|
Value body_arg = &vm.empty_string();
|
|
|
|
|
if (!arguments.is_empty())
|
|
|
|
|
body_arg = arguments.last();
|
2020-09-27 18:45:21 +02:00
|
|
|
|
2024-11-03 20:10:56 +13:00
|
|
|
// 3. Return ? CreateDynamicFunction(C, NewTarget, normal, parameterArgs, bodyArg).
|
2024-12-03 10:56:21 +00:00
|
|
|
return TRY(create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Normal, parameter_args, body_arg));
|
2020-04-04 14:34:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|