mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:07:45 +00:00
LibJS: Use OrdinaryCreateFromConstructor() in a bunch of constructors
Resolves various FIXMEs :^)
This commit is contained in:
parent
e5753443ae
commit
8f6ac0db1c
16 changed files with 173 additions and 102 deletions
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/AggregateError.h>
|
#include <LibJS/Runtime/AggregateError.h>
|
||||||
#include <LibJS/Runtime/AggregateErrorConstructor.h>
|
#include <LibJS/Runtime/AggregateErrorConstructor.h>
|
||||||
#include <LibJS/Runtime/Array.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
|
// 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();
|
auto& vm = this->vm();
|
||||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%")
|
auto& global_object = this->global_object();
|
||||||
auto* aggregate_error = AggregateError::create(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;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
|
|
||||||
if (!vm.argument(1).is_undefined()) {
|
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())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
aggregate_error->define_property(vm.names.message, js_string(vm, message), attr);
|
aggregate_error->define_property(vm.names.message, js_string(vm, message), attr);
|
||||||
|
@ -55,11 +59,11 @@ Value AggregateErrorConstructor::construct(Function&)
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
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())
|
if (vm.exception())
|
||||||
return {};
|
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;
|
return aggregate_error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,9 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibJS/Heap/Heap.h>
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/BooleanConstructor.h>
|
#include <LibJS/Runtime/BooleanConstructor.h>
|
||||||
#include <LibJS/Runtime/BooleanObject.h>
|
#include <LibJS/Runtime/BooleanObject.h>
|
||||||
#include <LibJS/Runtime/BooleanPrototype.h>
|
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
@ -35,13 +34,20 @@ BooleanConstructor::~BooleanConstructor()
|
||||||
// 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
|
// 20.3.1.1 Boolean ( value ), https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
|
||||||
Value BooleanConstructor::call()
|
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
|
// 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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/DataView.h>
|
#include <LibJS/Runtime/DataView.h>
|
||||||
#include <LibJS/Runtime/DataViewConstructor.h>
|
#include <LibJS/Runtime/DataViewConstructor.h>
|
||||||
#include <LibJS/Runtime/Error.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
|
// 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& vm = this->vm();
|
||||||
|
auto& global_object = this->global_object();
|
||||||
|
|
||||||
auto buffer = vm.argument(0);
|
auto buffer = vm.argument(0);
|
||||||
if (!buffer.is_object() || !is<ArrayBuffer>(buffer.as_object())) {
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
auto& array_buffer = static_cast<ArrayBuffer&>(buffer.as_object());
|
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())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (array_buffer.is_detached()) {
|
if (array_buffer.is_detached()) {
|
||||||
vm.throw_exception<TypeError>(global_object(), ErrorType::DetachedArrayBuffer);
|
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buffer_byte_length = array_buffer.byte_length();
|
auto buffer_byte_length = array_buffer.byte_length();
|
||||||
if (offset > 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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,22 +72,25 @@ Value DataViewConstructor::construct(Function&)
|
||||||
if (vm.argument(2).is_undefined()) {
|
if (vm.argument(2).is_undefined()) {
|
||||||
view_byte_length = buffer_byte_length - offset;
|
view_byte_length = buffer_byte_length - offset;
|
||||||
} else {
|
} else {
|
||||||
view_byte_length = vm.argument(2).to_index(global_object());
|
view_byte_length = vm.argument(2).to_index(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (offset + view_byte_length > buffer_byte_length) {
|
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 {};
|
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()) {
|
if (array_buffer.is_detached()) {
|
||||||
vm.throw_exception<TypeError>(global_object(), ErrorType::DetachedArrayBuffer);
|
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||||
return {};
|
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());
|
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)
|
Date::Date(Core::DateTime datetime, i16 milliseconds, bool is_invalid, Object& prototype)
|
||||||
: Object(prototype)
|
: Object(prototype)
|
||||||
, m_datetime(datetime)
|
, m_datetime(datetime)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <AK/CharacterTypes.h>
|
#include <AK/CharacterTypes.h>
|
||||||
#include <AK/GenericLexer.h>
|
#include <AK/GenericLexer.h>
|
||||||
#include <LibCore/DateTime.h>
|
#include <LibCore/DateTime.h>
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Date.h>
|
#include <LibJS/Runtime/Date.h>
|
||||||
#include <LibJS/Runtime/DateConstructor.h>
|
#include <LibJS/Runtime/DateConstructor.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
@ -144,23 +145,43 @@ DateConstructor::~DateConstructor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// 21.4.2.1 Date ( ...values ), https://tc39.es/ecma262/#sec-date
|
struct DatetimeAndMilliseconds {
|
||||||
Value DateConstructor::call()
|
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
|
// 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();
|
auto& vm = this->vm();
|
||||||
if (vm.argument_count() == 0)
|
auto& global_object = this->global_object();
|
||||||
return Date::now(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 datetime = Core::DateTime::create(1970, 1, 1, 0, 0, 0);
|
||||||
auto milliseconds = static_cast<i16>(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) {
|
if (vm.argument_count() == 1) {
|
||||||
|
@ -168,7 +189,7 @@ Value DateConstructor::construct(Function&)
|
||||||
if (value.is_string())
|
if (value.is_string())
|
||||||
value = parse_simplified_iso8601(value.as_string().string());
|
value = parse_simplified_iso8601(value.as_string().string());
|
||||||
else
|
else
|
||||||
value = value.to_number(global_object());
|
value = value.to_number(global_object);
|
||||||
|
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
|
@ -183,13 +204,15 @@ Value DateConstructor::construct(Function&)
|
||||||
return create_invalid_date();
|
return create_invalid_date();
|
||||||
auto datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000));
|
auto datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000));
|
||||||
auto milliseconds = static_cast<i16>(fmod(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.
|
// 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())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (!year_value.is_finite_number()) {
|
if (!year_value.is_finite_number()) {
|
||||||
|
@ -197,7 +220,7 @@ Value DateConstructor::construct(Function&)
|
||||||
}
|
}
|
||||||
auto year = year_value.as_i32();
|
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())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (!month_index_value.is_finite_number()) {
|
if (!month_index_value.is_finite_number()) {
|
||||||
|
@ -256,10 +279,10 @@ Value DateConstructor::construct(Function&)
|
||||||
year += 1900;
|
year += 1900;
|
||||||
int month = month_index + 1;
|
int month = month_index + 1;
|
||||||
auto datetime = Core::DateTime::create(year, month, day, hours, minutes, seconds);
|
auto datetime = Core::DateTime::create(year, month, day, hours, minutes, seconds);
|
||||||
auto* date = Date::create(global_object(), datetime, milliseconds);
|
auto time = datetime.timestamp() * 1000.0 + milliseconds;
|
||||||
if (date->time() > Date::time_clip)
|
if (time > Date::time_clip)
|
||||||
return create_invalid_date();
|
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
|
// 21.4.3.1 Date.now ( ), https://tc39.es/ecma262/#sec-date.now
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/ErrorConstructor.h>
|
#include <LibJS/Runtime/ErrorConstructor.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.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
|
// 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();
|
auto& vm = this->vm();
|
||||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%Error.prototype%")
|
auto& global_object = this->global_object();
|
||||||
auto* error = Error::create(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;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
|
|
||||||
if (!vm.argument(0).is_undefined()) {
|
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())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
error->define_property(vm.names.message, js_string(vm, message), attr);
|
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 */ \
|
/* 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(); \
|
auto& vm = this->vm(); \
|
||||||
/* FIXME: Use OrdinaryCreateFromConstructor( \
|
auto& global_object = this->global_object(); \
|
||||||
* FIXME: newTarget, "%NativeError.prototype%"). */ \
|
\
|
||||||
auto* error = ClassName::create(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; \
|
u8 attr = Attribute::Writable | Attribute::Configurable; \
|
||||||
\
|
\
|
||||||
if (!vm.argument(0).is_undefined()) { \
|
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()) \
|
if (vm.exception()) \
|
||||||
return {}; \
|
return {}; \
|
||||||
error->define_property(vm.names.message, js_string(vm, message), attr); \
|
error->define_property(vm.names.message, js_string(vm, message), attr); \
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/FinalizationRegistry.h>
|
#include <LibJS/Runtime/FinalizationRegistry.h>
|
||||||
#include <LibJS/Runtime/FinalizationRegistryConstructor.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
|
// 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& vm = this->vm();
|
||||||
|
auto& global_object = this->global_object();
|
||||||
|
|
||||||
auto cleanup_callback = vm.argument(0);
|
auto cleanup_callback = vm.argument(0);
|
||||||
if (!cleanup_callback.is_function()) {
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
return ordinary_create_from_constructor<FinalizationRegistry>(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function());
|
||||||
// FIXME: Use OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%")
|
|
||||||
return FinalizationRegistry::create(global_object(), cleanup_callback.as_function());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/IteratorOperations.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
|
// 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& 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())
|
if (vm.argument(0).is_nullish())
|
||||||
return map;
|
return map;
|
||||||
|
|
||||||
|
@ -56,14 +60,14 @@ Value MapConstructor::construct(Function&)
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (!adder.is_function()) {
|
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 {};
|
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())
|
if (vm.exception())
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
if (!iterator_value.is_object()) {
|
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;
|
return IterationDecision::Break;
|
||||||
}
|
}
|
||||||
auto key = iterator_value.as_object().get(0).value_or(js_undefined());
|
auto key = iterator_value.as_object().get(0).value_or(js_undefined());
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/NumberConstructor.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
|
// 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& vm = this->vm();
|
||||||
auto& global_object = this->global_object();
|
auto& global_object = this->global_object();
|
||||||
|
@ -102,8 +103,7 @@ Value NumberConstructor::construct(Function&)
|
||||||
auto number = get_value_from_constructor_argument(global_object);
|
auto number = get_value_from_constructor_argument(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
// FIXME: Use OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%")
|
return ordinary_create_from_constructor<NumberObject>(global_object, new_target, &GlobalObject::number_prototype, number.as_double());
|
||||||
return NumberObject::create(global_object, number.as_double());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 21.1.2.2 Number.isFinite ( number ), https://tc39.es/ecma262/#sec-number.isfinite
|
// 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
|
// 20.1.1.1 Object ( [ value ] ), https://tc39.es/ecma262/#sec-object-value
|
||||||
Value ObjectConstructor::call()
|
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& vm = this->vm();
|
||||||
auto& global_object = this->global_object();
|
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);
|
auto value = vm.argument(0);
|
||||||
if (value.is_nullish())
|
if (value.is_nullish())
|
||||||
return Object::create(global_object, global_object.object_prototype());
|
return Object::create(global_object, global_object.object_prototype());
|
||||||
return value.to_object(global_object);
|
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
|
// 20.1.2.10 Object.getOwnPropertyNames ( O ), https://tc39.es/ecma262/#sec-object.getownpropertynames
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
|
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibJS/Interpreter.h>
|
#include <LibJS/Interpreter.h>
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/Function.h>
|
#include <LibJS/Runtime/Function.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.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
|
// 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& vm = this->vm();
|
||||||
|
auto& global_object = this->global_object();
|
||||||
|
|
||||||
auto executor = vm.argument(0);
|
auto executor = vm.argument(0);
|
||||||
if (!executor.is_function()) {
|
if (!executor.is_function()) {
|
||||||
vm.throw_exception<TypeError>(global_object(), ErrorType::PromiseExecutorNotAFunction);
|
vm.throw_exception<TypeError>(global_object, ErrorType::PromiseExecutorNotAFunction);
|
||||||
return {};
|
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 [resolve_function, reject_function] = promise->create_resolving_functions();
|
||||||
|
|
||||||
auto completion_value = vm.call(executor.as_function(), js_undefined(), &resolve_function, &reject_function);
|
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())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
// FIXME: Use RegExpAlloc (which uses OrdinaryCreateFromConstructor)
|
||||||
return RegExpObject::create(global_object(), pattern, flags);
|
return RegExpObject::create(global_object(), pattern, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/IteratorOperations.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
|
// 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();
|
auto& vm = this->vm();
|
||||||
if (vm.argument(0).is_nullish())
|
auto& global_object = this->global_object();
|
||||||
return Set::create(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);
|
auto adder = set->get(vm.names.add);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (!adder.is_function()) {
|
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 {};
|
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())
|
if (vm.exception())
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
(void)vm.call(adder.as_function(), Value(set), iterator_value);
|
(void)vm.call(adder.as_function(), Value(set), iterator_value);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/IteratorOperations.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
|
// 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();
|
auto& vm = this->vm();
|
||||||
if (vm.argument(0).is_nullish())
|
auto& global_object = this->global_object();
|
||||||
return WeakMap::create(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);
|
auto adder = weak_map->get(vm.names.set);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (!adder.is_function()) {
|
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 {};
|
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())
|
if (vm.exception())
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
if (!iterator_value.is_object()) {
|
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;
|
return IterationDecision::Break;
|
||||||
}
|
}
|
||||||
auto key = iterator_value.as_object().get(0).value_or(js_undefined());
|
auto key = iterator_value.as_object().get(0).value_or(js_undefined());
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/WeakRef.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
|
// 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& vm = this->vm();
|
||||||
|
auto& global_object = this->global_object();
|
||||||
|
|
||||||
auto target = vm.argument(0);
|
auto target = vm.argument(0);
|
||||||
if (!target.is_object()) {
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
return ordinary_create_from_constructor<WeakRef>(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object());
|
||||||
// FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%WeakRef.prototype%")
|
|
||||||
return WeakRef::create(global_object(), &target.as_object());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/IteratorOperations.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
|
// 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();
|
auto& vm = this->vm();
|
||||||
if (vm.argument(0).is_nullish())
|
auto& global_object = this->global_object();
|
||||||
return WeakSet::create(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);
|
auto adder = weak_set->get(vm.names.add);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
if (!adder.is_function()) {
|
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 {};
|
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())
|
if (vm.exception())
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
(void)vm.call(adder.as_function(), Value(weak_set), iterator_value);
|
(void)vm.call(adder.as_function(), Value(weak_set), iterator_value);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue