LibJS: Improve UpdateExpression::execute()

- Let undefined variables throw a ReferenceError by using
  Identifier::execute() rather than doing variable lookup manually and
  ASSERT()ing
- Coerce value to number rather than ASSERT()ing
- Make code DRY
- Add tests
This commit is contained in:
Linus Groh 2020-04-21 23:27:11 +01:00 committed by Andreas Kling
parent b2305cb67d
commit a1b820b11c
Notes: sideshowbarker 2024-07-19 07:23:45 +09:00
2 changed files with 63 additions and 11 deletions

View file

@ -775,11 +775,10 @@ Value UpdateExpression::execute(Interpreter& interpreter) const
{
ASSERT(m_argument->is_identifier());
auto name = static_cast<const Identifier&>(*m_argument).string();
auto previous_variable = interpreter.get_variable(name);
ASSERT(previous_variable.has_value());
auto previous_value = previous_variable.value();
ASSERT(previous_value.is_number());
auto old_value = m_argument->execute(interpreter);
if (interpreter.exception())
return {};
old_value = old_value.to_number();
int op_result = 0;
switch (m_op) {
@ -789,14 +788,13 @@ Value UpdateExpression::execute(Interpreter& interpreter) const
case UpdateOp::Decrement:
op_result = -1;
break;
default:
ASSERT_NOT_REACHED();
}
interpreter.set_variable(name, Value(previous_value.as_double() + op_result));
if (m_prefixed)
return JS::Value(previous_value.as_double() + op_result);
return previous_value;
auto new_value = Value(old_value.as_double() + op_result);
interpreter.set_variable(name, new_value);
return m_prefixed ? new_value : old_value;
}
void AssignmentExpression::dump(int indent) const

View file

@ -0,0 +1,54 @@
load("test-common.js");
try {
assertThrowsError(() => {
++x;
}, {
error: ReferenceError,
message: "'x' not known"
});
var n = 0;
assert(++n === 1);
assert(n === 1);
var n = 0;
assert(n++ === 0);
assert(n === 1);
var n = 0;
assert(--n === -1);
assert(n === -1);
var n = 0;
assert(n-- === 0);
assert(n === -1);
var a = [];
assert(a++ === 0);
assert(a === 1);
var b = true;
assert(b-- === 1);
assert(b === 0);
var s = "foo";
assert(isNaN(++s));
assert(isNaN(s));
var s = "foo";
assert(isNaN(s++));
assert(isNaN(s));
var s = "foo";
assert(isNaN(--s));
assert(isNaN(s));
var s = "foo";
assert(isNaN(s--));
assert(isNaN(s));
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}