From ced222fdbabacc695f8f081c5b009afc9be6b8d0 Mon Sep 17 00:00:00 2001
From: Haled Odat <8566042+HalidOdat@users.noreply.github.com>
Date: Sun, 12 May 2024 21:48:06 +0200
Subject: [PATCH] Separate `JsString` into its own crate (#3837)
---
ABOUT.md | 2 +
Cargo.lock | 16 +-
Cargo.toml | 1 +
cli/ABOUT.md | 2 +
core/ast/ABOUT.md | 2 +
core/engine/ABOUT.md | 2 +
core/engine/Cargo.toml | 5 +-
core/engine/src/builtins/array/mod.rs | 2 +-
core/engine/src/builtins/array_buffer/mod.rs | 2 +-
.../src/builtins/array_buffer/shared.rs | 2 +-
.../engine/src/builtins/async_function/mod.rs | 2 +-
.../src/builtins/async_generator/mod.rs | 2 +-
.../builtins/async_generator_function/mod.rs | 2 +-
core/engine/src/builtins/atomics/mod.rs | 2 +-
core/engine/src/builtins/bigint/mod.rs | 2 +-
core/engine/src/builtins/boolean/mod.rs | 2 +-
core/engine/src/builtins/builder.rs | 2 +-
core/engine/src/builtins/dataview/mod.rs | 2 +-
core/engine/src/builtins/date/mod.rs | 2 +-
core/engine/src/builtins/error/aggregate.rs | 2 +-
core/engine/src/builtins/error/eval.rs | 2 +-
core/engine/src/builtins/error/mod.rs | 2 +-
core/engine/src/builtins/error/range.rs | 2 +-
core/engine/src/builtins/error/reference.rs | 2 +-
core/engine/src/builtins/error/syntax.rs | 2 +-
core/engine/src/builtins/error/type.rs | 2 +-
core/engine/src/builtins/error/uri.rs | 2 +-
core/engine/src/builtins/escape/mod.rs | 4 +-
core/engine/src/builtins/eval/mod.rs | 2 +-
core/engine/src/builtins/function/mod.rs | 2 +-
core/engine/src/builtins/generator/mod.rs | 2 +-
.../src/builtins/generator_function/mod.rs | 2 +-
core/engine/src/builtins/intl/collator/mod.rs | 2 +-
.../src/builtins/intl/date_time_format.rs | 2 +-
.../src/builtins/intl/list_format/mod.rs | 2 +-
core/engine/src/builtins/intl/locale/mod.rs | 2 +-
core/engine/src/builtins/intl/mod.rs | 2 +-
.../src/builtins/intl/number_format/mod.rs | 2 +-
.../src/builtins/intl/plural_rules/mod.rs | 2 +-
.../engine/src/builtins/intl/segmenter/mod.rs | 2 +-
core/engine/src/builtins/json/mod.rs | 2 +-
core/engine/src/builtins/map/mod.rs | 2 +-
core/engine/src/builtins/math/mod.rs | 4 +-
core/engine/src/builtins/number/globals.rs | 2 +-
core/engine/src/builtins/number/mod.rs | 2 +-
core/engine/src/builtins/object/mod.rs | 2 +-
core/engine/src/builtins/promise/mod.rs | 2 +-
core/engine/src/builtins/proxy/mod.rs | 2 +-
core/engine/src/builtins/reflect/mod.rs | 2 +-
core/engine/src/builtins/regexp/mod.rs | 2 +-
core/engine/src/builtins/set/mod.rs | 2 +-
core/engine/src/builtins/string/mod.rs | 19 +-
core/engine/src/builtins/symbol/mod.rs | 2 +-
.../src/builtins/temporal/calendar/mod.rs | 2 +-
.../src/builtins/temporal/duration/mod.rs | 2 +-
.../src/builtins/temporal/instant/mod.rs | 2 +-
core/engine/src/builtins/temporal/mod.rs | 2 +-
core/engine/src/builtins/temporal/now.rs | 2 +-
.../src/builtins/temporal/plain_date/mod.rs | 2 +-
.../builtins/temporal/plain_date_time/mod.rs | 2 +-
.../builtins/temporal/plain_month_day/mod.rs | 2 +-
.../src/builtins/temporal/plain_time/mod.rs | 2 +-
.../builtins/temporal/plain_year_month/mod.rs | 2 +-
.../src/builtins/temporal/time_zone/mod.rs | 2 +-
.../builtins/temporal/zoned_date_time/mod.rs | 2 +-
.../src/builtins/typed_array/builtin.rs | 2 +-
core/engine/src/builtins/typed_array/mod.rs | 2 +-
core/engine/src/builtins/uri/mod.rs | 2 +-
core/engine/src/builtins/weak/weak_ref.rs | 2 +-
core/engine/src/builtins/weak_map/mod.rs | 2 +-
core/engine/src/builtins/weak_set/mod.rs | 2 +-
core/engine/src/object/mod.rs | 2 +-
core/engine/src/object/operations.rs | 2 +-
core/engine/src/string.rs | 211 ++++
core/engine/src/string/common.rs | 950 -----------------
core/engine/src/symbol.rs | 2 +-
core/engine/src/tagged.rs | 1 +
core/engine/src/vm/opcode/push/array.rs | 2 +-
core/gc/ABOUT.md | 2 +
core/gc/Cargo.toml | 3 +
core/gc/src/trace.rs | 12 +
core/icu_provider/ABOUT.md | 2 +
core/interner/ABOUT.md | 2 +
core/interop/ABOUT.md | 2 +
core/macros/ABOUT.md | 2 +
core/parser/ABOUT.md | 2 +
core/profiler/ABOUT.md | 2 +
core/runtime/ABOUT.md | 2 +
core/string/ABOUT.md | 34 +
core/string/Cargo.toml | 28 +
core/string/src/common.rs | 951 ++++++++++++++++++
.../{engine/src/string => string/src}/iter.rs | 4 +
.../src/string/mod.rs => string/src/lib.rs} | 369 ++-----
core/{engine/src/string => string/src}/str.rs | 17 +-
core/string/src/tagged.rs | 109 ++
core/string/src/tests.rs | 166 +++
96 files changed, 1750 insertions(+), 1308 deletions(-)
create mode 100644 core/engine/src/string.rs
delete mode 100644 core/engine/src/string/common.rs
create mode 100644 core/string/ABOUT.md
create mode 100644 core/string/Cargo.toml
create mode 100644 core/string/src/common.rs
rename core/{engine/src/string => string/src}/iter.rs (97%)
rename core/{engine/src/string/mod.rs => string/src/lib.rs} (82%)
rename core/{engine/src/string => string/src}/str.rs (96%)
create mode 100644 core/string/src/tagged.rs
create mode 100644 core/string/src/tests.rs
diff --git a/ABOUT.md b/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/ABOUT.md
+++ b/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/Cargo.lock b/Cargo.lock
index 3889476774..2a012fc602 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -395,6 +395,7 @@ dependencies = [
"boa_macros",
"boa_parser",
"boa_profiler",
+ "boa_string",
"bytemuck",
"cfg-if",
"criterion",
@@ -427,7 +428,6 @@ dependencies = [
"num-traits",
"num_enum",
"once_cell",
- "paste",
"pollster",
"portable-atomic",
"rand",
@@ -437,7 +437,6 @@ dependencies = [
"serde",
"serde_json",
"sptr",
- "static_assertions",
"sys-locale",
"tap",
"temporal_rs",
@@ -475,6 +474,7 @@ version = "0.18.0"
dependencies = [
"boa_macros",
"boa_profiler",
+ "boa_string",
"hashbrown 0.14.5",
"icu_locid",
"thin-vec",
@@ -571,6 +571,18 @@ dependencies = [
"textwrap",
]
+[[package]]
+name = "boa_string"
+version = "0.18.0"
+dependencies = [
+ "boa_macros",
+ "fast-float",
+ "paste",
+ "rustc-hash",
+ "sptr",
+ "static_assertions",
+]
+
[[package]]
name = "boa_tester"
version = "0.18.0"
diff --git a/Cargo.toml b/Cargo.toml
index 75650ecd0b..ac1c3bf75d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -47,6 +47,7 @@ boa_macros = { version = "~0.18.0", path = "core/macros" }
boa_parser = { version = "~0.18.0", path = "core/parser" }
boa_profiler = { version = "~0.18.0", path = "core/profiler" }
boa_runtime = { version = "~0.18.0", path = "core/runtime" }
+boa_string = { version = "~0.18.0", path = "core/string" }
# Shared deps
arbitrary = "1"
diff --git a/cli/ABOUT.md b/cli/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/cli/ABOUT.md
+++ b/cli/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/ast/ABOUT.md b/core/ast/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/ast/ABOUT.md
+++ b/core/ast/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/engine/ABOUT.md b/core/engine/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/engine/ABOUT.md
+++ b/core/engine/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/engine/Cargo.toml b/core/engine/Cargo.toml
index 40883df1bd..73502507c1 100644
--- a/core/engine/Cargo.toml
+++ b/core/engine/Cargo.toml
@@ -69,11 +69,12 @@ js = ["dep:web-time"]
[dependencies]
boa_interner.workspace = true
-boa_gc = { workspace = true, features = ["thin-vec"] }
+boa_gc = { workspace = true, features = ["thin-vec", "boa_string"] }
boa_profiler.workspace = true
boa_macros.workspace = true
boa_ast.workspace = true
boa_parser.workspace = true
+boa_string.workspace = true
serde = { workspace = true, features = ["derive", "rc"] }
serde_json.workspace = true
rand = "0.8.5"
@@ -89,7 +90,6 @@ fast-float.workspace = true
once_cell = { workspace = true, features = ["std"] }
tap = "1.0.1"
sptr = "0.3.2"
-static_assertions.workspace = true
thiserror = "1.0.59"
dashmap = "5.5.3"
num_enum = "0.7.2"
@@ -97,7 +97,6 @@ pollster.workspace = true
thin-vec.workspace = true
itertools = { version = "0.12.1", default-features = false }
icu_normalizer = { workspace = true, features = ["compiled_data"] }
-paste = "1.0"
portable-atomic = "1.6.0"
bytemuck = { version = "1.15.0", features = ["derive"] }
arrayvec = "0.7.4"
diff --git a/core/engine/src/builtins/array/mod.rs b/core/engine/src/builtins/array/mod.rs
index aa96247040..31472c605f 100644
--- a/core/engine/src/builtins/array/mod.rs
+++ b/core/engine/src/builtins/array/mod.rs
@@ -32,7 +32,7 @@ use crate::{
},
property::{Attribute, PropertyDescriptor, PropertyKey, PropertyNameKind},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::{IntegerOrInfinity, JsValue},
Context, JsArgs, JsResult, JsString,
diff --git a/core/engine/src/builtins/array_buffer/mod.rs b/core/engine/src/builtins/array_buffer/mod.rs
index 1145c26f82..d5ea40ab55 100644
--- a/core/engine/src/builtins/array_buffer/mod.rs
+++ b/core/engine/src/builtins/array_buffer/mod.rs
@@ -29,7 +29,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject, Object},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsData, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/array_buffer/shared.rs b/core/engine/src/builtins/array_buffer/shared.rs
index 790a15eda0..10c1092ee7 100644
--- a/core/engine/src/builtins/array_buffer/shared.rs
+++ b/core/engine/src/builtins/array_buffer/shared.rs
@@ -18,7 +18,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
diff --git a/core/engine/src/builtins/async_function/mod.rs b/core/engine/src/builtins/async_function/mod.rs
index 865510b4ea..f8db6134e9 100644
--- a/core/engine/src/builtins/async_function/mod.rs
+++ b/core/engine/src/builtins/async_function/mod.rs
@@ -12,7 +12,7 @@ use crate::{
context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/async_generator/mod.rs b/core/engine/src/builtins/async_generator/mod.rs
index 976dab93cf..6fa423ddbd 100644
--- a/core/engine/src/builtins/async_generator/mod.rs
+++ b/core/engine/src/builtins/async_generator/mod.rs
@@ -19,7 +19,7 @@ use crate::{
object::{FunctionObjectBuilder, JsObject, CONSTRUCTOR},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
vm::{CompletionRecord, GeneratorResumeKind},
diff --git a/core/engine/src/builtins/async_generator_function/mod.rs b/core/engine/src/builtins/async_generator_function/mod.rs
index 975bb842cd..c0ca21b09e 100644
--- a/core/engine/src/builtins/async_generator_function/mod.rs
+++ b/core/engine/src/builtins/async_generator_function/mod.rs
@@ -11,7 +11,7 @@ use crate::{
object::{JsObject, PROTOTYPE},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
Context, JsResult, JsString,
diff --git a/core/engine/src/builtins/atomics/mod.rs b/core/engine/src/builtins/atomics/mod.rs
index db74e6fbca..2d4ff957ae 100644
--- a/core/engine/src/builtins/atomics/mod.rs
+++ b/core/engine/src/builtins/atomics/mod.rs
@@ -16,7 +16,7 @@ use std::sync::atomic::Ordering;
use crate::{
builtins::BuiltInObject, context::intrinsics::Intrinsics, js_string, object::JsObject,
- property::Attribute, realm::Realm, string::common::StaticJsStrings, symbol::JsSymbol,
+ property::Attribute, realm::Realm, string::StaticJsStrings, symbol::JsSymbol,
sys::time::Duration, value::IntegerOrInfinity, Context, JsArgs, JsNativeError, JsResult,
JsString, JsValue,
};
diff --git a/core/engine/src/builtins/bigint/mod.rs b/core/engine/src/builtins/bigint/mod.rs
index 3dc75356b1..947183afa5 100644
--- a/core/engine/src/builtins/bigint/mod.rs
+++ b/core/engine/src/builtins/bigint/mod.rs
@@ -20,7 +20,7 @@ use crate::{
object::JsObject,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::{IntegerOrInfinity, PreferredType},
Context, JsArgs, JsBigInt, JsResult, JsString, JsValue,
diff --git a/core/engine/src/builtins/boolean/mod.rs b/core/engine/src/builtins/boolean/mod.rs
index 3ae156b44b..b33525a023 100644
--- a/core/engine/src/builtins/boolean/mod.rs
+++ b/core/engine/src/builtins/boolean/mod.rs
@@ -19,7 +19,7 @@ use crate::{
js_string,
object::{internal_methods::get_prototype_from_constructor, JsObject},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsResult, JsString, JsValue,
};
use boa_profiler::Profiler;
diff --git a/core/engine/src/builtins/builder.rs b/core/engine/src/builtins/builder.rs
index c87b9ab729..610a910db3 100644
--- a/core/engine/src/builtins/builder.rs
+++ b/core/engine/src/builtins/builder.rs
@@ -9,7 +9,7 @@ use crate::{
},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
JsObject, JsString, JsValue, NativeFunction,
};
diff --git a/core/engine/src/builtins/dataview/mod.rs b/core/engine/src/builtins/dataview/mod.rs
index 7274cc1fd9..dd8dfef309 100644
--- a/core/engine/src/builtins/dataview/mod.rs
+++ b/core/engine/src/builtins/dataview/mod.rs
@@ -17,7 +17,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
Context, JsArgs, JsData, JsResult, JsString,
diff --git a/core/engine/src/builtins/date/mod.rs b/core/engine/src/builtins/date/mod.rs
index 49be23c5f8..17304c6e5e 100644
--- a/core/engine/src/builtins/date/mod.rs
+++ b/core/engine/src/builtins/date/mod.rs
@@ -27,7 +27,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::{JsValue, PreferredType},
Context, JsArgs, JsData, JsError, JsResult, JsString,
diff --git a/core/engine/src/builtins/error/aggregate.rs b/core/engine/src/builtins/error/aggregate.rs
index bc4b9c3292..6a8042df31 100644
--- a/core/engine/src/builtins/error/aggregate.rs
+++ b/core/engine/src/builtins/error/aggregate.rs
@@ -17,7 +17,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::{Attribute, PropertyDescriptorBuilder},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsString, JsValue,
};
use boa_macros::js_str;
diff --git a/core/engine/src/builtins/error/eval.rs b/core/engine/src/builtins/error/eval.rs
index 266fd82053..88f6d21f0d 100644
--- a/core/engine/src/builtins/error/eval.rs
+++ b/core/engine/src/builtins/error/eval.rs
@@ -18,7 +18,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsString, JsValue,
};
use boa_macros::js_str;
diff --git a/core/engine/src/builtins/error/mod.rs b/core/engine/src/builtins/error/mod.rs
index ed005d0e38..39911f7115 100644
--- a/core/engine/src/builtins/error/mod.rs
+++ b/core/engine/src/builtins/error/mod.rs
@@ -18,7 +18,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsResult, JsString, JsValue,
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/builtins/error/range.rs b/core/engine/src/builtins/error/range.rs
index cc192396c3..15cf63d64f 100644
--- a/core/engine/src/builtins/error/range.rs
+++ b/core/engine/src/builtins/error/range.rs
@@ -16,7 +16,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsString, JsValue,
};
use boa_macros::js_str;
diff --git a/core/engine/src/builtins/error/reference.rs b/core/engine/src/builtins/error/reference.rs
index eb8a115862..f56f6b403a 100644
--- a/core/engine/src/builtins/error/reference.rs
+++ b/core/engine/src/builtins/error/reference.rs
@@ -16,7 +16,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsString, JsValue,
};
use boa_macros::js_str;
diff --git a/core/engine/src/builtins/error/syntax.rs b/core/engine/src/builtins/error/syntax.rs
index 9074856694..70333aaa10 100644
--- a/core/engine/src/builtins/error/syntax.rs
+++ b/core/engine/src/builtins/error/syntax.rs
@@ -18,7 +18,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsString, JsValue,
};
use boa_macros::js_str;
diff --git a/core/engine/src/builtins/error/type.rs b/core/engine/src/builtins/error/type.rs
index 3b3223d0fb..364afba24d 100644
--- a/core/engine/src/builtins/error/type.rs
+++ b/core/engine/src/builtins/error/type.rs
@@ -24,7 +24,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsString, JsValue, NativeFunction,
};
use boa_macros::js_str;
diff --git a/core/engine/src/builtins/error/uri.rs b/core/engine/src/builtins/error/uri.rs
index fcf7b1d208..36e6f275bc 100644
--- a/core/engine/src/builtins/error/uri.rs
+++ b/core/engine/src/builtins/error/uri.rs
@@ -17,7 +17,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsString, JsValue,
};
use boa_macros::js_str;
diff --git a/core/engine/src/builtins/escape/mod.rs b/core/engine/src/builtins/escape/mod.rs
index e3fcf1cb2b..dc11cd0ae3 100644
--- a/core/engine/src/builtins/escape/mod.rs
+++ b/core/engine/src/builtins/escape/mod.rs
@@ -11,8 +11,8 @@
//! [spec]: https://tc39.es/ecma262/#sec-additional-properties-of-the-global-object
use crate::{
- context::intrinsics::Intrinsics, js_string, realm::Realm, string::common::StaticJsStrings,
- Context, JsArgs, JsObject, JsResult, JsString, JsValue,
+ context::intrinsics::Intrinsics, js_string, realm::Realm, string::StaticJsStrings, Context,
+ JsArgs, JsObject, JsResult, JsString, JsValue,
};
use super::{BuiltInBuilder, BuiltInObject, IntrinsicObject};
diff --git a/core/engine/src/builtins/eval/mod.rs b/core/engine/src/builtins/eval/mod.rs
index 2026208ab7..8982c716c0 100644
--- a/core/engine/src/builtins/eval/mod.rs
+++ b/core/engine/src/builtins/eval/mod.rs
@@ -20,7 +20,7 @@ use crate::{
js_string,
object::JsObject,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
vm::{CallFrame, CallFrameFlags, Opcode},
Context, JsArgs, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/function/mod.rs b/core/engine/src/builtins/function/mod.rs
index 653a402ec7..1bf76b5e82 100644
--- a/core/engine/src/builtins/function/mod.rs
+++ b/core/engine/src/builtins/function/mod.rs
@@ -30,7 +30,7 @@ use crate::{
},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::IntegerOrInfinity,
vm::{ActiveRunnable, CallFrame, CallFrameFlags, CodeBlock},
diff --git a/core/engine/src/builtins/generator/mod.rs b/core/engine/src/builtins/generator/mod.rs
index 3a9d56aa5b..da8e38d181 100644
--- a/core/engine/src/builtins/generator/mod.rs
+++ b/core/engine/src/builtins/generator/mod.rs
@@ -17,7 +17,7 @@ use crate::{
object::{JsObject, CONSTRUCTOR},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
vm::{CallFrame, CallFrameFlags, CompletionRecord, GeneratorResumeKind},
diff --git a/core/engine/src/builtins/generator_function/mod.rs b/core/engine/src/builtins/generator_function/mod.rs
index 300600d1ec..c4687f1b05 100644
--- a/core/engine/src/builtins/generator_function/mod.rs
+++ b/core/engine/src/builtins/generator_function/mod.rs
@@ -16,7 +16,7 @@ use crate::{
object::PROTOTYPE,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
Context, JsResult, JsString,
diff --git a/core/engine/src/builtins/intl/collator/mod.rs b/core/engine/src/builtins/intl/collator/mod.rs
index a99aec57a6..edbb931436 100644
--- a/core/engine/src/builtins/intl/collator/mod.rs
+++ b/core/engine/src/builtins/intl/collator/mod.rs
@@ -29,7 +29,7 @@ use crate::{
},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsData, JsNativeError, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/intl/date_time_format.rs b/core/engine/src/builtins/intl/date_time_format.rs
index 0dff2fe4dd..f6dca66bfc 100644
--- a/core/engine/src/builtins/intl/date_time_format.rs
+++ b/core/engine/src/builtins/intl/date_time_format.rs
@@ -17,7 +17,7 @@ use crate::{
js_string,
object::{internal_methods::get_prototype_from_constructor, JsObject},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsData, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/intl/list_format/mod.rs b/core/engine/src/builtins/intl/list_format/mod.rs
index c76889ffae..6bc069570e 100644
--- a/core/engine/src/builtins/intl/list_format/mod.rs
+++ b/core/engine/src/builtins/intl/list_format/mod.rs
@@ -17,7 +17,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsData, JsNativeError, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/intl/locale/mod.rs b/core/engine/src/builtins/intl/locale/mod.rs
index a70ab770f6..9c1afe0bd2 100644
--- a/core/engine/src/builtins/intl/locale/mod.rs
+++ b/core/engine/src/builtins/intl/locale/mod.rs
@@ -1,4 +1,4 @@
-use crate::{builtins::options::get_option, realm::Realm, string::common::StaticJsStrings};
+use crate::{builtins::options::get_option, realm::Realm, string::StaticJsStrings};
use boa_macros::js_str;
use boa_profiler::Profiler;
use icu_collator::CaseFirst;
diff --git a/core/engine/src/builtins/intl/mod.rs b/core/engine/src/builtins/intl/mod.rs
index 149babe56b..5f033a7568 100644
--- a/core/engine/src/builtins/intl/mod.rs
+++ b/core/engine/src/builtins/intl/mod.rs
@@ -20,7 +20,7 @@ use crate::{
object::JsObject,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsData, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/intl/number_format/mod.rs b/core/engine/src/builtins/intl/number_format/mod.rs
index 3b63fca375..a94d8e56cc 100644
--- a/core/engine/src/builtins/intl/number_format/mod.rs
+++ b/core/engine/src/builtins/intl/number_format/mod.rs
@@ -32,7 +32,7 @@ use crate::{
},
property::{Attribute, PropertyDescriptor},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
value::PreferredType,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
NativeFunction,
diff --git a/core/engine/src/builtins/intl/plural_rules/mod.rs b/core/engine/src/builtins/intl/plural_rules/mod.rs
index d0dad83b30..917e85c191 100644
--- a/core/engine/src/builtins/intl/plural_rules/mod.rs
+++ b/core/engine/src/builtins/intl/plural_rules/mod.rs
@@ -21,7 +21,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, ObjectInitializer},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsStr, JsString, JsSymbol, JsValue,
};
diff --git a/core/engine/src/builtins/intl/segmenter/mod.rs b/core/engine/src/builtins/intl/segmenter/mod.rs
index 517e359b68..7353acfef5 100644
--- a/core/engine/src/builtins/intl/segmenter/mod.rs
+++ b/core/engine/src/builtins/intl/segmenter/mod.rs
@@ -18,7 +18,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectInitializer},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsResult, JsStr, JsString, JsSymbol, JsValue,
};
diff --git a/core/engine/src/builtins/json/mod.rs b/core/engine/src/builtins/json/mod.rs
index af6a4513ba..52e8debde2 100644
--- a/core/engine/src/builtins/json/mod.rs
+++ b/core/engine/src/builtins/json/mod.rs
@@ -27,7 +27,7 @@ use crate::{
object::{internal_methods::InternalMethodContext, JsObject},
property::{Attribute, PropertyNameKind},
realm::Realm,
- string::{common::StaticJsStrings, CodePoint},
+ string::{CodePoint, StaticJsStrings},
symbol::JsSymbol,
value::IntegerOrInfinity,
vm::{CallFrame, CallFrameFlags},
diff --git a/core/engine/src/builtins/map/mod.rs b/core/engine/src/builtins/map/mod.rs
index c5c4edee46..ef8eaad1e5 100644
--- a/core/engine/src/builtins/map/mod.rs
+++ b/core/engine/src/builtins/map/mod.rs
@@ -18,7 +18,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::{Attribute, PropertyNameKind},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/math/mod.rs b/core/engine/src/builtins/math/mod.rs
index 13d5748c07..424aed1e2d 100644
--- a/core/engine/src/builtins/math/mod.rs
+++ b/core/engine/src/builtins/math/mod.rs
@@ -13,8 +13,8 @@
use crate::{
builtins::BuiltInObject, context::intrinsics::Intrinsics, js_string, object::JsObject,
- property::Attribute, realm::Realm, string::common::StaticJsStrings, symbol::JsSymbol, Context,
- JsArgs, JsResult, JsString, JsValue,
+ property::Attribute, realm::Realm, string::StaticJsStrings, symbol::JsSymbol, Context, JsArgs,
+ JsResult, JsString, JsValue,
};
use boa_profiler::Profiler;
diff --git a/core/engine/src/builtins/number/globals.rs b/core/engine/src/builtins/number/globals.rs
index 1900fa850c..9564d4de92 100644
--- a/core/engine/src/builtins/number/globals.rs
+++ b/core/engine/src/builtins/number/globals.rs
@@ -3,7 +3,7 @@ use crate::{
context::intrinsics::Intrinsics,
object::JsObject,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsResult, JsStr, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/number/mod.rs b/core/engine/src/builtins/number/mod.rs
index 025c25acf6..7334591278 100644
--- a/core/engine/src/builtins/number/mod.rs
+++ b/core/engine/src/builtins/number/mod.rs
@@ -21,7 +21,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
value::{AbstractRelation, IntegerOrInfinity, JsValue},
Context, JsArgs, JsResult, JsString,
};
diff --git a/core/engine/src/builtins/object/mod.rs b/core/engine/src/builtins/object/mod.rs
index a0fe635191..92d2abe835 100644
--- a/core/engine/src/builtins/object/mod.rs
+++ b/core/engine/src/builtins/object/mod.rs
@@ -28,7 +28,7 @@ use crate::{
},
property::{Attribute, PropertyDescriptor, PropertyKey, PropertyNameKind},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
Context, JsArgs, JsData, JsResult, JsString,
diff --git a/core/engine/src/builtins/promise/mod.rs b/core/engine/src/builtins/promise/mod.rs
index b3fc4d103f..0578ad98eb 100644
--- a/core/engine/src/builtins/promise/mod.rs
+++ b/core/engine/src/builtins/promise/mod.rs
@@ -17,7 +17,7 @@ use crate::{
},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
Context, JsArgs, JsError, JsResult, JsString,
diff --git a/core/engine/src/builtins/proxy/mod.rs b/core/engine/src/builtins/proxy/mod.rs
index ea0d032910..ff6327c63c 100644
--- a/core/engine/src/builtins/proxy/mod.rs
+++ b/core/engine/src/builtins/proxy/mod.rs
@@ -26,7 +26,7 @@ use crate::{
},
property::{PropertyDescriptor, PropertyKey},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
value::Type,
Context, JsArgs, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/reflect/mod.rs b/core/engine/src/builtins/reflect/mod.rs
index f4d405adf7..841a24d4b3 100644
--- a/core/engine/src/builtins/reflect/mod.rs
+++ b/core/engine/src/builtins/reflect/mod.rs
@@ -19,7 +19,7 @@ use crate::{
object::{internal_methods::InternalMethodContext, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/regexp/mod.rs b/core/engine/src/builtins/regexp/mod.rs
index 34be1ef965..beb782af1a 100644
--- a/core/engine/src/builtins/regexp/mod.rs
+++ b/core/engine/src/builtins/regexp/mod.rs
@@ -17,7 +17,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject, CONSTRUCTOR},
property::Attribute,
realm::Realm,
- string::{common::StaticJsStrings, CodePoint, JsStrVariant},
+ string::{CodePoint, JsStrVariant, StaticJsStrings},
symbol::JsSymbol,
value::JsValue,
Context, JsArgs, JsData, JsResult, JsString,
diff --git a/core/engine/src/builtins/set/mod.rs b/core/engine/src/builtins/set/mod.rs
index a82f8c973f..2927a9e846 100644
--- a/core/engine/src/builtins/set/mod.rs
+++ b/core/engine/src/builtins/set/mod.rs
@@ -26,7 +26,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::{Attribute, PropertyNameKind},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/string/mod.rs b/core/engine/src/builtins/string/mod.rs
index a49f08a186..f0a3d8ce34 100644
--- a/core/engine/src/builtins/string/mod.rs
+++ b/core/engine/src/builtins/string/mod.rs
@@ -17,7 +17,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::{Attribute, PropertyDescriptor},
realm::Realm,
- string::{common::StaticJsStrings, CodePoint},
+ string::{CodePoint, StaticJsStrings},
symbol::JsSymbol,
value::IntegerOrInfinity,
Context, JsArgs, JsResult, JsString, JsValue,
@@ -73,23 +73,6 @@ pub(crate) const fn is_trimmable_whitespace(c: char) -> bool {
)
}
-/// Helper function to check if a `u8` latin1 character is trimmable.
-pub(crate) const fn is_trimmable_whitespace_latin1(c: u8) -> bool {
- // The rust implementation of `trim` does not regard the same characters whitespace as ecma standard does
- //
- // Rust uses \p{White_Space} by default, which also includes:
- // `\u{0085}' (next line)
- // And does not include:
- // '\u{FEFF}' (zero width non-breaking space)
- // Explicit whitespace: https://tc39.es/ecma262/#sec-white-space
- matches!(
- c,
- 0x09 | 0x0B | 0x0C | 0x20 | 0xA0 |
- // Line terminators: https://tc39.es/ecma262/#sec-line-terminators
- 0x0A | 0x0D
- )
-}
-
/// JavaScript `String` implementation.
#[derive(Debug, Clone, Copy)]
pub(crate) struct String;
diff --git a/core/engine/src/builtins/symbol/mod.rs b/core/engine/src/builtins/symbol/mod.rs
index dd50afb104..ca18aee702 100644
--- a/core/engine/src/builtins/symbol/mod.rs
+++ b/core/engine/src/builtins/symbol/mod.rs
@@ -28,7 +28,7 @@ use crate::{
object::JsObject,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
Context, JsArgs, JsResult, JsString,
diff --git a/core/engine/src/builtins/temporal/calendar/mod.rs b/core/engine/src/builtins/temporal/calendar/mod.rs
index 2da4335a92..489e8f0163 100644
--- a/core/engine/src/builtins/temporal/calendar/mod.rs
+++ b/core/engine/src/builtins/temporal/calendar/mod.rs
@@ -18,7 +18,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{custom_trace, Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/duration/mod.rs b/core/engine/src/builtins/temporal/duration/mod.rs
index 8e242ae44a..f22ef7599c 100644
--- a/core/engine/src/builtins/temporal/duration/mod.rs
+++ b/core/engine/src/builtins/temporal/duration/mod.rs
@@ -10,7 +10,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/instant/mod.rs b/core/engine/src/builtins/temporal/instant/mod.rs
index 48335b5db3..d4c927e4ca 100644
--- a/core/engine/src/builtins/temporal/instant/mod.rs
+++ b/core/engine/src/builtins/temporal/instant/mod.rs
@@ -14,7 +14,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsBigInt, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol,
JsValue,
};
diff --git a/core/engine/src/builtins/temporal/mod.rs b/core/engine/src/builtins/temporal/mod.rs
index adb2688780..d8aa749aaa 100644
--- a/core/engine/src/builtins/temporal/mod.rs
+++ b/core/engine/src/builtins/temporal/mod.rs
@@ -33,7 +33,7 @@ use crate::{
js_string,
property::{Attribute, PropertyKey},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
value::Type,
Context, JsBigInt, JsError, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
diff --git a/core/engine/src/builtins/temporal/now.rs b/core/engine/src/builtins/temporal/now.rs
index 4e13a3424d..0578244144 100644
--- a/core/engine/src/builtins/temporal/now.rs
+++ b/core/engine/src/builtins/temporal/now.rs
@@ -9,7 +9,7 @@ use crate::{
js_string,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
sys::time::SystemTime,
Context, JsBigInt, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
diff --git a/core/engine/src/builtins/temporal/plain_date/mod.rs b/core/engine/src/builtins/temporal/plain_date/mod.rs
index aac77d7e01..558d8121a6 100644
--- a/core/engine/src/builtins/temporal/plain_date/mod.rs
+++ b/core/engine/src/builtins/temporal/plain_date/mod.rs
@@ -13,7 +13,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/plain_date_time/mod.rs b/core/engine/src/builtins/temporal/plain_date_time/mod.rs
index 462b1caf33..55e4d81562 100644
--- a/core/engine/src/builtins/temporal/plain_date_time/mod.rs
+++ b/core/engine/src/builtins/temporal/plain_date_time/mod.rs
@@ -11,7 +11,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/plain_month_day/mod.rs b/core/engine/src/builtins/temporal/plain_month_day/mod.rs
index 3cdc17652b..62e483ab2b 100644
--- a/core/engine/src/builtins/temporal/plain_month_day/mod.rs
+++ b/core/engine/src/builtins/temporal/plain_month_day/mod.rs
@@ -6,7 +6,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/plain_time/mod.rs b/core/engine/src/builtins/temporal/plain_time/mod.rs
index 846b23cc63..adba3b53ed 100644
--- a/core/engine/src/builtins/temporal/plain_time/mod.rs
+++ b/core/engine/src/builtins/temporal/plain_time/mod.rs
@@ -10,7 +10,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/plain_year_month/mod.rs b/core/engine/src/builtins/temporal/plain_year_month/mod.rs
index c651534b5d..4b06c7ae46 100644
--- a/core/engine/src/builtins/temporal/plain_year_month/mod.rs
+++ b/core/engine/src/builtins/temporal/plain_year_month/mod.rs
@@ -7,7 +7,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/time_zone/mod.rs b/core/engine/src/builtins/temporal/time_zone/mod.rs
index 826cf94bb5..a1e35e93e6 100644
--- a/core/engine/src/builtins/temporal/time_zone/mod.rs
+++ b/core/engine/src/builtins/temporal/time_zone/mod.rs
@@ -11,7 +11,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, CONSTRUCTOR},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsArgs, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{custom_trace, Finalize, Trace};
diff --git a/core/engine/src/builtins/temporal/zoned_date_time/mod.rs b/core/engine/src/builtins/temporal/zoned_date_time/mod.rs
index d95f7de02f..3c0e8691d5 100644
--- a/core/engine/src/builtins/temporal/zoned_date_time/mod.rs
+++ b/core/engine/src/builtins/temporal/zoned_date_time/mod.rs
@@ -4,7 +4,7 @@ use crate::{
context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsBigInt, JsData, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
use boa_gc::{custom_trace, Finalize, Trace};
diff --git a/core/engine/src/builtins/typed_array/builtin.rs b/core/engine/src/builtins/typed_array/builtin.rs
index 9119edd361..faa4961e6e 100644
--- a/core/engine/src/builtins/typed_array/builtin.rs
+++ b/core/engine/src/builtins/typed_array/builtin.rs
@@ -24,7 +24,7 @@ use crate::{
object::internal_methods::get_prototype_from_constructor,
property::{Attribute, PropertyNameKind},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
value::IntegerOrInfinity,
Context, JsArgs, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
};
diff --git a/core/engine/src/builtins/typed_array/mod.rs b/core/engine/src/builtins/typed_array/mod.rs
index 15f63e0fe3..8bbdf820a6 100644
--- a/core/engine/src/builtins/typed_array/mod.rs
+++ b/core/engine/src/builtins/typed_array/mod.rs
@@ -23,7 +23,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
value::{JsValue, Numeric},
Context, JsArgs, JsResult, JsString,
diff --git a/core/engine/src/builtins/uri/mod.rs b/core/engine/src/builtins/uri/mod.rs
index 3389a36f6d..0e7fb3d476 100644
--- a/core/engine/src/builtins/uri/mod.rs
+++ b/core/engine/src/builtins/uri/mod.rs
@@ -25,7 +25,7 @@ use crate::{
js_string,
object::{JsFunction, JsObject},
realm::Realm,
- string::{common::StaticJsStrings, CodePoint},
+ string::{CodePoint, StaticJsStrings},
Context, JsArgs, JsNativeError, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/weak/weak_ref.rs b/core/engine/src/builtins/weak/weak_ref.rs
index 8442e6ac1b..a19ec15a7c 100644
--- a/core/engine/src/builtins/weak/weak_ref.rs
+++ b/core/engine/src/builtins/weak/weak_ref.rs
@@ -8,7 +8,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, ErasedVTableObject, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsNativeError, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/weak_map/mod.rs b/core/engine/src/builtins/weak_map/mod.rs
index 01cd63c0a9..57e2bd588e 100644
--- a/core/engine/src/builtins/weak_map/mod.rs
+++ b/core/engine/src/builtins/weak_map/mod.rs
@@ -17,7 +17,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, ErasedVTableObject, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsNativeError, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/builtins/weak_set/mod.rs b/core/engine/src/builtins/weak_set/mod.rs
index d90a825772..493051b873 100644
--- a/core/engine/src/builtins/weak_set/mod.rs
+++ b/core/engine/src/builtins/weak_set/mod.rs
@@ -14,7 +14,7 @@ use crate::{
object::{internal_methods::get_prototype_from_constructor, ErasedVTableObject, JsObject},
property::Attribute,
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
symbol::JsSymbol,
Context, JsArgs, JsNativeError, JsResult, JsString, JsValue,
};
diff --git a/core/engine/src/object/mod.rs b/core/engine/src/object/mod.rs
index ffffaa5579..b6696e6e66 100644
--- a/core/engine/src/object/mod.rs
+++ b/core/engine/src/object/mod.rs
@@ -23,7 +23,7 @@ use crate::{
native_function::{NativeFunction, NativeFunctionObject},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
Context, JsStr, JsString, JsSymbol, JsValue,
};
diff --git a/core/engine/src/object/operations.rs b/core/engine/src/object/operations.rs
index 6cee0140e1..0301d6c10b 100644
--- a/core/engine/src/object/operations.rs
+++ b/core/engine/src/object/operations.rs
@@ -9,7 +9,7 @@ use crate::{
object::{JsObject, PrivateElement, PrivateName, CONSTRUCTOR, PROTOTYPE},
property::{PropertyDescriptor, PropertyDescriptorBuilder, PropertyKey, PropertyNameKind},
realm::Realm,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
value::Type,
Context, JsResult, JsSymbol, JsValue,
};
diff --git a/core/engine/src/string.rs b/core/engine/src/string.rs
new file mode 100644
index 0000000000..cfddb9328c
--- /dev/null
+++ b/core/engine/src/string.rs
@@ -0,0 +1,211 @@
+//! This module contains the [`js_string`][crate::js_string] macro and the
+//! [`js_str`][crate::js_str] macro.
+//!
+//! The [`js_string`][crate::js_string] macro is used when you need to create a new [`JsString`],
+//! and the [`js_str`][crate::js_str] macro is used for const conversions of string literals to [`JsStr`].
+
+#[doc(inline)]
+pub use boa_string::*;
+
+/// Utility macro to create a [`JsString`].
+///
+/// # Examples
+///
+/// You can call the macro without arguments to create an empty `JsString`:
+///
+/// ```
+/// use boa_engine::js_string;
+///
+/// let empty_str = js_string!();
+/// assert!(empty_str.is_empty());
+/// ```
+///
+///
+/// You can create a `JsString` from a string literal, which completely skips the runtime
+/// conversion from [`&str`] to [&\[u16\]][slice]
:
+///
+/// ```
+/// # use boa_engine::js_string;
+/// let hw = js_string!("Hello, world!");
+/// assert_eq!(&hw, "Hello, world!");
+/// ```
+///
+/// Any `&[u16]` slice is a valid `JsString`, including unpaired surrogates:
+///
+/// ```
+/// # use boa_engine::js_string;
+/// let array = js_string!(&[0xD8AFu16, 0x00A0, 0xD8FF, 0x00F0]);
+/// ```
+///
+/// You can also pass it any number of `&[u16]` as arguments to create a new `JsString` with
+/// the concatenation of every slice:
+///
+/// ```
+/// # use boa_engine::{js_string, js_str, JsStr};
+/// const NAME: JsStr<'_> = js_str!("human! ");
+/// let greeting = js_string!("Hello, ");
+/// let msg = js_string!(&greeting, NAME, js_str!("Nice to meet you!"));
+///
+/// assert_eq!(&msg, "Hello, human! Nice to meet you!");
+/// ```
+#[macro_export]
+#[allow(clippy::module_name_repetitions)]
+macro_rules! js_string {
+ () => {
+ $crate::string::JsString::default()
+ };
+ ($s:literal) => {
+ $crate::string::JsString::from($crate::js_str!($s))
+ };
+ ($s:expr) => {
+ $crate::string::JsString::from($s)
+ };
+ ( $x:expr, $y:expr ) => {
+ $crate::string::JsString::concat($crate::string::JsStr::from($x), $crate::string::JsStr::from($y))
+ };
+ ( $( $s:expr ),+ ) => {
+ $crate::string::JsString::concat_array(&[ $( $crate::string::JsStr::from($s) ),+ ])
+ };
+}
+
+#[allow(clippy::redundant_clone)]
+#[cfg(test)]
+mod tests {
+ use std::hash::{BuildHasher, BuildHasherDefault, Hash};
+
+ use crate::{string::StaticJsStrings, JsStr};
+
+ use super::JsString;
+ use boa_macros::{js_str, utf16};
+ use rustc_hash::FxHasher;
+
+ fn hash_value(value: &T) -> u64 {
+ BuildHasherDefault::::default().hash_one(value)
+ }
+
+ #[test]
+ fn empty() {
+ let s = js_string!();
+ assert_eq!(&s, utf16!(""));
+ }
+
+ #[test]
+ fn refcount() {
+ let x = js_string!("Hello world");
+ assert_eq!(x.refcount(), Some(1));
+
+ {
+ let y = x.clone();
+ assert_eq!(x.refcount(), Some(2));
+ assert_eq!(y.refcount(), Some(2));
+
+ {
+ let z = y.clone();
+ assert_eq!(x.refcount(), Some(3));
+ assert_eq!(y.refcount(), Some(3));
+ assert_eq!(z.refcount(), Some(3));
+ }
+
+ assert_eq!(x.refcount(), Some(2));
+ assert_eq!(y.refcount(), Some(2));
+ }
+
+ assert_eq!(x.refcount(), Some(1));
+ }
+
+ #[test]
+ fn static_refcount() {
+ let x = js_string!();
+ assert_eq!(x.refcount(), None);
+
+ {
+ let y = x.clone();
+ assert_eq!(x.refcount(), None);
+ assert_eq!(y.refcount(), None);
+ };
+
+ assert_eq!(x.refcount(), None);
+ }
+
+ #[test]
+ fn as_str() {
+ const HELLO: &[u16] = utf16!("Hello");
+ let x = js_string!(HELLO);
+
+ assert_eq!(&x, HELLO);
+ }
+
+ #[test]
+ fn hash() {
+ const HELLOWORLD: JsStr<'_> = js_str!("Hello World!");
+ let x = js_string!(HELLOWORLD);
+
+ assert_eq!(x.as_str(), HELLOWORLD);
+
+ assert!(HELLOWORLD.is_latin1());
+ assert!(x.as_str().is_latin1());
+
+ let s_hash = hash_value(&HELLOWORLD);
+ let x_hash = hash_value(&x);
+
+ assert_eq!(s_hash, x_hash);
+ }
+
+ #[test]
+ fn concat() {
+ const Y: &[u16] = utf16!(", ");
+ const W: &[u16] = utf16!("!");
+
+ let x = js_string!("hello");
+ let z = js_string!("world");
+
+ let xy = js_string!(&x, &JsString::from(Y));
+ assert_eq!(&xy, utf16!("hello, "));
+ assert_eq!(xy.refcount(), Some(1));
+
+ let xyz = js_string!(&xy, &z);
+ assert_eq!(&xyz, utf16!("hello, world"));
+ assert_eq!(xyz.refcount(), Some(1));
+
+ let xyzw = js_string!(&xyz, &JsString::from(W));
+ assert_eq!(&xyzw, utf16!("hello, world!"));
+ assert_eq!(xyzw.refcount(), Some(1));
+ }
+
+ #[test]
+ fn trim_start_non_ascii_to_ascii() {
+ let s = "\u{2029}abc";
+ let x = js_string!(s);
+
+ let y = js_string!(x.trim_start());
+
+ assert_eq!(&y, s.trim_start());
+ }
+
+ #[test]
+ fn conversion_to_known_static_js_string() {
+ const JS_STR_U8: &JsStr<'_> = &js_str!("length");
+ const JS_STR_U16: &JsStr<'_> = &JsStr::utf16(utf16!("length"));
+
+ assert!(JS_STR_U8.is_latin1());
+ assert!(!JS_STR_U16.is_latin1());
+
+ assert_eq!(JS_STR_U8, JS_STR_U8);
+ assert_eq!(JS_STR_U16, JS_STR_U16);
+
+ assert_eq!(JS_STR_U8, JS_STR_U16);
+ assert_eq!(JS_STR_U16, JS_STR_U8);
+
+ assert_eq!(hash_value(JS_STR_U8), hash_value(JS_STR_U16));
+
+ let string = StaticJsStrings::get_string(JS_STR_U8);
+
+ assert!(string.is_some());
+ assert!(string.unwrap().as_str().is_latin1());
+
+ let string = StaticJsStrings::get_string(JS_STR_U16);
+
+ assert!(string.is_some());
+ assert!(string.unwrap().as_str().is_latin1());
+ }
+}
diff --git a/core/engine/src/string/common.rs b/core/engine/src/string/common.rs
deleted file mode 100644
index ba7785d7f6..0000000000
--- a/core/engine/src/string/common.rs
+++ /dev/null
@@ -1,950 +0,0 @@
-//! List of commonly used strings in Javascript code.
-
-use crate::{tagged::Tagged, JsStr};
-
-use super::JsString;
-use boa_macros::js_str;
-use paste::paste;
-use rustc_hash::{FxHashMap, FxHasher};
-use std::hash::BuildHasherDefault;
-
-macro_rules! well_known_statics {
- ( $( $(#[$attr:meta])* ($name:ident, $string:literal) ),+$(,)? ) => {
- $(
- paste!{
- #[doc = "Gets the static `JsString` for `\"" $string "\"`."]
- pub const $name: JsString = JsString {
- ptr: Tagged::from_tag(
- Self::find_index($string),
- ),
- };
- }
- )+
- };
-}
-
-/// List of commonly used strings in Javascript code.
-///
-/// Any strings defined here are used as a static [`JsString`] instead of allocating on the heap.
-#[derive(Debug, Clone, Copy)]
-pub struct StaticJsStrings;
-
-impl StaticJsStrings {
- // useful to search at compile time a certain string in the array
- const fn find_index(candidate: &str) -> usize {
- const fn const_eq(lhs: &[u8], rhs: &[u8]) -> bool {
- if lhs.len() != rhs.len() {
- return false;
- }
-
- let mut i = 0;
- while i < lhs.len() {
- if lhs[i] != rhs[i] {
- return false;
- }
- i += 1;
- }
- true
- }
-
- let len = RAW_STATICS.len();
- let mut i = 0;
- while i < len {
- let Some(s) = RAW_STATICS[i].as_latin1() else {
- // All static strings are latin1 encoded
- unreachable!()
- };
- if const_eq(s, candidate.as_bytes()) {
- return i;
- }
- i += 1;
- }
-
- panic!("couldn't find the required string on the common string array");
- }
-
- /// Gets the `JsString` corresponding to `string`, or `None` if the string
- /// doesn't exist inside the static array.
- pub(crate) fn get_string(string: &JsStr<'_>) -> Option {
- if string.len() > MAX_STATIC_LENGTH {
- return None;
- }
-
- let index = RAW_STATICS_CACHE.with(|map| map.get(string).copied())?;
-
- Some(JsString {
- ptr: Tagged::from_tag(index),
- })
- }
-
- /// Gets the `&[u16]` slice corresponding to the provided index, or `None` if the index
- /// provided exceeds the size of the static array.
- pub(crate) fn get(index: usize) -> Option> {
- RAW_STATICS.get(index).copied()
- }
-
- // Some consts are only used on certain features, which triggers the unused lint.
- well_known_statics! {
- (EMPTY_STRING, ""),
- (LENGTH, "length"),
- // Symbols
- (SYMBOL_ASYNC_ITERATOR, "Symbol.asyncIterator"),
- (SYMBOL_HAS_INSTANCE, "Symbol.hasInstance"),
- (SYMBOL_IS_CONCAT_SPREADABLE, "Symbol.isConcatSpreadable"),
- (SYMBOL_ITERATOR, "Symbol.iterator"),
- (SYMBOL_MATCH, "Symbol.match"),
- (SYMBOL_MATCH_ALL, "Symbol.matchAll"),
- (SYMBOL_REPLACE, "Symbol.replace"),
- (SYMBOL_SEARCH, "Symbol.search"),
- (SYMBOL_SPECIES, "Symbol.species"),
- (SYMBOL_SPLIT, "Symbol.split"),
- (SYMBOL_TO_PRIMITIVE, "Symbol.toPrimitive"),
- (SYMBOL_TO_STRING_TAG, "Symbol.toStringTag"),
- (SYMBOL_UNSCOPABLES, "Symbol.unscopables"),
- (FN_SYMBOL_ASYNC_ITERATOR, "[Symbol.asyncIterator]"),
- (FN_SYMBOL_HAS_INSTANCE, "[Symbol.hasInstance]"),
- (FN_SYMBOL_IS_CONCAT_SPREADABLE, "[Symbol.isConcatSpreadable]"),
- (FN_SYMBOL_ITERATOR, "[Symbol.iterator]"),
- (FN_SYMBOL_MATCH, "[Symbol.match]"),
- (FN_SYMBOL_MATCH_ALL, "[Symbol.matchAll]"),
- (FN_SYMBOL_REPLACE, "[Symbol.replace]"),
- (FN_SYMBOL_SEARCH, "[Symbol.search]"),
- (FN_SYMBOL_SPECIES, "[Symbol.species]"),
- (FN_SYMBOL_SPLIT, "[Symbol.split]"),
- (FN_SYMBOL_TO_PRIMITIVE, "[Symbol.toPrimitive]"),
- (FN_SYMBOL_TO_STRING_TAG, "[Symbol.toStringTag]"),
- (FN_SYMBOL_UNSCOPABLES, "[Symbol.unscopables]"),
- // Builtins
- (ARRAY, "Array"),
- (ARRAY_BUFFER, "ArrayBuffer"),
- (SHARED_ARRAY_BUFFER, "SharedArrayBuffer"),
- (ASYNC_FUNCTION, "AsyncFunction"),
- (ASYNC_GENERATOR, "AsyncGenerator"),
- (ASYNC_GENERATOR_FUNCTION, "AsyncGeneratorFunction"),
- (ATOMICS, "Atomics"),
- (BIG_INT, "BigInt"),
- (BOOLEAN, "Boolean"),
- (DATA_VIEW, "DataView"),
- (DATE, "Date"),
- (ERROR, "Error"),
- (AGGREGATE_ERROR, "AggregateError"),
- (EVAL_ERROR, "EvalError"),
- (RANGE_ERROR, "RangeError"),
- (REFERENCE_ERROR, "ReferenceError"),
- (SYNTAX_ERROR, "SyntaxError"),
- (TYPE_ERROR, "TypeError"),
- (URI_ERROR, "URIError"),
- (ESCAPE, "escape"),
- (UNESCAPE, "unescape"),
- (EVAL, "eval"),
- (FUNCTION, "Function"),
- (GENERATOR, "Generator"),
- (GENERATOR_FUNCTION, "GeneratorFunction"),
- (INTL, "Intl"),
- (COLLATOR, "Collator"),
- (LIST_FORMAT, "ListFormat"),
- (LOCALE, "Locale"),
- (PLURAL_RULES, "PluralRules"),
- (SEGMENTER, "Segmenter"),
- (DATE_TIME_FORMAT, "DateTimeFormat"),
- (JSON, "JSON"),
- (MAP, "Map"),
- (MATH, "Math"),
- (NUMBER, "Number"),
- (NUMBER_FORMAT, "NumberFormat"),
- (IS_FINITE, "isFinite"),
- (IS_NAN, "isNaN"),
- (PARSE_INT, "parseInt"),
- (PARSE_FLOAT, "parseFloat"),
- (OBJECT, "Object"),
- (PROMISE, "Promise"),
- (PROXY, "Proxy"),
- (REFLECT, "Reflect"),
- (REG_EXP, "RegExp"),
- (SET, "Set"),
- (STRING, "String"),
- (SYMBOL, "Symbol"),
- (TYPED_ARRAY, "TypedArray"),
- (INT8_ARRAY, "Int8Array"),
- (UINT8_ARRAY, "Uint8Array"),
- (UINT8_CLAMPED_ARRAY, "Uint8ClampedArray"),
- (INT16_ARRAY, "Int16Array"),
- (UINT16_ARRAY, "Uint16Array"),
- (INT32_ARRAY, "Int32Array"),
- (UINT32_ARRAY, "Uint32Array"),
- (BIG_INT64_ARRAY, "BigInt64Array"),
- (BIG_UINT64_ARRAY, "BigUint64Array"),
- (FLOAT32_ARRAY, "Float32Array"),
- (FLOAT64_ARRAY, "Float64Array"),
- (ENCODE_URI, "encodeURI"),
- (ENCODE_URI_COMPONENT, "encodeURIComponent"),
- (DECODE_URI, "decodeURI"),
- (DECODE_URI_COMPONENT, "decodeURIComponent"),
- (WEAK_REF, "WeakRef"),
- (WEAK_MAP, "WeakMap"),
- (WEAK_SET, "WeakSet"),
- (TEMPORAL, "Temporal"),
- (NOW, "Temporal.Now"),
- (INSTANT, "Temporal.Instant"),
- (DURATION, "Temporal.Duration"),
- (PLAIN_DATE, "Temporal.PlainDate"),
- (PLAIN_DATETIME, "Temporal.PlainDateTime"),
- (PLAIN_TIME, "Temporal.PlainTime"),
- (PLAIN_YM, "Temporal.PlainYearMonth"),
- (PLAIN_MD, "Temporal.PlainMonthDay"),
- (CALENDAR, "Temporal.Calendar"),
- (TIMEZONE, "Temporal.TimeZone"),
- (ZONED_DT, "Temporal.ZonedDateTime"),
- }
-}
-
-const MAX_STATIC_LENGTH: usize = {
- let mut max = 0;
- let mut i = 0;
- while i < RAW_STATICS.len() {
- // TOOD: Because `get_index` is not const, we are accessing doc hidden stuff, that may change.
- let len = RAW_STATICS[i].len();
- if len > max {
- max = len;
- }
- i += 1;
- }
- max
-};
-
-thread_local! {
- /// Map from a string inside [`RAW_STATICS`] to its corresponding static index on `RAW_STATICS`.
- static RAW_STATICS_CACHE: FxHashMap, usize> = {
- let mut constants = FxHashMap::with_capacity_and_hasher(
- RAW_STATICS.len(),
- BuildHasherDefault::::default(),
- );
-
- for (idx, &s) in RAW_STATICS.iter().enumerate() {
- constants.insert(s, idx);
- }
-
- constants
- };
-}
-
-/// Array of raw static strings that aren't reference counted.
-const RAW_STATICS: &[JsStr<'_>] = &[
- js_str!(""),
- // Well known symbols
- js_str!("Symbol.asyncIterator"),
- js_str!("[Symbol.asyncIterator]"),
- js_str!("Symbol.hasInstance"),
- js_str!("[Symbol.hasInstance]"),
- js_str!("Symbol.isConcatSpreadable"),
- js_str!("[Symbol.isConcatSpreadable]"),
- js_str!("Symbol.iterator"),
- js_str!("[Symbol.iterator]"),
- js_str!("Symbol.match"),
- js_str!("[Symbol.match]"),
- js_str!("Symbol.matchAll"),
- js_str!("[Symbol.matchAll]"),
- js_str!("Symbol.replace"),
- js_str!("[Symbol.replace]"),
- js_str!("Symbol.search"),
- js_str!("[Symbol.search]"),
- js_str!("Symbol.species"),
- js_str!("[Symbol.species]"),
- js_str!("Symbol.split"),
- js_str!("[Symbol.split]"),
- js_str!("Symbol.toPrimitive"),
- js_str!("[Symbol.toPrimitive]"),
- js_str!("Symbol.toStringTag"),
- js_str!("[Symbol.toStringTag]"),
- js_str!("Symbol.unscopables"),
- js_str!("[Symbol.unscopables]"),
- js_str!("get [Symbol.species]"),
- js_str!("get [Symbol.toStringTag]"),
- // Well known builtins
- js_str!("Array"),
- js_str!("ArrayBuffer"),
- js_str!("SharedArrayBuffer"),
- js_str!("AsyncFunction"),
- js_str!("AsyncGenerator"),
- js_str!("AsyncGeneratorFunction"),
- js_str!("Atomics"),
- js_str!("BigInt"),
- js_str!("Boolean"),
- js_str!("DataView"),
- js_str!("Date"),
- js_str!("Error"),
- js_str!("AggregateError"),
- js_str!("EvalError"),
- js_str!("RangeError"),
- js_str!("ReferenceError"),
- js_str!("SyntaxError"),
- js_str!("TypeError"),
- js_str!("URIError"),
- js_str!("escape"),
- js_str!("unescape"),
- js_str!("eval"),
- js_str!("Function"),
- js_str!("Generator"),
- js_str!("GeneratorFunction"),
- js_str!("Intl"),
- js_str!("Collator"),
- js_str!("ListFormat"),
- js_str!("Locale"),
- js_str!("PluralRules"),
- js_str!("Segmenter"),
- js_str!("DateTimeFormat"),
- js_str!("JSON"),
- js_str!("Map"),
- js_str!("Math"),
- js_str!("Number"),
- js_str!("NumberFormat"),
- js_str!("isFinite"),
- js_str!("isNaN"),
- js_str!("parseInt"),
- js_str!("parseFloat"),
- js_str!("Object"),
- js_str!("Promise"),
- js_str!("Proxy"),
- js_str!("Reflect"),
- js_str!("RegExp"),
- js_str!("Set"),
- js_str!("String"),
- js_str!("Symbol"),
- js_str!("TypedArray"),
- js_str!("Int8Array"),
- js_str!("Uint8Array"),
- js_str!("Uint8ClampedArray"),
- js_str!("Int16Array"),
- js_str!("Uint16Array"),
- js_str!("Int32Array"),
- js_str!("Uint32Array"),
- js_str!("BigInt64Array"),
- js_str!("BigUint64Array"),
- js_str!("Float32Array"),
- js_str!("Float64Array"),
- js_str!("encodeURI"),
- js_str!("encodeURIComponent"),
- js_str!("decodeURI"),
- js_str!("decodeURIComponent"),
- js_str!("WeakRef"),
- js_str!("WeakMap"),
- js_str!("WeakSet"),
- js_str!("Temporal"),
- js_str!("Temporal.Now"),
- js_str!("Temporal.Instant"),
- js_str!("Temporal.Duration"),
- js_str!("Temporal.Calendar"),
- js_str!("Temporal.PlainDate"),
- js_str!("Temporal.PlainDateTime"),
- js_str!("Temporal.PlainMonthDay"),
- js_str!("Temporal.PlainYearMonth"),
- js_str!("Temporal.PlainTime"),
- js_str!("Temporal.TimeZone"),
- js_str!("Temporal.ZonedDateTime"),
- // Misc
- js_str!(","),
- js_str!(":"),
- // Generic use
- js_str!("name"),
- js_str!("length"),
- js_str!("arguments"),
- js_str!("prototype"),
- js_str!("constructor"),
- js_str!("return"),
- js_str!("throw"),
- js_str!("global"),
- js_str!("globalThis"),
- // typeof
- js_str!("null"),
- js_str!("undefined"),
- js_str!("number"),
- js_str!("string"),
- js_str!("symbol"),
- js_str!("bigint"),
- js_str!("object"),
- js_str!("function"),
- // Property descriptor
- js_str!("value"),
- js_str!("get"),
- js_str!("set"),
- js_str!("writable"),
- js_str!("enumerable"),
- js_str!("configurable"),
- // Object object
- js_str!("assign"),
- js_str!("create"),
- js_str!("toString"),
- js_str!("valueOf"),
- js_str!("is"),
- js_str!("seal"),
- js_str!("isSealed"),
- js_str!("freeze"),
- js_str!("isFrozen"),
- js_str!("isExtensible"),
- js_str!("hasOwnProperty"),
- js_str!("isPrototypeOf"),
- js_str!("setPrototypeOf"),
- js_str!("getPrototypeOf"),
- js_str!("defineProperty"),
- js_str!("defineProperties"),
- js_str!("deleteProperty"),
- js_str!("construct"),
- js_str!("hasOwn"),
- js_str!("ownKeys"),
- js_str!("keys"),
- js_str!("values"),
- js_str!("entries"),
- js_str!("fromEntries"),
- js_str!("propertyIsEnumerable"),
- js_str!("preventExtensions"),
- js_str!("getOwnPropertyDescriptor"),
- js_str!("getOwnPropertyDescriptors"),
- js_str!("getOwnPropertyNames"),
- js_str!("getOwnPropertySymbols"),
- js_str!("__defineGetter__"),
- js_str!("__defineSetter__"),
- js_str!("__lookupGetter__"),
- js_str!("__lookupSetter__"),
- js_str!("__proto__"),
- js_str!("get __proto__"),
- js_str!("set __proto__"),
- // Function object
- js_str!("apply"),
- js_str!("bind"),
- js_str!("call"),
- js_str!("caller"),
- // Arguments object
- js_str!("callee"),
- // Array object
- js_str!("at"),
- js_str!("from"),
- js_str!("isArray"),
- js_str!("of"),
- js_str!("copyWithin"),
- js_str!("every"),
- js_str!("fill"),
- js_str!("filter"),
- js_str!("find"),
- js_str!("findIndex"),
- js_str!("findLast"),
- js_str!("findLastIndex"),
- js_str!("flat"),
- js_str!("flatMap"),
- js_str!("forEach"),
- js_str!("includes"),
- js_str!("indexOf"),
- js_str!("join"),
- js_str!("map"),
- js_str!("next"),
- js_str!("reduce"),
- js_str!("reduceRight"),
- js_str!("reverse"),
- js_str!("shift"),
- js_str!("slice"),
- js_str!("splice"),
- js_str!("some"),
- js_str!("sort"),
- js_str!("unshift"),
- js_str!("push"),
- js_str!("pop"),
- js_str!("groupBy"),
- js_str!("toReversed"),
- js_str!("toSorted"),
- js_str!("toSpliced"),
- js_str!("with"),
- // String object
- js_str!("charAt"),
- js_str!("charCodeAt"),
- js_str!("codePointAt"),
- js_str!("concat"),
- js_str!("endsWith"),
- js_str!("fromCharCode"),
- js_str!("fromCodePoint"),
- js_str!("lastIndexOf"),
- js_str!("match"),
- js_str!("matchAll"),
- js_str!("normalize"),
- js_str!("padEnd"),
- js_str!("padStart"),
- js_str!("raw"),
- js_str!("repeat"),
- js_str!("replace"),
- js_str!("replaceAll"),
- js_str!("search"),
- js_str!("split"),
- js_str!("startsWith"),
- js_str!("substr"),
- js_str!("substring"),
- js_str!("toLocaleString"),
- js_str!("toLowerCase"),
- js_str!("toUpperCase"),
- js_str!("trim"),
- js_str!("trimEnd"),
- js_str!("trimStart"),
- js_str!("isWellFormed"),
- js_str!("localeCompare"),
- js_str!("toWellFormed"),
- js_str!("toLocaleLowerCase"),
- js_str!("toLocaleUpperCase"),
- js_str!("trimLeft"),
- js_str!("trimRight"),
- js_str!("anchor"),
- js_str!("big"),
- js_str!("blink"),
- js_str!("bold"),
- js_str!("fixed"),
- js_str!("fontcolor"),
- js_str!("fontsize"),
- js_str!("italics"),
- js_str!("link"),
- js_str!("small"),
- js_str!("strike"),
- js_str!("sub"),
- js_str!("sup"),
- // Number object
- js_str!("Infinity"),
- js_str!("NaN"),
- js_str!("EPSILON"),
- js_str!("MAX_SAFE_INTEGER"),
- js_str!("MIN_SAFE_INTEGER"),
- js_str!("MAX_VALUE"),
- js_str!("MIN_VALUE"),
- js_str!("NEGATIVE_INFINITY"),
- js_str!("POSITIVE_INFINITY"),
- js_str!("isSafeInteger"),
- js_str!("isInteger"),
- js_str!("toExponential"),
- js_str!("toFixed"),
- js_str!("toPrecision"),
- // BigInt object
- js_str!("asIntN"),
- js_str!("asUintN"),
- // RegExp object
- js_str!("exec"),
- js_str!("test"),
- js_str!("compile"),
- js_str!("flags"),
- js_str!("index"),
- js_str!("lastIndex"),
- js_str!("hasIndices"),
- js_str!("ignoreCase"),
- js_str!("multiline"),
- js_str!("dotAll"),
- js_str!("unicode"),
- js_str!("sticky"),
- js_str!("source"),
- js_str!("get hasIndices"),
- js_str!("get global"),
- js_str!("get ignoreCase"),
- js_str!("get multiline"),
- js_str!("get dotAll"),
- js_str!("get unicode"),
- js_str!("get sticky"),
- js_str!("get flags"),
- js_str!("get source"),
- // Symbol object
- js_str!("for"),
- js_str!("keyFor"),
- js_str!("description"),
- js_str!("asyncIterator"),
- js_str!("hasInstance"),
- js_str!("species"),
- js_str!("unscopables"),
- js_str!("iterator"),
- js_str!("toStringTag"),
- js_str!("toPrimitive"),
- js_str!("isConcatSpreadable"),
- js_str!("get description"),
- // Map object
- js_str!("clear"),
- js_str!("delete"),
- js_str!("has"),
- js_str!("size"),
- // Set object
- js_str!("add"),
- // Reflect object
- // Proxy object
- js_str!("revocable"),
- // Error objects
- js_str!("message"),
- // Date object
- js_str!("toJSON"),
- js_str!("getDate"),
- js_str!("getDay"),
- js_str!("getFullYear"),
- js_str!("getHours"),
- js_str!("getMilliseconds"),
- js_str!("getMinutes"),
- js_str!("getMonth"),
- js_str!("getSeconds"),
- js_str!("getTime"),
- js_str!("getYear"),
- js_str!("getUTCDate"),
- js_str!("getUTCDay"),
- js_str!("getUTCFullYear"),
- js_str!("getUTCHours"),
- js_str!("getUTCMinutes"),
- js_str!("getUTCMonth"),
- js_str!("getUTCSeconds"),
- js_str!("setDate"),
- js_str!("setFullYear"),
- js_str!("setHours"),
- js_str!("setMilliseconds"),
- js_str!("setMinutes"),
- js_str!("setMonth"),
- js_str!("setSeconds"),
- js_str!("setYear"),
- js_str!("setTime"),
- js_str!("setUTCDate"),
- js_str!("setUTCFullYear"),
- js_str!("setUTCHours"),
- js_str!("setUTCMinutes"),
- js_str!("setUTCMonth"),
- js_str!("setUTCSeconds"),
- js_str!("toDateString"),
- js_str!("toGMTString"),
- js_str!("toISOString"),
- js_str!("toTimeString"),
- js_str!("toUTCString"),
- js_str!("now"),
- js_str!("UTC"),
- js_str!("getTimezoneOffset"),
- js_str!("getUTCMilliseconds"),
- js_str!("setUTCMilliseconds"),
- js_str!("toLocaleDateString"),
- js_str!("toLocaleTimeString"),
- // JSON object
- js_str!("parse"),
- js_str!("stringify"),
- // Promise object
- js_str!("promise"),
- js_str!("resolve"),
- js_str!("reject"),
- js_str!("all"),
- js_str!("allSettled"),
- js_str!("any"),
- js_str!("race"),
- js_str!("then"),
- js_str!("catch"),
- js_str!("finally"),
- js_str!("withResolvers"),
- // Iterator object
- js_str!("Array Iterator"),
- js_str!("Set Iterator"),
- js_str!("String Iterator"),
- js_str!("Map Iterator"),
- js_str!("For In Iterator"),
- js_str!("RegExp String Iterator"),
- // Iterator result object
- js_str!("done"),
- // Math object
- js_str!("LN10"),
- js_str!("LN2"),
- js_str!("LOG10E"),
- js_str!("LOG2E"),
- js_str!("PI"),
- js_str!("SQRT1_2"),
- js_str!("SQRT2"),
- js_str!("abs"),
- js_str!("acos"),
- js_str!("acosh"),
- js_str!("asin"),
- js_str!("asinh"),
- js_str!("atan"),
- js_str!("atanh"),
- js_str!("atan2"),
- js_str!("cbrt"),
- js_str!("ceil"),
- js_str!("clz32"),
- js_str!("cos"),
- js_str!("cosh"),
- js_str!("exp"),
- js_str!("expm1"),
- js_str!("floor"),
- js_str!("fround"),
- js_str!("hypot"),
- js_str!("imul"),
- js_str!("log"),
- js_str!("log1p"),
- js_str!("log10"),
- js_str!("log2"),
- js_str!("max"),
- js_str!("min"),
- js_str!("pow"),
- js_str!("random"),
- js_str!("round"),
- js_str!("sign"),
- js_str!("sin"),
- js_str!("sinh"),
- js_str!("sqrt"),
- js_str!("tan"),
- js_str!("tanh"),
- js_str!("trunc"),
- // TypedArray object
- js_str!("BYTES_PER_ELEMENT"),
- js_str!("buffer"),
- js_str!("byteLength"),
- js_str!("byteOffset"),
- js_str!("isView"),
- js_str!("subarray"),
- js_str!("get byteLength"),
- js_str!("get buffer"),
- js_str!("get byteOffset"),
- js_str!("get size"),
- js_str!("get length"),
- // DataView object
- js_str!("getBigInt64"),
- js_str!("getBigUint64"),
- js_str!("getFloat32"),
- js_str!("getFloat64"),
- js_str!("getInt8"),
- js_str!("getInt16"),
- js_str!("getInt32"),
- js_str!("getUint8"),
- js_str!("getUint16"),
- js_str!("getUint32"),
- js_str!("setBigInt64"),
- js_str!("setBigUint64"),
- js_str!("setFloat32"),
- js_str!("setFloat64"),
- js_str!("setInt8"),
- js_str!("setInt16"),
- js_str!("setInt32"),
- js_str!("setUint8"),
- js_str!("setUint16"),
- js_str!("setUint32"),
- // WeakRef object
- js_str!("deref"),
- // Atomic object
- js_str!("and"),
- js_str!("compareExchange"),
- js_str!("exchange"),
- js_str!("isLockFree"),
- js_str!("load"),
- js_str!("or"),
- js_str!("store"),
- js_str!("wait"),
- js_str!("notify"),
- js_str!("xor"),
- // Intl object
- js_str!("getCanonicalLocales"),
- js_str!("get compare"),
- js_str!("supportedLocalesOf"),
- js_str!("Intl.Collator"),
- js_str!("compare"),
- js_str!("resolvedOptions"),
- js_str!("Intl.ListFormat"),
- js_str!("format"),
- js_str!("formatToParts"),
- js_str!("get baseName"),
- js_str!("get calendar"),
- js_str!("get caseFirst"),
- js_str!("get collation"),
- js_str!("get hourCycle"),
- js_str!("get numeric"),
- js_str!("get numberingSystem"),
- js_str!("get language"),
- js_str!("get script"),
- js_str!("get region"),
- js_str!("Intl.Locale"),
- js_str!("maximize"),
- js_str!("minimize"),
- js_str!("baseName"),
- js_str!("calendar"),
- js_str!("caseFirst"),
- js_str!("collation"),
- js_str!("hourCycle"),
- js_str!("numeric"),
- js_str!("numberingSystem"),
- js_str!("language"),
- js_str!("script"),
- js_str!("region"),
- js_str!("Intl.Segmenter"),
- js_str!("segment"),
- js_str!("containing"),
- js_str!("Segmenter String Iterator"),
- js_str!("Intl.PluralRules"),
- js_str!("select"),
- // Temporal object
- js_str!("get Id"),
- js_str!("getOffsetNanosecondsFor"),
- js_str!("getOffsetStringFor"),
- js_str!("getPlainDateTimeFor"),
- js_str!("getInstantFor"),
- js_str!("getPossibleInstantFor"),
- js_str!("getNextTransition"),
- js_str!("getPreviousTransition"),
- js_str!("id"),
- js_str!("Now"),
- js_str!("Calendar"),
- js_str!("Duration"),
- js_str!("Instant"),
- js_str!("PlainDate"),
- js_str!("PlainDateTime"),
- js_str!("PlainMonthDay"),
- js_str!("PlainTime"),
- js_str!("PlainYearMonth"),
- js_str!("TimeZone"),
- js_str!("ZonedDateTime"),
- js_str!("timeZoneId"),
- js_str!("instant"),
- js_str!("plainDateTime"),
- js_str!("plainDateTimeISO"),
- js_str!("zonedDateTime"),
- js_str!("zonedDateTimeISO"),
- js_str!("plainDate"),
- js_str!("plainDateISO"),
- js_str!("get epochSeconds"),
- js_str!("get epochMilliseconds"),
- js_str!("get epochMicroseconds"),
- js_str!("get epochNanoseconds"),
- js_str!("epochSeconds"),
- js_str!("epochMilliseconds"),
- js_str!("epochMicroseconds"),
- js_str!("epochNanoseconds"),
- js_str!("subtract"),
- js_str!("until"),
- js_str!("since"),
- js_str!("equals"),
- js_str!("toZonedDateTime"),
- js_str!("toZonedDateTimeISO"),
- js_str!("get Years"),
- js_str!("get Months"),
- js_str!("get Weeks"),
- js_str!("get Days"),
- js_str!("get Hours"),
- js_str!("get Minutes"),
- js_str!("get Seconds"),
- js_str!("get Milliseconds"),
- js_str!("get Microseconds"),
- js_str!("get Nanoseconds"),
- js_str!("get Sign"),
- js_str!("get blank"),
- js_str!("years"),
- js_str!("months"),
- js_str!("weeks"),
- js_str!("days"),
- js_str!("hours"),
- js_str!("minutes"),
- js_str!("seconds"),
- js_str!("milliseconds"),
- js_str!("microseconds"),
- js_str!("nanoseconds"),
- js_str!("blank"),
- js_str!("negated"),
- js_str!("total"),
- js_str!("get calendarId"),
- js_str!("get year"),
- js_str!("get month"),
- js_str!("get monthCode"),
- js_str!("get day"),
- js_str!("get dayOfWeek"),
- js_str!("get dayOfYear"),
- js_str!("get weekOfYear"),
- js_str!("get yearOfWeek"),
- js_str!("get daysInWeek"),
- js_str!("get daysInMonth"),
- js_str!("get daysInYear"),
- js_str!("get monthsInYear"),
- js_str!("get inLeapYear"),
- js_str!("calendarId"),
- js_str!("year"),
- js_str!("month"),
- js_str!("monthCode"),
- js_str!("day"),
- js_str!("dayOfWeek"),
- js_str!("dayOfYear"),
- js_str!("weekOfYear"),
- js_str!("yearOfWeek"),
- js_str!("daysInWeek"),
- js_str!("daysInMonth"),
- js_str!("daysInYear"),
- js_str!("monthsInYear"),
- js_str!("inLeapYear"),
- js_str!("toPlainYearMonth"),
- js_str!("toPlainMonthDay"),
- js_str!("getISOFields"),
- js_str!("getCalendar"),
- js_str!("withCalendar"),
- js_str!("dateFromFields"),
- js_str!("yearMonthFromFields"),
- js_str!("monthDayFromFields"),
- js_str!("dateAdd"),
- js_str!("dateUntil"),
- js_str!("era"),
- js_str!("eraYear"),
- js_str!("fields"),
- js_str!("mergeFields"),
- // Console object
- js_str!("console"),
- js_str!("assert"),
- js_str!("debug"),
- js_str!("error"),
- js_str!("info"),
- js_str!("trace"),
- js_str!("warn"),
- js_str!("exception"),
- js_str!("count"),
- js_str!("countReset"),
- js_str!("group"),
- js_str!("groupCollapsed"),
- js_str!("groupEnd"),
- js_str!("time"),
- js_str!("timeLog"),
- js_str!("timeEnd"),
- js_str!("dir"),
- js_str!("dirxml"),
- // Minified name
- js_str!("a"),
- js_str!("c"),
- js_str!("d"),
- js_str!("e"),
- js_str!("f"),
- js_str!("g"),
- js_str!("h"),
- js_str!("i"),
- js_str!("j"),
- js_str!("k"),
- js_str!("l"),
- js_str!("m"),
- js_str!("n"),
- js_str!("o"),
- js_str!("p"),
- js_str!("q"),
- js_str!("r"),
- js_str!("s"),
- js_str!("t"),
- js_str!("u"),
- js_str!("v"),
- js_str!("w"),
- js_str!("x"),
- js_str!("y"),
- js_str!("z"),
- js_str!("A"),
- js_str!("C"),
- js_str!("D"),
- js_str!("E"),
- js_str!("F"),
- js_str!("G"),
- js_str!("H"),
- js_str!("I"),
- js_str!("J"),
- js_str!("K"),
- js_str!("L"),
- js_str!("M"),
- js_str!("N"),
- js_str!("O"),
- js_str!("P"),
- js_str!("Q"),
- js_str!("R"),
- js_str!("S"),
- js_str!("T"),
- js_str!("U"),
- js_str!("V"),
- js_str!("W"),
- js_str!("X"),
- js_str!("Y"),
- js_str!("Z"),
- js_str!("_"),
- js_str!("$"),
-];
diff --git a/core/engine/src/symbol.rs b/core/engine/src/symbol.rs
index 11b04dd9e6..a25cf08855 100644
--- a/core/engine/src/symbol.rs
+++ b/core/engine/src/symbol.rs
@@ -23,7 +23,7 @@
use crate::{
js_string,
- string::{common::StaticJsStrings, JsString},
+ string::{JsString, StaticJsStrings},
tagged::{Tagged, UnwrappedTagged},
};
use boa_gc::{Finalize, Trace};
diff --git a/core/engine/src/tagged.rs b/core/engine/src/tagged.rs
index 83ec17c24b..3415b38ed8 100644
--- a/core/engine/src/tagged.rs
+++ b/core/engine/src/tagged.rs
@@ -39,6 +39,7 @@ impl Clone for Tagged {
impl Copy for Tagged {}
+#[allow(dead_code)]
impl Tagged {
/// Creates a new, tagged `Tagged` pointer from an integer.
///
diff --git a/core/engine/src/vm/opcode/push/array.rs b/core/engine/src/vm/opcode/push/array.rs
index 9135f4109b..480e979ecf 100644
--- a/core/engine/src/vm/opcode/push/array.rs
+++ b/core/engine/src/vm/opcode/push/array.rs
@@ -1,6 +1,6 @@
use crate::{
builtins::Array,
- string::common::StaticJsStrings,
+ string::StaticJsStrings,
vm::{opcode::Operation, CompletionType},
Context, JsResult, JsValue,
};
diff --git a/core/gc/ABOUT.md b/core/gc/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/gc/ABOUT.md
+++ b/core/gc/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/gc/Cargo.toml b/core/gc/Cargo.toml
index b21b61c44c..af223d0767 100644
--- a/core/gc/Cargo.toml
+++ b/core/gc/Cargo.toml
@@ -15,12 +15,15 @@ rust-version.workspace = true
thin-vec = ["dep:thin-vec"]
# Enable default implementations of trace and finalize for some `ICU4X` types
icu = ["dep:icu_locid"]
+# Enable default implementations of trace and finalize for the `boa_string` crate
+boa_string = ["dep:boa_string"]
[dependencies]
boa_profiler.workspace = true
boa_macros.workspace = true
hashbrown = { workspace = true, features = ["ahash", "raw"] }
+boa_string = { workspace = true, optional = true }
thin-vec = { workspace = true, optional = true }
icu_locid = { workspace = true, optional = true }
diff --git a/core/gc/src/trace.rs b/core/gc/src/trace.rs
index b28d976e8d..41ac9d9144 100644
--- a/core/gc/src/trace.rs
+++ b/core/gc/src/trace.rs
@@ -521,3 +521,15 @@ mod icu {
empty_trace!();
}
}
+
+#[cfg(feature = "boa_string")]
+mod boa_string_trace {
+ use crate::{Finalize, Trace};
+
+ // SAFETY: `boa_string::JsString` doesn't have any traceable data.
+ unsafe impl Trace for boa_string::JsString {
+ empty_trace!();
+ }
+
+ impl Finalize for boa_string::JsString {}
+}
diff --git a/core/icu_provider/ABOUT.md b/core/icu_provider/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/icu_provider/ABOUT.md
+++ b/core/icu_provider/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/interner/ABOUT.md b/core/interner/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/interner/ABOUT.md
+++ b/core/interner/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/interop/ABOUT.md b/core/interop/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/interop/ABOUT.md
+++ b/core/interop/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/macros/ABOUT.md b/core/macros/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/macros/ABOUT.md
+++ b/core/macros/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/parser/ABOUT.md b/core/parser/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/parser/ABOUT.md
+++ b/core/parser/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/profiler/ABOUT.md b/core/profiler/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/profiler/ABOUT.md
+++ b/core/profiler/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/runtime/ABOUT.md b/core/runtime/ABOUT.md
index c1de9c5a19..c8c37206ac 100644
--- a/core/runtime/ABOUT.md
+++ b/core/runtime/ABOUT.md
@@ -18,6 +18,7 @@ Try out the most recent release with Boa's live demo
- [**`boa_profiler`**][profiler] - Boa's code profiler.
- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
[boa-conformance]: https://boajs.dev/conformance
[boa-web]: https://boajs.dev/
@@ -30,3 +31,4 @@ Try out the most recent release with Boa's live demo
[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/string/ABOUT.md b/core/string/ABOUT.md
new file mode 100644
index 0000000000..c8c37206ac
--- /dev/null
+++ b/core/string/ABOUT.md
@@ -0,0 +1,34 @@
+# About Boa
+
+Boa is an open-source, experimental ECMAScript Engine written in Rust for
+lexing, parsing and executing ECMAScript/JavaScript. Currently, Boa supports some
+of the [language][boa-conformance]. More information can be viewed at [Boa's
+website][boa-web].
+
+Try out the most recent release with Boa's live demo
+[playground][boa-playground].
+
+## Boa Crates
+
+- [**`boa_ast`**][ast] - Boa's ECMAScript Abstract Syntax Tree.
+- [**`boa_engine`**][engine] - Boa's implementation of ECMAScript builtin objects and execution.
+- [**`boa_gc`**][gc] - Boa's garbage collector.
+- [**`boa_interner`**][interner] - Boa's string interner.
+- [**`boa_parser`**][parser] - Boa's lexer and parser.
+- [**`boa_profiler`**][profiler] - Boa's code profiler.
+- [**`boa_icu_provider`**][icu] - Boa's ICU4X data provider.
+- [**`boa_runtime`**][runtime] - Boa's WebAPI features.
+- [**`boa_string`**][string] - Boa's ECMAScript string implementation.
+
+[boa-conformance]: https://boajs.dev/conformance
+[boa-web]: https://boajs.dev/
+[boa-playground]: https://boajs.dev/playground
+[ast]: https://docs.rs/boa_ast/latest/boa_ast/index.html
+[engine]: https://docs.rs/boa_engine/latest/boa_engine/index.html
+[gc]: https://docs.rs/boa_gc/latest/boa_gc/index.html
+[interner]: https://docs.rs/boa_interner/latest/boa_interner/index.html
+[parser]: https://docs.rs/boa_parser/latest/boa_parser/index.html
+[profiler]: https://docs.rs/boa_profiler/latest/boa_profiler/index.html
+[icu]: https://docs.rs/boa_icu_provider/latest/boa_icu_provider/index.html
+[runtime]: https://docs.rs/boa_runtime/latest/boa_runtime/index.html
+[string]: https://docs.rs/boa_string/latest/boa_string/index.html
diff --git a/core/string/Cargo.toml b/core/string/Cargo.toml
new file mode 100644
index 0000000000..2a36d739c0
--- /dev/null
+++ b/core/string/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+name = "boa_string"
+keywords = ["javascript", "js", "string"]
+categories = ["parser-implementations", "compilers"]
+readme = "../../README.md"
+description.workspace = true
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[dependencies]
+rustc-hash = { workspace = true, features = ["std"] }
+sptr = "0.3.2"
+static_assertions.workspace = true
+paste = "1.0"
+fast-float.workspace = true
+
+[dev-dependencies]
+boa_macros.workspace = true
+
+[lints]
+workspace = true
+
+[package.metadata.docs.rs]
+all-features = true
diff --git a/core/string/src/common.rs b/core/string/src/common.rs
new file mode 100644
index 0000000000..8b420f7c68
--- /dev/null
+++ b/core/string/src/common.rs
@@ -0,0 +1,951 @@
+//! List of commonly used strings in Javascript code.
+
+use crate::{tagged::Tagged, JsStr};
+
+use super::JsString;
+use paste::paste;
+use rustc_hash::{FxHashMap, FxHasher};
+use std::hash::BuildHasherDefault;
+
+macro_rules! well_known_statics {
+ ( $( $(#[$attr:meta])* ($name:ident, $string:literal) ),+$(,)? ) => {
+ $(
+ paste!{
+ #[doc = "Gets the static `JsString` for `\"" $string "\"`."]
+ pub const $name: JsString = JsString {
+ ptr: Tagged::from_tag(
+ Self::find_index($string),
+ ),
+ };
+ }
+ )+
+ };
+}
+
+/// List of commonly used strings in Javascript code.
+///
+/// Any strings defined here are used as a static [`JsString`] instead of allocating on the heap.
+#[derive(Debug, Clone, Copy)]
+pub struct StaticJsStrings;
+
+impl StaticJsStrings {
+ // useful to search at compile time a certain string in the array
+ const fn find_index(candidate: &str) -> usize {
+ const fn const_eq(lhs: &[u8], rhs: &[u8]) -> bool {
+ if lhs.len() != rhs.len() {
+ return false;
+ }
+
+ let mut i = 0;
+ while i < lhs.len() {
+ if lhs[i] != rhs[i] {
+ return false;
+ }
+ i += 1;
+ }
+ true
+ }
+
+ let len = RAW_STATICS.len();
+ let mut i = 0;
+ while i < len {
+ let Some(s) = RAW_STATICS[i].as_latin1() else {
+ // All static strings are latin1 encoded
+ unreachable!()
+ };
+ if const_eq(s, candidate.as_bytes()) {
+ return i;
+ }
+ i += 1;
+ }
+
+ panic!("couldn't find the required string on the common string array");
+ }
+
+ /// Gets the `JsString` corresponding to `string`, or `None` if the string
+ /// doesn't exist inside the static array.
+ #[inline]
+ #[must_use]
+ pub fn get_string(string: &JsStr<'_>) -> Option {
+ if string.len() > MAX_STATIC_LENGTH {
+ return None;
+ }
+
+ let index = RAW_STATICS_CACHE.with(|map| map.get(string).copied())?;
+
+ Some(JsString {
+ ptr: Tagged::from_tag(index),
+ })
+ }
+
+ /// Gets the `&[u16]` slice corresponding to the provided index, or `None` if the index
+ /// provided exceeds the size of the static array.
+ pub(crate) fn get(index: usize) -> Option> {
+ RAW_STATICS.get(index).copied()
+ }
+
+ // Some consts are only used on certain features, which triggers the unused lint.
+ well_known_statics! {
+ (EMPTY_STRING, ""),
+ (LENGTH, "length"),
+ // Symbols
+ (SYMBOL_ASYNC_ITERATOR, "Symbol.asyncIterator"),
+ (SYMBOL_HAS_INSTANCE, "Symbol.hasInstance"),
+ (SYMBOL_IS_CONCAT_SPREADABLE, "Symbol.isConcatSpreadable"),
+ (SYMBOL_ITERATOR, "Symbol.iterator"),
+ (SYMBOL_MATCH, "Symbol.match"),
+ (SYMBOL_MATCH_ALL, "Symbol.matchAll"),
+ (SYMBOL_REPLACE, "Symbol.replace"),
+ (SYMBOL_SEARCH, "Symbol.search"),
+ (SYMBOL_SPECIES, "Symbol.species"),
+ (SYMBOL_SPLIT, "Symbol.split"),
+ (SYMBOL_TO_PRIMITIVE, "Symbol.toPrimitive"),
+ (SYMBOL_TO_STRING_TAG, "Symbol.toStringTag"),
+ (SYMBOL_UNSCOPABLES, "Symbol.unscopables"),
+ (FN_SYMBOL_ASYNC_ITERATOR, "[Symbol.asyncIterator]"),
+ (FN_SYMBOL_HAS_INSTANCE, "[Symbol.hasInstance]"),
+ (FN_SYMBOL_IS_CONCAT_SPREADABLE, "[Symbol.isConcatSpreadable]"),
+ (FN_SYMBOL_ITERATOR, "[Symbol.iterator]"),
+ (FN_SYMBOL_MATCH, "[Symbol.match]"),
+ (FN_SYMBOL_MATCH_ALL, "[Symbol.matchAll]"),
+ (FN_SYMBOL_REPLACE, "[Symbol.replace]"),
+ (FN_SYMBOL_SEARCH, "[Symbol.search]"),
+ (FN_SYMBOL_SPECIES, "[Symbol.species]"),
+ (FN_SYMBOL_SPLIT, "[Symbol.split]"),
+ (FN_SYMBOL_TO_PRIMITIVE, "[Symbol.toPrimitive]"),
+ (FN_SYMBOL_TO_STRING_TAG, "[Symbol.toStringTag]"),
+ (FN_SYMBOL_UNSCOPABLES, "[Symbol.unscopables]"),
+ // Builtins
+ (ARRAY, "Array"),
+ (ARRAY_BUFFER, "ArrayBuffer"),
+ (SHARED_ARRAY_BUFFER, "SharedArrayBuffer"),
+ (ASYNC_FUNCTION, "AsyncFunction"),
+ (ASYNC_GENERATOR, "AsyncGenerator"),
+ (ASYNC_GENERATOR_FUNCTION, "AsyncGeneratorFunction"),
+ (ATOMICS, "Atomics"),
+ (BIG_INT, "BigInt"),
+ (BOOLEAN, "Boolean"),
+ (DATA_VIEW, "DataView"),
+ (DATE, "Date"),
+ (ERROR, "Error"),
+ (AGGREGATE_ERROR, "AggregateError"),
+ (EVAL_ERROR, "EvalError"),
+ (RANGE_ERROR, "RangeError"),
+ (REFERENCE_ERROR, "ReferenceError"),
+ (SYNTAX_ERROR, "SyntaxError"),
+ (TYPE_ERROR, "TypeError"),
+ (URI_ERROR, "URIError"),
+ (ESCAPE, "escape"),
+ (UNESCAPE, "unescape"),
+ (EVAL, "eval"),
+ (FUNCTION, "Function"),
+ (GENERATOR, "Generator"),
+ (GENERATOR_FUNCTION, "GeneratorFunction"),
+ (INTL, "Intl"),
+ (COLLATOR, "Collator"),
+ (LIST_FORMAT, "ListFormat"),
+ (LOCALE, "Locale"),
+ (PLURAL_RULES, "PluralRules"),
+ (SEGMENTER, "Segmenter"),
+ (DATE_TIME_FORMAT, "DateTimeFormat"),
+ (JSON, "JSON"),
+ (MAP, "Map"),
+ (MATH, "Math"),
+ (NUMBER, "Number"),
+ (NUMBER_FORMAT, "NumberFormat"),
+ (IS_FINITE, "isFinite"),
+ (IS_NAN, "isNaN"),
+ (PARSE_INT, "parseInt"),
+ (PARSE_FLOAT, "parseFloat"),
+ (OBJECT, "Object"),
+ (PROMISE, "Promise"),
+ (PROXY, "Proxy"),
+ (REFLECT, "Reflect"),
+ (REG_EXP, "RegExp"),
+ (SET, "Set"),
+ (STRING, "String"),
+ (SYMBOL, "Symbol"),
+ (TYPED_ARRAY, "TypedArray"),
+ (INT8_ARRAY, "Int8Array"),
+ (UINT8_ARRAY, "Uint8Array"),
+ (UINT8_CLAMPED_ARRAY, "Uint8ClampedArray"),
+ (INT16_ARRAY, "Int16Array"),
+ (UINT16_ARRAY, "Uint16Array"),
+ (INT32_ARRAY, "Int32Array"),
+ (UINT32_ARRAY, "Uint32Array"),
+ (BIG_INT64_ARRAY, "BigInt64Array"),
+ (BIG_UINT64_ARRAY, "BigUint64Array"),
+ (FLOAT32_ARRAY, "Float32Array"),
+ (FLOAT64_ARRAY, "Float64Array"),
+ (ENCODE_URI, "encodeURI"),
+ (ENCODE_URI_COMPONENT, "encodeURIComponent"),
+ (DECODE_URI, "decodeURI"),
+ (DECODE_URI_COMPONENT, "decodeURIComponent"),
+ (WEAK_REF, "WeakRef"),
+ (WEAK_MAP, "WeakMap"),
+ (WEAK_SET, "WeakSet"),
+ (TEMPORAL, "Temporal"),
+ (NOW, "Temporal.Now"),
+ (INSTANT, "Temporal.Instant"),
+ (DURATION, "Temporal.Duration"),
+ (PLAIN_DATE, "Temporal.PlainDate"),
+ (PLAIN_DATETIME, "Temporal.PlainDateTime"),
+ (PLAIN_TIME, "Temporal.PlainTime"),
+ (PLAIN_YM, "Temporal.PlainYearMonth"),
+ (PLAIN_MD, "Temporal.PlainMonthDay"),
+ (CALENDAR, "Temporal.Calendar"),
+ (TIMEZONE, "Temporal.TimeZone"),
+ (ZONED_DT, "Temporal.ZonedDateTime"),
+ }
+}
+
+const MAX_STATIC_LENGTH: usize = {
+ let mut max = 0;
+ let mut i = 0;
+ while i < RAW_STATICS.len() {
+ // TOOD: Because `get_index` is not const, we are accessing doc hidden stuff, that may change.
+ let len = RAW_STATICS[i].len();
+ if len > max {
+ max = len;
+ }
+ i += 1;
+ }
+ max
+};
+
+thread_local! {
+ /// Map from a string inside [`RAW_STATICS`] to its corresponding static index on `RAW_STATICS`.
+ static RAW_STATICS_CACHE: FxHashMap, usize> = {
+ let mut constants = FxHashMap::with_capacity_and_hasher(
+ RAW_STATICS.len(),
+ BuildHasherDefault::::default(),
+ );
+
+ for (idx, &s) in RAW_STATICS.iter().enumerate() {
+ constants.insert(s, idx);
+ }
+
+ constants
+ };
+}
+
+/// Array of raw static strings that aren't reference counted.
+const RAW_STATICS: &[JsStr<'_>] = &[
+ JsStr::latin1("".as_bytes()),
+ // Well known symbols
+ JsStr::latin1("Symbol.asyncIterator".as_bytes()),
+ JsStr::latin1("[Symbol.asyncIterator]".as_bytes()),
+ JsStr::latin1("Symbol.hasInstance".as_bytes()),
+ JsStr::latin1("[Symbol.hasInstance]".as_bytes()),
+ JsStr::latin1("Symbol.isConcatSpreadable".as_bytes()),
+ JsStr::latin1("[Symbol.isConcatSpreadable]".as_bytes()),
+ JsStr::latin1("Symbol.iterator".as_bytes()),
+ JsStr::latin1("[Symbol.iterator]".as_bytes()),
+ JsStr::latin1("Symbol.match".as_bytes()),
+ JsStr::latin1("[Symbol.match]".as_bytes()),
+ JsStr::latin1("Symbol.matchAll".as_bytes()),
+ JsStr::latin1("[Symbol.matchAll]".as_bytes()),
+ JsStr::latin1("Symbol.replace".as_bytes()),
+ JsStr::latin1("[Symbol.replace]".as_bytes()),
+ JsStr::latin1("Symbol.search".as_bytes()),
+ JsStr::latin1("[Symbol.search]".as_bytes()),
+ JsStr::latin1("Symbol.species".as_bytes()),
+ JsStr::latin1("[Symbol.species]".as_bytes()),
+ JsStr::latin1("Symbol.split".as_bytes()),
+ JsStr::latin1("[Symbol.split]".as_bytes()),
+ JsStr::latin1("Symbol.toPrimitive".as_bytes()),
+ JsStr::latin1("[Symbol.toPrimitive]".as_bytes()),
+ JsStr::latin1("Symbol.toStringTag".as_bytes()),
+ JsStr::latin1("[Symbol.toStringTag]".as_bytes()),
+ JsStr::latin1("Symbol.unscopables".as_bytes()),
+ JsStr::latin1("[Symbol.unscopables]".as_bytes()),
+ JsStr::latin1("get [Symbol.species]".as_bytes()),
+ JsStr::latin1("get [Symbol.toStringTag]".as_bytes()),
+ // Well known builtins
+ JsStr::latin1("Array".as_bytes()),
+ JsStr::latin1("ArrayBuffer".as_bytes()),
+ JsStr::latin1("SharedArrayBuffer".as_bytes()),
+ JsStr::latin1("AsyncFunction".as_bytes()),
+ JsStr::latin1("AsyncGenerator".as_bytes()),
+ JsStr::latin1("AsyncGeneratorFunction".as_bytes()),
+ JsStr::latin1("Atomics".as_bytes()),
+ JsStr::latin1("BigInt".as_bytes()),
+ JsStr::latin1("Boolean".as_bytes()),
+ JsStr::latin1("DataView".as_bytes()),
+ JsStr::latin1("Date".as_bytes()),
+ JsStr::latin1("Error".as_bytes()),
+ JsStr::latin1("AggregateError".as_bytes()),
+ JsStr::latin1("EvalError".as_bytes()),
+ JsStr::latin1("RangeError".as_bytes()),
+ JsStr::latin1("ReferenceError".as_bytes()),
+ JsStr::latin1("SyntaxError".as_bytes()),
+ JsStr::latin1("TypeError".as_bytes()),
+ JsStr::latin1("URIError".as_bytes()),
+ JsStr::latin1("escape".as_bytes()),
+ JsStr::latin1("unescape".as_bytes()),
+ JsStr::latin1("eval".as_bytes()),
+ JsStr::latin1("Function".as_bytes()),
+ JsStr::latin1("Generator".as_bytes()),
+ JsStr::latin1("GeneratorFunction".as_bytes()),
+ JsStr::latin1("Intl".as_bytes()),
+ JsStr::latin1("Collator".as_bytes()),
+ JsStr::latin1("ListFormat".as_bytes()),
+ JsStr::latin1("Locale".as_bytes()),
+ JsStr::latin1("PluralRules".as_bytes()),
+ JsStr::latin1("Segmenter".as_bytes()),
+ JsStr::latin1("DateTimeFormat".as_bytes()),
+ JsStr::latin1("JSON".as_bytes()),
+ JsStr::latin1("Map".as_bytes()),
+ JsStr::latin1("Math".as_bytes()),
+ JsStr::latin1("Number".as_bytes()),
+ JsStr::latin1("NumberFormat".as_bytes()),
+ JsStr::latin1("isFinite".as_bytes()),
+ JsStr::latin1("isNaN".as_bytes()),
+ JsStr::latin1("parseInt".as_bytes()),
+ JsStr::latin1("parseFloat".as_bytes()),
+ JsStr::latin1("Object".as_bytes()),
+ JsStr::latin1("Promise".as_bytes()),
+ JsStr::latin1("Proxy".as_bytes()),
+ JsStr::latin1("Reflect".as_bytes()),
+ JsStr::latin1("RegExp".as_bytes()),
+ JsStr::latin1("Set".as_bytes()),
+ JsStr::latin1("String".as_bytes()),
+ JsStr::latin1("Symbol".as_bytes()),
+ JsStr::latin1("TypedArray".as_bytes()),
+ JsStr::latin1("Int8Array".as_bytes()),
+ JsStr::latin1("Uint8Array".as_bytes()),
+ JsStr::latin1("Uint8ClampedArray".as_bytes()),
+ JsStr::latin1("Int16Array".as_bytes()),
+ JsStr::latin1("Uint16Array".as_bytes()),
+ JsStr::latin1("Int32Array".as_bytes()),
+ JsStr::latin1("Uint32Array".as_bytes()),
+ JsStr::latin1("BigInt64Array".as_bytes()),
+ JsStr::latin1("BigUint64Array".as_bytes()),
+ JsStr::latin1("Float32Array".as_bytes()),
+ JsStr::latin1("Float64Array".as_bytes()),
+ JsStr::latin1("encodeURI".as_bytes()),
+ JsStr::latin1("encodeURIComponent".as_bytes()),
+ JsStr::latin1("decodeURI".as_bytes()),
+ JsStr::latin1("decodeURIComponent".as_bytes()),
+ JsStr::latin1("WeakRef".as_bytes()),
+ JsStr::latin1("WeakMap".as_bytes()),
+ JsStr::latin1("WeakSet".as_bytes()),
+ JsStr::latin1("Temporal".as_bytes()),
+ JsStr::latin1("Temporal.Now".as_bytes()),
+ JsStr::latin1("Temporal.Instant".as_bytes()),
+ JsStr::latin1("Temporal.Duration".as_bytes()),
+ JsStr::latin1("Temporal.Calendar".as_bytes()),
+ JsStr::latin1("Temporal.PlainDate".as_bytes()),
+ JsStr::latin1("Temporal.PlainDateTime".as_bytes()),
+ JsStr::latin1("Temporal.PlainMonthDay".as_bytes()),
+ JsStr::latin1("Temporal.PlainYearMonth".as_bytes()),
+ JsStr::latin1("Temporal.PlainTime".as_bytes()),
+ JsStr::latin1("Temporal.TimeZone".as_bytes()),
+ JsStr::latin1("Temporal.ZonedDateTime".as_bytes()),
+ // Misc
+ JsStr::latin1(",".as_bytes()),
+ JsStr::latin1(":".as_bytes()),
+ // Generic use
+ JsStr::latin1("name".as_bytes()),
+ JsStr::latin1("length".as_bytes()),
+ JsStr::latin1("arguments".as_bytes()),
+ JsStr::latin1("prototype".as_bytes()),
+ JsStr::latin1("constructor".as_bytes()),
+ JsStr::latin1("return".as_bytes()),
+ JsStr::latin1("throw".as_bytes()),
+ JsStr::latin1("global".as_bytes()),
+ JsStr::latin1("globalThis".as_bytes()),
+ // typeof
+ JsStr::latin1("null".as_bytes()),
+ JsStr::latin1("undefined".as_bytes()),
+ JsStr::latin1("number".as_bytes()),
+ JsStr::latin1("string".as_bytes()),
+ JsStr::latin1("symbol".as_bytes()),
+ JsStr::latin1("bigint".as_bytes()),
+ JsStr::latin1("object".as_bytes()),
+ JsStr::latin1("function".as_bytes()),
+ // Property descriptor
+ JsStr::latin1("value".as_bytes()),
+ JsStr::latin1("get".as_bytes()),
+ JsStr::latin1("set".as_bytes()),
+ JsStr::latin1("writable".as_bytes()),
+ JsStr::latin1("enumerable".as_bytes()),
+ JsStr::latin1("configurable".as_bytes()),
+ // Object object
+ JsStr::latin1("assign".as_bytes()),
+ JsStr::latin1("create".as_bytes()),
+ JsStr::latin1("toString".as_bytes()),
+ JsStr::latin1("valueOf".as_bytes()),
+ JsStr::latin1("is".as_bytes()),
+ JsStr::latin1("seal".as_bytes()),
+ JsStr::latin1("isSealed".as_bytes()),
+ JsStr::latin1("freeze".as_bytes()),
+ JsStr::latin1("isFrozen".as_bytes()),
+ JsStr::latin1("isExtensible".as_bytes()),
+ JsStr::latin1("hasOwnProperty".as_bytes()),
+ JsStr::latin1("isPrototypeOf".as_bytes()),
+ JsStr::latin1("setPrototypeOf".as_bytes()),
+ JsStr::latin1("getPrototypeOf".as_bytes()),
+ JsStr::latin1("defineProperty".as_bytes()),
+ JsStr::latin1("defineProperties".as_bytes()),
+ JsStr::latin1("deleteProperty".as_bytes()),
+ JsStr::latin1("construct".as_bytes()),
+ JsStr::latin1("hasOwn".as_bytes()),
+ JsStr::latin1("ownKeys".as_bytes()),
+ JsStr::latin1("keys".as_bytes()),
+ JsStr::latin1("values".as_bytes()),
+ JsStr::latin1("entries".as_bytes()),
+ JsStr::latin1("fromEntries".as_bytes()),
+ JsStr::latin1("propertyIsEnumerable".as_bytes()),
+ JsStr::latin1("preventExtensions".as_bytes()),
+ JsStr::latin1("getOwnPropertyDescriptor".as_bytes()),
+ JsStr::latin1("getOwnPropertyDescriptors".as_bytes()),
+ JsStr::latin1("getOwnPropertyNames".as_bytes()),
+ JsStr::latin1("getOwnPropertySymbols".as_bytes()),
+ JsStr::latin1("__defineGetter__".as_bytes()),
+ JsStr::latin1("__defineSetter__".as_bytes()),
+ JsStr::latin1("__lookupGetter__".as_bytes()),
+ JsStr::latin1("__lookupSetter__".as_bytes()),
+ JsStr::latin1("__proto__".as_bytes()),
+ JsStr::latin1("get __proto__".as_bytes()),
+ JsStr::latin1("set __proto__".as_bytes()),
+ // Function object
+ JsStr::latin1("apply".as_bytes()),
+ JsStr::latin1("bind".as_bytes()),
+ JsStr::latin1("call".as_bytes()),
+ JsStr::latin1("caller".as_bytes()),
+ // Arguments object
+ JsStr::latin1("callee".as_bytes()),
+ // Array object
+ JsStr::latin1("at".as_bytes()),
+ JsStr::latin1("from".as_bytes()),
+ JsStr::latin1("isArray".as_bytes()),
+ JsStr::latin1("of".as_bytes()),
+ JsStr::latin1("copyWithin".as_bytes()),
+ JsStr::latin1("every".as_bytes()),
+ JsStr::latin1("fill".as_bytes()),
+ JsStr::latin1("filter".as_bytes()),
+ JsStr::latin1("find".as_bytes()),
+ JsStr::latin1("findIndex".as_bytes()),
+ JsStr::latin1("findLast".as_bytes()),
+ JsStr::latin1("findLastIndex".as_bytes()),
+ JsStr::latin1("flat".as_bytes()),
+ JsStr::latin1("flatMap".as_bytes()),
+ JsStr::latin1("forEach".as_bytes()),
+ JsStr::latin1("includes".as_bytes()),
+ JsStr::latin1("indexOf".as_bytes()),
+ JsStr::latin1("join".as_bytes()),
+ JsStr::latin1("map".as_bytes()),
+ JsStr::latin1("next".as_bytes()),
+ JsStr::latin1("reduce".as_bytes()),
+ JsStr::latin1("reduceRight".as_bytes()),
+ JsStr::latin1("reverse".as_bytes()),
+ JsStr::latin1("shift".as_bytes()),
+ JsStr::latin1("slice".as_bytes()),
+ JsStr::latin1("splice".as_bytes()),
+ JsStr::latin1("some".as_bytes()),
+ JsStr::latin1("sort".as_bytes()),
+ JsStr::latin1("unshift".as_bytes()),
+ JsStr::latin1("push".as_bytes()),
+ JsStr::latin1("pop".as_bytes()),
+ JsStr::latin1("groupBy".as_bytes()),
+ JsStr::latin1("toReversed".as_bytes()),
+ JsStr::latin1("toSorted".as_bytes()),
+ JsStr::latin1("toSpliced".as_bytes()),
+ JsStr::latin1("with".as_bytes()),
+ // String object
+ JsStr::latin1("charAt".as_bytes()),
+ JsStr::latin1("charCodeAt".as_bytes()),
+ JsStr::latin1("codePointAt".as_bytes()),
+ JsStr::latin1("concat".as_bytes()),
+ JsStr::latin1("endsWith".as_bytes()),
+ JsStr::latin1("fromCharCode".as_bytes()),
+ JsStr::latin1("fromCodePoint".as_bytes()),
+ JsStr::latin1("lastIndexOf".as_bytes()),
+ JsStr::latin1("match".as_bytes()),
+ JsStr::latin1("matchAll".as_bytes()),
+ JsStr::latin1("normalize".as_bytes()),
+ JsStr::latin1("padEnd".as_bytes()),
+ JsStr::latin1("padStart".as_bytes()),
+ JsStr::latin1("raw".as_bytes()),
+ JsStr::latin1("repeat".as_bytes()),
+ JsStr::latin1("replace".as_bytes()),
+ JsStr::latin1("replaceAll".as_bytes()),
+ JsStr::latin1("search".as_bytes()),
+ JsStr::latin1("split".as_bytes()),
+ JsStr::latin1("startsWith".as_bytes()),
+ JsStr::latin1("substr".as_bytes()),
+ JsStr::latin1("substring".as_bytes()),
+ JsStr::latin1("toLocaleString".as_bytes()),
+ JsStr::latin1("toLowerCase".as_bytes()),
+ JsStr::latin1("toUpperCase".as_bytes()),
+ JsStr::latin1("trim".as_bytes()),
+ JsStr::latin1("trimEnd".as_bytes()),
+ JsStr::latin1("trimStart".as_bytes()),
+ JsStr::latin1("isWellFormed".as_bytes()),
+ JsStr::latin1("localeCompare".as_bytes()),
+ JsStr::latin1("toWellFormed".as_bytes()),
+ JsStr::latin1("toLocaleLowerCase".as_bytes()),
+ JsStr::latin1("toLocaleUpperCase".as_bytes()),
+ JsStr::latin1("trimLeft".as_bytes()),
+ JsStr::latin1("trimRight".as_bytes()),
+ JsStr::latin1("anchor".as_bytes()),
+ JsStr::latin1("big".as_bytes()),
+ JsStr::latin1("blink".as_bytes()),
+ JsStr::latin1("bold".as_bytes()),
+ JsStr::latin1("fixed".as_bytes()),
+ JsStr::latin1("fontcolor".as_bytes()),
+ JsStr::latin1("fontsize".as_bytes()),
+ JsStr::latin1("italics".as_bytes()),
+ JsStr::latin1("link".as_bytes()),
+ JsStr::latin1("small".as_bytes()),
+ JsStr::latin1("strike".as_bytes()),
+ JsStr::latin1("sub".as_bytes()),
+ JsStr::latin1("sup".as_bytes()),
+ // Number object
+ JsStr::latin1("Infinity".as_bytes()),
+ JsStr::latin1("NaN".as_bytes()),
+ JsStr::latin1("EPSILON".as_bytes()),
+ JsStr::latin1("MAX_SAFE_INTEGER".as_bytes()),
+ JsStr::latin1("MIN_SAFE_INTEGER".as_bytes()),
+ JsStr::latin1("MAX_VALUE".as_bytes()),
+ JsStr::latin1("MIN_VALUE".as_bytes()),
+ JsStr::latin1("NEGATIVE_INFINITY".as_bytes()),
+ JsStr::latin1("POSITIVE_INFINITY".as_bytes()),
+ JsStr::latin1("isSafeInteger".as_bytes()),
+ JsStr::latin1("isInteger".as_bytes()),
+ JsStr::latin1("toExponential".as_bytes()),
+ JsStr::latin1("toFixed".as_bytes()),
+ JsStr::latin1("toPrecision".as_bytes()),
+ // BigInt object
+ JsStr::latin1("asIntN".as_bytes()),
+ JsStr::latin1("asUintN".as_bytes()),
+ // RegExp object
+ JsStr::latin1("exec".as_bytes()),
+ JsStr::latin1("test".as_bytes()),
+ JsStr::latin1("compile".as_bytes()),
+ JsStr::latin1("flags".as_bytes()),
+ JsStr::latin1("index".as_bytes()),
+ JsStr::latin1("lastIndex".as_bytes()),
+ JsStr::latin1("hasIndices".as_bytes()),
+ JsStr::latin1("ignoreCase".as_bytes()),
+ JsStr::latin1("multiline".as_bytes()),
+ JsStr::latin1("dotAll".as_bytes()),
+ JsStr::latin1("unicode".as_bytes()),
+ JsStr::latin1("sticky".as_bytes()),
+ JsStr::latin1("source".as_bytes()),
+ JsStr::latin1("get hasIndices".as_bytes()),
+ JsStr::latin1("get global".as_bytes()),
+ JsStr::latin1("get ignoreCase".as_bytes()),
+ JsStr::latin1("get multiline".as_bytes()),
+ JsStr::latin1("get dotAll".as_bytes()),
+ JsStr::latin1("get unicode".as_bytes()),
+ JsStr::latin1("get sticky".as_bytes()),
+ JsStr::latin1("get flags".as_bytes()),
+ JsStr::latin1("get source".as_bytes()),
+ // Symbol object
+ JsStr::latin1("for".as_bytes()),
+ JsStr::latin1("keyFor".as_bytes()),
+ JsStr::latin1("description".as_bytes()),
+ JsStr::latin1("asyncIterator".as_bytes()),
+ JsStr::latin1("hasInstance".as_bytes()),
+ JsStr::latin1("species".as_bytes()),
+ JsStr::latin1("unscopables".as_bytes()),
+ JsStr::latin1("iterator".as_bytes()),
+ JsStr::latin1("toStringTag".as_bytes()),
+ JsStr::latin1("toPrimitive".as_bytes()),
+ JsStr::latin1("isConcatSpreadable".as_bytes()),
+ JsStr::latin1("get description".as_bytes()),
+ // Map object
+ JsStr::latin1("clear".as_bytes()),
+ JsStr::latin1("delete".as_bytes()),
+ JsStr::latin1("has".as_bytes()),
+ JsStr::latin1("size".as_bytes()),
+ // Set object
+ JsStr::latin1("add".as_bytes()),
+ // Reflect object
+ // Proxy object
+ JsStr::latin1("revocable".as_bytes()),
+ // Error objects
+ JsStr::latin1("message".as_bytes()),
+ // Date object
+ JsStr::latin1("toJSON".as_bytes()),
+ JsStr::latin1("getDate".as_bytes()),
+ JsStr::latin1("getDay".as_bytes()),
+ JsStr::latin1("getFullYear".as_bytes()),
+ JsStr::latin1("getHours".as_bytes()),
+ JsStr::latin1("getMilliseconds".as_bytes()),
+ JsStr::latin1("getMinutes".as_bytes()),
+ JsStr::latin1("getMonth".as_bytes()),
+ JsStr::latin1("getSeconds".as_bytes()),
+ JsStr::latin1("getTime".as_bytes()),
+ JsStr::latin1("getYear".as_bytes()),
+ JsStr::latin1("getUTCDate".as_bytes()),
+ JsStr::latin1("getUTCDay".as_bytes()),
+ JsStr::latin1("getUTCFullYear".as_bytes()),
+ JsStr::latin1("getUTCHours".as_bytes()),
+ JsStr::latin1("getUTCMinutes".as_bytes()),
+ JsStr::latin1("getUTCMonth".as_bytes()),
+ JsStr::latin1("getUTCSeconds".as_bytes()),
+ JsStr::latin1("setDate".as_bytes()),
+ JsStr::latin1("setFullYear".as_bytes()),
+ JsStr::latin1("setHours".as_bytes()),
+ JsStr::latin1("setMilliseconds".as_bytes()),
+ JsStr::latin1("setMinutes".as_bytes()),
+ JsStr::latin1("setMonth".as_bytes()),
+ JsStr::latin1("setSeconds".as_bytes()),
+ JsStr::latin1("setYear".as_bytes()),
+ JsStr::latin1("setTime".as_bytes()),
+ JsStr::latin1("setUTCDate".as_bytes()),
+ JsStr::latin1("setUTCFullYear".as_bytes()),
+ JsStr::latin1("setUTCHours".as_bytes()),
+ JsStr::latin1("setUTCMinutes".as_bytes()),
+ JsStr::latin1("setUTCMonth".as_bytes()),
+ JsStr::latin1("setUTCSeconds".as_bytes()),
+ JsStr::latin1("toDateString".as_bytes()),
+ JsStr::latin1("toGMTString".as_bytes()),
+ JsStr::latin1("toISOString".as_bytes()),
+ JsStr::latin1("toTimeString".as_bytes()),
+ JsStr::latin1("toUTCString".as_bytes()),
+ JsStr::latin1("now".as_bytes()),
+ JsStr::latin1("UTC".as_bytes()),
+ JsStr::latin1("getTimezoneOffset".as_bytes()),
+ JsStr::latin1("getUTCMilliseconds".as_bytes()),
+ JsStr::latin1("setUTCMilliseconds".as_bytes()),
+ JsStr::latin1("toLocaleDateString".as_bytes()),
+ JsStr::latin1("toLocaleTimeString".as_bytes()),
+ // JSON object
+ JsStr::latin1("parse".as_bytes()),
+ JsStr::latin1("stringify".as_bytes()),
+ // Promise object
+ JsStr::latin1("promise".as_bytes()),
+ JsStr::latin1("resolve".as_bytes()),
+ JsStr::latin1("reject".as_bytes()),
+ JsStr::latin1("all".as_bytes()),
+ JsStr::latin1("allSettled".as_bytes()),
+ JsStr::latin1("any".as_bytes()),
+ JsStr::latin1("race".as_bytes()),
+ JsStr::latin1("then".as_bytes()),
+ JsStr::latin1("catch".as_bytes()),
+ JsStr::latin1("finally".as_bytes()),
+ JsStr::latin1("withResolvers".as_bytes()),
+ // Iterator object
+ JsStr::latin1("Array Iterator".as_bytes()),
+ JsStr::latin1("Set Iterator".as_bytes()),
+ JsStr::latin1("String Iterator".as_bytes()),
+ JsStr::latin1("Map Iterator".as_bytes()),
+ JsStr::latin1("For In Iterator".as_bytes()),
+ JsStr::latin1("RegExp String Iterator".as_bytes()),
+ // Iterator result object
+ JsStr::latin1("done".as_bytes()),
+ // Math object
+ JsStr::latin1("LN10".as_bytes()),
+ JsStr::latin1("LN2".as_bytes()),
+ JsStr::latin1("LOG10E".as_bytes()),
+ JsStr::latin1("LOG2E".as_bytes()),
+ JsStr::latin1("PI".as_bytes()),
+ JsStr::latin1("SQRT1_2".as_bytes()),
+ JsStr::latin1("SQRT2".as_bytes()),
+ JsStr::latin1("abs".as_bytes()),
+ JsStr::latin1("acos".as_bytes()),
+ JsStr::latin1("acosh".as_bytes()),
+ JsStr::latin1("asin".as_bytes()),
+ JsStr::latin1("asinh".as_bytes()),
+ JsStr::latin1("atan".as_bytes()),
+ JsStr::latin1("atanh".as_bytes()),
+ JsStr::latin1("atan2".as_bytes()),
+ JsStr::latin1("cbrt".as_bytes()),
+ JsStr::latin1("ceil".as_bytes()),
+ JsStr::latin1("clz32".as_bytes()),
+ JsStr::latin1("cos".as_bytes()),
+ JsStr::latin1("cosh".as_bytes()),
+ JsStr::latin1("exp".as_bytes()),
+ JsStr::latin1("expm1".as_bytes()),
+ JsStr::latin1("floor".as_bytes()),
+ JsStr::latin1("fround".as_bytes()),
+ JsStr::latin1("hypot".as_bytes()),
+ JsStr::latin1("imul".as_bytes()),
+ JsStr::latin1("log".as_bytes()),
+ JsStr::latin1("log1p".as_bytes()),
+ JsStr::latin1("log10".as_bytes()),
+ JsStr::latin1("log2".as_bytes()),
+ JsStr::latin1("max".as_bytes()),
+ JsStr::latin1("min".as_bytes()),
+ JsStr::latin1("pow".as_bytes()),
+ JsStr::latin1("random".as_bytes()),
+ JsStr::latin1("round".as_bytes()),
+ JsStr::latin1("sign".as_bytes()),
+ JsStr::latin1("sin".as_bytes()),
+ JsStr::latin1("sinh".as_bytes()),
+ JsStr::latin1("sqrt".as_bytes()),
+ JsStr::latin1("tan".as_bytes()),
+ JsStr::latin1("tanh".as_bytes()),
+ JsStr::latin1("trunc".as_bytes()),
+ // TypedArray object
+ JsStr::latin1("BYTES_PER_ELEMENT".as_bytes()),
+ JsStr::latin1("buffer".as_bytes()),
+ JsStr::latin1("byteLength".as_bytes()),
+ JsStr::latin1("byteOffset".as_bytes()),
+ JsStr::latin1("isView".as_bytes()),
+ JsStr::latin1("subarray".as_bytes()),
+ JsStr::latin1("get byteLength".as_bytes()),
+ JsStr::latin1("get buffer".as_bytes()),
+ JsStr::latin1("get byteOffset".as_bytes()),
+ JsStr::latin1("get size".as_bytes()),
+ JsStr::latin1("get length".as_bytes()),
+ // DataView object
+ JsStr::latin1("getBigInt64".as_bytes()),
+ JsStr::latin1("getBigUint64".as_bytes()),
+ JsStr::latin1("getFloat32".as_bytes()),
+ JsStr::latin1("getFloat64".as_bytes()),
+ JsStr::latin1("getInt8".as_bytes()),
+ JsStr::latin1("getInt16".as_bytes()),
+ JsStr::latin1("getInt32".as_bytes()),
+ JsStr::latin1("getUint8".as_bytes()),
+ JsStr::latin1("getUint16".as_bytes()),
+ JsStr::latin1("getUint32".as_bytes()),
+ JsStr::latin1("setBigInt64".as_bytes()),
+ JsStr::latin1("setBigUint64".as_bytes()),
+ JsStr::latin1("setFloat32".as_bytes()),
+ JsStr::latin1("setFloat64".as_bytes()),
+ JsStr::latin1("setInt8".as_bytes()),
+ JsStr::latin1("setInt16".as_bytes()),
+ JsStr::latin1("setInt32".as_bytes()),
+ JsStr::latin1("setUint8".as_bytes()),
+ JsStr::latin1("setUint16".as_bytes()),
+ JsStr::latin1("setUint32".as_bytes()),
+ // WeakRef object
+ JsStr::latin1("deref".as_bytes()),
+ // Atomic object
+ JsStr::latin1("and".as_bytes()),
+ JsStr::latin1("compareExchange".as_bytes()),
+ JsStr::latin1("exchange".as_bytes()),
+ JsStr::latin1("isLockFree".as_bytes()),
+ JsStr::latin1("load".as_bytes()),
+ JsStr::latin1("or".as_bytes()),
+ JsStr::latin1("store".as_bytes()),
+ JsStr::latin1("wait".as_bytes()),
+ JsStr::latin1("notify".as_bytes()),
+ JsStr::latin1("xor".as_bytes()),
+ // Intl object
+ JsStr::latin1("getCanonicalLocales".as_bytes()),
+ JsStr::latin1("get compare".as_bytes()),
+ JsStr::latin1("supportedLocalesOf".as_bytes()),
+ JsStr::latin1("Intl.Collator".as_bytes()),
+ JsStr::latin1("compare".as_bytes()),
+ JsStr::latin1("resolvedOptions".as_bytes()),
+ JsStr::latin1("Intl.ListFormat".as_bytes()),
+ JsStr::latin1("format".as_bytes()),
+ JsStr::latin1("formatToParts".as_bytes()),
+ JsStr::latin1("get baseName".as_bytes()),
+ JsStr::latin1("get calendar".as_bytes()),
+ JsStr::latin1("get caseFirst".as_bytes()),
+ JsStr::latin1("get collation".as_bytes()),
+ JsStr::latin1("get hourCycle".as_bytes()),
+ JsStr::latin1("get numeric".as_bytes()),
+ JsStr::latin1("get numberingSystem".as_bytes()),
+ JsStr::latin1("get language".as_bytes()),
+ JsStr::latin1("get script".as_bytes()),
+ JsStr::latin1("get region".as_bytes()),
+ JsStr::latin1("Intl.Locale".as_bytes()),
+ JsStr::latin1("maximize".as_bytes()),
+ JsStr::latin1("minimize".as_bytes()),
+ JsStr::latin1("baseName".as_bytes()),
+ JsStr::latin1("calendar".as_bytes()),
+ JsStr::latin1("caseFirst".as_bytes()),
+ JsStr::latin1("collation".as_bytes()),
+ JsStr::latin1("hourCycle".as_bytes()),
+ JsStr::latin1("numeric".as_bytes()),
+ JsStr::latin1("numberingSystem".as_bytes()),
+ JsStr::latin1("language".as_bytes()),
+ JsStr::latin1("script".as_bytes()),
+ JsStr::latin1("region".as_bytes()),
+ JsStr::latin1("Intl.Segmenter".as_bytes()),
+ JsStr::latin1("segment".as_bytes()),
+ JsStr::latin1("containing".as_bytes()),
+ JsStr::latin1("Segmenter String Iterator".as_bytes()),
+ JsStr::latin1("Intl.PluralRules".as_bytes()),
+ JsStr::latin1("select".as_bytes()),
+ // Temporal object
+ JsStr::latin1("get Id".as_bytes()),
+ JsStr::latin1("getOffsetNanosecondsFor".as_bytes()),
+ JsStr::latin1("getOffsetStringFor".as_bytes()),
+ JsStr::latin1("getPlainDateTimeFor".as_bytes()),
+ JsStr::latin1("getInstantFor".as_bytes()),
+ JsStr::latin1("getPossibleInstantFor".as_bytes()),
+ JsStr::latin1("getNextTransition".as_bytes()),
+ JsStr::latin1("getPreviousTransition".as_bytes()),
+ JsStr::latin1("id".as_bytes()),
+ JsStr::latin1("Now".as_bytes()),
+ JsStr::latin1("Calendar".as_bytes()),
+ JsStr::latin1("Duration".as_bytes()),
+ JsStr::latin1("Instant".as_bytes()),
+ JsStr::latin1("PlainDate".as_bytes()),
+ JsStr::latin1("PlainDateTime".as_bytes()),
+ JsStr::latin1("PlainMonthDay".as_bytes()),
+ JsStr::latin1("PlainTime".as_bytes()),
+ JsStr::latin1("PlainYearMonth".as_bytes()),
+ JsStr::latin1("TimeZone".as_bytes()),
+ JsStr::latin1("ZonedDateTime".as_bytes()),
+ JsStr::latin1("timeZoneId".as_bytes()),
+ JsStr::latin1("instant".as_bytes()),
+ JsStr::latin1("plainDateTime".as_bytes()),
+ JsStr::latin1("plainDateTimeISO".as_bytes()),
+ JsStr::latin1("zonedDateTime".as_bytes()),
+ JsStr::latin1("zonedDateTimeISO".as_bytes()),
+ JsStr::latin1("plainDate".as_bytes()),
+ JsStr::latin1("plainDateISO".as_bytes()),
+ JsStr::latin1("get epochSeconds".as_bytes()),
+ JsStr::latin1("get epochMilliseconds".as_bytes()),
+ JsStr::latin1("get epochMicroseconds".as_bytes()),
+ JsStr::latin1("get epochNanoseconds".as_bytes()),
+ JsStr::latin1("epochSeconds".as_bytes()),
+ JsStr::latin1("epochMilliseconds".as_bytes()),
+ JsStr::latin1("epochMicroseconds".as_bytes()),
+ JsStr::latin1("epochNanoseconds".as_bytes()),
+ JsStr::latin1("subtract".as_bytes()),
+ JsStr::latin1("until".as_bytes()),
+ JsStr::latin1("since".as_bytes()),
+ JsStr::latin1("equals".as_bytes()),
+ JsStr::latin1("toZonedDateTime".as_bytes()),
+ JsStr::latin1("toZonedDateTimeISO".as_bytes()),
+ JsStr::latin1("get Years".as_bytes()),
+ JsStr::latin1("get Months".as_bytes()),
+ JsStr::latin1("get Weeks".as_bytes()),
+ JsStr::latin1("get Days".as_bytes()),
+ JsStr::latin1("get Hours".as_bytes()),
+ JsStr::latin1("get Minutes".as_bytes()),
+ JsStr::latin1("get Seconds".as_bytes()),
+ JsStr::latin1("get Milliseconds".as_bytes()),
+ JsStr::latin1("get Microseconds".as_bytes()),
+ JsStr::latin1("get Nanoseconds".as_bytes()),
+ JsStr::latin1("get Sign".as_bytes()),
+ JsStr::latin1("get blank".as_bytes()),
+ JsStr::latin1("years".as_bytes()),
+ JsStr::latin1("months".as_bytes()),
+ JsStr::latin1("weeks".as_bytes()),
+ JsStr::latin1("days".as_bytes()),
+ JsStr::latin1("hours".as_bytes()),
+ JsStr::latin1("minutes".as_bytes()),
+ JsStr::latin1("seconds".as_bytes()),
+ JsStr::latin1("milliseconds".as_bytes()),
+ JsStr::latin1("microseconds".as_bytes()),
+ JsStr::latin1("nanoseconds".as_bytes()),
+ JsStr::latin1("blank".as_bytes()),
+ JsStr::latin1("negated".as_bytes()),
+ JsStr::latin1("total".as_bytes()),
+ JsStr::latin1("get calendarId".as_bytes()),
+ JsStr::latin1("get year".as_bytes()),
+ JsStr::latin1("get month".as_bytes()),
+ JsStr::latin1("get monthCode".as_bytes()),
+ JsStr::latin1("get day".as_bytes()),
+ JsStr::latin1("get dayOfWeek".as_bytes()),
+ JsStr::latin1("get dayOfYear".as_bytes()),
+ JsStr::latin1("get weekOfYear".as_bytes()),
+ JsStr::latin1("get yearOfWeek".as_bytes()),
+ JsStr::latin1("get daysInWeek".as_bytes()),
+ JsStr::latin1("get daysInMonth".as_bytes()),
+ JsStr::latin1("get daysInYear".as_bytes()),
+ JsStr::latin1("get monthsInYear".as_bytes()),
+ JsStr::latin1("get inLeapYear".as_bytes()),
+ JsStr::latin1("calendarId".as_bytes()),
+ JsStr::latin1("year".as_bytes()),
+ JsStr::latin1("month".as_bytes()),
+ JsStr::latin1("monthCode".as_bytes()),
+ JsStr::latin1("day".as_bytes()),
+ JsStr::latin1("dayOfWeek".as_bytes()),
+ JsStr::latin1("dayOfYear".as_bytes()),
+ JsStr::latin1("weekOfYear".as_bytes()),
+ JsStr::latin1("yearOfWeek".as_bytes()),
+ JsStr::latin1("daysInWeek".as_bytes()),
+ JsStr::latin1("daysInMonth".as_bytes()),
+ JsStr::latin1("daysInYear".as_bytes()),
+ JsStr::latin1("monthsInYear".as_bytes()),
+ JsStr::latin1("inLeapYear".as_bytes()),
+ JsStr::latin1("toPlainYearMonth".as_bytes()),
+ JsStr::latin1("toPlainMonthDay".as_bytes()),
+ JsStr::latin1("getISOFields".as_bytes()),
+ JsStr::latin1("getCalendar".as_bytes()),
+ JsStr::latin1("withCalendar".as_bytes()),
+ JsStr::latin1("dateFromFields".as_bytes()),
+ JsStr::latin1("yearMonthFromFields".as_bytes()),
+ JsStr::latin1("monthDayFromFields".as_bytes()),
+ JsStr::latin1("dateAdd".as_bytes()),
+ JsStr::latin1("dateUntil".as_bytes()),
+ JsStr::latin1("era".as_bytes()),
+ JsStr::latin1("eraYear".as_bytes()),
+ JsStr::latin1("fields".as_bytes()),
+ JsStr::latin1("mergeFields".as_bytes()),
+ // Console object
+ JsStr::latin1("console".as_bytes()),
+ JsStr::latin1("assert".as_bytes()),
+ JsStr::latin1("debug".as_bytes()),
+ JsStr::latin1("error".as_bytes()),
+ JsStr::latin1("info".as_bytes()),
+ JsStr::latin1("trace".as_bytes()),
+ JsStr::latin1("warn".as_bytes()),
+ JsStr::latin1("exception".as_bytes()),
+ JsStr::latin1("count".as_bytes()),
+ JsStr::latin1("countReset".as_bytes()),
+ JsStr::latin1("group".as_bytes()),
+ JsStr::latin1("groupCollapsed".as_bytes()),
+ JsStr::latin1("groupEnd".as_bytes()),
+ JsStr::latin1("time".as_bytes()),
+ JsStr::latin1("timeLog".as_bytes()),
+ JsStr::latin1("timeEnd".as_bytes()),
+ JsStr::latin1("dir".as_bytes()),
+ JsStr::latin1("dirxml".as_bytes()),
+ // Minified name
+ JsStr::latin1("a".as_bytes()),
+ JsStr::latin1("c".as_bytes()),
+ JsStr::latin1("d".as_bytes()),
+ JsStr::latin1("e".as_bytes()),
+ JsStr::latin1("f".as_bytes()),
+ JsStr::latin1("g".as_bytes()),
+ JsStr::latin1("h".as_bytes()),
+ JsStr::latin1("i".as_bytes()),
+ JsStr::latin1("j".as_bytes()),
+ JsStr::latin1("k".as_bytes()),
+ JsStr::latin1("l".as_bytes()),
+ JsStr::latin1("m".as_bytes()),
+ JsStr::latin1("n".as_bytes()),
+ JsStr::latin1("o".as_bytes()),
+ JsStr::latin1("p".as_bytes()),
+ JsStr::latin1("q".as_bytes()),
+ JsStr::latin1("r".as_bytes()),
+ JsStr::latin1("s".as_bytes()),
+ JsStr::latin1("t".as_bytes()),
+ JsStr::latin1("u".as_bytes()),
+ JsStr::latin1("v".as_bytes()),
+ JsStr::latin1("w".as_bytes()),
+ JsStr::latin1("x".as_bytes()),
+ JsStr::latin1("y".as_bytes()),
+ JsStr::latin1("z".as_bytes()),
+ JsStr::latin1("A".as_bytes()),
+ JsStr::latin1("C".as_bytes()),
+ JsStr::latin1("D".as_bytes()),
+ JsStr::latin1("E".as_bytes()),
+ JsStr::latin1("F".as_bytes()),
+ JsStr::latin1("G".as_bytes()),
+ JsStr::latin1("H".as_bytes()),
+ JsStr::latin1("I".as_bytes()),
+ JsStr::latin1("J".as_bytes()),
+ JsStr::latin1("K".as_bytes()),
+ JsStr::latin1("L".as_bytes()),
+ JsStr::latin1("M".as_bytes()),
+ JsStr::latin1("N".as_bytes()),
+ JsStr::latin1("O".as_bytes()),
+ JsStr::latin1("P".as_bytes()),
+ JsStr::latin1("Q".as_bytes()),
+ JsStr::latin1("R".as_bytes()),
+ JsStr::latin1("S".as_bytes()),
+ JsStr::latin1("T".as_bytes()),
+ JsStr::latin1("U".as_bytes()),
+ JsStr::latin1("V".as_bytes()),
+ JsStr::latin1("W".as_bytes()),
+ JsStr::latin1("X".as_bytes()),
+ JsStr::latin1("Y".as_bytes()),
+ JsStr::latin1("Z".as_bytes()),
+ JsStr::latin1("_".as_bytes()),
+ JsStr::latin1("$".as_bytes()),
+];
diff --git a/core/engine/src/string/iter.rs b/core/string/src/iter.rs
similarity index 97%
rename from core/engine/src/string/iter.rs
rename to core/string/src/iter.rs
index 03dedcb6b8..ead0e8c94c 100644
--- a/core/engine/src/string/iter.rs
+++ b/core/string/src/iter.rs
@@ -29,6 +29,7 @@ impl<'a> Iter<'a> {
impl Iterator for Iter<'_> {
type Item = u16;
+ #[inline]
fn next(&mut self) -> Option {
match &mut self.inner {
IterInner::U8(iter) => iter.map(u16::from).next(),
@@ -40,6 +41,7 @@ impl Iterator for Iter<'_> {
impl FusedIterator for Iter<'_> {}
impl ExactSizeIterator for Iter<'_> {
+ #[inline]
fn len(&self) -> usize {
match &self.inner {
IterInner::U8(v) => v.len(),
@@ -75,6 +77,7 @@ impl<'a> Windows<'a> {
impl<'a> Iterator for Windows<'a> {
type Item = JsStr<'a>;
+ #[inline]
fn next(&mut self) -> Option {
match &mut self.inner {
WindowsInner::U8(iter) => iter.next().map(JsStr::latin1),
@@ -86,6 +89,7 @@ impl<'a> Iterator for Windows<'a> {
impl FusedIterator for Windows<'_> {}
impl ExactSizeIterator for Windows<'_> {
+ #[inline]
fn len(&self) -> usize {
match &self.inner {
WindowsInner::U8(v) => v.len(),
diff --git a/core/engine/src/string/mod.rs b/core/string/src/lib.rs
similarity index 82%
rename from core/engine/src/string/mod.rs
rename to core/string/src/lib.rs
index 16f2172731..2daae7d5c6 100644
--- a/core/engine/src/string/mod.rs
+++ b/core/string/src/lib.rs
@@ -1,10 +1,4 @@
//! A Latin1 or UTF-16 encoded, reference counted, immutable string.
-//!
-//! This module contains the [`JsString`] type, the [`js_string`][crate::js_string] macro and the
-//! [`js_str`][crate::js_str] macro.
-//!
-//! The [`js_string`][crate::js_string] macro is used when you need to create a new [`JsString`],
-//! and the [`js_str`][crate::js_str] macro is used for const conversions of string literals to [`JsStr`].
// Required per unsafe code standards to ensure every unsafe usage is properly documented.
// - `unsafe_op_in_unsafe_fn` will be warn-by-default in edition 2024:
@@ -20,22 +14,24 @@
// Right now this allows us to use the stable polyfill from the `sptr` crate, which uses
// the same names from the unstable functions of the `std::ptr` module.
#![allow(unstable_name_collisions)]
+#![allow(clippy::module_name_repetitions)]
-pub mod common;
+mod common;
mod iter;
mod str;
+mod tagged;
-use self::{common::StaticJsStrings, iter::Windows, str::JsSliceIndex};
+#[cfg(test)]
+mod tests;
+
+use self::{iter::Windows, str::JsSliceIndex};
+use crate::tagged::{Tagged, UnwrappedTagged};
#[doc(inline)]
-pub use crate::string::{
+pub use crate::{
+ common::StaticJsStrings,
iter::Iter,
str::{JsStr, JsStrVariant},
};
-use crate::{
- builtins::string::is_trimmable_whitespace,
- tagged::{Tagged, UnwrappedTagged},
-};
-use boa_gc::{Finalize, Trace};
use std::{
alloc::{alloc, dealloc, Layout},
cell::Cell,
@@ -51,65 +47,41 @@ fn alloc_overflow() -> ! {
panic!("detected overflow during string allocation")
}
-/// Utility macro to create a [`JsString`].
-///
-/// # Examples
-///
-/// You can call the macro without arguments to create an empty `JsString`:
-///
-/// ```
-/// use boa_engine::js_string;
-///
-/// let empty_str = js_string!();
-/// assert!(empty_str.is_empty());
-/// ```
-///
-///
-/// You can create a `JsString` from a string literal, which completely skips the runtime
-/// conversion from [`&str`] to [&\[u16\]][slice]
:
-///
-/// ```
-/// # use boa_engine::js_string;
-/// let hw = js_string!("Hello, world!");
-/// assert_eq!(&hw, "Hello, world!");
-/// ```
-///
-/// Any `&[u16]` slice is a valid `JsString`, including unpaired surrogates:
-///
-/// ```
-/// # use boa_engine::js_string;
-/// let array = js_string!(&[0xD8AFu16, 0x00A0, 0xD8FF, 0x00F0]);
-/// ```
-///
-/// You can also pass it any number of `&[u16]` as arguments to create a new `JsString` with
-/// the concatenation of every slice:
-///
-/// ```
-/// # use boa_engine::{js_string, js_str, JsStr};
-/// const NAME: JsStr<'_> = js_str!("human! ");
-/// let greeting = js_string!("Hello, ");
-/// let msg = js_string!(&greeting, NAME, js_str!("Nice to meet you!"));
-///
-/// assert_eq!(&msg, "Hello, human! Nice to meet you!");
-/// ```
-#[macro_export]
-#[allow(clippy::module_name_repetitions)]
-macro_rules! js_string {
- () => {
- $crate::string::JsString::default()
- };
- ($s:literal) => {
- $crate::string::JsString::from($crate::js_str!($s))
- };
- ($s:expr) => {
- $crate::string::JsString::from($s)
- };
- ( $x:expr, $y:expr ) => {
- $crate::string::JsString::concat($crate::string::JsStr::from($x), $crate::string::JsStr::from($y))
- };
- ( $( $s:expr ),+ ) => {
- $crate::string::JsString::concat_array(&[ $( $crate::string::JsStr::from($s) ),+ ])
- };
+/// Helper function to check if a `char` is trimmable.
+pub(crate) const fn is_trimmable_whitespace(c: char) -> bool {
+ // The rust implementation of `trim` does not regard the same characters whitespace as ecma standard does
+ //
+ // Rust uses \p{White_Space} by default, which also includes:
+ // `\u{0085}' (next line)
+ // And does not include:
+ // '\u{FEFF}' (zero width non-breaking space)
+ // Explicit whitespace: https://tc39.es/ecma262/#sec-white-space
+ matches!(
+ c,
+ '\u{0009}' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' |
+ // Unicode Space_Separator category
+ '\u{1680}' | '\u{2000}'
+ ..='\u{200A}' | '\u{202F}' | '\u{205F}' | '\u{3000}' |
+ // Line terminators: https://tc39.es/ecma262/#sec-line-terminators
+ '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}'
+ )
+}
+
+/// Helper function to check if a `u8` latin1 character is trimmable.
+pub(crate) const fn is_trimmable_whitespace_latin1(c: u8) -> bool {
+ // The rust implementation of `trim` does not regard the same characters whitespace as ecma standard does
+ //
+ // Rust uses \p{White_Space} by default, which also includes:
+ // `\u{0085}' (next line)
+ // And does not include:
+ // '\u{FEFF}' (zero width non-breaking space)
+ // Explicit whitespace: https://tc39.es/ecma262/#sec-white-space
+ matches!(
+ c,
+ 0x09 | 0x0B | 0x0C | 0x20 | 0xA0 |
+ // Line terminators: https://tc39.es/ecma262/#sec-line-terminators
+ 0x0A | 0x0D
+ )
}
/// Represents a Unicode codepoint within a [`JsString`], which could be a valid
@@ -127,6 +99,7 @@ pub enum CodePoint {
impl CodePoint {
/// Get the number of UTF-16 code units needed to encode this code point.
+ #[inline]
#[must_use]
pub const fn code_unit_count(self) -> usize {
match self {
@@ -136,6 +109,7 @@ impl CodePoint {
}
/// Convert the code point to its [`u32`] representation.
+ #[inline]
#[must_use]
pub fn as_u32(self) -> u32 {
match self {
@@ -146,6 +120,7 @@ impl CodePoint {
/// If the code point represents a valid 'Unicode scalar value', returns its [`char`]
/// representation, otherwise returns [`None`] on unpaired surrogates.
+ #[inline]
#[must_use]
pub const fn as_char(self) -> Option {
match self {
@@ -161,6 +136,8 @@ impl CodePoint {
///
/// Panics if the buffer is not large enough. A buffer of length 2 is large enough to encode any
/// code point.
+ #[inline]
+ #[must_use]
pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
match self {
Self::Unicode(c) => c.encode_utf16(dst),
@@ -218,9 +195,6 @@ const DATA_OFFSET: usize = std::mem::size_of::();
///
/// We define some commonly used string constants in an interner. For these strings, we don't allocate
/// memory on the heap to reduce the overhead of memory allocation and reference counting.
-#[derive(Trace, Finalize)]
-// Safety: `JsString` does not contain any objects which needs to be traced, so this is safe.
-#[boa_gc(unsafe_empty_trace)]
#[allow(clippy::module_name_repetitions)]
pub struct JsString {
ptr: Tagged,
@@ -230,6 +204,7 @@ pub struct JsString {
static_assertions::assert_eq_size!(JsString, *const ());
impl<'a> From<&'a JsString> for JsStr<'a> {
+ #[inline]
fn from(value: &'a JsString) -> Self {
value.as_str()
}
@@ -237,8 +212,9 @@ impl<'a> From<&'a JsString> for JsStr<'a> {
impl<'a> IntoIterator for &'a JsString {
type IntoIter = Iter<'a>;
-
type Item = u16;
+
+ #[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
@@ -260,6 +236,7 @@ impl JsString {
}
/// Obtains the underlying [`&[u16]`][slice] slice of a [`JsString`]
+ #[inline]
#[must_use]
pub fn as_str(&self) -> JsStr<'_> {
match self.ptr.unwrap() {
@@ -298,6 +275,7 @@ impl JsString {
}
/// Creates a new [`JsString`] from the concatenation of `x` and `y`.
+ #[inline]
#[must_use]
pub fn concat(x: JsStr<'_>, y: JsStr<'_>) -> Self {
Self::concat_array(&[x, y])
@@ -305,6 +283,7 @@ impl JsString {
/// Creates a new [`JsString`] from the concatenation of every element of
/// `strings`.
+ #[inline]
#[must_use]
pub fn concat_array(strings: &[JsStr<'_>]) -> Self {
let mut latin1_encoding = true;
@@ -373,6 +352,7 @@ impl JsString {
/// Decodes a [`JsString`] into a [`String`], replacing invalid data with its escaped representation
/// in 4 digit hexadecimal.
+ #[inline]
#[must_use]
pub fn to_std_string_escaped(&self) -> String {
self.to_string_escaped()
@@ -383,6 +363,7 @@ impl JsString {
/// # Errors
///
/// [`FromUtf16Error`][std::string::FromUtf16Error] if it contains any invalid data.
+ #[inline]
pub fn to_std_string(&self) -> Result {
match self.as_str().variant() {
JsStrVariant::Latin1(v) => Ok(v.iter().copied().map(char::from).collect()),
@@ -392,6 +373,7 @@ impl JsString {
/// Decodes a [`JsString`] into an iterator of [`Result`], returning surrogates as
/// errors.
+ #[inline]
pub fn to_std_string_with_surrogates(&self) -> impl Iterator- > + '_ {
struct WideStringDecoderIterator {
codepoints: Peekable,
@@ -443,6 +425,7 @@ impl JsString {
}
/// Maps the valid segments of an UTF16 string and leaves the unpaired surrogates unchanged.
+ #[inline]
#[must_use]
pub fn map_valid_segments(&self, mut f: F) -> Self
where
@@ -457,10 +440,11 @@ impl JsString {
}
}
- js_string!(&text[..])
+ Self::from(&text[..])
}
/// Gets an iterator of all the Unicode codepoints of a [`JsString`].
+ #[inline]
pub fn code_points(&self) -> impl Iterator
- + Clone + '_ {
char::decode_utf16(self.iter()).map(|res| match res {
Ok(c) => CodePoint::Unicode(c),
@@ -477,6 +461,7 @@ impl JsString {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-stringindexof
+ #[inline]
#[must_use]
pub fn index_of(&self, search_value: JsStr<'_>, from_index: usize) -> Option {
// 1. Assert: Type(string) is String.
@@ -522,6 +507,7 @@ impl JsString {
/// # Panics
///
/// If `position` is smaller than size of string.
+ #[inline]
#[must_use]
pub fn code_point_at(&self, position: usize) -> CodePoint {
// 1. Let size be the length of string.
@@ -569,6 +555,8 @@ impl JsString {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-stringtonumber
+ #[inline]
+ #[must_use]
pub fn to_number(&self) -> f64 {
// 1. Let text be ! StringToCodePoints(str).
// 2. Let literal be ParseText(text, StringNumericLiteral).
@@ -781,12 +769,14 @@ impl JsString {
}
/// Convert the [`JsString`] into a [`Vec`].
+ #[inline]
#[must_use]
pub fn to_vec(&self) -> Vec {
self.as_str().to_vec()
}
/// Check if the [`JsString`] contains a byte.
+ #[inline]
#[must_use]
pub fn contains(&self, element: u8) -> bool {
match self.as_str().variant() {
@@ -796,30 +786,35 @@ impl JsString {
}
/// Trim whitespace from the start and end of the [`JsString`].
+ #[inline]
#[must_use]
pub fn trim(&self) -> JsStr<'_> {
self.as_str().trim()
}
/// Trim whitespace from the start of the [`JsString`].
+ #[inline]
#[must_use]
pub fn trim_start(&self) -> JsStr<'_> {
self.as_str().trim_start()
}
/// Trim whitespace from the end of the [`JsString`].
+ #[inline]
#[must_use]
pub fn trim_end(&self) -> JsStr<'_> {
self.as_str().trim_end()
}
/// Check if the [`JsString`] is static.
+ #[inline]
#[must_use]
pub fn is_static(&self) -> bool {
self.ptr.is_tagged()
}
/// Get the element a the given index, [`None`] otherwise.
+ #[inline]
#[must_use]
pub fn get<'a, I>(&'a self, index: I) -> Option
where
@@ -833,6 +828,7 @@ impl JsString {
/// # Panics
///
/// If the index is out of bounds.
+ #[inline]
#[must_use]
pub fn get_expect<'a, I>(&'a self, index: I) -> I::Value
where
@@ -840,6 +836,20 @@ impl JsString {
{
self.get(index).expect("Index out of bounds")
}
+
+ /// Gets the number of `JsString`s which point to this allocation.
+ #[inline]
+ #[must_use]
+ pub fn refcount(&self) -> Option {
+ match self.ptr.unwrap() {
+ UnwrappedTagged::Ptr(inner) => {
+ // SAFETY: The reference count of `JsString` guarantees that `inner` is always valid.
+ let inner = unsafe { inner.as_ref() };
+ Some(inner.refcount.get())
+ }
+ UnwrappedTagged::Tag(_inner) => None,
+ }
+ }
}
impl Clone for JsString {
@@ -866,6 +876,7 @@ impl Default for JsString {
}
impl Drop for JsString {
+ #[inline]
fn drop(&mut self) {
if let UnwrappedTagged::Ptr(raw) = self.ptr.unwrap() {
// See https://doc.rust-lang.org/src/alloc/sync.rs.html#1672 for details.
@@ -947,6 +958,7 @@ impl From<&str> for JsString {
}
impl From> for JsString {
+ #[inline]
fn from(value: JsStr<'_>) -> Self {
StaticJsStrings::get_string(&value)
.unwrap_or_else(|| JsString::from_slice_skip_interning(value))
@@ -954,6 +966,7 @@ impl From> for JsString {
}
impl From<&[JsString]> for JsString {
+ #[inline]
fn from(value: &[JsString]) -> Self {
Self::concat_array(
&value
@@ -972,36 +985,42 @@ impl From for JsString {
}
impl From<&[u16; N]> for JsString {
+ #[inline]
fn from(s: &[u16; N]) -> Self {
Self::from(&s[..])
}
}
impl Hash for JsString {
+ #[inline]
fn hash(&self, state: &mut H) {
self.as_str().hash(state);
}
}
impl PartialOrd for JsStr<'_> {
+ #[inline]
fn partial_cmp(&self, other: &Self) -> Option {
Some(self.cmp(other))
}
}
impl Ord for JsString {
+ #[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_str().cmp(&other.as_str())
}
}
impl PartialEq for JsString {
+ #[inline]
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl PartialEq for [u16] {
+ #[inline]
fn eq(&self, other: &JsString) -> bool {
if self.len() != other.len() {
return false;
@@ -1016,24 +1035,28 @@ impl PartialEq for [u16] {
}
impl PartialEq for [u16; N] {
+ #[inline]
fn eq(&self, other: &JsString) -> bool {
self[..] == *other
}
}
impl PartialEq<[u16]> for JsString {
+ #[inline]
fn eq(&self, other: &[u16]) -> bool {
other == self
}
}
impl PartialEq<[u16; N]> for JsString {
+ #[inline]
fn eq(&self, other: &[u16; N]) -> bool {
*self == other[..]
}
}
impl PartialEq for JsString {
+ #[inline]
fn eq(&self, other: &str) -> bool {
let utf16 = self.code_points();
let mut utf8 = other.chars();
@@ -1052,24 +1075,28 @@ impl PartialEq for JsString {
}
impl PartialEq for str {
+ #[inline]
fn eq(&self, other: &JsString) -> bool {
other == self
}
}
impl PartialEq> for JsString {
+ #[inline]
fn eq(&self, other: &JsStr<'_>) -> bool {
self.as_str() == *other
}
}
impl PartialEq for JsStr<'_> {
+ #[inline]
fn eq(&self, other: &JsString) -> bool {
other == self
}
}
impl PartialOrd for JsString {
+ #[inline]
fn partial_cmp(&self, other: &Self) -> Option {
Some(self.cmp(other))
}
@@ -1078,6 +1105,7 @@ impl PartialOrd for JsString {
impl FromStr for JsString {
type Err = Infallible;
+ #[inline]
fn from_str(s: &str) -> Result {
Ok(Self::from(s))
}
@@ -1091,6 +1119,7 @@ pub(crate) trait ToStringEscaped {
}
impl ToStringEscaped for [u16] {
+ #[inline]
fn to_string_escaped(&self) -> String {
char::decode_utf16(self.iter().copied())
.map(|r| match r {
@@ -1100,187 +1129,3 @@ impl ToStringEscaped for [u16] {
.collect()
}
}
-
-#[allow(clippy::redundant_clone)]
-#[cfg(test)]
-mod tests {
- use std::hash::{BuildHasher, BuildHasherDefault, Hash};
-
- use crate::{string::common::StaticJsStrings, tagged::UnwrappedTagged, JsStr};
-
- use super::JsString;
- use boa_macros::{js_str, utf16};
- use rustc_hash::FxHasher;
-
- impl JsString {
- /// Gets the number of `JsString`s which point to this allocation.
- fn refcount(&self) -> Option {
- match self.ptr.unwrap() {
- UnwrappedTagged::Ptr(inner) => {
- // SAFETY: The reference count of `JsString` guarantees that `inner` is always valid.
- let inner = unsafe { inner.as_ref() };
- Some(inner.refcount.get())
- }
- UnwrappedTagged::Tag(_inner) => None,
- }
- }
- }
-
- fn hash_value(value: &T) -> u64 {
- BuildHasherDefault::::default().hash_one(value)
- }
-
- #[test]
- fn empty() {
- let s = js_string!();
- assert_eq!(&s, utf16!(""));
- }
-
- #[test]
- fn refcount() {
- let x = js_string!("Hello world");
- assert_eq!(x.refcount(), Some(1));
-
- {
- let y = x.clone();
- assert_eq!(x.refcount(), Some(2));
- assert_eq!(y.refcount(), Some(2));
-
- {
- let z = y.clone();
- assert_eq!(x.refcount(), Some(3));
- assert_eq!(y.refcount(), Some(3));
- assert_eq!(z.refcount(), Some(3));
- }
-
- assert_eq!(x.refcount(), Some(2));
- assert_eq!(y.refcount(), Some(2));
- }
-
- assert_eq!(x.refcount(), Some(1));
- }
-
- #[test]
- fn static_refcount() {
- let x = js_string!();
- assert_eq!(x.refcount(), None);
-
- {
- let y = x.clone();
- assert_eq!(x.refcount(), None);
- assert_eq!(y.refcount(), None);
- };
-
- assert_eq!(x.refcount(), None);
- }
-
- #[test]
- fn ptr_eq() {
- let x = js_string!("Hello");
- let y = x.clone();
-
- assert!(!x.ptr.is_tagged());
-
- assert_eq!(x.ptr.addr(), y.ptr.addr());
-
- let z = js_string!("Hello");
- assert_ne!(x.ptr.addr(), z.ptr.addr());
- assert_ne!(y.ptr.addr(), z.ptr.addr());
- }
-
- #[test]
- fn static_ptr_eq() {
- let x = js_string!();
- let y = x.clone();
-
- assert!(x.ptr.is_tagged());
-
- assert_eq!(x.ptr.addr(), y.ptr.addr());
-
- let z = js_string!();
- assert_eq!(x.ptr.addr(), z.ptr.addr());
- assert_eq!(y.ptr.addr(), z.ptr.addr());
- }
-
- #[test]
- fn as_str() {
- const HELLO: &[u16] = utf16!("Hello");
- let x = js_string!(HELLO);
-
- assert_eq!(&x, HELLO);
- }
-
- #[test]
- fn hash() {
- const HELLOWORLD: JsStr<'_> = js_str!("Hello World!");
- let x = js_string!(HELLOWORLD);
-
- assert_eq!(x.as_str(), HELLOWORLD);
-
- assert!(HELLOWORLD.is_latin1());
- assert!(x.as_str().is_latin1());
-
- let s_hash = hash_value(&HELLOWORLD);
- let x_hash = hash_value(&x);
-
- assert_eq!(s_hash, x_hash);
- }
-
- #[test]
- fn concat() {
- const Y: &[u16] = utf16!(", ");
- const W: &[u16] = utf16!("!");
-
- let x = js_string!("hello");
- let z = js_string!("world");
-
- let xy = js_string!(&x, &JsString::from(Y));
- assert_eq!(&xy, utf16!("hello, "));
- assert_eq!(xy.refcount(), Some(1));
-
- let xyz = js_string!(&xy, &z);
- assert_eq!(&xyz, utf16!("hello, world"));
- assert_eq!(xyz.refcount(), Some(1));
-
- let xyzw = js_string!(&xyz, &JsString::from(W));
- assert_eq!(&xyzw, utf16!("hello, world!"));
- assert_eq!(xyzw.refcount(), Some(1));
- }
-
- #[test]
- fn trim_start_non_ascii_to_ascii() {
- let s = "\u{2029}abc";
- let x = js_string!(s);
-
- let y = js_string!(x.trim_start());
-
- assert_eq!(&y, s.trim_start());
- }
-
- #[test]
- fn conversion_to_known_static_js_string() {
- const JS_STR_U8: &JsStr<'_> = &js_str!("length");
- const JS_STR_U16: &JsStr<'_> = &JsStr::utf16(utf16!("length"));
-
- assert!(JS_STR_U8.is_latin1());
- assert!(!JS_STR_U16.is_latin1());
-
- assert_eq!(JS_STR_U8, JS_STR_U8);
- assert_eq!(JS_STR_U16, JS_STR_U16);
-
- assert_eq!(JS_STR_U8, JS_STR_U16);
- assert_eq!(JS_STR_U16, JS_STR_U8);
-
- assert_eq!(hash_value(JS_STR_U8), hash_value(JS_STR_U16));
-
- let string = StaticJsStrings::get_string(JS_STR_U8);
-
- assert!(string.is_some());
- assert!(string.unwrap().as_str().is_latin1());
-
- let string = StaticJsStrings::get_string(JS_STR_U16);
-
- assert!(string.is_some());
- assert!(string.unwrap().as_str().is_latin1());
- }
-}
diff --git a/core/engine/src/string/str.rs b/core/string/src/str.rs
similarity index 96%
rename from core/engine/src/string/str.rs
rename to core/string/src/str.rs
index 6ce3c4cabd..ef31ac7a27 100644
--- a/core/engine/src/string/str.rs
+++ b/core/string/src/str.rs
@@ -1,7 +1,4 @@
-use crate::{
- builtins::string::{is_trimmable_whitespace, is_trimmable_whitespace_latin1},
- string::Iter,
-};
+use crate::{is_trimmable_whitespace, is_trimmable_whitespace_latin1, Iter};
use std::{
hash::{Hash, Hasher},
slice::SliceIndex,
@@ -195,6 +192,8 @@ impl<'a> JsStr<'a> {
}
/// Convert the [`JsStr`] into a [`Vec`].
+ #[inline]
+ #[must_use]
pub fn to_vec(&self) -> Vec {
match self.variant() {
JsStrVariant::Latin1(v) => v.iter().copied().map(u16::from).collect(),
@@ -203,13 +202,19 @@ impl<'a> JsStr<'a> {
}
/// Returns true if needle is a prefix of the [`JsStr`].
+ #[inline]
#[must_use]
+ // We check the size, so this should never panic.
+ #[allow(clippy::missing_panics_doc)]
pub fn starts_with(&self, needle: JsStr<'_>) -> bool {
let n = needle.len();
self.len() >= n && needle == self.get(..n).expect("already checked size")
}
/// Returns `true` if `needle` is a suffix of the [`JsStr`].
+ #[inline]
#[must_use]
+ // We check the size, so this should never panic.
+ #[allow(clippy::missing_panics_doc)]
pub fn ends_with(&self, needle: JsStr<'_>) -> bool {
let (m, n) = (self.len(), needle.len());
m >= n && needle == self.get(m - n..).expect("already checked size")
@@ -217,6 +222,7 @@ impl<'a> JsStr<'a> {
}
impl Hash for JsStr<'_> {
+ #[inline]
fn hash(&self, state: &mut H) {
// NOTE: The hash function has been inlined to ensure that a hash of latin1 and U16
// encoded strings remains the same if they have the same characters
@@ -238,6 +244,7 @@ impl Hash for JsStr<'_> {
}
impl Ord for JsStr<'_> {
+ #[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self.variant(), other.variant()) {
(JsStrVariant::Latin1(x), JsStrVariant::Latin1(y)) => x.cmp(y),
@@ -250,6 +257,7 @@ impl Ord for JsStr<'_> {
impl Eq for JsStr<'_> {}
impl PartialEq for JsStr<'_> {
+ #[inline]
fn eq(&self, other: &Self) -> bool {
match (self.variant(), other.variant()) {
(JsStrVariant::Latin1(lhs), JsStrVariant::Latin1(rhs)) => return lhs == rhs,
@@ -269,6 +277,7 @@ impl PartialEq for JsStr<'_> {
}
impl<'a> PartialEq> for [u16] {
+ #[inline]
fn eq(&self, other: &JsStr<'a>) -> bool {
if self.len() != other.len() {
return false;
diff --git a/core/string/src/tagged.rs b/core/string/src/tagged.rs
new file mode 100644
index 0000000000..83ec17c24b
--- /dev/null
+++ b/core/string/src/tagged.rs
@@ -0,0 +1,109 @@
+// Remove when/if https://github.com/rust-lang/rust/issues/95228 stabilizes.
+// Right now this allows us to use the stable polyfill from the `sptr` crate, which uses
+// the same names from the unstable functions of the `std::ptr` module.
+#![allow(unstable_name_collisions)]
+
+use sptr::Strict;
+use std::ptr::NonNull;
+
+/// A pointer that can be tagged with an `usize`.
+///
+/// Only pointers with a minimum alignment of 2-bytes are valid, and the tag must have its most
+/// significant bit (MSB) unset. In other words, the tag must fit inside `usize::BITS - 1` bits.
+///
+/// # Representation
+///
+/// If the least significant bit (LSB) of the internal [`NonNull`] is set (1), then the pointer
+/// address represents a tag where the remaining bits store the tag. Otherwise, the whole pointer
+/// represents the pointer itself.
+///
+/// It uses [`NonNull`], which guarantees that [`Tagged`] can use the "null pointer optimization"
+/// to optimize the size of [`Option`].
+///
+/// # Provenance
+///
+/// This struct stores a [`NonNull`] instead of a [`NonZeroUsize`][std::num::NonZeroUsize]
+/// in order to preserve the provenance of our valid heap pointers.
+/// On the other hand, all index values are just casted to invalid pointers, because we don't need to
+/// preserve the provenance of [`usize`] indices.
+///
+/// [tagged_wp]: https://en.wikipedia.org/wiki/Tagged_pointer
+#[derive(Debug)]
+pub(crate) struct Tagged(NonNull);
+
+impl Clone for Tagged {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl Copy for Tagged {}
+
+impl Tagged {
+ /// Creates a new, tagged `Tagged` pointer from an integer.
+ ///
+ /// # Requirements
+ ///
+ /// - `T` must have an alignment of at least 2.
+ /// - `tag` must fit inside `usize::BITS - 1` bits
+ pub(crate) const fn from_tag(tag: usize) -> Self {
+ debug_assert!(std::mem::align_of::() >= 2);
+ let addr = (tag << 1) | 1;
+ // SAFETY: `addr` is never zero, since we always set its LSB to 1
+ unsafe { Self(NonNull::new_unchecked(sptr::invalid_mut(addr))) }
+ }
+
+ /// Creates a new `Tagged` pointer from a raw pointer.
+ ///
+ /// # Requirements
+ ///
+ /// - `T` must have an alignment of at least 2.
+ ///
+ /// # Safety
+ ///
+ /// - `T` must be non null.
+ pub(crate) const unsafe fn from_ptr(ptr: *mut T) -> Self {
+ debug_assert!(std::mem::align_of::() >= 2);
+ // SAFETY: the caller must ensure the invariants hold.
+ unsafe { Self(NonNull::new_unchecked(ptr)) }
+ }
+
+ /// Creates a new `Tagged` pointer from a `NonNull` pointer.
+ ///
+ /// # Requirements
+ ///
+ /// - `T` must have an alignment of at least 2.
+ pub(crate) const fn from_non_null(ptr: NonNull) -> Self {
+ debug_assert!(std::mem::align_of::() >= 2);
+ Self(ptr)
+ }
+
+ /// Unwraps the `Tagged` pointer.
+ pub(crate) fn unwrap(self) -> UnwrappedTagged {
+ let addr = self.0.as_ptr().addr();
+ if addr & 1 == 0 {
+ UnwrappedTagged::Ptr(self.0)
+ } else {
+ UnwrappedTagged::Tag(addr >> 1)
+ }
+ }
+
+ /// Gets the address of the inner pointer.
+ #[allow(unused)]
+ pub(crate) fn addr(self) -> usize {
+ self.0.as_ptr().addr()
+ }
+
+ /// Returns `true` if `self ` is a tagged pointer.
+ #[allow(unused)]
+ pub(crate) fn is_tagged(self) -> bool {
+ self.0.as_ptr().addr() & 1 > 0
+ }
+}
+
+/// The unwrapped value of a [`Tagged`] pointer.
+#[derive(Debug, Clone, Copy)]
+pub(crate) enum UnwrappedTagged {
+ Ptr(NonNull),
+ Tag(usize),
+}
diff --git a/core/string/src/tests.rs b/core/string/src/tests.rs
new file mode 100644
index 0000000000..2022994b48
--- /dev/null
+++ b/core/string/src/tests.rs
@@ -0,0 +1,166 @@
+#![allow(clippy::redundant_clone)]
+
+use std::hash::{BuildHasher, BuildHasherDefault, Hash};
+
+use crate::{JsStr, JsString, StaticJsStrings};
+
+use boa_macros::utf16;
+use rustc_hash::FxHasher;
+
+fn hash_value(value: &T) -> u64 {
+ BuildHasherDefault::::default().hash_one(value)
+}
+
+#[test]
+fn empty() {
+ let s = StaticJsStrings::EMPTY_STRING;
+ assert_eq!(&s, utf16!(""));
+}
+
+#[test]
+fn refcount() {
+ let x = JsString::from("Hello world");
+ assert_eq!(x.refcount(), Some(1));
+
+ {
+ let y = x.clone();
+ assert_eq!(x.refcount(), Some(2));
+ assert_eq!(y.refcount(), Some(2));
+
+ {
+ let z = y.clone();
+ assert_eq!(x.refcount(), Some(3));
+ assert_eq!(y.refcount(), Some(3));
+ assert_eq!(z.refcount(), Some(3));
+ }
+
+ assert_eq!(x.refcount(), Some(2));
+ assert_eq!(y.refcount(), Some(2));
+ }
+
+ assert_eq!(x.refcount(), Some(1));
+}
+
+#[test]
+fn static_refcount() {
+ let x = StaticJsStrings::EMPTY_STRING;
+ assert_eq!(x.refcount(), None);
+
+ {
+ let y = x.clone();
+ assert_eq!(x.refcount(), None);
+ assert_eq!(y.refcount(), None);
+ };
+
+ assert_eq!(x.refcount(), None);
+}
+
+#[test]
+fn ptr_eq() {
+ let x = JsString::from("Hello");
+ let y = x.clone();
+
+ assert!(!x.ptr.is_tagged());
+
+ assert_eq!(x.ptr.addr(), y.ptr.addr());
+
+ let z = JsString::from("Hello");
+ assert_ne!(x.ptr.addr(), z.ptr.addr());
+ assert_ne!(y.ptr.addr(), z.ptr.addr());
+}
+
+#[test]
+fn static_ptr_eq() {
+ let x = StaticJsStrings::EMPTY_STRING;
+ let y = x.clone();
+
+ assert!(x.ptr.is_tagged());
+
+ assert_eq!(x.ptr.addr(), y.ptr.addr());
+
+ let z = StaticJsStrings::EMPTY_STRING;
+ assert_eq!(x.ptr.addr(), z.ptr.addr());
+ assert_eq!(y.ptr.addr(), z.ptr.addr());
+}
+
+#[test]
+fn as_str() {
+ const HELLO: &[u16] = utf16!("Hello");
+ let x = JsString::from(HELLO);
+
+ assert_eq!(&x, HELLO);
+}
+
+#[test]
+fn hash() {
+ const HELLOWORLD: JsStr<'_> = JsStr::latin1("Hello World!".as_bytes());
+ let x = JsString::from(HELLOWORLD);
+
+ assert_eq!(x.as_str(), HELLOWORLD);
+
+ assert!(HELLOWORLD.is_latin1());
+ assert!(x.as_str().is_latin1());
+
+ let s_hash = hash_value(&HELLOWORLD);
+ let x_hash = hash_value(&x);
+
+ assert_eq!(s_hash, x_hash);
+}
+
+#[test]
+fn concat() {
+ const Y: &[u16] = utf16!(", ");
+ const W: &[u16] = utf16!("!");
+
+ let x = JsString::from("hello");
+ let z = JsString::from("world");
+
+ let xy = JsString::concat(x.as_str(), JsString::from(Y).as_str());
+ assert_eq!(&xy, utf16!("hello, "));
+ assert_eq!(xy.refcount(), Some(1));
+
+ let xyz = JsString::concat(xy.as_str(), z.as_str());
+ assert_eq!(&xyz, utf16!("hello, world"));
+ assert_eq!(xyz.refcount(), Some(1));
+
+ let xyzw = JsString::concat(xyz.as_str(), JsString::from(W).as_str());
+ assert_eq!(&xyzw, utf16!("hello, world!"));
+ assert_eq!(xyzw.refcount(), Some(1));
+}
+
+#[test]
+fn trim_start_non_ascii_to_ascii() {
+ let s = "\u{2029}abc";
+ let x = JsString::from(s);
+
+ let y = JsString::from(x.trim_start());
+
+ assert_eq!(&y, s.trim_start());
+}
+
+#[test]
+fn conversion_to_known_static_js_string() {
+ const JS_STR_U8: &JsStr<'_> = &JsStr::latin1("length".as_bytes());
+ const JS_STR_U16: &JsStr<'_> = &JsStr::utf16(utf16!("length"));
+
+ assert!(JS_STR_U8.is_latin1());
+ assert!(!JS_STR_U16.is_latin1());
+
+ assert_eq!(JS_STR_U8, JS_STR_U8);
+ assert_eq!(JS_STR_U16, JS_STR_U16);
+
+ assert_eq!(JS_STR_U8, JS_STR_U16);
+ assert_eq!(JS_STR_U16, JS_STR_U8);
+
+ assert_eq!(hash_value(JS_STR_U8), hash_value(JS_STR_U16));
+
+ let string = StaticJsStrings::get_string(JS_STR_U8);
+
+ assert!(string.is_some());
+ assert!(string.unwrap().as_str().is_latin1());
+
+ let string = StaticJsStrings::get_string(JS_STR_U16);
+
+ assert!(string.is_some());
+ assert!(string.unwrap().as_str().is_latin1());
+}