1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 00:27:43 +00:00

LibJS: Add ECMA-262 section/title/URL comments almost everywhere

As mentioned on Discord earlier, we'll add these to all new functions
going forward - this is the backfill. Reasons:

- It makes you look at the spec, implementing based on MDN or V8
  behavior is a no-go
- It makes finding the various functions that are non-compliant easier,
  in the future everything should either have such a comment or, if it's
  not from the spec at all, a comment explaining why that is the case
- It makes it easier to check whether a certain abstract operation is
  implemented in LibJS, not all of them use the same name as the spec.
  E.g. RejectPromise() is Promise::reject()
- It makes it easier to reason about vm.arguments(), e.g. when the
  function has a rest parameter
- It makes it easier to see whether a certain function is from a
  proposal or Annex B

Also:

- Add arguments to all functions and abstract operations that already
  had a comment
- Fix some outdated section numbers
- Replace some ecma-international.org URLs with tc39.es
This commit is contained in:
Linus Groh 2021-06-13 00:22:35 +01:00
parent 322c8a3995
commit 7327a28ccc
52 changed files with 480 additions and 101 deletions

View file

@ -70,9 +70,9 @@ ALWAYS_INLINE bool both_bigint(const Value& lhs, const Value& rhs)
return lhs.is_bigint() && rhs.is_bigint();
}
// 6.1.6.1.20 Number::toString ( x ), https://tc39.es/ecma262/#sec-numeric-types-number-tostring
static String double_to_string(double d)
{
// https://tc39.es/ecma262/#sec-numeric-types-number-tostring
if (isnan(d))
return "NaN";
if (d == +0.0 || d == -0.0)
@ -198,7 +198,7 @@ static String double_to_string(double d)
return builder.to_string();
}
// 7.2.2 IsArray, https://tc39.es/ecma262/#sec-isarray
// 7.2.2 IsArray ( argument ), https://tc39.es/ecma262/#sec-isarray
bool Value::is_array(GlobalObject& global_object) const
{
if (!is_object())
@ -224,6 +224,7 @@ Array& Value::as_array()
return static_cast<Array&>(*m_value.as_object);
}
// 7.2.3 IsCallable ( argument ), https://tc39.es/ecma262/#sec-iscallable
bool Value::is_function() const
{
return is_object() && as_object().is_function();
@ -235,7 +236,7 @@ Function& Value::as_function()
return static_cast<Function&>(as_object());
}
// 7.2.4 IsConstructor, https://tc39.es/ecma262/#sec-isconstructor
// 7.2.4 IsConstructor ( argument ), https://tc39.es/ecma262/#sec-isconstructor
bool Value::is_constructor() const
{
if (!is_function())
@ -246,7 +247,7 @@ bool Value::is_constructor() const
return true;
}
// 7.2.8 IsRegExp, https://tc39.es/ecma262/#sec-isregexp
// 7.2.8 IsRegExp ( argument ), https://tc39.es/ecma262/#sec-isregexp
bool Value::is_regexp(GlobalObject& global_object) const
{
if (!is_object())
@ -261,6 +262,7 @@ bool Value::is_regexp(GlobalObject& global_object) const
return is<RegExpObject>(as_object());
}
// 13.5.3 The typeof Operator, https://tc39.es/ecma262/#sec-typeof-operator
String Value::typeof() const
{
switch (m_type) {
@ -328,6 +330,7 @@ PrimitiveString* Value::to_primitive_string(GlobalObject& global_object)
return js_string(global_object.heap(), string);
}
// 7.1.17 ToString ( argument ), https://tc39.es/ecma262/#sec-tostring
String Value::to_string(GlobalObject& global_object, bool legacy_null_to_empty_string) const
{
switch (m_type) {
@ -359,6 +362,7 @@ String Value::to_string(GlobalObject& global_object, bool legacy_null_to_empty_s
}
}
// 7.1.2 ToBoolean ( argument ), https://tc39.es/ecma262/#sec-toboolean
bool Value::to_boolean() const
{
switch (m_type) {
@ -386,6 +390,7 @@ bool Value::to_boolean() const
}
}
// 7.1.1 ToPrimitive ( input [ , preferredType ] ), https://tc39.es/ecma262/#sec-toprimitive
Value Value::to_primitive(GlobalObject& global_object, PreferredType preferred_type) const
{
auto get_hint_for_preferred_type = [&]() -> String {
@ -422,6 +427,7 @@ Value Value::to_primitive(GlobalObject& global_object, PreferredType preferred_t
return *this;
}
// 7.1.18 ToObject ( argument ), https://tc39.es/ecma262/#sec-toobject
Object* Value::to_object(GlobalObject& global_object) const
{
switch (m_type) {
@ -448,6 +454,7 @@ Object* Value::to_object(GlobalObject& global_object) const
}
}
// 7.1.3 ToNumeric ( value ), https://tc39.es/ecma262/#sec-tonumeric
FLATTEN Value Value::to_numeric(GlobalObject& global_object) const
{
auto primitive = to_primitive(global_object, Value::PreferredType::Number);
@ -458,6 +465,7 @@ FLATTEN Value Value::to_numeric(GlobalObject& global_object) const
return primitive.to_number(global_object);
}
// 7.1.4 ToNumber ( argument ), https://tc39.es/ecma262/#sec-tonumber
Value Value::to_number(GlobalObject& global_object) const
{
switch (m_type) {
@ -501,6 +509,7 @@ Value Value::to_number(GlobalObject& global_object) const
}
}
// 7.1.13 ToBigInt ( argument ), https://tc39.es/ecma262/#sec-tobigint
BigInt* Value::to_bigint(GlobalObject& global_object) const
{
auto& vm = global_object.vm();
@ -560,6 +569,7 @@ double Value::to_double(GlobalObject& global_object) const
return number.as_double();
}
// 7.1.19 ToPropertyKey ( argument ), https://tc39.es/ecma262/#sec-topropertykey
StringOrSymbol Value::to_property_key(GlobalObject& global_object) const
{
auto key = to_primitive(global_object, PreferredType::String);
@ -590,9 +600,9 @@ i32 Value::to_i32_slow_case(GlobalObject& global_object) const
return static_cast<i32>(int32bit);
}
// 7.1.7 ToUint32 ( argument ), https://tc39.es/ecma262/#sec-touint32
u32 Value::to_u32(GlobalObject& global_object) const
{
// 7.1.7 ToUint32, https://tc39.es/ecma262/#sec-touint32
auto number = to_number(global_object);
if (global_object.vm().exception())
return INVALID;
@ -606,10 +616,9 @@ u32 Value::to_u32(GlobalObject& global_object) const
return static_cast<u32>(int32bit);
}
// 7.1.20 ToLength ( argument ), https://tc39.es/ecma262/#sec-tolength
size_t Value::to_length(GlobalObject& global_object) const
{
// 7.1.20 ToLength, https://tc39.es/ecma262/#sec-tolength
auto& vm = global_object.vm();
auto len = to_integer_or_infinity(global_object);
@ -620,10 +629,9 @@ size_t Value::to_length(GlobalObject& global_object) const
return min(len, MAX_ARRAY_LIKE_INDEX);
}
// 7.1.22 ToIndex ( argument ), https://tc39.es/ecma262/#sec-toindex
size_t Value::to_index(GlobalObject& global_object) const
{
// 7.1.22 ToIndex, https://tc39.es/ecma262/#sec-toindex
auto& vm = global_object.vm();
if (is_undefined())
@ -644,10 +652,9 @@ size_t Value::to_index(GlobalObject& global_object) const
return index;
}
// 7.1.5 ToIntegerOrInfinity ( argument ), https://tc39.es/ecma262/#sec-tointegerorinfinity
double Value::to_integer_or_infinity(GlobalObject& global_object) const
{
// 7.1.5 ToIntegerOrInfinity, https://tc39.es/ecma262/#sec-tointegerorinfinity
auto& vm = global_object.vm();
auto number = to_number(global_object);
@ -663,6 +670,7 @@ double Value::to_integer_or_infinity(GlobalObject& global_object) const
return integer;
}
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value greater_than(GlobalObject& global_object, Value lhs, Value rhs)
{
TriState relation = abstract_relation(global_object, false, lhs, rhs);
@ -671,6 +679,7 @@ Value greater_than(GlobalObject& global_object, Value lhs, Value rhs)
return Value(relation == TriState::True);
}
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value greater_than_equals(GlobalObject& global_object, Value lhs, Value rhs)
{
TriState relation = abstract_relation(global_object, true, lhs, rhs);
@ -679,6 +688,7 @@ Value greater_than_equals(GlobalObject& global_object, Value lhs, Value rhs)
return Value(true);
}
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value less_than(GlobalObject& global_object, Value lhs, Value rhs)
{
TriState relation = abstract_relation(global_object, true, lhs, rhs);
@ -687,6 +697,7 @@ Value less_than(GlobalObject& global_object, Value lhs, Value rhs)
return Value(relation == TriState::True);
}
// 13.10 Relational Operators, https://tc39.es/ecma262/#sec-relational-operators
Value less_than_equals(GlobalObject& global_object, Value lhs, Value rhs)
{
TriState relation = abstract_relation(global_object, false, lhs, rhs);
@ -695,6 +706,7 @@ Value less_than_equals(GlobalObject& global_object, Value lhs, Value rhs)
return Value(true);
}
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
Value bitwise_and(GlobalObject& global_object, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(global_object);
@ -714,6 +726,7 @@ Value bitwise_and(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
Value bitwise_or(GlobalObject& global_object, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(global_object);
@ -737,6 +750,7 @@ Value bitwise_or(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.12 Binary Bitwise Operators, https://tc39.es/ecma262/#sec-binary-bitwise-operators
Value bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(global_object);
@ -760,6 +774,7 @@ Value bitwise_xor(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.5.6 Bitwise NOT Operator ( ~ ), https://tc39.es/ecma262/#sec-bitwise-not-operator
Value bitwise_not(GlobalObject& global_object, Value lhs)
{
auto lhs_numeric = lhs.to_numeric(global_object);
@ -773,11 +788,13 @@ Value bitwise_not(GlobalObject& global_object, Value lhs)
return js_bigint(global_object.heap(), big_integer_bitwise_not);
}
// 13.5.4 Unary + Operator, https://tc39.es/ecma262/#sec-unary-plus-operator
Value unary_plus(GlobalObject& global_object, Value lhs)
{
return lhs.to_number(global_object);
}
// 13.5.5 Unary - Operator, https://tc39.es/ecma262/#sec-unary-minus-operator
Value unary_minus(GlobalObject& global_object, Value lhs)
{
auto lhs_numeric = lhs.to_numeric(global_object);
@ -795,10 +812,9 @@ Value unary_minus(GlobalObject& global_object, Value lhs)
return js_bigint(global_object.heap(), big_integer_negated);
}
// 13.9.1 The Left Shift Operator ( << ), https://tc39.es/ecma262/#sec-left-shift-operator
Value left_shift(GlobalObject& global_object, Value lhs, Value rhs)
{
// 6.1.6.1.9 Number::leftShift
// https://tc39.es/ecma262/#sec-numeric-types-number-leftShift
auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception())
return {};
@ -826,10 +842,9 @@ Value left_shift(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.9.2 The Signed Right Shift Operator ( >> ), https://tc39.es/ecma262/#sec-signed-right-shift-operator
Value right_shift(GlobalObject& global_object, Value lhs, Value rhs)
{
// 6.1.6.1.11 Number::signedRightShift
// https://tc39.es/ecma262/#sec-numeric-types-number-signedRightShift
auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception())
return {};
@ -841,7 +856,6 @@ Value right_shift(GlobalObject& global_object, Value lhs, Value rhs)
return Value(0);
if (!rhs_numeric.is_finite_number())
return lhs_numeric;
// Ok, so this performs toNumber() again but that "can't" throw
auto lhs_i32 = lhs_numeric.to_i32(global_object);
auto rhs_u32 = rhs_numeric.to_u32(global_object);
return Value(lhs_i32 >> rhs_u32);
@ -855,10 +869,9 @@ Value right_shift(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.9.3 The Unsigned Right Shift Operator ( >>> ), https://tc39.es/ecma262/#sec-unsigned-right-shift-operator
Value unsigned_right_shift(GlobalObject& global_object, Value lhs, Value rhs)
{
// 6.1.6.1.11 Number::unsignedRightShift
// https://tc39.es/ecma262/#sec-numeric-types-number-unsignedRightShift
auto lhs_numeric = lhs.to_numeric(global_object);
if (global_object.vm().exception())
return {};
@ -879,6 +892,7 @@ Value unsigned_right_shift(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.8.1 The Addition Operator ( + ), https://tc39.es/ecma262/#sec-addition-operator-plus
Value add(GlobalObject& global_object, Value lhs, Value rhs)
{
if (both_number(lhs, rhs)) {
@ -926,6 +940,7 @@ Value add(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.8.2 The Subtraction Operator ( - ), https://tc39.es/ecma262/#sec-subtraction-operator-minus
Value sub(GlobalObject& global_object, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(global_object);
@ -942,6 +957,7 @@ Value sub(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
Value mul(GlobalObject& global_object, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(global_object);
@ -958,6 +974,7 @@ Value mul(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
Value div(GlobalObject& global_object, Value lhs, Value rhs)
{
auto& vm = global_object.vm();
@ -980,6 +997,7 @@ Value div(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.7 Multiplicative Operators, https://tc39.es/ecma262/#sec-multiplicative-operators
Value mod(GlobalObject& global_object, Value lhs, Value rhs)
{
auto& vm = global_object.vm();
@ -1008,6 +1026,7 @@ Value mod(GlobalObject& global_object, Value lhs, Value rhs)
return {};
}
// 13.6 Exponentiation Operator, https://tc39.es/ecma262/#sec-exp-operator
Value exp(GlobalObject& global_object, Value lhs, Value rhs)
{
auto& vm = global_object.vm();
@ -1042,6 +1061,7 @@ Value in(GlobalObject& global_object, Value lhs, Value rhs)
return Value(rhs.as_object().has_property(lhs_property_key));
}
// 13.10.2 InstanceofOperator ( V, target ), https://tc39.es/ecma262/#sec-instanceofoperator
Value instance_of(GlobalObject& global_object, Value lhs, Value rhs)
{
auto& vm = global_object.vm();
@ -1100,6 +1120,7 @@ Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
}
}
// 7.2.10 SameValue ( x, y ), https://tc39.es/ecma262/#sec-samevalue
bool same_value(Value lhs, Value rhs)
{
if (!same_type_for_equality(lhs, rhs))
@ -1126,6 +1147,7 @@ bool same_value(Value lhs, Value rhs)
return same_value_non_numeric(lhs, rhs);
}
// 7.2.11 SameValueZero ( x, y ), https://tc39.es/ecma262/#sec-samevaluezero
bool same_value_zero(Value lhs, Value rhs)
{
if (!same_type_for_equality(lhs, rhs))
@ -1143,6 +1165,7 @@ bool same_value_zero(Value lhs, Value rhs)
return same_value_non_numeric(lhs, rhs);
}
// 7.2.12 SameValueNonNumeric ( x, y ), https://tc39.es/ecma262/#sec-samevaluenonnumeric
bool same_value_non_numeric(Value lhs, Value rhs)
{
VERIFY(!lhs.is_number() && !lhs.is_bigint());
@ -1165,6 +1188,7 @@ bool same_value_non_numeric(Value lhs, Value rhs)
}
}
// 7.2.15 IsStrictlyEqual ( x, y ), https://tc39.es/ecma262/#sec-isstrictlyequal
bool strict_eq(Value lhs, Value rhs)
{
if (!same_type_for_equality(lhs, rhs))
@ -1184,6 +1208,7 @@ bool strict_eq(Value lhs, Value rhs)
return same_value_non_numeric(lhs, rhs);
}
// 7.2.14 IsLooselyEqual ( x, y ), https://tc39.es/ecma262/#sec-islooselyequal
bool abstract_eq(GlobalObject& global_object, Value lhs, Value rhs)
{
if (same_type_for_equality(lhs, rhs))
@ -1242,6 +1267,7 @@ bool abstract_eq(GlobalObject& global_object, Value lhs, Value rhs)
return false;
}
// 7.2.13 IsLessThan ( x, y, LeftFirst ), https://tc39.es/ecma262/#sec-islessthan
TriState abstract_relation(GlobalObject& global_object, bool left_first, Value lhs, Value rhs)
{
Value x_primitive;
@ -1357,7 +1383,7 @@ TriState abstract_relation(GlobalObject& global_object, bool left_first, Value l
return TriState::False;
}
// 7.3.10 GetMethod, https://tc39.es/ecma262/#sec-getmethod
// 7.3.10 GetMethod ( V, P ), https://tc39.es/ecma262/#sec-getmethod
Function* get_method(GlobalObject& global_object, Value value, const PropertyName& property_name)
{
auto& vm = global_object.vm();
@ -1376,7 +1402,7 @@ Function* get_method(GlobalObject& global_object, Value value, const PropertyNam
return &property_value.as_function();
}
// 7.3.18 LengthOfArrayLike, https://tc39.es/ecma262/#sec-lengthofarraylike
// 7.3.18 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike
size_t length_of_array_like(GlobalObject& global_object, const Object& object)
{
auto& vm = global_object.vm();
@ -1386,7 +1412,7 @@ size_t length_of_array_like(GlobalObject& global_object, const Object& object)
return result.to_length(global_object);
}
// 7.3.22 SpeciesConstructor, https://tc39.es/ecma262/#sec-speciesconstructor
// 7.3.22 SpeciesConstructor ( O, defaultConstructor ), https://tc39.es/ecma262/#sec-speciesconstructor
Function* species_constructor(GlobalObject& global_object, const Object& object, Function& default_constructor)
{
auto& vm = global_object.vm();
@ -1408,7 +1434,7 @@ Function* species_constructor(GlobalObject& global_object, const Object& object,
return nullptr;
}
// 7.2.1 RequireObjectCoercible, https://tc39.es/ecma262/#sec-requireobjectcoercible
// 7.2.1 RequireObjectCoercible ( argument ), https://tc39.es/ecma262/#sec-requireobjectcoercible
Value require_object_coercible(GlobalObject& global_object, Value value)
{
auto& vm = global_object.vm();
@ -1419,7 +1445,7 @@ Value require_object_coercible(GlobalObject& global_object, Value value)
return value;
}
// 7.3.19 CreateListFromArrayLike, https://tc39.es/ecma262/#sec-createlistfromarraylike
// 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value value, AK::Function<Result<void, ErrorType>(Value)> check_value)
{
auto& vm = global_object.vm();