Previously, certain crafted input could cause the JS parser to hang, as
it repeatedly tried to parse an EOF token after hitting an "invalid
destructuring assignment target" error. This change ensures that we
stop parsing after hitting this error condition.
We currently cannot parse the output of `toString` and `toUTCString`.
While the spec does not require such support, test262 expects it, and
all major engines support it.
https://cldr.unicode.org/index/downloads/cldr-44
Notable changes that affect us include:
* The Islamic Calendar is now localized as the Hijri Calender (in en-US)
but has not been updated for all locales. So this patch updates tests
where possible and removes a few test cases that currently cannot be
localized.
* The und locale has received more likely subtag data (the und locale is
basically a pseudo-locale meaning "undetermined").
* The exponential symbol in the Arabic number system was changed from
U+0627 to U+0623.
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.
In case of {get func() {}, set func() {}} we were wrongly setting the
function name to 'func' and then later trying to replace an empty name
with 'get func'/'set func' which failed.
Instead, set the name to 'get func'/'set func' right away.
The code in put_by_property_key is kept, for when that is called
by put_by_value.
The previous implementation was calling `backtrace()` for every
function call, which is quite slow.
Instead, this implementation provides VM::stack_trace() which unwinds
the native stack, maps it through NativeExecutable::get_source_range
and combines it with source ranges from interpreted call frames.
These are then restored upon `ContinuePendingUnwind`.
This stops us from forgetting where we needed to jump when we do extra
try-catches in finally blocks.
Co-Authored-By: Jesús "gsus" Lapastora <cyber.gsuscode@gmail.com>
As of https://tc39.es/ecma262/#sec-yearfromtime, YearFromTime(t) should
return `y` such that `TimeFromYear(YearFromTime(t)) <= t`. This wasn't
held, since the approximation contained decimal digits that would nudge
the final value in the wrong direction.
Adapted from Kiesel:
6548a85743
Co-authored-by: Linus Groh <mail@linusgroh.de>
The spec asks us to perform some calculations that quickly exceed an
`u64`, but instead of jumping through hoops we can rely on our AK
implementation of floating point formatting to come up with the
correctly rounded result.
Note that most other JS engines seem to diverge from the spec as well
and fall back to a generic dtoa path.
For example, the locale "fr-FR" will have the preferred hour cycle list
of "H hB", meaning h23 and h12-with-day-periods. Whether date-times are
actually formatted with day-periods is up to the user, but we need to
parse the hour cycle as h12 to know that the FR region supports h12.
This bug was revealed by LibJS no longer blindly falling back to h12 (if
the `hour12` option is true) or h24 (if the `hour12` option is false).
These are normative changes in the ECMA-402 spec. See:
896ffccaf4ec46e25c455
(This combines the above commits into one patch as they each do not work
on their own).
This change makes LibJS correctly report a syntax error when a unary
expression is followed by exponentiation, as the spec requires.
Apparently this is due to that expression being ambiguous ordering.
Strangely this check does not seem to apply in the same way for '++' and
'--' for reasons that I don't fully understand. For example
```
let x = 5;
++x ** 2
```
Since `--5` and `++5` on it's own results in a syntax error anyway, it
seems we do not need to perform this exponentiation check in those
places.
Diff Tests:
+6 ✅ -6 ❌
Our implementation of environment.CreateImmutableBinding(name, true)
in this AO was not correctly initializing const variables in strict
mode. This would mean that constant declarations in for loop bodies
would not throw if they were modified.
To fix this, add a new parameter to CreateVariable to set strict mode.
Also remove the vm.is_strict mode check here, as it doesn't look like
anywhere in the spec will change strict mode depending on whether the
script itself is running in script mode or not.
This fixes two of our test-js tests, no change to test262.
We were translating the pattern [\⪾-\⫀] to [\\u2abe-\\u2ac0], which
is a very different pattern; as a code unit converted to the \uhhh
format has no meaning when escaped, this commit makes us simply skip
escaping it when translating the pattern.
When formatting a currency style pattern with compact notation, we were
(trying to) doubly insert the currency symbol into the formatted string.
We would first look up the currency pattern in GetNumberFormatPattern
(for the en locale, this is "¤#,##0.00", which our generator transforms
to "{currency}{number}").
When we hit the "{number}" field, NumberFormat will do a second lookup
for the compact pattern to use for the number being formatted. By using
the currency compact patterns, we receive a second pattern that also has
the currency symbol (for the en locale, if formatting the number 1000,
this is "¤0K", which our generator transforms to
"{currency}{number}{compactIdentifier:0}". This second lookup is not
supposed to have currency symbols (or any other symbols), thus we hit a
VERIFY_NOT_REACHED().
Instead, we are meant to use the decimal compact pattern, and allow the
currency symbol to be handled by only the outer currency pattern.
This works by adding source start/end offset to every bytecode
instruction. In the future we can make this more efficient by keeping
a map of bytecode ranges to source ranges in the Executable instead,
but let's just get traces working first.
Co-Authored-By: Andrew Kaster <akaster@serenityos.org>
This is not we're supposed to do according to https://tc39.es/ecma262/#sec-runtime-semantics-propertydefinitionevaluation
Furthermore, this was observable by ToPrimitive looking up toString and
valueOf and potentially calling them if they exist. The big ticket
issue however is that for objects without toString and valueOf, such as
null-proto objects, this would unexpectedly throw.
When a substitution refers to a 2-digit capture group that doesn't exist
we need to check if the first digit refers to an existing capture group.
In other words, '$10' should be treated as capture group #1, followed by
the literal '0' if 1 is a valid capture group but 10 is not.
This makes the Dromaeo "dom-query" subtest run to completion.
This is a normative change in the array from async proposal, see:
49cfde2
It fixes a double construction when Array.fromAsync is given an array
like object.
When determining the precedence of the + and - operators, the parser
always returned the precedence using these operators in a binary
expression (lower than division!). The context of whether the operator
is used in a unary or binary expression must be taken into account.
The first test crashes in AST, and fails in bytecode, so the best thing
which we can do here without complicated test setup logic is to just
skip this test for now. Interestinglny, this crashing test is very
similar to the existing thenable test case, and only differs in the way
that the thenable is given to the async function.
The next two tests are effectively the same as the above two mentioned
tests, with the only different being that the thenable calls the fulfill
function. For the test case that crashes in AST mode, doing that appears
to fix the test case for AST mode (but both still fail in bytecode).
To allow us to add tests that are failing now, but can be enabled as
soon as a change is made to make it pass (without any opportunity to
forget about enabling it).
Additionally, support is added for `xfailIf`, for tests that are
expected to fail given a certain condition, but are expected to pass
otherwise. This is intended to be used for tests that fail in bytecode
mode, but pass in AST (and vice versa).
This fixes an issue where returning inside a `try` block and then
calling a function inside `finally` would clobber the saved return
value from the `try` block.
Note that we didn't need to change the base of register allocation,
since it was already 1 too high.
With this fixed, https://microsoft.com/edge loads in bytecode mode. :^)
Thanks to Luke for reducing the issue!
The Heap::uproot_cell() API was used to implement markAsGarbage() which
was used in 3 tests to forcibly destroy a value, even if it had
references on the stack or elsewhere.
This patch rewrites the 3 tests that used this mechanism to be
structured in a way that allows garbage collection to collect the values
as intended without hacks. And now that the uprooting mechanism is no
longer needed, it's uprooted as well.
This fixes 3 test-js tests in bytecode mode. :^)