summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2020-04-21 23:27:11 +0100
committerAndreas Kling <kling@serenityos.org>2020-04-22 13:09:59 +0200
commita1b820b11ca5f8c4134972de82f85b0f00fd6127 (patch)
treedfd62bb8ed6c4bf5f0597eaed482bd4717ce5e01
parentb2305cb67db98bc658a4eaca7f3d97f5ecdcd2ed (diff)
downloadserenity-a1b820b11ca5f8c4134972de82f85b0f00fd6127.zip
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
-rw-r--r--Libraries/LibJS/AST.cpp20
-rw-r--r--Libraries/LibJS/Tests/update-expressions-basic.js54
2 files changed, 63 insertions, 11 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp
index 686fde556b..ed8e790df2 100644
--- a/Libraries/LibJS/AST.cpp
+++ b/Libraries/LibJS/AST.cpp
@@ -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
diff --git a/Libraries/LibJS/Tests/update-expressions-basic.js b/Libraries/LibJS/Tests/update-expressions-basic.js
new file mode 100644
index 0000000000..17e887ed46
--- /dev/null
+++ b/Libraries/LibJS/Tests/update-expressions-basic.js
@@ -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);
+}