diff --git a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp index 3985d03ed4..204bd37853 100644 --- a/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/AggregateErrorConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(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; } diff --git a/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp b/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp index eb89763c3c..3fb98b235f 100644 --- a/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/BooleanConstructor.cpp @@ -4,10 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include #include #include -#include #include 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(global_object, new_target, &GlobalObject::boolean_prototype, b); } } diff --git a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp index 05667876a9..ff21e9675c 100644 --- a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(buffer.as_object())) { - vm.throw_exception(global_object(), ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer); + vm.throw_exception(global_object, ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer); return {}; } auto& array_buffer = static_cast(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(global_object(), ErrorType::DetachedArrayBuffer); + vm.throw_exception(global_object, ErrorType::DetachedArrayBuffer); return {}; } auto buffer_byte_length = array_buffer.byte_length(); if (offset > buffer_byte_length) { - vm.throw_exception(global_object(), ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length); + vm.throw_exception(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(global_object(), ErrorType::InvalidLength, vm.names.DataView); + vm.throw_exception(global_object, ErrorType::InvalidLength, vm.names.DataView); return {}; } } - // FIXME: Use OrdinaryCreateFromConstructor(newTarget, "%DataView.prototype%") + auto* data_view = ordinary_create_from_constructor(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(global_object(), ErrorType::DetachedArrayBuffer); + vm.throw_exception(global_object, ErrorType::DetachedArrayBuffer); return {}; } - return DataView::create(global_object(), &array_buffer, view_byte_length, offset); + return data_view; } } diff --git a/Userland/Libraries/LibJS/Runtime/Date.cpp b/Userland/Libraries/LibJS/Runtime/Date.cpp index b56b8b7c8d..3bb5d09da9 100644 --- a/Userland/Libraries/LibJS/Runtime/Date.cpp +++ b/Userland/Libraries/LibJS/Runtime/Date.cpp @@ -19,15 +19,6 @@ Date* Date::create(GlobalObject& global_object, Core::DateTime datetime, i16 mil return global_object.heap().allocate(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(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) diff --git a/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp b/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp index ba4f701aa5..b811978225 100644 --- a/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/DateConstructor.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -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(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(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(0); - return Date::create(global_object(), datetime, milliseconds, true); + return ordinary_create_from_constructor(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(value_as_double / 1000)); auto milliseconds = static_cast(fmod(value_as_double, 1000)); - return Date::create(global_object(), datetime, milliseconds); + return ordinary_create_from_constructor(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(global_object, new_target, &GlobalObject::date_prototype, datetime, milliseconds, false); } // 21.4.3.1 Date.now ( ), https://tc39.es/ecma262/#sec-date.now diff --git a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp index 156e0b09f4..27014c74d5 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ErrorConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(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( \ + 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); \ diff --git a/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp b/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp index 2f89ce0d77..72b15afbce 100644 --- a/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/FinalizationRegistryConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(global_object(), ErrorType::NotAFunction, cleanup_callback.to_string_without_side_effects()); + vm.throw_exception(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(global_object, new_target, &GlobalObject::finalization_registry_prototype, cleanup_callback.as_function()); } } diff --git a/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp index dfb4fffdbb..efc3a6e3d0 100644 --- a/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/MapConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(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(global_object(), ErrorType::NotAFunction, "'set' property of Map"); + vm.throw_exception(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(global_object(), ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects())); + vm.throw_exception(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()); diff --git a/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp b/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp index 618777388f..97f79a1242 100644 --- a/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/NumberConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(global_object, new_target, &GlobalObject::number_prototype, number.as_double()); } // 21.1.2.2 Number.isFinite ( number ), https://tc39.es/ecma262/#sec-number.isfinite diff --git a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp index c4b917af0e..5af4c7250a 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -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(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) { diff --git a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp index 2fee8bb656..e71d37135e 100644 --- a/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromiseConstructor.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -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(global_object(), ErrorType::PromiseExecutorNotAFunction); + vm.throw_exception(global_object, ErrorType::PromiseExecutorNotAFunction); return {}; } - auto* promise = Promise::create(global_object()); + + auto* promise = ordinary_create_from_constructor(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); diff --git a/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp b/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp index 1740d5d62b..0f85ca53e4 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpConstructor.cpp @@ -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); } diff --git a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp index f4ec3c6f27..fa53125d86 100644 --- a/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/SetConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(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(global_object(), ErrorType::NotAFunction, "'add' property of Set"); + vm.throw_exception(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); diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp index 40c272c962..b51761d0ec 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakMapConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(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(global_object(), ErrorType::NotAFunction, "'set' property of WeakMap"); + vm.throw_exception(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(global_object(), ErrorType::NotAnObject, String::formatted("Iterator value {}", iterator_value.to_string_without_side_effects())); + vm.throw_exception(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()); diff --git a/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp index 7cab7cfd10..37e4b95988 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakRefConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(global_object(), ErrorType::NotAnObject, target.to_string_without_side_effects()); + vm.throw_exception(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(global_object, new_target, &GlobalObject::weak_ref_prototype, &target.as_object()); } } diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp index d07b514440..9509e63082 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakSetConstructor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -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(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(global_object(), ErrorType::NotAFunction, "'add' property of WeakSet"); + vm.throw_exception(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);