mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:28:12 +00:00
LibJS: Pass prototype to Function constructors
This commit is contained in:
parent
205ac0090d
commit
f6d57c82f6
21 changed files with 66 additions and 24 deletions
|
@ -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
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
namespace JS {
|
||||
|
||||
ArrayConstructor::ArrayConstructor()
|
||||
: NativeFunction("Array")
|
||||
: NativeFunction("Array", *interpreter().function_prototype())
|
||||
{
|
||||
put("prototype", interpreter().array_prototype());
|
||||
put("length", Value(1));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
namespace JS {
|
||||
|
||||
DateConstructor::DateConstructor()
|
||||
: NativeFunction("Date")
|
||||
: NativeFunction("Date", *interpreter().function_prototype())
|
||||
{
|
||||
put("prototype", interpreter().date_prototype());
|
||||
put("length", Value(7));
|
||||
|
|
|
@ -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)); \
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
|
||||
namespace JS {
|
||||
|
||||
Function::Function()
|
||||
Function::Function(Object& prototype)
|
||||
{
|
||||
set_prototype(interpreter().function_prototype());
|
||||
set_prototype(&prototype);
|
||||
}
|
||||
|
||||
Function::~Function()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
namespace JS {
|
||||
|
||||
FunctionConstructor::FunctionConstructor()
|
||||
: NativeFunction("Function")
|
||||
: NativeFunction("Function", *interpreter().function_prototype())
|
||||
{
|
||||
put("prototype", interpreter().function_prototype());
|
||||
put("length", Value(1));
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
namespace JS {
|
||||
|
||||
FunctionPrototype::FunctionPrototype()
|
||||
{
|
||||
}
|
||||
|
||||
void FunctionPrototype::initialize()
|
||||
{
|
||||
put_native_function("apply", apply, 2);
|
||||
put_native_function("bind", bind, 1);
|
||||
|
|
|
@ -33,6 +33,8 @@ namespace JS {
|
|||
class FunctionPrototype final : public Object {
|
||||
public:
|
||||
FunctionPrototype();
|
||||
void initialize();
|
||||
|
||||
virtual ~FunctionPrototype() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
namespace JS {
|
||||
|
||||
NumberConstructor::NumberConstructor()
|
||||
: NativeFunction("Number")
|
||||
: NativeFunction("Number", *interpreter().function_prototype())
|
||||
{
|
||||
put_native_function("isSafeInteger", is_safe_integer, 1);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
namespace JS {
|
||||
|
||||
ObjectConstructor::ObjectConstructor()
|
||||
: NativeFunction("Object")
|
||||
: NativeFunction("Object", *interpreter().function_prototype())
|
||||
{
|
||||
put("prototype", interpreter().object_prototype());
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -33,6 +33,8 @@ namespace JS {
|
|||
class ObjectPrototype final : public Object {
|
||||
public:
|
||||
ObjectPrototype();
|
||||
void initialize();
|
||||
|
||||
virtual ~ObjectPrototype() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
namespace JS {
|
||||
|
||||
StringConstructor::StringConstructor()
|
||||
: NativeFunction("String")
|
||||
: NativeFunction("String", *interpreter().function_prototype())
|
||||
{
|
||||
put("prototype", interpreter().string_prototype());
|
||||
put("length", Value(1));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue