summaryrefslogtreecommitdiff
path: root/Libraries/LibJS
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-17 19:59:32 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-18 10:28:22 +0200
commitf6d57c82f6dbbb5c7e18bffb43d0258956aa0d46 (patch)
tree1a2a20ded1dccf299926da1f02babf3e30c386b3 /Libraries/LibJS
parent205ac0090da21c593ac7cef7db348412e4f52168 (diff)
downloadserenity-f6d57c82f6dbbb5c7e18bffb43d0258956aa0d46.zip
LibJS: Pass prototype to Function constructors
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r--Libraries/LibJS/AST.cpp4
-rw-r--r--Libraries/LibJS/Interpreter.cpp3
-rw-r--r--Libraries/LibJS/Runtime/ArrayConstructor.cpp2
-rw-r--r--Libraries/LibJS/Runtime/BooleanConstructor.cpp2
-rw-r--r--Libraries/LibJS/Runtime/DateConstructor.cpp2
-rw-r--r--Libraries/LibJS/Runtime/ErrorConstructor.cpp3
-rw-r--r--Libraries/LibJS/Runtime/Function.cpp4
-rw-r--r--Libraries/LibJS/Runtime/Function.h2
-rw-r--r--Libraries/LibJS/Runtime/FunctionConstructor.cpp2
-rw-r--r--Libraries/LibJS/Runtime/FunctionPrototype.cpp4
-rw-r--r--Libraries/LibJS/Runtime/FunctionPrototype.h2
-rw-r--r--Libraries/LibJS/Runtime/NativeFunction.cpp21
-rw-r--r--Libraries/LibJS/Runtime/NativeFunction.h8
-rw-r--r--Libraries/LibJS/Runtime/NumberConstructor.cpp2
-rw-r--r--Libraries/LibJS/Runtime/Object.cpp2
-rw-r--r--Libraries/LibJS/Runtime/ObjectConstructor.cpp2
-rw-r--r--Libraries/LibJS/Runtime/ObjectPrototype.cpp5
-rw-r--r--Libraries/LibJS/Runtime/ObjectPrototype.h2
-rw-r--r--Libraries/LibJS/Runtime/ScriptFunction.cpp12
-rw-r--r--Libraries/LibJS/Runtime/ScriptFunction.h4
-rw-r--r--Libraries/LibJS/Runtime/StringConstructor.cpp2
21 files changed, 66 insertions, 24 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp
index 6929ce43ea..a29229422f 100644
--- a/Libraries/LibJS/AST.cpp
+++ b/Libraries/LibJS/AST.cpp
@@ -48,14 +48,14 @@ Value ScopeNode::execute(Interpreter& interpreter) const
Value FunctionDeclaration::execute(Interpreter& interpreter) const
{
- auto* function = interpreter.heap().allocate<ScriptFunction>(name(), body(), parameters(), interpreter.current_environment());
+ auto* function = ScriptFunction::create(interpreter.global_object(), name(), body(), parameters(), interpreter.current_environment());
interpreter.set_variable(name(), function);
return js_undefined();
}
Value FunctionExpression::execute(Interpreter& interpreter) const
{
- return interpreter.heap().allocate<ScriptFunction>(name(), body(), parameters(), interpreter.current_environment());
+ return ScriptFunction::create(interpreter.global_object(), name(), body(), parameters(), interpreter.current_environment());
}
Value ExpressionStatement::execute(Interpreter& interpreter) const
diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp
index 48820e9f10..d8ab574d55 100644
--- a/Libraries/LibJS/Interpreter.cpp
+++ b/Libraries/LibJS/Interpreter.cpp
@@ -54,6 +54,9 @@ Interpreter::Interpreter()
m_object_prototype = heap().allocate<ObjectPrototype>();
m_function_prototype = heap().allocate<FunctionPrototype>();
+ static_cast<FunctionPrototype*>(m_function_prototype)->initialize();
+ static_cast<ObjectPrototype*>(m_object_prototype)->initialize();
+
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
if (!m_##snake_name##_prototype) \
m_##snake_name##_prototype = heap().allocate<PrototypeName>();
diff --git a/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Libraries/LibJS/Runtime/ArrayConstructor.cpp
index f2578c0b81..2fd7162f33 100644
--- a/Libraries/LibJS/Runtime/ArrayConstructor.cpp
+++ b/Libraries/LibJS/Runtime/ArrayConstructor.cpp
@@ -34,7 +34,7 @@
namespace JS {
ArrayConstructor::ArrayConstructor()
- : NativeFunction("Array")
+ : NativeFunction("Array", *interpreter().function_prototype())
{
put("prototype", interpreter().array_prototype());
put("length", Value(1));
diff --git a/Libraries/LibJS/Runtime/BooleanConstructor.cpp b/Libraries/LibJS/Runtime/BooleanConstructor.cpp
index 4ffdf9071d..b588671946 100644
--- a/Libraries/LibJS/Runtime/BooleanConstructor.cpp
+++ b/Libraries/LibJS/Runtime/BooleanConstructor.cpp
@@ -33,7 +33,7 @@
namespace JS {
BooleanConstructor::BooleanConstructor()
- : NativeFunction("Boolean")
+ : NativeFunction("Boolean", *interpreter().function_prototype())
{
put("prototype", Value(interpreter().boolean_prototype()));
put("length", Value(1));
diff --git a/Libraries/LibJS/Runtime/DateConstructor.cpp b/Libraries/LibJS/Runtime/DateConstructor.cpp
index 87eefc4de7..79bf837e78 100644
--- a/Libraries/LibJS/Runtime/DateConstructor.cpp
+++ b/Libraries/LibJS/Runtime/DateConstructor.cpp
@@ -34,7 +34,7 @@
namespace JS {
DateConstructor::DateConstructor()
- : NativeFunction("Date")
+ : NativeFunction("Date", *interpreter().function_prototype())
{
put("prototype", interpreter().date_prototype());
put("length", Value(7));
diff --git a/Libraries/LibJS/Runtime/ErrorConstructor.cpp b/Libraries/LibJS/Runtime/ErrorConstructor.cpp
index 3932911d8d..11ce86f885 100644
--- a/Libraries/LibJS/Runtime/ErrorConstructor.cpp
+++ b/Libraries/LibJS/Runtime/ErrorConstructor.cpp
@@ -31,7 +31,7 @@
namespace JS {
ErrorConstructor::ErrorConstructor()
- : NativeFunction("Error")
+ : NativeFunction("Error", *interpreter().function_prototype())
{
put("prototype", interpreter().error_prototype());
put("length", Value(1));
@@ -56,6 +56,7 @@ Value ErrorConstructor::construct(Interpreter& interpreter)
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ConstructorName::ConstructorName() \
+ : NativeFunction(*interpreter().function_prototype()) \
{ \
put("prototype", interpreter().snake_name##_prototype()); \
put("length", Value(1)); \
diff --git a/Libraries/LibJS/Runtime/Function.cpp b/Libraries/LibJS/Runtime/Function.cpp
index fe72c6668c..06c760eac1 100644
--- a/Libraries/LibJS/Runtime/Function.cpp
+++ b/Libraries/LibJS/Runtime/Function.cpp
@@ -29,9 +29,9 @@
namespace JS {
-Function::Function()
+Function::Function(Object& prototype)
{
- set_prototype(interpreter().function_prototype());
+ set_prototype(&prototype);
}
Function::~Function()
diff --git a/Libraries/LibJS/Runtime/Function.h b/Libraries/LibJS/Runtime/Function.h
index 3465e02135..f06182a42a 100644
--- a/Libraries/LibJS/Runtime/Function.h
+++ b/Libraries/LibJS/Runtime/Function.h
@@ -41,7 +41,7 @@ public:
virtual LexicalEnvironment* create_environment() = 0;
protected:
- Function();
+ explicit Function(Object& prototype);
virtual const char* class_name() const override { return "Function"; }
private:
diff --git a/Libraries/LibJS/Runtime/FunctionConstructor.cpp b/Libraries/LibJS/Runtime/FunctionConstructor.cpp
index beb2ea842d..cb716e6206 100644
--- a/Libraries/LibJS/Runtime/FunctionConstructor.cpp
+++ b/Libraries/LibJS/Runtime/FunctionConstructor.cpp
@@ -35,7 +35,7 @@
namespace JS {
FunctionConstructor::FunctionConstructor()
- : NativeFunction("Function")
+ : NativeFunction("Function", *interpreter().function_prototype())
{
put("prototype", interpreter().function_prototype());
put("length", Value(1));
diff --git a/Libraries/LibJS/Runtime/FunctionPrototype.cpp b/Libraries/LibJS/Runtime/FunctionPrototype.cpp
index 62e6c60068..1cbf9cf082 100644
--- a/Libraries/LibJS/Runtime/FunctionPrototype.cpp
+++ b/Libraries/LibJS/Runtime/FunctionPrototype.cpp
@@ -37,6 +37,10 @@ namespace JS {
FunctionPrototype::FunctionPrototype()
{
+}
+
+void FunctionPrototype::initialize()
+{
put_native_function("apply", apply, 2);
put_native_function("bind", bind, 1);
put_native_function("call", call, 1);
diff --git a/Libraries/LibJS/Runtime/FunctionPrototype.h b/Libraries/LibJS/Runtime/FunctionPrototype.h
index 3248d7bb3b..1760522af3 100644
--- a/Libraries/LibJS/Runtime/FunctionPrototype.h
+++ b/Libraries/LibJS/Runtime/FunctionPrototype.h
@@ -33,6 +33,8 @@ namespace JS {
class FunctionPrototype final : public Object {
public:
FunctionPrototype();
+ void initialize();
+
virtual ~FunctionPrototype() override;
private:
diff --git a/Libraries/LibJS/Runtime/NativeFunction.cpp b/Libraries/LibJS/Runtime/NativeFunction.cpp
index aadf7d8060..f0fe227216 100644
--- a/Libraries/LibJS/Runtime/NativeFunction.cpp
+++ b/Libraries/LibJS/Runtime/NativeFunction.cpp
@@ -25,19 +25,32 @@
*/
#include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
-NativeFunction::NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&)> native_function)
- : m_name(name)
+NativeFunction* NativeFunction::create(Interpreter& interpreter, GlobalObject&, const FlyString& name, AK::Function<Value(Interpreter&)> function)
+{
+ return interpreter.heap().allocate<NativeFunction>(name, move(function), *interpreter.function_prototype());
+}
+
+NativeFunction::NativeFunction(Object& prototype)
+ : Function(prototype)
+{
+}
+
+NativeFunction::NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&)> native_function, Object& prototype)
+ : Function(prototype)
+ , m_name(name)
, m_native_function(move(native_function))
{
}
-NativeFunction::NativeFunction(const FlyString& name)
- : m_name(name)
+NativeFunction::NativeFunction(const FlyString& name, Object& prototype)
+ : Function(prototype)
+ , m_name(name)
{
}
diff --git a/Libraries/LibJS/Runtime/NativeFunction.h b/Libraries/LibJS/Runtime/NativeFunction.h
index ee03bafb47..9f0331c1a4 100644
--- a/Libraries/LibJS/Runtime/NativeFunction.h
+++ b/Libraries/LibJS/Runtime/NativeFunction.h
@@ -33,7 +33,9 @@ namespace JS {
class NativeFunction : public Function {
public:
- explicit NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&)>);
+ static NativeFunction* create(Interpreter&, GlobalObject&, const FlyString& name, AK::Function<Value(Interpreter&)>);
+
+ explicit NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&)>, Object& prototype);
virtual ~NativeFunction() override;
virtual Value call(Interpreter&) override;
@@ -43,8 +45,8 @@ public:
virtual bool has_constructor() const { return false; }
protected:
- NativeFunction(const FlyString& name);
- NativeFunction() {}
+ NativeFunction(const FlyString& name, Object& prototype);
+ explicit NativeFunction(Object& prototype);
private:
virtual bool is_native_function() const override { return true; }
diff --git a/Libraries/LibJS/Runtime/NumberConstructor.cpp b/Libraries/LibJS/Runtime/NumberConstructor.cpp
index 47dd980482..0d7c08e873 100644
--- a/Libraries/LibJS/Runtime/NumberConstructor.cpp
+++ b/Libraries/LibJS/Runtime/NumberConstructor.cpp
@@ -37,7 +37,7 @@
namespace JS {
NumberConstructor::NumberConstructor()
- : NativeFunction("Number")
+ : NativeFunction("Number", *interpreter().function_prototype())
{
put_native_function("isSafeInteger", is_safe_integer, 1);
diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp
index 251599ae7c..5d304cb2da 100644
--- a/Libraries/LibJS/Runtime/Object.cpp
+++ b/Libraries/LibJS/Runtime/Object.cpp
@@ -235,7 +235,7 @@ void Object::put(PropertyName property_name, Value value)
void Object::put_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&)> native_function, i32 length)
{
- auto* function = heap().allocate<NativeFunction>(property_name, move(native_function));
+ auto* function = NativeFunction::create(interpreter(), interpreter().global_object(), property_name, move(native_function));
function->put("length", Value(length));
put(property_name, function);
}
diff --git a/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Libraries/LibJS/Runtime/ObjectConstructor.cpp
index aa54de74b9..e9f4a67551 100644
--- a/Libraries/LibJS/Runtime/ObjectConstructor.cpp
+++ b/Libraries/LibJS/Runtime/ObjectConstructor.cpp
@@ -35,7 +35,7 @@
namespace JS {
ObjectConstructor::ObjectConstructor()
- : NativeFunction("Object")
+ : NativeFunction("Object", *interpreter().function_prototype())
{
put("prototype", interpreter().object_prototype());
diff --git a/Libraries/LibJS/Runtime/ObjectPrototype.cpp b/Libraries/LibJS/Runtime/ObjectPrototype.cpp
index c70c590253..85332ca727 100644
--- a/Libraries/LibJS/Runtime/ObjectPrototype.cpp
+++ b/Libraries/LibJS/Runtime/ObjectPrototype.cpp
@@ -36,7 +36,12 @@ namespace JS {
ObjectPrototype::ObjectPrototype()
{
set_prototype(nullptr);
+}
+void ObjectPrototype::initialize()
+{
+ // This must be called after the constructor has returned, so that the below code
+ // can find the ObjectPrototype through normal paths.
put_native_function("hasOwnProperty", has_own_property, 1);
put_native_function("toString", to_string);
put_native_function("valueOf", value_of);
diff --git a/Libraries/LibJS/Runtime/ObjectPrototype.h b/Libraries/LibJS/Runtime/ObjectPrototype.h
index f398c7b91c..737dadab8c 100644
--- a/Libraries/LibJS/Runtime/ObjectPrototype.h
+++ b/Libraries/LibJS/Runtime/ObjectPrototype.h
@@ -33,6 +33,8 @@ namespace JS {
class ObjectPrototype final : public Object {
public:
ObjectPrototype();
+ void initialize();
+
virtual ~ObjectPrototype() override;
private:
diff --git a/Libraries/LibJS/Runtime/ScriptFunction.cpp b/Libraries/LibJS/Runtime/ScriptFunction.cpp
index 67801181f6..1348eb4d05 100644
--- a/Libraries/LibJS/Runtime/ScriptFunction.cpp
+++ b/Libraries/LibJS/Runtime/ScriptFunction.cpp
@@ -28,13 +28,21 @@
#include <LibJS/AST.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/ScriptFunction.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
-ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment)
- : m_name(name)
+ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment)
+{
+ auto& interpreter = global_object.interpreter();
+ return interpreter.heap().allocate<ScriptFunction>(name, body, move(parameters), parent_environment, *interpreter.function_prototype());
+}
+
+ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment, Object& prototype)
+ : Function(prototype)
+ , m_name(name)
, m_body(body)
, m_parameters(move(parameters))
, m_parent_environment(parent_environment)
diff --git a/Libraries/LibJS/Runtime/ScriptFunction.h b/Libraries/LibJS/Runtime/ScriptFunction.h
index 1e65faca41..eb6da007c8 100644
--- a/Libraries/LibJS/Runtime/ScriptFunction.h
+++ b/Libraries/LibJS/Runtime/ScriptFunction.h
@@ -32,7 +32,9 @@ namespace JS {
class ScriptFunction final : public Function {
public:
- ScriptFunction(const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment);
+ static ScriptFunction* create(GlobalObject&, const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment);
+
+ ScriptFunction(const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment, Object& prototype);
virtual ~ScriptFunction();
const Statement& body() const { return m_body; }
diff --git a/Libraries/LibJS/Runtime/StringConstructor.cpp b/Libraries/LibJS/Runtime/StringConstructor.cpp
index b92f0491c9..53fc50e3d1 100644
--- a/Libraries/LibJS/Runtime/StringConstructor.cpp
+++ b/Libraries/LibJS/Runtime/StringConstructor.cpp
@@ -33,7 +33,7 @@
namespace JS {
StringConstructor::StringConstructor()
- : NativeFunction("String")
+ : NativeFunction("String", *interpreter().function_prototype())
{
put("prototype", interpreter().string_prototype());
put("length", Value(1));