LibJS: Don't allow delete super.property

This should throw a ReferenceError, since `delete` is not allowed
on super references.
This commit is contained in:
Andreas Kling 2021-07-03 01:25:07 +02:00
parent 1270df257b
commit e8430cf0d3
Notes: sideshowbarker 2024-07-18 11:05:12 +09:00
3 changed files with 40 additions and 4 deletions
Userland/Libraries/LibJS

View file

@ -769,7 +769,7 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject&
if (!property_name.is_valid())
return Reference {};
return Reference { object_value, property_name, object_value };
return Reference { object_value, property_name, {} };
}
Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_object) const

View file

@ -164,6 +164,7 @@
M(TypedArrayPrototypeOneArg, "TypedArray.prototype.{}() requires at least one argument") \
M(TypedArrayFailedSettingIndex, "Failed setting value of index {} of typed array") \
M(UnknownIdentifier, "'{}' is not defined") \
M(UnsupportedDeleteSuperProperty, "Can't delete a property on 'super'") \
M(URIMalformed, "URI malformed") /* LibWeb bindings */ \
M(NotAByteString, "Argument to {}() must be a byte string") \
M(BadArgCountOne, "{}() needs one argument") \

View file

@ -110,26 +110,61 @@ Value Reference::get_value(GlobalObject& global_object, bool throw_if_undefined)
bool Reference::delete_(GlobalObject& global_object)
{
// 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
// UnaryExpression : delete UnaryExpression
// NOTE: The following steps have already been evaluated by the time we get here:
// 1. Let ref be the result of evaluating UnaryExpression.
// 2. ReturnIfAbrupt(ref).
// 3. If ref is not a Reference Record, return true.
// 4. If IsUnresolvableReference(ref) is true, then
if (is_unresolvable()) {
// a. Assert: ref.[[Strict]] is false.
VERIFY(!m_strict);
// b. Return true.
return true;
}
auto& vm = global_object.vm();
// 5. If IsPropertyReference(ref) is true, then
if (is_property_reference()) {
// a. Assert: ! IsPrivateReference(ref) is false.
// FIXME: We don't have private references yet.
// b. If IsSuperReference(ref) is true, throw a ReferenceError exception.
if (is_super_reference()) {
vm.throw_exception<ReferenceError>(global_object, ErrorType::UnsupportedDeleteSuperProperty);
return false;
}
// c. Let baseObj be ! ToObject(ref.[[Base]]).
auto* base_obj = m_base_value.to_object(global_object);
if (!base_obj)
return false;
bool succeeded = base_obj->delete_property(m_name);
if (!succeeded && m_strict) {
// d. Let deleteStatus be ? baseObj.[[Delete]](ref.[[ReferencedName]]).
bool delete_status = base_obj->delete_property(m_name);
// e. If deleteStatus is false and ref.[[Strict]] is true, throw a TypeError exception.
if (!delete_status && m_strict) {
vm.throw_exception<TypeError>(global_object, ErrorType::ReferenceNullishDeleteProperty, m_name.to_value(vm).to_string_without_side_effects(), m_base_value.to_string_without_side_effects());
return false;
}
return succeeded;
// f. Return deleteStatus.
return delete_status;
}
// 6. Else,
// a. Let base be ref.[[Base]].
// b. Assert: base is an Environment Record.
VERIFY(m_base_type == BaseType::Environment);
// c. Return ? base.DeleteBinding(ref.[[ReferencedName]]).
// FIXME: This is ad-hoc, we should be calling DeleteBinding.
return m_base_environment->delete_from_environment(m_name.as_string());
}