From f6d57c82f6dbbb5c7e18bffb43d0258956aa0d46 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 17 Apr 2020 19:59:32 +0200 Subject: LibJS: Pass prototype to Function constructors --- Libraries/LibJS/Runtime/ArrayConstructor.cpp | 2 +- Libraries/LibJS/Runtime/BooleanConstructor.cpp | 2 +- Libraries/LibJS/Runtime/DateConstructor.cpp | 2 +- Libraries/LibJS/Runtime/ErrorConstructor.cpp | 3 ++- Libraries/LibJS/Runtime/Function.cpp | 4 ++-- Libraries/LibJS/Runtime/Function.h | 2 +- Libraries/LibJS/Runtime/FunctionConstructor.cpp | 2 +- Libraries/LibJS/Runtime/FunctionPrototype.cpp | 4 ++++ Libraries/LibJS/Runtime/FunctionPrototype.h | 2 ++ Libraries/LibJS/Runtime/NativeFunction.cpp | 21 +++++++++++++++++---- Libraries/LibJS/Runtime/NativeFunction.h | 8 +++++--- Libraries/LibJS/Runtime/NumberConstructor.cpp | 2 +- Libraries/LibJS/Runtime/Object.cpp | 2 +- Libraries/LibJS/Runtime/ObjectConstructor.cpp | 2 +- Libraries/LibJS/Runtime/ObjectPrototype.cpp | 5 +++++ Libraries/LibJS/Runtime/ObjectPrototype.h | 2 ++ Libraries/LibJS/Runtime/ScriptFunction.cpp | 12 ++++++++++-- Libraries/LibJS/Runtime/ScriptFunction.h | 4 +++- Libraries/LibJS/Runtime/StringConstructor.cpp | 2 +- 19 files changed, 61 insertions(+), 22 deletions(-) (limited to 'Libraries/LibJS/Runtime') 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 @@ -36,6 +36,10 @@ namespace JS { FunctionPrototype::FunctionPrototype() +{ +} + +void FunctionPrototype::initialize() { put_native_function("apply", apply, 2); put_native_function("bind", bind, 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 +#include #include #include namespace JS { -NativeFunction::NativeFunction(const FlyString& name, AK::Function native_function) - : m_name(name) +NativeFunction* NativeFunction::create(Interpreter& interpreter, GlobalObject&, const FlyString& name, AK::Function function) +{ + return interpreter.heap().allocate(name, move(function), *interpreter.function_prototype()); +} + +NativeFunction::NativeFunction(Object& prototype) + : Function(prototype) +{ +} + +NativeFunction::NativeFunction(const FlyString& name, AK::Function 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); + static NativeFunction* create(Interpreter&, GlobalObject&, const FlyString& name, AK::Function); + + explicit NativeFunction(const FlyString& name, AK::Function, 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 native_function, i32 length) { - auto* function = heap().allocate(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 #include #include +#include #include #include namespace JS { -ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vector parameters, LexicalEnvironment* parent_environment) - : m_name(name) +ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector parameters, LexicalEnvironment* parent_environment) +{ + auto& interpreter = global_object.interpreter(); + return interpreter.heap().allocate(name, body, move(parameters), parent_environment, *interpreter.function_prototype()); +} + +ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vector 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 parameters, LexicalEnvironment* parent_environment); + static ScriptFunction* create(GlobalObject&, const FlyString& name, const Statement& body, Vector parameters, LexicalEnvironment* parent_environment); + + ScriptFunction(const FlyString& name, const Statement& body, Vector 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)); -- cgit v1.2.3