1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 04:28:13 +00:00

LibJS: Add "constructor" property to constructor prototypes

This commit is contained in:
Andreas Kling 2020-04-08 11:05:38 +02:00
parent 39855fe9ef
commit f07f8d5a44
8 changed files with 98 additions and 10 deletions

View file

@ -32,6 +32,7 @@
#include <LibJS/Interpreter.h> #include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/NativeFunction.h> #include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/ScriptFunction.h> #include <LibJS/Runtime/ScriptFunction.h>

View file

@ -29,17 +29,24 @@
namespace JS { namespace JS {
class ASTNode; class ASTNode;
class ArrayConstructor;
class BooleanConstructor;
class Cell; class Cell;
class DateConstructor;
class Error; class Error;
class ErrorConstructor;
class Exception; class Exception;
class Expression; class Expression;
class Function; class Function;
class FunctionConstructor;
class GlobalObject; class GlobalObject;
class HandleImpl; class HandleImpl;
class Heap; class Heap;
class HeapBlock; class HeapBlock;
class Interpreter; class Interpreter;
class NumberConstructor;
class Object; class Object;
class ObjectConstructor;
class PrimitiveString; class PrimitiveString;
class ScopeNode; class ScopeNode;
class Shape; class Shape;

View file

@ -227,4 +227,14 @@ Value Interpreter::throw_exception(Exception* exception)
return {}; return {};
} }
GlobalObject& Interpreter::global_object()
{
return static_cast<GlobalObject&>(*m_global_object);
}
const GlobalObject& Interpreter::global_object() const
{
return static_cast<const GlobalObject&>(*m_global_object);
}
} }

View file

@ -83,8 +83,8 @@ public:
Value run(const Statement&, ArgumentVector = {}, ScopeType = ScopeType::Block); Value run(const Statement&, ArgumentVector = {}, ScopeType = ScopeType::Block);
Object& global_object() { return *m_global_object; } GlobalObject& global_object();
const Object& global_object() const { return *m_global_object; } const GlobalObject& global_object() const;
Heap& heap() { return m_heap; } Heap& heap() { return m_heap; }

View file

@ -43,6 +43,14 @@
namespace JS { namespace JS {
template<typename ConstructorType>
void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype)
{
constructor = heap().allocate<ConstructorType>();
prototype.put("constructor", constructor);
put(property_name, constructor);
}
GlobalObject::GlobalObject() GlobalObject::GlobalObject()
{ {
put_native_function("gc", gc); put_native_function("gc", gc);
@ -54,20 +62,34 @@ GlobalObject::GlobalObject()
put("undefined", js_undefined()); put("undefined", js_undefined());
put("console", heap().allocate<ConsoleObject>()); put("console", heap().allocate<ConsoleObject>());
put("Date", heap().allocate<DateConstructor>());
put("Error", heap().allocate<ErrorConstructor>());
put("Function", heap().allocate<FunctionConstructor>());
put("Math", heap().allocate<MathObject>()); put("Math", heap().allocate<MathObject>());
put("Object", heap().allocate<ObjectConstructor>());
put("Array", heap().allocate<ArrayConstructor>()); add_constructor("Array", m_array_constructor, *interpreter().array_prototype());
put("Boolean", heap().allocate<BooleanConstructor>()); add_constructor("Boolean", m_boolean_constructor, *interpreter().boolean_prototype());
put("Number", heap().allocate<NumberConstructor>()); add_constructor("Date", m_date_constructor, *interpreter().date_prototype());
add_constructor("Error", m_error_constructor, *interpreter().error_prototype());
add_constructor("Function", m_function_constructor, *interpreter().function_prototype());
add_constructor("Number", m_number_constructor, *interpreter().number_prototype());
add_constructor("Object", m_object_constructor, *interpreter().object_prototype());
} }
GlobalObject::~GlobalObject() GlobalObject::~GlobalObject()
{ {
} }
void GlobalObject::visit_children(Visitor& visitor)
{
Object::visit_children(visitor);
visitor.visit(m_array_constructor);
visitor.visit(m_boolean_constructor);
visitor.visit(m_date_constructor);
visitor.visit(m_error_constructor);
visitor.visit(m_function_constructor);
visitor.visit(m_number_constructor);
visitor.visit(m_object_constructor);
}
Value GlobalObject::gc(Interpreter& interpreter) Value GlobalObject::gc(Interpreter& interpreter)
{ {
dbg() << "Forced garbage collection requested!"; dbg() << "Forced garbage collection requested!";

View file

@ -24,7 +24,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #pragma once
#include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/Object.h>
@ -36,11 +35,31 @@ public:
explicit GlobalObject(); explicit GlobalObject();
virtual ~GlobalObject() override; virtual ~GlobalObject() override;
ArrayConstructor* array_constructor() { return m_array_constructor; }
BooleanConstructor* boolean_constructor() { return m_boolean_constructor; }
DateConstructor* date_constructor() { return m_date_constructor; }
ErrorConstructor* error_constructor() { return m_error_constructor; }
FunctionConstructor* function_constructor() { return m_function_constructor; }
NumberConstructor* number_constructor() { return m_number_constructor; };
ObjectConstructor* object_constructor() { return m_object_constructor; }
private: private:
virtual const char* class_name() const override { return "GlobalObject"; } virtual const char* class_name() const override { return "GlobalObject"; }
virtual void visit_children(Visitor&) override;
static Value gc(Interpreter&); static Value gc(Interpreter&);
static Value is_nan(Interpreter&); static Value is_nan(Interpreter&);
template<typename ConstructorType>
void add_constructor(const FlyString& property_name, ConstructorType*&, Object& prototype);
ArrayConstructor* m_array_constructor { nullptr };
BooleanConstructor* m_boolean_constructor { nullptr };
DateConstructor* m_date_constructor { nullptr };
ErrorConstructor* m_error_constructor { nullptr };
FunctionConstructor* m_function_constructor { nullptr };
NumberConstructor* m_number_constructor { nullptr };
ObjectConstructor* m_object_constructor { nullptr };
}; };
} }

View file

@ -28,6 +28,7 @@
#include <LibJS/Heap/Heap.h> #include <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h> #include <LibJS/Interpreter.h>
#include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/NativeFunction.h> #include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/NativeProperty.h> #include <LibJS/Runtime/NativeProperty.h>
#include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/Object.h>

View file

@ -0,0 +1,28 @@
try {
assert(Array.prototype.constructor === Array)
assert(Boolean.prototype.constructor === Boolean)
assert(Date.prototype.constructor === Date)
assert(Error.prototype.constructor === Error)
assert(Function.prototype.constructor === Function)
assert(Number.prototype.constructor === Number)
assert(Object.prototype.constructor === Object)
o = {}
assert(o.constructor === Object)
o = new Object
assert(o.constructor === Object)
a = []
assert(a.constructor === Array)
a = new Array
assert(a.constructor === Array)
n = new Number(3)
assert(n.constructor === Number)
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}