2020-04-06 11:09:01 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-04-06 11:09:01 +02:00
|
|
|
*/
|
|
|
|
|
2020-03-12 20:11:35 +01:00
|
|
|
#pragma once
|
|
|
|
|
2020-05-02 20:43:44 +02:00
|
|
|
#include <LibJS/Heap/Heap.h>
|
2021-06-21 23:17:24 +02:00
|
|
|
#include <LibJS/Runtime/EnvironmentRecord.h>
|
2020-09-27 20:18:30 +02:00
|
|
|
#include <LibJS/Runtime/VM.h>
|
2020-03-12 20:11:35 +01:00
|
|
|
|
|
|
|
namespace JS {
|
|
|
|
|
2021-06-22 17:16:08 +02:00
|
|
|
class GlobalObject : public Object {
|
|
|
|
JS_OBJECT(GlobalObject, Object);
|
2020-06-21 15:14:02 +02:00
|
|
|
|
2020-03-12 20:11:35 +01:00
|
|
|
public:
|
2020-03-13 11:06:32 +01:00
|
|
|
explicit GlobalObject();
|
2021-03-17 16:52:26 +01:00
|
|
|
virtual void initialize_global_object();
|
2020-04-18 13:18:06 +02:00
|
|
|
|
2020-03-12 20:11:35 +01:00
|
|
|
virtual ~GlobalObject() override;
|
|
|
|
|
2021-06-22 17:16:08 +02:00
|
|
|
GlobalEnvironmentRecord& environment_record() { return *m_environment_record; }
|
2020-11-28 16:02:27 +01:00
|
|
|
|
2020-09-29 21:15:06 +02:00
|
|
|
Console& console() { return *m_console; }
|
|
|
|
|
2020-04-18 13:56:13 +02:00
|
|
|
Shape* empty_object_shape() { return m_empty_object_shape; }
|
|
|
|
|
2020-10-17 23:13:37 +02:00
|
|
|
Shape* new_object_shape() { return m_new_object_shape; }
|
|
|
|
Shape* new_script_function_prototype_object_shape() { return m_new_script_function_prototype_object_shape; }
|
|
|
|
|
2020-11-30 22:50:43 +00:00
|
|
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
|
|
|
|
ProxyConstructor* proxy_constructor() { return m_proxy_constructor; }
|
|
|
|
|
2021-06-15 00:04:08 -07:00
|
|
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor
|
|
|
|
GeneratorObjectPrototype* generator_object_prototype() { return m_generator_object_prototype; }
|
|
|
|
|
2021-06-19 20:13:53 -07:00
|
|
|
Function* eval_function() const { return m_eval_function; }
|
|
|
|
|
2020-12-01 21:05:25 +01:00
|
|
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
2020-04-18 13:18:06 +02:00
|
|
|
ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; } \
|
|
|
|
Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
|
2020-04-10 14:06:52 +02:00
|
|
|
JS_ENUMERATE_BUILTIN_TYPES
|
|
|
|
#undef __JS_ENUMERATE
|
2020-04-08 11:05:38 +02:00
|
|
|
|
2020-07-09 14:58:20 -07:00
|
|
|
#define __JS_ENUMERATE(ClassName, snake_name) \
|
|
|
|
Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
|
|
|
|
JS_ENUMERATE_ITERATOR_PROTOTYPES
|
|
|
|
#undef __JS_ENUMERATE
|
|
|
|
|
2020-04-08 21:11:51 +02:00
|
|
|
protected:
|
2020-11-28 14:33:36 +01:00
|
|
|
virtual void visit_edges(Visitor&) override;
|
2020-04-08 21:11:51 +02:00
|
|
|
|
2020-12-02 00:23:40 +00:00
|
|
|
template<typename ConstructorType>
|
2021-06-13 18:59:07 +02:00
|
|
|
void initialize_constructor(PropertyName const&, ConstructorType*&, Object* prototype);
|
2020-05-02 19:18:55 +01:00
|
|
|
template<typename ConstructorType>
|
2021-06-13 18:59:07 +02:00
|
|
|
void add_constructor(PropertyName const&, ConstructorType*&, Object* prototype);
|
2020-05-02 19:18:55 +01:00
|
|
|
|
2020-03-12 20:11:35 +01:00
|
|
|
private:
|
2021-03-19 11:28:44 +01:00
|
|
|
virtual bool is_global_object() const final { return true; }
|
|
|
|
|
2020-06-20 13:55:34 +02:00
|
|
|
JS_DECLARE_NATIVE_FUNCTION(gc);
|
|
|
|
JS_DECLARE_NATIVE_FUNCTION(is_nan);
|
|
|
|
JS_DECLARE_NATIVE_FUNCTION(is_finite);
|
|
|
|
JS_DECLARE_NATIVE_FUNCTION(parse_float);
|
2020-12-05 13:51:09 +01:00
|
|
|
JS_DECLARE_NATIVE_FUNCTION(parse_int);
|
2021-03-14 16:20:01 +01:00
|
|
|
JS_DECLARE_NATIVE_FUNCTION(eval);
|
2021-04-13 22:50:29 +03:00
|
|
|
JS_DECLARE_NATIVE_FUNCTION(encode_uri);
|
|
|
|
JS_DECLARE_NATIVE_FUNCTION(decode_uri);
|
|
|
|
JS_DECLARE_NATIVE_FUNCTION(encode_uri_component);
|
|
|
|
JS_DECLARE_NATIVE_FUNCTION(decode_uri_component);
|
2021-06-05 19:21:15 +03:00
|
|
|
JS_DECLARE_NATIVE_FUNCTION(escape);
|
|
|
|
JS_DECLARE_NATIVE_FUNCTION(unescape);
|
2020-04-08 11:05:38 +02:00
|
|
|
|
2020-09-29 21:15:06 +02:00
|
|
|
NonnullOwnPtr<Console> m_console;
|
|
|
|
|
2020-04-18 13:56:13 +02:00
|
|
|
Shape* m_empty_object_shape { nullptr };
|
2020-10-17 23:13:37 +02:00
|
|
|
Shape* m_new_object_shape { nullptr };
|
|
|
|
Shape* m_new_script_function_prototype_object_shape { nullptr };
|
2020-04-18 13:56:13 +02:00
|
|
|
|
2020-11-30 22:50:43 +00:00
|
|
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
|
|
|
|
ProxyConstructor* m_proxy_constructor { nullptr };
|
|
|
|
|
2021-06-15 00:04:08 -07:00
|
|
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor
|
|
|
|
GeneratorObjectPrototype* m_generator_object_prototype { nullptr };
|
|
|
|
|
2021-06-22 17:16:08 +02:00
|
|
|
GlobalEnvironmentRecord* m_environment_record { nullptr };
|
|
|
|
|
2020-12-01 21:05:25 +01:00
|
|
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
|
|
|
ConstructorName* m_##snake_name##_constructor { nullptr }; \
|
2020-04-18 13:18:06 +02:00
|
|
|
Object* m_##snake_name##_prototype { nullptr };
|
2020-04-10 14:06:52 +02:00
|
|
|
JS_ENUMERATE_BUILTIN_TYPES
|
|
|
|
#undef __JS_ENUMERATE
|
2020-07-09 14:58:20 -07:00
|
|
|
|
|
|
|
#define __JS_ENUMERATE(ClassName, snake_name) \
|
|
|
|
Object* m_##snake_name##_prototype { nullptr };
|
|
|
|
JS_ENUMERATE_ITERATOR_PROTOTYPES
|
|
|
|
#undef __JS_ENUMERATE
|
2021-06-19 20:13:53 -07:00
|
|
|
|
|
|
|
Function* m_eval_function;
|
2020-03-12 20:11:35 +01:00
|
|
|
};
|
|
|
|
|
2020-05-02 20:43:44 +02:00
|
|
|
template<typename ConstructorType>
|
2021-06-13 18:59:07 +02:00
|
|
|
inline void GlobalObject::initialize_constructor(PropertyName const& property_name, ConstructorType*& constructor, Object* prototype)
|
2020-05-02 20:43:44 +02:00
|
|
|
{
|
2020-10-13 23:49:19 +02:00
|
|
|
auto& vm = this->vm();
|
2020-06-20 15:40:48 +02:00
|
|
|
constructor = heap().allocate<ConstructorType>(*this, *this);
|
2021-06-13 18:59:07 +02:00
|
|
|
constructor->define_property(vm.names.name, js_string(heap(), property_name.as_string()), Attribute::Configurable);
|
2020-10-13 23:49:19 +02:00
|
|
|
if (vm.exception())
|
2020-06-07 10:53:14 -07:00
|
|
|
return;
|
2020-11-30 22:50:43 +00:00
|
|
|
if (prototype) {
|
|
|
|
prototype->define_property(vm.names.constructor, constructor, Attribute::Writable | Attribute::Configurable);
|
|
|
|
if (vm.exception())
|
|
|
|
return;
|
|
|
|
}
|
2020-12-02 00:23:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ConstructorType>
|
2021-06-13 18:59:07 +02:00
|
|
|
inline void GlobalObject::add_constructor(PropertyName const& property_name, ConstructorType*& constructor, Object* prototype)
|
2020-12-02 00:23:40 +00:00
|
|
|
{
|
2021-06-11 18:03:24 +01:00
|
|
|
// Some constructors are pre-initialized separately.
|
|
|
|
if (!constructor)
|
|
|
|
initialize_constructor(property_name, constructor, prototype);
|
LibJS: Simplify and normalize publicly-exposed Object functions
Previously, the Object class had many different types of functions for
each action. For example: get_by_index, get(PropertyName),
get(FlyString). This is a bit verbose, so these methods have been
shortened to simply use the PropertyName structure. The methods then
internally call _by_index if necessary. Note that the _by_index
have been made private to enforce this change.
Secondly, a clear distinction has been made between "putting" and
"defining" an object property. "Putting" should mean modifying a
(potentially) already existing property. This is akin to doing "a.b =
'foo'".
This implies two things about put operations:
- They will search the prototype chain for setters and call them, if
necessary.
- If no property exists with a particular key, the put operation
should create a new property with the default attributes
(configurable, writable, and enumerable).
In contrast, "defining" a property should completely overwrite any
existing value without calling setters (if that property is
configurable, of course).
Thus, all of the many JS objects have had any "put" calls changed to
"define_property" calls. Additionally, "put_native_function" and
"put_native_property" have had their "put" replaced with "define".
Finally, "put_own_property" has been made private, as all necessary
functionality should be exposed with the put and define_property
methods.
2020-05-26 21:33:37 -07:00
|
|
|
define_property(property_name, constructor, Attribute::Writable | Attribute::Configurable);
|
2020-05-02 20:43:44 +02:00
|
|
|
}
|
|
|
|
|
2021-01-05 12:02:59 +01:00
|
|
|
inline GlobalObject* Shape::global_object() const
|
|
|
|
{
|
|
|
|
return static_cast<GlobalObject*>(m_global_object);
|
|
|
|
}
|
|
|
|
|
2021-03-19 11:28:44 +01:00
|
|
|
template<>
|
|
|
|
inline bool Object::fast_is<GlobalObject>() const { return is_global_object(); }
|
|
|
|
|
2020-03-12 20:11:35 +01:00
|
|
|
}
|