For various statements the spec states:
Return NormalCompletion(empty).
In those cases we have been returning undefined so far, which is
incorrect.
In other cases it states:
Return Completion(UpdateEmpty(stmtCompletion, undefined)).
Which essentially means a statement is evaluated and its completion
value returned if non-empty, and undefined otherwise.
While not actually noticeable in normal scripts as the VM's "last value"
can't be accessed from JS code directly (with the exception of eval(),
see below), it provided an inconsistent experience in the REPL:
> if (true) 42;
42
> if (true) { 42; }
undefined
This also fixes the case where eval() would return undefined if the last
executed statement is not a value-producing one:
eval("1;;;;;")
eval("1;{}")
eval("1;var a;")
As a consequence of the changes outlined above, these now all correctly
return 1.
See https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation,
"NOTE 2".
Fixes#3609.
With one small exception, this is how we've been using this API already,
and it makes sense: a Program is just a ScopeNode with any number of
statements, which are executed one by one. There's no explicit return
value at the end, only a completion value of the last value-producing
statement, which we then access using VM::last_value() if needed (e.g.
in the REPL).
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)
Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.
We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.