mirror of
https://github.com/RGBCube/serenity
synced 2025-05-29 20:15:11 +00:00
LibJS: Improve error messages for primitive strict mode property access
Using ErrorType::ReferencePrimitiveSetProperty the errors for primitives now look like "Cannot set property 'foo' of number '123'". The strict-mode-errors test has been adjusted and re-enabled.
This commit is contained in:
parent
b9c9315bcb
commit
eaf8c2e398
3 changed files with 19 additions and 15 deletions
|
@ -147,6 +147,11 @@ ThrowCompletionOr<Value> get_global(Bytecode::Interpreter& interpreter, Identifi
|
||||||
|
|
||||||
ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value, Value value, PropertyKey name, Op::PropertyKind kind)
|
ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value, Value value, PropertyKey name, Op::PropertyKind kind)
|
||||||
{
|
{
|
||||||
|
// Better error message than to_object would give
|
||||||
|
if (vm.in_strict_mode() && base.is_nullish())
|
||||||
|
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishSetProperty, name, base.to_string_without_side_effects());
|
||||||
|
|
||||||
|
// a. Let baseObj be ? ToObject(V.[[Base]]).
|
||||||
auto object = TRY(base.to_object(vm));
|
auto object = TRY(base.to_object(vm));
|
||||||
if (kind == Op::PropertyKind::Getter || kind == Op::PropertyKind::Setter) {
|
if (kind == Op::PropertyKind::Getter || kind == Op::PropertyKind::Setter) {
|
||||||
// The generator should only pass us functions for getters and setters.
|
// The generator should only pass us functions for getters and setters.
|
||||||
|
@ -169,8 +174,11 @@ ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value
|
||||||
}
|
}
|
||||||
case Op::PropertyKind::KeyValue: {
|
case Op::PropertyKind::KeyValue: {
|
||||||
bool succeeded = TRY(object->internal_set(name, value, this_value));
|
bool succeeded = TRY(object->internal_set(name, value, this_value));
|
||||||
if (!succeeded && vm.in_strict_mode())
|
if (!succeeded && vm.in_strict_mode()) {
|
||||||
|
if (base.is_object())
|
||||||
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishSetProperty, name, base.to_string_without_side_effects());
|
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishSetProperty, name, base.to_string_without_side_effects());
|
||||||
|
return vm.throw_completion<TypeError>(ErrorType::ReferencePrimitiveSetProperty, name, base.typeof(), base.to_string_without_side_effects());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op::PropertyKind::DirectKeyValue:
|
case Op::PropertyKind::DirectKeyValue:
|
||||||
|
|
|
@ -23,5 +23,5 @@ test("setting new properties on a symbol is an error in strict mode", () => {
|
||||||
var symbol = Symbol("foo");
|
var symbol = Symbol("foo");
|
||||||
expect(() => {
|
expect(() => {
|
||||||
symbol.bar = 42;
|
symbol.bar = 42;
|
||||||
}).toThrowWithMessage(TypeError, "Cannot set property 'bar' of Symbol(foo)");
|
}).toThrowWithMessage(TypeError, "Cannot set property 'bar' of symbol 'Symbol(foo)'");
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,23 +1,19 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
test.xfail("basic functionality", () => {
|
test("basic functionality", () => {
|
||||||
[true, false, "foo", 123].forEach(primitive => {
|
[true, false, "foo", 123, 123n, null, undefined].forEach(primitive => {
|
||||||
|
let description = `${typeof primitive} '${primitive}${
|
||||||
|
typeof primitive == "bigint" ? "n" : ""
|
||||||
|
}'`;
|
||||||
|
if (primitive == null) description = String(primitive);
|
||||||
expect(() => {
|
expect(() => {
|
||||||
primitive.foo = "bar";
|
primitive.foo = "bar";
|
||||||
}).toThrowWithMessage(TypeError, `Cannot set property 'foo' of ${primitive}`);
|
}).toThrowWithMessage(TypeError, `Cannot set property 'foo' of ${description}`);
|
||||||
expect(() => {
|
expect(() => {
|
||||||
primitive[Symbol.hasInstance] = 123;
|
primitive[Symbol.hasInstance] = 123;
|
||||||
}).toThrowWithMessage(
|
}).toThrowWithMessage(
|
||||||
TypeError,
|
TypeError,
|
||||||
`Cannot set property 'Symbol(Symbol.hasInstance)' of ${primitive}`
|
`Cannot set property 'Symbol(Symbol.hasInstance)' of ${description}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
[null, undefined].forEach(primitive => {
|
|
||||||
expect(() => {
|
|
||||||
primitive.foo = "bar";
|
|
||||||
}).toThrowWithMessage(TypeError, `${primitive} cannot be converted to an object`);
|
|
||||||
expect(() => {
|
|
||||||
primitive[Symbol.hasInstance] = 123;
|
|
||||||
}).toThrowWithMessage(TypeError, `${primitive} cannot be converted to an object`);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue