1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:47:44 +00:00

LibJS: Use empty value for Reference unresolvable state, not undefined

This fixes an issue where `undefined.foo = "bar"` would throw a
ReferenceError instead of a TypeError as undefined was also used for
truly unresolvable references (e.g. `foo() = "bar"`). I also made the
various error messages here a bit nicer, just "primitive value" is not
very helpful.
This commit is contained in:
Linus Groh 2021-04-02 21:00:37 +02:00 committed by Andreas Kling
parent d6cffb82a2
commit e875513ff7
4 changed files with 39 additions and 15 deletions

View file

@ -47,12 +47,23 @@ void Reference::put(GlobalObject& global_object, Value value)
return;
}
if (!base().is_object() && vm.in_strict_mode()) {
vm.throw_exception<TypeError>(global_object, ErrorType::ReferencePrimitiveAssignment, m_name.to_value(global_object.vm()).to_string_without_side_effects());
auto base = this->base();
if (!base.is_object() && vm.in_strict_mode()) {
if (base.is_nullish())
vm.throw_exception<TypeError>(global_object, ErrorType::ReferenceNullishAssignment, m_name.to_value(global_object.vm()).to_string_without_side_effects(), base.to_string_without_side_effects());
else
vm.throw_exception<TypeError>(global_object, ErrorType::ReferencePrimitiveAssignment, m_name.to_value(global_object.vm()).to_string_without_side_effects(), base.typeof(), base.to_string_without_side_effects());
return;
}
auto* object = base().to_object(global_object);
if (base.is_nullish()) {
// This will always fail the to_object() call below, let's throw the TypeError ourselves with a nice message instead.
vm.throw_exception<TypeError>(global_object, ErrorType::ReferenceNullishAssignment, m_name.to_value(global_object.vm()).to_string_without_side_effects(), base.to_string_without_side_effects());
return;
}
auto* object = base.to_object(global_object);
if (!object)
return;
@ -61,13 +72,11 @@ void Reference::put(GlobalObject& global_object, Value value)
void Reference::throw_reference_error(GlobalObject& global_object)
{
auto property_name = m_name.to_string();
String message;
if (property_name.is_empty()) {
global_object.vm().throw_exception<ReferenceError>(global_object, ErrorType::ReferenceUnresolvable);
} else {
global_object.vm().throw_exception<ReferenceError>(global_object, ErrorType::UnknownIdentifier, property_name);
}
auto& vm = global_object.vm();
if (!m_name.is_valid())
vm.throw_exception<ReferenceError>(global_object, ErrorType::ReferenceUnresolvable);
else
vm.throw_exception<ReferenceError>(global_object, ErrorType::UnknownIdentifier, m_name.to_string_or_symbol().to_display_string());
}
Value Reference::get(GlobalObject& global_object)