The auto naming of function expressions is a purely syntactic
decision, so shouldn't be decided based on the dynamic type of
an assignment. This moves the decision making into the parser.
One icky hack is that we add a field to FunctionExpression to
indicate whether we can autoname. The real solution is to actually
generate a CompoundExpression node so that the parser can make
the correct decision, however this would have a potentially
significant run time cost.
This does not correct the behaviour for class expressions.
Patch from Anonymous.
Previously we would generate function names for anonymous functions
on every AssignmentExpression, even if we weren't assigning a function.
We were also setting names of anonymous functions in arrays, which is
apparently a SpiderMonkey specific behavior not supported by V8, JSC
or required by ECMA262. This patch removes that behavior.
This is a huge performance improvement on the CanvasCycle demo! :^)
This patch rethinks the way indexed property storage works:
Instead of having a cut-off point at 200 elements where we always move
to generic property storage, we now allow arrays to stay in simple mode
as long as we don't create a gap/hole larger than 200 elements.
We also simplify generic storage to only have a hash map (for now)
instead of juggling both a vector and a hash map. This is mostly fine
since the vast majority of arrays get to stay simple now.
This is a huge speedup on anything that uses basic JS arrays with more
than 200 elements in them. :^)
Otherwise we continuously lose the first sparse element (at index
SPARSE_ARRAY_THRESHOLD) without noticing, as we overwrite all indices
with the value at index+1.
Fixes#5884.
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.
https://tc39.es/ecma262/#sec-function.prototype.tostring - this is how
the spec wants us to do it. :^)
Also change the function name behaviour to only provide a name for
NativeFunctions, which matches other engines - presumably to not expose
Proxy objects, and to prevent "function bound foo() { [native code] }".
https://tc39.es/ecma262/#sec-properties-of-the-array-prototype-object
The Array prototype object: [...] is an Array exotic object and has the
internal methods specified for such objects.
NOTE: The Array prototype object is specified to be an Array exotic
object to ensure compatibility with ECMAScript code that was created
prior to the ECMAScript 2015 specification.
This was not implementing the following part of the spec correctly:
27. For each integer i such that i ≥ 1 and i ≤ n, do
a. Let captureI be ith element of r's captures List.
b. If captureI is undefined, let capturedValue be undefined.
Expecting a capture group match to exist for each of the RegExp's
capture groups would assert in Vector's operator[] if that's not the
case, for example:
/(foo)(bar)?/.exec("foo")
Append undefined instead.
Fixes#5256.
If we have a function as class extends value, we still cannot assume
that it has a prototype property and that property has a function or
null as its value - blindly calling to_object() on it may fail.
Fixes#5075.