mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-14 01:04:38 +03:00
LibJS: Move Object::invoke to Value::invoke and fix it for primitives
This is a tiny difference and only changes anything for primitives in strict mode. However this is tested in test262 and can be noticed by overriding toString of primitive values. This does now require one to wrap an object in a Value to call invoke but all code using invoke has been migrated.
This commit is contained in:
parent
74e6a70958
commit
151447bdf7
Notes:
sideshowbarker
2024-07-18 07:11:14 +09:00
Author: https://github.com/davidot Commit: https://github.com/SerenityOS/serenity/commit/151447bdf72 Pull-request: https://github.com/SerenityOS/serenity/pull/9303 Issue: https://github.com/SerenityOS/serenity/issues/9024 Issue: https://github.com/SerenityOS/serenity/issues/9025 Reviewed-by: https://github.com/linusg
@ -542,10 +542,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
|
||||
return {};
|
||||
if (value.is_nullish())
|
||||
continue;
|
||||
auto* value_object = value.to_object(global_object);
|
||||
if (!value_object)
|
||||
return {};
|
||||
auto locale_string_result = value_object->invoke(vm.names.toLocaleString);
|
||||
auto locale_string_result = value.invoke(global_object, vm.names.toLocaleString);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
auto string = locale_string_result.to_string(global_object);
|
||||
|
@ -846,18 +846,16 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_string)
|
||||
// 21.4.4.37 Date.prototype.toJSON ( key ), https://tc39.es/ecma262/#sec-date.prototype.tojson
|
||||
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_json)
|
||||
{
|
||||
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||
if (!this_object)
|
||||
return {};
|
||||
auto this_value = vm.this_value(global_object);
|
||||
|
||||
auto time_value = Value(this_object).to_primitive(global_object, Value::PreferredType::Number);
|
||||
auto time_value = this_value.to_primitive(global_object, Value::PreferredType::Number);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
if (time_value.is_number() && !time_value.is_finite_number())
|
||||
return js_null();
|
||||
|
||||
return this_object->invoke(vm.names.toISOString);
|
||||
return this_value.invoke(global_object, vm.names.toISOString);
|
||||
}
|
||||
|
||||
// 14.1.1 Date.prototype.toTemporalInstant ( ), https://tc39.es/proposal-temporal/#sec-date.prototype.totemporalinstant
|
||||
|
@ -163,4 +163,16 @@ inline GlobalObject* Shape::global_object() const
|
||||
template<>
|
||||
inline bool Object::fast_is<GlobalObject>() const { return is_global_object(); }
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] ALWAYS_INLINE Value Value::invoke(GlobalObject& global_object, PropertyName const& property_name, Args... args)
|
||||
{
|
||||
if constexpr (sizeof...(Args) > 0) {
|
||||
MarkedValueList arglist { global_object.vm().heap() };
|
||||
(..., arglist.append(move(args)));
|
||||
return invoke_internal(global_object, property_name, move(arglist));
|
||||
}
|
||||
|
||||
return invoke_internal(global_object, property_name, Optional<MarkedValueList> {});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1199,17 +1199,4 @@ Value Object::ordinary_to_primitive(Value::PreferredType preferred_type) const
|
||||
return {};
|
||||
}
|
||||
|
||||
Value Object::invoke_internal(PropertyName const& property_name, Optional<MarkedValueList> arguments)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto property = get(property_name);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!property.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, property.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
return vm.call(property.as_function(), this, move(arguments));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -150,20 +150,6 @@ public:
|
||||
IndexedProperties& indexed_properties() { return m_indexed_properties; }
|
||||
void set_indexed_property_elements(Vector<Value>&& values) { m_indexed_properties = IndexedProperties(move(values)); }
|
||||
|
||||
[[nodiscard]] Value invoke_internal(PropertyName const&, Optional<MarkedValueList> arguments);
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] ALWAYS_INLINE Value invoke(PropertyName const& property_name, Args... args)
|
||||
{
|
||||
if constexpr (sizeof...(Args) > 0) {
|
||||
MarkedValueList arglist { heap() };
|
||||
(..., arglist.append(move(args)));
|
||||
return invoke(property_name, move(arglist));
|
||||
}
|
||||
|
||||
return invoke(property_name);
|
||||
}
|
||||
|
||||
Shape& shape() { return *m_shape; }
|
||||
Shape const& shape() const { return *m_shape; }
|
||||
|
||||
@ -201,13 +187,4 @@ private:
|
||||
IndexedProperties m_indexed_properties;
|
||||
};
|
||||
|
||||
template<>
|
||||
[[nodiscard]] ALWAYS_INLINE Value Object::invoke(PropertyName const& property_name, MarkedValueList arguments) { return invoke_internal(property_name, move(arguments)); }
|
||||
|
||||
template<>
|
||||
[[nodiscard]] ALWAYS_INLINE Value Object::invoke(PropertyName const& property_name, Optional<MarkedValueList> arguments) { return invoke_internal(property_name, move(arguments)); }
|
||||
|
||||
template<>
|
||||
[[nodiscard]] ALWAYS_INLINE Value Object::invoke(PropertyName const& property_name) { return invoke(property_name, Optional<MarkedValueList> {}); }
|
||||
|
||||
}
|
||||
|
@ -145,10 +145,8 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
|
||||
// 20.1.3.5 Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-object.prototype.tolocalestring
|
||||
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string)
|
||||
{
|
||||
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||
if (!this_object)
|
||||
return {};
|
||||
return this_object->invoke(vm.names.toString);
|
||||
auto this_value = vm.this_value(global_object);
|
||||
return this_value.invoke(global_object, vm.names.toString);
|
||||
}
|
||||
|
||||
// 20.1.3.7 Object.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-object.prototype.valueof
|
||||
|
@ -67,11 +67,9 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::then)
|
||||
// 27.2.5.1 Promise.prototype.catch ( onRejected ), https://tc39.es/ecma262/#sec-promise.prototype.catch
|
||||
JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::catch_)
|
||||
{
|
||||
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||
if (!this_object)
|
||||
return {};
|
||||
auto this_value = vm.this_value(global_object);
|
||||
auto on_rejected = vm.argument(0);
|
||||
return this_object->invoke(vm.names.then, js_undefined(), on_rejected);
|
||||
return this_value.invoke(global_object, vm.names.then, js_undefined(), on_rejected);
|
||||
}
|
||||
|
||||
// 27.2.5.3 Promise.prototype.finally ( onFinally ), https://tc39.es/ecma262/#sec-promise.prototype.finally
|
||||
@ -104,7 +102,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
||||
auto* value_thunk = NativeFunction::create(global_object, "", [value](auto&, auto&) -> Value {
|
||||
return value;
|
||||
});
|
||||
return promise->invoke(vm.names.then, value_thunk);
|
||||
return Value(promise).invoke(global_object, vm.names.then, value_thunk);
|
||||
});
|
||||
then_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
|
||||
@ -123,14 +121,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
||||
vm.throw_exception(global_object, reason);
|
||||
return {};
|
||||
});
|
||||
return promise->invoke(vm.names.then, thrower);
|
||||
return Value(promise).invoke(global_object, vm.names.then, thrower);
|
||||
});
|
||||
catch_finally_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
|
||||
then_finally = Value(then_finally_function);
|
||||
catch_finally = Value(catch_finally_function);
|
||||
}
|
||||
return promise->invoke(vm.names.then, then_finally, catch_finally);
|
||||
return Value(promise).invoke(global_object, vm.names.then, then_finally, catch_finally);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -878,7 +878,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match)
|
||||
auto rx = regexp_create(global_object, regexp, js_undefined());
|
||||
if (!rx)
|
||||
return {};
|
||||
return rx->invoke(*vm.well_known_symbol_match(), js_string(vm, utf16_string_view));
|
||||
return Value(rx).invoke(global_object, *vm.well_known_symbol_match(), js_string(vm, utf16_string_view));
|
||||
}
|
||||
|
||||
// 22.1.3.12 String.prototype.matchAll ( regexp ), https://tc39.es/ecma262/#sec-string.prototype.matchall
|
||||
@ -921,7 +921,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all)
|
||||
auto rx = regexp_create(global_object, regexp, js_string(vm, "g"));
|
||||
if (!rx)
|
||||
return {};
|
||||
return rx->invoke(*vm.well_known_symbol_match_all(), js_string(vm, utf16_string_view));
|
||||
return Value(rx).invoke(global_object, *vm.well_known_symbol_match_all(), js_string(vm, utf16_string_view));
|
||||
}
|
||||
|
||||
// 22.1.3.17 String.prototype.replace ( searchValue, replaceValue ), https://tc39.es/ecma262/#sec-string.prototype.replace
|
||||
@ -1119,7 +1119,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::search)
|
||||
auto rx = regexp_create(global_object, regexp, js_undefined());
|
||||
if (!rx)
|
||||
return {};
|
||||
return rx->invoke(*vm.well_known_symbol_search(), js_string(vm, utf16_string_view));
|
||||
return Value(rx).invoke(global_object, *vm.well_known_symbol_search(), js_string(vm, utf16_string_view));
|
||||
}
|
||||
|
||||
// B.2.3.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml
|
||||
|
@ -129,7 +129,7 @@ double calendar_year(GlobalObject& global_object, Object& calendar, Object& date
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Let result be ? Invoke(calendar, "year", « dateLike »).
|
||||
auto result = calendar.invoke(vm.names.year, &date_like);
|
||||
auto result = Value(&calendar).invoke(global_object, vm.names.year, &date_like);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
@ -150,7 +150,7 @@ double calendar_month(GlobalObject& global_object, Object& calendar, Object& dat
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Let result be ? Invoke(calendar, "month", « dateLike »).
|
||||
auto result = calendar.invoke(vm.names.month, &date_like);
|
||||
auto result = Value(&calendar).invoke(global_object, vm.names.month, &date_like);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
@ -171,7 +171,7 @@ String calendar_month_code(GlobalObject& global_object, Object& calendar, Object
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Let result be ? Invoke(calendar, "monthCode", « dateLike »).
|
||||
auto result = calendar.invoke(vm.names.monthCode, &date_like);
|
||||
auto result = Value(&calendar).invoke(global_object, vm.names.monthCode, &date_like);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
@ -192,7 +192,7 @@ double calendar_day(GlobalObject& global_object, Object& calendar, Object& date_
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Let result be ? Invoke(calendar, "day", « dateLike »).
|
||||
auto result = calendar.invoke(vm.names.day, &date_like);
|
||||
auto result = Value(&calendar).invoke(global_object, vm.names.day, &date_like);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
@ -213,7 +213,7 @@ Value calendar_day_of_week(GlobalObject& global_object, Object& calendar, Object
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "dayOfWeek", « dateLike »).
|
||||
return calendar.invoke(vm.names.dayOfWeek, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.dayOfWeek, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.14 CalendarDayOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardayofyear
|
||||
@ -223,7 +223,7 @@ Value calendar_day_of_year(GlobalObject& global_object, Object& calendar, Object
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "dayOfYear", « dateLike »).
|
||||
return calendar.invoke(vm.names.dayOfYear, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.dayOfYear, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.15 CalendarWeekOfYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarweekofyear
|
||||
@ -233,7 +233,7 @@ Value calendar_week_of_year(GlobalObject& global_object, Object& calendar, Objec
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "weekOfYear", « dateLike »).
|
||||
return calendar.invoke(vm.names.weekOfYear, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.weekOfYear, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.16 CalendarDaysInWeek ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinweek
|
||||
@ -243,7 +243,7 @@ Value calendar_days_in_week(GlobalObject& global_object, Object& calendar, Objec
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "daysInWeek", « dateLike »).
|
||||
return calendar.invoke(vm.names.daysInWeek, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.daysInWeek, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.17 CalendarDaysInMonth ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinmonth
|
||||
@ -253,7 +253,7 @@ Value calendar_days_in_month(GlobalObject& global_object, Object& calendar, Obje
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "daysInMonth", « dateLike »).
|
||||
return calendar.invoke(vm.names.daysInMonth, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.daysInMonth, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.18 CalendarDaysInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardaysinyear
|
||||
@ -263,7 +263,7 @@ Value calendar_days_in_year(GlobalObject& global_object, Object& calendar, Objec
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "daysInYear", « dateLike »).
|
||||
return calendar.invoke(vm.names.daysInYear, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.daysInYear, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.19 CalendarMonthsInYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonthsinyear
|
||||
@ -273,7 +273,7 @@ Value calendar_months_in_year(GlobalObject& global_object, Object& calendar, Obj
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "monthsInYear", « dateLike »).
|
||||
return calendar.invoke(vm.names.monthsInYear, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.monthsInYear, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.20 CalendarInLeapYear ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarinleapyear
|
||||
@ -283,7 +283,7 @@ Value calendar_in_leap_year(GlobalObject& global_object, Object& calendar, Objec
|
||||
// 1. Assert: Type(calendar) is Object.
|
||||
|
||||
// 2. Return ? Invoke(calendar, "inLeapYear", « dateLike »).
|
||||
return calendar.invoke(vm.names.inLeapYear, &date_like);
|
||||
return Value(&calendar).invoke(global_object, vm.names.inLeapYear, &date_like);
|
||||
}
|
||||
|
||||
// 12.1.21 ToTemporalCalendar ( temporalCalendarLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalcalendar
|
||||
@ -396,7 +396,7 @@ PlainDate* date_from_fields(GlobalObject& global_object, Object& calendar, Objec
|
||||
// 2. Assert: Type(fields) is Object.
|
||||
|
||||
// 3. Let date be ? Invoke(calendar, "dateFromFields", « fields, options »).
|
||||
auto date = calendar.invoke(vm.names.dateFromFields, &fields, &options);
|
||||
auto date = Value(&calendar).invoke(global_object, vm.names.dateFromFields, &fields, &options);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
|
@ -1521,10 +1521,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
|
||||
return {};
|
||||
if (value.is_nullish())
|
||||
continue;
|
||||
auto* value_object = value.to_object(global_object);
|
||||
if (!value_object)
|
||||
return {};
|
||||
auto locale_string_result = value_object->invoke(vm.names.toLocaleString);
|
||||
auto locale_string_result = value.invoke(global_object, vm.names.toLocaleString);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
auto string = locale_string_result.to_string(global_object);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <LibJS/Runtime/RegExpObject.h>
|
||||
#include <LibJS/Runtime/StringObject.h>
|
||||
#include <LibJS/Runtime/SymbolObject.h>
|
||||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -1581,4 +1582,19 @@ TriState abstract_relation(GlobalObject& global_object, bool left_first, Value l
|
||||
return TriState::False;
|
||||
}
|
||||
|
||||
// 7.3.20 Invoke ( V, P [ , argumentsList ] ), https://tc39.es/ecma262/#sec-invoke
|
||||
Value Value::invoke_internal(GlobalObject& global_object, JS::PropertyName const& property_name, Optional<MarkedValueList> arguments)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto property = get(global_object, property_name);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!property.is_function()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, property.to_string_without_side_effects());
|
||||
return {};
|
||||
}
|
||||
|
||||
return vm.call(property.as_function(), *this, move(arguments));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -290,9 +290,14 @@ public:
|
||||
|
||||
bool operator==(Value const&) const;
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] ALWAYS_INLINE Value invoke(GlobalObject& global_object, PropertyName const& property_name, Args... args);
|
||||
|
||||
private:
|
||||
Type m_type { Type::Empty };
|
||||
|
||||
[[nodiscard]] Value invoke_internal(GlobalObject& global_object, PropertyName const&, Optional<MarkedValueList> arguments);
|
||||
|
||||
i32 to_i32_slow_case(GlobalObject&) const;
|
||||
|
||||
union {
|
||||
|
Loading…
Reference in New Issue
Block a user