Skip to content

Commit

Permalink
LibJS: Don't allow delete super.property
Browse files Browse the repository at this point in the history
This should throw a ReferenceError, since `delete` is not allowed
on super references.
  • Loading branch information
awesomekling committed Jul 2, 2021
1 parent 1270df2 commit e8430cf
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Userland/Libraries/LibJS/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibJS/Runtime/ErrorTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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") \
Expand Down
41 changes: 38 additions & 3 deletions Userland/Libraries/LibJS/Runtime/Reference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down

0 comments on commit e8430cf

Please sign in to comment.