|
@@ -4,11 +4,12 @@
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
*/
|
|
|
|
|
|
-#include <AK/StringBuilder.h>
|
|
|
#include <LibJS/AST.h>
|
|
|
#include <LibJS/Interpreter.h>
|
|
|
+#include <LibJS/Lexer.h>
|
|
|
#include <LibJS/Parser.h>
|
|
|
#include <LibJS/Runtime/Error.h>
|
|
|
+#include <LibJS/Runtime/Function.h>
|
|
|
#include <LibJS/Runtime/FunctionConstructor.h>
|
|
|
#include <LibJS/Runtime/GlobalObject.h>
|
|
|
|
|
@@ -31,48 +32,59 @@ FunctionConstructor::~FunctionConstructor()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
|
|
-Value FunctionConstructor::call()
|
|
|
-{
|
|
|
- return construct(*this);
|
|
|
-}
|
|
|
-
|
|
|
-// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
|
|
-Value FunctionConstructor::construct(Function&)
|
|
|
+// 20.2.1.1.1 CreateDynamicFunction ( constructor, newTarget, kind, args ), https://tc39.es/ecma262/#sec-createdynamicfunction
|
|
|
+RefPtr<FunctionExpression> FunctionConstructor::create_dynamic_function_node(GlobalObject& global_object, Function&, FunctionKind kind)
|
|
|
{
|
|
|
- auto& vm = this->vm();
|
|
|
+ auto& vm = global_object.vm();
|
|
|
String parameters_source = "";
|
|
|
String body_source = "";
|
|
|
if (vm.argument_count() == 1) {
|
|
|
- body_source = vm.argument(0).to_string(global_object());
|
|
|
+ body_source = vm.argument(0).to_string(global_object);
|
|
|
if (vm.exception())
|
|
|
return {};
|
|
|
}
|
|
|
if (vm.argument_count() > 1) {
|
|
|
Vector<String> parameters;
|
|
|
for (size_t i = 0; i < vm.argument_count() - 1; ++i) {
|
|
|
- parameters.append(vm.argument(i).to_string(global_object()));
|
|
|
+ parameters.append(vm.argument(i).to_string(global_object));
|
|
|
if (vm.exception())
|
|
|
return {};
|
|
|
}
|
|
|
StringBuilder parameters_builder;
|
|
|
parameters_builder.join(',', parameters);
|
|
|
parameters_source = parameters_builder.build();
|
|
|
- body_source = vm.argument(vm.argument_count() - 1).to_string(global_object());
|
|
|
+ body_source = vm.argument(vm.argument_count() - 1).to_string(global_object);
|
|
|
if (vm.exception())
|
|
|
return {};
|
|
|
}
|
|
|
- auto source = String::formatted("function anonymous({}\n) {{\n{}\n}}", parameters_source, body_source);
|
|
|
+ auto is_generator = kind == FunctionKind::Generator;
|
|
|
+ auto source = String::formatted("function{} anonymous({}\n) {{\n{}\n}}", is_generator ? "*" : "", parameters_source, body_source);
|
|
|
auto parser = Parser(Lexer(source));
|
|
|
- auto function_expression = parser.parse_function_node<FunctionExpression>();
|
|
|
+ auto function = parser.parse_function_node<FunctionExpression>();
|
|
|
if (parser.has_errors()) {
|
|
|
auto error = parser.errors()[0];
|
|
|
- vm.throw_exception<SyntaxError>(global_object(), error.to_string());
|
|
|
+ vm.throw_exception<SyntaxError>(global_object, error.to_string());
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
+ return function;
|
|
|
+}
|
|
|
+
|
|
|
+// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
|
|
+Value FunctionConstructor::call()
|
|
|
+{
|
|
|
+ return construct(*this);
|
|
|
+}
|
|
|
+
|
|
|
+// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
|
|
+Value FunctionConstructor::construct(Function& new_target)
|
|
|
+{
|
|
|
+ auto function = create_dynamic_function_node(global_object(), new_target, FunctionKind::Regular);
|
|
|
+ if (!function)
|
|
|
+ return {};
|
|
|
+
|
|
|
OwnPtr<Interpreter> local_interpreter;
|
|
|
- Interpreter* interpreter = vm.interpreter_if_exists();
|
|
|
+ Interpreter* interpreter = vm().interpreter_if_exists();
|
|
|
|
|
|
if (!interpreter) {
|
|
|
local_interpreter = Interpreter::create_with_existing_global_object(global_object());
|
|
@@ -80,7 +92,7 @@ Value FunctionConstructor::construct(Function&)
|
|
|
}
|
|
|
|
|
|
VM::InterpreterExecutionScope scope(*interpreter);
|
|
|
- return function_expression->execute(*interpreter, global_object());
|
|
|
+ return function->execute(*interpreter, global_object());
|
|
|
}
|
|
|
|
|
|
}
|