diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index da509592787..9c51af9ba9b 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -122,9 +122,15 @@ jobs:
         with:
           key: clippy
       - name: Clippy (All features)
-        run: cargo workspaces exec cargo clippy --all-features --all-targets -- -D warnings
+        run: cargo workspaces exec cargo clippy --all-features --all-targets
       - name: Clippy (No features)
-        run: cargo workspaces exec cargo clippy --no-default-features --all-targets -- -D warnings
+        run: cargo workspaces exec cargo clippy --no-default-features --all-targets
+      - name: Clippy (Intl)
+        run: cargo clippy -p boa_engine --features intl
+      - name: Clippy (Annex-B)
+        run: cargo clippy -p boa_engine --features annex-b
+      - name: Clippy (Experimental)
+        run: cargo clippy -p boa_engine --features experimental
 
   docs:
     name: Documentation
diff --git a/Cargo.lock b/Cargo.lock
index 4afd8aa15e9..c6ab9477d1c 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 251c88f5360..ead4e6dfca4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,7 +20,7 @@ members = [
 [workspace.package]
 edition = "2021"
 version = "0.17.0"
-rust-version = "1.73.0"
+rust-version = "1.74.0"
 authors = ["boa-dev"]
 repository = "https://github.com/boa-dev/boa"
 license = "Unlicense OR MIT"
@@ -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"
@@ -116,3 +117,58 @@ opt-level = 1
 lto = "fat"
 # Makes sure that all code is compiled together, for LTO
 codegen-units = 1
+
+[workspace.lints.rust]
+# rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
+warnings = "warn"
+future_incompatible = "warn"
+let_underscore = "warn"
+nonstandard_style = "warn"
+rust_2018_compatibility = "warn"
+rust_2018_idioms = "warn"
+rust_2021_compatibility = "warn"
+unused = "warn"
+
+# rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
+missing_docs = "warn"
+macro_use_extern_crate = "warn"
+meta_variable_misuse = "warn"
+missing_abi = "warn"
+missing_copy_implementations = "warn"
+missing_debug_implementations = "warn"
+non_ascii_idents = "warn"
+noop_method_call = "warn"
+single_use_lifetimes = "warn"
+trivial_casts = "warn"
+trivial_numeric_casts = "warn"
+unreachable_pub = "warn"
+unsafe_op_in_unsafe_fn = "warn"
+unused_crate_dependencies = "warn"
+unused_import_braces = "warn"
+unused_lifetimes = "warn"
+unused_qualifications = "warn"
+unused_tuple_struct_fields = "warn"
+variant_size_differences = "warn"
+
+[workspace.lints.rustdoc]
+# rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
+broken_intra_doc_links = "warn"
+private_intra_doc_links = "warn"
+missing_crate_level_docs = "warn"
+private_doc_tests = "warn"
+invalid_codeblock_attributes = "warn"
+invalid_rust_codeblocks = "warn"
+bare_urls = "warn"
+
+[workspace.lints.clippy]
+# clippy allowed by default
+dbg_macro = "warn"
+
+# clippy categories https://doc.rust-lang.org/clippy/
+all = "warn"
+correctness = "warn"
+suspicious = "warn"
+style = "warn"
+complexity = "warn"
+perf = "warn"
+pedantic = "warn"
diff --git a/boa_ast/Cargo.toml b/boa_ast/Cargo.toml
index 40d371fc525..1945d562223 100644
--- a/boa_ast/Cargo.toml
+++ b/boa_ast/Cargo.toml
@@ -24,3 +24,6 @@ num-bigint.workspace = true
 serde = { workspace = true, features = ["derive"], optional = true }
 arbitrary = { workspace = true, features = ["derive"], optional = true }
 indexmap.workspace = true
+
+[lints]
+workspace = true
diff --git a/boa_ast/src/position.rs b/boa_ast/src/position.rs
index 8e8afa3eb1e..a42a1768103 100644
--- a/boa_ast/src/position.rs
+++ b/boa_ast/src/position.rs
@@ -141,14 +141,14 @@ mod tests {
 
     /// Checks that we cannot create a position with 0 as the column.
     #[test]
-    #[should_panic]
+    #[should_panic(expected = "column number cannot be 0")]
     fn invalid_position_column() {
         Position::new(10, 0);
     }
 
     /// Checks that we cannot create a position with 0 as the line.
     #[test]
-    #[should_panic]
+    #[should_panic(expected = "line number cannot be 0")]
     fn invalid_position_line() {
         Position::new(0, 10);
     }
@@ -195,7 +195,7 @@ mod tests {
 
     /// Checks that we cannot create an invalid span.
     #[test]
-    #[should_panic]
+    #[should_panic(expected = "a span cannot start after its end")]
     fn invalid_span() {
         let a = Position::new(10, 30);
         let b = Position::new(10, 50);
diff --git a/boa_cli/Cargo.toml b/boa_cli/Cargo.toml
index d62f21b553f..7c1e34b3c3b 100644
--- a/boa_cli/Cargo.toml
+++ b/boa_cli/Cargo.toml
@@ -37,3 +37,6 @@ jemallocator.workspace = true
 name = "boa"
 doc = false
 path = "src/main.rs"
+
+[lints]
+workspace = true
diff --git a/boa_cli/src/main.rs b/boa_cli/src/main.rs
index a8187739c07..f2fa0c5f9ce 100644
--- a/boa_cli/src/main.rs
+++ b/boa_cli/src/main.rs
@@ -5,59 +5,6 @@
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
 #![cfg_attr(not(test), deny(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 
 mod debug;
 mod helper;
@@ -305,7 +252,7 @@ fn generate_flowgraph(
 fn evaluate_files(
     args: &Opt,
     context: &mut Context,
-    loader: Rc<SimpleModuleLoader>,
+    loader: &SimpleModuleLoader,
 ) -> Result<(), io::Error> {
     for file in &args.files {
         let buffer = read(file)?;
@@ -485,7 +432,7 @@ fn main() -> Result<(), io::Error> {
             .save_history(CLI_HISTORY)
             .expect("could not save CLI history");
     } else {
-        evaluate_files(&args, &mut context, loader)?;
+        evaluate_files(&args, &mut context, &loader)?;
     }
 
     Ok(())
diff --git a/boa_engine/Cargo.toml b/boa_engine/Cargo.toml
index cb9a15a2412..288238c9099 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]
@@ -133,3 +133,6 @@ bench = false
 [[bench]]
 name = "full"
 harness = false
+
+[lints]
+workspace = true
diff --git a/boa_engine/benches/full.rs b/boa_engine/benches/full.rs
index 2478f187fb3..c0df062855e 100644
--- a/boa_engine/benches/full.rs
+++ b/boa_engine/benches/full.rs
@@ -1,3 +1,5 @@
+#![allow(unused_crate_dependencies, missing_docs)]
+
 //! Benchmarks of the whole execution engine in Boa.
 
 use boa_engine::{
@@ -17,7 +19,7 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
 fn create_realm(c: &mut Criterion) {
     c.bench_function("Create Realm", move |b| {
         let root_shape = RootShape::default();
-        b.iter(|| Realm::create(&DefaultHooks, &root_shape))
+        b.iter(|| Realm::create(&DefaultHooks, &root_shape));
     });
 }
 
diff --git a/boa_engine/src/builtins/function/mod.rs b/boa_engine/src/builtins/function/mod.rs
index 3fdaef9bf32..7b12288f168 100644
--- a/boa_engine/src/builtins/function/mod.rs
+++ b/boa_engine/src/builtins/function/mod.rs
@@ -253,7 +253,7 @@ impl OrdinaryFunction {
         &self.realm
     }
 
-    /// Check if function is [`FunctionKind::Ordinary`].
+    /// Checks if this function is an ordinary function.
     pub(crate) fn is_ordinary(&self) -> bool {
         self.code.is_ordinary()
     }
diff --git a/boa_engine/src/builtins/intl/locale/utils.rs b/boa_engine/src/builtins/intl/locale/utils.rs
index e2879c22786..1f76a9eb162 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::<M>(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;
@@ -499,8 +503,8 @@ fn lookup_supported_locales<M: KeyedDataMarker>(
     // 3. Return subset.
     requested_locales
         .iter()
-        .cloned()
         .filter(|loc| best_available_locale(loc.id.clone(), provider).is_some())
+        .cloned()
         .collect()
 }
 
@@ -517,8 +521,8 @@ fn best_fit_supported_locales<M: KeyedDataMarker>(
 ) -> Vec<Locale> {
     requested_locales
         .iter()
-        .cloned()
         .filter(|loc| best_locale_for_provider(loc.id.clone(), provider).is_some())
+        .cloned()
         .collect()
 }
 
diff --git a/boa_engine/src/builtins/intl/number_format/options.rs b/boa_engine/src/builtins/intl/number_format/options.rs
index 04f3ed2010a..c3dfb8dba65 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 7dd82927bd9..ff5f4c265fb 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<Self> {
+        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<DigitFormatOptions> {
-    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 1ae32277079..4750d6245f3 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<NativePluralRules>,
     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<JsValue> {
+        // 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)
+        // <https://tc39.es/ecma402/#sec-resolvepluralrange>
+
+        // 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/builtins/options.rs b/boa_engine/src/builtins/options.rs
index b2a99f5559a..4628f0eee4b 100644
--- a/boa_engine/src/builtins/options.rs
+++ b/boa_engine/src/builtins/options.rs
@@ -124,53 +124,6 @@ pub(crate) enum RoundingMode {
     HalfEven,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) enum UnsignedRoundingMode {
-    Infinity,
-    Zero,
-    HalfInfinity,
-    HalfZero,
-    HalfEven,
-}
-
-impl RoundingMode {
-    pub(crate) const fn negate(self) -> Self {
-        use RoundingMode::{
-            Ceil, Expand, Floor, HalfCeil, HalfEven, HalfExpand, HalfFloor, HalfTrunc, Trunc,
-        };
-
-        match self {
-            Ceil => Self::Floor,
-            Floor => Self::Ceil,
-            HalfCeil => Self::HalfFloor,
-            HalfFloor => Self::HalfCeil,
-            Trunc => Self::Trunc,
-            Expand => Self::Expand,
-            HalfTrunc => Self::HalfTrunc,
-            HalfExpand => Self::HalfExpand,
-            HalfEven => Self::HalfEven,
-        }
-    }
-
-    pub(crate) const fn get_unsigned_round_mode(self, is_negative: bool) -> UnsignedRoundingMode {
-        use RoundingMode::{
-            Ceil, Expand, Floor, HalfCeil, HalfEven, HalfExpand, HalfFloor, HalfTrunc, Trunc,
-        };
-
-        match self {
-            Ceil if !is_negative => UnsignedRoundingMode::Infinity,
-            Ceil => UnsignedRoundingMode::Zero,
-            Floor if !is_negative => UnsignedRoundingMode::Zero,
-            Floor | Trunc | Expand => UnsignedRoundingMode::Infinity,
-            HalfCeil if !is_negative => UnsignedRoundingMode::HalfInfinity,
-            HalfCeil | HalfTrunc => UnsignedRoundingMode::HalfZero,
-            HalfFloor if !is_negative => UnsignedRoundingMode::HalfZero,
-            HalfFloor | HalfExpand => UnsignedRoundingMode::HalfInfinity,
-            HalfEven => UnsignedRoundingMode::HalfEven,
-        }
-    }
-}
-
 #[derive(Debug)]
 pub(crate) struct ParseRoundingModeError;
 
@@ -217,3 +170,53 @@ impl fmt::Display for RoundingMode {
         .fmt(f)
     }
 }
+
+#[cfg(feature = "temporal")]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) enum UnsignedRoundingMode {
+    Infinity,
+    Zero,
+    HalfInfinity,
+    HalfZero,
+    HalfEven,
+}
+
+impl RoundingMode {
+    #[cfg(feature = "temporal")]
+    pub(crate) const fn negate(self) -> Self {
+        use RoundingMode::{
+            Ceil, Expand, Floor, HalfCeil, HalfEven, HalfExpand, HalfFloor, HalfTrunc, Trunc,
+        };
+
+        match self {
+            Ceil => Self::Floor,
+            Floor => Self::Ceil,
+            HalfCeil => Self::HalfFloor,
+            HalfFloor => Self::HalfCeil,
+            Trunc => Self::Trunc,
+            Expand => Self::Expand,
+            HalfTrunc => Self::HalfTrunc,
+            HalfExpand => Self::HalfExpand,
+            HalfEven => Self::HalfEven,
+        }
+    }
+
+    #[cfg(feature = "temporal")]
+    pub(crate) const fn get_unsigned_round_mode(self, is_negative: bool) -> UnsignedRoundingMode {
+        use RoundingMode::{
+            Ceil, Expand, Floor, HalfCeil, HalfEven, HalfExpand, HalfFloor, HalfTrunc, Trunc,
+        };
+
+        match self {
+            Ceil if !is_negative => UnsignedRoundingMode::Infinity,
+            Ceil => UnsignedRoundingMode::Zero,
+            Floor if !is_negative => UnsignedRoundingMode::Zero,
+            Floor | Trunc | Expand => UnsignedRoundingMode::Infinity,
+            HalfCeil if !is_negative => UnsignedRoundingMode::HalfInfinity,
+            HalfCeil | HalfTrunc => UnsignedRoundingMode::HalfZero,
+            HalfFloor if !is_negative => UnsignedRoundingMode::HalfZero,
+            HalfFloor | HalfExpand => UnsignedRoundingMode::HalfInfinity,
+            HalfEven => UnsignedRoundingMode::HalfEven,
+        }
+    }
+}
diff --git a/boa_engine/src/builtins/temporal/duration/record.rs b/boa_engine/src/builtins/temporal/duration/record.rs
index 18266c1e7ef..cd29c089a6e 100644
--- a/boa_engine/src/builtins/temporal/duration/record.rs
+++ b/boa_engine/src/builtins/temporal/duration/record.rs
@@ -1425,7 +1425,7 @@ impl DurationRecord {
         // 2. If zonedRelativeTo is not present, set zonedRelativeTo to undefined.
         let zoned_relative_to = relative_targets.1;
         // 3. If precalculatedPlainDateTime is not present, set precalculatedPlainDateTime to undefined.
-        let _precalc_pdt = relative_targets.2;
+        let _ = relative_targets.2;
 
         let (frac_days, frac_secs) = match unit {
             // 4. If unit is "year", "month", or "week", and plainRelativeTo is undefined, then
diff --git a/boa_engine/src/builtins/typed_array/element/mod.rs b/boa_engine/src/builtins/typed_array/element/mod.rs
index 3137816f4ba..1d0383766ac 100644
--- a/boa_engine/src/builtins/typed_array/element/mod.rs
+++ b/boa_engine/src/builtins/typed_array/element/mod.rs
@@ -1,5 +1,6 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 #![allow(clippy::cast_ptr_alignment)] // Invariants are checked by the caller.
+#![allow(unused_tuple_struct_fields)] // Weird false-positive with `boa_macros_tests`
 
 mod atomic;
 
diff --git a/boa_engine/src/lib.rs b/boa_engine/src/lib.rs
index d7bb7cf7707..a9bb3af0ddf 100644
--- a/boa_engine/src/lib.rs
+++ b/boa_engine/src/lib.rs
@@ -50,60 +50,8 @@
     html_logo_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg",
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
+#![cfg_attr(test, allow(clippy::needless_raw_string_hashes))] // Makes strings a bit more copy-pastable
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 #![allow(
     // Currently throws a false positive regarding dependencies that are only used in benchmarks.
     unused_crate_dependencies,
diff --git a/boa_engine/src/object/mod.rs b/boa_engine/src/object/mod.rs
index fbec95e8cae..c0e246027d3 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<PluralRules>),
 
     /// 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_engine/src/symbol.rs b/boa_engine/src/symbol.rs
index d6a6b6c180e..7514a69088c 100644
--- a/boa_engine/src/symbol.rs
+++ b/boa_engine/src/symbol.rs
@@ -151,7 +151,7 @@ unsafe impl Trace for JsSymbol {
 macro_rules! well_known_symbols {
     ( $( $(#[$attr:meta])* ($name:ident, $variant:path) ),+$(,)? ) => {
         $(
-            $(#[$attr])* pub const fn $name() -> JsSymbol {
+            $(#[$attr])* #[must_use] pub const fn $name() -> JsSymbol {
                 JsSymbol {
                     // the cast shouldn't matter since we only have 127 const symbols
                     repr: Tagged::from_tag($variant.hash() as usize),
diff --git a/boa_examples/Cargo.toml b/boa_examples/Cargo.toml
index 5be71d7cd7f..72c27113263 100644
--- a/boa_examples/Cargo.toml
+++ b/boa_examples/Cargo.toml
@@ -19,3 +19,41 @@ boa_runtime.workspace = true
 chrono.workspace = true
 smol = "1.3.0"
 futures-util = "0.3.29"
+
+
+# use explicit lints for examples, since we don't need to lint for docs
+[lints.rust]
+# rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
+warnings = "warn"
+future_incompatible = "warn"
+let_underscore = "warn"
+nonstandard_style = "warn"
+rust_2018_compatibility = "warn"
+rust_2018_idioms = "warn"
+rust_2021_compatibility = "warn"
+unused = "warn"
+macro_use_extern_crate = "warn"
+meta_variable_misuse = "warn"
+missing_abi = "warn"
+missing_copy_implementations = "warn"
+missing_debug_implementations = "warn"
+non_ascii_idents = "warn"
+noop_method_call = "warn"
+single_use_lifetimes = "warn"
+trivial_casts = "warn"
+trivial_numeric_casts = "warn"
+unreachable_pub = "warn"
+unsafe_op_in_unsafe_fn = "warn"
+unused_import_braces = "warn"
+unused_lifetimes = "warn"
+unused_qualifications = "warn"
+unused_tuple_struct_fields = "warn"
+variant_size_differences = "warn"
+
+[lints.clippy]
+all = "warn"
+correctness = "warn"
+suspicious = "warn"
+style = "warn"
+complexity = "warn"
+perf = "warn"
diff --git a/boa_examples/src/bin/classes.rs b/boa_examples/src/bin/classes.rs
index 2c62e2521c6..c23d3da2bd9 100644
--- a/boa_examples/src/bin/classes.rs
+++ b/boa_examples/src/bin/classes.rs
@@ -85,7 +85,7 @@ impl Class for Person {
     }
 
     /// Here is where the class is initialized.
-    fn init(class: &mut ClassBuilder) -> JsResult<()> {
+    fn init(class: &mut ClassBuilder<'_>) -> JsResult<()> {
         // We add a inheritable method `sayHello` with `0` arguments of length.
         //
         // This function is added to the `Person` prototype.
diff --git a/boa_examples/src/bin/closures.rs b/boa_examples/src/bin/closures.rs
index 8548f79a5e5..97408827639 100644
--- a/boa_examples/src/bin/closures.rs
+++ b/boa_examples/src/bin/closures.rs
@@ -161,7 +161,7 @@ fn main() -> Result<(), JsError> {
 
                     // We return the moved variable as a `JsValue`.
                     Ok(JsArray::from_iter(
-                        numbers.borrow().iter().cloned().map(JsValue::from),
+                        numbers.borrow().iter().copied().map(JsValue::from),
                         context,
                     )
                     .into())
diff --git a/boa_examples/src/bin/commuter_visitor.rs b/boa_examples/src/bin/commuter_visitor.rs
index 17fdff8da75..e6fb2cc9e04 100644
--- a/boa_examples/src/bin/commuter_visitor.rs
+++ b/boa_examples/src/bin/commuter_visitor.rs
@@ -53,7 +53,7 @@ impl<'ast> VisitorMut<'ast> for CommutorVisitor {
                     let mut exchanger = OpExchanger::default();
                     assert!(matches!(
                         exchanger.visit_binary_mut(node),
-                        ControlFlow::Break(_)
+                        ControlFlow::Break(())
                     ));
                 }
                 _ => {}
@@ -74,7 +74,7 @@ fn main() {
 
     assert!(matches!(
         visitor.visit_statement_list_mut(script.statements_mut()),
-        ControlFlow::Continue(_)
+        ControlFlow::Continue(())
     ));
 
     println!("{}", script.to_interned_string(ctx.interner()));
diff --git a/boa_examples/src/bin/futures.rs b/boa_examples/src/bin/futures.rs
index 060d410abcf..d677a761af2 100644
--- a/boa_examples/src/bin/futures.rs
+++ b/boa_examples/src/bin/futures.rs
@@ -34,16 +34,16 @@ impl<'a> Queue<'a> {
     }
 }
 
-impl<'a> JobQueue for Queue<'a> {
-    fn enqueue_promise_job(&self, job: NativeJob, _context: &mut boa_engine::Context) {
+impl JobQueue for Queue<'_> {
+    fn enqueue_promise_job(&self, job: NativeJob, _context: &mut Context) {
         self.jobs.borrow_mut().push_back(job);
     }
 
-    fn enqueue_future_job(&self, future: FutureJob, _context: &mut boa_engine::Context) {
-        self.futures.borrow().push(future)
+    fn enqueue_future_job(&self, future: FutureJob, _context: &mut Context) {
+        self.futures.borrow().push(future);
     }
 
-    fn run_jobs(&self, context: &mut boa_engine::Context) {
+    fn run_jobs(&self, context: &mut Context) {
         // Early return in case there were no jobs scheduled.
         if self.jobs.borrow().is_empty() && self.futures.borrow().is_empty() {
             return;
@@ -55,7 +55,7 @@ impl<'a> JobQueue for Queue<'a> {
             // Used to sync the finalization of both tasks
             let finished = Cell::new(0b00u8);
 
-            let fqueue = async {
+            let fut_queue = async {
                 loop {
                     if self.futures.borrow().is_empty() {
                         finished.set(finished.get() | 0b01);
@@ -82,7 +82,7 @@ impl<'a> JobQueue for Queue<'a> {
                 }
             };
 
-            let jqueue = async {
+            let job_queue = async {
                 loop {
                     if self.jobs.borrow().is_empty() {
                         finished.set(finished.get() | 0b10);
@@ -109,8 +109,8 @@ impl<'a> JobQueue for Queue<'a> {
             };
 
             // Wait for both queues to complete
-            future::zip(fqueue, jqueue).await;
-        }))
+            future::zip(fut_queue, job_queue).await;
+        }));
     }
 }
 
@@ -126,7 +126,7 @@ fn delay(
         let millis = millis?;
         println!("Delaying for {millis} milliseconds ...");
         let now = Instant::now();
-        smol::Timer::after(Duration::from_millis(millis as u64)).await;
+        smol::Timer::after(Duration::from_millis(u64::from(millis))).await;
         let elapsed = now.elapsed().as_secs_f64();
         Ok(elapsed.into())
     }
@@ -163,7 +163,7 @@ fn main() {
     add_runtime(context);
 
     // Multiple calls to multiple async timers.
-    let script = r#"
+    let script = r"
         function print(elapsed) {
             console.log(`Finished. elapsed time: ${elapsed * 1000} ms`)
         }
@@ -172,7 +172,7 @@ fn main() {
         delay(200).then(print);
         delay(600).then(print);
         delay(30).then(print);
-    "#;
+    ";
 
     let now = Instant::now();
     context.eval(Source::from_bytes(script)).unwrap();
diff --git a/boa_examples/src/bin/jsarraybuffer.rs b/boa_examples/src/bin/jsarraybuffer.rs
index 26df61bac8c..2614ffd7e74 100644
--- a/boa_examples/src/bin/jsarraybuffer.rs
+++ b/boa_examples/src/bin/jsarraybuffer.rs
@@ -17,7 +17,7 @@ fn main() -> JsResult<()> {
     // We can now create an typed array to access the data.
     let uint32_typed_array = JsUint32Array::from_array_buffer(array_buffer, context)?;
 
-    let value = 0x12345678u32;
+    let value = 0x1234_5678_u32;
     uint32_typed_array.set(0_u64, value, true, context)?;
 
     assert_eq!(uint32_typed_array.get(0_u64, context)?, JsValue::new(value));
diff --git a/boa_examples/src/bin/jsdate.rs b/boa_examples/src/bin/jsdate.rs
index b1da16f25f6..04df85acda2 100644
--- a/boa_examples/src/bin/jsdate.rs
+++ b/boa_examples/src/bin/jsdate.rs
@@ -40,7 +40,7 @@ fn main() -> JsResult<()> {
     .as_number()
     .unwrap();
 
-    assert_eq!(timestamp, 823230245000.0);
+    assert_eq!(timestamp, 823_230_245_000.0);
 
     // Gets the current time in UTC time.
     let date = JsDate::new(context);
diff --git a/boa_examples/src/bin/modules.rs b/boa_examples/src/bin/modules.rs
index 65af1470a41..68037590f3e 100644
--- a/boa_examples/src/bin/modules.rs
+++ b/boa_examples/src/bin/modules.rs
@@ -93,7 +93,7 @@ fn main() -> Result<(), Box<dyn Error>> {
     match promise_result.state() {
         PromiseState::Pending => return Err("module didn't execute!".into()),
         PromiseState::Fulfilled(v) => {
-            assert_eq!(v, JsValue::undefined())
+            assert_eq!(v, JsValue::undefined());
         }
         PromiseState::Rejected(err) => {
             return Err(JsError::from_opaque(err).try_native(context)?.into())
diff --git a/boa_examples/src/bin/synthetic.rs b/boa_examples/src/bin/synthetic.rs
index ea3e23fe8da..48f17844896 100644
--- a/boa_examples/src/bin/synthetic.rs
+++ b/boa_examples/src/bin/synthetic.rs
@@ -68,7 +68,7 @@ fn main() -> Result<(), Box<dyn Error>> {
     match promise_result.state() {
         PromiseState::Pending => return Err("module didn't execute!".into()),
         PromiseState::Fulfilled(v) => {
-            assert_eq!(v, JsValue::undefined())
+            assert_eq!(v, JsValue::undefined());
         }
         PromiseState::Rejected(err) => {
             return Err(JsError::from_opaque(err).try_native(context)?.into())
diff --git a/boa_gc/Cargo.toml b/boa_gc/Cargo.toml
index 6e91cf05d0f..2f682112e7e 100644
--- a/boa_gc/Cargo.toml
+++ b/boa_gc/Cargo.toml
@@ -20,3 +20,6 @@ boa_macros.workspace = true
 
 thin-vec = { workspace = true, optional = true }
 hashbrown = { workspace = true, features = ["ahash", "raw"] }
+
+[lints]
+workspace = true
diff --git a/boa_gc/src/lib.rs b/boa_gc/src/lib.rs
index 698f6001bd8..2d1808b4254 100644
--- a/boa_gc/src/lib.rs
+++ b/boa_gc/src/lib.rs
@@ -9,60 +9,6 @@
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-    clippy::undocumented_unsafe_blocks,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 #![allow(
     clippy::module_name_repetitions,
     clippy::redundant_pub_crate,
diff --git a/boa_icu_provider/Cargo.toml b/boa_icu_provider/Cargo.toml
index d679e1b5787..7b66f09758b 100644
--- a/boa_icu_provider/Cargo.toml
+++ b/boa_icu_provider/Cargo.toml
@@ -13,21 +13,25 @@ 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"
 path = "src/bin/datagen.rs"
 required-features = ["bin"]
+
+[lints]
+workspace = true
diff --git a/boa_icu_provider/data/icudata.postcard b/boa_icu_provider/data/icudata.postcard
index a79e621fe75..8343eeb0700 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 b791581f3cb..5da227f5917 100644
--- a/boa_icu_provider/src/bin/datagen.rs
+++ b/boa_icu_provider/src/bin/datagen.rs
@@ -2,13 +2,88 @@
     html_logo_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg",
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
+#![allow(
+    unused_crate_dependencies,
+    missing_docs,
+    rustdoc::missing_crate_level_docs
+)]
 
 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<AnyMarker> for PluralRangesFallbackHack {
+    fn load_data(
+        &self,
+        key: DataKey,
+        req: DataRequest<'_>,
+    ) -> Result<DataResponse<AnyMarker>, DataError> {
+        if req.locale.is_und() && key.hashed() == PluralRangesV1Marker::KEY.hashed() {
+            let payload = <AnyMarker as UpcastDataPayload<PluralRangesV1Marker>>::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<ExportMarker> for PluralRangesFallbackHack {
+    fn load_data(
+        &self,
+        key: DataKey,
+        req: DataRequest<'_>,
+    ) -> Result<DataResponse<ExportMarker>, DataError> {
+        if req.locale.is_und() && key.hashed() == PluralRangesV1Marker::KEY.hashed() {
+            let payload = <ExportMarker as UpcastDataPayload<PluralRangesV1Marker>>::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<ExportMarker> for PluralRangesFallbackHack {
+    fn supported_locales_for_key(&self, key: DataKey) -> Result<Vec<DataLocale>, 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<dyn Error>> {
     simple_logger::SimpleLogger::new()
         .env()
@@ -22,7 +97,7 @@ fn main() -> Result<(), Box<dyn Error>> {
         .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"),
             )?)),
diff --git a/boa_icu_provider/src/lib.rs b/boa_icu_provider/src/lib.rs
index 0a9aa072dde..abf29ee919b 100644
--- a/boa_icu_provider/src/lib.rs
+++ b/boa_icu_provider/src/lib.rs
@@ -19,60 +19,8 @@
     html_logo_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg",
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
-#![allow(elided_lifetimes_in_paths)]
 #![cfg_attr(not(feature = "bin"), no_std)]
+#![allow(unused_crate_dependencies)]
 
 /// Gets the path to the directory where the generated data is stored.
 #[cfg(feature = "bin")]
diff --git a/boa_interner/Cargo.toml b/boa_interner/Cargo.toml
index 4bc9909d611..cdd433aecf2 100644
--- a/boa_interner/Cargo.toml
+++ b/boa_interner/Cargo.toml
@@ -25,3 +25,6 @@ indexmap.workspace = true
 serde = { workspace = true, features = ["derive"], optional = true }
 arbitrary = { workspace = true, features = ["derive"], optional = true }
 hashbrown = { workspace = true, default-features = false, features = ["inline-more"] }
+
+[lints]
+workspace = true
diff --git a/boa_interner/src/lib.rs b/boa_interner/src/lib.rs
index 9ac053b4214..115d5b497ef 100644
--- a/boa_interner/src/lib.rs
+++ b/boa_interner/src/lib.rs
@@ -15,59 +15,6 @@
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 #![allow(
     clippy::redundant_pub_crate,
     // TODO deny once false positive is fixed (https://github.com/rust-lang/rust-clippy/issues/9626).
diff --git a/boa_macros/Cargo.toml b/boa_macros/Cargo.toml
index 6c8741dce51..ac70c271951 100644
--- a/boa_macros/Cargo.toml
+++ b/boa_macros/Cargo.toml
@@ -16,3 +16,6 @@ quote = "1.0.33"
 syn = { version = "2.0.39", features = ["full"] }
 proc-macro2 = "1.0"
 synstructure = "0.13"
+
+[lints]
+workspace = true
diff --git a/boa_macros/src/lib.rs b/boa_macros/src/lib.rs
index c56fb5f1e0b..42b32d4c891 100644
--- a/boa_macros/src/lib.rs
+++ b/boa_macros/src/lib.rs
@@ -5,59 +5,6 @@
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 
 use proc_macro::TokenStream;
 use quote::{quote, ToTokens};
diff --git a/boa_macros/tests/tests.rs b/boa_macros/tests/tests.rs
index c3ece6489b1..f0888e0c61d 100644
--- a/boa_macros/tests/tests.rs
+++ b/boa_macros/tests/tests.rs
@@ -1,3 +1,5 @@
+#![allow(unused_crate_dependencies)]
+
 use boa_macros::utf16;
 
 #[test]
diff --git a/boa_macros_tests/Cargo.toml b/boa_macros_tests/Cargo.toml
index 9dca444385c..a4da3ee7ab6 100644
--- a/boa_macros_tests/Cargo.toml
+++ b/boa_macros_tests/Cargo.toml
@@ -14,3 +14,6 @@ rust-version.workspace = true
 trybuild = "1.0.85"
 boa_macros.workspace = true
 boa_engine.workspace = true
+
+[lints]
+workspace = true
diff --git a/boa_macros_tests/tests/derive/from_js_with.rs b/boa_macros_tests/tests/derive/from_js_with.rs
index a40bba62a6a..2fd5184d274 100644
--- a/boa_macros_tests/tests/derive/from_js_with.rs
+++ b/boa_macros_tests/tests/derive/from_js_with.rs
@@ -1,3 +1,5 @@
+#![allow(unused, unused_tuple_struct_fields)]
+
 use boa_engine::{value::TryFromJs, Context, JsNativeError, JsResult, JsValue};
 
 #[derive(TryFromJs)]
diff --git a/boa_macros_tests/tests/derive/simple_struct.rs b/boa_macros_tests/tests/derive/simple_struct.rs
index f9ea0c97b23..5249412bb63 100644
--- a/boa_macros_tests/tests/derive/simple_struct.rs
+++ b/boa_macros_tests/tests/derive/simple_struct.rs
@@ -1,3 +1,5 @@
+#![allow(unused, unused_tuple_struct_fields)]
+
 use boa_engine::value::TryFromJs;
 
 #[derive(TryFromJs)]
diff --git a/boa_macros_tests/tests/tests.rs b/boa_macros_tests/tests/tests.rs
index 16de9065e06..d94f31d8b65 100644
--- a/boa_macros_tests/tests/tests.rs
+++ b/boa_macros_tests/tests/tests.rs
@@ -1,3 +1,5 @@
+#![allow(unused_crate_dependencies, unused_tuple_struct_fields)]
+
 #[test]
 fn try_from_js() {
     let t = trybuild::TestCases::new();
diff --git a/boa_parser/Cargo.toml b/boa_parser/Cargo.toml
index 3ca20507b29..0207b59d84a 100644
--- a/boa_parser/Cargo.toml
+++ b/boa_parser/Cargo.toml
@@ -26,3 +26,6 @@ icu_properties.workspace = true
 [features]
 annex-b = []
 temporal = ["boa_ast/temporal"]
+
+[lints]
+workspace = true
diff --git a/boa_parser/src/lib.rs b/boa_parser/src/lib.rs
index 13aa2e56c0d..ab6370c516f 100644
--- a/boa_parser/src/lib.rs
+++ b/boa_parser/src/lib.rs
@@ -14,60 +14,8 @@
     html_logo_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg",
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
+#![cfg_attr(test, allow(clippy::needless_raw_string_hashes))] // Makes strings a bit more copy-pastable
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 #![allow(
     clippy::module_name_repetitions,
     clippy::too_many_lines,
diff --git a/boa_parser/src/parser/tests/test.js b/boa_parser/src/parser/tests/test.js
new file mode 100644
index 00000000000..e292865b735
--- /dev/null
+++ b/boa_parser/src/parser/tests/test.js
@@ -0,0 +1 @@
+"Hello" + "World";
diff --git a/boa_parser/src/source.rs b/boa_parser/src/source.rs
index af60e9467ed..fb37e50ce16 100644
--- a/boa_parser/src/source.rs
+++ b/boa_parser/src/source.rs
@@ -90,7 +90,7 @@ impl<'path, R: Read> Source<'path, R> {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use std::{fs, io::Cursor};
+    use std::io::Cursor;
 
     #[test]
     fn from_bytes() {
@@ -106,15 +106,16 @@ mod tests {
 
     #[test]
     fn from_filepath() {
-        fs::write("test.js", "'Hello' + 'World';").unwrap();
-        let mut source = Source::from_filepath("test.js".as_ref()).unwrap();
+        let manifest_path = Path::new(env!("CARGO_MANIFEST_DIR"));
+        let filepath = manifest_path.join("src/parser/tests/test.js");
+        let mut source = Source::from_filepath(&filepath).unwrap();
 
-        assert_eq!(source.path, Some("test.js".as_ref()));
+        assert_eq!(source.path, Some(&*filepath));
 
         let mut content = String::new();
         source.reader.read_to_string(&mut content).unwrap();
 
-        assert_eq!(content, "'Hello' + 'World';");
+        assert_eq!(content, "\"Hello\" + \"World\";\n");
     }
 
     #[test]
diff --git a/boa_profiler/Cargo.toml b/boa_profiler/Cargo.toml
index 28eec85eb18..86edbf43c56 100644
--- a/boa_profiler/Cargo.toml
+++ b/boa_profiler/Cargo.toml
@@ -17,3 +17,6 @@ profiler = ["dep:measureme", "dep:once_cell", "dep:rustc-hash"]
 measureme = { version = "10.1.1", optional = true }
 once_cell = { workspace = true, optional = true, features = ["std"] }
 rustc-hash = { workspace = true, optional = true }
+
+[lints]
+workspace = true
diff --git a/boa_profiler/src/lib.rs b/boa_profiler/src/lib.rs
index 2723c958c04..69d1927cab1 100644
--- a/boa_profiler/src/lib.rs
+++ b/boa_profiler/src/lib.rs
@@ -12,59 +12,6 @@
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 #![cfg_attr(not(feature = "profiler"), no_std)]
 
 use core::fmt::{self, Debug};
diff --git a/boa_runtime/Cargo.toml b/boa_runtime/Cargo.toml
index 655f9bc767f..f9e0ee974b8 100644
--- a/boa_runtime/Cargo.toml
+++ b/boa_runtime/Cargo.toml
@@ -18,3 +18,6 @@ rustc-hash = { workspace = true, features = ["std"] }
 [dev-dependencies]
 indoc.workspace = true
 textwrap.workspace = true
+
+[lints]
+workspace = true
diff --git a/boa_runtime/src/lib.rs b/boa_runtime/src/lib.rs
index d3e71b29c59..93ff44feff6 100644
--- a/boa_runtime/src/lib.rs
+++ b/boa_runtime/src/lib.rs
@@ -43,60 +43,8 @@
     html_logo_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg",
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
+#![cfg_attr(test, allow(clippy::needless_raw_string_hashes))] // Makes strings a bit more copy-pastable
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 #![allow(
     clippy::module_name_repetitions,
     clippy::redundant_pub_crate,
diff --git a/boa_tester/Cargo.toml b/boa_tester/Cargo.toml
index d4e2d45d94d..c4d95a11df9 100644
--- a/boa_tester/Cargo.toml
+++ b/boa_tester/Cargo.toml
@@ -34,3 +34,6 @@ bus = "2.4.1"
 
 [features]
 default = ["boa_engine/intl", "boa_engine/experimental", "boa_engine/annex-b"]
+
+[lints]
+workspace = true
diff --git a/boa_tester/src/main.rs b/boa_tester/src/main.rs
index 1271f396bbe..0305d2f4b78 100644
--- a/boa_tester/src/main.rs
+++ b/boa_tester/src/main.rs
@@ -8,59 +8,6 @@
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
 #![cfg_attr(not(test), deny(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 #![allow(
     clippy::too_many_lines,
     clippy::redundant_pub_crate,
diff --git a/boa_wasm/Cargo.toml b/boa_wasm/Cargo.toml
index 7c0b2f571e4..8dcdd89312b 100644
--- a/boa_wasm/Cargo.toml
+++ b/boa_wasm/Cargo.toml
@@ -25,3 +25,6 @@ default = ["boa_engine/annex-b", "boa_engine/intl", "boa_engine/experimental"]
 crate-type = ["cdylib", "lib"]
 name = "boa_wasm"
 bench = false
+
+[lints]
+workspace = true
diff --git a/boa_wasm/src/lib.rs b/boa_wasm/src/lib.rs
index 45027194b3e..57e18379557 100644
--- a/boa_wasm/src/lib.rs
+++ b/boa_wasm/src/lib.rs
@@ -5,59 +5,6 @@
     html_favicon_url = "https://raw.githubusercontent.com/boa-dev/boa/main/assets/logo.svg"
 )]
 #![cfg_attr(not(test), forbid(clippy::unwrap_used))]
-#![warn(
-    // rustc lint groups https://doc.rust-lang.org/rustc/lints/groups.html
-    warnings,
-    future_incompatible,
-    let_underscore,
-    nonstandard_style,
-    rust_2018_compatibility,
-    rust_2018_idioms,
-    rust_2021_compatibility,
-    unused,
-
-    // rustc allowed-by-default lints https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html
-    missing_docs,
-    macro_use_extern_crate,
-    meta_variable_misuse,
-    missing_abi,
-    missing_copy_implementations,
-    missing_debug_implementations,
-    non_ascii_idents,
-    noop_method_call,
-    single_use_lifetimes,
-    trivial_casts,
-    trivial_numeric_casts,
-    unreachable_pub,
-    unsafe_op_in_unsafe_fn,
-    unused_crate_dependencies,
-    unused_import_braces,
-    unused_lifetimes,
-    unused_qualifications,
-    unused_tuple_struct_fields,
-    variant_size_differences,
-
-    // rustdoc lints https://doc.rust-lang.org/rustdoc/lints.html
-    rustdoc::broken_intra_doc_links,
-    rustdoc::private_intra_doc_links,
-    rustdoc::missing_crate_level_docs,
-    rustdoc::private_doc_tests,
-    rustdoc::invalid_codeblock_attributes,
-    rustdoc::invalid_rust_codeblocks,
-    rustdoc::bare_urls,
-
-    // clippy allowed by default
-    clippy::dbg_macro,
-
-    // clippy categories https://doc.rust-lang.org/clippy/
-    clippy::all,
-    clippy::correctness,
-    clippy::suspicious,
-    clippy::style,
-    clippy::complexity,
-    clippy::perf,
-    clippy::pedantic,
-)]
 
 use boa_engine::{Context, Source};
 use chrono as _;
@@ -70,6 +17,10 @@ fn main() {
 }
 
 /// Evaluate the given ECMAScript code.
+///
+/// # Errors
+///
+/// If the execution of the script throws, returns a `JsValue` with the error string.
 #[wasm_bindgen]
 pub fn evaluate(src: &str) -> Result<String, JsValue> {
     // Setup the executor