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:
parent
39855fe9ef
commit
f07f8d5a44
8 changed files with 98 additions and 10 deletions
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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!";
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
28
Libraries/LibJS/Tests/Object.prototype.constructor.js
Normal file
28
Libraries/LibJS/Tests/Object.prototype.constructor.js
Normal 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);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue