1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-25 17:55:08 +00:00
Commit graph

2483 commits

Author SHA1 Message Date
Linus Groh
f1784c9c87 LibJS/Tests: Fix failing Array.prototype.toLocaleString() test 2021-11-17 10:00:20 +00:00
Timothy Flynn
39ab1a8999 LibJS: Implement ECMA-402 Array.prototype.toLocaleString
Turns out the only difference between our existing implementation and
the ECMA-402 implementation is we weren't passing the locales and
options list to each element.toLocaleString invocation.

This also adds spec comments to the definition.
2021-11-17 09:01:32 +00:00
Timothy Flynn
c19c3205ff LibJS: Implement ECMA-402 Number.prototype.toLocaleString 2021-11-17 09:01:32 +00:00
Andreas Kling
216e21a1fa AK: Convert AK::Format formatting helpers to returning ErrorOr<void>
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
2021-11-17 00:21:13 +01:00
Andreas Kling
587f9af960 AK: Make JSON parser return ErrorOr<JsonValue> (instead of Optional)
Also add slightly richer parse errors now that we can include a string
literal with returned errors.

This will allow us to use TRY() when working with JSON data.
2021-11-17 00:21:10 +01:00
Timothy Flynn
a1d5849e67 LibJS: Implement unit number formatting 2021-11-16 23:14:09 +00:00
Timothy Flynn
04b8b87c17 LibJS+LibUnicode: Support multiple identifiers within format pattern
This wasn't the case for compact patterns, but unit patterns can contain
multiple (up to 2, really) identifiers that must each be recognized by
LibJS.

Each generated NumberFormat object now stores an array of identifiers
parsed. The format pattern itself is encoded with the index into this
array for that identifier, e.g. the compact format string "0K" will
become "{number}{compactIdentifier:0}".
2021-11-16 23:14:09 +00:00
Timothy Flynn
3b68370212 LibJS+LibUnicode: Rename the generated compact_identifier to identifier
This field is currently used to store the StringView into the compact
name/symbol in the format string. Units will need to store a similar
field, so rename the field to be more generic, and extract the parser
for it.
2021-11-16 23:14:09 +00:00
Timothy Flynn
6d34a0b4e8 LibJS+LibUnicode: Rename method to select a NumberFormat plurality
Instead of currency pattern lookups within select_currency_unit_pattern,
rename the method to select_pattern_with_plurality and accept any list
of patterns. This method will be needed for units.
2021-11-16 23:14:09 +00:00
Linus Groh
6b2e004c28 LibJS: Fix incorrect use of "modulo" in {hour,min,sec,ms}_from_time()
These all would return incorrect results for negative time values.
Also adds a missing floor() in sec_from_time().
2021-11-16 19:40:49 +00:00
Linus Groh
58c6a156bf LibCrypto: Fix subtracting two negative SignedBigIntegers
Currently, we get the following results

    -1 - -2 = -1
    -2 - -1 =  1

Correct would be:

    -1 - -2 =  1
    -2 - -1 = -1

This was already attempted to be fixed in 7ed8970, but that change was
incorrect. This directly translates to LibJS BigInts having the same
incorrect behavior - it even was tested.
2021-11-16 10:06:53 +00:00
Luke Wilde
014840eeca LibJS: Use else-if's in Temporal.Duration.prototype.until
This is an editorial change in the Temporal spec.

See: 3dd2397
2021-11-16 09:10:41 +00:00
Luke Wilde
ac65fb40d9 LibJS: Implement Temporal.PlainDate.prototype.since 2021-11-16 01:06:07 +00:00
Luke Wilde
ddec3bc888 LibJS: Implement Temporal.PlainDate.prototype.until 2021-11-16 01:06:07 +00:00
Timothy Flynn
99c15741ba LibJS: Conditionally ignore [[UseGrouping]] in compact notation 2021-11-16 00:56:55 +00:00
Timothy Flynn
14aca03161 LibJS: Remove FIXME comment from PartitionNotationSubPattern AO
All possible patterns generated by LibUnicode are now handled. We have a
similar VERIFY_NOT_REACHED in PartitionNumberPattern.
2021-11-16 00:56:55 +00:00
Timothy Flynn
fdae323401 LibJS: Implement compact formatting for Intl.NumberFormat 2021-11-16 00:56:55 +00:00
Timothy Flynn
80b86d20dc LibJS: Cache the number format used for compact notation
Finding the best number format to use for compact notation involves
creating a Vector of all compact formats for the locale and looking for
the one that best matches the number's magnitude. ECMA-402 wants this
number format to be found multiple times, so cache the result for future
use.
2021-11-16 00:56:55 +00:00
Timothy Flynn
1f546476d5 LibJS+LibUnicode: Fix computation of compact pattern exponents
The compact scale of each formatting rule was precomputed in commit:
be69eae651

Using the formula: compact scale = magnitude - pattern scale

This computation was off-by-one.

For example, consider the format key "10000-count-one", which maps to
"00 thousand" in en-US. What we are really after is the exponent that
best represents the string "thousand" for values greater than 10000
and less than 100000 (the next format key). We were previously doing:

    log10(10000) - "00 thousand".count("0") = 2

Which clearly isn't what we want. Instead, if we do:

    log10(10000) + 1 - "00 thousand".count("0") = 3

We get the correct exponent for each format key for each locale.

This commit also renames the generated variable from "compact_scale" to
"exponent" to match the terminology used in ECMA-402.
2021-11-16 00:56:55 +00:00
Nico Weber
a164e6ecbb LibJS: Unbreak to_iso_day_of_week
481f7d6afa tried to use `modulo()` here, but missed that the
code used `<=` instead of `<`.

Keep using `modulo()` and add an explicit conditional, which is
arguably clearer.
2021-11-16 00:41:45 +00:00
Nico Weber
481f7d6afa LibJS: Use modulo() function in to_iso_day_of_week
No behavior change.
2021-11-15 23:54:41 +00:00
Linus Groh
a757f3f421 LibJS: Fix leap year check in to_iso_week_of_year() for week < 1
When the resulting week is in the previous year, we need to check if the
previous year is a leap year and can potentially have 53 weeks, instead
of the given year.
Also added a comment to briefly explain what's going on, as it took me a
while to figure out.
2021-11-15 21:33:26 +00:00
Linus Groh
42071f69cf LibJS: Fix balance_time() for times with negative offset day outcome
...and change the parameter types from i64 to double, as predicted by
a FIXME. The issue here is that integer division with a negative
dividend doesn't yield the same result as floating point division
wrapped in floor().
Additionally, the `days` variable needs to be signed.
2021-11-14 23:10:00 +00:00
Linus Groh
32c52e3511 LibJS: Add missing spaces in balance_iso_date() spec comments 2021-11-14 23:08:49 +00:00
Linus Groh
a3de9dcf95 LibJS: Fix incorrect use of "modulo" in balance_iso_year_month() 2021-11-14 23:08:40 +00:00
Timothy Flynn
4d79ab6866 LibJS: Implement engineering and scientific number formatting 2021-11-14 17:00:35 +00:00
Timothy Flynn
b019a7fe64 LibJS: Define the "name" property on the number format function
Also add a missing spec link.
2021-11-14 17:00:35 +00:00
Linus Groh
27d84bebd4 LibJS: Remove redundant exception checks from initialize_constructor()
define_direct_property() simply wraps storage_set(), which cannot throw.
2021-11-14 16:14:38 +00:00
Linus Groh
57de5056b6 LibJS: Convert push_execution_context() to ThrowCompletionOr 2021-11-14 16:14:38 +00:00
Linus Groh
7cdca08090 LibJS: Convert prepare_for_ordinary_call() to ThrowCompletionOr 2021-11-14 16:14:38 +00:00
Linus Groh
33ed87d642 LibJS: Convert TypedArray create() functions to ThrowCompletionOr 2021-11-14 16:14:38 +00:00
Linus Groh
878668efc9 LibJS: Call [[Reject]] in PromiseResolveThenableJob after abrupt then() 2021-11-14 15:27:46 +00:00
Linus Groh
194d90dc72 LibJS: Don't coerce this value to object in Promise.prototype.finally() 2021-11-14 15:27:46 +00:00
Linus Groh
53ec432e8d LibJS: Don't coerce this value to object in Promise.resolve() 2021-11-14 15:27:46 +00:00
Linus Groh
cd391aa8ef LibJS: Convert call_job_callback() to ThrowCompletionOr 2021-11-14 15:27:46 +00:00
Linus Groh
68ac13a192 LibJS: Add a Completion(ThrowCompletionOr<Value> const&) constructor 2021-11-14 15:27:46 +00:00
Linus Groh
01c2570678 LibJS: Annotate Promise implementation with spec comments
I wanted to do this for a long time. The guts of Promise are pretty
complex, and it's easier to understand with the spec right next to it.
Also found a couple of issues along the way :^)
2021-11-14 15:27:46 +00:00
Timothy Flynn
15c5fbd9e9 LibJS: Implement number grouping for Intl.NumberFormat
For example, in en-US, the number 123456 should be formatted as the
string "123,456". In en-IN, it should be formatted as "1,23,456".
2021-11-14 10:35:19 +00:00
Luke Wilde
f6ab63993a LibJS: Implement Temporal.ZonedDateTime.prototype.round 2021-11-13 19:48:54 +00:00
Timothy Flynn
3450def494 LibJS: Implement Intl.NumberFormat.prototype.formatToParts 2021-11-13 19:01:25 +00:00
Timothy Flynn
40973814e9 LibJS: Throw an exception in NumberFormat.prototype.format for BigInts
Rather than crashing in the call to as_double(), throw an exception for
now.
2021-11-13 19:01:25 +00:00
Timothy Flynn
c65dea64bd LibJS+LibUnicode: Don't remove {currency} keys in GetNumberFormatPattern
In order to implement Intl.NumberFormat.prototype.formatToParts, do not
replace {currency} keys in the format pattern before ECMA-402 tells us
to. Otherwise, the array return by formatToParts will not contain the
expected currency key.

Early replacement was done to avoid resolving the currency display more
than once, as it involves a couple of round trips to search through
LibUnicode data. So this adds a non-standard method to NumberFormat to
do this resolution and cache the result.

Another side effect of this change is that LibUnicode must replace unit
format patterns of the form "{0} {1}" during code generation. These were
previously skipped during code generation because LibJS would just
replace the keys with the currency display at runtime. But now that the
currency display injection is delayed, any {0} or {1} keys in the format
pattern will cause PartitionNumberPattern to abort.
2021-11-13 19:01:25 +00:00
Timothy Flynn
d872d030f1 LibJS: Avoid potential for dangling string views in partition patterns
There aren't any dangling views in as of yet, but a subsequent commit
will cause the "part" variable to be a view into an internally generated
string. Therefore, after returning from PartitionNumberPattern, that
view will be pointed at freed memory.

This commit is to set the precendence of not returning a view to "part".
2021-11-13 19:01:25 +00:00
Linus Groh
dbe70e7c55 LibJS: Implement Temporal.Duration.prototype.total() 2021-11-13 18:50:54 +00:00
Linus Groh
656efe5d6c LibJS: Fix days calculation in round_duration() for "year" - "day" units
This relies on floating point division, which is not possible with
LibCrypto bigints at the moment. So, instead of completely ignoring the
remainder we now first do a bigint division, then convert the remainder
to a double, and do another native floating point division to get the
final result.
2021-11-13 18:50:54 +00:00
Linus Groh
f11277b50d LibJS: Fix missing handling of "week" largest_unit in balance_duration()
It would crash because of VERIFY(largest_unit == "nanosecond"sv) in the
final else branch when passing "week", because it's not handled in any
of the previous branches.
2021-11-13 14:21:08 +00:00
Linus Groh
8c73d85a65 LibJS: Fix logic typo in round_duration() remainder calculation
For unit == "hour", the remainder would not return the difference
between fractional_hours and hours, but fractional_hours and days.
2021-11-13 13:33:00 +00:00
Linus Groh
f0cd727d74 LibJS: Fix logic typo in balance_duration() hours calculation
By using milliseconds_division_result instead of seconds_division_result
here, the result for hours was off by a factor of 60.
2021-11-13 13:32:35 +00:00
Timothy Flynn
a701ed52fc LibJS+LibUnicode: Fully implement currency number formatting
Currencies are a bit strange; the layout of currency data in the CLDR is
not particularly compatible with what ECMA-402 expects. For example, the
currency format in the "en" and "ar" locales for the Latin script are:

    en: "¤#,##0.00"
    ar: "¤\u00A0#,##0.00"

Note how the "ar" locale has a non-breaking space after the currency
symbol (¤), but "en" does not. This does not mean that this space will
appear in the "ar"-formatted string, nor does it mean that a space won't
appear in the "en"-formatted string. This is a runtime decision based on
the currency display chosen by the user ("$" vs. "USD" vs. "US dollar")
and other rules in the Unicode TR-35 spec.

ECMA-402 shies away from the nuances here with "implementation-defined"
steps. LibUnicode will store the data parsed from the CLDR however it is
presented; making decisions about spacing, etc. will occur at runtime
based on user input.
2021-11-13 11:52:45 +00:00
Timothy Flynn
39e031c4dd LibJS+LibUnicode: Generate all styles of currency localizations
Currently, LibUnicode is only parsing and generating the "long" style of
currency display names. However, the CLDR contains "short" and "narrow"
forms as well that need to be handled. Parse these, and update LibJS to
actually respect the "style" option provided by the user for displaying
currencies with Intl.DisplayNames.

Note: There are some discrepencies between the engines on how style is
handled. In particular, running:

new Intl.DisplayNames('en', {type:'currency', style:'narrow'}).of('usd')

Gives:

  SpiderMoney: "USD"
  V8: "US Dollar"
  LibJS: "$"

And running:

new Intl.DisplayNames('en', {type:'currency', style:'short'}).of('usd')

Gives:

  SpiderMonkey: "$"
  V8: "US Dollar"
  LibJS: "$"

My best guess is V8 isn't handling style, and just returning the long
form (which is what LibJS did before this commit). And SpiderMoney can
handle some styles, but if they don't have a value for the requested
style, they fall back to the canonicalized code passed into of().
2021-11-13 11:52:45 +00:00