diff --git a/Cargo.lock b/Cargo.lock index 4afd8aa15e..c6ab9477d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,13 +30,14 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -143,13 +144,26 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-channel" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" +dependencies = [ + "concurrent-queue", + "event-listener 3.1.0", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-executor" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" dependencies = [ - "async-lock", + "async-lock 2.8.0", "async-task", "concurrent-queue", "fastrand 2.0.1", @@ -163,7 +177,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "blocking", "futures-lite 1.13.0", @@ -175,20 +189,40 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", "futures-lite 1.13.0", "log", "parking", - "polling", - "rustix 0.37.26", + "polling 2.8.0", + "rustix 0.37.27", "slab", "socket2", "waker-fn", ] +[[package]] +name = "async-io" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997" +dependencies = [ + "async-lock 3.1.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.0.1", + "parking", + "polling 3.3.0", + "rustix 0.38.24", + "slab", + "tracing", + "waker-fn", + "windows-sys 0.48.0", +] + [[package]] name = "async-lock" version = "2.8.0" @@ -198,13 +232,24 @@ dependencies = [ "event-listener 2.5.3", ] +[[package]] +name = "async-lock" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb2ab2aa8a746e221ab826c73f48bc6ba41be6763f0855cb249eb6d154cf1d7" +dependencies = [ + "event-listener 3.1.0", + "event-listener-strategy", + "pin-project-lite", +] + [[package]] name = "async-net" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" dependencies = [ - "async-io", + "async-io 1.13.0", "blocking", "futures-lite 1.13.0", ] @@ -215,30 +260,30 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-signal", "blocking", "cfg-if", - "event-listener 3.0.0", + "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.20", + "rustix 0.38.24", "windows-sys 0.48.0", ] [[package]] name = "async-signal" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2a5415b7abcdc9cd7d63d6badba5288b2ca017e3fbd4173b8f405449f1a2399" +checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io", - "async-lock", + "async-io 2.2.0", + "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.20", + "rustix 0.38.24", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -294,15 +339,15 @@ checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "basic-toml" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" +checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778" dependencies = [ "serde", ] @@ -336,16 +381,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.1.0", + "async-lock 3.1.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 1.13.0", + "futures-lite 2.0.1", "piper", "tracing", ] @@ -480,6 +525,7 @@ name = "boa_icu_provider" version = "0.17.0" dependencies = [ "icu_datagen", + "icu_plurals", "icu_provider", "icu_provider_adapters", "icu_provider_blob", @@ -1064,21 +1110,20 @@ dependencies = [ [[package]] name = "databake" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "959b676312ba1aaafb2219c475560082e6b20c3bc572ec1483f93cecd748cf3d" +checksum = "82175d72e69414ceafbe2b49686794d3a8bed846e0d50267355f83ea8fdd953a" dependencies = [ "databake-derive", "proc-macro2", "quote", - "syn 2.0.39", ] [[package]] name = "databake-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0694dfe255f1af0289d3d1b40787bb955e8603d96e96a6b14b225926e108fb" +checksum = "377af281d8f23663862a7c84623bc5dcf7f8c44b13c7496a590bdc157f941a43" dependencies = [ "proc-macro2", "quote", @@ -1259,9 +1304,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1285,15 +1330,25 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +dependencies = [ + "event-listener 3.1.0", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.8" @@ -1338,15 +1393,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" dependencies = [ "cfg-if", - "rustix 0.38.20", + "rustix 0.38.24", "windows-sys 0.48.0", ] [[package]] name = "fixed_decimal" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5287d527037d0f35c8801880361eb38bb9bce194805350052c2a79538388faeb" +checksum = "cbc7fdec9d7f6671a3ebb3282c969962aba67c49f6abac5311959b65cafabc10" dependencies = [ "displaydoc", "ryu", @@ -1388,6 +1443,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fraction" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a78dd758a47a7305478e0e054f9fde4e983b9f9eccda162bf7ca03b79e9d40" +dependencies = [ + "num", +] + [[package]] name = "funty" version = "2.0.0" @@ -1402,9 +1466,9 @@ checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1541,7 +1605,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", ] [[package]] @@ -1550,7 +1614,7 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.6", ] [[package]] @@ -1599,9 +1663,9 @@ dependencies = [ [[package]] name = "icu_calendar" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b520c5675775e3838447c33fc55bf558148c6824ef0d20ff7a9e0df7345a281c" +checksum = "7eb932a690c92f87955e923106181ee0d5682e688ff37fb5c7b296e1fe806edb" dependencies = [ "calendrical_calculations", "databake", @@ -1616,9 +1680,9 @@ dependencies = [ [[package]] name = "icu_casemap" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976068d7759293cbd9daa0d1669618bb9094c7ee54e546cd8b877dd4fe59007a" +checksum = "7988d4f2655012592ac5b027722a93fbe12ff2a86d3e0f9ae686aedba0984f5e" dependencies = [ "databake", "displaydoc", @@ -1633,9 +1697,9 @@ dependencies = [ [[package]] name = "icu_codepointtrie_builder" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872a3fcc14248bb28572e1340fc23c14c0bcc083d1660743a76c4121e7fcb859" +checksum = "6030944910d61b4d2832e89b866f5f7961c22c70a73c9aeccffe57eaa3707418" dependencies = [ "icu_collections", "once_cell", @@ -1646,9 +1710,9 @@ dependencies = [ [[package]] name = "icu_collator" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be493c81154545a00fc5196e814cae0e1470bc696d518b5df877049aa6bcefe1" +checksum = "8a2a45056e541cffde068f5c81ac1c0503b9ee2a4b967546422e509c5c653750" dependencies = [ "databake", "displaydoc", @@ -1666,9 +1730,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3907b2246e8dd5a29ead8a965e7c0c8a90e9b928e614a4279257d45c5e553e91" +checksum = "137d96353afc8544d437e8a99eceb10ab291352699573b0de5b08bda38c78c60" dependencies = [ "databake", "displaydoc", @@ -1680,12 +1744,14 @@ dependencies = [ [[package]] name = "icu_datagen" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212acb6e6f3793755dbd6785e95c0fa5048c43a44e817154cdfb909f72afb57d" +checksum = "35e2d9466b2860a0c23132001e774589624c264e48b98d14382d71805404d56a" dependencies = [ "displaydoc", + "either", "elsa", + "fraction", "icu_calendar", "icu_casemap", "icu_codepointtrie_builder", @@ -1707,6 +1773,7 @@ dependencies = [ "log", "memchr", "ndarray", + "num-bigint", "once_cell", "serde", "serde-aux", @@ -1723,9 +1790,9 @@ dependencies = [ [[package]] name = "icu_datetime" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5bf2e6dd961b59ee5935070220915db6cf0ab5137de362964f800c2b7d14fa" +checksum = "1508c7ed627cc0b031c81203eb98f34433e24b32b39d5b2c0238e4962a00957d" dependencies = [ "databake", "displaydoc", @@ -1747,9 +1814,9 @@ dependencies = [ [[package]] name = "icu_decimal" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1986a0b7df834aaddb911b4593c990950ac5606fc83ce9aad4311be80f51e81a" +checksum = "dcf994f9ed8061c17bb313f28fba6cffc736f0a16c7fab827efc9b73fd3f7778" dependencies = [ "databake", "displaydoc", @@ -1762,9 +1829,9 @@ dependencies = [ [[package]] name = "icu_list" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1a44bbed77a7e7b555f9d7dd4b43f75ec1402b438a901d20451943d50cbd90" +checksum = "fe6c04ec71ad1bacdbfb47164d4801f80a0533d9340f94f1a880f521eff59f54" dependencies = [ "databake", "deduplicating_array", @@ -1777,9 +1844,9 @@ dependencies = [ [[package]] name = "icu_locid" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f284eb342dc49d3e9d9f3b188489d76b5d22dfb1d1a5e0d1941811253bac625c" +checksum = "5c0aa2536adc14c07e2a521e95512b75ed8ef832f0fdf9299d4a0a45d2be2a9d" dependencies = [ "databake", "displaydoc", @@ -1792,9 +1859,9 @@ dependencies = [ [[package]] name = "icu_locid_transform" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6551daf80882d8e68eee186cc19e132d8bde1b1f059a79b93384a5ca0e8fc5e7" +checksum = "57c17d8f6524fdca4471101dd71f0a132eb6382b5d6d7f2970441cb25f6f435a" dependencies = [ "databake", "displaydoc", @@ -1808,15 +1875,15 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a741eba5431f75eb2f1f9022d3cffabcadda6771e54fb4e77c8ba8653e4da44" +checksum = "545c6c3e8bf9580e2dafee8de6f9ec14826aaf359787789c7724f1f85f47d3dc" [[package]] name = "icu_normalizer" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080fc33a720d50a7342b0c58df010fbcfb842d6f78ef81555f8b1ac6bba57d3c" +checksum = "419a6ef743237a64c37619def388b13f6266318a24652dff91ca046a7c4afc40" dependencies = [ "databake", "displaydoc", @@ -1834,15 +1901,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d22f74066c2e6442db2a9aa14950278e86719e811e304e48bae03094b369d" +checksum = "22026918a80e6a9a330cb01b60f950e2b4e5284c59528fd0c6150076ef4c8522" [[package]] name = "icu_plurals" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20556516b8be2b2f5dc3d6b23884b65c5c59ed8be0b44c419e4808c9b0792fce" +checksum = "37d807b123eb2a9ae8f12080fb8cce479f5c8a761fba0bb5ab52da6dd5e31a03" dependencies = [ "databake", "displaydoc", @@ -1855,9 +1922,9 @@ dependencies = [ [[package]] name = "icu_properties" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3477ae70f8ca8dc08ff7574b5398ed0a2f2e4e6b66bdff2558a92ed67e262be1" +checksum = "976e296217453af983efa25f287a4c1da04b9a63bf1ed63719455068e4453eb5" dependencies = [ "databake", "displaydoc", @@ -1872,15 +1939,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c8bb3b67a8347e94d580434369e5c7ee89999b9309d04b7cfc88dfaa0f31b59" +checksum = "f6a86c0e384532b06b6c104814f9c1b13bcd5b64409001c0d05713a1f3529d99" [[package]] name = "icu_provider" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68acdef80034b5e35d8524e9817479d389a4f9774f3f0cbe1bf3884d80fd5934" +checksum = "ba58e782287eb6950247abbf11719f83f5d4e4a5c1f2cd490d30a334bc47c2f4" dependencies = [ "databake", "displaydoc", @@ -1900,9 +1967,9 @@ dependencies = [ [[package]] name = "icu_provider_adapters" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36b380ef2d3d93b015cd0563d7e0d005cc07f82a5503716dbc191798d0079e1d" +checksum = "a229f978260da7c3aabb68cb7dc7316589936680570fe55e50fdd3f97711a4dd" dependencies = [ "icu_locid", "icu_locid_transform", @@ -1914,23 +1981,24 @@ dependencies = [ [[package]] name = "icu_provider_blob" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31326d28c7f95a964a4f0ee86c24002da5f6db907e3bcb079949b4ff103b6a9" +checksum = "4a7202cddda672db167c6352719959e9b01cb1ca576d32fa79103f61b5a73601" dependencies = [ "icu_provider", "log", "postcard", "serde", "writeable", + "zerotrie", "zerovec", ] [[package]] name = "icu_provider_macros" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2060258edfcfe32ca7058849bf0f146cb5c59aadbedf480333c0d0002f97bc99" +checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" dependencies = [ "proc-macro2", "quote", @@ -1939,9 +2007,9 @@ dependencies = [ [[package]] name = "icu_segmenter" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb3c1981ce2187a745f391a741cb14e77453325acb3b2e014b05da51c0a39f2" +checksum = "b2dc1e8f4ba33a6a4956770ac5c08570f255d6605519fb3a859a0c0a270a2f8f" dependencies = [ "core_maths", "databake", @@ -1956,9 +2024,9 @@ dependencies = [ [[package]] name = "icu_timezone" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e6401cd210ccda98b2e7fc707831b29c6efe319efbbec460f957b6f331f626" +checksum = "b35aabe571a7c653c0f543ff1512b8a1b2ad481cfa24b3d25115298d2ff3b50f" dependencies = [ "databake", "displaydoc", @@ -2056,7 +2124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.20", + "rustix 0.38.24", "windows-sys 0.48.0", ] @@ -2106,9 +2174,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -2127,9 +2195,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -2155,15 +2223,15 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "litemap" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2647d5b7134127971a6de0d533c49de2159167e7f259c427195f87168a1" +checksum = "f9d642685b028806386b2b6e75685faadd3eb65a85fff7df711ce18446a422da" dependencies = [ "serde", ] @@ -2338,6 +2406,19 @@ dependencies = [ "libc", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.4" @@ -2370,6 +2451,28 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -2646,6 +2749,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite", + "rustix 0.38.24", + "tracing", + "windows-sys 0.48.0", +] + [[package]] name = "pollster" version = "0.3.0" @@ -2683,12 +2800,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "toml_edit 0.20.7", ] [[package]] @@ -2840,15 +2956,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2936,17 +3043,16 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", + "getrandom", "libc", - "once_cell", "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -3000,9 +3106,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.26" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f3f8f960ed3b5a59055428714943298bf3fa2d4a1d53135084e0544829d995" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", @@ -3014,22 +3120,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" dependencies = [ "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.10", + "linux-raw-sys 0.4.11", "windows-sys 0.48.0", ] [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", "ring", @@ -3039,9 +3145,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ "ring", "untrusted", @@ -3117,9 +3223,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", "untrusted", @@ -3297,9 +3403,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" dependencies = [ "serde", ] @@ -3316,11 +3422,11 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-fs", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-net", "async-process", "blocking", @@ -3329,9 +3435,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -3339,9 +3445,9 @@ dependencies = [ [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "sptr" @@ -3517,22 +3623,22 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.3.5", - "rustix 0.38.20", + "redox_syscall 0.4.1", + "rustix 0.38.24", "windows-sys 0.48.0", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -3661,9 +3767,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0e245e80bdc9b4e5356fc45a72184abbc3861992603f515270e9340f5a219" +checksum = "83c02bf3c538ab32ba913408224323915f4ef9a6d61c0e85d493f355921c0ece" dependencies = [ "databake", "displaydoc", @@ -3728,9 +3834,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap 2.1.0", "toml_datetime", @@ -3795,9 +3901,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "sharded-slab", "thread_local", @@ -3882,9 +3988,9 @@ checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" @@ -4303,9 +4409,9 @@ checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -4336,7 +4442,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.20", + "rustix 0.38.24", ] [[package]] @@ -4547,9 +4653,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.17" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -4562,9 +4668,9 @@ checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" [[package]] name = "writeable" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0af0c3d13faebf8dda0b5256fa7096a2d5ccb662f7b9f54a40fe201077ab1c2" +checksum = "dad7bb64b8ef9c0aa27b6da38b452b0ee9fd82beaf276a87dd796fb55cbae14e" [[package]] name = "wyz" @@ -4577,9 +4683,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e38c508604d6bbbd292dadb3c02559aa7fff6b654a078a36217cad871636e4" +checksum = "65e71b2e4f287f467794c671e2b8f8a5f3716b3c829079a1c44740148eff07e4" dependencies = [ "serde", "stable_deref_trait", @@ -4589,9 +4695,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e19fb6ed40002bab5403ffa37e53e0e56f914a4450c8765f533018db1db35f" +checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8" dependencies = [ "proc-macro2", "quote", @@ -4599,6 +4705,26 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "zerofrom" version = "0.1.3" @@ -4622,9 +4748,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9685bb4deb98dab812e87c296a9631fc00d7ca4bc5c2c5f304f375bbed711a8a" +checksum = "d0594125a0574fb93059c92c588ab209cc036a23d1baeb3410fa9181bea551a0" dependencies = [ "databake", "displaydoc", @@ -4637,9 +4763,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1194130c5b155bf8ae50ab16c86ab758cd695cf9ad176d2f870b744cbdbb572e" +checksum = "eff4439ae91fb5c72b8abc12f3f2dbf51bd27e6eadb9f8a5bc8898dddb0e27ea" dependencies = [ "databake", "serde", @@ -4650,9 +4776,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acabf549809064225ff8878baedc4ce3732ac3b07e7c7ce6e5c2ccdbc485c324" +checksum = "7b4e5997cbf58990550ef1f0e5124a05e47e1ebd33a84af25739be6031a62c20" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index d79e7b4014..ead4e6dfca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,24 +66,25 @@ thin-vec = "0.2.12" # ICU4X -icu_provider = { version = "~1.3.1", default-features = false } -icu_locid = { version = "~1.3.2", default-features = false } -icu_locid_transform = { version = "~1.3.1", default-features = false } -icu_datetime = { version = "~1.3.2", default-features = false } -icu_calendar = { version = "~1.3.2", default-features = false } -icu_collator = { version = "~1.3.3", default-features = false } -icu_plurals = { version = "~1.3.0", default-features = false } -icu_list = { version = "~1.3.2", default-features = false } -icu_casemap = { version = "~1.3.2", default-features = false } -icu_segmenter = { version = "~1.3.2", default-features = false } -icu_datagen = { version = "~1.3.3", default-features = false } -icu_provider_adapters = { version = "~1.3.0", default-features = false } -icu_provider_blob = { version = "~1.3.2", default-features = false } -icu_properties = { version = "~1.3.0", default-features = true } -writeable = "~0.5.3" -yoke = "~0.7.2" +icu_provider = { version = "~1.4.0", default-features = false } +icu_locid = { version = "~1.4.0", default-features = false } +icu_locid_transform = { version = "~1.4.0", default-features = false } +icu_datetime = { version = "~1.4.0", default-features = false } +icu_calendar = { version = "~1.4.0", default-features = false } +icu_collator = { version = "~1.4.0", default-features = false } +icu_plurals = { version = "~1.4.0", default-features = false } +icu_list = { version = "~1.4.0", default-features = false } +icu_casemap = { version = "~1.4.0", default-features = false } +icu_segmenter = { version = "~1.4.0", default-features = false } +icu_datagen = { version = "~1.4.0", default-features = false } +icu_provider_adapters = { version = "~1.4.0", default-features = false } +icu_provider_blob = { version = "~1.4.0", default-features = false } +icu_properties = { version = "~1.4.0", default-features = true } +icu_normalizer = { version = "~1.4.0", default-features = true } +writeable = "~0.5.4" +yoke = "~0.7.3" zerofrom = "~0.1.3" -fixed_decimal = "~0.5.4" +fixed_decimal = "~0.5.5" [workspace.metadata.workspaces] allow_branch = "main" diff --git a/boa_engine/Cargo.toml b/boa_engine/Cargo.toml index 4052c8cf32..288238c909 100644 --- a/boa_engine/Cargo.toml +++ b/boa_engine/Cargo.toml @@ -85,7 +85,7 @@ num_enum = "0.7.1" pollster.workspace = true thin-vec.workspace = true itertools = { version = "0.12.0", default-features = false } -icu_normalizer = "~1.3.0" +icu_normalizer.workspace = true paste = "1.0" portable-atomic = "1.5.1" bytemuck = { version = "1.14.0", features = ["derive"] } @@ -102,14 +102,14 @@ icu_locid_transform = { workspace = true, default-features = false, features = [ icu_datetime = { workspace = true, default-features = false, features = ["serde", "experimental"], optional = true } icu_calendar = { workspace = true, default-features = false, optional = true } icu_collator = { workspace = true, default-features = false, features = ["serde"], optional = true } -icu_plurals = { workspace = true, default-features = false, features = ["serde"], optional = true } +icu_plurals = { workspace = true, default-features = false, features = ["serde", "experimental"], optional = true } icu_list = { workspace = true, default-features = false, features = ["serde"], optional = true } icu_casemap = { workspace = true, default-features = false, features = ["serde"], optional = true} icu_segmenter = { workspace = true, default-features = false, features = ["auto", "serde"], optional = true } writeable = { workspace = true, optional = true } yoke = { workspace = true, optional = true } zerofrom = { workspace = true, optional = true } -fixed_decimal = { workspace = true, features = ["ryu"], optional = true} +fixed_decimal = { workspace = true, features = ["ryu", "experimental"], optional = true} hashbrown.workspace = true [target.'cfg(all(target_family = "wasm", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies] diff --git a/boa_engine/src/builtins/intl/locale/utils.rs b/boa_engine/src/builtins/intl/locale/utils.rs index 8b3d46cdb0..1f76a9eb16 100644 --- a/boa_engine/src/builtins/intl/locale/utils.rs +++ b/boa_engine/src/builtins/intl/locale/utils.rs @@ -325,6 +325,8 @@ where // extension sequences removed. let mut locale = locale.clone(); let id = std::mem::take(&mut locale.id); + locale.extensions.transform.clear(); + locale.extensions.private.clear(); // b. Let availableLocale be ! BestAvailableLocale(availableLocales, noExtensionsLocale). let available_locale = best_available_locale::(id, icu.provider()); @@ -371,6 +373,8 @@ where })) { let id = std::mem::take(&mut locale.id); + locale.extensions.transform.clear(); + locale.extensions.private.clear(); if let Some(available) = best_locale_for_provider(id, icu.provider()) { locale.id = available; diff --git a/boa_engine/src/builtins/intl/number_format/options.rs b/boa_engine/src/builtins/intl/number_format/options.rs index 04f3ed2010..c3dfb8dba6 100644 --- a/boa_engine/src/builtins/intl/number_format/options.rs +++ b/boa_engine/src/builtins/intl/number_format/options.rs @@ -2,10 +2,12 @@ use std::fmt; use crate::builtins::options::{ParsableOptionType, RoundingMode}; +use super::RoundingIncrement; + #[derive(Debug)] pub(crate) struct DigitFormatOptions { pub(crate) minimum_integer_digits: u8, - pub(crate) rounding_increment: u16, + pub(crate) rounding_increment: RoundingIncrement, pub(crate) rounding_mode: RoundingMode, pub(crate) trailing_zero_display: TrailingZeroDisplay, pub(crate) rounding_type: RoundingType, diff --git a/boa_engine/src/builtins/intl/number_format/utils.rs b/boa_engine/src/builtins/intl/number_format/utils.rs index 7dd82927bd..ff5f4c265f 100644 --- a/boa_engine/src/builtins/intl/number_format/utils.rs +++ b/boa_engine/src/builtins/intl/number_format/utils.rs @@ -1,5 +1,5 @@ use boa_macros::utf16; -use fixed_decimal::{FixedDecimal, FloatPrecision}; +use fixed_decimal::{FixedDecimal, FloatPrecision, RoundingIncrement as BaseMultiple}; use crate::{ builtins::{ @@ -14,6 +14,76 @@ use crate::{ use super::{DigitFormatOptions, Notation, RoundingPriority}; +/// The increment of a rounding operation. +/// +/// This differs from [`fixed_decimal::RoundingIncrement`] because ECMA402 accepts +/// several more increments than `fixed_decimal`, but all increments can be decomposed +/// into the target multiple and the magnitude offset. +/// +/// For example, rounding the number `0.02456` to the increment 200 at position +/// -3 is equivalent to rounding the same number to the increment 2 at position -1, and adding +/// trailing zeroes. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub(crate) struct RoundingIncrement { + multiple: BaseMultiple, + // INVARIANT: can only be 0, 1, 2, or 3 + magnitude_offset: u8, +} + +impl RoundingIncrement { + /// Creates a `RoundingIncrement` from the numeric value of the increment. + fn from_u16(increment: u16) -> Option { + let mut offset = 0u8; + let multiple = loop { + let rem = increment % 10u16.checked_pow(u32::from(offset + 1))?; + + if rem != 0 { + break increment / 10u16.pow(u32::from(offset)); + } + + offset += 1; + }; + + if offset > 3 { + return None; + } + + let multiple = match multiple { + 1 => BaseMultiple::MultiplesOf1, + 2 => BaseMultiple::MultiplesOf2, + 5 => BaseMultiple::MultiplesOf5, + 25 => BaseMultiple::MultiplesOf25, + _ => return None, + }; + + Some(RoundingIncrement { + multiple, + magnitude_offset: offset, + }) + } + + /// Gets the numeric value of this `RoundingIncrement`. + pub(crate) fn to_u16(self) -> u16 { + u16::from(self.magnitude_offset + 1) + * match self.multiple { + BaseMultiple::MultiplesOf1 => 1, + BaseMultiple::MultiplesOf2 => 2, + BaseMultiple::MultiplesOf5 => 5, + BaseMultiple::MultiplesOf25 => 25, + _ => { + debug_assert!(false, "base multiples can only be 1, 2, 5, or 25"); + 1 + } + } + } + + /// Gets the magnitude offset that needs to be added to the rounding position + /// for this rounding increment. + fn magnitude_offset(self) -> i16 { + i16::from(self.magnitude_offset) + } +} + /// Abstract operation [`SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault, notation )`][spec]. /// /// Gets the digit format options of the number formatter from the options object and the requested notation. @@ -26,10 +96,6 @@ pub(crate) fn get_digit_format_options( notation: Notation, context: &mut Context, ) -> JsResult { - const VALID_ROUNDING_INCREMENTS: [u16; 15] = [ - 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000, - ]; - // 1. Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1). let minimum_integer_digits = get_number_option(options, utf16!("minimumIntegerDigits"), 1, 21, context)?.unwrap_or(1); @@ -51,11 +117,9 @@ pub(crate) fn get_digit_format_options( let rounding_increment = get_number_option(options, utf16!("roundingIncrement"), 1, 5000, context)?.unwrap_or(1); - if !VALID_ROUNDING_INCREMENTS.contains(&rounding_increment) { - return Err(JsNativeError::range() - .with_message("invalid value for option `roundingIncrement`") - .into()); - } + let rounding_increment = RoundingIncrement::from_u16(rounding_increment).ok_or_else(|| { + JsNativeError::range().with_message("invalid value for option `roundingIncrement`") + })?; // 10. Let roundingMode be ? GetOption(options, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfExpand"). let rounding_mode = get_option(options, utf16!("roundingMode"), context)?.unwrap_or_default(); @@ -67,7 +131,7 @@ pub(crate) fn get_digit_format_options( // 12. NOTE: All fields required by SetNumberFormatDigitOptions have now been read from options. The remainder of this AO interprets the options and may throw exceptions. // 13. If roundingIncrement is not 1, set mxfdDefault to mnfdDefault. - if rounding_increment != 1 { + if rounding_increment.to_u16() != 1 { max_float_digits_default = min_float_digits_default; } @@ -220,7 +284,7 @@ pub(crate) fn get_digit_format_options( (None, Some(frac)) => RoundingType::FractionDigits(frac), }; - if rounding_increment != 1 { + if rounding_increment.to_u16() != 1 { let RoundingType::FractionDigits(range) = rounding_type else { return Err(JsNativeError::typ() .with_message("option `roundingIncrement` invalid for the current set of options") @@ -257,17 +321,17 @@ pub(crate) fn f64_to_formatted_fixed_decimal( number: f64, options: &DigitFormatOptions, ) -> FixedDecimal { - fn round(number: &mut FixedDecimal, position: i16, mode: RoundingMode) { + fn round(number: &mut FixedDecimal, position: i16, mode: RoundingMode, multiple: BaseMultiple) { match mode { - RoundingMode::Ceil => number.ceil(position), - RoundingMode::Floor => number.floor(position), - RoundingMode::Expand => number.expand(position), - RoundingMode::Trunc => number.trunc(position), - RoundingMode::HalfCeil => number.half_ceil(position), - RoundingMode::HalfFloor => number.half_floor(position), - RoundingMode::HalfExpand => number.half_expand(position), - RoundingMode::HalfTrunc => number.half_trunc(position), - RoundingMode::HalfEven => number.half_even(position), + RoundingMode::Ceil => number.ceil_to_increment(position, multiple), + RoundingMode::Floor => number.floor_to_increment(position, multiple), + RoundingMode::Expand => number.expand_to_increment(position, multiple), + RoundingMode::Trunc => number.trunc_to_increment(position, multiple), + RoundingMode::HalfCeil => number.half_ceil_to_increment(position, multiple), + RoundingMode::HalfFloor => number.half_floor_to_increment(position, multiple), + RoundingMode::HalfExpand => number.half_expand_to_increment(position, multiple), + RoundingMode::HalfTrunc => number.half_trunc_to_increment(position, multiple), + RoundingMode::HalfEven => number.half_even_to_increment(position, multiple), } } @@ -282,7 +346,7 @@ pub(crate) fn f64_to_formatted_fixed_decimal( let min_msb = msb - i16::from(min_precision) + 1; let max_msb = msb - i16::from(max_precision) + 1; number.pad_end(min_msb); - round(number, max_msb, rounding_mode); + round(number, max_msb, rounding_mode, BaseMultiple::MultiplesOf1); max_msb } @@ -291,12 +355,21 @@ pub(crate) fn f64_to_formatted_fixed_decimal( number: &mut FixedDecimal, min_fraction: u8, max_fraction: u8, - // TODO: missing support for `roundingIncrement` on `FixedDecimal`. - _rounding_increment: u16, + rounding_increment: RoundingIncrement, rounding_mode: RoundingMode, ) -> i16 { + #[cfg(debug_assertions)] + if rounding_increment.to_u16() != 1 { + assert_eq!(min_fraction, max_fraction); + } + number.pad_end(-i16::from(min_fraction)); - round(number, -i16::from(max_fraction), rounding_mode); + round( + number, + rounding_increment.magnitude_offset() - i16::from(max_fraction), + rounding_mode, + rounding_increment.multiple, + ); -i16::from(max_fraction) } @@ -405,3 +478,48 @@ pub(crate) fn f64_to_formatted_fixed_decimal( // 14. Return the Record { [[RoundedNumber]]: x, [[FormattedString]]: string }. number } + +#[cfg(test)] +mod tests { + use crate::builtins::intl::number_format::RoundingIncrement; + use fixed_decimal::RoundingIncrement::*; + + #[test] + fn u16_to_rounding_increment_sunny_day() { + #[rustfmt::skip] + const VALID_CASES: [(u16, RoundingIncrement); 15] = [ + // Singles + (1, RoundingIncrement { multiple: MultiplesOf1, magnitude_offset: 0 }), + (2, RoundingIncrement { multiple: MultiplesOf2, magnitude_offset: 0 }), + (5, RoundingIncrement { multiple: MultiplesOf5, magnitude_offset: 0 }), + // Tens + (10, RoundingIncrement { multiple: MultiplesOf1, magnitude_offset: 1 }), + (20, RoundingIncrement { multiple: MultiplesOf2, magnitude_offset: 1 }), + (25, RoundingIncrement { multiple: MultiplesOf25, magnitude_offset: 0 }), + (50, RoundingIncrement { multiple: MultiplesOf5, magnitude_offset: 1 }), + // Hundreds + (100, RoundingIncrement { multiple: MultiplesOf1, magnitude_offset: 2 }), + (200, RoundingIncrement { multiple: MultiplesOf2, magnitude_offset: 2 }), + (250, RoundingIncrement { multiple: MultiplesOf25, magnitude_offset: 1 }), + (500, RoundingIncrement { multiple: MultiplesOf5, magnitude_offset: 2 }), + // Thousands + (1000, RoundingIncrement { multiple: MultiplesOf1, magnitude_offset: 3 }), + (2000, RoundingIncrement { multiple: MultiplesOf2, magnitude_offset: 3 }), + (2500, RoundingIncrement { multiple: MultiplesOf25, magnitude_offset: 2 }), + (5000, RoundingIncrement { multiple: MultiplesOf5, magnitude_offset: 3 }), + ]; + + for (num, increment) in VALID_CASES { + assert_eq!(RoundingIncrement::from_u16(num), Some(increment)); + } + } + + #[test] + fn u16_to_rounding_increment_rainy_day() { + const INVALID_CASES: [u16; 9] = [0, 4, 6, 24, 10000, 65535, 7373, 140, 1500]; + + for num in INVALID_CASES { + assert!(RoundingIncrement::from_u16(num).is_none()); + } + } +} diff --git a/boa_engine/src/builtins/intl/plural_rules/mod.rs b/boa_engine/src/builtins/intl/plural_rules/mod.rs index 1ae3227707..4750d6245f 100644 --- a/boa_engine/src/builtins/intl/plural_rules/mod.rs +++ b/boa_engine/src/builtins/intl/plural_rules/mod.rs @@ -6,6 +6,7 @@ use fixed_decimal::FixedDecimal; use icu_locid::Locale; use icu_plurals::{ provider::CardinalV1Marker, PluralCategory, PluralRuleType, PluralRules as NativePluralRules, + PluralRulesWithRanges, }; use icu_provider::DataLocale; @@ -36,7 +37,7 @@ use super::{ #[derive(Debug)] pub struct PluralRules { locale: Locale, - native: NativePluralRules, + native: PluralRulesWithRanges, rule_type: PluralRuleType, format_options: DigitFormatOptions, } @@ -64,6 +65,7 @@ impl IntrinsicObject for PluralRules { ) .method(Self::resolved_options, js_string!("resolvedOptions"), 0) .method(Self::select, js_string!("select"), 1) + .method(Self::select_range, js_string!("selectRange"), 2) .build(); } @@ -93,6 +95,12 @@ impl BuiltInConstructor for PluralRules { .with_message("cannot call `Intl.PluralRules` constructor without `new`") .into()); } + let proto = get_prototype_from_constructor( + new_target, + StandardConstructors::plural_rules, + context, + )?; + // 2. Let pluralRules be ? OrdinaryCreateFromConstructor(NewTarget, "%PluralRules.prototype%", // « [[InitializedPluralRules]], [[Locale]], [[Type]], [[MinimumIntegerDigits]], // [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], @@ -136,11 +144,11 @@ impl BuiltInConstructor for PluralRules { ); let native = match rule_type { - PluralRuleType::Cardinal => NativePluralRules::try_new_cardinal_unstable( + PluralRuleType::Cardinal => PluralRulesWithRanges::try_new_cardinal_unstable( context.icu().provider(), &DataLocale::from(&locale), ), - PluralRuleType::Ordinal => NativePluralRules::try_new_ordinal_unstable( + PluralRuleType::Ordinal => PluralRulesWithRanges::try_new_ordinal_unstable( context.icu().provider(), &DataLocale::from(&locale), ), @@ -152,12 +160,6 @@ impl BuiltInConstructor for PluralRules { } .map_err(|e| JsNativeError::typ().with_message(e.to_string()))?; - let proto = get_prototype_from_constructor( - new_target, - StandardConstructors::plural_rules, - context, - )?; - // 12. Return pluralRules. Ok(JsObject::from_proto_and_data_with_shared_shape( context.root_shape(), @@ -187,20 +189,86 @@ impl PluralRules { // 1. Let pr be the this value. // 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]). let plural_rules = this.as_object().map(JsObject::borrow).ok_or_else(|| { - JsNativeError::typ().with_message( - "`resolved_options` can only be called on an `Intl.PluralRules` object", - ) + JsNativeError::typ() + .with_message("`select` can only be called on an `Intl.PluralRules` object") })?; let plural_rules = plural_rules.as_plural_rules().ok_or_else(|| { - JsNativeError::typ().with_message( - "`resolved_options` can only be called on an `Intl.PluralRules` object", - ) + JsNativeError::typ() + .with_message("`select` can only be called on an `Intl.PluralRules` object") })?; let n = args.get_or_undefined(0).to_number(context)?; Ok(plural_category_to_js_string(resolve_plural(plural_rules, n).category).into()) } + + /// [`Intl.PluralRules.prototype.selectRange ( start, end )`][spec]. + /// + /// Receives two values and returns a string indicating which plural rule to use for + /// locale-aware formatting of the indicated range. + /// + /// More information: + /// - [MDN documentation][mdn] + /// + /// [spec]: https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.selectrange + /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules/selectRange + fn select_range(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult { + // 1. Let pr be the this value. + // 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]). + let plural_rules = this.as_object().map(JsObject::borrow).ok_or_else(|| { + JsNativeError::typ() + .with_message("`select_range` can only be called on an `Intl.PluralRules` object") + })?; + let plural_rules = plural_rules.as_plural_rules().ok_or_else(|| { + JsNativeError::typ() + .with_message("`select_range` can only be called on an `Intl.PluralRules` object") + })?; + + // 3. If start is undefined or end is undefined, throw a TypeError exception. + let x = args.get_or_undefined(0); + let y = args.get_or_undefined(1); + if x.is_undefined() || y.is_undefined() { + return Err(JsNativeError::typ() + .with_message("extremum of range cannot be `undefined`") + .into()); + } + + // 4. Let x be ? ToNumber(start). + let x = x.to_number(context)?; + // 5. Let y be ? ToNumber(end). + let y = y.to_number(context)?; + + // 6. Return ? ResolvePluralRange(pr, x, y). + // ResolvePluralRange(pr, x, y) + // + + // 1. If x is NaN or y is NaN, throw a RangeError exception. + if x.is_nan() || y.is_nan() { + return Err(JsNativeError::typ() + .with_message("extremum of range cannot be NaN") + .into()); + } + + // 2. Let xp be ResolvePlural(pluralRules, x). + let x = resolve_plural(plural_rules, x); + // 3. Let yp be ResolvePlural(pluralRules, y). + let y = resolve_plural(plural_rules, y); + + // 4. If xp.[[FormattedString]] is yp.[[FormattedString]], then + if x.formatted == y.formatted { + // a. Return xp.[[PluralCategory]]. + return Ok(plural_category_to_js_string(x.category).into()); + } + + // 5. Let locale be pluralRules.[[Locale]]. + // 6. Let type be pluralRules.[[Type]]. + // 7. Return PluralRuleSelectRange(locale, type, xp.[[PluralCategory]], yp.[[PluralCategory]]). + Ok( + plural_category_to_js_string(plural_rules.native.resolve_range(x.category, y.category)) + .into(), + ) + } + /// [`Intl.PluralRules.supportedLocalesOf ( locales [ , options ] )`][spec]. /// /// Returns an array containing those of the provided locales that are supported in plural rules @@ -322,7 +390,7 @@ impl PluralRules { ) .property( js_string!("roundingIncrement"), - plural_rules.format_options.rounding_increment, + plural_rules.format_options.rounding_increment.to_u16(), Attribute::all(), ) .property( @@ -339,6 +407,7 @@ impl PluralRules { let plural_categories = Array::create_array_from_list( plural_rules .native + .rules() .categories() .map(|category| plural_category_to_js_string(category).into()), options.context(), @@ -401,7 +470,7 @@ fn resolve_plural(plural_rules: &PluralRules, n: f64) -> ResolvedPlural { // 8. Let s be res.[[FormattedString]]. // 9. Let operands be ! GetOperands(s). // 10. Let p be ! PluralRuleSelect(locale, type, n, operands). - let category = plural_rules.native.category_for(&fixed); + let category = plural_rules.native.rules().category_for(&fixed); // 11. Return the Record { [[PluralCategory]]: p, [[FormattedString]]: s }. ResolvedPlural { diff --git a/boa_engine/src/object/mod.rs b/boa_engine/src/object/mod.rs index fbec95e8ca..c0e246027d 100644 --- a/boa_engine/src/object/mod.rs +++ b/boa_engine/src/object/mod.rs @@ -438,7 +438,7 @@ pub enum ObjectKind { SegmentIterator(SegmentIterator), /// The `PluralRules` object kind. #[cfg(feature = "intl")] - PluralRules(PluralRules), + PluralRules(Box), /// The `Temporal.Instant` object kind. #[cfg(feature = "temporal")] @@ -982,7 +982,7 @@ impl ObjectData { #[must_use] pub fn plural_rules(plural_rules: PluralRules) -> Self { Self { - kind: ObjectKind::PluralRules(plural_rules), + kind: ObjectKind::PluralRules(Box::new(plural_rules)), internal_methods: &ORDINARY_INTERNAL_METHODS, } } diff --git a/boa_icu_provider/Cargo.toml b/boa_icu_provider/Cargo.toml index 309fab6015..7b66f09758 100644 --- a/boa_icu_provider/Cargo.toml +++ b/boa_icu_provider/Cargo.toml @@ -13,19 +13,20 @@ rust-version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -icu_provider = { workspace = true, features = ["serde", "sync"] } +icu_provider = { workspace = true, features = ["serde", "sync", "datagen"] } icu_provider_blob = { workspace = true, features = ["export"] } icu_provider_adapters = { workspace = true, features = ["serde"] } once_cell = { workspace = true, default-features = false, features = ["critical-section"] } icu_datagen = { workspace = true, optional = true, features = ["networking", "use_wasm"] } +icu_plurals = { workspace = true, optional = true, features = ["datagen", "experimental"] } log = { version = "0.4.20", optional = true } simple_logger = { version = "4.2.0", optional = true } [features] default = ["std"] std = ["once_cell/std"] -bin = ["dep:icu_datagen", "dep:simple_logger", "dep:log"] +bin = ["dep:icu_datagen", "dep:simple_logger", "dep:log", "dep:icu_plurals"] [[bin]] name = "boa_datagen" diff --git a/boa_icu_provider/data/icudata.postcard b/boa_icu_provider/data/icudata.postcard index a79e621fe7..8343eeb070 100644 Binary files a/boa_icu_provider/data/icudata.postcard and b/boa_icu_provider/data/icudata.postcard differ diff --git a/boa_icu_provider/src/bin/datagen.rs b/boa_icu_provider/src/bin/datagen.rs index 22cf441aa8..5da227f591 100644 --- a/boa_icu_provider/src/bin/datagen.rs +++ b/boa_icu_provider/src/bin/datagen.rs @@ -12,8 +12,78 @@ use std::{error::Error, fs::File}; use boa_icu_provider::data_root; use icu_datagen::{all_keys, CoverageLevel, DatagenDriver, DatagenProvider}; +use icu_plurals::provider::{PluralRangesV1, PluralRangesV1Marker}; +use icu_provider::{ + datagen::{ExportMarker, IterableDynamicDataProvider}, + dynutil::UpcastDataPayload, + prelude::*, +}; use icu_provider_blob::export::BlobExporter; +/// Hack that associates the `und` locale with an empty plural ranges data. +/// This enables the default behaviour for all locales without data. +#[derive(Debug)] +struct PluralRangesFallbackHack(DatagenProvider); + +// We definitely don't want to import dependencies just to do `T::default`. +#[allow(clippy::default_trait_access)] +impl DynamicDataProvider for PluralRangesFallbackHack { + fn load_data( + &self, + key: DataKey, + req: DataRequest<'_>, + ) -> Result, DataError> { + if req.locale.is_und() && key.hashed() == PluralRangesV1Marker::KEY.hashed() { + let payload = >::upcast( + DataPayload::from_owned(PluralRangesV1 { + ranges: Default::default(), + }), + ); + Ok(DataResponse { + metadata: DataResponseMetadata::default(), + payload: Some(payload), + }) + } else { + self.0.load_data(key, req) + } + } +} + +#[allow(clippy::default_trait_access)] +impl DynamicDataProvider for PluralRangesFallbackHack { + fn load_data( + &self, + key: DataKey, + req: DataRequest<'_>, + ) -> Result, DataError> { + if req.locale.is_und() && key.hashed() == PluralRangesV1Marker::KEY.hashed() { + let payload = >::upcast( + DataPayload::from_owned(PluralRangesV1 { + ranges: Default::default(), + }), + ); + Ok(DataResponse { + metadata: DataResponseMetadata::default(), + payload: Some(payload), + }) + } else { + self.0.load_data(key, req) + } + } +} + +impl IterableDynamicDataProvider for PluralRangesFallbackHack { + fn supported_locales_for_key(&self, key: DataKey) -> Result, DataError> { + if key.hashed() == PluralRangesV1Marker::KEY.hashed() { + let mut locales = self.0.supported_locales_for_key(key)?; + locales.push(DataLocale::default()); + Ok(locales) + } else { + self.0.supported_locales_for_key(key) + } + } +} + fn main() -> Result<(), Box> { simple_logger::SimpleLogger::new() .env() @@ -27,7 +97,7 @@ fn main() -> Result<(), Box> { .with_locales(provider.locales_for_coverage_levels([CoverageLevel::Modern])?) .with_additional_collations([String::from("search*")]) .export( - &provider, + &PluralRangesFallbackHack(provider), BlobExporter::new_with_sink(Box::new(File::create( data_root().join("icudata.postcard"), )?)),