1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 19:38:12 +00:00

LibJS/Bytecode: Do not coerce the receiver to Object for internal_set

This makes the behavior of `Symbol` correct in strict mode, wherein if
the receiver is a symbol primitive, assigning new properties should
throw a TypeError.
This commit is contained in:
Daniel Bertalan 2023-07-02 20:33:58 +02:00 committed by Linus Groh
parent 0cd85ab0fc
commit d165590809
2 changed files with 16 additions and 7 deletions

View file

@ -48,8 +48,9 @@ DeprecatedString Instruction::to_deprecated_string(Bytecode::Executable const& e
namespace JS::Bytecode::Op {
static ThrowCompletionOr<void> put_by_property_key(VM& vm, Object* object, Value value, PropertyKey name, PropertyKind kind)
static ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value value, PropertyKey name, PropertyKind kind)
{
auto object = TRY(base.to_object(vm));
if (kind == PropertyKind::Getter || kind == PropertyKind::Setter) {
// The generator should only pass us functions for getters and setters.
VERIFY(value.is_function());
@ -70,9 +71,9 @@ static ThrowCompletionOr<void> put_by_property_key(VM& vm, Object* object, Value
break;
}
case PropertyKind::KeyValue: {
bool succeeded = TRY(object->internal_set(name, value, object));
bool succeeded = TRY(object->internal_set(name, value, base));
if (!succeeded && vm.in_strict_mode())
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishSetProperty, name, TRY_OR_THROW_OOM(vm, value.to_string_without_side_effects()));
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishSetProperty, name, TRY_OR_THROW_OOM(vm, base.to_string_without_side_effects()));
break;
}
case PropertyKind::Spread:
@ -548,9 +549,9 @@ ThrowCompletionOr<void> PutById::execute_impl(Bytecode::Interpreter& interpreter
auto& vm = interpreter.vm();
// NOTE: Get the value from the accumulator before side effects have a chance to overwrite it.
auto value = interpreter.accumulator();
auto object = TRY(interpreter.reg(m_base).to_object(vm));
auto base = interpreter.reg(m_base);
PropertyKey name = interpreter.current_executable().get_identifier(m_property);
TRY(put_by_property_key(vm, object, value, name, m_kind));
TRY(put_by_property_key(vm, base, value, name, m_kind));
interpreter.accumulator() = value;
return {};
}
@ -1017,10 +1018,10 @@ ThrowCompletionOr<void> PutByValue::execute_impl(Bytecode::Interpreter& interpre
// NOTE: Get the value from the accumulator before side effects have a chance to overwrite it.
auto value = interpreter.accumulator();
auto object = TRY(interpreter.reg(m_base).to_object(vm));
auto base = interpreter.reg(m_base);
auto property_key = TRY(interpreter.reg(m_property).to_property_key(vm));
TRY(put_by_property_key(vm, object, value, property_key, m_kind));
TRY(put_by_property_key(vm, base, value, property_key, m_kind));
interpreter.accumulator() = value;
return {};
}