diff options
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)); |