mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +00:00
LibJS: Use OrdinaryCreateFromConstructor() in a bunch of constructors
Resolves various FIXMEs :^)
This commit is contained in:
parent
e5753443ae
commit
8f6ac0db1c
Notes:
sideshowbarker
2024-07-18 11:59:23 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/8f6ac0db1cc Pull-request: https://github.com/SerenityOS/serenity/pull/8161 Reviewed-by: https://github.com/mattco98
16 changed files with 173 additions and 102 deletions
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/AggregateError.h>
|
||||
#include <LibJS/Runtime/AggregateErrorConstructor.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
|
@ -36,16 +37,19 @@ Value AggregateErrorConstructor::call()
|
|||
}
|
||||
|
||||
// 20.5.7.1.1 AggregateError ( errors, message ), https://tc39.es/ecma262/#sec-aggregate-error
|
||||
Value AggregateErrorConstructor::construct(Function&)
|
||||
Value AggregateErrorConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%")
|
||||
auto* aggregate_error = AggregateError::create(global_object());
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* aggregate_error = ordinary_create_from_constructor<AggregateError>(global_object, new_target, &GlobalObject::aggregate_error_prototype);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
|
||||
if (!vm.argument(1).is_undefined()) {
|
||||
auto message = vm.argument(1).to_string(global_object());
|
||||
auto message = vm.argument(1).to_string(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
aggregate_error->define_property(vm.names.message, js_string(vm, message), attr);
|
||||
|
@ -55,11 +59,11 @@ Value AggregateErrorConstructor::construct(Function&)
|
|||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
auto errors_list = iterable_to_list(global_object(), vm.argument(0));
|
||||
auto errors_list = iterable_to_list(global_object, vm.argument(0));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
aggregate_error->define_property(vm.names.errors, Array::create_from(global_object(), errors_list), attr);
|
||||
aggregate_error->define_property(vm.names.errors, Array::create_from(global_object, errors_list), attr);
|
||||
|
||||
return aggregate_error;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/BooleanConstructor.h>
|
||||
#include <LibJS/Runtime/BooleanObject.h>
|
||||
#include <LibJS/Runtime/BooleanPrototype.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
||||
namespace JS {
|
||||
|
@ -35,13 +34,20 @@ BooleanConstructor::~BooleanConstructor()
|
|||
// 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
|
||||
Value BooleanConstructor::call()
|
||||
{
|
||||
return Value(vm().argument(0).to_boolean());
|
||||
auto& vm = this->vm();
|
||||
|
||||
auto b = vm.argument(0).to_boolean();
|
||||
return Value(b);
|
||||
}
|
||||
|
||||
// 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
|
||||
Value BooleanConstructor::construct(Function&)
|
||||
Value BooleanConstructor::construct(Function& new_target)
|
||||
{
|
||||
return BooleanObject::create(global_object(), vm().argument(0).to_boolean());
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto b = vm.argument(0).to_boolean();
|
||||
return ordinary_create_from_constructor<BooleanObject>(global_object, new_target, &GlobalObject::boolean_prototype, b);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/DataView.h>
|
||||
#include <LibJS/Runtime/DataViewConstructor.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
|
@ -40,28 +41,30 @@ Value DataViewConstructor::call()
|
|||
}
|
||||
|
||||
// 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength
|
||||
Value DataViewConstructor::construct(Function&)
|
||||
Value DataViewConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto buffer = vm.argument(0);
|
||||
if (!buffer.is_object() || !is<ArrayBuffer>(buffer.as_object())) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer);
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
auto& array_buffer = static_cast<ArrayBuffer&>(buffer.as_object());
|
||||
|
||||
auto offset = vm.argument(1).to_index(global_object());
|
||||
auto offset = vm.argument(1).to_index(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
if (array_buffer.is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::DetachedArrayBuffer);
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buffer_byte_length = array_buffer.byte_length();
|
||||
if (offset > buffer_byte_length) {
|
||||
vm.throw_exception<RangeError>(global_object(), ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length);
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -69,22 +72,25 @@ Value DataViewConstructor::construct(Function&)
|
|||
if (vm.argument(2).is_undefined()) {
|
||||
view_byte_length = buffer_byte_length - offset;
|
||||
} else {
|
||||
view_byte_length = vm.argument(2).to_index(global_object());
|
||||
view_byte_length = vm.argument(2).to_index(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (offset + view_byte_length > buffer_byte_length) {
|
||||
vm.throw_exception<RangeError>(global_object(), ErrorType::InvalidLength, vm.names.DataView);
|
||||
vm.throw_exception<RangeError>(global_object, ErrorType::InvalidLength, vm.names.DataView);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%DataView.prototype%")
|
||||
auto* data_view = ordinary_create_from_constructor<DataView>(global_object, new_target, &GlobalObject::data_view_prototype, &array_buffer, view_byte_length, offset);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
if (array_buffer.is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::DetachedArrayBuffer);
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
|
||||
return DataView::create(global_object(), &array_buffer, view_byte_length, offset);
|
||||
return data_view;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,15 +19,6 @@ Date* Date::create(GlobalObject& global_object, Core::DateTime datetime, i16 mil
|
|||
return global_object.heap().allocate<Date>(global_object, datetime, milliseconds, is_invalid, *global_object.date_prototype());
|
||||
}
|
||||
|
||||
Date* Date::now(GlobalObject& global_object)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
auto datetime = Core::DateTime::now();
|
||||
auto milliseconds = static_cast<i16>(tv.tv_usec / 1000);
|
||||
return create(global_object, datetime, milliseconds);
|
||||
}
|
||||
|
||||
Date::Date(Core::DateTime datetime, i16 milliseconds, bool is_invalid, Object& prototype)
|
||||
: Object(prototype)
|
||||
, m_datetime(datetime)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <AK/CharacterTypes.h>
|
||||
#include <AK/GenericLexer.h>
|
||||
#include <LibCore/DateTime.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Date.h>
|
||||
#include <LibJS/Runtime/DateConstructor.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
@ -144,23 +145,43 @@ DateConstructor::~DateConstructor()
|
|||
{
|
||||
}
|
||||
|
||||
// 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date
|
||||
Value DateConstructor::call()
|
||||
struct DatetimeAndMilliseconds {
|
||||
Core::DateTime datetime;
|
||||
i16 milliseconds { 0 };
|
||||
};
|
||||
|
||||
static DatetimeAndMilliseconds now()
|
||||
{
|
||||
return js_string(heap(), Date::now(global_object())->string());
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
auto datetime = Core::DateTime::now();
|
||||
auto milliseconds = static_cast<i16>(tv.tv_usec / 1000);
|
||||
return { datetime, milliseconds };
|
||||
}
|
||||
|
||||
// 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date
|
||||
Value DateConstructor::construct(Function&)
|
||||
Value DateConstructor::call()
|
||||
{
|
||||
auto [datetime, milliseconds] = JS::now();
|
||||
auto* date = Date::create(global_object(), datetime, milliseconds);
|
||||
return js_string(heap(), date->string());
|
||||
}
|
||||
|
||||
// 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date
|
||||
Value DateConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (vm.argument_count() == 0)
|
||||
return Date::now(global_object());
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto create_invalid_date = [this]() {
|
||||
if (vm.argument_count() == 0) {
|
||||
auto [datetime, milliseconds] = JS::now();
|
||||
return ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false);
|
||||
}
|
||||
|
||||
auto create_invalid_date = [&global_object, &new_target]() {
|
||||
auto datetime = Core::DateTime::create(1970, 1, 1, 0, 0, 0);
|
||||
auto milliseconds = static_cast<i16>(0);
|
||||
return Date::create(global_object(), datetime, milliseconds, true);
|
||||
return ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, true);
|
||||
};
|
||||
|
||||
if (vm.argument_count() == 1) {
|
||||
|
@ -168,7 +189,7 @@ Value DateConstructor::construct(Function&)
|
|||
if (value.is_string())
|
||||
value = parse_simplified_iso8601(value.as_string().string());
|
||||
else
|
||||
value = value.to_number(global_object());
|
||||
value = value.to_number(global_object);
|
||||
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
@ -183,13 +204,15 @@ Value DateConstructor::construct(Function&)
|
|||
return create_invalid_date();
|
||||
auto datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000));
|
||||
auto milliseconds = static_cast<i16>(fmod(value_as_double, 1000));
|
||||
return Date::create(global_object(), datetime, milliseconds);
|
||||
return ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false);
|
||||
}
|
||||
|
||||
// A date/time in components, in local time.
|
||||
auto arg_or = [&vm, this](size_t i, i32 fallback) { return vm.argument_count() > i ? vm.argument(i).to_number(global_object()) : Value(fallback); };
|
||||
auto arg_or = [&vm, &global_object](size_t i, i32 fallback) {
|
||||
return vm.argument_count() > i ? vm.argument(i).to_number(global_object) : Value(fallback);
|
||||
};
|
||||
|
||||
auto year_value = vm.argument(0).to_number(global_object());
|
||||
auto year_value = vm.argument(0).to_number(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!year_value.is_finite_number()) {
|
||||
|
@ -197,7 +220,7 @@ Value DateConstructor::construct(Function&)
|
|||
}
|
||||
auto year = year_value.as_i32();
|
||||
|
||||
auto month_index_value = vm.argument(1).to_number(global_object());
|
||||
auto month_index_value = vm.argument(1).to_number(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!month_index_value.is_finite_number()) {
|
||||
|
@ -256,10 +279,10 @@ Value DateConstructor::construct(Function&)
|
|||
year += 1900;
|
||||
int month = month_index + 1;
|
||||
auto datetime = Core::DateTime::create(year, month, day, hours, minutes, seconds);
|
||||
auto* date = Date::create(global_object(), datetime, milliseconds);
|
||||
if (date->time() > Date::time_clip)
|
||||
auto time = datetime.timestamp() * 1000.0 + milliseconds;
|
||||
if (time > Date::time_clip)
|
||||
return create_invalid_date();
|
||||
return date;
|
||||
return ordinary_create_from_constructor<Date>(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false);
|
||||
}
|
||||
|
||||
// 21.4.3.1 Date.now ( ), https://tc39.es/ecma262/#sec-date.now
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/ErrorConstructor.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
@ -33,16 +34,19 @@ Value ErrorConstructor::call()
|
|||
}
|
||||
|
||||
// 20.5.1.1 Error ( message ), https://tc39.es/ecma262/#sec-error-message
|
||||
Value ErrorConstructor::construct(Function&)
|
||||
Value ErrorConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%Error.prototype%")
|
||||
auto* error = Error::create(global_object());
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* error = ordinary_create_from_constructor<Error>(global_object, new_target, &GlobalObject::error_prototype);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
|
||||
if (!vm.argument(0).is_undefined()) {
|
||||
auto message = vm.argument(0).to_string(global_object());
|
||||
auto message = vm.argument(0).to_string(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
error->define_property(vm.names.message, js_string(vm, message), attr);
|
||||
|
@ -82,17 +86,20 @@ Value ErrorConstructor::construct(Function&)
|
|||
} \
|
||||
\
|
||||
/* 20.5.6.1.1 NativeError ( message ), https://tc39.es/ecma262/#sec-nativeerror */ \
|
||||
Value ConstructorName::construct(Function&) \
|
||||
Value ConstructorName::construct(Function& new_target) \
|
||||
{ \
|
||||
auto& vm = this->vm(); \
|
||||
/* FIXME: Use OrdinaryCreateFromConstructor( \
|
||||
* FIXME: newTarget, "%NativeError.prototype%"). */ \
|
||||
auto* error = ClassName::create(global_object()); \
|
||||
auto& global_object = this->global_object(); \
|
||||
\
|
||||
auto* error = ordinary_create_from_constructor<ClassName>( \
|
||||
global_object, new_target, &GlobalObject::snake_name##_prototype); \
|
||||
if (vm.exception()) \
|
||||
return {}; \
|
||||
\
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable; \
|
||||
\
|
||||
if (!vm.argument(0).is_undefined()) { \
|
||||
auto message = vm.argument(0).to_string(global_object()); \
|
||||
auto message = vm.argument(0).to_string(global_object); \
|
||||
if (vm.exception()) \
|
||||
return {}; \
|
||||
error->define_property(vm.names.message, js_string(vm, message), attr); \
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/FinalizationRegistry.h>
|
||||
#include <LibJS/Runtime/FinalizationRegistryConstructor.h>
|
||||
|
@ -40,17 +41,17 @@ Value FinalizationRegistryConstructor::call()
|
|||
}
|
||||
|
||||
// 26.2.1.1 FinalizationRegistry ( cleanupCallback ), https://tc39.es/ecma262/#sec-finalization-registry-cleanup-callback
|
||||
Value FinalizationRegistryConstructor::construct(Function&)
|
||||
Value FinalizationRegistryConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto cleanup_callback = vm.argument(0);
|
||||
if (!cleanup_callback.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects());
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: Use OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%")
|
||||
return FinalizationRegistry::create(global_object(), cleanup_callback.as_function());
|
||||
return ordinary_create_from_constructor<FinalizationRegistry>(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/IteratorOperations.h>
|
||||
|
@ -43,12 +44,15 @@ Value MapConstructor::call()
|
|||
}
|
||||
|
||||
// 24.1.1.1 Map ( [ iterable ] ), https://tc39.es/ecma262/#sec-map-iterable
|
||||
Value MapConstructor::construct(Function&)
|
||||
Value MapConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* map = ordinary_create_from_constructor<Map>(global_object, new_target, &GlobalObject::map_prototype);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%Map.prototype%")
|
||||
auto* map = Map::create(global_object());
|
||||
if (vm.argument(0).is_nullish())
|
||||
return map;
|
||||
|
||||
|
@ -56,14 +60,14 @@ Value MapConstructor::construct(Function&)
|
|||
if (vm.exception())
|
||||
return {};
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, "'set' property of Map");
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of Map");
|
||||
return {};
|
||||
}
|
||||
get_iterator_values(global_object(), vm.argument(0), [&](Value iterator_value) {
|
||||
get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) {
|
||||
if (vm.exception())
|
||||
return IterationDecision::Break;
|
||||
if (!iterator_value.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
auto key = iterator_value.as_object().get(0).value_or(js_undefined());
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/NumberConstructor.h>
|
||||
|
@ -94,7 +95,7 @@ Value NumberConstructor::call()
|
|||
}
|
||||
|
||||
// 21.1.1.1 Number ( value ), https://tc39.es/ecma262/#sec-number-constructor-number-value
|
||||
Value NumberConstructor::construct(Function&)
|
||||
Value NumberConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
@ -102,8 +103,7 @@ Value NumberConstructor::construct(Function&)
|
|||
auto number = get_value_from_constructor_argument(global_object);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
// FIXME: Use OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%")
|
||||
return NumberObject::create(global_object, number.as_double());
|
||||
return ordinary_create_from_constructor<NumberObject>(global_object, new_target, &GlobalObject::number_prototype, number.as_double());
|
||||
}
|
||||
|
||||
// 21.1.2.2 Number.isFinite ( number ), https://tc39.es/ecma262/#sec-number.isfinite
|
||||
|
|
|
@ -62,22 +62,24 @@ ObjectConstructor::~ObjectConstructor()
|
|||
|
||||
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||
Value ObjectConstructor::call()
|
||||
{
|
||||
return construct(*this);
|
||||
}
|
||||
|
||||
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||
Value ObjectConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
if (&new_target != this)
|
||||
return ordinary_create_from_constructor<Object>(global_object, new_target, &GlobalObject::object_prototype);
|
||||
auto value = vm.argument(0);
|
||||
if (value.is_nullish())
|
||||
return Object::create(global_object, global_object.object_prototype());
|
||||
return value.to_object(global_object);
|
||||
}
|
||||
|
||||
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||
Value ObjectConstructor::construct(Function&)
|
||||
{
|
||||
return call();
|
||||
}
|
||||
|
||||
// 20.1.2.10 Object.getOwnPropertyNames ( O ), https://tc39.es/ecma262/#sec-object.getownpropertynames
|
||||
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/Function.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
@ -50,15 +51,21 @@ Value PromiseConstructor::call()
|
|||
}
|
||||
|
||||
// 27.2.3.1 Promise ( executor ), https://tc39.es/ecma262/#sec-promise-executor
|
||||
Value PromiseConstructor::construct(Function&)
|
||||
Value PromiseConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto executor = vm.argument(0);
|
||||
if (!executor.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::PromiseExecutorNotAFunction);
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction);
|
||||
return {};
|
||||
}
|
||||
auto* promise = Promise::create(global_object());
|
||||
|
||||
auto* promise = ordinary_create_from_constructor<Promise>(global_object, new_target, &GlobalObject::promise_prototype);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
auto [resolve_function, reject_function] = promise->create_resolving_functions();
|
||||
|
||||
auto completion_value = vm.call(executor.as_function(), js_undefined(), &resolve_function, &reject_function);
|
||||
|
|
|
@ -55,6 +55,7 @@ Value RegExpConstructor::construct(Function&)
|
|||
if (vm.exception())
|
||||
return {};
|
||||
}
|
||||
// FIXME: Use RegExpAlloc (which uses OrdinaryCreateFromConstructor)
|
||||
return RegExpObject::create(global_object(), pattern, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/IteratorOperations.h>
|
||||
|
@ -43,21 +44,26 @@ Value SetConstructor::call()
|
|||
}
|
||||
|
||||
// 24.2.1.1 Set ( [ iterable ] ), https://tc39.es/ecma262/#sec-set-iterable
|
||||
Value SetConstructor::construct(Function&)
|
||||
Value SetConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (vm.argument(0).is_nullish())
|
||||
return Set::create(global_object());
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* set = ordinary_create_from_constructor<Set>(global_object, new_target, &GlobalObject::set_prototype);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
if (vm.argument(0).is_nullish())
|
||||
return set;
|
||||
|
||||
auto* set = Set::create(global_object());
|
||||
auto adder = set->get(vm.names.add);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, "'add' property of Set");
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of Set");
|
||||
return {};
|
||||
}
|
||||
get_iterator_values(global_object(), vm.argument(0), [&](Value iterator_value) {
|
||||
get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) {
|
||||
if (vm.exception())
|
||||
return IterationDecision::Break;
|
||||
(void)vm.call(adder.as_function(), Value(set), iterator_value);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/IteratorOperations.h>
|
||||
|
@ -41,25 +42,30 @@ Value WeakMapConstructor::call()
|
|||
}
|
||||
|
||||
// 24.3.1.1 WeakMap ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakmap-iterable
|
||||
Value WeakMapConstructor::construct(Function&)
|
||||
Value WeakMapConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (vm.argument(0).is_nullish())
|
||||
return WeakMap::create(global_object());
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* weak_map = ordinary_create_from_constructor<WeakMap>(global_object, new_target, &GlobalObject::weak_map_prototype);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
if (vm.argument(0).is_nullish())
|
||||
return weak_map;
|
||||
|
||||
auto* weak_map = WeakMap::create(global_object());
|
||||
auto adder = weak_map->get(vm.names.set);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, "'set' property of WeakMap");
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'set' property of WeakMap");
|
||||
return {};
|
||||
}
|
||||
get_iterator_values(global_object(), vm.argument(0), [&](Value iterator_value) {
|
||||
get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) {
|
||||
if (vm.exception())
|
||||
return IterationDecision::Break;
|
||||
if (!iterator_value.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects()));
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
auto key = iterator_value.as_object().get(0).value_or(js_undefined());
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/WeakRef.h>
|
||||
|
@ -40,17 +41,17 @@ Value WeakRefConstructor::call()
|
|||
}
|
||||
|
||||
// 26.1.1.1 WeakRef ( target ), https://tc39.es/ecma262/#sec-weak-ref-target
|
||||
Value WeakRefConstructor::construct(Function&)
|
||||
Value WeakRefConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto target = vm.argument(0);
|
||||
if (!target.is_object()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAnObject, target.to_string_without_side_effects());
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, target.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
|
||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%WeakRef.prototype%")
|
||||
return WeakRef::create(global_object(), &target.as_object());
|
||||
return ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/IteratorOperations.h>
|
||||
|
@ -41,21 +42,26 @@ Value WeakSetConstructor::call()
|
|||
}
|
||||
|
||||
// 24.4.1.1 WeakSet ( [ iterable ] ), https://tc39.es/ecma262/#sec-weakset-iterable
|
||||
Value WeakSetConstructor::construct(Function&)
|
||||
Value WeakSetConstructor::construct(Function& new_target)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (vm.argument(0).is_nullish())
|
||||
return WeakSet::create(global_object());
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto* weak_set = ordinary_create_from_constructor<WeakSet>(global_object, new_target, &GlobalObject::weak_set_prototype);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
if (vm.argument(0).is_nullish())
|
||||
return weak_set;
|
||||
|
||||
auto* weak_set = WeakSet::create(global_object());
|
||||
auto adder = weak_set->get(vm.names.add);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!adder.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, "'add' property of WeakSet");
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, "'add' property of WeakSet");
|
||||
return {};
|
||||
}
|
||||
get_iterator_values(global_object(), vm.argument(0), [&](Value iterator_value) {
|
||||
get_iterator_values(global_object, vm.argument(0), [&](Value iterator_value) {
|
||||
if (vm.exception())
|
||||
return IterationDecision::Break;
|
||||
(void)vm.call(adder.as_function(), Value(weak_set), iterator_value);
|
||||
|
|
Loading…
Reference in a new issue